mirror of
https://github.com/openssl/openssl.git
synced 2024-11-30 13:34:44 +08:00
Move PKCS#12 KDF to provider.
This KDF is defined in RFC7292 in appendix B. It is widely used in PKCS#12 and should be provided. Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12624)
This commit is contained in:
parent
c19e6da9a3
commit
b7466c1303
@ -2874,6 +2874,7 @@ PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
|
||||
PROV_R_INVALID_DATA:115:invalid data
|
||||
PROV_R_INVALID_DIGEST:122:invalid digest
|
||||
PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length
|
||||
PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size
|
||||
PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count
|
||||
PROV_R_INVALID_IVLEN:116:invalid ivlen
|
||||
PROV_R_INVALID_IV_LENGTH:109:invalid iv length
|
||||
|
@ -12,11 +12,9 @@
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/trace.h>
|
||||
|
||||
/* PKCS12 compatible key/IV generation */
|
||||
#ifndef min
|
||||
# define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/provider.h"
|
||||
|
||||
int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
|
||||
int saltlen, int id, int iter, int n,
|
||||
@ -68,16 +66,37 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
|
||||
int saltlen, int id, int iter, int n,
|
||||
unsigned char *out, const EVP_MD *md_type)
|
||||
{
|
||||
unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
|
||||
int Slen, Plen, Ilen;
|
||||
int i, j, u, v;
|
||||
int ret = 0;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
unsigned char *tmpout = out;
|
||||
int tmpn = n;
|
||||
int res = 0;
|
||||
EVP_KDF *kdf;
|
||||
EVP_KDF_CTX *ctx;
|
||||
OSSL_PARAM params[6], *p = params;
|
||||
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The parameter query isn't available but the library context can be
|
||||
* extracted from the passed digest.
|
||||
*/
|
||||
kdf = EVP_KDF_fetch(ossl_provider_library_context(EVP_MD_provider(md_type)),
|
||||
"PKCS12KDF", NULL);
|
||||
if (kdf == NULL)
|
||||
return 0;
|
||||
ctx = EVP_KDF_CTX_new(kdf);
|
||||
EVP_KDF_free(kdf);
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
|
||||
(char *)EVP_MD_name(md_type), 0);
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
|
||||
pass, passlen);
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
|
||||
salt, saltlen);
|
||||
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS12_ID, &id);
|
||||
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
|
||||
*p = OSSL_PARAM_construct_end();
|
||||
if (!EVP_KDF_CTX_set_params(ctx, params))
|
||||
goto err;
|
||||
|
||||
OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
|
||||
@ -89,77 +108,16 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
|
||||
BIO_hex_string(trc_out, 0, saltlen, salt, saltlen);
|
||||
BIO_printf(trc_out, "\n");
|
||||
} OSSL_TRACE_END(PKCS12_KEYGEN);
|
||||
v = EVP_MD_block_size(md_type);
|
||||
u = EVP_MD_size(md_type);
|
||||
if (u < 0 || v <= 0)
|
||||
goto err;
|
||||
D = OPENSSL_malloc(v);
|
||||
Ai = OPENSSL_malloc(u);
|
||||
B = OPENSSL_malloc(v + 1);
|
||||
Slen = v * ((saltlen + v - 1) / v);
|
||||
if (passlen)
|
||||
Plen = v * ((passlen + v - 1) / v);
|
||||
else
|
||||
Plen = 0;
|
||||
Ilen = Slen + Plen;
|
||||
I = OPENSSL_malloc(Ilen);
|
||||
if (D == NULL || Ai == NULL || B == NULL || I == NULL)
|
||||
goto err;
|
||||
for (i = 0; i < v; i++)
|
||||
D[i] = id;
|
||||
p = I;
|
||||
for (i = 0; i < Slen; i++)
|
||||
*p++ = salt[i % saltlen];
|
||||
for (i = 0; i < Plen; i++)
|
||||
*p++ = pass[i % passlen];
|
||||
for (;;) {
|
||||
if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, D, v)
|
||||
|| !EVP_DigestUpdate(ctx, I, Ilen)
|
||||
|| !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
||||
goto err;
|
||||
for (j = 1; j < iter; j++) {
|
||||
if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, Ai, u)
|
||||
|| !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
||||
goto err;
|
||||
}
|
||||
memcpy(out, Ai, min(n, u));
|
||||
if (u >= n) {
|
||||
OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
|
||||
BIO_printf(trc_out, "Output KEY (length %d)\n", tmpn);
|
||||
BIO_hex_string(trc_out, 0, tmpn, tmpout, tmpn);
|
||||
BIO_printf(trc_out, "\n");
|
||||
} OSSL_TRACE_END(PKCS12_KEYGEN);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
n -= u;
|
||||
out += u;
|
||||
for (j = 0; j < v; j++)
|
||||
B[j] = Ai[j % u];
|
||||
for (j = 0; j < Ilen; j += v) {
|
||||
int k;
|
||||
unsigned char *Ij = I + j;
|
||||
uint16_t c = 1;
|
||||
|
||||
/* Work out Ij = Ij + B + 1 */
|
||||
for (k = v - 1; k >= 0; k--) {
|
||||
c += Ij[k] + B[k];
|
||||
Ij[k] = (unsigned char)c;
|
||||
c >>= 8;
|
||||
}
|
||||
}
|
||||
if (EVP_KDF_derive(ctx, out, (size_t)n)) {
|
||||
res = 1;
|
||||
OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
|
||||
BIO_printf(trc_out, "Output KEY (length %d)\n", n);
|
||||
BIO_hex_string(trc_out, 0, n, out, n);
|
||||
BIO_printf(trc_out, "\n");
|
||||
} OSSL_TRACE_END(PKCS12_KEYGEN);
|
||||
}
|
||||
|
||||
err:
|
||||
PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
end:
|
||||
OPENSSL_free(Ai);
|
||||
OPENSSL_free(B);
|
||||
OPENSSL_free(D);
|
||||
OPENSSL_free(I);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
EVP_KDF_CTX_free(ctx);
|
||||
return res;
|
||||
}
|
||||
|
86
doc/man7/EVP_KDF-PKCS12KDF.pod
Normal file
86
doc/man7/EVP_KDF-PKCS12KDF.pod
Normal file
@ -0,0 +1,86 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
EVP_KDF-PKCS12KDF - The PKCS#12 EVP_KDF implementation
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Support for computing the B<PKCS#12> password-based KDF through the B<EVP_KDF>
|
||||
API.
|
||||
|
||||
The EVP_KDF-PKCS12KDF algorithm implements the PKCS#12 password-based key
|
||||
derivation function, as described in appendix B of RFC 7292 (PKCS #12:
|
||||
Personal Information Exchange Syntax); it derives a key from a password
|
||||
using a salt, iteration count and the intended usage.
|
||||
|
||||
=head2 Identity
|
||||
|
||||
"PKCS12KDF" is the name for this implementation; it
|
||||
can be used with the EVP_KDF_fetch() function.
|
||||
|
||||
=head2 Supported parameters
|
||||
|
||||
The supported parameters are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item "pass" (B<OSSL_KDF_PARAM_PASSWORD>) <octet string>
|
||||
|
||||
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
|
||||
|
||||
=item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
|
||||
|
||||
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
|
||||
|
||||
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
|
||||
|
||||
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
|
||||
|
||||
=item "id" (B<OSSL_KDF_PARAM_PKCS12_ID>) <integer>
|
||||
|
||||
This parameter is used to specify the intended usage of the output bits, as per
|
||||
RFC 7292 section B.3.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
A typical application of this algorithm is to derive keying material for an
|
||||
encryption algorithm from a password in the "pass", a salt in "salt",
|
||||
and an iteration count.
|
||||
|
||||
Increasing the "iter" parameter slows down the algorithm which makes it
|
||||
harder for an attacker to perform a brute force attack using a large number
|
||||
of candidate passwords.
|
||||
|
||||
No assumption is made regarding the given password; it is simply treated as a
|
||||
byte sequence.
|
||||
|
||||
=head1 CONFORMING TO
|
||||
|
||||
RFC7292
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<EVP_KDF(3)>,
|
||||
L<EVP_KDF_CTX_new(3)>,
|
||||
L<EVP_KDF_CTX_free(3)>,
|
||||
L<EVP_KDF_CTX_set_params(3)>,
|
||||
L<EVP_KDF_derive(3)>,
|
||||
L<EVP_KDF(3)/PARAMETERS>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
This functionality was added to OpenSSL 3.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
@ -124,6 +124,8 @@ The OpenSSL default provider supports these operations and algorithms:
|
||||
|
||||
=item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
|
||||
|
||||
=item PKCS12KDF, see L<EVP_KDF-PKCS12KDF(7)>
|
||||
|
||||
=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
|
||||
|
||||
=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
|
||||
|
@ -178,6 +178,7 @@ extern "C" {
|
||||
#define OSSL_KDF_PARAM_SIZE "size" /* size_t */
|
||||
#define OSSL_KDF_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */
|
||||
#define OSSL_KDF_PARAM_CONSTANT "constant" /* octet string */
|
||||
#define OSSL_KDF_PARAM_PKCS12_ID "id" /* int */
|
||||
|
||||
/* Known KDF names */
|
||||
#define OSSL_KDF_NAME_HKDF "HKDF"
|
||||
|
@ -88,6 +88,7 @@ int ERR_load_PROV_strings(void);
|
||||
# define PROV_R_INVALID_DATA 115
|
||||
# define PROV_R_INVALID_DIGEST 122
|
||||
# define PROV_R_INVALID_DIGEST_LENGTH 166
|
||||
# define PROV_R_INVALID_DIGEST_SIZE 218
|
||||
# define PROV_R_INVALID_ITERATION_COUNT 123
|
||||
# define PROV_R_INVALID_IVLEN 116
|
||||
# define PROV_R_INVALID_IV_LENGTH 109
|
||||
|
@ -79,6 +79,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH),
|
||||
"invalid digest length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_SIZE),
|
||||
"invalid digest size"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
|
||||
"invalid iteration count"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"},
|
||||
|
@ -316,6 +316,7 @@ static const OSSL_ALGORITHM deflt_kdfs[] = {
|
||||
{ "HKDF", "provider=default", kdf_hkdf_functions },
|
||||
{ "SSKDF", "provider=default", kdf_sskdf_functions },
|
||||
{ "PBKDF2", "provider=default", kdf_pbkdf2_functions },
|
||||
{ "PKCS12KDF", "provider=default", kdf_pkcs12_functions },
|
||||
{ "SSHKDF", "provider=default", kdf_sshkdf_functions },
|
||||
{ "X963KDF", "provider=default", kdf_x963_kdf_functions },
|
||||
{ "TLS1-PRF", "provider=default", kdf_tls1_prf_functions },
|
||||
|
@ -244,6 +244,7 @@ extern const OSSL_DISPATCH poly1305_functions[];
|
||||
|
||||
/* KDFs / PRFs */
|
||||
extern const OSSL_DISPATCH kdf_pbkdf2_functions[];
|
||||
extern const OSSL_DISPATCH kdf_pkcs12_functions[];
|
||||
#ifndef OPENSSL_NO_SCRYPT
|
||||
extern const OSSL_DISPATCH kdf_scrypt_functions[];
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@ $HKDF_GOAL=../../libimplementations.a
|
||||
$KBKDF_GOAL=../../libimplementations.a
|
||||
$KRB5KDF_GOAL=../../libimplementations.a
|
||||
$PBKDF2_GOAL=../../libimplementations.a
|
||||
$PKCS12KDF_GOAL=../../libimplementations.a
|
||||
$SSKDF_GOAL=../../libimplementations.a
|
||||
$SCRYPT_GOAL=../../libimplementations.a
|
||||
$SSHKDF_GOAL=../../libimplementations.a
|
||||
@ -25,6 +26,8 @@ SOURCE[$PBKDF2_GOAL]=pbkdf2.c
|
||||
SOURCE[../../libfips.a]=pbkdf2_fips.c
|
||||
SOURCE[../../libnonfips.a]=pbkdf2_fips.c
|
||||
|
||||
SOURCE[$PKCS12KDF_GOAL]=pkcs12kdf.c
|
||||
|
||||
SOURCE[$SSKDF_GOAL]=sskdf.c
|
||||
|
||||
SOURCE[$SCRYPT_GOAL]=scrypt.c
|
||||
|
285
providers/implementations/kdfs/pkcs12kdf.c
Normal file
285
providers/implementations/kdfs/pkcs12kdf.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/trace.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "crypto/evp.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/providercommonerr.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/provider_util.h"
|
||||
|
||||
static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;
|
||||
static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;
|
||||
static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;
|
||||
static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;
|
||||
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pkcs12_settable_ctx_params;
|
||||
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pkcs12_set_ctx_params;
|
||||
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pkcs12_gettable_ctx_params;
|
||||
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pkcs12_get_ctx_params;
|
||||
|
||||
typedef struct {
|
||||
void *provctx;
|
||||
PROV_DIGEST digest;
|
||||
unsigned char *pass;
|
||||
size_t pass_len;
|
||||
unsigned char *salt;
|
||||
size_t salt_len;
|
||||
uint64_t iter;
|
||||
int id;
|
||||
} KDF_PKCS12;
|
||||
|
||||
/* PKCS12 compatible key/IV generation */
|
||||
|
||||
static int pkcs12kdf_derive(const unsigned char *pass, size_t passlen,
|
||||
const unsigned char *salt, size_t saltlen,
|
||||
int id, uint64_t iter, const EVP_MD *md_type,
|
||||
unsigned char *out, size_t n)
|
||||
{
|
||||
unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
|
||||
size_t Slen, Plen, Ilen;
|
||||
size_t i, j, k, u, v;
|
||||
uint64_t iter_cnt;
|
||||
int ret = 0, ui, vi;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
}
|
||||
vi = EVP_MD_block_size(md_type);
|
||||
ui = EVP_MD_size(md_type);
|
||||
if (ui < 0 || vi <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
|
||||
goto end;
|
||||
}
|
||||
u = (size_t)ui;
|
||||
v = (size_t)vi;
|
||||
D = OPENSSL_malloc(v);
|
||||
Ai = OPENSSL_malloc(u);
|
||||
B = OPENSSL_malloc(v + 1);
|
||||
Slen = v * ((saltlen + v - 1) / v);
|
||||
if (passlen != 0)
|
||||
Plen = v * ((passlen + v - 1) / v);
|
||||
else
|
||||
Plen = 0;
|
||||
Ilen = Slen + Plen;
|
||||
I = OPENSSL_malloc(Ilen);
|
||||
if (D == NULL || Ai == NULL || B == NULL || I == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
goto end;
|
||||
}
|
||||
for (i = 0; i < v; i++)
|
||||
D[i] = id;
|
||||
p = I;
|
||||
for (i = 0; i < Slen; i++)
|
||||
*p++ = salt[i % saltlen];
|
||||
for (i = 0; i < Plen; i++)
|
||||
*p++ = pass[i % passlen];
|
||||
for (;;) {
|
||||
if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, D, v)
|
||||
|| !EVP_DigestUpdate(ctx, I, Ilen)
|
||||
|| !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
||||
goto end;
|
||||
for (iter_cnt = 1; iter_cnt < iter; iter_cnt++) {
|
||||
if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, Ai, u)
|
||||
|| !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
||||
goto end;
|
||||
}
|
||||
memcpy(out, Ai, n < u ? n : u);
|
||||
if (u >= n) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
n -= u;
|
||||
out += u;
|
||||
for (j = 0; j < v; j++)
|
||||
B[j] = Ai[j % u];
|
||||
for (j = 0; j < Ilen; j += v) {
|
||||
unsigned char *Ij = I + j;
|
||||
uint16_t c = 1;
|
||||
|
||||
/* Work out Ij = Ij + B + 1 */
|
||||
for (k = v; k > 0;) {
|
||||
k--;
|
||||
c += Ij[k] + B[k];
|
||||
Ij[k] = (unsigned char)c;
|
||||
c >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
OPENSSL_free(Ai);
|
||||
OPENSSL_free(B);
|
||||
OPENSSL_free(D);
|
||||
OPENSSL_free(I);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *kdf_pkcs12_new(void *provctx)
|
||||
{
|
||||
KDF_PKCS12 *ctx;
|
||||
|
||||
ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ctx->provctx = provctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void kdf_pkcs12_cleanup(KDF_PKCS12 *ctx)
|
||||
{
|
||||
ossl_prov_digest_reset(&ctx->digest);
|
||||
OPENSSL_free(ctx->salt);
|
||||
OPENSSL_clear_free(ctx->pass, ctx->pass_len);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void kdf_pkcs12_free(void *vctx)
|
||||
{
|
||||
KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
||||
|
||||
if (ctx != NULL) {
|
||||
kdf_pkcs12_cleanup(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void kdf_pkcs12_reset(void *vctx)
|
||||
{
|
||||
KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
||||
void *provctx = ctx->provctx;
|
||||
|
||||
kdf_pkcs12_cleanup(ctx);
|
||||
ctx->provctx = provctx;
|
||||
}
|
||||
|
||||
static int pkcs12kdf_set_membuf(unsigned char **buffer, size_t *buflen,
|
||||
const OSSL_PARAM *p)
|
||||
{
|
||||
OPENSSL_clear_free(*buffer, *buflen);
|
||||
if (p->data_size == 0) {
|
||||
if ((*buffer = OPENSSL_malloc(1)) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else if (p->data != NULL) {
|
||||
*buffer = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int kdf_pkcs12_derive(void *vctx, unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (ctx->pass == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->salt == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pkcs12kdf_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
|
||||
ctx->id, ctx->iter, md, key, keylen);
|
||||
}
|
||||
|
||||
static int kdf_pkcs12_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
KDF_PKCS12 *ctx = vctx;
|
||||
OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
|
||||
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
|
||||
if (!pkcs12kdf_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
|
||||
if (!pkcs12kdf_set_membuf(&ctx->salt, &ctx->salt_len,p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS12_ID)) != NULL)
|
||||
if (!OSSL_PARAM_get_int(p, &ctx->id))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
|
||||
if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_pkcs12_settable_ctx_params(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
||||
OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
|
||||
OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS12_ID, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int kdf_pkcs12_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, SIZE_MAX);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_pkcs12_gettable_ctx_params(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kdf_pkcs12_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_pkcs12_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_pkcs12_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
Loading…
Reference in New Issue
Block a user