Make D-H safer, include well-known primes.
authorBen Laurie <ben@openssl.org>
Sun, 21 Aug 2005 16:00:17 +0000 (16:00 +0000)
committerBen Laurie <ben@openssl.org>
Sun, 21 Aug 2005 16:00:17 +0000 (16:00 +0000)
CHANGES
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c
crypto/bn/Makefile
crypto/bn/bn.h
crypto/dh/dh.h
crypto/dh/dh_check.c
crypto/dh/dh_err.c
crypto/dh/dh_key.c

diff --git a/CHANGES b/CHANGES
index c58c811..a695a4d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,7 +2,7 @@
  OpenSSL CHANGES
  _______________
 
- Changes between 0.9.8 and 0.9.9  [xx XXX xxxx]
+ Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
   *) Support for PKCS#1 RSAPublicKey format on rsa utility command line.
      [Steve Henson]
 
  Changes between 0.9.8 and 0.9.8a  [XX xxx XXXX]
 
+  *) Avoid small subgroup attacks in Diffie-Hellman.
+     [Nick Mathewson and Ben Laurie]
+
+  *) Add functions for well-known primes.
+     [Nick Mathewson]
+
   *) Extended Windows CE support.
      [Satoshi Nakamura and Andy Polyakov]
  
index e0e474f..680f928 100644 (file)
@@ -1040,6 +1040,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_F_ASN1_MBSTRING_NCOPY                      122
 #define ASN1_F_ASN1_OBJECT_NEW                          123
 #define ASN1_F_ASN1_PACK_STRING                                 124
+#define ASN1_F_ASN1_PCTX_NEW                            205
 #define ASN1_F_ASN1_PKCS5_PBE_SET                       125
 #define ASN1_F_ASN1_SEQ_PACK                            126
 #define ASN1_F_ASN1_SEQ_UNPACK                          127
index b9df21c..bef2519 100644 (file)
@@ -111,6 +111,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
 {ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
 {ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW),     "ASN1_OBJECT_new"},
 {ERR_FUNC(ASN1_F_ASN1_PACK_STRING),    "ASN1_pack_string"},
+{ERR_FUNC(ASN1_F_ASN1_PCTX_NEW),       "ASN1_PCTX_NEW"},
 {ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET),  "ASN1_PKCS5_PBE_SET"},
 {ERR_FUNC(ASN1_F_ASN1_SEQ_PACK),       "ASN1_seq_pack"},
 {ERR_FUNC(ASN1_F_ASN1_SEQ_UNPACK),     "ASN1_seq_unpack"},
index 4afb6a3..ab9c494 100644 (file)
@@ -28,13 +28,13 @@ LIBSRC=     bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \
        bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
        bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c bn_asm.c \
        bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \
-       bn_depr.c
+       bn_depr.c bn_const.c
 
 LIBOBJ=        bn_add.o bn_div.o bn_exp.o bn_lib.o bn_ctx.o bn_mul.o bn_mod.o \
        bn_print.o bn_rand.o bn_shift.o bn_word.o bn_blind.o \
        bn_kron.o bn_sqrt.o bn_gcd.o bn_prime.o bn_err.o bn_sqr.o $(BN_ASM) \
        bn_recp.o bn_mont.o bn_mpi.o bn_exp2.o bn_gf2m.o bn_nist.o \
-       bn_depr.o
+       bn_depr.o bn_const.o
 
 SRC= $(LIBSRC)
 
index 670584a..b990ff2 100644 (file)
@@ -732,6 +732,18 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
 BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
 BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
 
+/* Primes from RFC 2409 */
+int get_rfc2409_prime_768(BIGNUM **bn);
+int get_rfc2409_prime_1024(BIGNUM **bn);
+
+/* Primes from RFC 3526 */
+int get_rfc3526_prime_1536(BIGNUM **bn);
+int get_rfc3526_prime_2048(BIGNUM **bn);
+int get_rfc3526_prime_3072(BIGNUM **bn);
+int get_rfc3526_prime_4096(BIGNUM **bn);
+int get_rfc3526_prime_6144(BIGNUM **bn);
+int get_rfc3526_prime_8192(BIGNUM **bn);
+
 int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
 
 /* BEGIN ERROR CODES */
index d1559fd..7871882 100644 (file)
@@ -145,6 +145,10 @@ struct dh_st
 #define DH_UNABLE_TO_CHECK_GENERATOR   0x04
 #define DH_NOT_SUITABLE_GENERATOR      0x08
 
+/* DH_check_pub_key error codes */
+#define DH_CHECK_PUBKEY_TOO_SMALL      0x01
+#define DH_CHECK_PUBKEY_TOO_LARGE      0x02
+
 /* primes p where (p-1)/2 is prime too are called "safe"; we define
    this for backward compatibility: */
 #define DH_CHECK_P_NOT_STRONG_PRIME    DH_CHECK_P_NOT_SAFE_PRIME
@@ -183,6 +187,7 @@ DH *        DH_generate_parameters(int prime_len,int generator,
 int    DH_generate_parameters_ex(DH *dh, int prime_len,int generator, BN_GENCB *cb);
 
 int    DH_check(const DH *dh,int *codes);
+int    DH_check_pub_key(const DH *dh,const BIGNUM *pub_key, int *codes);
 int    DH_generate_key(DH *dh);
 int    DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
 DH *   d2i_DHparams(DH **a,const unsigned char **pp, long length);
@@ -216,6 +221,7 @@ void ERR_load_DH_strings(void);
 /* Reason codes. */
 #define DH_R_BAD_GENERATOR                              101
 #define DH_R_NO_PRIVATE_VALUE                           100
+#define DH_R_INVALID_PUBKEY                             102
 
 #ifdef  __cplusplus
 }
index bfc9c3a..10217c8 100644 (file)
@@ -118,3 +118,25 @@ err:
        if (q != NULL) BN_free(q);
        return(ok);
        }
+
+int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
+       {
+       int ok=0;
+       BIGNUM *q=NULL;
+
+       *ret=0;
+       q=BN_new();
+       if (q == NULL) goto err;
+       BN_set_word(q,1);
+       if (BN_cmp(pub_key,q)<=0)
+               *ret|=DH_CHECK_PUBKEY_TOO_SMALL;
+       BN_copy(q,dh->p);
+       BN_sub_word(q,1);
+       if (BN_cmp(pub_key,q)>=0)
+               *ret|=DH_CHECK_PUBKEY_TOO_LARGE;
+
+       ok = 1;
+err:
+       if (q != NULL) BN_free(q);
+       return(ok);
+       }
index edce2c7..ea67fb7 100644 (file)
@@ -84,6 +84,7 @@ static ERR_STRING_DATA DH_str_reasons[]=
        {
 {ERR_REASON(DH_R_BAD_GENERATOR)          ,"bad generator"},
 {ERR_REASON(DH_R_NO_PRIVATE_VALUE)       ,"no private value"},
+{ERR_REASON(DH_R_INVALID_PUBKEY)         ,"invalid public key"},
 {0,NULL}
        };
 
index 39eefe3..cc17c88 100644 (file)
@@ -177,6 +177,7 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
        BN_MONT_CTX *mont=NULL;
        BIGNUM *tmp;
        int ret= -1;
+        int check_result;
 
        ctx = BN_CTX_new();
        if (ctx == NULL) goto err;
@@ -202,6 +203,12 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
                        goto err;
                }
 
+        if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result)
+               {
+               DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY);
+               goto err;
+               }
+
        if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont))
                {
                DHerr(DH_F_COMPUTE_KEY,ERR_R_BN_LIB);