From b7eca574bb161da06c59c310f4e84e9d8d507786 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 22 Apr 2024 12:28:36 +1000 Subject: [PATCH] SSL/TLS: blind private key DER When WOLFSSL_BLIND_PRIVATE_KEY is defined, blind the private key DER encoding so that stored private key data is always changing. --- src/internal.c | 151 +++++++++++++++++++++++++++++++++++++- src/pk.c | 3 +- src/ssl.c | 155 ++++++++++++++++++++++++++++++++++++---- src/ssl_load.c | 60 ++++++++++++++-- src/tls13.c | 25 ++++++- wolfcrypt/src/ecc.c | 11 +++ wolfssl/internal.h | 17 +++++ wolfssl/wolfcrypt/ecc.h | 5 +- 8 files changed, 403 insertions(+), 24 deletions(-) diff --git a/src/internal.c b/src/internal.c index 38cd26e9d..1bf5963ae 100644 --- a/src/internal.c +++ b/src/internal.c @@ -266,6 +266,49 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif /* !WOLFSSL_NO_TLS12 */ +#if !defined(NO_CERT) && defined(WOLFSSL_BLIND_PRIVATE_KEY) +int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, DerBuffer** mask) +{ + int ret = 0; + WC_RNG local_rng; + + if (key != NULL) { + if (*mask != NULL) { + FreeDer(mask); + } + ret = AllocDer(mask, key->length, key->type, key->heap); + if ((ret == 0) && (rng == NULL)) { + if (wc_InitRng(&local_rng) != 0) { + ret = RNG_FAILURE_E; + } + else { + rng = &local_rng; + } + } + if (ret == 0) { + ret = wc_RNG_GenerateBlock(rng, (*mask)->buffer, (*mask)->length); + } + if (ret == 0) { + xorbuf(key->buffer, (*mask)->buffer, (*mask)->length); + } + + if (rng == &local_rng) { + wc_FreeRng(rng); + } + } + + return ret; +} + +void wolfssl_priv_der_unblind(DerBuffer* key, DerBuffer* mask) +{ + if (key != NULL) { + xorbuf(key->buffer, mask->buffer, mask->length); + } +} +#endif + + #if defined(WOLFSSL_RENESAS_FSPSM_TLS) || defined(WOLFSSL_RENESAS_TSIP_TLS) #include #endif @@ -2604,11 +2647,17 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) ForceZero(ctx->privateKey->buffer, ctx->privateKey->length); } FreeDer(&ctx->privateKey); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ctx->privateKeyMask); +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS if (ctx->altPrivateKey != NULL && ctx->altPrivateKey->buffer != NULL) { ForceZero(ctx->altPrivateKey->buffer, ctx->altPrivateKey->length); } FreeDer(&ctx->altPrivateKey); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ctx->altPrivateKeyMask); +#endif #endif /* WOLFSSL_DUAL_ALG_CERTS */ #ifdef OPENSSL_ALL wolfSSL_EVP_PKEY_free(ctx->privateKeyPKey); @@ -6763,14 +6812,45 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = ctx->certChainCnt; #endif +#ifndef WOLFSSL_BLIND_PRIVATE_KEY ssl->buffers.key = ctx->privateKey; +#else + if (ctx->privateKey != NULL) { + AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer, + ctx->privateKey->length, ctx->privateKey->type, + ctx->privateKey->heap); + ssl->buffers.weOwnKey = 1; + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.key, ctx->privateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + if (ret != 0) { + return ret; + } + } +#endif ssl->buffers.keyType = ctx->privateKeyType; ssl->buffers.keyId = ctx->privateKeyId; ssl->buffers.keyLabel = ctx->privateKeyLabel; ssl->buffers.keySz = ctx->privateKeySz; ssl->buffers.keyDevId = ctx->privateKeyDevId; #ifdef WOLFSSL_DUAL_ALG_CERTS - ssl->buffers.altKey = ctx->altPrivateKey; +#ifndef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKey = ctx->altPrivateKey; +#else + if (ctx->altPrivateKey != NULL) { + AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer, + ctx->altPrivateKey->length, ctx->altPrivateKey->type, + ctx->altPrivateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.altKey, ctx->altPrivateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + if (ret != 0) { + return ret; + } + } +#endif ssl->buffers.altKeyType = ctx->altPrivateKeyType; ssl->buffers.altKeyId = ctx->altPrivateKeyId; ssl->buffers.altKeyLabel = ctx->altPrivateKeyLabel; @@ -8518,8 +8598,14 @@ void FreeHandshakeResources(WOLFSSL* ssl) } #endif /* !NO_DH */ -#ifndef NO_CERTS - wolfSSL_UnloadCertsKeys(ssl); +#if !defined(NO_CERTS) && !defined(OPENSSL_EXTRA) && \ + !defined(WOLFSSL_WPAS_SMALL) +#ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side != WOLFSSL_CLIENT_END) +#endif + { + wolfSSL_UnloadCertsKeys(ssl); + } #endif #ifdef HAVE_PK_CALLBACKS #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) @@ -28322,6 +28408,10 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length) ERROR_OUT(NO_PRIVATE_KEY, exit_dapk); } +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.altKey, ssl->buffers.altKeyMask); +#endif + #ifdef WOLF_PRIVATE_KEY_ID if (ssl->buffers.altKeyDevId != INVALID_DEVID && (ssl->buffers.altKeyId || ssl->buffers.altKeyLabel)) { @@ -28724,6 +28814,16 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length) (void)length; exit_dapk: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif + if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); } @@ -32746,6 +32846,10 @@ int SendCertificateVerify(WOLFSSL* ssl) WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); WOLFSSL_ENTER("SendCertificateVerify"); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + #ifdef WOLFSSL_ASYNC_IO if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -32792,6 +32896,10 @@ int SendCertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, + ssl->buffers.keyMask); + #endif return 0; /* sent blank cert, can't verify */ } @@ -33196,6 +33304,15 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* switch(ssl->options.asyncState) */ exit_scv: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif WOLFSSL_LEAVE("SendCertificateVerify", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); @@ -33859,6 +33976,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); WOLFSSL_ENTER("SendServerKeyExchange"); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + #endif + #ifdef WOLFSSL_ASYNC_IO if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -35415,6 +35536,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, exit_sske: + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } + #endif + WOLFSSL_LEAVE("SendServerKeyExchange", ret); WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); @@ -38937,6 +39068,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); WOLFSSL_ENTER("DoClientKeyExchange"); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + #endif + #ifdef WOLFSSL_ASYNC_CRYPT if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -40131,6 +40266,16 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], exit_dcke: + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } + #endif + WOLFSSL_LEAVE("DoClientKeyExchange", ret); WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); #ifdef WOLFSSL_ASYNC_CRYPT diff --git a/src/pk.c b/src/pk.c index 67f85fd45..02a4c4ae7 100644 --- a/src/pk.c +++ b/src/pk.c @@ -11704,7 +11704,8 @@ static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src) if (ret == 0) { /* Copy private key. */ - ret = mp_copy(wc_ecc_key_get_priv(src), wc_ecc_key_get_priv(dst)); + ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src), + wc_ecc_key_get_priv(dst)); if (ret != MP_OKAY) { WOLFSSL_MSG("mp_copy error"); } diff --git a/src/ssl.c b/src/ssl.c index 641235066..4d7188665 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6339,20 +6339,54 @@ static int check_cert_key(DerBuffer* cert, DerBuffer* key, DerBuffer* altKey, * WOLFSSL_FAILURE if mismatched. */ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) { + int res; + if (ctx == NULL) { return WOLFSSL_FAILURE; } #ifdef WOLFSSL_DUAL_ALG_CERTS - return check_cert_key(ctx->certificate, ctx->privateKey, ctx->altPrivateKey, +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + wolfssl_priv_der_unblind(ctx->altPrivateKey, ctx->altPrivateKeyMask); +#endif + res = check_cert_key(ctx->certificate, ctx->privateKey, ctx->altPrivateKey, ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId, ctx->altPrivateKeyDevId, ctx->altPrivateKeyLabel, - ctx->altPrivateKeyId); + ctx->altPrivateKeyId) != 0 +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + { + int ret; + ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + (DerBuffer**)&ctx->privateKeyMask); + if (ret == 0) { + ret = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey, + (DerBuffer**)&ctx->altPrivateKeyMask); + } + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } +#endif #else - return check_cert_key(ctx->certificate, ctx->privateKey, NULL, ctx->heap, +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); +#endif + res = check_cert_key(ctx->certificate, ctx->privateKey, NULL, ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId, INVALID_DEVID, 0, 0); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + { + int ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + (DerBuffer**)&ctx->privateKeyMask); + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } #endif +#endif + + return res; } #endif /* !NO_CHECK_PRIVATE_KEY */ @@ -6363,6 +6397,7 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) */ WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx) { + WOLFSSL_EVP_PKEY* res; const unsigned char *key; int type; @@ -6399,12 +6434,22 @@ WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx) key = ctx->privateKey->buffer; - if (ctx->privateKeyPKey != NULL) - return ctx->privateKeyPKey; - else - return wolfSSL_d2i_PrivateKey(type, + if (ctx->privateKeyPKey != NULL) { + res = ctx->privateKeyPKey; + } + else { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + #endif + res = wolfSSL_d2i_PrivateKey(type, (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key, (long)ctx->privateKey->length); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + #endif + } + + return res; } #endif @@ -7584,19 +7629,53 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out, * WOLFSSL_FAILURE if mismatched. */ int wolfSSL_check_private_key(const WOLFSSL* ssl) { + int res = WOLFSSL_SUCCESS; + if (ssl == NULL) { return WOLFSSL_FAILURE; } #ifdef WOLFSSL_DUAL_ALG_CERTS - return check_cert_key(ssl->buffers.certificate, ssl->buffers.key, +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + wolfssl_priv_der_unblind(ssl->buffers.altKey, ssl->buffers.altKeyMask); +#endif + res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key, ssl->buffers.altKey, ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel, ssl->buffers.keyId, ssl->buffers.altKeyDevId, ssl->buffers.altKeyLabel, ssl->buffers.altKeyId); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (res == WOLFSSL_SUCCESS) { + int ret; + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + (DerBuffer**)&ssl->buffers.keyMask); + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + (DerBuffer**)&ssl->buffers.altKeyMask); + } + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } +#endif #else - return check_cert_key(ssl->buffers.certificate, ssl->buffers.key, NULL, +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key, NULL, ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel, ssl->buffers.keyId, INVALID_DEVID, 0, 0); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (res == WOLFSSL_SUCCESS) { + int ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + (DerBuffer**)&ssl->buffers.keyMask); + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } #endif +#endif + + return res; } #endif /* !NO_CHECK_PRIVATE_KEY */ @@ -10726,6 +10805,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("Unloading key"); ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif ssl->buffers.weOwnKey = 0; } @@ -10734,6 +10816,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("Unloading alt key"); ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length); FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif ssl->buffers.weOwnAltKey = 0; } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -19405,18 +19490,32 @@ void wolfSSL_certs_clear(WOLFSSL* ssl) #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = 0; #endif - if (ssl->buffers.weOwnKey) + if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif + } ssl->buffers.key = NULL; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.keyMask = NULL; +#endif ssl->buffers.keyType = 0; ssl->buffers.keyId = 0; ssl->buffers.keyLabel = 0; ssl->buffers.keySz = 0; ssl->buffers.keyDevId = 0; #ifdef WOLFSSL_DUAL_ALG_CERTS - if (ssl->buffers.weOwnAltKey) + if (ssl->buffers.weOwnAltKey) { FreeDer(&ssl->buffers.altKey); - ssl->buffers.altKey = NULL; + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + } + ssl->buffers.altKey = NULL; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKeyMask = NULL; +#endif #endif /* WOLFSSL_DUAL_ALG_CERTS */ } #endif @@ -19985,7 +20084,22 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = ctx->certChainCnt; #endif +#ifndef WOLFSSL_BLIND_PRIVATE_KEY ssl->buffers.key = ctx->privateKey; +#else + if (ctx->privateKey != NULL) { + AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer, + ctx->privateKey->length, ctx->privateKey->type, + ctx->privateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.key, ctx->privateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + if (ret != 0) { + return ret; + } + } +#endif ssl->buffers.keyType = ctx->privateKeyType; ssl->buffers.keyId = ctx->privateKeyId; ssl->buffers.keyLabel = ctx->privateKeyLabel; @@ -20000,7 +20114,22 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.haveFalconSig = ctx->haveFalconSig; ssl->options.haveDilithiumSig = ctx->haveDilithiumSig; #ifdef WOLFSSL_DUAL_ALG_CERTS - ssl->buffers.altKey = ctx->altPrivateKey; +#ifndef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKey = ctx->altPrivateKey; +#else + if (ctx->altPrivateKey != NULL) { + AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer, + ctx->altPrivateKey->length, ctx->altPrivateKey->type, + ctx->altPrivateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.altKey, ctx->altPrivateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + if (ret != 0) { + return ret; + } + } +#endif ssl->buffers.altKeySz = ctx->altPrivateKeySz; ssl->buffers.altKeyType = ctx->altPrivateKeyType; #endif /* WOLFSSL_DUAL_ALG_CERTS */ diff --git a/src/ssl_load.c b/src/ssl_load.c index 5e011fab0..f3f6ce3b9 100644 --- a/src/ssl_load.c +++ b/src/ssl_load.c @@ -1243,10 +1243,13 @@ static int ProcessBufferPrivPkcs8Dec(EncryptedInfo* info, DerBuffer* der, * @param [in, out] ctx SSL context object. * @param [in, out] ssl SSL object. * @param [in] der DER encoding. + * @return 0 on success. */ -static void ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, +static int ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer** der, int type) { + int ret = 0; + (void)type; #ifdef WOLFSSL_DUAL_ALG_CERTS @@ -1256,6 +1259,9 @@ static void ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, /* Dispose of previous key if not context's. */ if (ssl->buffers.weOwnAltKey) { FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif } ssl->buffers.altKeyId = 0; ssl->buffers.altKeyLabel = 0; @@ -1286,6 +1292,9 @@ static void ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, /* Dispose of previous key if not context's. */ if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } ssl->buffers.keyId = 0; ssl->buffers.keyLabel = 0; @@ -1309,6 +1318,8 @@ static void ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length); #endif } + + return ret; } /* Decode private key. @@ -1352,9 +1363,11 @@ static int ProcessBufferPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, #endif /* Put the data into the SSL or SSL context object. */ - ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type); - /* Try to decode the DER data. */ - ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type); + ret = ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type); + if (ret == 0) { + /* Try to decode the DER data. */ + ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type); + } #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) /* If private key type PKCS8 header wasn't already removed (algId == 0). */ @@ -1369,6 +1382,30 @@ static int ProcessBufferPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, } #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ +#ifdef WOLFSSL_BLIND_PRIVATE_KEY +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (type == ALT_PRIVATEKEY_TYPE) { + if (ssl != NULL) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + } + else { + ret = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey, + &ctx->altPrivateKeyMask); + } + } + else +#endif + if (ssl != NULL) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + &ctx->privateKeyMask); + } +#endif + /* Check if we were able to determine algorithm id. */ if ((ret == 0) && (algId == 0)) { #ifdef OPENSSL_EXTRA @@ -4257,6 +4294,9 @@ int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, /* Dispose of old private key if owned and allocate and copy in id. */ if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } if (AllocCopyDer(&ssl->buffers.key, id, (word32)sz, PRIVATEKEY_TYPE, ssl->heap) != 0) { @@ -4324,6 +4364,9 @@ int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) /* Dispose of old private key if owned and allocate and copy in label. */ if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } if (AllocCopyDer(&ssl->buffers.key, (const byte*)label, (word32)sz, PRIVATEKEY_TYPE, ssl->heap) != 0) { @@ -4366,6 +4409,9 @@ int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, long sz, if (ret == 1) { if (ssl->buffers.weOwnAltKey) { FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif } if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE, ssl->heap) == 0) { @@ -4409,8 +4455,12 @@ int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) if (ret == 1) { sz = (word32)XSTRLEN(label) + 1; - if (ssl->buffers.weOwnAltKey) + if (ssl->buffers.weOwnAltKey) { FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + } if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE, ssl->heap) == 0) { ret = 0; diff --git a/src/tls13.c b/src/tls13.c index 37c5ebdcc..951ca5a34 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8803,6 +8803,10 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); WOLFSSL_ENTER("SendTls13CertificateVerify"); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + ssl->options.buildingMsg = 1; #if defined(WOLFSSL_RENESAS_TSIP_TLS) @@ -8855,6 +8859,10 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, + ssl->buffers.keyMask); + #endif return 0; /* sent blank cert, can't verify */ } @@ -8915,10 +8923,16 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) /* If we own it, free key before overriding it. */ if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } /* Swap keys */ - ssl->buffers.key = ssl->buffers.altKey; + ssl->buffers.key = ssl->buffers.altKey; + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.keyMask = ssl->buffers.altKeyMask; + #endif ssl->buffers.weOwnKey = ssl->buffers.weOwnAltKey; } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -9543,6 +9557,15 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) } /* switch(ssl->options.asyncState) */ exit_scv: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 2bd410436..a58c239a3 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -98,6 +98,12 @@ Possible ECC enable options: * Use this when CPU state can be closely observed by * attacker. * default: off + * WOLFSSL_ECC_BLIND_K + * Blind the private key k by using a random mask. + * The private key is never stored unprotected but an + * unmasked copy is computed and stored each time it is + * needed. + * default: off */ /* @@ -337,6 +343,11 @@ int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng) } return ret; } + +mp_int* wc_ecc_key_get_priv(ecc_key* key) +{ + return ecc_get_k(key); +} #endif /* forward declarations */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 28b72877b..c2d412986 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2180,6 +2180,11 @@ WOLFSSL_LOCAL int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, int label, int id, void* heap, int devId); #endif +#ifdef WOLFSSL_BLIND_PRIVATE_KEY +WOLFSSL_LOCAL int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, + DerBuffer** mask); +WOLFSSL_LOCAL void wolfssl_priv_der_unblind(DerBuffer* key, DerBuffer* mask); +#endif WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word32* length); #ifdef WOLFSSL_DUAL_ALG_CERTS WOLFSSL_LOCAL int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length); @@ -3574,6 +3579,9 @@ struct WOLFSSL_CTX { int certChainCnt; #endif DerBuffer* privateKey; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* privateKeyMask; /* Mask of private key DER. */ +#endif byte privateKeyType; byte privateKeyId:1; byte privateKeyLabel:1; @@ -3582,6 +3590,9 @@ struct WOLFSSL_CTX { #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altPrivateKey; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* altPrivateKeyMask; /* Mask of alt private key DER. */ +#endif byte altPrivateKeyType; byte altPrivateKeyId:1; byte altPrivateKeyLabel:1; @@ -4553,6 +4564,9 @@ typedef struct Buffers { #ifndef NO_CERTS DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* keyMask; /* Mask of private key DER. */ +#endif byte keyType; /* Type of key */ byte keyId:1; /* Key data is an id not data */ byte keyLabel:1; /* Key data is a label not data */ @@ -4560,6 +4574,9 @@ typedef struct Buffers { int keyDevId; /* Device Id for key */ #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altKey; /* WOLFSSL_CTX owns, unless we own */ +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* altKeyMask; /* Mask of alt private key DER. */ +#endif byte altKeyType; /* Type of alt key */ byte altKeyId:1; /* Key data is an id not data */ byte altKeyLabel:1; /* Key data is a label not data */ diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ecad0b623..48a43f63c 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -613,13 +613,16 @@ struct ecc_key { #define ecc_get_k(key) (key)->k #define ecc_blind_k(key, b) (void)b #define ecc_blind_k_rng(key, rng) 0 + +#define wc_ecc_key_get_priv(key) (key)->k #else mp_int* ecc_get_k(ecc_key* key); void ecc_blind_k(ecc_key* key, mp_int* b); int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng); + +WOLFSSL_API mp_int* wc_ecc_key_get_priv(ecc_key* key); #endif -#define wc_ecc_key_get_priv(key) (ecc_get_k(key)) #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV