1/* 2 * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9{- 10use OpenSSL::paramnames qw(produce_param_decoder); 11-} 12 13#include <string.h> 14#include <openssl/evp.h> 15#include <openssl/core_names.h> 16#include <openssl/proverr.h> 17#include <openssl/err.h> 18#include "internal/common.h" 19#include "internal/numbers.h" /* SIZE_MAX */ 20#include "prov/provider_ctx.h" 21#include "prov/providercommon.h" 22#include "prov/implementations.h" 23#include "prov/provider_util.h" 24 25static OSSL_FUNC_kdf_newctx_fn kdf_pvk_new; 26static OSSL_FUNC_kdf_dupctx_fn kdf_pvk_dup; 27static OSSL_FUNC_kdf_freectx_fn kdf_pvk_free; 28static OSSL_FUNC_kdf_reset_fn kdf_pvk_reset; 29static OSSL_FUNC_kdf_derive_fn kdf_pvk_derive; 30static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pvk_settable_ctx_params; 31static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pvk_set_ctx_params; 32static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pvk_gettable_ctx_params; 33static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pvk_get_ctx_params; 34 35typedef struct { 36 void *provctx; 37 unsigned char *pass; 38 size_t pass_len; 39 unsigned char *salt; 40 size_t salt_len; 41 PROV_DIGEST digest; 42} KDF_PVK; 43 44static void kdf_pvk_init(KDF_PVK *ctx); 45 46static void *kdf_pvk_new(void *provctx) 47{ 48 KDF_PVK *ctx; 49 50 if (!ossl_prov_is_running()) 51 return NULL; 52 53 ctx = OPENSSL_zalloc(sizeof(*ctx)); 54 if (ctx == NULL) 55 return NULL; 56 ctx->provctx = provctx; 57 kdf_pvk_init(ctx); 58 return ctx; 59} 60 61static void kdf_pvk_cleanup(KDF_PVK *ctx) 62{ 63 ossl_prov_digest_reset(&ctx->digest); 64 OPENSSL_free(ctx->salt); 65 OPENSSL_clear_free(ctx->pass, ctx->pass_len); 66 OPENSSL_cleanse(ctx, sizeof(*ctx)); 67} 68 69static void kdf_pvk_free(void *vctx) 70{ 71 KDF_PVK *ctx = (KDF_PVK *)vctx; 72 73 if (ctx != NULL) { 74 kdf_pvk_cleanup(ctx); 75 OPENSSL_free(ctx); 76 } 77} 78 79static void *kdf_pvk_dup(void *vctx) 80{ 81 const KDF_PVK *src = (const KDF_PVK *)vctx; 82 KDF_PVK *dest; 83 84 dest = kdf_pvk_new(src->provctx); 85 if (dest != NULL) 86 if (!ossl_prov_memdup(src->salt, src->salt_len, 87 &dest->salt, &dest->salt_len) 88 || !ossl_prov_memdup(src->pass, src->pass_len, 89 &dest->pass , &dest->pass_len) 90 || !ossl_prov_digest_copy(&dest->digest, &src->digest)) 91 goto err; 92 return dest; 93 94 err: 95 kdf_pvk_free(dest); 96 return NULL; 97} 98 99static void kdf_pvk_reset(void *vctx) 100{ 101 KDF_PVK *ctx = (KDF_PVK *)vctx; 102 void *provctx = ctx->provctx; 103 104 kdf_pvk_cleanup(ctx); 105 ctx->provctx = provctx; 106 kdf_pvk_init(ctx); 107} 108 109static void kdf_pvk_init(KDF_PVK *ctx) 110{ 111 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 112 OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx); 113 114 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, 115 SN_sha1, 0); 116 if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) 117 /* This is an error, but there is no way to indicate such directly */ 118 ossl_prov_digest_reset(&ctx->digest); 119} 120 121static int pvk_set_membuf(unsigned char **buffer, size_t *buflen, 122 const OSSL_PARAM *p) 123{ 124 OPENSSL_clear_free(*buffer, *buflen); 125 *buffer = NULL; 126 *buflen = 0; 127 128 if (p->data_size == 0) { 129 if ((*buffer = OPENSSL_malloc(1)) == NULL) 130 return 0; 131 } else if (p->data != NULL) { 132 if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen)) 133 return 0; 134 } 135 return 1; 136} 137 138static int kdf_pvk_derive(void *vctx, unsigned char *key, size_t keylen, 139 const OSSL_PARAM params[]) 140{ 141 KDF_PVK *ctx = (KDF_PVK *)vctx; 142 const EVP_MD *md; 143 EVP_MD_CTX *mctx; 144 int res; 145 146 if (!ossl_prov_is_running() || !kdf_pvk_set_ctx_params(ctx, params)) 147 return 0; 148 149 if (ctx->pass == NULL) { 150 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS); 151 return 0; 152 } 153 154 if (ctx->salt == NULL) { 155 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT); 156 return 0; 157 } 158 159 md = ossl_prov_digest_md(&ctx->digest); 160 if (md == NULL) { 161 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); 162 return 0; 163 } 164 res = EVP_MD_get_size(md); 165 if (res <= 0) { 166 ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); 167 return 0; 168 } 169 if ((size_t)res > keylen) { 170 ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); 171 return 0; 172 } 173 174 mctx = EVP_MD_CTX_new(); 175 res = mctx != NULL 176 && EVP_DigestInit_ex(mctx, md, NULL) 177 && EVP_DigestUpdate(mctx, ctx->salt, ctx->salt_len) 178 && EVP_DigestUpdate(mctx, ctx->pass, ctx->pass_len) 179 && EVP_DigestFinal_ex(mctx, key, NULL); 180 EVP_MD_CTX_free(mctx); 181 return res; 182} 183 184{- produce_param_decoder('pvk_set_ctx_params', 185 (['KDF_PARAM_PROPERTIES', 'propq', 'utf8_string'], 186 ['ALG_PARAM_ENGINE', 'engine', 'utf8_string', 'hidden'], 187 ['KDF_PARAM_DIGEST', 'digest', 'utf8_string'], 188 ['KDF_PARAM_PASSWORD', 'pass', 'octet_string'], 189 ['KDF_PARAM_SALT', 'salt', 'octet_string'], 190 )); -} 191 192static int kdf_pvk_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 193{ 194 struct pvk_set_ctx_params_st p; 195 KDF_PVK *ctx = vctx; 196 OSSL_LIB_CTX *provctx; 197 198 if (ctx == NULL || !pvk_set_ctx_params_decoder(params, &p)) 199 return 0; 200 201 provctx = PROV_LIBCTX_OF(ctx->provctx); 202 203 if (!ossl_prov_digest_load(&ctx->digest, p.digest, p.propq, p.engine, 204 provctx)) 205 return 0; 206 207 if (p.pass != NULL && !pvk_set_membuf(&ctx->pass, &ctx->pass_len, p.pass)) 208 return 0; 209 210 if (p.salt != NULL && !pvk_set_membuf(&ctx->salt, &ctx->salt_len, p.salt)) 211 return 0; 212 213 return 1; 214} 215 216static const OSSL_PARAM *kdf_pvk_settable_ctx_params(ossl_unused void *ctx, 217 ossl_unused void *p_ctx) 218{ 219 return pvk_set_ctx_params_list; 220} 221 222{- produce_param_decoder('pvk_get_ctx_params', 223 (['KDF_PARAM_SIZE', 'size', 'size_t'], 224 )); -} 225 226static int kdf_pvk_get_ctx_params(void *vctx, OSSL_PARAM params[]) 227{ 228 struct pvk_get_ctx_params_st p; 229 KDF_PVK *ctx = vctx; 230 231 if (ctx == NULL || !pvk_get_ctx_params_decoder(params, &p)) 232 return 0; 233 234 if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX)) 235 return 0; 236 return 1; 237} 238 239static const OSSL_PARAM *kdf_pvk_gettable_ctx_params(ossl_unused void *ctx, 240 ossl_unused void *p_ctx) 241{ 242 return pvk_get_ctx_params_list; 243} 244 245const OSSL_DISPATCH ossl_kdf_pvk_functions[] = { 246 { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pvk_new }, 247 { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pvk_dup }, 248 { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pvk_free }, 249 { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pvk_reset }, 250 { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pvk_derive }, 251 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, 252 (void(*)(void))kdf_pvk_settable_ctx_params }, 253 { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pvk_set_ctx_params }, 254 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, 255 (void(*)(void))kdf_pvk_gettable_ctx_params }, 256 { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pvk_get_ctx_params }, 257 OSSL_DISPATCH_END 258}; 259