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