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

Diff for /src/usr.bin/ssh/cipher.c between version 1.103 and 1.104

version 1.103, 2017/04/30 23:10:43 version 1.104, 2017/04/30 23:15:04
Line 59 
Line 59 
   
 struct sshcipher {  struct sshcipher {
         char    *name;          char    *name;
         int     number;         /* for ssh1 only */  
         u_int   block_size;          u_int   block_size;
         u_int   key_len;          u_int   key_len;
         u_int   iv_len;         /* defaults to block_size */          u_int   iv_len;         /* defaults to block_size */
Line 70 
Line 69 
 #define CFLAG_CHACHAPOLY        (1<<1)  #define CFLAG_CHACHAPOLY        (1<<1)
 #define CFLAG_AESCTR            (1<<2)  #define CFLAG_AESCTR            (1<<2)
 #define CFLAG_NONE              (1<<3)  #define CFLAG_NONE              (1<<3)
   #define CFLAG_INTERNAL          CFLAG_NONE /* Don't use "none" for packets */
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         const EVP_CIPHER        *(*evptype)(void);          const EVP_CIPHER        *(*evptype)(void);
 #else  #else
Line 79 
Line 79 
   
 static const struct sshcipher ciphers[] = {  static const struct sshcipher ciphers[] = {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         { "none",       SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },          { "3des-cbc",           8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
         { "3des-cbc",   SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },          { "blowfish-cbc",       8, 16, 0, 0, 0, 1, EVP_bf_cbc },
         { "blowfish-cbc",          { "cast128-cbc",        8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
                         SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },          { "arcfour",            8, 16, 0, 0, 0, 0, EVP_rc4 },
         { "cast128-cbc",          { "arcfour128",         8, 16, 0, 0, 1536, 0, EVP_rc4 },
                         SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },          { "arcfour256",         8, 32, 0, 0, 1536, 0, EVP_rc4 },
         { "arcfour",    SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },          { "aes128-cbc",         16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
         { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },          { "aes192-cbc",         16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
         { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },          { "aes256-cbc",         16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
         { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },  
         { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },  
         { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },  
         { "rijndael-cbc@lysator.liu.se",          { "rijndael-cbc@lysator.liu.se",
                         SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },                                  16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
         { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },          { "aes128-ctr",         16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
         { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },          { "aes192-ctr",         16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
         { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },          { "aes256-ctr",         16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
         { "aes128-gcm@openssh.com",          { "aes128-gcm@openssh.com",
                         SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },                                  16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
         { "aes256-gcm@openssh.com",          { "aes256-gcm@openssh.com",
                         SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },                                  16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
 #else  #else
         { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },          { "aes128-ctr",         16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
         { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },          { "aes192-ctr",         16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
         { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },          { "aes256-ctr",         16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
         { "none",       SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },  
 #endif  #endif
         { "chacha20-poly1305@openssh.com",          { "chacha20-poly1305@openssh.com",
                         SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },                                  8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
           { "none",               8, 0, 0, 0, 0, CFLAG_NONE, NULL },
   
         { NULL,         SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }          { NULL,                 0, 0, 0, 0, 0, 0, NULL }
 };  };
   
 /*--*/  /*--*/
Line 123 
Line 120 
         const struct sshcipher *c;          const struct sshcipher *c;
   
         for (c = ciphers; c->name != NULL; c++) {          for (c = ciphers; c->name != NULL; c++) {
                 if (c->number != SSH_CIPHER_SSH2)                  if ((c->flags & CFLAG_INTERNAL) != 0)
                         continue;                          continue;
                 if (auth_only && c->auth_len == 0)                  if (auth_only && c->auth_len == 0)
                         continue;                          continue;
Line 179 
Line 176 
 }  }
   
 u_int  u_int
 cipher_get_number(const struct sshcipher *c)  
 {  
         return (c->number);  
 }  
   
 u_int  
 cipher_is_cbc(const struct sshcipher *c)  cipher_is_cbc(const struct sshcipher *c)
 {  {
         return (c->flags & CFLAG_CBC) != 0;          return (c->flags & CFLAG_CBC) != 0;
Line 196 
Line 187 
         return cc->plaintext;          return cc->plaintext;
 }  }
   
 u_int  
 cipher_ctx_get_number(struct sshcipher_ctx *cc)  
 {  
         return cc->cipher->number;  
 }  
   
 u_int  
 cipher_mask_ssh1(int client)  
 {  
         u_int mask = 0;  
         mask |= 1 << SSH_CIPHER_3DES;           /* Mandatory */  
         mask |= 1 << SSH_CIPHER_BLOWFISH;  
         if (client) {  
                 mask |= 1 << SSH_CIPHER_DES;  
         }  
         return mask;  
 }  
   
 const struct sshcipher *  const struct sshcipher *
 cipher_by_name(const char *name)  cipher_by_name(const char *name)
 {  {
Line 224 
Line 197 
         return NULL;          return NULL;
 }  }
   
 const struct sshcipher *  
 cipher_by_number(int id)  
 {  
         const struct sshcipher *c;  
         for (c = ciphers; c->name != NULL; c++)  
                 if (c->number == id)  
                         return c;  
         return NULL;  
 }  
   
 #define CIPHER_SEP      ","  #define CIPHER_SEP      ","
 int  int
 ciphers_valid(const char *names)  ciphers_valid(const char *names)
Line 249 
Line 212 
         for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';          for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
             (p = strsep(&cp, CIPHER_SEP))) {              (p = strsep(&cp, CIPHER_SEP))) {
                 c = cipher_by_name(p);                  c = cipher_by_name(p);
                 if (c == NULL || c->number != SSH_CIPHER_SSH2) {                  if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) {
                         free(cipher_list);                          free(cipher_list);
                         return 0;                          return 0;
                 }                  }
Line 258 
Line 221 
         return 1;          return 1;
 }  }
   
 /*  
  * Parses the name of the cipher.  Returns the number of the corresponding  
  * cipher, or -1 on error.  
  */  
   
 int  
 cipher_number(const char *name)  
 {  
         const struct sshcipher *c;  
         if (name == NULL)  
                 return -1;  
         for (c = ciphers; c->name != NULL; c++)  
                 if (strcasecmp(c->name, name) == 0)  
                         return c->number;  
         return -1;  
 }  
   
 char *  
 cipher_name(int id)  
 {  
         const struct sshcipher *c = cipher_by_number(id);  
         return (c==NULL) ? "<unknown>" : c->name;  
 }  
   
 const char *  const char *
 cipher_warning_message(const struct sshcipher_ctx *cc)  cipher_warning_message(const struct sshcipher_ctx *cc)
 {  {
         if (cc == NULL || cc->cipher == NULL)          if (cc == NULL || cc->cipher == NULL)
                 return NULL;                  return NULL;
         if (cc->cipher->number == SSH_CIPHER_DES)          /* XXX repurpose for CBC warning */
                 return "use of DES is strongly discouraged due to "  
                     "cryptographic weaknesses";  
         return NULL;          return NULL;
 }  }
   
Line 310 
Line 247 
         if ((cc = calloc(sizeof(*cc), 1)) == NULL)          if ((cc = calloc(sizeof(*cc), 1)) == NULL)
                 return SSH_ERR_ALLOC_FAIL;                  return SSH_ERR_ALLOC_FAIL;
   
         if (cipher->number == SSH_CIPHER_DES) {          cc->plaintext = 0; /* XXX */
                 if (keylen > 8)  
                         keylen = 8;  
         }  
   
         cc->plaintext = (cipher->number == SSH_CIPHER_NONE);  
         cc->encrypt = do_encrypt;          cc->encrypt = do_encrypt;
   
         if (keylen < cipher->key_len ||          if (keylen < cipher->key_len ||
Line 329 
Line 261 
                 ret = chachapoly_init(&cc->cp_ctx, key, keylen);                  ret = chachapoly_init(&cc->cp_ctx, key, keylen);
                 goto out;                  goto out;
         }          }
           if ((cc->cipher->flags & CFLAG_NONE) != 0) {
                   ret = 0;
                   goto out;
           }
 #ifndef WITH_OPENSSL  #ifndef WITH_OPENSSL
         if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {          if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
                 aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);                  aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
Line 336 
Line 272 
                 ret = 0;                  ret = 0;
                 goto out;                  goto out;
         }          }
         if ((cc->cipher->flags & CFLAG_NONE) != 0) {  
                 ret = 0;  
                 goto out;  
         }  
         ret = SSH_ERR_INVALID_ARGUMENT;          ret = SSH_ERR_INVALID_ARGUMENT;
         goto out;          goto out;
 #else /* WITH_OPENSSL */  #else /* WITH_OPENSSL */
Line 424 
Line 356 
                 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,                  return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
                     len, aadlen, authlen, cc->encrypt);                      len, aadlen, authlen, cc->encrypt);
         }          }
           if ((cc->cipher->flags & CFLAG_NONE) != 0) {
                   memcpy(dest, src, aadlen + len);
                   return 0;
           }
 #ifndef WITH_OPENSSL  #ifndef WITH_OPENSSL
         if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {          if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
                 if (aadlen)                  if (aadlen)
Line 432 
Line 368 
                     dest + aadlen, len);                      dest + aadlen, len);
                 return 0;                  return 0;
         }          }
         if ((cc->cipher->flags & CFLAG_NONE) != 0) {  
                 memcpy(dest, src, aadlen + len);  
                 return 0;  
         }  
         return SSH_ERR_INVALID_ARGUMENT;          return SSH_ERR_INVALID_ARGUMENT;
 #else  #else
         if (authlen) {          if (authlen) {
Line 542 
Line 474 
 cipher_get_keyiv_len(const struct sshcipher_ctx *cc)  cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
 {  {
         const struct sshcipher *c = cc->cipher;          const struct sshcipher *c = cc->cipher;
         int ivlen = 0;  
   
         if (c->number == SSH_CIPHER_3DES)          if ((c->flags & CFLAG_CHACHAPOLY) != 0)
                 ivlen = 24;                  return 0;
         else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)          else if ((c->flags & CFLAG_AESCTR) != 0)
                 ivlen = 0;                  return sizeof(cc->ac_ctx.ctr);
         else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)  
                 ivlen = sizeof(cc->ac_ctx.ctr);  
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         else          return EVP_CIPHER_CTX_iv_length(cc->evp);
                 ivlen = EVP_CIPHER_CTX_iv_length(cc->evp);  #else
 #endif /* WITH_OPENSSL */          return 0;
         return (ivlen);  #endif
 }  }
   
 int  int
Line 579 
Line 508 
         if ((cc->cipher->flags & CFLAG_NONE) != 0)          if ((cc->cipher->flags & CFLAG_NONE) != 0)
                 return 0;                  return 0;
   
         switch (c->number) {  
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case SSH_CIPHER_SSH2:          evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
         case SSH_CIPHER_DES:          if (evplen == 0)
         case SSH_CIPHER_BLOWFISH:                  return 0;
                 evplen = EVP_CIPHER_CTX_iv_length(cc->evp);          else if (evplen < 0)
                 if (evplen == 0)                  return SSH_ERR_LIBCRYPTO_ERROR;
                         return 0;          if ((u_int)evplen != len)
                 else if (evplen < 0)  
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 if ((u_int)evplen != len)  
                         return SSH_ERR_INVALID_ARGUMENT;  
                 if (cipher_authlen(c)) {  
                         if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,  
                            len, iv))  
                                return SSH_ERR_LIBCRYPTO_ERROR;  
                 } else  
                         memcpy(iv, cc->evp->iv, len);  
                 break;  
 #endif  
         default:  
                 return SSH_ERR_INVALID_ARGUMENT;                  return SSH_ERR_INVALID_ARGUMENT;
         }          if (cipher_authlen(c)) {
                   if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
                      len, iv))
                          return SSH_ERR_LIBCRYPTO_ERROR;
           } else
                   memcpy(iv, cc->evp->iv, len);
   #endif
         return 0;          return 0;
 }  }
   
Line 618 
Line 539 
         if ((cc->cipher->flags & CFLAG_NONE) != 0)          if ((cc->cipher->flags & CFLAG_NONE) != 0)
                 return 0;                  return 0;
   
         switch (c->number) {  
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case SSH_CIPHER_SSH2:          evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
         case SSH_CIPHER_DES:          if (evplen <= 0)
         case SSH_CIPHER_BLOWFISH:                  return SSH_ERR_LIBCRYPTO_ERROR;
                 evplen = EVP_CIPHER_CTX_iv_length(cc->evp);          if (cipher_authlen(c)) {
                 if (evplen <= 0)                  /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
                   if (!EVP_CIPHER_CTX_ctrl(cc->evp,
                       EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
                         return SSH_ERR_LIBCRYPTO_ERROR;                          return SSH_ERR_LIBCRYPTO_ERROR;
                 if (cipher_authlen(c)) {          } else
                         /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */                  memcpy(cc->evp->iv, iv, evplen);
                         if (!EVP_CIPHER_CTX_ctrl(cc->evp,  
                             EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))  
                                 return SSH_ERR_LIBCRYPTO_ERROR;  
                 } else  
                         memcpy(cc->evp->iv, iv, evplen);  
                 break;  
 #endif  #endif
         default:  
                 return SSH_ERR_INVALID_ARGUMENT;  
         }  
         return 0;          return 0;
 }  }
   

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