[openssl-commits] [openssl] master update

Dr. Stephen Henson steve at openssl.org
Tue May 26 12:27:21 UTC 2015


The branch master has been updated
       via  f2e19cb15e3d68c748ce3dc2b791be9a2fc14fd3 (commit)
       via  0ceb8b74f50066a4bfa55227bc741e3259f7df43 (commit)
       via  6355d31538fb3d50ba34210e6514cfac1c627243 (commit)
       via  fef034f85ea8b533423d4102cb8f83ef0ac24154 (commit)
       via  764ca96c953b4bcc23a390a1f68dbcad81a2b12f (commit)
       via  351fe21402496dfdb2673a610162519b80991665 (commit)
      from  e8356e32aed70d139eae2d05aeaeb160509262aa (commit)


- Log -----------------------------------------------------------------
commit f2e19cb15e3d68c748ce3dc2b791be9a2fc14fd3
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu May 21 16:33:35 2015 +0100

    make update
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 0ceb8b74f50066a4bfa55227bc741e3259f7df43
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu May 21 14:17:32 2015 +0100

    scrypt in pkcs8 util
    
    Add support for PKCS#8 private key encryption using the scrypt algorithm
    in the pkcs8 utility. Update documentation.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 6355d31538fb3d50ba34210e6514cfac1c627243
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu May 21 00:37:39 2015 +0100

    Add function PKCS8_set0_pbe
    
    This adds a new function which will encrypt a private key using PKCS#8
    based on an X509_ALGOR structure and reimplements PKCS8_encrypt to use it.
    
    Update pkcs8 utlity to use PKCS8_set0_pbe.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit fef034f85ea8b533423d4102cb8f83ef0ac24154
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu May 21 01:16:31 2015 +0100

    Error if memory limit exceeded.
    
    Set a specific error if the parameters are otherwise valid but exceed the
    memory limit.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 764ca96c953b4bcc23a390a1f68dbcad81a2b12f
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu May 21 01:15:51 2015 +0100

    Fix memory leak.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

commit 351fe21402496dfdb2673a610162519b80991665
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri May 22 17:17:21 2015 +0100

    Add PBE tests.
    
    Add support for PKCS#12 and PBKDF2 password based encryption tests. Add
    additional test data.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 apps/pkcs8.c             |  53 ++++++++++++++--
 crypto/evp/Makefile      |   3 +-
 crypto/evp/evp_err.c     |   2 +
 crypto/evp/scrypt.c      |   5 +-
 crypto/pkcs12/p12_decr.c |   4 +-
 crypto/pkcs12/p12_p8e.c  |  49 +++++++++------
 crypto/pkcs12/pk12err.c  |   3 +-
 doc/apps/pkcs8.pod       |  15 +++++
 include/openssl/evp.h    |   2 +
 include/openssl/pkcs12.h |   3 +
 test/Makefile            |  10 +--
 test/evp_test.c          | 110 ++++++++++++++++++++++++++-------
 test/evptests.txt        | 156 +++++++++++++++++++++++++++++++++++++++++++++++
 util/libeay.num          |   1 +
 14 files changed, 360 insertions(+), 56 deletions(-)

diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index 55c4eea..b4af160 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -68,7 +68,8 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
     OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, OPT_NOOCT, OPT_NSDB, OPT_EMBED,
-    OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT
+    OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
+    OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P
 } OPTION_CHOICE;
 
 OPTIONS pkcs8_options[] = {
@@ -93,6 +94,10 @@ OPTIONS pkcs8_options[] = {
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
+    {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"},
+    {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"},
+    {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"},
+    {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"},
     {NULL}
 };
 
@@ -110,6 +115,7 @@ int pkcs8_main(int argc, char **argv)
     OPTION_CHOICE o;
     int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER, p8_broken = PKCS8_OK;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
+    uint64_t scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
 
     prog = opt_init(argc, argv, pkcs8_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -188,6 +194,25 @@ int pkcs8_main(int argc, char **argv)
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_SCRYPT:
+            scrypt_N = 1024;
+            scrypt_r = 8;
+            scrypt_p = 16;
+            if (cipher == NULL)
+                cipher = EVP_aes_256_cbc();
+            break;
+        case OPT_SCRYPT_N:
+            if (!opt_ulong(opt_arg(), &scrypt_N))
+                goto opthelp;
+            break;
+        case OPT_SCRYPT_R:
+            if (!opt_ulong(opt_arg(), &scrypt_r))
+                goto opthelp;
+            break;
+        case OPT_SCRYPT_P:
+            if (!opt_ulong(opt_arg(), &scrypt_p))
+                goto opthelp;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -226,18 +251,36 @@ int pkcs8_main(int argc, char **argv)
                 goto end;
             }
         } else {
+            X509_ALGOR *pbe;
+            if (cipher) {
+                if (scrypt_N && scrypt_r && scrypt_p)
+                    pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL,
+                                                scrypt_N, scrypt_r, scrypt_p);
+                else
+                    pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL,
+                                            pbe_nid);
+            } else {
+                pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0);
+            }
+            if (pbe == NULL) {
+                BIO_printf(bio_err, "Error setting PBE algorithm\n");
+                ERR_print_errors(bio_err);
+                goto end;
+            }
             if (passout)
                 p8pass = passout;
             else {
                 p8pass = pass;
                 if (EVP_read_pw_string
-                    (pass, sizeof pass, "Enter Encryption Password:", 1))
+                    (pass, sizeof pass, "Enter Encryption Password:", 1)) {
+                    X509_ALGOR_free(pbe);
                     goto end;
+                }
             }
             app_RAND_load_file(NULL, 0);
-            if ((p8 = PKCS8_encrypt(pbe_nid, cipher,
-                                    p8pass, strlen(p8pass),
-                                    NULL, 0, iter, p8inf)) == NULL) {
+            p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe);
+            if (p8 == NULL) {
+                X509_ALGOR_free(pbe);
                 BIO_printf(bio_err, "Error encrypting key\n");
                 ERR_print_errors(bio_err);
                 goto end;
diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile
index c23c39a..1a65b46 100644
--- a/crypto/evp/Makefile
+++ b/crypto/evp/Makefile
@@ -772,7 +772,8 @@ pmeth_lib.o: ../include/internal/cryptlib.h ../include/internal/evp_int.h
 pmeth_lib.o: pmeth_lib.c
 scrypt.o: ../../include/internal/numbers.h ../../include/openssl/asn1.h
 scrypt.o: ../../include/openssl/bio.h ../../include/openssl/crypto.h
-scrypt.o: ../../include/openssl/e_os2.h ../../include/openssl/evp.h
+scrypt.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
+scrypt.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
 scrypt.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
 scrypt.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
 scrypt.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 00c9386..d718b60 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -100,6 +100,7 @@ static ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_FUNC(EVP_F_EVP_PBE_ALG_ADD), "EVP_PBE_alg_add"},
     {ERR_FUNC(EVP_F_EVP_PBE_ALG_ADD_TYPE), "EVP_PBE_alg_add_type"},
     {ERR_FUNC(EVP_F_EVP_PBE_CIPHERINIT), "EVP_PBE_CipherInit"},
+    {ERR_FUNC(EVP_F_EVP_PBE_SCRYPT), "EVP_PBE_scrypt"},
     {ERR_FUNC(EVP_F_EVP_PKCS82PKEY), "EVP_PKCS82PKEY"},
     {ERR_FUNC(EVP_F_EVP_PKCS82PKEY_BROKEN), "EVP_PKCS82PKEY_BROKEN"},
     {ERR_FUNC(EVP_F_EVP_PKEY2PKCS8_BROKEN), "EVP_PKEY2PKCS8_broken"},
@@ -197,6 +198,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_REASON(EVP_R_INVALID_OPERATION), "invalid operation"},
     {ERR_REASON(EVP_R_IV_TOO_LARGE), "iv too large"},
     {ERR_REASON(EVP_R_KEYGEN_FAILURE), "keygen failure"},
+    {ERR_REASON(EVP_R_MEMORY_LIMIT_EXCEEDED), "memory limit exceeded"},
     {ERR_REASON(EVP_R_MESSAGE_DIGEST_IS_NULL), "message digest is null"},
     {ERR_REASON(EVP_R_METHOD_NOT_SUPPORTED), "method not supported"},
     {ERR_REASON(EVP_R_MISSING_PARAMETERS), "missing parameters"},
diff --git a/crypto/evp/scrypt.c b/crypto/evp/scrypt.c
index 971d53e..09dfdf2 100644
--- a/crypto/evp/scrypt.c
+++ b/crypto/evp/scrypt.c
@@ -61,6 +61,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <openssl/evp.h>
+#include <openssl/err.h>
 #include <internal/numbers.h>
 
 #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
@@ -255,8 +256,10 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
     if (maxmem == 0)
         maxmem = SCRYPT_MAX_MEM;
 
-    if (Blen + Vlen > maxmem)
+    if (Blen + Vlen > maxmem) {
+        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
         return 0;
+    }
 
     /* If no key return to indicate parameters are OK */
     if (key == NULL)
diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c
index f19830c..8996b9e 100644
--- a/crypto/pkcs12/p12_decr.c
+++ b/crypto/pkcs12/p12_decr.c
@@ -75,7 +75,7 @@ unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass,
                                 int passlen, unsigned char *in, int inlen,
                                 unsigned char **data, int *datalen, int en_de)
 {
-    unsigned char *out;
+    unsigned char *out = NULL;
     int outlen, i;
     EVP_CIPHER_CTX ctx;
 
@@ -85,7 +85,7 @@ unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass,
                             algor->parameter, &ctx, en_de)) {
         PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,
                   PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR);
-        return NULL;
+        goto err;
     }
 
     if ((out = OPENSSL_malloc(inlen + EVP_CIPHER_CTX_block_size(&ctx)))
diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c
index 46ed78a..552f2f0 100644
--- a/crypto/pkcs12/p12_p8e.c
+++ b/crypto/pkcs12/p12_p8e.c
@@ -66,14 +66,9 @@ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
                         unsigned char *salt, int saltlen, int iter,
                         PKCS8_PRIV_KEY_INFO *p8inf)
 {
-    X509_SIG *p8;
+    X509_SIG *p8 = NULL;
     X509_ALGOR *pbe;
 
-    if ((p8 = X509_SIG_new()) == NULL) {
-        PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
     if (pbe_nid == -1)
         pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen);
     else if (EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0))
@@ -84,22 +79,40 @@ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
     }
     if (!pbe) {
         PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_ASN1_LIB);
-        goto err;
+        return NULL;
     }
-    X509_ALGOR_free(p8->algor);
-    p8->algor = pbe;
-    ASN1_OCTET_STRING_free(p8->digest);
-    p8->digest =
+    p8 = PKCS8_set0_pbe(pass, passlen, p8inf, pbe);
+    if (p8 == NULL) {
+        X509_ALGOR_free(pbe);
+        return NULL;
+    }
+
+    return p8;
+}
+
+X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+                         PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe)
+{
+    X509_SIG *p8;
+    ASN1_OCTET_STRING *enckey;
+
+    enckey =
         PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO),
                                 pass, passlen, p8inf, 1);
-    if (!p8->digest) {
-        PKCS12err(PKCS12_F_PKCS8_ENCRYPT, PKCS12_R_ENCRYPT_ERROR);
-        goto err;
+    if (!enckey) {
+        PKCS12err(PKCS12_F_PKCS8_SET0_PBE, PKCS12_R_ENCRYPT_ERROR);
+        return NULL;
     }
 
-    return p8;
+    if (!(p8 = X509_SIG_new())) {
+        PKCS12err(PKCS12_F_PKCS8_SET0_PBE, ERR_R_MALLOC_FAILURE);
+        ASN1_OCTET_STRING_free(enckey);
+        return NULL;
+    }
+    X509_ALGOR_free(p8->algor);
+    ASN1_OCTET_STRING_free(p8->digest);
+    p8->algor = pbe;
+    p8->digest = enckey;
 
- err:
-    X509_SIG_free(p8);
-    return NULL;
+    return p8;
 }
diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c
index e58710b..4e6c7dd 100644
--- a/crypto/pkcs12/pk12err.c
+++ b/crypto/pkcs12/pk12err.c
@@ -1,6 +1,6 @@
 /* crypto/pkcs12/pk12err.c */
 /* ====================================================================
- * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2015 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -101,6 +101,7 @@ static ERR_STRING_DATA PKCS12_str_functs[] = {
     {ERR_FUNC(PKCS12_F_PKCS12_VERIFY_MAC), "PKCS12_verify_mac"},
     {ERR_FUNC(PKCS12_F_PKCS8_ADD_KEYUSAGE), "PKCS8_add_keyusage"},
     {ERR_FUNC(PKCS12_F_PKCS8_ENCRYPT), "PKCS8_encrypt"},
+    {ERR_FUNC(PKCS12_F_PKCS8_SET0_PBE), "PKCS8_set0_pbe"},
     {0, NULL}
 };
 
diff --git a/doc/apps/pkcs8.pod b/doc/apps/pkcs8.pod
index e946cbd..44c27f1 100644
--- a/doc/apps/pkcs8.pod
+++ b/doc/apps/pkcs8.pod
@@ -24,6 +24,10 @@ B<openssl> B<pkcs8>
 [B<-v2prf alg>]
 [B<-v1 alg>]
 [B<-engine id>]
+[B<-scrypt>]
+[B<-scrypt_N N>]
+[B<-scrypt_r r>]
+[B<-scrypt_p p>]
 
 =head1 DESCRIPTION
 
@@ -144,6 +148,17 @@ to attempt to obtain a functional reference to the specified engine,
 thus initialising it if needed. The engine will then be set as the default
 for all available algorithms.
 
+=item B<-scrypt>
+
+uses the B<scrypt> algorithm for private key encryption using default
+parameters: currently N=1024, r=8 and p=16 and AES in CBC mode with a 256 bit
+key. These parameters can be modified using the B<-scrypt_N>, B<-scrypt_r>,
+B<-scrypt_p> and B<-v2> options.
+
+B<-scrypt_N N> B<-scrypt_r r> B<-scrypt_p p>
+
+sets the scrypt B<N>, B<r> or B<p> parameters.
+
 =back
 
 =head1 NOTES
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 3a4bcbd..dd4d701 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1447,6 +1447,7 @@ void ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PBE_ALG_ADD                            115
 # define EVP_F_EVP_PBE_ALG_ADD_TYPE                       160
 # define EVP_F_EVP_PBE_CIPHERINIT                         116
+# define EVP_F_EVP_PBE_SCRYPT                             181
 # define EVP_F_EVP_PKCS82PKEY                             111
 # define EVP_F_EVP_PKCS82PKEY_BROKEN                      136
 # define EVP_F_EVP_PKEY2PKCS8_BROKEN                      113
@@ -1538,6 +1539,7 @@ void ERR_load_EVP_strings(void);
 # define EVP_R_INVALID_OPERATION                          148
 # define EVP_R_IV_TOO_LARGE                               102
 # define EVP_R_KEYGEN_FAILURE                             120
+# define EVP_R_MEMORY_LIMIT_EXCEEDED                      172
 # define EVP_R_MESSAGE_DIGEST_IS_NULL                     159
 # define EVP_R_METHOD_NOT_SUPPORTED                       144
 # define EVP_R_MISSING_PARAMETERS                         103
diff --git a/include/openssl/pkcs12.h b/include/openssl/pkcs12.h
index e58e55c..ba8b944 100644
--- a/include/openssl/pkcs12.h
+++ b/include/openssl/pkcs12.h
@@ -182,6 +182,8 @@ PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag,
 X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
                         const char *pass, int passlen, unsigned char *salt,
                         int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
+X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+                        PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
 PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass,
                                      int passlen, unsigned char *salt,
                                      int saltlen, int iter,
@@ -309,6 +311,7 @@ void ERR_load_PKCS12_strings(void);
 # define PKCS12_F_PKCS12_VERIFY_MAC                       126
 # define PKCS12_F_PKCS8_ADD_KEYUSAGE                      124
 # define PKCS12_F_PKCS8_ENCRYPT                           125
+# define PKCS12_F_PKCS8_SET0_PBE                          132
 
 /* Reason codes. */
 # define PKCS12_R_CANT_PACK_STRUCTURE                     100
diff --git a/test/Makefile b/test/Makefile
index 86a251f..99b999a 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -701,11 +701,11 @@ evp_test.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
 evp_test.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
 evp_test.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
 evp_test.o: ../include/openssl/pem.h ../include/openssl/pem2.h
-evp_test.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h
-evp_test.o: ../include/openssl/sha.h ../include/openssl/stack.h
-evp_test.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
-evp_test.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h
-evp_test.o: evp_test.c
+evp_test.o: ../include/openssl/pkcs12.h ../include/openssl/pkcs7.h
+evp_test.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+evp_test.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+evp_test.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
+evp_test.o: ../include/openssl/x509v3.h evp_test.c
 exptest.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/bn.h
 exptest.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
 exptest.o: ../include/openssl/err.h ../include/openssl/lhash.h
diff --git a/test/evp_test.c b/test/evp_test.c
index e0e4857..90441f3 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -60,6 +60,7 @@
 #include <openssl/pem.h>
 #include <openssl/err.h>
 #include <openssl/x509v3.h>
+#include <openssl/pkcs12.h>
 #include "internal/numbers.h"
 
 /* Remove spaces from beginning and end of a string */
@@ -1283,6 +1284,8 @@ static const struct evp_test_method pverify_test_method = {
 /* PBE tests */
 
 #define PBE_TYPE_SCRYPT 1
+#define PBE_TYPE_PBKDF2 2
+#define PBE_TYPE_PKCS12 3
 
 struct pbe_data {
 
@@ -1291,6 +1294,10 @@ struct pbe_data {
     /* scrypt parameters */
     uint64_t N, r, p, maxmem;
 
+    /* PKCS#12 parameters */
+    int id, iter;
+    const EVP_MD *md;
+
     /* password */
     unsigned char *pass;
     size_t pass_len;
@@ -1308,6 +1315,7 @@ static int scrypt_test_parse(struct evp_test *t,
                              const char *keyword, const char *value)
 {
     struct pbe_data *pdata = t->data;
+
     if (strcmp(keyword, "N") == 0)
         return test_uint64(value, &pdata->N);
     if (strcmp(keyword, "p") == 0)
@@ -1319,36 +1327,51 @@ static int scrypt_test_parse(struct evp_test *t,
     return 0;
 }
 
-static int scrypt_test_run(struct evp_test *t)
+static int pbkdf2_test_parse(struct evp_test *t,
+                             const char *keyword, const char *value)
 {
     struct pbe_data *pdata = t->data;
-    const char *err = "INTERNAL_ERROR";
-    unsigned char *key;
-    key = OPENSSL_malloc(pdata->key_len);
-    if (!key)
-        goto err;
-    err = "SCRYPT_ERROR";
-    if (EVP_PBE_scrypt((const char *)pdata->pass, pdata->pass_len,
-                       pdata->salt, pdata->salt_len,
-                       pdata->N, pdata->r, pdata->p, pdata->maxmem,
-                       key, pdata->key_len) == 0)
-        goto err;
-    err = "KEY_MISMATCH";
-    if (check_output(t, pdata->key, key, pdata->key_len))
-        goto err;
-    err = NULL;
-    err:
-    OPENSSL_free(key);
-    t->err = err;
-    return 1;
+
+    if (strcmp(keyword, "iter") == 0) {
+        pdata->iter = atoi(value);
+        if (pdata->iter <= 0)
+            return 0;
+        return 1;
+    }
+    if (strcmp(keyword, "MD") == 0) {
+        pdata->md = EVP_get_digestbyname(value);
+        if (pdata->md == NULL)
+            return 0;
+        return 1;
+    }
+    return 0;
+}
+
+static int pkcs12_test_parse(struct evp_test *t,
+                             const char *keyword, const char *value)
+{
+    struct pbe_data *pdata = t->data;
+
+    if (strcmp(keyword, "id") == 0) {
+        pdata->id = atoi(value);
+        if (pdata->id <= 0)
+            return 0;
+        return 1;
+    }
+    return pbkdf2_test_parse(t, keyword, value);
 }
 
 static int pbe_test_init(struct evp_test *t, const char *alg)
 {
     struct pbe_data *pdat;
     int pbe_type = 0;
+
     if (strcmp(alg, "scrypt") == 0)
         pbe_type = PBE_TYPE_SCRYPT;
+    else if (strcmp(alg, "pbkdf2") == 0)
+        pbe_type = PBE_TYPE_PBKDF2;
+    else if (strcmp(alg, "pkcs12") == 0)
+        pbe_type = PBE_TYPE_PKCS12;
     else
         fprintf(stderr, "Unknown pbe algorithm %s\n", alg);
     pdat = OPENSSL_malloc(sizeof(*pdat));
@@ -1359,6 +1382,9 @@ static int pbe_test_init(struct evp_test *t, const char *alg)
     pdat->r = 0;
     pdat->p = 0;
     pdat->maxmem = 0;
+    pdat->id = 0;
+    pdat->iter = 0;
+    pdat->md = NULL;
     t->data = pdat;
     return 1;
 }
@@ -1375,6 +1401,7 @@ static int pbe_test_parse(struct evp_test *t,
                              const char *keyword, const char *value)
 {
     struct pbe_data *pdata = t->data;
+
     if (strcmp(keyword, "Password") == 0)
         return test_bin(value, &pdata->pass, &pdata->pass_len);
     if (strcmp(keyword, "Salt") == 0)
@@ -1383,15 +1410,52 @@ static int pbe_test_parse(struct evp_test *t,
         return test_bin(value, &pdata->key, &pdata->key_len);
     if (pdata->pbe_type == PBE_TYPE_SCRYPT)
         return scrypt_test_parse(t, keyword, value);
+    else if (pdata->pbe_type == PBE_TYPE_PBKDF2)
+        return pbkdf2_test_parse(t, keyword, value);
+    else if (pdata->pbe_type == PBE_TYPE_PKCS12)
+        return pkcs12_test_parse(t, keyword, value);
     return 0;
 }
 
 static int pbe_test_run(struct evp_test *t)
 {
     struct pbe_data *pdata = t->data;
-    if (pdata->pbe_type == PBE_TYPE_SCRYPT)
-        return scrypt_test_run(t);
-    return 0;
+    const char *err = "INTERNAL_ERROR";
+    unsigned char *key;
+
+    key = OPENSSL_malloc(pdata->key_len);
+    if (!key)
+        goto err;
+    if (pdata->pbe_type == PBE_TYPE_PBKDF2) {
+        err = "PBKDF2_ERROR";
+        if (PKCS5_PBKDF2_HMAC((char *)pdata->pass, pdata->pass_len,
+                              pdata->salt, pdata->salt_len,
+                              pdata->iter, pdata->md,
+                              pdata->key_len, key) == 0)
+            goto err;
+    } else if (pdata->pbe_type == PBE_TYPE_SCRYPT) {
+        err = "SCRYPT_ERROR";
+        if (EVP_PBE_scrypt((const char *)pdata->pass, pdata->pass_len,
+                           pdata->salt, pdata->salt_len,
+                           pdata->N, pdata->r, pdata->p, pdata->maxmem,
+                           key, pdata->key_len) == 0)
+            goto err;
+    } else if (pdata->pbe_type == PBE_TYPE_PKCS12) {
+        err = "PKCS12_ERROR";
+        if (PKCS12_key_gen_uni(pdata->pass, pdata->pass_len,
+                               pdata->salt, pdata->salt_len,
+                               pdata->id, pdata->iter, pdata->key_len,
+                               key, pdata->md) == 0)
+            goto err;
+    }
+    err = "KEY_MISMATCH";
+    if (check_output(t, pdata->key, key, pdata->key_len))
+        goto err;
+    err = NULL;
+    err:
+    OPENSSL_free(key);
+    t->err = err;
+    return 1;
 }
 
 static const struct evp_test_method pbe_test_method = {
diff --git a/test/evptests.txt b/test/evptests.txt
index db63362..a4faba7 100644
--- a/test/evptests.txt
+++ b/test/evptests.txt
@@ -2353,3 +2353,159 @@ p = 1
 Key = 2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4
 #maxmem = 10000000000
 Result = SCRYPT_ERROR
+
+# PKCS#12 tests
+
+PBE = pkcs12
+id = 1
+iter = 1
+MD = SHA1
+Password = 0073006D006500670000
+Salt = 0A58CF64530D823F
+Key = 8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3
+
+PBE = pkcs12
+id = 2
+iter = 1
+MD = SHA1
+Password = 0073006D006500670000
+Salt = 0A58CF64530D823F
+Key = 79993DFE048D3B76
+
+PBE = pkcs12
+id = 3
+iter 1
+MD = SHA1
+Password = 0073006D006500670000
+Salt = 3D83C0E4546AC140
+Key = 8D967D88F6CAA9D714800AB3D48051D63F73A312
+
+PBE = pkcs12
+id = 1
+iter = 1000
+MD = SHA1
+Password = 007100750065006500670000
+Salt = 1682C0FC5B3F7EC5
+Key = 483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F
+
+PBE = pkcs12
+id = 2
+iter = 1000
+MD = SHA1
+Password = 007100750065006500670000
+Salt = 1682C0FC5B3F7EC5
+Key = 9D461D1B00355C50
+
+PBE = pkcs12
+id = 3
+iter = 1000
+MD = SHA1
+Password = 007100750065006500670000
+Salt = 263216FCC2FAB31C
+Key = 5EC4C7A80DF652294C3925B6489A7AB857C83476
+
+# PBKDF2 tests from p5_crpt2_test.c
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 1
+MD = sha1
+Key = 0c60c80f961f0e71f3a9b524af6012062fe037a6
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 1
+MD = sha256
+Key = 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 1
+MD = sha512
+Key = 867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 2
+MD = sha1
+Key = ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 2
+MD = sha256
+Key = ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 2
+MD = sha512
+Key = e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 4096
+MD = sha1
+Key = 4b007901b765489abead49d926f721d065a429c1
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 4096
+MD = sha256
+Key = c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
+
+PBE = pbkdf2
+Password = "password"
+Salt = "salt"
+iter = 4096
+MD = sha512
+Key = d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5
+
+PBE = pbkdf2
+Password = "passwordPASSWORDpassword"
+Salt = "saltSALTsaltSALTsaltSALTsaltSALTsalt"
+iter = 4096
+MD = sha1
+Key = 3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038
+
+PBE = pbkdf2
+Password = "passwordPASSWORDpassword"
+Salt = "saltSALTsaltSALTsaltSALTsaltSALTsalt"
+iter = 4096
+MD = sha256
+Key = 348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9
+
+PBE = pbkdf2
+Password = "passwordPASSWORDpassword"
+Salt = "saltSALTsaltSALTsaltSALTsaltSALTsalt"
+iter = 4096
+MD = sha512
+Key = 8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8
+
+PBE = pbkdf2
+Password = 7061737300776f7264
+Salt = 7361006c74
+iter = 4096
+MD = sha1
+Key = 56fa6aa75548099dcc37d7f03425e0c3
+
+PBE = pbkdf2
+Password = 7061737300776f7264
+Salt = 7361006c74
+iter = 4096
+MD = sha256
+Key = 89b69d0516f829893c696226650a8687
+
+PBE = pbkdf2
+Password = 7061737300776f7264
+Salt = 7361006c74
+iter = 4096
+MD = sha512
+Key = 9d9e9c4cd21fe4be24d5b8244c759665
diff --git a/util/libeay.num b/util/libeay.num
index 9d0213c..27460f0 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -4570,3 +4570,4 @@ PKCS5_v2_scrypt_keyivgen                4928	EXIST::FUNCTION:
 ASN1_INTEGER_get_uint64                 4929	EXIST::FUNCTION:
 ASN1_INTEGER_set_uint64                 4930	EXIST::FUNCTION:
 PKCS5_pbe2_set_scrypt                   4931	EXIST::FUNCTION:
+PKCS8_set0_pbe                          4932	EXIST::FUNCTION:


More information about the openssl-commits mailing list