From ad3156c006153711f4299c4bc214cb86e7f6b83a Mon Sep 17 00:00:00 2001 From: tb Date: Sat, 27 Jan 2024 17:14:33 +0000 Subject: [PATCH] Fold keyivgen functions into evp_pbe.c These are only used by the EVP_PBE routines and will become internal in the next major bump. --- lib/libcrypto/Makefile | 5 +- lib/libcrypto/evp/evp_pbe.c | 393 +++++++++++++++++++++++++++++++- lib/libcrypto/evp/p5_crpt.c | 157 ------------- lib/libcrypto/evp/p5_crpt2.c | 308 ------------------------- lib/libcrypto/pkcs12/p12_crpt.c | 123 ---------- 5 files changed, 387 insertions(+), 599 deletions(-) delete mode 100644 lib/libcrypto/evp/p5_crpt.c delete mode 100644 lib/libcrypto/evp/p5_crpt2.c delete mode 100644 lib/libcrypto/pkcs12/p12_crpt.c diff --git a/lib/libcrypto/Makefile b/lib/libcrypto/Makefile index 0461363e3cc..2ac252aabcb 100644 --- a/lib/libcrypto/Makefile +++ b/lib/libcrypto/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.166 2024/01/13 12:18:52 tb Exp $ +# $OpenBSD: Makefile,v 1.167 2024/01/27 17:14:33 tb Exp $ LIB= crypto LIBREBUILD=y @@ -387,8 +387,6 @@ SRCS+= m_sigver.c SRCS+= m_sm3.c SRCS+= m_streebog.c SRCS+= m_wp.c -SRCS+= p5_crpt.c -SRCS+= p5_crpt2.c SRCS+= p_legacy.c SRCS+= p_lib.c SRCS+= p_sign.c @@ -485,7 +483,6 @@ SRCS+= pvkfmt.c SRCS+= p12_add.c SRCS+= p12_asn.c SRCS+= p12_attr.c -SRCS+= p12_crpt.c SRCS+= p12_crt.c SRCS+= p12_decr.c SRCS+= p12_init.c diff --git a/lib/libcrypto/evp/evp_pbe.c b/lib/libcrypto/evp/evp_pbe.c index 7f7784847b5..dd06a768b38 100644 --- a/lib/libcrypto/evp/evp_pbe.c +++ b/lib/libcrypto/evp/evp_pbe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_pbe.c,v 1.38 2024/01/27 16:26:25 tb Exp $ */ +/* $OpenBSD: evp_pbe.c,v 1.39 2024/01/27 17:14:33 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -59,14 +59,16 @@ #include #include -#include - +#include #include #include +#include +#include #include #include #include "evp_local.h" +#include "hmac_local.h" /* Password based encryption (PBE) functions */ @@ -96,14 +98,12 @@ static const struct pbe_config pbe_outer[] = { .md_nid = NID_sha1, .keygen = PKCS5_PBE_keyivgen, }, -#ifndef OPENSSL_NO_HMAC { .pbe_nid = NID_id_pbkdf2, .cipher_nid = -1, .md_nid = -1, .keygen = PKCS5_v2_PBKDF2_keyivgen, }, -#endif { .pbe_nid = NID_pbe_WithSHA1And128BitRC4, .cipher_nid = NID_rc4, @@ -140,14 +140,12 @@ static const struct pbe_config pbe_outer[] = { .md_nid = NID_sha1, .keygen = PKCS12_PBE_keyivgen, }, -#ifndef OPENSSL_NO_HMAC { .pbe_nid = NID_pbes2, .cipher_nid = -1, .md_nid = -1, .keygen = PKCS5_v2_PBE_keyivgen, }, -#endif { .pbe_nid = NID_pbeWithMD2AndRC2_CBC, .cipher_nid = NID_rc2_64_cbc, @@ -341,6 +339,387 @@ EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, return 1; } +int +PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de) +{ + EVP_MD_CTX ctx; + unsigned char md_tmp[EVP_MAX_MD_SIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + int i; + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt; + const unsigned char *pbuf; + int mdsize; + int rv = 0; + + /* Extract useful info from parameter */ + if (param == NULL || param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + EVPerror(EVP_R_DECODE_ERROR); + return 0; + } + + mdsize = EVP_MD_size(md); + if (mdsize < 0) + return 0; + + pbuf = param->value.sequence->data; + if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) { + EVPerror(EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) + iter = 1; + else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) { + EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS); + PBEPARAM_free(pbe); + return 0; + } + salt = pbe->salt->data; + saltlen = pbe->salt->length; + + if (!pass) + passlen = 0; + else if (passlen == -1) + passlen = strlen(pass); + + EVP_MD_CTX_init(&ctx); + + if (!EVP_DigestInit_ex(&ctx, md, NULL)) + goto err; + if (!EVP_DigestUpdate(&ctx, pass, passlen)) + goto err; + if (!EVP_DigestUpdate(&ctx, salt, saltlen)) + goto err; + if (!EVP_DigestFinal_ex(&ctx, md_tmp, NULL)) + goto err; + for (i = 1; i < iter; i++) { + if (!EVP_DigestInit_ex(&ctx, md, NULL)) + goto err; + if (!EVP_DigestUpdate(&ctx, md_tmp, mdsize)) + goto err; + if (!EVP_DigestFinal_ex (&ctx, md_tmp, NULL)) + goto err; + } + if ((size_t)EVP_CIPHER_key_length(cipher) > sizeof(md_tmp)) { + EVPerror(EVP_R_BAD_KEY_LENGTH); + goto err; + } + memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher)); + if ((size_t)EVP_CIPHER_iv_length(cipher) > 16) { + EVPerror(EVP_R_IV_TOO_LARGE); + goto err; + } + memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), + EVP_CIPHER_iv_length(cipher)); + if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de)) + goto err; + explicit_bzero(md_tmp, EVP_MAX_MD_SIZE); + explicit_bzero(key, EVP_MAX_KEY_LENGTH); + explicit_bzero(iv, EVP_MAX_IV_LENGTH); + + rv = 1; + err: + EVP_MD_CTX_cleanup(&ctx); + PBEPARAM_free(pbe); + + return rv; +} + +/* + * PKCS#5 v2.0 password based encryption key derivation function PBKDF2. + */ + +int +PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, + int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) +{ + unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; + int cplen, j, k, tkeylen, mdlen; + unsigned long i = 1; + HMAC_CTX hctx_tpl, hctx; + + mdlen = EVP_MD_size(digest); + if (mdlen < 0) + return 0; + + HMAC_CTX_init(&hctx_tpl); + p = out; + tkeylen = keylen; + if (!pass) + passlen = 0; + else if (passlen == -1) + passlen = strlen(pass); + if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + while (tkeylen) { + if (tkeylen > mdlen) + cplen = mdlen; + else + cplen = tkeylen; + /* + * We are unlikely to ever use more than 256 blocks (5120 bits!) + * but just in case... + */ + itmp[0] = (unsigned char)((i >> 24) & 0xff); + itmp[1] = (unsigned char)((i >> 16) & 0xff); + itmp[2] = (unsigned char)((i >> 8) & 0xff); + itmp[3] = (unsigned char)(i & 0xff); + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + if (!HMAC_Update(&hctx, salt, saltlen) || + !HMAC_Update(&hctx, itmp, 4) || + !HMAC_Final(&hctx, digtmp, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + HMAC_CTX_cleanup(&hctx); + return 0; + } + HMAC_CTX_cleanup(&hctx); + memcpy(p, digtmp, cplen); + for (j = 1; j < iter; j++) { + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + if (!HMAC_Update(&hctx, digtmp, mdlen) || + !HMAC_Final(&hctx, digtmp, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + HMAC_CTX_cleanup(&hctx); + return 0; + } + HMAC_CTX_cleanup(&hctx); + for (k = 0; k < cplen; k++) + p[k] ^= digtmp[k]; + } + tkeylen -= cplen; + i++; + p += cplen; + } + HMAC_CTX_cleanup(&hctx_tpl); + return 1; +} + +int +PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, const unsigned char *salt, + int saltlen, int iter, int keylen, unsigned char *out) +{ + return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, + EVP_sha1(), keylen, out); +} + +/* + * Now the key derivation function itself. This is a bit evil because + * it has to check the ASN1 parameters are valid: and there are quite a + * few of them... + */ + +int +PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ + const unsigned char *pbuf; + int plen; + PBE2PARAM *pbe2 = NULL; + const EVP_CIPHER *cipher; + + int rv = 0; + + if (param == NULL || param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + EVPerror(EVP_R_DECODE_ERROR); + goto err; + } + + pbuf = param->value.sequence->data; + plen = param->value.sequence->length; + if (!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { + EVPerror(EVP_R_DECODE_ERROR); + goto err; + } + + /* See if we recognise the key derivation function */ + + if (OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { + EVPerror(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); + goto err; + } + + /* Let's see if we recognise the encryption algorithm. */ + cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); + if (!cipher) { + EVPerror(EVP_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Fixup cipher based on AlgorithmIdentifier */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) + goto err; + if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { + EVPerror(EVP_R_CIPHER_PARAMETER_ERROR); + goto err; + } + + rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen, + pbe2->keyfunc->parameter, c, md, en_de); + + err: + PBE2PARAM_free(pbe2); + + return rv; +} + +int +PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ + unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; + const unsigned char *pbuf; + int saltlen, iter, plen; + int rv = 0; + unsigned int keylen = 0; + int prf_nid, hmac_md_nid; + PBKDF2PARAM *kdf = NULL; + const EVP_MD *prfmd; + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + EVPerror(EVP_R_NO_CIPHER_SET); + return 0; + } + keylen = EVP_CIPHER_CTX_key_length(ctx); + if (keylen > sizeof key) { + EVPerror(EVP_R_BAD_KEY_LENGTH); + return 0; + } + + /* Decode parameter */ + + if (!param || (param->type != V_ASN1_SEQUENCE)) { + EVPerror(EVP_R_DECODE_ERROR); + return 0; + } + + pbuf = param->value.sequence->data; + plen = param->value.sequence->length; + + if (!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) { + EVPerror(EVP_R_DECODE_ERROR); + return 0; + } + + /* Now check the parameters of the kdf */ + + if (kdf->keylength && + (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){ + EVPerror(EVP_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + + if (kdf->prf) + prf_nid = OBJ_obj2nid(kdf->prf->algorithm); + else + prf_nid = NID_hmacWithSHA1; + + if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, NULL)) { + EVPerror(EVP_R_UNSUPPORTED_PRF); + goto err; + } + + prfmd = EVP_get_digestbynid(hmac_md_nid); + if (prfmd == NULL) { + EVPerror(EVP_R_UNSUPPORTED_PRF); + goto err; + } + + if (kdf->salt->type != V_ASN1_OCTET_STRING) { + EVPerror(EVP_R_UNSUPPORTED_SALT_TYPE); + goto err; + } + + /* it seems that its all OK */ + salt = kdf->salt->value.octet_string->data; + saltlen = kdf->salt->value.octet_string->length; + if ((iter = ASN1_INTEGER_get(kdf->iter)) <= 0) { + EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS); + goto err; + } + if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, + keylen, key)) + goto err; + + rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); + + err: + explicit_bzero(key, keylen); + PBKDF2PARAM_free(kdf); + + return rv; +} + +void +PKCS12_PBE_add(void) +{ +} +LCRYPTO_ALIAS(PKCS12_PBE_add); + +int +PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de) +{ + PBEPARAM *pbe; + int saltlen, iter, ret; + unsigned char *salt; + const unsigned char *pbuf; + unsigned char 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) { + PKCS12error(PKCS12_R_DECODE_ERROR); + return 0; + } + + pbuf = param->value.sequence->data; + if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) { + PKCS12error(PKCS12_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) + iter = 1; + else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) { + PKCS12error(PKCS12_R_DECODE_ERROR); + PBEPARAM_free(pbe); + return 0; + } + salt = pbe->salt->data; + saltlen = pbe->salt->length; + if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_KEY_ID, + iter, EVP_CIPHER_key_length(cipher), key, md)) { + PKCS12error(PKCS12_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_IV_ID, + iter, EVP_CIPHER_iv_length(cipher), iv, md)) { + PKCS12error(PKCS12_R_IV_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + PBEPARAM_free(pbe); + ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de); + explicit_bzero(key, EVP_MAX_KEY_LENGTH); + explicit_bzero(iv, EVP_MAX_IV_LENGTH); + return ret; +} +LCRYPTO_ALIAS(PKCS12_PBE_keyivgen); + /* * XXX - remove the functions below in the next major bump */ diff --git a/lib/libcrypto/evp/p5_crpt.c b/lib/libcrypto/evp/p5_crpt.c deleted file mode 100644 index 7a56a3d4ada..00000000000 --- a/lib/libcrypto/evp/p5_crpt.c +++ /dev/null @@ -1,157 +0,0 @@ -/* $OpenBSD: p5_crpt.c,v 1.25 2024/01/27 16:36:17 tb Exp $ */ -/* 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 -#include -#include - -#include -#include -#include - -#include "evp_local.h" - -int -PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, - ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de) -{ - EVP_MD_CTX ctx; - unsigned char md_tmp[EVP_MAX_MD_SIZE]; - unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; - int i; - PBEPARAM *pbe; - int saltlen, iter; - unsigned char *salt; - const unsigned char *pbuf; - int mdsize; - int rv = 0; - - /* Extract useful info from parameter */ - if (param == NULL || param->type != V_ASN1_SEQUENCE || - param->value.sequence == NULL) { - EVPerror(EVP_R_DECODE_ERROR); - return 0; - } - - mdsize = EVP_MD_size(md); - if (mdsize < 0) - return 0; - - pbuf = param->value.sequence->data; - if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) { - EVPerror(EVP_R_DECODE_ERROR); - return 0; - } - - if (!pbe->iter) - iter = 1; - else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) { - EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS); - PBEPARAM_free(pbe); - return 0; - } - salt = pbe->salt->data; - saltlen = pbe->salt->length; - - if (!pass) - passlen = 0; - else if (passlen == -1) - passlen = strlen(pass); - - EVP_MD_CTX_init(&ctx); - - if (!EVP_DigestInit_ex(&ctx, md, NULL)) - goto err; - if (!EVP_DigestUpdate(&ctx, pass, passlen)) - goto err; - if (!EVP_DigestUpdate(&ctx, salt, saltlen)) - goto err; - if (!EVP_DigestFinal_ex(&ctx, md_tmp, NULL)) - goto err; - for (i = 1; i < iter; i++) { - if (!EVP_DigestInit_ex(&ctx, md, NULL)) - goto err; - if (!EVP_DigestUpdate(&ctx, md_tmp, mdsize)) - goto err; - if (!EVP_DigestFinal_ex (&ctx, md_tmp, NULL)) - goto err; - } - if ((size_t)EVP_CIPHER_key_length(cipher) > sizeof(md_tmp)) { - EVPerror(EVP_R_BAD_KEY_LENGTH); - goto err; - } - memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher)); - if ((size_t)EVP_CIPHER_iv_length(cipher) > 16) { - EVPerror(EVP_R_IV_TOO_LARGE); - goto err; - } - memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), - EVP_CIPHER_iv_length(cipher)); - if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de)) - goto err; - explicit_bzero(md_tmp, EVP_MAX_MD_SIZE); - explicit_bzero(key, EVP_MAX_KEY_LENGTH); - explicit_bzero(iv, EVP_MAX_IV_LENGTH); - - rv = 1; - err: - EVP_MD_CTX_cleanup(&ctx); - PBEPARAM_free(pbe); - - return rv; -} diff --git a/lib/libcrypto/evp/p5_crpt2.c b/lib/libcrypto/evp/p5_crpt2.c deleted file mode 100644 index 9917b3cc5e1..00000000000 --- a/lib/libcrypto/evp/p5_crpt2.c +++ /dev/null @@ -1,308 +0,0 @@ -/* $OpenBSD: p5_crpt2.c,v 1.29 2024/01/27 16:50:39 tb Exp $ */ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 1999. - */ -/* ==================================================================== - * Copyright (c) 1999-2006 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 -#include -#include - -#include - -#if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA) - -#include -#include -#include -#include - -#include "evp_local.h" -#include "hmac_local.h" - -/* - * PKCS#5 v2.0 password based encryption key derivation function PBKDF2. - */ - -int -PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, - int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) -{ - unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; - int cplen, j, k, tkeylen, mdlen; - unsigned long i = 1; - HMAC_CTX hctx_tpl, hctx; - - mdlen = EVP_MD_size(digest); - if (mdlen < 0) - return 0; - - HMAC_CTX_init(&hctx_tpl); - p = out; - tkeylen = keylen; - if (!pass) - passlen = 0; - else if (passlen == -1) - passlen = strlen(pass); - if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) { - HMAC_CTX_cleanup(&hctx_tpl); - return 0; - } - while (tkeylen) { - if (tkeylen > mdlen) - cplen = mdlen; - else - cplen = tkeylen; - /* - * We are unlikely to ever use more than 256 blocks (5120 bits!) - * but just in case... - */ - itmp[0] = (unsigned char)((i >> 24) & 0xff); - itmp[1] = (unsigned char)((i >> 16) & 0xff); - itmp[2] = (unsigned char)((i >> 8) & 0xff); - itmp[3] = (unsigned char)(i & 0xff); - if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { - HMAC_CTX_cleanup(&hctx_tpl); - return 0; - } - if (!HMAC_Update(&hctx, salt, saltlen) || - !HMAC_Update(&hctx, itmp, 4) || - !HMAC_Final(&hctx, digtmp, NULL)) { - HMAC_CTX_cleanup(&hctx_tpl); - HMAC_CTX_cleanup(&hctx); - return 0; - } - HMAC_CTX_cleanup(&hctx); - memcpy(p, digtmp, cplen); - for (j = 1; j < iter; j++) { - if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { - HMAC_CTX_cleanup(&hctx_tpl); - return 0; - } - if (!HMAC_Update(&hctx, digtmp, mdlen) || - !HMAC_Final(&hctx, digtmp, NULL)) { - HMAC_CTX_cleanup(&hctx_tpl); - HMAC_CTX_cleanup(&hctx); - return 0; - } - HMAC_CTX_cleanup(&hctx); - for (k = 0; k < cplen; k++) - p[k] ^= digtmp[k]; - } - tkeylen -= cplen; - i++; - p += cplen; - } - HMAC_CTX_cleanup(&hctx_tpl); - return 1; -} - -int -PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, const unsigned char *salt, - int saltlen, int iter, int keylen, unsigned char *out) -{ - return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, - EVP_sha1(), keylen, out); -} - -/* - * Now the key derivation function itself. This is a bit evil because - * it has to check the ASN1 parameters are valid: and there are quite a - * few of them... - */ - -int -PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) -{ - const unsigned char *pbuf; - int plen; - PBE2PARAM *pbe2 = NULL; - const EVP_CIPHER *cipher; - - int rv = 0; - - if (param == NULL || param->type != V_ASN1_SEQUENCE || - param->value.sequence == NULL) { - EVPerror(EVP_R_DECODE_ERROR); - goto err; - } - - pbuf = param->value.sequence->data; - plen = param->value.sequence->length; - if (!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { - EVPerror(EVP_R_DECODE_ERROR); - goto err; - } - - /* See if we recognise the key derivation function */ - - if (OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { - EVPerror(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); - goto err; - } - - /* Let's see if we recognise the encryption algorithm. */ - cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); - if (!cipher) { - EVPerror(EVP_R_UNSUPPORTED_CIPHER); - goto err; - } - - /* Fixup cipher based on AlgorithmIdentifier */ - if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) - goto err; - if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { - EVPerror(EVP_R_CIPHER_PARAMETER_ERROR); - goto err; - } - - rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen, - pbe2->keyfunc->parameter, c, md, en_de); - - err: - PBE2PARAM_free(pbe2); - - return rv; -} - -int -PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) -{ - unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; - const unsigned char *pbuf; - int saltlen, iter, plen; - int rv = 0; - unsigned int keylen = 0; - int prf_nid, hmac_md_nid; - PBKDF2PARAM *kdf = NULL; - const EVP_MD *prfmd; - - if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { - EVPerror(EVP_R_NO_CIPHER_SET); - return 0; - } - keylen = EVP_CIPHER_CTX_key_length(ctx); - if (keylen > sizeof key) { - EVPerror(EVP_R_BAD_KEY_LENGTH); - return 0; - } - - /* Decode parameter */ - - if (!param || (param->type != V_ASN1_SEQUENCE)) { - EVPerror(EVP_R_DECODE_ERROR); - return 0; - } - - pbuf = param->value.sequence->data; - plen = param->value.sequence->length; - - if (!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) { - EVPerror(EVP_R_DECODE_ERROR); - return 0; - } - - /* Now check the parameters of the kdf */ - - if (kdf->keylength && - (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){ - EVPerror(EVP_R_UNSUPPORTED_KEYLENGTH); - goto err; - } - - if (kdf->prf) - prf_nid = OBJ_obj2nid(kdf->prf->algorithm); - else - prf_nid = NID_hmacWithSHA1; - - if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, NULL)) { - EVPerror(EVP_R_UNSUPPORTED_PRF); - goto err; - } - - prfmd = EVP_get_digestbynid(hmac_md_nid); - if (prfmd == NULL) { - EVPerror(EVP_R_UNSUPPORTED_PRF); - goto err; - } - - if (kdf->salt->type != V_ASN1_OCTET_STRING) { - EVPerror(EVP_R_UNSUPPORTED_SALT_TYPE); - goto err; - } - - /* it seems that its all OK */ - salt = kdf->salt->value.octet_string->data; - saltlen = kdf->salt->value.octet_string->length; - if ((iter = ASN1_INTEGER_get(kdf->iter)) <= 0) { - EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS); - goto err; - } - if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, - keylen, key)) - goto err; - - rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); - - err: - explicit_bzero(key, keylen); - PBKDF2PARAM_free(kdf); - - return rv; -} - -#endif diff --git a/lib/libcrypto/pkcs12/p12_crpt.c b/lib/libcrypto/pkcs12/p12_crpt.c deleted file mode 100644 index e7d30101c36..00000000000 --- a/lib/libcrypto/pkcs12/p12_crpt.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $OpenBSD: p12_crpt.c,v 1.17 2023/02/16 08:38:17 tb Exp $ */ -/* 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 -#include - -#include -#include - -/* PKCS#12 PBE algorithms now in static table */ - -void -PKCS12_PBE_add(void) -{ -} -LCRYPTO_ALIAS(PKCS12_PBE_add); - -int -PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de) -{ - PBEPARAM *pbe; - int saltlen, iter, ret; - unsigned char *salt; - const unsigned char *pbuf; - unsigned char 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) { - PKCS12error(PKCS12_R_DECODE_ERROR); - return 0; - } - - pbuf = param->value.sequence->data; - if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) { - PKCS12error(PKCS12_R_DECODE_ERROR); - return 0; - } - - if (!pbe->iter) - iter = 1; - else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) { - PKCS12error(PKCS12_R_DECODE_ERROR); - PBEPARAM_free(pbe); - return 0; - } - salt = pbe->salt->data; - saltlen = pbe->salt->length; - if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_KEY_ID, - iter, EVP_CIPHER_key_length(cipher), key, md)) { - PKCS12error(PKCS12_R_KEY_GEN_ERROR); - PBEPARAM_free(pbe); - return 0; - } - if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_IV_ID, - iter, EVP_CIPHER_iv_length(cipher), iv, md)) { - PKCS12error(PKCS12_R_IV_GEN_ERROR); - PBEPARAM_free(pbe); - return 0; - } - PBEPARAM_free(pbe); - ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de); - explicit_bzero(key, EVP_MAX_KEY_LENGTH); - explicit_bzero(iv, EVP_MAX_IV_LENGTH); - return ret; -} -LCRYPTO_ALIAS(PKCS12_PBE_keyivgen); -- 2.20.1