Enhance EVP code to generate random symmetric keys of the
authorDr. Stephen Henson <steve@openssl.org>
Sun, 28 Mar 2004 17:38:00 +0000 (17:38 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 28 Mar 2004 17:38:00 +0000 (17:38 +0000)
appropriate form, for example correct DES parity.

Update S/MIME code and EVP_SealInit to use new functions.

PR: 700

CHANGES
crypto/evp/e_des.c
crypto/evp/e_des3.c
crypto/evp/evp.h
crypto/evp/evp_enc.c
crypto/evp/p_seal.c
crypto/pkcs7/pk7_doit.c

diff --git a/CHANGES b/CHANGES
index c5c2ebba9ba266ef9ba0a06cdf3c60a553f734bd..a72d5d6eaaf5f8d9c9c1aef4ad96ac24c8cebd49 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,16 @@
 
  Changes between 0.9.7c and 0.9.8  [xx XXX xxxx]
 
+  *) Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality.
+     This will generate a random key of the appropriate length based on the 
+     cipher context. The EVP_CIPHER can provide its own random key generation
+     routine to support keys of a specific form. This is used in the des and 
+     3des routines to generate a key of the correct parity. Update S/MIME
+     code to use new functions and hence generate correct parity DES keys.
+     Add EVP_CHECK_DES_KEY #define to return an error if the key is not 
+     valid (weak or incorrect parity).
+     [Steve Henson]
+
   *) Add a local set of CRLs that can be used by X509_verify_cert() as well
      as looking them up. This is useful when the verified structure may contain
      CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs
index f2554ecc6a2ef50170632939e4ef223ae6bbbbff..856323648cd4c69ab3a9cfe66c87db824a7d8827 100644 (file)
 #include <openssl/objects.h>
 #include "evp_locl.h"
 #include <openssl/des.h>
+#include <openssl/rand.h>
 
 static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                        const unsigned char *iv, int enc);
+static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
 
 /* Because of various casts and different names can't use IMPLEMENT_BLOCK_CIPHER */
 
@@ -127,26 +129,48 @@ static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     }
 
 BLOCK_CIPHER_defs(des, DES_key_schedule, NID_des, 8, 8, 8, 64,
-                       0, des_init_key, NULL,
+                       EVP_CIPH_RAND_KEY, des_init_key, NULL,
                        EVP_CIPHER_set_asn1_iv,
                        EVP_CIPHER_get_asn1_iv,
-                       NULL)
+                       des_ctrl)
 
-BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,1,0,des_init_key,NULL,
+BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,1,
+                    EVP_CIPH_RAND_KEY, des_init_key,NULL,
                     EVP_CIPHER_set_asn1_iv,
-                    EVP_CIPHER_get_asn1_iv,NULL)
+                    EVP_CIPHER_get_asn1_iv,des_ctrl)
 
-BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,8,0,des_init_key,NULL,
+BLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,8,
+                    EVP_CIPH_RAND_KEY,des_init_key,NULL,
                     EVP_CIPHER_set_asn1_iv,
-                    EVP_CIPHER_get_asn1_iv,NULL)
+                    EVP_CIPHER_get_asn1_iv,des_ctrl)
 
 static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                        const unsigned char *iv, int enc)
        {
        DES_cblock *deskey = (DES_cblock *)key;
-
+#ifdef EVP_CHECK_DES_KEY
+       if(DES_set_key_checked(deskey,ctx->cipher_data) != 0)
+               return 0;
+#else
        DES_set_key_unchecked(deskey,ctx->cipher_data);
+#endif
        return 1;
        }
 
+static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+       {
+       
+       switch(type)
+               {
+       case EVP_CTRL_RAND_KEY:
+               if (RAND_bytes(ptr, 8) <= 0)
+                       return 0;
+               DES_set_odd_parity((DES_cblock *)ptr);
+               return 1;
+
+       default:
+               return -1;
+               }
+       }
+
 #endif
index 86342fb952e88ed376a5b924bf3802cc2cef254f..ac148efab237f4363261f1795cc24b8c72c9667f 100644 (file)
@@ -63,6 +63,7 @@
 #include <openssl/objects.h>
 #include "evp_locl.h"
 #include <openssl/des.h>
+#include <openssl/rand.h>
 
 static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                            const unsigned char *iv,int enc);
@@ -70,6 +71,8 @@ static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                             const unsigned char *iv,int enc);
 
+static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
+
 typedef struct
     {
     DES_key_schedule ks1;/* key schedule */
@@ -161,10 +164,10 @@ static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     }
 
 BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
-                       0, des_ede_init_key, NULL, 
+                       EVP_CIPH_RAND_KEY, des_ede_init_key, NULL, 
                        EVP_CIPHER_set_asn1_iv,
                        EVP_CIPHER_get_asn1_iv,
-                       NULL)
+                       des3_ctrl)
 
 #define des_ede3_cfb64_cipher des_ede_cfb64_cipher
 #define des_ede3_ofb_cipher des_ede_ofb_cipher
@@ -172,28 +175,35 @@ BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
 #define des_ede3_ecb_cipher des_ede_ecb_cipher
 
 BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64,
-                       0, des_ede3_init_key, NULL, 
+                       EVP_CIPH_RAND_KEY, des_ede3_init_key, NULL, 
                        EVP_CIPHER_set_asn1_iv,
                        EVP_CIPHER_get_asn1_iv,
-                       NULL)
+                       des3_ctrl)
 
-BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,1,0,
-                    des_ede3_init_key,NULL,
+BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,1,
+                    EVP_CIPH_RAND_KEY, des_ede3_init_key,NULL,
                     EVP_CIPHER_set_asn1_iv,
-                    EVP_CIPHER_get_asn1_iv,NULL)
+                    EVP_CIPHER_get_asn1_iv,
+                    des3_ctrl)
 
-BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,8,0,
-                    des_ede3_init_key,NULL,
+BLOCK_CIPHER_def_cfb(des_ede3,DES_EDE_KEY,NID_des_ede3,24,8,8,
+                    EVP_CIPH_RAND_KEY, des_ede3_init_key,NULL,
                     EVP_CIPHER_set_asn1_iv,
-                    EVP_CIPHER_get_asn1_iv,NULL)
+                    EVP_CIPHER_get_asn1_iv,
+                    des3_ctrl)
 
 static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                            const unsigned char *iv, int enc)
        {
        DES_cblock *deskey = (DES_cblock *)key;
-
+#ifdef EVP_CHECK_DES_KEY
+       if (DES_set_key_checked(&deskey[0],&data(ctx)->ks1)
+               !! DES_set_key_checked(&deskey[1],&data(ctx)->ks2))
+               return 0;
+#else
        DES_set_key_unchecked(&deskey[0],&data(ctx)->ks1);
        DES_set_key_unchecked(&deskey[1],&data(ctx)->ks2);
+#endif
        memcpy(&data(ctx)->ks3,&data(ctx)->ks1,
               sizeof(data(ctx)->ks1));
        return 1;
@@ -214,13 +224,41 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        }
 #endif /* KSSL_DEBUG */
 
+#ifdef EVP_CHECK_DES_KEY
+       if (DES_set_key_checked(&deskey[0],&data(ctx)->ks1)
+               || DES_set_key_checked(&deskey[1],&data(ctx)->ks2)
+               || DES_set_key_checked(&deskey[2],&data(ctx)->ks3))
+               return 0;
+#else
        DES_set_key_unchecked(&deskey[0],&data(ctx)->ks1);
        DES_set_key_unchecked(&deskey[1],&data(ctx)->ks2);
        DES_set_key_unchecked(&deskey[2],&data(ctx)->ks3);
-
+#endif
        return 1;
        }
 
+static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+       {
+
+       DES_cblock *deskey = ptr;
+
+       switch(type)
+               {
+       case EVP_CTRL_RAND_KEY:
+               if (RAND_bytes(ptr, c->key_len) <= 0)
+                       return 0;
+               DES_set_odd_parity(deskey);
+               if (c->key_len >= 16)
+                       DES_set_odd_parity(deskey + 1);
+               if (c->key_len >= 24)
+                       DES_set_odd_parity(deskey + 2);
+               return 1;
+
+       default:
+               return -1;
+               }
+       }
+
 const EVP_CIPHER *EVP_des_ede(void)
 {
        return &des_ede_ecb;
index ce5c210f61bfa9308fd2e4238ba38c11cbda74a8..6adbe891a0dcfa753be0a036b50730ac18cb5c02 100644 (file)
@@ -332,6 +332,8 @@ struct evp_cipher_st
 #define        EVP_CIPH_CUSTOM_KEY_LENGTH      0x80
 /* Don't use standard block padding */
 #define        EVP_CIPH_NO_PADDING             0x100
+/* cipher handles random key generation */
+#define        EVP_CIPH_RAND_KEY               0x200
 
 /* ctrl() values */
 
@@ -341,6 +343,7 @@ struct evp_cipher_st
 #define        EVP_CTRL_SET_RC2_KEY_BITS       0x3
 #define        EVP_CTRL_GET_RC5_ROUNDS         0x4
 #define        EVP_CTRL_SET_RC5_ROUNDS         0x5
+#define        EVP_CTRL_RAND_KEY               0x6
 
 typedef struct evp_cipher_info_st
        {
@@ -567,6 +570,7 @@ int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
 int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
 
 #ifndef OPENSSL_NO_BIO
 BIO_METHOD *BIO_f_md(void);
index cecb09cbe775e6cc10a68a3396787532b906a119..b5236b976631f59904ff5db20d7b1bc5ad97ec0a 100644 (file)
@@ -534,3 +534,13 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
        }
        return ret;
 }
+
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
+       {
+       if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
+               return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
+       if (RAND_bytes(key, ctx->key_len) <= 0)
+               return 0;
+       return 1;
+       }
+
index 37e547fe7276a1ee748456a5008f4ca34bacde18..8cc8fcb0bd058e4c4022fdceefde0e0c2e5e379f 100644 (file)
@@ -78,7 +78,7 @@ int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char **ek
        }
        if ((npubk <= 0) || !pubk)
                return 1;
-       if (RAND_bytes(key,EVP_MAX_KEY_LENGTH) <= 0)
+       if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
                return 0;
        if (EVP_CIPHER_CTX_iv_length(ctx))
                RAND_pseudo_bytes(iv,EVP_CIPHER_CTX_iv_length(ctx));
index 0b262fa0653f6c1542fc8e8cdea6138b0f46cb8d..25483bc156e3ecb122ecc996352e34e293cee918 100644 (file)
@@ -215,11 +215,14 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
                BIO_get_cipher_ctx(btmp, &ctx);
                keylen=EVP_CIPHER_key_length(evp_cipher);
                ivlen=EVP_CIPHER_iv_length(evp_cipher);
-               if (RAND_bytes(key,keylen) <= 0)
-                       goto err;
                xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
                if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
-               EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1);
+               if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
+                       goto err;
+               if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
+                       goto err;
+               if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
+                       goto err;
 
                if (ivlen > 0) {
                        if (xalg->parameter == NULL) 
@@ -440,7 +443,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 
                evp_ctx=NULL;
                BIO_get_cipher_ctx(etmp,&evp_ctx);
-               EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0);
+               if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
+                       goto err;
                if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
                        goto err;
 
@@ -456,7 +460,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
                                goto err;
                                }
                } 
-               EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0);
+               if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
+                       goto err;
 
                OPENSSL_cleanse(tmp,jj);