handle scrypt PBKDF in PKCS#12 files info
[openssl.git] / apps / pkcs12.c
index 82d2bb972e3a7a546e3abf21e8015ae59d09d961..e8c1c87cb3550f569c62437700f512c0e7bbff70 100644 (file)
@@ -27,6 +27,8 @@ NON_EMPTY_TRANSLATION_UNIT
 # define CLCERTS         0x8
 # define CACERTS         0x10
 
+#define PASSWD_BUF_SIZE 2048
+
 static int get_cert_chain(X509 *cert, X509_STORE *store,
                           STACK_OF(X509) **chain);
 int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
@@ -51,9 +53,10 @@ typedef enum OPTION_choice {
     OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
     OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
     OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
-    OPT_RAND, OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
+    OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
     OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
-    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE
+    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs12_options[] = {
@@ -89,8 +92,7 @@ const OPTIONS pkcs12_options[] = {
     {"macalg", OPT_MACALG, 's',
      "Digest algorithm used in MAC (default SHA1)"},
     {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"inkey", OPT_INKEY, 's', "Private key if not infile"},
     {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
     {"name", OPT_NAME, 's', "Use name as friendly name"},
@@ -119,7 +121,7 @@ int pkcs12_main(int argc, char **argv)
 {
     char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
     char *name = NULL, *csp_name = NULL;
-    char pass[2048] = "", macpass[2048] = "";
+    char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
     int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
     int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
 # ifndef OPENSSL_NO_RC2
@@ -131,7 +133,7 @@ int pkcs12_main(int argc, char **argv)
     int ret = 1, macver = 1, add_lmk = 0, private = 0;
     int noprompt = 0;
     char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
-    char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL;
+    char *passin = NULL, *passout = NULL, *macalg = NULL;
     char *cpass = NULL, *mpass = NULL, *badpass = NULL;
     const char *CApath = NULL, *CAfile = NULL, *prog;
     int noCApath = 0, noCAfile = 0;
@@ -223,8 +225,9 @@ int pkcs12_main(int argc, char **argv)
             if (!set_pbe(&key_pbe, opt_arg()))
                 goto opthelp;
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_INKEY:
             keyname = opt_arg();
@@ -312,13 +315,6 @@ int pkcs12_main(int argc, char **argv)
         mpass = macpass;
     }
 
-    if (export_cert || inrand != NULL) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     if (twopass) {
         /* To avoid bit rot */
         if (1) {
@@ -455,7 +451,7 @@ int pkcs12_main(int argc, char **argv)
         }
 
         if (!twopass)
-            strcpy(macpass, pass);
+            OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
 
         p12 = PKCS12_create(cpass, name, key, ucert, certs,
                             key_pbe, cert_pbe, iter, -1, keytype);
@@ -527,12 +523,20 @@ int pkcs12_main(int argc, char **argv)
         const ASN1_INTEGER *tmaciter;
         const X509_ALGOR *macalgid;
         const ASN1_OBJECT *macobj;
-        PKCS12_get0_mac(NULL, &macalgid, NULL, &tmaciter, p12);
+        const ASN1_OCTET_STRING *tmac;
+        const ASN1_OCTET_STRING *tsalt;
+
+        PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12);
+        /* current hash algorithms do not use parameters so extract just name,
+           in future alg_print() may be needed */
         X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
-        BIO_puts(bio_err, "MAC:");
+        BIO_puts(bio_err, "MAC: ");
         i2a_ASN1_OBJECT(bio_err, macobj);
-        BIO_printf(bio_err, " Iteration %ld\n",
-                   tmaciter  != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
+        BIO_printf(bio_err, ", Iteration %ld\n",
+                   tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
+        BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
+                   tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
+                   tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
     }
     if (macver) {
         /* If we enter empty password try no password first */
@@ -574,8 +578,6 @@ int pkcs12_main(int argc, char **argv)
     ret = 0;
  end:
     PKCS12_free(p12);
-    if (export_cert || inrand)
-        app_RAND_write_file(NULL);
     release_engine(e);
     BIO_free(in);
     BIO_free_all(out);
@@ -583,7 +585,7 @@ int pkcs12_main(int argc, char **argv)
     OPENSSL_free(badpass);
     OPENSSL_free(passin);
     OPENSSL_free(passout);
-    return (ret);
+    return ret;
 }
 
 int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
@@ -788,7 +790,7 @@ static int alg_print(const X509_ALGOR *alg)
         if (aparamtype == V_ASN1_SEQUENCE)
             pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
         if (pbe2 == NULL) {
-            BIO_puts(bio_err, "<unsupported parameters>");
+            BIO_puts(bio_err, "<unsupported parameters>");
             goto done;
         }
         X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
@@ -804,7 +806,7 @@ static int alg_print(const X509_ALGOR *alg)
             if (aparamtype == V_ASN1_SEQUENCE)
                 kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
             if (kdf == NULL) {
-                BIO_puts(bio_err, "<unsupported parameters>");
+                BIO_puts(bio_err, "<unsupported parameters>");
                 goto done;
             }
 
@@ -817,13 +819,29 @@ static int alg_print(const X509_ALGOR *alg)
             BIO_printf(bio_err, ", Iteration %ld, PRF %s",
                        ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
             PBKDF2PARAM_free(kdf);
+        } else if (pbenid == NID_id_scrypt) {
+            SCRYPT_PARAMS *kdf = NULL;
+
+            if (aparamtype == V_ASN1_SEQUENCE)
+                kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
+            if (kdf == NULL) {
+                BIO_puts(bio_err, ", <unsupported parameters>");
+                goto done;
+            }
+            BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
+                       "Block size(r): %ld, Paralelizm(p): %ld",
+                       ASN1_STRING_length(kdf->salt),
+                       ASN1_INTEGER_get(kdf->costParameter),
+                       ASN1_INTEGER_get(kdf->blockSize),
+                       ASN1_INTEGER_get(kdf->parallelizationParameter));
+            SCRYPT_PARAMS_free(kdf);
         }
         PBE2PARAM_free(pbe2);
     } else {
         if (aparamtype == V_ASN1_SEQUENCE)
             pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
         if (pbe == NULL) {
-            BIO_puts(bio_err, "<unsupported parameters>");
+            BIO_puts(bio_err, "<unsupported parameters>");
             goto done;
         }
         BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));