| 1 | /* |
| 2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. |
| 3 | * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. |
| 4 | * |
| 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
| 6 | * this file except in compliance with the License. You can obtain a copy |
| 7 | * in the file LICENSE in the source distribution or at |
| 8 | * https://www.openssl.org/source/license.html |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final |
| 13 | * Section 4.1. |
| 14 | * |
| 15 | * The Single Step KDF algorithm is given by: |
| 16 | * |
| 17 | * Result(0) = empty bit string (i.e., the null string). |
| 18 | * For i = 1 to reps, do the following: |
| 19 | * Increment counter by 1. |
| 20 | * Result(i) = Result(i - 1) || H(counter || Z || FixedInfo). |
| 21 | * DKM = LeftmostBits(Result(reps), L)) |
| 22 | * |
| 23 | * NOTES: |
| 24 | * Z is a shared secret required to produce the derived key material. |
| 25 | * counter is a 4 byte buffer. |
| 26 | * FixedInfo is a bit string containing context specific data. |
| 27 | * DKM is the output derived key material. |
| 28 | * L is the required size of the DKM. |
| 29 | * reps = [L / H_outputBits] |
| 30 | * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC. |
| 31 | * H_outputBits is the length of the output of the auxiliary function H(x). |
| 32 | * |
| 33 | * Currently there is not a comprehensive list of test vectors for this |
| 34 | * algorithm, especially for H(x) = HMAC and H(x) = KMAC. |
| 35 | * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests. |
| 36 | */ |
| 37 | #include <stdlib.h> |
| 38 | #include <stdarg.h> |
| 39 | #include <string.h> |
| 40 | #include <openssl/hmac.h> |
| 41 | #include <openssl/evp.h> |
| 42 | #include <openssl/kdf.h> |
| 43 | #include <openssl/core_names.h> |
| 44 | #include <openssl/params.h> |
| 45 | #include "internal/cryptlib.h" |
| 46 | #include "internal/numbers.h" |
| 47 | #include "crypto/evp.h" |
| 48 | #include "prov/provider_ctx.h" |
| 49 | #include "prov/providercommonerr.h" |
| 50 | #include "prov/implementations.h" |
| 51 | #include "prov/provider_util.h" |
| 52 | |
| 53 | typedef struct { |
| 54 | void *provctx; |
| 55 | EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */ |
| 56 | PROV_DIGEST digest; /* H(x) = hash(x) */ |
| 57 | unsigned char *secret; |
| 58 | size_t secret_len; |
| 59 | unsigned char *info; |
| 60 | size_t info_len; |
| 61 | unsigned char *salt; |
| 62 | size_t salt_len; |
| 63 | size_t out_len; /* optional KMAC parameter */ |
| 64 | } KDF_SSKDF; |
| 65 | |
| 66 | #define SSKDF_MAX_INLEN (1<<30) |
| 67 | #define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4) |
| 68 | #define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4) |
| 69 | |
| 70 | /* KMAC uses a Customisation string of 'KDF' */ |
| 71 | static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; |
| 72 | |
| 73 | static OSSL_OP_kdf_newctx_fn sskdf_new; |
| 74 | static OSSL_OP_kdf_freectx_fn sskdf_free; |
| 75 | static OSSL_OP_kdf_reset_fn sskdf_reset; |
| 76 | static OSSL_OP_kdf_derive_fn sskdf_derive; |
| 77 | static OSSL_OP_kdf_derive_fn x963kdf_derive; |
| 78 | static OSSL_OP_kdf_settable_ctx_params_fn sskdf_settable_ctx_params; |
| 79 | static OSSL_OP_kdf_set_ctx_params_fn sskdf_set_ctx_params; |
| 80 | static OSSL_OP_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params; |
| 81 | static OSSL_OP_kdf_get_ctx_params_fn sskdf_get_ctx_params; |
| 82 | |
| 83 | /* |
| 84 | * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final |
| 85 | * Section 4. One-Step Key Derivation using H(x) = hash(x) |
| 86 | * Note: X9.63 also uses this code with the only difference being that the |
| 87 | * counter is appended to the secret 'z'. |
| 88 | * i.e. |
| 89 | * result[i] = Hash(counter || z || info) for One Step OR |
| 90 | * result[i] = Hash(z || counter || info) for X9.63. |
| 91 | */ |
| 92 | static int SSKDF_hash_kdm(const EVP_MD *kdf_md, |
| 93 | const unsigned char *z, size_t z_len, |
| 94 | const unsigned char *info, size_t info_len, |
| 95 | unsigned int append_ctr, |
| 96 | unsigned char *derived_key, size_t derived_key_len) |
| 97 | { |
| 98 | int ret = 0, hlen; |
| 99 | size_t counter, out_len, len = derived_key_len; |
| 100 | unsigned char c[4]; |
| 101 | unsigned char mac[EVP_MAX_MD_SIZE]; |
| 102 | unsigned char *out = derived_key; |
| 103 | EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; |
| 104 | |
| 105 | if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN |
| 106 | || derived_key_len > SSKDF_MAX_INLEN |
| 107 | || derived_key_len == 0) |
| 108 | return 0; |
| 109 | |
| 110 | hlen = EVP_MD_size(kdf_md); |
| 111 | if (hlen <= 0) |
| 112 | return 0; |
| 113 | out_len = (size_t)hlen; |
| 114 | |
| 115 | ctx = EVP_MD_CTX_create(); |
| 116 | ctx_init = EVP_MD_CTX_create(); |
| 117 | if (ctx == NULL || ctx_init == NULL) |
| 118 | goto end; |
| 119 | |
| 120 | if (!EVP_DigestInit(ctx_init, kdf_md)) |
| 121 | goto end; |
| 122 | |
| 123 | for (counter = 1;; counter++) { |
| 124 | c[0] = (unsigned char)((counter >> 24) & 0xff); |
| 125 | c[1] = (unsigned char)((counter >> 16) & 0xff); |
| 126 | c[2] = (unsigned char)((counter >> 8) & 0xff); |
| 127 | c[3] = (unsigned char)(counter & 0xff); |
| 128 | |
| 129 | if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init) |
| 130 | && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) |
| 131 | && EVP_DigestUpdate(ctx, z, z_len) |
| 132 | && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) |
| 133 | && EVP_DigestUpdate(ctx, info, info_len))) |
| 134 | goto end; |
| 135 | if (len >= out_len) { |
| 136 | if (!EVP_DigestFinal_ex(ctx, out, NULL)) |
| 137 | goto end; |
| 138 | out += out_len; |
| 139 | len -= out_len; |
| 140 | if (len == 0) |
| 141 | break; |
| 142 | } else { |
| 143 | if (!EVP_DigestFinal_ex(ctx, mac, NULL)) |
| 144 | goto end; |
| 145 | memcpy(out, mac, len); |
| 146 | break; |
| 147 | } |
| 148 | } |
| 149 | ret = 1; |
| 150 | end: |
| 151 | EVP_MD_CTX_destroy(ctx); |
| 152 | EVP_MD_CTX_destroy(ctx_init); |
| 153 | OPENSSL_cleanse(mac, sizeof(mac)); |
| 154 | return ret; |
| 155 | } |
| 156 | |
| 157 | static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, |
| 158 | size_t custom_len, size_t kmac_out_len, |
| 159 | size_t derived_key_len, unsigned char **out) |
| 160 | { |
| 161 | OSSL_PARAM params[2]; |
| 162 | |
| 163 | /* Only KMAC has custom data - so return if not KMAC */ |
| 164 | if (custom == NULL) |
| 165 | return 1; |
| 166 | |
| 167 | params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, |
| 168 | (void *)custom, custom_len); |
| 169 | params[1] = OSSL_PARAM_construct_end(); |
| 170 | |
| 171 | if (!EVP_MAC_CTX_set_params(ctx, params)) |
| 172 | return 0; |
| 173 | |
| 174 | /* By default only do one iteration if kmac_out_len is not specified */ |
| 175 | if (kmac_out_len == 0) |
| 176 | kmac_out_len = derived_key_len; |
| 177 | /* otherwise check the size is valid */ |
| 178 | else if (!(kmac_out_len == derived_key_len |
| 179 | || kmac_out_len == 20 |
| 180 | || kmac_out_len == 28 |
| 181 | || kmac_out_len == 32 |
| 182 | || kmac_out_len == 48 |
| 183 | || kmac_out_len == 64)) |
| 184 | return 0; |
| 185 | |
| 186 | params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, |
| 187 | &kmac_out_len); |
| 188 | |
| 189 | if (EVP_MAC_CTX_set_params(ctx, params) <= 0) |
| 190 | return 0; |
| 191 | |
| 192 | /* |
| 193 | * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so |
| 194 | * alloc a buffer for this case. |
| 195 | */ |
| 196 | if (kmac_out_len > EVP_MAX_MD_SIZE) { |
| 197 | *out = OPENSSL_zalloc(kmac_out_len); |
| 198 | if (*out == NULL) |
| 199 | return 0; |
| 200 | } |
| 201 | return 1; |
| 202 | } |
| 203 | |
| 204 | /* |
| 205 | * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final |
| 206 | * Section 4. One-Step Key Derivation using MAC: i.e either |
| 207 | * H(x) = HMAC-hash(salt, x) OR |
| 208 | * H(x) = KMAC#(salt, x, outbits, CustomString='KDF') |
| 209 | */ |
| 210 | static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, |
| 211 | const unsigned char *kmac_custom, |
| 212 | size_t kmac_custom_len, size_t kmac_out_len, |
| 213 | const unsigned char *salt, size_t salt_len, |
| 214 | const unsigned char *z, size_t z_len, |
| 215 | const unsigned char *info, size_t info_len, |
| 216 | unsigned char *derived_key, size_t derived_key_len) |
| 217 | { |
| 218 | int ret = 0; |
| 219 | size_t counter, out_len, len; |
| 220 | unsigned char c[4]; |
| 221 | unsigned char mac_buf[EVP_MAX_MD_SIZE]; |
| 222 | unsigned char *out = derived_key; |
| 223 | EVP_MAC_CTX *ctx = NULL; |
| 224 | unsigned char *mac = mac_buf, *kmac_buffer = NULL; |
| 225 | OSSL_PARAM params[2], *p = params; |
| 226 | |
| 227 | if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN |
| 228 | || derived_key_len > SSKDF_MAX_INLEN |
| 229 | || derived_key_len == 0) |
| 230 | return 0; |
| 231 | |
| 232 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, |
| 233 | (void *)salt, salt_len); |
| 234 | *p = OSSL_PARAM_construct_end(); |
| 235 | |
| 236 | if (!EVP_MAC_CTX_set_params(ctx_init, params)) |
| 237 | goto end; |
| 238 | |
| 239 | if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, |
| 240 | derived_key_len, &kmac_buffer)) |
| 241 | goto end; |
| 242 | if (kmac_buffer != NULL) |
| 243 | mac = kmac_buffer; |
| 244 | |
| 245 | if (!EVP_MAC_init(ctx_init)) |
| 246 | goto end; |
| 247 | |
| 248 | out_len = EVP_MAC_size(ctx_init); /* output size */ |
| 249 | if (out_len <= 0) |
| 250 | goto end; |
| 251 | len = derived_key_len; |
| 252 | |
| 253 | for (counter = 1;; counter++) { |
| 254 | c[0] = (unsigned char)((counter >> 24) & 0xff); |
| 255 | c[1] = (unsigned char)((counter >> 16) & 0xff); |
| 256 | c[2] = (unsigned char)((counter >> 8) & 0xff); |
| 257 | c[3] = (unsigned char)(counter & 0xff); |
| 258 | |
| 259 | ctx = EVP_MAC_CTX_dup(ctx_init); |
| 260 | if (!(ctx != NULL |
| 261 | && EVP_MAC_update(ctx, c, sizeof(c)) |
| 262 | && EVP_MAC_update(ctx, z, z_len) |
| 263 | && EVP_MAC_update(ctx, info, info_len))) |
| 264 | goto end; |
| 265 | if (len >= out_len) { |
| 266 | if (!EVP_MAC_final(ctx, out, NULL, len)) |
| 267 | goto end; |
| 268 | out += out_len; |
| 269 | len -= out_len; |
| 270 | if (len == 0) |
| 271 | break; |
| 272 | } else { |
| 273 | if (!EVP_MAC_final(ctx, mac, NULL, len)) |
| 274 | goto end; |
| 275 | memcpy(out, mac, len); |
| 276 | break; |
| 277 | } |
| 278 | EVP_MAC_CTX_free(ctx); |
| 279 | ctx = NULL; |
| 280 | } |
| 281 | ret = 1; |
| 282 | end: |
| 283 | if (kmac_buffer != NULL) |
| 284 | OPENSSL_clear_free(kmac_buffer, kmac_out_len); |
| 285 | else |
| 286 | OPENSSL_cleanse(mac_buf, sizeof(mac_buf)); |
| 287 | |
| 288 | EVP_MAC_CTX_free(ctx); |
| 289 | return ret; |
| 290 | } |
| 291 | |
| 292 | static void *sskdf_new(void *provctx) |
| 293 | { |
| 294 | KDF_SSKDF *ctx; |
| 295 | |
| 296 | if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) |
| 297 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
| 298 | ctx->provctx = provctx; |
| 299 | return ctx; |
| 300 | } |
| 301 | |
| 302 | static void sskdf_reset(void *vctx) |
| 303 | { |
| 304 | KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
| 305 | |
| 306 | EVP_MAC_CTX_free(ctx->macctx); |
| 307 | ossl_prov_digest_reset(&ctx->digest); |
| 308 | OPENSSL_clear_free(ctx->secret, ctx->secret_len); |
| 309 | OPENSSL_clear_free(ctx->info, ctx->info_len); |
| 310 | OPENSSL_clear_free(ctx->salt, ctx->salt_len); |
| 311 | memset(ctx, 0, sizeof(*ctx)); |
| 312 | } |
| 313 | |
| 314 | static void sskdf_free(void *vctx) |
| 315 | { |
| 316 | KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
| 317 | |
| 318 | if (ctx != NULL) { |
| 319 | sskdf_reset(ctx); |
| 320 | OPENSSL_free(ctx); |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | static int sskdf_set_buffer(unsigned char **out, size_t *out_len, |
| 325 | const OSSL_PARAM *p) |
| 326 | { |
| 327 | if (p->data == NULL || p->data_size == 0) |
| 328 | return 1; |
| 329 | OPENSSL_free(*out); |
| 330 | *out = NULL; |
| 331 | return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); |
| 332 | } |
| 333 | |
| 334 | static size_t sskdf_size(KDF_SSKDF *ctx) |
| 335 | { |
| 336 | int len; |
| 337 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
| 338 | |
| 339 | if (md == NULL) { |
| 340 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
| 341 | return 0; |
| 342 | } |
| 343 | len = EVP_MD_size(md); |
| 344 | return (len <= 0) ? 0 : (size_t)len; |
| 345 | } |
| 346 | |
| 347 | static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) |
| 348 | { |
| 349 | KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
| 350 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
| 351 | |
| 352 | if (ctx->secret == NULL) { |
| 353 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); |
| 354 | return 0; |
| 355 | } |
| 356 | |
| 357 | if (ctx->macctx != NULL) { |
| 358 | /* H(x) = KMAC or H(x) = HMAC */ |
| 359 | int ret; |
| 360 | const unsigned char *custom = NULL; |
| 361 | size_t custom_len = 0; |
| 362 | int default_salt_len; |
| 363 | EVP_MAC *mac = EVP_MAC_CTX_mac(ctx->macctx); |
| 364 | |
| 365 | /* |
| 366 | * TODO(3.0) investigate the necessity to have all these controls. |
| 367 | * Why does KMAC require a salt length that's shorter than the MD |
| 368 | * block size? |
| 369 | */ |
| 370 | if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) { |
| 371 | /* H(x) = HMAC(x, salt, hash) */ |
| 372 | if (md == NULL) { |
| 373 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
| 374 | return 0; |
| 375 | } |
| 376 | default_salt_len = EVP_MD_size(md); |
| 377 | if (default_salt_len <= 0) |
| 378 | return 0; |
| 379 | } else if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128) |
| 380 | || EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC256)) { |
| 381 | /* H(x) = KMACzzz(x, salt, custom) */ |
| 382 | custom = kmac_custom_str; |
| 383 | custom_len = sizeof(kmac_custom_str); |
| 384 | if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128)) |
| 385 | default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; |
| 386 | else |
| 387 | default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; |
| 388 | } else { |
| 389 | ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE); |
| 390 | return 0; |
| 391 | } |
| 392 | /* If no salt is set then use a default_salt of zeros */ |
| 393 | if (ctx->salt == NULL || ctx->salt_len <= 0) { |
| 394 | ctx->salt = OPENSSL_zalloc(default_salt_len); |
| 395 | if (ctx->salt == NULL) { |
| 396 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
| 397 | return 0; |
| 398 | } |
| 399 | ctx->salt_len = default_salt_len; |
| 400 | } |
| 401 | ret = SSKDF_mac_kdm(ctx->macctx, |
| 402 | custom, custom_len, ctx->out_len, |
| 403 | ctx->salt, ctx->salt_len, |
| 404 | ctx->secret, ctx->secret_len, |
| 405 | ctx->info, ctx->info_len, key, keylen); |
| 406 | return ret; |
| 407 | } else { |
| 408 | /* H(x) = hash */ |
| 409 | if (md == NULL) { |
| 410 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
| 411 | return 0; |
| 412 | } |
| 413 | return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, |
| 414 | ctx->info, ctx->info_len, 0, key, keylen); |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen) |
| 419 | { |
| 420 | KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
| 421 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
| 422 | |
| 423 | if (ctx->secret == NULL) { |
| 424 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); |
| 425 | return 0; |
| 426 | } |
| 427 | |
| 428 | if (ctx->macctx != NULL) { |
| 429 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); |
| 430 | return 0; |
| 431 | } |
| 432 | |
| 433 | /* H(x) = hash */ |
| 434 | if (md == NULL) { |
| 435 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
| 436 | return 0; |
| 437 | } |
| 438 | |
| 439 | return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, |
| 440 | ctx->info, ctx->info_len, 1, key, keylen); |
| 441 | } |
| 442 | |
| 443 | static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
| 444 | { |
| 445 | const OSSL_PARAM *p; |
| 446 | KDF_SSKDF *ctx = vctx; |
| 447 | OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); |
| 448 | size_t sz; |
| 449 | |
| 450 | if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) |
| 451 | return 0; |
| 452 | |
| 453 | if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params, |
| 454 | NULL, NULL, NULL, libctx)) |
| 455 | return 0; |
| 456 | |
| 457 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL |
| 458 | || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) |
| 459 | if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) |
| 460 | return 0; |
| 461 | |
| 462 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) |
| 463 | if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p)) |
| 464 | return 0; |
| 465 | |
| 466 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) |
| 467 | if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p)) |
| 468 | return 0; |
| 469 | |
| 470 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE)) |
| 471 | != NULL) { |
| 472 | if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0) |
| 473 | return 0; |
| 474 | ctx->out_len = sz; |
| 475 | } |
| 476 | return 1; |
| 477 | } |
| 478 | |
| 479 | static const OSSL_PARAM *sskdf_settable_ctx_params(void) |
| 480 | { |
| 481 | static const OSSL_PARAM known_settable_ctx_params[] = { |
| 482 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), |
| 483 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), |
| 484 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), |
| 485 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), |
| 486 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), |
| 487 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), |
| 488 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), |
| 489 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL), |
| 490 | OSSL_PARAM_END |
| 491 | }; |
| 492 | return known_settable_ctx_params; |
| 493 | } |
| 494 | |
| 495 | static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
| 496 | { |
| 497 | KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
| 498 | OSSL_PARAM *p; |
| 499 | |
| 500 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
| 501 | return OSSL_PARAM_set_size_t(p, sskdf_size(ctx)); |
| 502 | return -2; |
| 503 | } |
| 504 | |
| 505 | static const OSSL_PARAM *sskdf_gettable_ctx_params(void) |
| 506 | { |
| 507 | static const OSSL_PARAM known_gettable_ctx_params[] = { |
| 508 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), |
| 509 | OSSL_PARAM_END |
| 510 | }; |
| 511 | return known_gettable_ctx_params; |
| 512 | } |
| 513 | |
| 514 | const OSSL_DISPATCH kdf_sskdf_functions[] = { |
| 515 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, |
| 516 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, |
| 517 | { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, |
| 518 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive }, |
| 519 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, |
| 520 | (void(*)(void))sskdf_settable_ctx_params }, |
| 521 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, |
| 522 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, |
| 523 | (void(*)(void))sskdf_gettable_ctx_params }, |
| 524 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, |
| 525 | { 0, NULL } |
| 526 | }; |
| 527 | |
| 528 | const OSSL_DISPATCH kdf_x963_kdf_functions[] = { |
| 529 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, |
| 530 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, |
| 531 | { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, |
| 532 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, |
| 533 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, |
| 534 | (void(*)(void))sskdf_settable_ctx_params }, |
| 535 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, |
| 536 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, |
| 537 | (void(*)(void))sskdf_gettable_ctx_params }, |
| 538 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, |
| 539 | { 0, NULL } |
| 540 | }; |
| 541 | |