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

Diff for /src/usr.bin/ssh/kex.c between version 1.64 and 1.64.2.2

version 1.64, 2005/07/25 11:59:39 version 1.64.2.2, 2006/10/06 03:19:32
Line 1 
Line 1 
   /* $OpenBSD$ */
 /*  /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.   * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *   *
Line 22 
Line 23 
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 #include "includes.h"  #include <sys/param.h>
 RCSID("$OpenBSD$");  
   
   #include <signal.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   
 #include <openssl/crypto.h>  #include <openssl/crypto.h>
   
 #include "ssh2.h"  
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "ssh2.h"
 #include "buffer.h"  #include "buffer.h"
 #include "bufaux.h"  
 #include "packet.h"  #include "packet.h"
 #include "compat.h"  #include "compat.h"
 #include "cipher.h"  #include "cipher.h"
 #include "kex.h"  
 #include "key.h"  #include "key.h"
   #include "kex.h"
 #include "log.h"  #include "log.h"
 #include "mac.h"  #include "mac.h"
 #include "match.h"  #include "match.h"
Line 44 
Line 48 
   
 #define KEX_COOKIE_LEN  16  #define KEX_COOKIE_LEN  16
   
   extern const EVP_MD *evp_ssh_sha256(void);
   
 /* prototype */  /* prototype */
 static void kex_kexinit_finish(Kex *);  static void kex_kexinit_finish(Kex *);
 static void kex_choose_conf(Kex *);  static void kex_choose_conf(Kex *);
Line 75 
Line 81 
         int i;          int i;
         char **proposal;          char **proposal;
   
         proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));          proposal = xcalloc(PROPOSAL_MAX, sizeof(char *));
   
         buffer_init(&b);          buffer_init(&b);
         buffer_append(&b, buffer_ptr(raw), buffer_len(raw));          buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
Line 210 
Line 216 
 {  {
         Kex *kex;          Kex *kex;
   
         kex = xmalloc(sizeof(*kex));          kex = xcalloc(1, sizeof(*kex));
         memset(kex, 0, sizeof(*kex));  
         buffer_init(&kex->peer);          buffer_init(&kex->peer);
         buffer_init(&kex->my);          buffer_init(&kex->my);
         kex_prop2buf(&kex->my, proposal);          kex_prop2buf(&kex->my, proposal);
Line 254 
Line 259 
         enc->key_len = cipher_keylen(enc->cipher);          enc->key_len = cipher_keylen(enc->cipher);
         enc->block_size = cipher_blocksize(enc->cipher);          enc->block_size = cipher_blocksize(enc->cipher);
 }  }
   
 static void  static void
 choose_mac(Mac *mac, char *client, char *server)  choose_mac(Mac *mac, char *client, char *server)
 {  {
Line 269 
Line 275 
         mac->key = NULL;          mac->key = NULL;
         mac->enabled = 0;          mac->enabled = 0;
 }  }
   
 static void  static void
 choose_comp(Comp *comp, char *client, char *server)  choose_comp(Comp *comp, char *client, char *server)
 {  {
Line 286 
Line 293 
         }          }
         comp->name = name;          comp->name = name;
 }  }
   
 static void  static void
 choose_kex(Kex *k, char *client, char *server)  choose_kex(Kex *k, char *client, char *server)
 {  {
Line 294 
Line 302 
                 fatal("no kex alg");                  fatal("no kex alg");
         if (strcmp(k->name, KEX_DH1) == 0) {          if (strcmp(k->name, KEX_DH1) == 0) {
                 k->kex_type = KEX_DH_GRP1_SHA1;                  k->kex_type = KEX_DH_GRP1_SHA1;
                   k->evp_md = EVP_sha1();
         } else if (strcmp(k->name, KEX_DH14) == 0) {          } else if (strcmp(k->name, KEX_DH14) == 0) {
                 k->kex_type = KEX_DH_GRP14_SHA1;                  k->kex_type = KEX_DH_GRP14_SHA1;
         } else if (strcmp(k->name, KEX_DHGEX) == 0) {                  k->evp_md = EVP_sha1();
           } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
                 k->kex_type = KEX_DH_GEX_SHA1;                  k->kex_type = KEX_DH_GEX_SHA1;
                   k->evp_md = EVP_sha1();
           } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
                   k->kex_type = KEX_DH_GEX_SHA256;
                   k->evp_md = evp_ssh_sha256();
         } else          } else
                 fatal("bad kex alg %s", k->name);                  fatal("bad kex alg %s", k->name);
 }  }
   
 static void  static void
 choose_hostkeyalg(Kex *k, char *client, char *server)  choose_hostkeyalg(Kex *k, char *client, char *server)
 {  {
Line 360 
Line 375 
   
         /* Algorithm Negotiation */          /* Algorithm Negotiation */
         for (mode = 0; mode < MODE_MAX; mode++) {          for (mode = 0; mode < MODE_MAX; mode++) {
                 newkeys = xmalloc(sizeof(*newkeys));                  newkeys = xcalloc(1, sizeof(*newkeys));
                 memset(newkeys, 0, sizeof(*newkeys));  
                 kex->newkeys[mode] = newkeys;                  kex->newkeys[mode] = newkeys;
                 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);                  ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
                 nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;                  nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
Line 404 
Line 418 
 }  }
   
 static u_char *  static u_char *
 derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret)  derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
       BIGNUM *shared_secret)
 {  {
         Buffer b;          Buffer b;
         const EVP_MD *evp_md = EVP_sha1();  
         EVP_MD_CTX md;          EVP_MD_CTX md;
         char c = id;          char c = id;
         u_int have;          u_int have;
         int mdsz = EVP_MD_size(evp_md);          int mdsz;
         u_char *digest;          u_char *digest;
   
         if (mdsz < 0)          if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0)
                 fatal("derive_key: mdsz < 0");                  fatal("bad kex md size %d", mdsz);
         digest = xmalloc(roundup(need, mdsz));          digest = xmalloc(roundup(need, mdsz));
   
         buffer_init(&b);          buffer_init(&b);
         buffer_put_bignum2(&b, shared_secret);          buffer_put_bignum2(&b, shared_secret);
   
         /* K1 = HASH(K || H || "A" || session_id) */          /* K1 = HASH(K || H || "A" || session_id) */
         EVP_DigestInit(&md, evp_md);          EVP_DigestInit(&md, kex->evp_md);
         if (!(datafellows & SSH_BUG_DERIVEKEY))          if (!(datafellows & SSH_BUG_DERIVEKEY))
                 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));                  EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
         EVP_DigestUpdate(&md, hash, mdsz);          EVP_DigestUpdate(&md, hash, hashlen);
         EVP_DigestUpdate(&md, &c, 1);          EVP_DigestUpdate(&md, &c, 1);
         EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);          EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
         EVP_DigestFinal(&md, digest, NULL);          EVP_DigestFinal(&md, digest, NULL);
Line 436 
Line 450 
          * Key = K1 || K2 || ... || Kn           * Key = K1 || K2 || ... || Kn
          */           */
         for (have = mdsz; need > have; have += mdsz) {          for (have = mdsz; need > have; have += mdsz) {
                 EVP_DigestInit(&md, evp_md);                  EVP_DigestInit(&md, kex->evp_md);
                 if (!(datafellows & SSH_BUG_DERIVEKEY))                  if (!(datafellows & SSH_BUG_DERIVEKEY))
                         EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));                          EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
                 EVP_DigestUpdate(&md, hash, mdsz);                  EVP_DigestUpdate(&md, hash, hashlen);
                 EVP_DigestUpdate(&md, digest, have);                  EVP_DigestUpdate(&md, digest, have);
                 EVP_DigestFinal(&md, digest + have, NULL);                  EVP_DigestFinal(&md, digest + have, NULL);
         }          }
Line 455 
Line 469 
   
 #define NKEYS   6  #define NKEYS   6
 void  void
 kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret)  kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret)
 {  {
         u_char *keys[NKEYS];          u_char *keys[NKEYS];
         u_int i, mode, ctos;          u_int i, mode, ctos;
   
         for (i = 0; i < NKEYS; i++)          for (i = 0; i < NKEYS; i++) {
                 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret);                  keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen,
                       shared_secret);
           }
   
         debug2("kex_derive_keys");          debug2("kex_derive_keys");
         for (mode = 0; mode < MODE_MAX; mode++) {          for (mode = 0; mode < MODE_MAX; mode++) {
                 current_keys[mode] = kex->newkeys[mode];                  current_keys[mode] = kex->newkeys[mode];
                 kex->newkeys[mode] = NULL;                  kex->newkeys[mode] = NULL;
                 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);                  ctos = (!kex->server && mode == MODE_OUT) ||
                       (kex->server && mode == MODE_IN);
                 current_keys[mode]->enc.iv  = keys[ctos ? 0 : 1];                  current_keys[mode]->enc.iv  = keys[ctos ? 0 : 1];
                 current_keys[mode]->enc.key = keys[ctos ? 2 : 3];                  current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
                 current_keys[mode]->mac.key = keys[ctos ? 4 : 5];                  current_keys[mode]->mac.key = keys[ctos ? 4 : 5];

Legend:
Removed from v.1.64  
changed lines
  Added in v.1.64.2.2