Path: blob/main/crypto/openssl/providers/implementations/kdfs/pkcs12kdf.c
48383 views
/*1* Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <openssl/trace.h>10#include <stdlib.h>11#include <stdarg.h>12#include <string.h>13#include <openssl/evp.h>14#include <openssl/kdf.h>15#include <openssl/core_names.h>16#include <openssl/proverr.h>17#include "internal/cryptlib.h"18#include "internal/numbers.h"19#include "crypto/evp.h"20#include "prov/provider_ctx.h"21#include "prov/providercommon.h"22#include "prov/implementations.h"23#include "prov/provider_util.h"2425static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;26static OSSL_FUNC_kdf_dupctx_fn kdf_pkcs12_dup;27static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;28static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;29static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;30static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pkcs12_settable_ctx_params;31static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pkcs12_set_ctx_params;32static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pkcs12_gettable_ctx_params;33static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pkcs12_get_ctx_params;3435typedef struct {36void *provctx;37PROV_DIGEST digest;38unsigned char *pass;39size_t pass_len;40unsigned char *salt;41size_t salt_len;42uint64_t iter;43int id;44} KDF_PKCS12;4546/* PKCS12 compatible key/IV generation */4748static int pkcs12kdf_derive(const unsigned char *pass, size_t passlen,49const unsigned char *salt, size_t saltlen,50int id, uint64_t iter, const EVP_MD *md_type,51unsigned char *out, size_t n)52{53unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;54size_t Slen, Plen, Ilen;55size_t i, j, k, u, v;56uint64_t iter_cnt;57int ret = 0, ui, vi;58EVP_MD_CTX *ctx = NULL;5960ctx = EVP_MD_CTX_new();61if (ctx == NULL) {62ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);63goto end;64}65vi = EVP_MD_get_block_size(md_type);66ui = EVP_MD_get_size(md_type);67if (ui <= 0 || vi <= 0) {68ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);69goto end;70}71u = (size_t)ui;72v = (size_t)vi;73D = OPENSSL_malloc(v);74Ai = OPENSSL_malloc(u);75B = OPENSSL_malloc(v + 1);76Slen = v * ((saltlen + v - 1) / v);77if (passlen != 0)78Plen = v * ((passlen + v - 1) / v);79else80Plen = 0;81Ilen = Slen + Plen;82I = OPENSSL_malloc(Ilen);83if (D == NULL || Ai == NULL || B == NULL || I == NULL)84goto end;85for (i = 0; i < v; i++)86D[i] = id;87p = I;88for (i = 0; i < Slen; i++)89*p++ = salt[i % saltlen];90for (i = 0; i < Plen; i++)91*p++ = pass[i % passlen];92for (;;) {93if (!EVP_DigestInit_ex(ctx, md_type, NULL)94|| !EVP_DigestUpdate(ctx, D, v)95|| !EVP_DigestUpdate(ctx, I, Ilen)96|| !EVP_DigestFinal_ex(ctx, Ai, NULL))97goto end;98for (iter_cnt = 1; iter_cnt < iter; iter_cnt++) {99if (!EVP_DigestInit_ex(ctx, md_type, NULL)100|| !EVP_DigestUpdate(ctx, Ai, u)101|| !EVP_DigestFinal_ex(ctx, Ai, NULL))102goto end;103}104memcpy(out, Ai, n < u ? n : u);105if (u >= n) {106ret = 1;107break;108}109n -= u;110out += u;111for (j = 0; j < v; j++)112B[j] = Ai[j % u];113for (j = 0; j < Ilen; j += v) {114unsigned char *Ij = I + j;115uint16_t c = 1;116117/* Work out Ij = Ij + B + 1 */118for (k = v; k > 0;) {119k--;120c += Ij[k] + B[k];121Ij[k] = (unsigned char)c;122c >>= 8;123}124}125}126127end:128OPENSSL_free(Ai);129OPENSSL_free(B);130OPENSSL_free(D);131OPENSSL_free(I);132EVP_MD_CTX_free(ctx);133return ret;134}135136static void *kdf_pkcs12_new(void *provctx)137{138KDF_PKCS12 *ctx;139140if (!ossl_prov_is_running())141return NULL;142143ctx = OPENSSL_zalloc(sizeof(*ctx));144if (ctx == NULL)145return NULL;146ctx->provctx = provctx;147return ctx;148}149150static void kdf_pkcs12_cleanup(KDF_PKCS12 *ctx)151{152ossl_prov_digest_reset(&ctx->digest);153OPENSSL_free(ctx->salt);154OPENSSL_clear_free(ctx->pass, ctx->pass_len);155memset(ctx, 0, sizeof(*ctx));156}157158static void kdf_pkcs12_free(void *vctx)159{160KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;161162if (ctx != NULL) {163kdf_pkcs12_cleanup(ctx);164OPENSSL_free(ctx);165}166}167168static void kdf_pkcs12_reset(void *vctx)169{170KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;171void *provctx = ctx->provctx;172173kdf_pkcs12_cleanup(ctx);174ctx->provctx = provctx;175}176177static void *kdf_pkcs12_dup(void *vctx)178{179const KDF_PKCS12 *src = (const KDF_PKCS12 *)vctx;180KDF_PKCS12 *dest;181182dest = kdf_pkcs12_new(src->provctx);183if (dest != NULL) {184if (!ossl_prov_memdup(src->salt, src->salt_len,185&dest->salt, &dest->salt_len)186|| !ossl_prov_memdup(src->pass, src->pass_len,187&dest->pass , &dest->pass_len)188|| !ossl_prov_digest_copy(&dest->digest, &src->digest))189goto err;190dest->iter = src->iter;191dest->id = src->id;192}193return dest;194195err:196kdf_pkcs12_free(dest);197return NULL;198}199200static int pkcs12kdf_set_membuf(unsigned char **buffer, size_t *buflen,201const OSSL_PARAM *p)202{203OPENSSL_clear_free(*buffer, *buflen);204*buffer = NULL;205*buflen = 0;206207if (p->data_size == 0) {208if ((*buffer = OPENSSL_malloc(1)) == NULL)209return 0;210} else if (p->data != NULL) {211if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))212return 0;213}214return 1;215}216217static int kdf_pkcs12_derive(void *vctx, unsigned char *key, size_t keylen,218const OSSL_PARAM params[])219{220KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;221const EVP_MD *md;222223if (!ossl_prov_is_running() || !kdf_pkcs12_set_ctx_params(ctx, params))224return 0;225226if (ctx->pass == NULL) {227ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);228return 0;229}230231if (ctx->salt == NULL) {232ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);233return 0;234}235236md = ossl_prov_digest_md(&ctx->digest);237return pkcs12kdf_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,238ctx->id, ctx->iter, md, key, keylen);239}240241static int kdf_pkcs12_set_ctx_params(void *vctx, const OSSL_PARAM params[])242{243const OSSL_PARAM *p;244KDF_PKCS12 *ctx = vctx;245OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);246247if (ossl_param_is_empty(params))248return 1;249250if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))251return 0;252253if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)254if (!pkcs12kdf_set_membuf(&ctx->pass, &ctx->pass_len, p))255return 0;256257if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)258if (!pkcs12kdf_set_membuf(&ctx->salt, &ctx->salt_len, p))259return 0;260261if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS12_ID)) != NULL)262if (!OSSL_PARAM_get_int(p, &ctx->id))263return 0;264265if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)266if (!OSSL_PARAM_get_uint64(p, &ctx->iter))267return 0;268return 1;269}270271static const OSSL_PARAM *kdf_pkcs12_settable_ctx_params(272ossl_unused void *ctx, ossl_unused void *provctx)273{274static const OSSL_PARAM known_settable_ctx_params[] = {275OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),276OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),277OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),278OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),279OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),280OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS12_ID, NULL),281OSSL_PARAM_END282};283return known_settable_ctx_params;284}285286static int kdf_pkcs12_get_ctx_params(void *vctx, OSSL_PARAM params[])287{288OSSL_PARAM *p;289290if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)291return OSSL_PARAM_set_size_t(p, SIZE_MAX);292return -2;293}294295static const OSSL_PARAM *kdf_pkcs12_gettable_ctx_params(296ossl_unused void *ctx, ossl_unused void *provctx)297{298static const OSSL_PARAM known_gettable_ctx_params[] = {299OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),300OSSL_PARAM_END301};302return known_gettable_ctx_params;303}304305const OSSL_DISPATCH ossl_kdf_pkcs12_functions[] = {306{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },307{ OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pkcs12_dup },308{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },309{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },310{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },311{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,312(void(*)(void))kdf_pkcs12_settable_ctx_params },313{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_set_ctx_params },314{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,315(void(*)(void))kdf_pkcs12_gettable_ctx_params },316{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_get_ctx_params },317OSSL_DISPATCH_END318};319320321