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

Diff for /src/usr.bin/ssh/dh.c between version 1.2.2.6 and 1.3

version 1.2.2.6, 2002/03/08 17:04:42 version 1.3, 2000/11/16 17:55:43
Line 31 
Line 31 
 #include <openssl/dh.h>  #include <openssl/dh.h>
 #include <openssl/evp.h>  #include <openssl/evp.h>
   
   #include "ssh.h"
 #include "buffer.h"  #include "buffer.h"
 #include "cipher.h"  
 #include "kex.h"  #include "kex.h"
 #include "dh.h"  #include "dh.h"
 #include "pathnames.h"  
 #include "log.h"  
 #include "misc.h"  
   
 static int  int
 parse_prime(int linenum, char *line, struct dhgroup *dhg)  parse_prime(int linenum, char *line, struct dhgroup *dhg)
 {  {
         char *cp, *arg;          char *cp, *arg;
Line 69 
Line 66 
         if (cp == NULL || *strsize == '\0' ||          if (cp == NULL || *strsize == '\0' ||
             (dhg->size = atoi(strsize)) == 0)              (dhg->size = atoi(strsize)) == 0)
                 goto fail;                  goto fail;
         /* The whole group is one bit larger */  
         dhg->size++;  
         gen = strsep(&cp, " "); /* gen */          gen = strsep(&cp, " "); /* gen */
         if (cp == NULL || *gen == '\0')          if (cp == NULL || *gen == '\0')
                 goto fail;                  goto fail;
Line 78 
Line 73 
         if (cp != NULL || *prime == '\0')          if (cp != NULL || *prime == '\0')
                 goto fail;                  goto fail;
   
         if ((dhg->g = BN_new()) == NULL)          dhg->g = BN_new();
                 fatal("parse_prime: BN_new failed");          if (BN_hex2bn(&dhg->g, gen) < 0) {
         if ((dhg->p = BN_new()) == NULL)                  BN_free(dhg->g);
                 fatal("parse_prime: BN_new failed");                  goto fail;
         if (BN_hex2bn(&dhg->g, gen) == 0)          }
                 goto failclean;          dhg->p = BN_new();
           if (BN_hex2bn(&dhg->p, prime) < 0) {
                   BN_free(dhg->g);
                   BN_free(dhg->p);
                   goto fail;
           }
   
         if (BN_hex2bn(&dhg->p, prime) == 0)  
                 goto failclean;  
   
         if (BN_num_bits(dhg->p) != dhg->size)  
                 goto failclean;  
   
         return (1);          return (1);
   
  failclean:  
         BN_clear_free(dhg->g);  
         BN_clear_free(dhg->p);  
  fail:   fail:
         error("Bad prime description in line %d", linenum);          fprintf(stderr, "Bad prime description in line %d\n", linenum);
         return (0);          return (0);
 }  }
   
 DH *  DH *
 choose_dh(int min, int wantbits, int max)  choose_dh(int minbits)
 {  {
         FILE *f;          FILE *f;
         char line[2048];          char line[1024];
         int best, bestcount, which;          int best, bestcount, which;
         int linenum;          int linenum;
         struct dhgroup dhg;          struct dhgroup dhg;
   
         if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&          f = fopen(DH_PRIMES, "r");
             (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {          if (!f) {
                 log("WARNING: %s does not exist, using old modulus", _PATH_DH_MODULI);                  log("WARNING: %s does not exist, using old prime", DH_PRIMES);
                 return (dh_new_group1());                  return (dh_new_group1());
         }          }
   
Line 122 
Line 112 
                 linenum++;                  linenum++;
                 if (!parse_prime(linenum, line, &dhg))                  if (!parse_prime(linenum, line, &dhg))
                         continue;                          continue;
                 BN_clear_free(dhg.g);                  BN_free(dhg.g);
                 BN_clear_free(dhg.p);                  BN_free(dhg.p);
   
                 if (dhg.size > max || dhg.size < min)                  if ((dhg.size > minbits && dhg.size < best) ||
                         continue;                      (dhg.size > best && best < minbits)) {
   
                 if ((dhg.size > wantbits && dhg.size < best) ||  
                     (dhg.size > best && best < wantbits)) {  
                         best = dhg.size;                          best = dhg.size;
                         bestcount = 0;                          bestcount = 0;
                 }                  }
                 if (dhg.size == best)                  if (dhg.size == best)
                         bestcount++;                          bestcount++;
         }          }
         rewind(f);          fclose (f);
   
         if (bestcount == 0) {          if (bestcount == 0) {
                 fclose(f);                  log("WARNING: no primes in %s, using old prime", DH_PRIMES);
                 log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);                  return (dh_new_group1());
                 return (NULL);  
         }          }
   
           f = fopen(DH_PRIMES, "r");
           if (!f) {
                   fatal("WARNING: %s dissappeared, giving up", DH_PRIMES);
           }
   
         linenum = 0;          linenum = 0;
         which = arc4random() % bestcount;          which = arc4random() % bestcount;
         while (fgets(line, sizeof(line), f)) {          while (fgets(line, sizeof(line), f)) {
                 if (!parse_prime(linenum, line, &dhg))                  if (!parse_prime(linenum, line, &dhg))
                         continue;                          continue;
                 if ((dhg.size > max || dhg.size < min) ||                  if (dhg.size != best)
                     dhg.size != best ||  
                     linenum++ != which) {  
                         BN_clear_free(dhg.g);  
                         BN_clear_free(dhg.p);  
                         continue;                          continue;
                   if (linenum++ != which) {
                           BN_free(dhg.g);
                           BN_free(dhg.p);
                           continue;
                 }                  }
                 break;                  break;
         }          }
         fclose(f);          fclose(f);
         if (linenum != which+1)  
                 fatal("WARNING: line %d disappeared in %s, giving up",  
                     which, _PATH_DH_PRIMES);  
   
         return (dh_new_group(dhg.g, dhg.p));          return (dh_new_group(dhg.g, dhg.p));
 }  
   
 /* diffie-hellman-group1-sha1 */  
   
 int  
 dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)  
 {  
         int i;  
         int n = BN_num_bits(dh_pub);  
         int bits_set = 0;  
   
         if (dh_pub->neg) {  
                 log("invalid public DH value: negativ");  
                 return 0;  
         }  
         for (i = 0; i <= n; i++)  
                 if (BN_is_bit_set(dh_pub, i))  
                         bits_set++;  
         debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));  
   
         /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */  
         if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))  
                 return 1;  
         log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));  
         return 0;  
 }  
   
 void  
 dh_gen_key(DH *dh, int need)  
 {  
         int i, bits_set = 0, tries = 0;  
   
         if (dh->p == NULL)  
                 fatal("dh_gen_key: dh->p == NULL");  
         if (2*need >= BN_num_bits(dh->p))  
                 fatal("dh_gen_key: group too small: %d (2*need %d)",  
                     BN_num_bits(dh->p), 2*need);  
         do {  
                 if (dh->priv_key != NULL)  
                         BN_clear_free(dh->priv_key);  
                 if ((dh->priv_key = BN_new()) == NULL)  
                         fatal("dh_gen_key: BN_new failed");  
                 /* generate a 2*need bits random private exponent */  
                 if (!BN_rand(dh->priv_key, 2*need, 0, 0))  
                         fatal("dh_gen_key: BN_rand failed");  
                 if (DH_generate_key(dh) == 0)  
                         fatal("DH_generate_key");  
                 for (i = 0; i <= BN_num_bits(dh->priv_key); i++)  
                         if (BN_is_bit_set(dh->priv_key, i))  
                                 bits_set++;  
                 debug("dh_gen_key: priv key bits set: %d/%d",  
                     bits_set, BN_num_bits(dh->priv_key));  
                 if (tries++ > 10)  
                         fatal("dh_gen_key: too many bad keys: giving up");  
         } while (!dh_pub_is_valid(dh, dh->pub_key));  
 }  
   
 DH *  
 dh_new_group_asc(const char *gen, const char *modulus)  
 {  
         DH *dh;  
   
         if ((dh = DH_new()) == NULL)  
                 fatal("dh_new_group_asc: DH_new");  
   
         if (BN_hex2bn(&dh->p, modulus) == 0)  
                 fatal("BN_hex2bn p");  
         if (BN_hex2bn(&dh->g, gen) == 0)  
                 fatal("BN_hex2bn g");  
   
         return (dh);  
 }  
   
 /*  
  * This just returns the group, we still need to generate the exchange  
  * value.  
  */  
   
 DH *  
 dh_new_group(BIGNUM *gen, BIGNUM *modulus)  
 {  
         DH *dh;  
   
         if ((dh = DH_new()) == NULL)  
                 fatal("dh_new_group: DH_new");  
         dh->p = modulus;  
         dh->g = gen;  
   
         return (dh);  
 }  
   
 DH *  
 dh_new_group1(void)  
 {  
         static char *gen = "2", *group1 =  
             "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"  
             "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"  
             "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"  
             "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"  
             "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"  
             "FFFFFFFF" "FFFFFFFF";  
   
         return (dh_new_group_asc(gen, group1));  
 }  
   
 /*  
  * Estimates the group order for a Diffie-Hellman group that has an  
  * attack complexity approximately the same as O(2**bits).  Estimate  
  * with:  O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))  
  */  
   
 int  
 dh_estimate(int bits)  
 {  
   
         if (bits < 64)  
                 return (512);   /* O(2**63) */  
         if (bits < 128)  
                 return (1024);  /* O(2**86) */  
         if (bits < 192)  
                 return (2048);  /* O(2**116) */  
         return (4096);          /* O(2**156) */  
 }  }

Legend:
Removed from v.1.2.2.6  
changed lines
  Added in v.1.3