Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@chromium.org>2014-06-20 23:00:00 +0400
committerAdam Langley <agl@chromium.org>2014-06-21 00:17:32 +0400
commit95c29f3cd1f6c08c6c0927868683392eea727ccb (patch)
tree012767320ced9abca61472a4daa4c4a56b7ebe2b /crypto/pkcs8
Inital import.
Initial fork from f2d678e6e89b6508147086610e985d4e8416e867 (1.0.2 beta). (This change contains substantial changes from the original and effectively starts a new history.)
Diffstat (limited to 'crypto/pkcs8')
-rw-r--r--crypto/pkcs8/CMakeLists.txt13
-rw-r--r--crypto/pkcs8/internal.h74
-rw-r--r--crypto/pkcs8/p5_pbe.c148
-rw-r--r--crypto/pkcs8/p5_pbev2.c298
-rw-r--r--crypto/pkcs8/p8_pkey.c84
-rw-r--r--crypto/pkcs8/pkcs8.c580
-rw-r--r--crypto/pkcs8/pkcs8.h112
-rw-r--r--crypto/pkcs8/pkcs8_error.c52
8 files changed, 1361 insertions, 0 deletions
diff --git a/crypto/pkcs8/CMakeLists.txt b/crypto/pkcs8/CMakeLists.txt
new file mode 100644
index 00000000..b89af85f
--- /dev/null
+++ b/crypto/pkcs8/CMakeLists.txt
@@ -0,0 +1,13 @@
+include_directories(. .. ../../include)
+
+add_library(
+ pkcs8
+
+ OBJECT
+
+ pkcs8.c
+ p8_pkey.c
+ p5_pbe.c
+ p5_pbev2.c
+ pkcs8_error.c
+)
diff --git a/crypto/pkcs8/internal.h b/crypto/pkcs8/internal.h
new file mode 100644
index 00000000..44ca4f7b
--- /dev/null
+++ b/crypto/pkcs8/internal.h
@@ -0,0 +1,74 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#ifndef OPENSSL_HEADER_PKCS8_INTERNAL_H
+#define OPENSSL_HEADER_PKCS8_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define PKCS5_DEFAULT_ITERATIONS 2048
+#define PKCS5_SALT_LEN 8
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_PKCS8_INTERNAL_H */
diff --git a/crypto/pkcs8/p5_pbe.c b/crypto/pkcs8/p5_pbe.c
new file mode 100644
index 00000000..9cdff4c4
--- /dev/null
+++ b/crypto/pkcs8/p5_pbe.c
@@ -0,0 +1,148 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+/* PKCS#5 password based encryption structure */
+
+ASN1_SEQUENCE(PBEPARAM) = {
+ ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(PBEPARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
+
+
+/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
+
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen)
+ {
+ PBEPARAM *pbe=NULL;
+ ASN1_STRING *pbe_str=NULL;
+ unsigned char *sstr;
+
+ pbe = PBEPARAM_new();
+ if (!pbe)
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if(iter <= 0)
+ iter = PKCS5_DEFAULT_ITERATIONS;
+ if (!ASN1_INTEGER_set(pbe->iter, iter))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!saltlen)
+ saltlen = PKCS5_SALT_LEN;
+ if (!ASN1_STRING_set(pbe->salt, NULL, saltlen))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ sstr = ASN1_STRING_data(pbe->salt);
+ if (salt)
+ memcpy(sstr, salt, saltlen);
+ else if (RAND_pseudo_bytes(sstr, saltlen) < 0)
+ goto err;
+
+ if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ PBEPARAM_free(pbe);
+ pbe = NULL;
+
+ if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
+ return 1;
+
+err:
+ if (pbe != NULL)
+ PBEPARAM_free(pbe);
+ if (pbe_str != NULL)
+ ASN1_STRING_free(pbe_str);
+ return 0;
+ }
+
+/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen)
+ {
+ X509_ALGOR *ret;
+ ret = X509_ALGOR_new();
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+ return ret;
+
+ X509_ALGOR_free(ret);
+ return NULL;
+ }
diff --git a/crypto/pkcs8/p5_pbev2.c b/crypto/pkcs8/p5_pbev2.c
new file mode 100644
index 00000000..66746df4
--- /dev/null
+++ b/crypto/pkcs8/p5_pbev2.c
@@ -0,0 +1,298 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999-2004.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+
+#include <openssl/asn1t.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+/* PKCS#5 v2.0 password based encryption structures */
+
+ASN1_SEQUENCE(PBE2PARAM) = {
+ ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
+ ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
+} ASN1_SEQUENCE_END(PBE2PARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
+
+ASN1_SEQUENCE(PBKDF2PARAM) = {
+ ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
+ ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
+ ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
+ ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
+} ASN1_SEQUENCE_END(PBKDF2PARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM);
+
+static int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
+ {
+ ASN1_STRING *os;
+
+ if ((os=M_ASN1_OCTET_STRING_new()) == NULL) return(0);
+ if (!M_ASN1_OCTET_STRING_set(os,data,len)) return(0);
+ ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,os);
+ return(1);
+ }
+
+static int param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+ {
+ unsigned iv_len;
+
+ iv_len = EVP_CIPHER_CTX_iv_length(c);
+ return ASN1_TYPE_set_octetstring(type, c->oiv, iv_len);
+ }
+
+/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
+ * yes I know this is horrible!
+ *
+ * Extended version to allow application supplied PRF NID and IV. */
+
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid)
+{
+ X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL;
+ int alg_nid, keylen;
+ EVP_CIPHER_CTX ctx;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ PBE2PARAM *pbe2 = NULL;
+ const ASN1_OBJECT *obj;
+
+ alg_nid = EVP_CIPHER_nid(cipher);
+ if(alg_nid == NID_undef) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+ goto err;
+ }
+ obj = OBJ_nid2obj(alg_nid);
+
+ if(!(pbe2 = PBE2PARAM_new())) goto merr;
+
+ /* Setup the AlgorithmIdentifier for the encryption scheme */
+ scheme = pbe2->encryption;
+
+ scheme->algorithm = (ASN1_OBJECT*) obj;
+ if(!(scheme->parameter = ASN1_TYPE_new())) goto merr;
+
+ /* Create random IV */
+ if (EVP_CIPHER_iv_length(cipher))
+ {
+ if (aiv)
+ memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
+ else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0)
+ goto err;
+ }
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ /* Dummy cipherinit to just setup the IV, and PRF */
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0))
+ goto err;
+ if(param_to_asn1(&ctx, scheme->parameter) < 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ goto err;
+ }
+ /* If prf NID unspecified see if cipher has a preference.
+ * An error is OK here: just means use default PRF.
+ */
+ if ((prf_nid == -1) &&
+ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0)
+ {
+ ERR_clear_error();
+ prf_nid = NID_hmacWithSHA1;
+ }
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ /* If its RC2 then we'd better setup the key length */
+
+ if(alg_nid == NID_rc2_cbc)
+ keylen = EVP_CIPHER_key_length(cipher);
+ else
+ keylen = -1;
+
+ /* Setup keyfunc */
+
+ X509_ALGOR_free(pbe2->keyfunc);
+
+ pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
+
+ if (!pbe2->keyfunc)
+ goto merr;
+
+ /* Now set up top level AlgorithmIdentifier */
+
+ if(!(ret = X509_ALGOR_new())) goto merr;
+ if(!(ret->parameter = ASN1_TYPE_new())) goto merr;
+
+ ret->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_pbes2);
+
+ /* Encode PBE2PARAM into parameter */
+
+ if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM),
+ &ret->parameter->value.sequence)) goto merr;
+ ret->parameter->type = V_ASN1_SEQUENCE;
+
+ PBE2PARAM_free(pbe2);
+ pbe2 = NULL;
+
+ return ret;
+
+ merr:
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, ERR_R_MALLOC_FAILURE);
+
+ err:
+ PBE2PARAM_free(pbe2);
+ /* Note 'scheme' is freed as part of pbe2 */
+ X509_ALGOR_free(kalg);
+ X509_ALGOR_free(ret);
+
+ return NULL;
+
+}
+
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen)
+ {
+ return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
+ }
+
+X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen)
+ {
+ X509_ALGOR *keyfunc = NULL;
+ PBKDF2PARAM *kdf = NULL;
+ ASN1_OCTET_STRING *osalt = NULL;
+
+ if(!(kdf = PBKDF2PARAM_new()))
+ goto merr;
+ if(!(osalt = M_ASN1_OCTET_STRING_new()))
+ goto merr;
+
+ kdf->salt->value.octet_string = osalt;
+ kdf->salt->type = V_ASN1_OCTET_STRING;
+
+ if (!saltlen)
+ saltlen = PKCS5_SALT_LEN;
+ if (!(osalt->data = OPENSSL_malloc (saltlen)))
+ goto merr;
+
+ osalt->length = saltlen;
+
+ if (salt)
+ memcpy (osalt->data, salt, saltlen);
+ else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0)
+ goto merr;
+
+ if(iter <= 0)
+ iter = PKCS5_DEFAULT_ITERATIONS;
+
+ if(!ASN1_INTEGER_set(kdf->iter, iter))
+ goto merr;
+
+ /* If have a key len set it up */
+
+ if(keylen > 0)
+ {
+ if(!(kdf->keylength = M_ASN1_INTEGER_new()))
+ goto merr;
+ if(!ASN1_INTEGER_set (kdf->keylength, keylen))
+ goto merr;
+ }
+
+ /* prf can stay NULL if we are using hmacWithSHA1 */
+ if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1)
+ {
+ kdf->prf = X509_ALGOR_new();
+ if (!kdf->prf)
+ goto merr;
+ X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid),
+ V_ASN1_NULL, NULL);
+ }
+
+ /* Finally setup the keyfunc structure */
+
+ keyfunc = X509_ALGOR_new();
+ if (!keyfunc)
+ goto merr;
+
+ keyfunc->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_pbkdf2);
+
+ /* Encode PBKDF2PARAM into parameter of pbe2 */
+
+ if(!(keyfunc->parameter = ASN1_TYPE_new()))
+ goto merr;
+
+ if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM),
+ &keyfunc->parameter->value.sequence))
+ goto merr;
+ keyfunc->parameter->type = V_ASN1_SEQUENCE;
+
+ PBKDF2PARAM_free(kdf);
+ return keyfunc;
+
+ merr:
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbkdf2_set, ERR_R_MALLOC_FAILURE);
+ PBKDF2PARAM_free(kdf);
+ X509_ALGOR_free(keyfunc);
+ return NULL;
+ }
+
diff --git a/crypto/pkcs8/p8_pkey.c b/crypto/pkcs8/p8_pkey.c
new file mode 100644
index 00000000..9095ffde
--- /dev/null
+++ b/crypto/pkcs8/p8_pkey.c
@@ -0,0 +1,84 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+/* Minor tweak to operation: zero private key data */
+static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ /* Since the structure must still be valid use ASN1_OP_FREE_PRE */
+ if(operation == ASN1_OP_FREE_PRE) {
+ PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
+ if (key->pkey->value.octet_string)
+ OPENSSL_cleanse(key->pkey->value.octet_string->data,
+ key->pkey->value.octet_string->length);
+ }
+ return 1;
+}
+
+ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
+ ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
new file mode 100644
index 00000000..310af83f
--- /dev/null
+++ b/crypto/pkcs8/pkcs8.c
@@ -0,0 +1,580 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/pkcs8.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bn.h>
+#include <openssl/cipher.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.h"
+
+
+#define PKCS12_KEY_ID 1
+#define PKCS12_IV_ID 2
+
+static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
+ uint8_t **out, size_t *out_len) {
+ uint8_t *unitmp;
+ size_t ulen, i;
+
+ ulen = ascii_len * 2 + 2;
+ if (ulen < ascii_len) {
+ return 0;
+ }
+ unitmp = OPENSSL_malloc(ulen);
+ if (unitmp == NULL) {
+ return 0;
+ }
+ for (i = 0; i < ulen - 2; i += 2) {
+ unitmp[i] = 0;
+ unitmp[i + 1] = ascii[i >> 1];
+ }
+
+ /* Make result double null terminated */
+ unitmp[ulen - 2] = 0;
+ unitmp[ulen - 1] = 0;
+ *out_len = ulen;
+ *out = unitmp;
+ return 1;
+}
+
+static int pkcs12_key_gen_uni(uint8_t *pass, size_t pass_len, uint8_t *salt,
+ size_t salt_len, int id, int iterations,
+ size_t out_len, uint8_t *out,
+ const EVP_MD *md_type) {
+ uint8_t *B, *D, *I, *p, *Ai;
+ int Slen, Plen, Ilen, Ijlen;
+ int i, j, v;
+ size_t u;
+ int ret = 0;
+ BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */
+ EVP_MD_CTX ctx;
+
+ EVP_MD_CTX_init(&ctx);
+ v = EVP_MD_block_size(md_type);
+ u = EVP_MD_size(md_type);
+ D = OPENSSL_malloc(v);
+ Ai = OPENSSL_malloc(u);
+ B = OPENSSL_malloc(v + 1);
+ Slen = v * ((salt_len + v - 1) / v);
+ if (pass_len)
+ Plen = v * ((pass_len + v - 1) / v);
+ else
+ Plen = 0;
+ Ilen = Slen + Plen;
+ I = OPENSSL_malloc(Ilen);
+ Ij = BN_new();
+ Bpl1 = BN_new();
+ if (!D || !Ai || !B || !I || !Ij || !Bpl1)
+ goto err;
+ for (i = 0; i < v; i++)
+ D[i] = id;
+ p = I;
+ for (i = 0; i < Slen; i++)
+ *p++ = salt[i % salt_len];
+ for (i = 0; i < Plen; i++)
+ *p++ = pass[i % pass_len];
+ for (;;) {
+ if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
+ !EVP_DigestUpdate(&ctx, D, v) ||
+ !EVP_DigestUpdate(&ctx, I, Ilen) ||
+ !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ goto err;
+ }
+ for (j = 1; j < iterations; j++) {
+ if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
+ !EVP_DigestUpdate(&ctx, Ai, u) ||
+ !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ goto err;
+ }
+ }
+ memcpy(out, Ai, out_len < u ? out_len : u);
+ if (u >= out_len) {
+ ret = 1;
+ goto end;
+ }
+ out_len -= u;
+ out += u;
+ for (j = 0; j < v; j++)
+ B[j] = Ai[j % u];
+ /* Work out B + 1 first then can use B as tmp space */
+ if (!BN_bin2bn(B, v, Bpl1))
+ goto err;
+ if (!BN_add_word(Bpl1, 1))
+ goto err;
+ for (j = 0; j < Ilen; j += v) {
+ if (!BN_bin2bn(I + j, v, Ij))
+ goto err;
+ if (!BN_add(Ij, Ij, Bpl1))
+ goto err;
+ if (!BN_bn2bin(Ij, B))
+ goto err;
+ Ijlen = BN_num_bytes(Ij);
+ /* If more than 2^(v*8) - 1 cut off MSB */
+ if (Ijlen > v) {
+ if (!BN_bn2bin(Ij, B))
+ goto err;
+ memcpy(I + j, B + 1, v);
+ /* If less than v bytes pad with zeroes */
+ } else if (Ijlen < v) {
+ memset(I + j, 0, v - Ijlen);
+ if (!BN_bn2bin(Ij, I + j + v - Ijlen))
+ goto err;
+ } else if (!BN_bn2bin(Ij, I + j)) {
+ goto err;
+ }
+ }
+ }
+
+err:
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_uni, ERR_R_MALLOC_FAILURE);
+
+end:
+ OPENSSL_free(Ai);
+ OPENSSL_free(B);
+ OPENSSL_free(D);
+ OPENSSL_free(I);
+ BN_free(Ij);
+ BN_free(Bpl1);
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+static int pkcs12_key_gen_asc(const char *pass, size_t pass_len, uint8_t *salt,
+ size_t salt_len, int id, int iterations,
+ int out_len, uint8_t *out,
+ const EVP_MD *md_type) {
+ int ret;
+ uint8_t *ucs2_pass = NULL;
+ size_t ucs2_pass_len = 0;
+
+ if (pass && !ascii_to_ucs2(pass, pass_len, &ucs2_pass, &ucs2_pass_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR);
+ return 0;
+ }
+ ret = pkcs12_key_gen_uni(ucs2_pass, ucs2_pass_len, salt, salt_len, id,
+ iterations, out_len, out, md_type);
+
+ if (ucs2_pass) {
+ OPENSSL_cleanse(ucs2_pass, ucs2_pass_len);
+ OPENSSL_free(ucs2_pass);
+ }
+
+ return ret;
+}
+
+static int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+ size_t pass_len, ASN1_TYPE *param,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ int is_encrypt) {
+ PBEPARAM *pbe;
+ int salt_len, iterations, ret;
+ uint8_t *salt;
+ const uint8_t *pbuf;
+ uint8_t key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+
+ /* Extract useful info from parameter */
+ if (param == NULL || param->type != V_ASN1_SEQUENCE ||
+ param->value.sequence == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR);
+ return 0;
+ }
+
+ pbuf = param->value.sequence->data;
+ pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length);
+ if (pbe == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR);
+ return 0;
+ }
+
+ if (!pbe->iter) {
+ iterations = 1;
+ } else {
+ iterations = ASN1_INTEGER_get(pbe->iter);
+ }
+ salt = pbe->salt->data;
+ salt_len = pbe->salt->length;
+ if (!pkcs12_key_gen_asc(pass, pass_len, salt, salt_len, PKCS12_KEY_ID,
+ iterations, EVP_CIPHER_key_length(cipher), key, md)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR);
+ PBEPARAM_free(pbe);
+ return 0;
+ }
+ if (!pkcs12_key_gen_asc(pass, pass_len, salt, salt_len, PKCS12_IV_ID,
+ iterations, EVP_CIPHER_iv_length(cipher), iv, md)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR);
+ PBEPARAM_free(pbe);
+ return 0;
+ }
+ PBEPARAM_free(pbe);
+ ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt);
+ OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
+ OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
+ return ret;
+}
+
+typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const char *pass,
+ size_t pass_len, ASN1_TYPE *param,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ int is_encrypt);
+
+struct pbe_suite {
+ int pbe_nid;
+ int cipher_nid;
+ int md_nid;
+ keygen_func keygen;
+};
+
+static const struct pbe_suite kBuiltinPBE[] = {
+ {
+ NID_pbe_WithSHA1And128BitRC4, NID_rc4, NID_sha1, pkcs12_pbe_keyivgen,
+ },
+ {
+ NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NID_des_ede3_cbc, NID_sha1,
+ pkcs12_pbe_keyivgen,
+ },
+};
+
+static int pbe_cipher_init(ASN1_OBJECT *pbe_obj, const char *pass,
+ size_t pass_len, ASN1_TYPE *param,
+ EVP_CIPHER_CTX *ctx, int is_encrypt) {
+ const EVP_CIPHER *cipher;
+ const EVP_MD *md;
+ unsigned i;
+
+ const struct pbe_suite *suite = NULL;
+ const int pbe_nid = OBJ_obj2nid(pbe_obj);
+
+ for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) {
+ suite = &kBuiltinPBE[i];
+ if (suite->pbe_nid == pbe_nid) {
+ break;
+ }
+ }
+
+ if (suite == NULL) {
+ char obj_str[80];
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_ALGORITHM);
+ if (!pbe_obj) {
+ strncpy(obj_str, "NULL", sizeof(obj_str));
+ } else {
+ i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj);
+ }
+ ERR_add_error_data(2, "TYPE=", obj_str);
+ return 0;
+ }
+
+ if (suite->cipher_nid == -1) {
+ cipher = NULL;
+ } else {
+ cipher = EVP_get_cipherbynid(suite->cipher_nid);
+ if (!cipher) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER);
+ return 0;
+ }
+ }
+
+ if (suite->md_nid == -1) {
+ md = NULL;
+ } else {
+ md = EVP_get_digestbynid(suite->md_nid);
+ if (!md) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST);
+ return 0;
+ }
+ }
+
+ if (!suite->keygen(ctx, pass, pass_len, param, cipher, md, is_encrypt)) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_KEYGEN_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pbe_crypt(const X509_ALGOR *algor, const char *pass, size_t pass_len,
+ uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len,
+ int is_encrypt) {
+ uint8_t *buf;
+ int n, ret = 0;
+ EVP_CIPHER_CTX ctx;
+ unsigned block_size;
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (!pbe_cipher_init(algor->algorithm, pass, pass_len, algor->parameter, &ctx,
+ is_encrypt)) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM);
+ return 0;
+ }
+ block_size = EVP_CIPHER_CTX_block_size(&ctx);
+
+ if (in_len + block_size < in_len) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_TOO_LONG);
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(in_len + block_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) {
+ OPENSSL_free(buf);
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB);
+ goto err;
+ }
+ *out_len = n;
+
+ if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) {
+ OPENSSL_free(buf);
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB);
+ goto err;
+ }
+ *out_len += n;
+ *out = buf;
+ ret = 1;
+
+err:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return ret;
+}
+
+static void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, size_t pass_len,
+ ASN1_OCTET_STRING *oct) {
+ uint8_t *out;
+ const uint8_t *p;
+ void *ret;
+ size_t out_len;
+
+ if (!pbe_crypt(algor, pass, pass_len, oct->data, oct->length, &out, &out_len,
+ 0 /* decrypt */)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_CRYPT_ERROR);
+ return NULL;
+ }
+ p = out;
+ ret = ASN1_item_d2i(NULL, &p, out_len, it);
+ OPENSSL_cleanse(out, out_len);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_DECODE_ERROR);
+ }
+ OPENSSL_free(out);
+ return ret;
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
+ int pass_len) {
+ if (pass && pass_len == -1) {
+ pass_len = strlen(pass);
+ }
+ return pkcs12_item_decrypt_d2i(pkcs8->algor,
+ ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass,
+ pass_len, pkcs8->digest);
+}
+
+static ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const char *pass,
+ size_t passlen, void *obj) {
+ ASN1_OCTET_STRING *oct;
+ uint8_t *in = NULL;
+ int in_len;
+ size_t crypt_len;
+
+ oct = M_ASN1_OCTET_STRING_new();
+ if (oct == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in_len = ASN1_item_i2d(obj, &in, it);
+ if (!in) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCODE_ERROR);
+ return NULL;
+ }
+ if (!pbe_crypt(algor, pass, passlen, in, in_len, &oct->data, &crypt_len,
+ 1 /* encrypt */)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCRYPT_ERROR);
+ OPENSSL_free(in);
+ return NULL;
+ }
+ oct->length = crypt_len;
+ OPENSSL_cleanse(in, in_len);
+ OPENSSL_free(in);
+ return oct;
+}
+
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
+ int pass_len, uint8_t *salt, size_t salt_len,
+ int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
+ X509_SIG *pkcs8 = NULL;
+ X509_ALGOR *pbe;
+
+ if (pass && pass_len == -1) {
+ pass_len = strlen(pass);
+ }
+
+ pkcs8 = X509_SIG_new();
+ if (pkcs8 == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (pbe_nid == -1) {
+ pbe = PKCS5_pbe2_set(cipher, iterations, salt, salt_len);
+ } else {
+ pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len);
+ }
+
+ if (!pbe) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ X509_ALGOR_free(pkcs8->algor);
+ pkcs8->algor = pbe;
+ M_ASN1_OCTET_STRING_free(pkcs8->digest);
+ pkcs8->digest = pkcs12_item_i2d_encrypt(
+ pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass, pass_len, p8inf);
+ if (!pkcs8->digest) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt, PKCS8_R_ENCRYPT_ERROR);
+ goto err;
+ }
+
+ return pkcs8;
+
+err:
+ X509_SIG_free(pkcs8);
+ return NULL;
+}
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
+ EVP_PKEY *pkey = NULL;
+ ASN1_OBJECT *algoid;
+ char obj_tmp[80];
+
+ if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
+ return NULL;
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY,
+ PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
+ ERR_add_error_data(2, "TYPE=", obj_tmp);
+ goto error;
+ }
+
+ if (pkey->ameth->priv_decode) {
+ if (!pkey->ameth->priv_decode(pkey, p8)) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_PRIVATE_KEY_DECODE_ERROR);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+
+ return pkey;
+
+error:
+ EVP_PKEY_free(pkey);
+ return NULL;
+}
+
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
+ PKCS8_PRIV_KEY_INFO *p8;
+
+ p8 = PKCS8_PRIV_KEY_INFO_new();
+ if (p8 == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ p8->broken = PKCS8_OK;
+
+ if (pkey->ameth) {
+ if (pkey->ameth->priv_encode) {
+ if (!pkey->ameth->priv_encode(p8, pkey)) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8,
+ PKCS8_R_PRIVATE_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8,
+ PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ goto error;
+ }
+ return p8;
+
+error:
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return NULL;
+}
diff --git a/crypto/pkcs8/pkcs8.h b/crypto/pkcs8/pkcs8.h
new file mode 100644
index 00000000..9c4f60c4
--- /dev/null
+++ b/crypto/pkcs8/pkcs8.h
@@ -0,0 +1,112 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+
+#ifndef OPENSSL_HEADER_PKCS8_H
+#define OPENSSL_HEADER_PKCS8_H
+
+#include <openssl/base.h>
+
+#include <openssl/x509.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
+ int pass_len, uint8_t *salt, size_t salt_len, int iterations,
+ PKCS8_PRIV_KEY_INFO *p8inf);
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
+ int pass_len);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define PKCS8_F_PKCS8_encrypt 100
+#define PKCS8_F_EVP_PKEY2PKCS8 101
+#define PKCS8_F_EVP_PKCS82PKEY 102
+#define PKCS8_F_PKCS5_pbe_set0_algor 103
+#define PKCS8_F_pbe_crypt 104
+#define PKCS8_F_pkcs12_item_decrypt_d2i 105
+#define PKCS8_F_PKCS5_pbe_set 106
+#define PKCS8_F_pkcs12_key_gen_uni 107
+#define PKCS8_F_pkcs12_key_gen_asc 108
+#define PKCS8_F_pkcs12_pbe_keyivgen 109
+#define PKCS8_F_pbe_cipher_init 110
+#define PKCS8_F_pkcs12_item_i2d_encrypt 111
+#define PKCS8_F_PKCS5_pbe2_set_iv 112
+#define PKCS8_F_PKCS5_pbkdf2_set 113
+#define PKCS8_R_ERROR_SETTING_CIPHER_PARAMS 100
+#define PKCS8_R_PRIVATE_KEY_ENCODE_ERROR 101
+#define PKCS8_R_UNKNOWN_ALGORITHM 102
+#define PKCS8_R_UNKNOWN_CIPHER 103
+#define PKCS8_R_UNKNOWN_DIGEST 104
+#define PKCS8_R_ENCODE_ERROR 105
+#define PKCS8_R_DECODE_ERROR 106
+#define PKCS8_R_ENCRYPT_ERROR 107
+#define PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 108
+#define PKCS8_R_PRIVATE_KEY_DECODE_ERROR 109
+#define PKCS8_R_UNKNOWN_CIPHER_ALGORITHM 110
+#define PKCS8_R_KEYGEN_FAILURE 111
+#define PKCS8_R_TOO_LONG 112
+#define PKCS8_R_CRYPT_ERROR 113
+#define PKCS8_R_METHOD_NOT_SUPPORTED 114
+#define PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 115
+#define PKCS8_R_KEY_GEN_ERROR 116
+
+#endif /* OPENSSL_HEADER_PKCS8_H */
diff --git a/crypto/pkcs8/pkcs8_error.c b/crypto/pkcs8/pkcs8_error.c
new file mode 100644
index 00000000..02129f03
--- /dev/null
+++ b/crypto/pkcs8/pkcs8_error.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/err.h>
+
+#include "pkcs8.h"
+
+const ERR_STRING_DATA PKCS8_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe2_set_iv, 0), "PKCS5_pbe2_set_iv"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set, 0), "PKCS5_pbe_set"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set0_algor, 0), "PKCS5_pbe_set0_algor"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbkdf2_set, 0), "PKCS5_pbkdf2_set"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_encrypt, 0), "PKCS8_encrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_cipher_init, 0), "pbe_cipher_init"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_crypt, 0), "pbe_crypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_decrypt_d2i, 0), "pkcs12_item_decrypt_d2i"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_i2d_encrypt, 0), "pkcs12_item_i2d_encrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_asc, 0), "pkcs12_key_gen_asc"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_uni, 0), "pkcs12_key_gen_uni"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_pbe_keyivgen, 0), "pkcs12_pbe_keyivgen"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CRYPT_ERROR), "CRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_DECODE_ERROR), "DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCODE_ERROR), "ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCRYPT_ERROR), "ENCRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEYGEN_FAILURE), "KEYGEN_FAILURE"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEY_GEN_ERROR), "KEY_GEN_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_DECODE_ERROR), "PRIVATE_KEY_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR), "PRIVATE_KEY_ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_TOO_LONG), "TOO_LONG"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_ALGORITHM), "UNKNOWN_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER), "UNKNOWN_CIPHER"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM), "UNKNOWN_CIPHER_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "UNSUPPORTED_PRIVATE_KEY_ALGORITHM"},
+ {0, NULL},
+};