[BACK]Return to sshkey.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/sshkey.c between version 1.102 and 1.103

version 1.102, 2020/03/06 18:23:17 version 1.103, 2020/04/08 00:01:52
Line 4005 
Line 4005 
 }  }
   
 static int  static int
 sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,  private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
     struct sshkey **keyp, char **commentp)  
 {  {
         char *comment = NULL, *ciphername = NULL, *kdfname = NULL;  
         const struct sshcipher *cipher = NULL;  
         const u_char *cp;          const u_char *cp;
         int r = SSH_ERR_INTERNAL_ERROR;  
         size_t encoded_len;          size_t encoded_len;
         size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;          int r;
           u_char last;
         struct sshbuf *encoded = NULL, *decoded = NULL;          struct sshbuf *encoded = NULL, *decoded = NULL;
         struct sshbuf *kdf = NULL, *decrypted = NULL;  
         struct sshcipher_ctx *ciphercontext = NULL;  
         struct sshkey *k = NULL;  
         u_char *key = NULL, *salt = NULL, *dp, pad, last;  
         u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;  
   
         if (keyp != NULL)          if (blob == NULL || decodedp == NULL)
                 *keyp = NULL;                  return SSH_ERR_INVALID_ARGUMENT;
         if (commentp != NULL)  
                 *commentp = NULL;  
   
           *decodedp = NULL;
   
         if ((encoded = sshbuf_new()) == NULL ||          if ((encoded = sshbuf_new()) == NULL ||
             (decoded = sshbuf_new()) == NULL ||              (decoded = sshbuf_new()) == NULL) {
             (decrypted = sshbuf_new()) == NULL) {  
                 r = SSH_ERR_ALLOC_FAIL;                  r = SSH_ERR_ALLOC_FAIL;
                 goto out;                  goto out;
         }          }
Line 4078 
Line 4069 
                 r = SSH_ERR_INVALID_FORMAT;                  r = SSH_ERR_INVALID_FORMAT;
                 goto out;                  goto out;
         }          }
           /* success */
           *decodedp = decoded;
           decoded = NULL;
           r = 0;
    out:
           sshbuf_free(encoded);
           sshbuf_free(decoded);
           return r;
   }
   
   static int
   private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
       const char *passphrase)
   {
           char *ciphername = NULL, *kdfname = NULL;
           const struct sshcipher *cipher = NULL;
           int r = SSH_ERR_INTERNAL_ERROR;
           size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
           struct sshbuf *kdf = NULL, *decrypted = NULL;
           struct sshcipher_ctx *ciphercontext = NULL;
           u_char *key = NULL, *salt = NULL, *dp;
           u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
   
           if (decoded == NULL || decryptedp == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
   
           *decryptedp = NULL;
   
           if ((decrypted = sshbuf_new()) == NULL) {
                   r = SSH_ERR_ALLOC_FAIL;
                   goto out;
           }
   
         /* parse public portion of key */          /* parse public portion of key */
         if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||          if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
             (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||              (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
             (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||              (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
             (r = sshbuf_froms(decoded, &kdf)) != 0 ||              (r = sshbuf_froms(decoded, &kdf)) != 0 ||
             (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||              (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
             (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */                  goto out;
   
           if (nkeys != 1) {
                   /* XXX only one key supported at present */
                   r = SSH_ERR_INVALID_FORMAT;
                   goto out;
           }
   
           if ((r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
             (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)              (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
                 goto out;                  goto out;
   
Line 4106 
Line 4138 
                 r = SSH_ERR_KEY_WRONG_PASSPHRASE;                  r = SSH_ERR_KEY_WRONG_PASSPHRASE;
                 goto out;                  goto out;
         }          }
         if (nkeys != 1) {  
                 /* XXX only one key supported */  
                 r = SSH_ERR_INVALID_FORMAT;  
                 goto out;  
         }  
   
         /* check size of encrypted key blob */          /* check size of encrypted key blob */
         blocksize = cipher_blocksize(cipher);          blocksize = cipher_blocksize(cipher);
Line 4173 
Line 4200 
                 r = SSH_ERR_KEY_WRONG_PASSPHRASE;                  r = SSH_ERR_KEY_WRONG_PASSPHRASE;
                 goto out;                  goto out;
         }          }
           /* success */
           *decryptedp = decrypted;
           decrypted = NULL;
           r = 0;
    out:
           cipher_free(ciphercontext);
           free(ciphername);
           free(kdfname);
           if (salt != NULL) {
                   explicit_bzero(salt, slen);
                   free(salt);
           }
           if (key != NULL) {
                   explicit_bzero(key, keylen + ivlen);
                   free(key);
           }
           sshbuf_free(kdf);
           sshbuf_free(decrypted);
           return r;
   }
   
         /* Load the private key and comment */  /* Check deterministic padding after private key */
         if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||  static int
             (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)  private2_check_padding(struct sshbuf *decrypted)
                 goto out;  {
           u_char pad;
           size_t i;
           int r = SSH_ERR_INTERNAL_ERROR;
   
         /* Check deterministic padding */  
         i = 0;          i = 0;
         while (sshbuf_len(decrypted)) {          while (sshbuf_len(decrypted)) {
                 if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)                  if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
Line 4189 
Line 4238 
                         goto out;                          goto out;
                 }                  }
         }          }
           /* success */
           r = 0;
    out:
           explicit_bzero(&pad, sizeof(pad));
           explicit_bzero(&i, sizeof(i));
           return r;
   }
   
   static int
   sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
       struct sshkey **keyp, char **commentp)
   {
           char *comment = NULL;
           int r = SSH_ERR_INTERNAL_ERROR;
           struct sshbuf *decoded = NULL, *decrypted = NULL;
           struct sshkey *k = NULL;
   
           if (keyp != NULL)
                   *keyp = NULL;
           if (commentp != NULL)
                   *commentp = NULL;
   
           /* Undo base64 encoding and decrypt the private section */
           if ((r = private2_uudecode(blob, &decoded)) != 0 ||
               (r = private2_decrypt(decoded, &decrypted, passphrase)) != 0)
                   goto out;
   
           /* Load the private key and comment */
           if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
               (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
                   goto out;
   
           /* Check deterministic padding after private section */
           if ((r = private2_check_padding(decrypted)) != 0)
                   goto out;
   
         /* XXX decode pubkey and check against private */          /* XXX decode pubkey and check against private */
   
         /* success */          /* success */
Line 4203 
Line 4287 
                 comment = NULL;                  comment = NULL;
         }          }
  out:   out:
         pad = 0;  
         cipher_free(ciphercontext);  
         free(ciphername);  
         free(kdfname);  
         free(comment);          free(comment);
         if (salt != NULL)  
                 freezero(salt, slen);  
         if (key != NULL)  
                 freezero(key, keylen + ivlen);  
         sshbuf_free(encoded);  
         sshbuf_free(decoded);          sshbuf_free(decoded);
         sshbuf_free(kdf);  
         sshbuf_free(decrypted);          sshbuf_free(decrypted);
         sshkey_free(k);          sshkey_free(k);
         return r;          return r;

Legend:
Removed from v.1.102  
changed lines
  Added in v.1.103