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 "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 13e1051a39Sopenharmony_ci#include <openssl/core.h> 14e1051a39Sopenharmony_ci#include <openssl/core_names.h> 15e1051a39Sopenharmony_ci#include <openssl/x509.h> 16e1051a39Sopenharmony_ci#include <openssl/rand.h> 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* PKCS#5 v2.0 password based encryption structures */ 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ciASN1_SEQUENCE(PBE2PARAM) = { 21e1051a39Sopenharmony_ci ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR), 22e1051a39Sopenharmony_ci ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR) 23e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(PBE2PARAM) 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM) 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ciASN1_SEQUENCE(PBKDF2PARAM) = { 28e1051a39Sopenharmony_ci ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY), 29e1051a39Sopenharmony_ci ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER), 30e1051a39Sopenharmony_ci ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER), 31e1051a39Sopenharmony_ci ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR) 32e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(PBKDF2PARAM) 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM) 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci/* 37e1051a39Sopenharmony_ci * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know 38e1051a39Sopenharmony_ci * this is horrible! Extended version to allow application supplied PRF NID 39e1051a39Sopenharmony_ci * and IV. 40e1051a39Sopenharmony_ci */ 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ciX509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter, 43e1051a39Sopenharmony_ci unsigned char *salt, int saltlen, 44e1051a39Sopenharmony_ci unsigned char *aiv, int prf_nid, 45e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx) 46e1051a39Sopenharmony_ci{ 47e1051a39Sopenharmony_ci X509_ALGOR *scheme = NULL, *ret = NULL; 48e1051a39Sopenharmony_ci int alg_nid, keylen, ivlen; 49e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = NULL; 50e1051a39Sopenharmony_ci unsigned char iv[EVP_MAX_IV_LENGTH]; 51e1051a39Sopenharmony_ci PBE2PARAM *pbe2 = NULL; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci alg_nid = EVP_CIPHER_get_type(cipher); 54e1051a39Sopenharmony_ci if (alg_nid == NID_undef) { 55e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); 56e1051a39Sopenharmony_ci goto err; 57e1051a39Sopenharmony_ci } 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci if ((pbe2 = PBE2PARAM_new()) == NULL) 60e1051a39Sopenharmony_ci goto merr; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci /* Setup the AlgorithmIdentifier for the encryption scheme */ 63e1051a39Sopenharmony_ci scheme = pbe2->encryption; 64e1051a39Sopenharmony_ci scheme->algorithm = OBJ_nid2obj(alg_nid); 65e1051a39Sopenharmony_ci if ((scheme->parameter = ASN1_TYPE_new()) == NULL) 66e1051a39Sopenharmony_ci goto merr; 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci /* Create random IV */ 69e1051a39Sopenharmony_ci ivlen = EVP_CIPHER_get_iv_length(cipher); 70e1051a39Sopenharmony_ci if (ivlen > 0) { 71e1051a39Sopenharmony_ci if (aiv) 72e1051a39Sopenharmony_ci memcpy(iv, aiv, ivlen); 73e1051a39Sopenharmony_ci else if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0) 74e1051a39Sopenharmony_ci goto err; 75e1051a39Sopenharmony_ci } 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci ctx = EVP_CIPHER_CTX_new(); 78e1051a39Sopenharmony_ci if (ctx == NULL) 79e1051a39Sopenharmony_ci goto merr; 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci /* Dummy cipherinit to just setup the IV, and PRF */ 82e1051a39Sopenharmony_ci if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0)) 83e1051a39Sopenharmony_ci goto err; 84e1051a39Sopenharmony_ci if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) { 85e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); 86e1051a39Sopenharmony_ci goto err; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci /* 89e1051a39Sopenharmony_ci * If prf NID unspecified see if cipher has a preference. An error is OK 90e1051a39Sopenharmony_ci * here: just means use default PRF. 91e1051a39Sopenharmony_ci */ 92e1051a39Sopenharmony_ci ERR_set_mark(); 93e1051a39Sopenharmony_ci if ((prf_nid == -1) && 94e1051a39Sopenharmony_ci EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { 95e1051a39Sopenharmony_ci prf_nid = NID_hmacWithSHA256; 96e1051a39Sopenharmony_ci } 97e1051a39Sopenharmony_ci ERR_pop_to_mark(); 98e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(ctx); 99e1051a39Sopenharmony_ci ctx = NULL; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci /* If its RC2 then we'd better setup the key length */ 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ci if (alg_nid == NID_rc2_cbc) 104e1051a39Sopenharmony_ci keylen = EVP_CIPHER_get_key_length(cipher); 105e1051a39Sopenharmony_ci else 106e1051a39Sopenharmony_ci keylen = -1; 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci /* Setup keyfunc */ 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci X509_ALGOR_free(pbe2->keyfunc); 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, 113e1051a39Sopenharmony_ci libctx); 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci if (pbe2->keyfunc == NULL) 116e1051a39Sopenharmony_ci goto merr; 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci /* Now set up top level AlgorithmIdentifier */ 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci if ((ret = X509_ALGOR_new()) == NULL) 121e1051a39Sopenharmony_ci goto merr; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci ret->algorithm = OBJ_nid2obj(NID_pbes2); 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci /* Encode PBE2PARAM into parameter */ 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ci if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, 128e1051a39Sopenharmony_ci &ret->parameter)) 129e1051a39Sopenharmony_ci goto merr; 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci PBE2PARAM_free(pbe2); 132e1051a39Sopenharmony_ci pbe2 = NULL; 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci return ret; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci merr: 137e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci err: 140e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(ctx); 141e1051a39Sopenharmony_ci PBE2PARAM_free(pbe2); 142e1051a39Sopenharmony_ci /* Note 'scheme' is freed as part of pbe2 */ 143e1051a39Sopenharmony_ci X509_ALGOR_free(ret); 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci return NULL; 146e1051a39Sopenharmony_ci} 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ciX509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, 149e1051a39Sopenharmony_ci unsigned char *salt, int saltlen, 150e1051a39Sopenharmony_ci unsigned char *aiv, int prf_nid) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid, 153e1051a39Sopenharmony_ci NULL); 154e1051a39Sopenharmony_ci} 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ciX509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, 157e1051a39Sopenharmony_ci unsigned char *salt, int saltlen) 158e1051a39Sopenharmony_ci{ 159e1051a39Sopenharmony_ci return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1, 160e1051a39Sopenharmony_ci NULL); 161e1051a39Sopenharmony_ci} 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ciX509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen, 165e1051a39Sopenharmony_ci int prf_nid, int keylen, 166e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx) 167e1051a39Sopenharmony_ci{ 168e1051a39Sopenharmony_ci X509_ALGOR *keyfunc = NULL; 169e1051a39Sopenharmony_ci PBKDF2PARAM *kdf = NULL; 170e1051a39Sopenharmony_ci ASN1_OCTET_STRING *osalt = NULL; 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci if ((kdf = PBKDF2PARAM_new()) == NULL) 173e1051a39Sopenharmony_ci goto merr; 174e1051a39Sopenharmony_ci if ((osalt = ASN1_OCTET_STRING_new()) == NULL) 175e1051a39Sopenharmony_ci goto merr; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci kdf->salt->value.octet_string = osalt; 178e1051a39Sopenharmony_ci kdf->salt->type = V_ASN1_OCTET_STRING; 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci if (saltlen < 0) 181e1051a39Sopenharmony_ci goto merr; 182e1051a39Sopenharmony_ci if (saltlen == 0) 183e1051a39Sopenharmony_ci saltlen = PKCS5_SALT_LEN; 184e1051a39Sopenharmony_ci if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL) 185e1051a39Sopenharmony_ci goto merr; 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci osalt->length = saltlen; 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci if (salt) 190e1051a39Sopenharmony_ci memcpy(osalt->data, salt, saltlen); 191e1051a39Sopenharmony_ci else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0) 192e1051a39Sopenharmony_ci goto merr; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci if (iter <= 0) 195e1051a39Sopenharmony_ci iter = PKCS5_DEFAULT_ITER; 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci if (!ASN1_INTEGER_set(kdf->iter, iter)) 198e1051a39Sopenharmony_ci goto merr; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci /* If have a key len set it up */ 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci if (keylen > 0) { 203e1051a39Sopenharmony_ci if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) 204e1051a39Sopenharmony_ci goto merr; 205e1051a39Sopenharmony_ci if (!ASN1_INTEGER_set(kdf->keylength, keylen)) 206e1051a39Sopenharmony_ci goto merr; 207e1051a39Sopenharmony_ci } 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci /* prf can stay NULL if we are using hmacWithSHA1 */ 210e1051a39Sopenharmony_ci if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) { 211e1051a39Sopenharmony_ci kdf->prf = X509_ALGOR_new(); 212e1051a39Sopenharmony_ci if (kdf->prf == NULL) 213e1051a39Sopenharmony_ci goto merr; 214e1051a39Sopenharmony_ci X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL); 215e1051a39Sopenharmony_ci } 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci /* Finally setup the keyfunc structure */ 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci keyfunc = X509_ALGOR_new(); 220e1051a39Sopenharmony_ci if (keyfunc == NULL) 221e1051a39Sopenharmony_ci goto merr; 222e1051a39Sopenharmony_ci 223e1051a39Sopenharmony_ci keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ci /* Encode PBKDF2PARAM into parameter of pbe2 */ 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ci if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf, 228e1051a39Sopenharmony_ci &keyfunc->parameter)) 229e1051a39Sopenharmony_ci goto merr; 230e1051a39Sopenharmony_ci 231e1051a39Sopenharmony_ci PBKDF2PARAM_free(kdf); 232e1051a39Sopenharmony_ci return keyfunc; 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ci merr: 235e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 236e1051a39Sopenharmony_ci PBKDF2PARAM_free(kdf); 237e1051a39Sopenharmony_ci X509_ALGOR_free(keyfunc); 238e1051a39Sopenharmony_ci return NULL; 239e1051a39Sopenharmony_ci} 240e1051a39Sopenharmony_ci 241e1051a39Sopenharmony_ciX509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, 242e1051a39Sopenharmony_ci int prf_nid, int keylen) 243e1051a39Sopenharmony_ci{ 244e1051a39Sopenharmony_ci return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL); 245e1051a39Sopenharmony_ci} 246e1051a39Sopenharmony_ci 247