Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/iperf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ jobs:
mkdir -p $KEY_DIR
cd $KEY_DIR
# Generate RSA keys for iperf tests
# PBKDF2 keys HMAC with the passphrase, and FIPS modules before
# v6.0.0 reject HMAC keys under 14 bytes, so keep this >= 14.
openssl genrsa -out rsa_private_unprotected.pem 2048
openssl rsa -in rsa_private_unprotected.pem -out rsa_private.pem -aes256 -passout 'pass:password'
openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem -passin 'pass:password'
openssl rsa -in rsa_private_unprotected.pem -out rsa_private.pem -aes256 -passout 'pass:wolfprov-iperf-pass'
openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem -passin 'pass:wolfprov-iperf-pass'
# Create a credentials file for iperf
# Username: mario, Password: rossi
echo "mario,bf7a49a846d44b454a5d11e7acfaf13d138bbe0b7483aa3e050879700572709b" > credentials.csv
Expand Down
7 changes: 7 additions & 0 deletions include/wolfprovider/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
#define WP_HAVE_DRBG_RESEED
#endif

/* The PKCS#8 encrypt/decrypt helpers need PKCS#8 and password-based key
* derivation. wolfSSL derives WOLFSSL_ENCRYPTED_KEYS from OPENSSL_EXTRA, which
* a FIPS build does not set even though both are present. */
#if defined(HAVE_PKCS8) && !defined(NO_PWDBASED)
#define WP_HAVE_PKCS8_ENC
#endif

#define WP_HAVE_DIGEST
#if !defined(NO_MD5)
#define WP_HAVE_MD5
Expand Down
7 changes: 5 additions & 2 deletions src/wp_dec_pem2der.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,17 +320,20 @@ static int wp_pem2der_decode_data(const unsigned char* data, word32 len,
dataFormat = "type-specific";
obj = OSSL_OBJECT_PKEY;
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
else if (XMEMCMP(data, "-----BEGIN ENCRYPTED PRIVATE KEY-----", 37) == 0) {
type = PKCS8_ENC_PRIVATEKEY_TYPE;
dataType = NULL;
dataFormat = "PrivateKeyInfo";
obj = OSSL_OBJECT_PKEY;

/* The body is base64 only; the PBES2 layer is decrypted later by the
* EncryptedPrivateKeyInfo decoder. The callback fields exist only when
* wolfSSL itself was built with encrypted-key support. */
#ifdef WOLFSSL_ENCRYPTED_KEYS
info.passwd_cb = wp_pem_password_cb;
info.passwd_userdata = (void*)&wpPwCb;
}
#endif
}
else {
ok = 0;
}
Expand Down
99 changes: 77 additions & 22 deletions src/wp_dh_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2359,7 +2359,7 @@ static int wp_dh_dec_send_params(wp_Dh* dh, OSSL_CALLBACK *dataCb,
return ok;
}

#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/**
* Decode an encrypted PKCS#8 DER DH private key into the DH key object.
*
Expand Down Expand Up @@ -2476,7 +2476,7 @@ static int wp_dh_decode(wp_DhEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
if (!wp_dh_decode_pki(dh, data, len)) {
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
if (!wp_dh_decode_enc_pki(dh, data, len, pwCb, pwCbArg))
#endif
{
Expand Down Expand Up @@ -2637,20 +2637,18 @@ static int wp_dh_encode_spki(const wp_Dh *dh, unsigned char* keyData,
}

/**
* Get the PKCS#8 encoding size for the key.
* Copy a generated private key into the inner wolfSSL key if not already set.
*
* @param [in] dh DH key object.
* @param [out] keyLen Length of encoding in bytes.
* @param [in] dh DH key object.
* @return 1 on success.
* @return 0 on failure.
*/
static int wp_dh_encode_pki_size(const wp_Dh *dh, size_t* keyLen)
static int wp_dh_sync_priv_to_key(const wp_Dh *dh)
{
int ok = 1;
int ret;
word32 len;

WOLFPROV_ENTER(WP_LOG_COMP_DH, "wp_dh_encode_pki_size");
WOLFPROV_ENTER(WP_LOG_COMP_DH, "wp_dh_sync_priv_to_key");

/* If we have a generated private key that is not set in the inner key,
* set it now */
Expand All @@ -2662,9 +2660,33 @@ static int wp_dh_encode_pki_size(const wp_Dh *dh, size_t* keyLen)
}
}

ret = wc_DhPrivKeyToDer((DhKey*)&dh->key, NULL, &len);
if (ret != LENGTH_ONLY_E) {
ok = 0;
WOLFPROV_LEAVE(WP_LOG_COMP_DH, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok);
return ok;
}

/**
* Get the PKCS#8 encoding size for the key.
*
* @param [in] dh DH key object.
* @param [out] keyLen Length of encoding in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
static int wp_dh_encode_pki_size(const wp_Dh *dh, size_t* keyLen)
{
int ok = 1;
int ret;
word32 len;

WOLFPROV_ENTER(WP_LOG_COMP_DH, "wp_dh_encode_pki_size");

ok = wp_dh_sync_priv_to_key(dh);

if (ok) {
ret = wc_DhPrivKeyToDer((DhKey*)&dh->key, NULL, &len);
if (ret != LENGTH_ONLY_E) {
ok = 0;
}
}
if (ok) {
*keyLen = len;
Expand All @@ -2684,6 +2706,14 @@ static int wp_dh_encode_pki_size(const wp_Dh *dh, size_t* keyLen)
* @return 1 on success.
* @return 0 on failure.
*/
/* wolfSSL calculating it wrong. */
static void wp_dh_fix_pki_len(unsigned char* keyData, word32 len)
{
if (keyData[1] == 0x81) {
keyData[2] = (unsigned char)(len - 3);
}
}

static int wp_dh_encode_pki(const wp_Dh *dh, unsigned char* keyData,
size_t* keyLen)
{
Expand All @@ -2699,17 +2729,14 @@ static int wp_dh_encode_pki(const wp_Dh *dh, unsigned char* keyData,
}
if (ok) {
*keyLen = len;
/* wolfSSL calculating it wrong. */
if (keyData[1] == 0x81) {
keyData[2] = len - 3;
}
wp_dh_fix_pki_len(keyData, len);
}

WOLFPROV_LEAVE(WP_LOG_COMP_DH, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok);
return ok;
}

#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/**
* Get the Encrypted PKCS#8 encoding size for the key.
*
Expand All @@ -2728,10 +2755,14 @@ static int wp_dh_encode_epki_size(const wp_DhEncDecCtx* ctx, const wp_Dh *dh,

WOLFPROV_ENTER(WP_LOG_COMP_DH, "wp_dh_encode_epki_size");

/* Get the plaintext PKCS #8 length. */
ret = wc_DhPrivKeyToDer((DhKey*)&dh->key, NULL, &len);
if (ret != LENGTH_ONLY_E) {
ok = 0;
ok = wp_dh_sync_priv_to_key(dh);

if (ok) {
/* Get the plaintext PKCS #8 length. */
ret = wc_DhPrivKeyToDer((DhKey*)&dh->key, NULL, &len);
if (ret != LENGTH_ONLY_E) {
ok = 0;
}
}
if (ok) {
/* Get the size of the PBES2 EncryptedPrivateKeyInfo encoding. */
Expand Down Expand Up @@ -2785,6 +2816,11 @@ static int wp_dh_encode_epki(const wp_DhEncDecCtx* ctx, const wp_Dh *dh,
ok = 0;
}
}
if (ok) {
/* Same length correction the plaintext encoder applies, so the
* encrypted body wraps an identical PKCS#8. */
wp_dh_fix_pki_len(encodedKey, pkcs8Len);
}
if (ok) {
/* Encrypt as a PBES2 EncryptedPrivateKeyInfo. */
ok = wp_encrypt_key_pkcs8(ctx->provCtx, ctx->cipher, encodedKey,
Expand Down Expand Up @@ -2861,11 +2897,20 @@ static int wp_dh_encode(wp_DhEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
private = 1;
#ifdef WP_HAVE_PKCS8_ENC
/* A cipher on a PrivateKeyInfo encoder selects the encrypted form. */
if (ctx->cipherName != NULL) {
if (!wp_dh_encode_epki_size(ctx, key, &derLen)) {
ok = 0;
}
}
else
#endif
if (!wp_dh_encode_pki_size(key, &derLen)) {
ok = 0;
}
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
else if (ok && (ctx->format == WP_ENC_FORMAT_EPKI)) {
private = 1;
if (!wp_dh_encode_epki_size(ctx, key, &derLen)) {
Expand Down Expand Up @@ -2896,11 +2941,21 @@ static int wp_dh_encode(wp_DhEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
private = 1;
#ifdef WP_HAVE_PKCS8_ENC
if (ctx->cipherName != NULL) {
pemType = PKCS8_ENC_PRIVATEKEY_TYPE;
if (!wp_dh_encode_epki(ctx, key, derData, &derLen, pwCb,
pwCbArg)) {
ok = 0;
}
}
else
#endif
if (!wp_dh_encode_pki(key, derData, &derLen)) {
ok = 0;
}
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
else if (ok && (ctx->format == WP_ENC_FORMAT_EPKI)) {
private = 1;
pemType = PKCS8_ENC_PRIVATEKEY_TYPE;
Expand Down
38 changes: 33 additions & 5 deletions src/wp_ecc_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2337,7 +2337,7 @@ static int wp_ecc_dec_send_params(wp_Ecc* ecc, OSSL_CALLBACK *dataCb,
return ok;
}

#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/**
* Decode an encrypted PKCS#8 DER ECC private key into the ECC key object.
*
Expand Down Expand Up @@ -2451,7 +2451,7 @@ static int wp_ecc_decode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
if (!wp_ecc_decode_pki(ecc, data, len)) {
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
if (!wp_ecc_decode_enc_pki(ecc, data, len, pwCb, pwCbArg))
#endif
{
Expand Down Expand Up @@ -2795,7 +2795,7 @@ static int wp_ecc_encode_pki(const wp_Ecc *ecc, unsigned char* keyData,
return ok;
}

#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/**
* Get the Encrypted PKCS#8 encoding size for the key.
*
Expand Down Expand Up @@ -2931,6 +2931,15 @@ static int wp_ecc_encode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
ok = 0;
}

/* Traditional PEM encryption is not implemented, so refuse a cipher here
* rather than write the private key in the clear. */
if (ok && ((ctx->format == WP_ENC_FORMAT_TYPE_SPECIFIC) ||
(ctx->format == WP_ENC_FORMAT_X9_62)) &&
(ctx->cipherName != NULL) &&
((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)) {
ok = 0;
}

if (ok && ((ctx->format == WP_ENC_FORMAT_TYPE_SPECIFIC) ||
(ctx->format == WP_ENC_FORMAT_X9_62))) {
if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
Expand All @@ -2957,11 +2966,20 @@ static int wp_ecc_encode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
private = 1;
#ifdef WP_HAVE_PKCS8_ENC
/* A cipher on a PrivateKeyInfo encoder selects the encrypted form. */
if (ctx->cipherName != NULL) {
if (!wp_ecc_encode_epki_size(ctx, key, &derLen)) {
ok = 0;
}
}
else
#endif
if (!wp_ecc_encode_pki_size(key, &derLen)) {
ok = 0;
}
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
else if (ok && (ctx->format == WP_ENC_FORMAT_EPKI)) {
private = 1;
if (!wp_ecc_encode_epki_size(ctx, key, &derLen)) {
Expand Down Expand Up @@ -3008,11 +3026,21 @@ static int wp_ecc_encode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
}
else if (ok && (ctx->format == WP_ENC_FORMAT_PKI)) {
private = 1;
#ifdef WP_HAVE_PKCS8_ENC
if (ctx->cipherName != NULL) {
pemType = PKCS8_ENC_PRIVATEKEY_TYPE;
if (!wp_ecc_encode_epki(ctx, key, derData, &derLen, pwCb,
pwCbArg)) {
ok = 0;
}
}
else
#endif
if (!wp_ecc_encode_pki(key, derData, &derLen)) {
ok = 0;
}
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
else if (ok && (ctx->format == WP_ENC_FORMAT_EPKI)) {
private = 1;
pemType = PKCS8_ENC_PRIVATEKEY_TYPE;
Expand Down
12 changes: 9 additions & 3 deletions src/wp_ecx_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2031,7 +2031,7 @@ static int wp_ecx_dec_send_params(wp_Ecx* ecx, const char* dataType,
return ok;
}

#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/**
* Decode an encrypted PKCS#8 DER ECX private key into the ECX key object.
*
Expand Down Expand Up @@ -2152,7 +2152,7 @@ static int wp_ecx_decode(wp_EcxEncDecCtx* ctx, OSSL_CORE_BIO* cBio,
if (ok) {
rc = ctx->decode(data, &idx, (void*)&ecx->key, len);
if (rc != 0) {
#ifdef WOLFSSL_ENCRYPTED_KEYS
#ifdef WP_HAVE_PKCS8_ENC
/* May be an encrypted PKCS#8 key - decrypt and retry. */
if ((ctx->format != WP_ENC_FORMAT_PKI) ||
(!wp_ecx_decode_enc_pki(ctx, ecx, data, len, pwCb, pwCbArg)))
Expand Down Expand Up @@ -2249,7 +2249,13 @@ static int wp_ecx_encode(wp_EcxEncDecCtx* ctx, OSSL_CORE_BIO *cBio,
/* By default the plaintext DER is the source for the output encoding. */
srcData = derData;
srcLen = derLen;
if (ok && (ctx->format == WP_ENC_FORMAT_EPKI)) {
/* A cipher on a PrivateKeyInfo encoder selects the encrypted form. */
if (ok && ((ctx->format == WP_ENC_FORMAT_EPKI)
#ifdef WP_HAVE_PKCS8_ENC
|| ((ctx->format == WP_ENC_FORMAT_PKI) &&
(ctx->cipherName != NULL))
#endif
)) {
pemType = PKCS8_ENC_PRIVATEKEY_TYPE;
/* The PBES2 output is larger than the plaintext and must use a
* separate buffer, so size it and encrypt into fresh memory. */
Expand Down
Loading
Loading