1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <stdlib.h> 12e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 13e1051a39Sopenharmony_ci#include <openssl/x509.h> 14e1051a39Sopenharmony_ci#include <openssl/evp.h> 15e1051a39Sopenharmony_ci#include <openssl/core_names.h> 16e1051a39Sopenharmony_ci#include <openssl/kdf.h> 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* 19e1051a39Sopenharmony_ci * Doesn't do anything now: Builtin PBE algorithms in static table. 20e1051a39Sopenharmony_ci */ 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_civoid PKCS5_PBE_add(void) 23e1051a39Sopenharmony_ci{ 24e1051a39Sopenharmony_ci} 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ciint PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, 27e1051a39Sopenharmony_ci ASN1_TYPE *param, const EVP_CIPHER *cipher, 28e1051a39Sopenharmony_ci const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx, 29e1051a39Sopenharmony_ci const char *propq) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci unsigned char md_tmp[EVP_MAX_MD_SIZE]; 32e1051a39Sopenharmony_ci unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; 33e1051a39Sopenharmony_ci int ivl, kl; 34e1051a39Sopenharmony_ci PBEPARAM *pbe = NULL; 35e1051a39Sopenharmony_ci int saltlen, iter; 36e1051a39Sopenharmony_ci unsigned char *salt; 37e1051a39Sopenharmony_ci int mdsize; 38e1051a39Sopenharmony_ci int rv = 0; 39e1051a39Sopenharmony_ci EVP_KDF *kdf; 40e1051a39Sopenharmony_ci EVP_KDF_CTX *kctx = NULL; 41e1051a39Sopenharmony_ci OSSL_PARAM params[5], *p = params; 42e1051a39Sopenharmony_ci const char *mdname = EVP_MD_name(md); 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci /* Extract useful info from parameter */ 45e1051a39Sopenharmony_ci if (param == NULL || param->type != V_ASN1_SEQUENCE || 46e1051a39Sopenharmony_ci param->value.sequence == NULL) { 47e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR); 48e1051a39Sopenharmony_ci return 0; 49e1051a39Sopenharmony_ci } 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param); 52e1051a39Sopenharmony_ci if (pbe == NULL) { 53e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR); 54e1051a39Sopenharmony_ci return 0; 55e1051a39Sopenharmony_ci } 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ci ivl = EVP_CIPHER_get_iv_length(cipher); 58e1051a39Sopenharmony_ci if (ivl < 0 || ivl > 16) { 59e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); 60e1051a39Sopenharmony_ci goto err; 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci kl = EVP_CIPHER_get_key_length(cipher); 63e1051a39Sopenharmony_ci if (kl < 0 || kl > (int)sizeof(md_tmp)) { 64e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); 65e1051a39Sopenharmony_ci goto err; 66e1051a39Sopenharmony_ci } 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci if (pbe->iter == NULL) 69e1051a39Sopenharmony_ci iter = 1; 70e1051a39Sopenharmony_ci else 71e1051a39Sopenharmony_ci iter = ASN1_INTEGER_get(pbe->iter); 72e1051a39Sopenharmony_ci salt = pbe->salt->data; 73e1051a39Sopenharmony_ci saltlen = pbe->salt->length; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci if (pass == NULL) 76e1051a39Sopenharmony_ci passlen = 0; 77e1051a39Sopenharmony_ci else if (passlen == -1) 78e1051a39Sopenharmony_ci passlen = strlen(pass); 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci mdsize = EVP_MD_get_size(md); 81e1051a39Sopenharmony_ci if (mdsize < 0) 82e1051a39Sopenharmony_ci goto err; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF1, propq); 85e1051a39Sopenharmony_ci kctx = EVP_KDF_CTX_new(kdf); 86e1051a39Sopenharmony_ci EVP_KDF_free(kdf); 87e1051a39Sopenharmony_ci if (kctx == NULL) 88e1051a39Sopenharmony_ci goto err; 89e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, 90e1051a39Sopenharmony_ci (char *)pass, (size_t)passlen); 91e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, 92e1051a39Sopenharmony_ci salt, saltlen); 93e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter); 94e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, 95e1051a39Sopenharmony_ci (char *)mdname, 0); 96e1051a39Sopenharmony_ci *p = OSSL_PARAM_construct_end(); 97e1051a39Sopenharmony_ci if (EVP_KDF_derive(kctx, md_tmp, mdsize, params) != 1) 98e1051a39Sopenharmony_ci goto err; 99e1051a39Sopenharmony_ci memcpy(key, md_tmp, kl); 100e1051a39Sopenharmony_ci memcpy(iv, md_tmp + (16 - ivl), ivl); 101e1051a39Sopenharmony_ci if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de)) 102e1051a39Sopenharmony_ci goto err; 103e1051a39Sopenharmony_ci OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE); 104e1051a39Sopenharmony_ci OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); 105e1051a39Sopenharmony_ci OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); 106e1051a39Sopenharmony_ci rv = 1; 107e1051a39Sopenharmony_ci err: 108e1051a39Sopenharmony_ci EVP_KDF_CTX_free(kctx); 109e1051a39Sopenharmony_ci PBEPARAM_free(pbe); 110e1051a39Sopenharmony_ci return rv; 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ciint PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, 114e1051a39Sopenharmony_ci ASN1_TYPE *param, const EVP_CIPHER *cipher, 115e1051a39Sopenharmony_ci const EVP_MD *md, int en_de) 116e1051a39Sopenharmony_ci{ 117e1051a39Sopenharmony_ci return PKCS5_PBE_keyivgen_ex(cctx, pass, passlen, param, cipher, md, en_de, 118e1051a39Sopenharmony_ci NULL, NULL); 119e1051a39Sopenharmony_ci} 120e1051a39Sopenharmony_ci 121