diff --git a/src/internal.c b/src/internal.c index 38cd26e9d8..1bf5963aee 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 67f85fd453..02a4c4ae7b 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 6412350665..4d71886658 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 5e011fab0e..f3f6ce3b9b 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 37c5ebdccf..951ca5a34a 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 b29c19ecce..a58c239a37 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 */ /* @@ -297,6 +303,53 @@ ECC Curve Sizes: #endif +#ifdef WOLFSSL_ECC_BLIND_K +mp_int* ecc_get_k(ecc_key* key) +{ + mp_xor_ct(key->k, key->kb, key->dp->size, key->ku); + return key->ku; +} +void ecc_blind_k(ecc_key* key, mp_int* b) +{ + mp_xor_ct(key->k, b, key->dp->size, key->k); + mp_xor_ct(key->kb, b, key->dp->size, key->kb); +} +int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng) +{ + int ret = 0; + WC_RNG local_rng; + +#ifdef ECC_TIMING_RESISTANT + if (rng == NULL) { + rng = key->rng; + } +#endif + if (rng == NULL) { + ret = wc_InitRng(&local_rng); + if (ret == 0) { + rng = &local_rng; + } + } + if (ret == 0) { + ret = mp_rand(key->kb, (key->dp->size + sizeof(mp_digit) - 1) / + sizeof(mp_digit), rng); + if (ret == 0) { + mp_xor_ct(key->k, key->kb, key->dp->size, key->k); + } + } + + if (rng == &local_rng) { + wc_FreeRng(&local_rng); + } + return ret; +} + +mp_int* wc_ecc_key_get_priv(ecc_key* key) +{ + return ecc_get_k(key); +} +#endif + /* forward declarations */ static int wc_ecc_new_point_ex(ecc_point** point, void* heap); static void wc_ecc_del_point_ex(ecc_point* p, void* heap); @@ -4693,7 +4746,7 @@ int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, byte* out, word32* outlen) { int err = MP_OKAY; - mp_int* k = private_key->k; + mp_int* k = ecc_get_k(private_key); #ifdef HAVE_ECC_CDH #ifdef WOLFSSL_SMALL_STACK mp_int *k_lcl = NULL; @@ -4723,7 +4776,7 @@ int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, goto errout; } /* multiply cofactor times private key "k" */ - err = mp_mul_d(private_key->k, cofactor, k); + err = mp_mul_d(ecc_get_k(private_key), cofactor, k); if (err != MP_OKAY) goto errout; } @@ -4964,7 +5017,8 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, word32 keySz = private_key->dp->size; /* sync public key x/y */ - err = wc_mp_to_bigint_sz(private_key->k, &private_key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(private_key), + &ecc_get_k(private_key)->raw, keySz); if (err == MP_OKAY) err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz); if (err == MP_OKAY) @@ -4978,7 +5032,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, NitroxEccGetSize(private_key)*2); if (err == MP_OKAY) err = NitroxEcdh(private_key, - &private_key->k->raw, &point->x->raw, &point->y->raw, + &ecc_get_k(private_key)->raw, &point->x->raw, &point->y->raw, private_key->e->raw.buf, &private_key->e->raw.len, &curve->prime->raw); #else @@ -4986,7 +5040,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); if (err == MP_OKAY) err = IntelQaEcdh(&private_key->asyncDev, - &private_key->k->raw, &point->x->raw, &point->y->raw, + &ecc_get_k(private_key)->raw, &point->x->raw, &point->y->raw, out, outlen, &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, private_key->dp->cofactor); @@ -5371,9 +5425,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, key->type = ECC_PRIVATEKEY_ONLY; } - if ((err == MP_OKAY) && (mp_iszero(key->k) || mp_isneg(key->k) || - (mp_cmp(key->k, curve->order) != MP_LT))) - { + if ((err == MP_OKAY) && (mp_iszero(ecc_get_k(key)) || + mp_isneg(ecc_get_k(key)) || + (mp_cmp(ecc_get_k(key), curve->order) != MP_LT))) { err = ECC_PRIV_KEY_E; } @@ -5395,10 +5449,10 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, if (err == MP_OKAY && key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { word32 keySz = key->dp->size; /* sync private key to raw */ - err = wc_mp_to_bigint_sz(key->k, &key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(key), &ecc_get_k(key)->raw, keySz); if (err == MP_OKAY) { err = IntelQaEccPointMul(&key->asyncDev, - &key->k->raw, pub->x, pub->y, pub->z, + &ecc_get_k(key)->raw, pub->x, pub->y, pub->z, &curve->Gx->raw, &curve->Gy->raw, &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, key->dp->cofactor); @@ -5414,25 +5468,25 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, else #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - err = sp_ecc_mulmod_base_256(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_256(ecc_get_k(key), pub, 1, key->heap); } else #endif /* WOLFSSL_SP_NO_256 */ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { - err = sp_ecc_mulmod_base_sm2_256(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_sm2_256(ecc_get_k(key), pub, 1, key->heap); } else #endif #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - err = sp_ecc_mulmod_base_384(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_384(ecc_get_k(key), pub, 1, key->heap); } else #endif #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { - err = sp_ecc_mulmod_base_521(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_521(ecc_get_k(key), pub, 1, key->heap); } else #endif @@ -5464,8 +5518,8 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, /* make the public key */ if (err == MP_OKAY) { /* Map in a separate call as this should be constant time */ - err = wc_ecc_mulmod_ex2(key->k, base, pub, curve->Af, curve->prime, - curve->order, rng, 0, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, pub, curve->Af, + curve->prime, curve->order, rng, 0, key->heap); if (err == MP_MEM) { err = MEMORY_E; } @@ -5720,6 +5774,11 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, if (err == SA_SILIB_RET_OK) { err = mp_read_unsigned_bin(key->k, ucompressed_key, raw_size); +#ifdef WOLFSSL_ECC_BLIND_K + if (err == MP_OKAY) { + err = ecc_blind_k_rng(key, rng); + } +#endif } #elif defined(WOLFSSL_SILABS_SE_ACCEL) @@ -5771,7 +5830,12 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, err = xil_mpi_import(key->pubkey.y, key->keyRaw + key->dp->size, key->dp->size, key->heap); if (err == 0) - err = xil_mpi_import(key->k, key->privKey, key->dp->size, key->heap); + err = xil_mpi_import(key->k, key->privKey, key->dp->size, + key->heap); +#ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) + err = ecc_blind_k_rng(key, rng); +#endif if (err == 0) err = mp_set(key->pubkey.z, 1); if (err) { @@ -5953,6 +6017,11 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw); #endif +#ifdef WOLFSSL_ECC_BLIND_K + if (err == MP_OKAY) + err = ecc_blind_k_rng(key, rng); +#endif + #endif /* HAVE_ECC_MAKE_PUB */ return err; @@ -6140,13 +6209,27 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); +#ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kia; + alt_fp_init(key->kb); + alt_fp_init(key->ku); +#endif #else ret = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL); +#ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL +#else + key->kb, key->ku +#endif + ); if (ret != MP_OKAY) { return MEMORY_E; } #endif /* ALT_ECC_SIZE */ +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif #endif /* WOLFSSL_ATECC508A */ #if (defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ @@ -6190,6 +6273,10 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) #ifdef WOLFSSL_CHECK_MEM_ZERO mp_memzero_add("ECC k", key->k); +#ifdef WOLFSSL_ECC_BLIND_K + mp_memzero_add("ECC kb", key->kb); + mp_memzero_add("ECC ku", key->ku); +#endif #endif #if defined(WOLFSSL_XILINX_CRYPT_VERSAL) @@ -6750,7 +6837,7 @@ static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key) /* currently limiting to SHA256 for auto create */ if (mp_init(key->sign_k) != MP_OKAY || wc_ecc_gen_deterministic_k(in, inlen, - WC_HASH_TYPE_SHA256, key->k, key->sign_k, + WC_HASH_TYPE_SHA256, ecc_get_k(key), key->sign_k, curve->order, key->heap) != 0) { mp_free(key->sign_k); XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); @@ -6769,8 +6856,8 @@ static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key) #else key->sign_k_set = 0; /* currently limiting to SHA256 for auto create */ - if (wc_ecc_gen_deterministic_k(in, inlen, WC_HASH_TYPE_SHA256, key->k, - key->sign_k, curve->order, key->heap) != 0) { + if (wc_ecc_gen_deterministic_k(in, inlen, WC_HASH_TYPE_SHA256, + ecc_get_k(key), key->sign_k, curve->order, key->heap) != 0) { err = ECC_PRIV_KEY_E; } else { @@ -6908,15 +6995,18 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, if (err != MP_OKAY) break; if (mp_iszero(r) == MP_NO) { - mp_int* ep = pubkey->k; - mp_int* kp = pubkey->k; - mp_int* x = key->k; + mp_int* kp = ecc_get_k(pubkey); + mp_int* ep = kp; + mp_int* x = ecc_get_k(key); + + /* Blind after getting. */ + ecc_blind_k(key, b); /* find s = (e + xr)/k = b.(e/k.b + x.r/k.b) */ /* k' = k.b */ - err = mp_mulmod(pubkey->k, b, curve->order, kp); + err = mp_mulmod(kp, b, curve->order, kp); if (err != MP_OKAY) break; /* k' = 1/k.b @@ -6995,12 +7085,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_256_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -7009,8 +7099,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_256(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_256(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7021,8 +7111,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, if (ecc_sets[key->idx].id == ECC_SM2P256V1) { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_sm2_256(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_sm2_256(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7035,12 +7125,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_384_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -7049,8 +7139,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_384(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_384(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7065,12 +7155,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_521_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_521_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -7079,8 +7169,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_521(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_521(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7303,7 +7393,8 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err == MP_OKAY) err = wc_mp_to_bigint_sz(e, &e->raw, keySz); if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(key->k, &key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(key), &ecc_get_k(key)->raw, + keySz); if (err == MP_OKAY) err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order); if (err == MP_OKAY) @@ -7311,14 +7402,15 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #ifdef HAVE_CAVIUM_V if (err == MP_OKAY) - err = NitroxEcdsaSign(key, &e->raw, &key->k->raw, &k->raw, - &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); + err = NitroxEcdsaSign(key, &e->raw, &ecc_get_k(key)->raw, + &k->raw, &r->raw, &s->raw, &curve->prime->raw, + &curve->order->raw); #else if (err == MP_OKAY) - err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k->raw, - &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, - &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, - &curve->Gy->raw); + err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, + &ecc_get_k(key)->raw, &k->raw, &r->raw, &s->raw, + &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, + &curve->order->raw, &curve->Gx->raw, &curve->Gy->raw); #endif #ifndef HAVE_CAVIUM_V @@ -7820,6 +7912,16 @@ int wc_ecc_free(ecc_key* key) if (key->k) #endif mp_forcezero(key->k); +#ifdef WOLFSSL_ECC_BLIND_K +#ifdef ALT_ECC_SIZE + if (key->kb) +#endif + mp_forcezero(key->kb); +#ifdef ALT_ECC_SIZE + if (key->ku) +#endif + mp_forcezero(key->ku); +#endif #ifdef WOLFSSL_CUSTOM_CURVES if (key->deallocSet && key->dp != NULL) @@ -9892,7 +9994,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_256(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_256(ecc_get_k(key), res, 1, key->heap); } } else @@ -9900,7 +10002,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_sm2_256(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_sm2_256(ecc_get_k(key), res, 1, key->heap); } } else @@ -9908,7 +10010,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_384(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_384(ecc_get_k(key), res, 1, key->heap); } } else @@ -9916,7 +10018,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_521(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_521(ecc_get_k(key), res, 1, key->heap); } } else @@ -9969,12 +10071,12 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #else #ifdef ECC_TIMING_RESISTANT if (err == MP_OKAY) - err = wc_ecc_mulmod_ex2(key->k, base, res, a, prime, curve->order, - key->rng, 1, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, res, a, prime, + curve->order, key->rng, 1, key->heap); #else if (err == MP_OKAY) - err = wc_ecc_mulmod_ex2(key->k, base, res, a, prime, curve->order, - NULL, 1, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, res, a, prime, + curve->order, NULL, 1, key->heap); #endif #endif /* WOLFSSL_KCAPI_ECC */ } @@ -10245,31 +10347,31 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { return sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { return sp_ecc_check_key_sm2_256(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { return sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { return sp_ecc_check_key_521(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #if defined(WOLFSSL_SP_1024) && defined(WOLFCRYPT_HAVE_SAKKE) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SAKKE_1) { return sp_ecc_check_key_1024(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #endif @@ -10380,8 +10482,8 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) /* SP 800-56Ar3, section 5.6.2.1.2 */ /* private keys must be in the range [1, n-1] */ if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) && - (mp_iszero(key->k) || mp_isneg(key->k) || - (mp_cmp(key->k, curve->order) != MP_LT)) + (mp_iszero(ecc_get_k(key)) || mp_isneg(ecc_get_k(key)) || + (mp_cmp(ecc_get_k(key), curve->order) != MP_LT)) #ifdef WOLFSSL_KCAPI_ECC && key->handle == NULL #endif @@ -10466,12 +10568,26 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); + #ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kua; + alt_fp_init(key->kb); + alt_fp_init(key->ku); + #endif #else - err = mp_init_multi(key->k, - key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); + err = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + #ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL + #else + key->kb, key->ku + #endif + ); #endif if (err != MP_OKAY) return MEMORY_E; +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif SAVE_VECTOR_REGISTERS(return _svr_ret;); @@ -10780,7 +10896,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, return BUFFER_E; } - err = wc_export_int(key->k, d, dLen, keySz + WC_CAAM_MAC_SZ, + err = wc_export_int(ecc_get_k(key), d, dLen, keySz + WC_CAAM_MAC_SZ, encType); *dLen = keySz + WC_CAAM_MAC_SZ; } @@ -10802,7 +10918,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, else #endif { - err = wc_export_int(key->k, d, dLen, keySz, encType); + err = wc_export_int(ecc_get_k(key), d, dLen, keySz, encType); if (err != MP_OKAY) return err; } @@ -10937,6 +11053,11 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, } ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif } #elif defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) if ((wc_ecc_size(key) + WC_CAAM_MAC_SZ) == (int)privSz) { @@ -10968,11 +11089,21 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, #else key->blackKey = CAAM_BLACK_KEY_CCM; ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif #endif } else { key->blackKey = 0; ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif /* If using AES-ECB encrypted black keys check here if key is valid, * if not valid than assume is an encrypted key. A public key is needed @@ -11001,8 +11132,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, ret = mp_read_unsigned_bin(key->k, priv, privSz); #ifdef HAVE_WOLF_BIGINT - if (ret == 0 && - wc_bigint_from_unsigned_bin(&key->k->raw, priv, privSz) != 0) { + if (ret == 0 && wc_bigint_from_unsigned_bin(&key->k->raw, priv, + privSz) != 0) { mp_clear(key->k); ret = ASN_GETINT_E; } @@ -11044,6 +11175,11 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, #endif } #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */ +#ifdef WOLFSSL_ECC_BLIND_K + if (ret == 0) { + ret = ecc_blind_k_rng(key, NULL); + } +#endif #endif /* WOLFSSL_CRYPTOCELL */ @@ -11236,12 +11372,26 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); +#ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kua; + alt_fp_init(key->kb); + alt_fp_init(key->ku); +#endif #else err = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL); +#ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL +#else + key->kb, key->ku +#endif + ); #endif if (err != MP_OKAY) return MEMORY_E; +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif /* read Qx */ if (err == MP_OKAY) { @@ -11388,6 +11538,11 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = wc_export_int(key->k, &keyRaw[0], &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } + #ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) { + err = ecc_blind_k_rng(key, NULL); + } + #endif if (err == MP_OKAY) { /* Create private key from external key buffer*/ @@ -11419,12 +11574,17 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, (word32)key->dp->size); } } + #ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) { + err = ecc_blind_k_rng(key, NULL); + } + #endif #if defined(WOLFSSL_XILINX_CRYPT_VERSAL) if (err == MP_OKAY) { const word32 key_size = key->dp->size; word32 buf_size = key_size; - err = wc_export_int(key->k, key->privKey, - &buf_size, key_size, WC_TYPE_UNSIGNED_BIN); + err = wc_export_int(key, key->privKey, &buf_size, key_size, + WC_TYPE_UNSIGNED_BIN); mp_reverse(key->privKey, key_size); } #endif diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 83a1306b59..3a6884a337 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -8097,6 +8097,27 @@ int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r) } #endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */ +#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) && \ + defined(WOLFSSL_ECC_BLIND_K) +void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r) +{ + if ((a != NULL) && (b != NULL) && (r != NULL)) { + unsigned int i; + + r->used = (len * 8 + SP_WORD_SIZE - 1) / SP_WORD_SIZE; + for (i = 0; i < r->used; i++) { + r->dp[i] = a->dp[i] ^ b->dp[i]; + } + i = (len * 8) % SP_WORD_SIZE; + if (i > 0) { + r->dp[r->used - 1] &= ((sp_int_digit)1 << i) - 1; + } + /* Remove leading zeros. */ + sp_clamp_ct(r); + } +} +#endif + /******************** * Shifting functoins ********************/ diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c index 11e85cd74b..df5f0f85ff 100644 --- a/wolfcrypt/src/wolfmath.c +++ b/wolfcrypt/src/wolfmath.c @@ -167,7 +167,8 @@ int get_rand_digit(WC_RNG* rng, mp_digit* d) return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); } -#if defined(WC_RSA_BLINDING) || defined(WOLFCRYPT_HAVE_SAKKE) +#if defined(WC_RSA_BLINDING) || defined(WOLFCRYPT_HAVE_SAKKE) || \ + defined(WOLFSSL_ECC_BLIND_K) int mp_rand(mp_int* a, int digits, WC_RNG* rng) { int ret = 0; @@ -221,7 +222,7 @@ int mp_rand(mp_int* a, int digits, WC_RNG* rng) return ret; } -#endif /* WC_RSA_BLINDING || WOLFCRYPT_HAVE_SAKKE */ +#endif /* WC_RSA_BLINDING || WOLFCRYPT_HAVE_SAKKE || WOLFSSL_ECC_BLIND_K */ #endif /* !WC_NO_RNG */ #if defined(HAVE_ECC) || defined(WOLFSSL_EXPORT_INT) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 28b72877b4..c2d412986a 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 73f2fa5602..48a43f63c4 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -501,6 +501,17 @@ struct ecc_key { mp_int* k; alt_fp_int ka[1]; #endif +#ifdef WOLFSSL_ECC_BLIND_K +#ifndef ALT_ECC_SIZE + mp_int kb[1]; + mp_int ku[1]; +#else + mp_int* kb; + mp_int* ku; + alt_fp_int kba[1]; + alt_fp_int kua[1]; +#endif +#endif #ifdef WOLFSSL_CAAM word32 blackKey; /* address of key encrypted and in secure memory */ @@ -598,7 +609,20 @@ struct ecc_key { #endif }; -#define wc_ecc_key_get_priv(key) ((key)->k) +#ifndef WOLFSSL_ECC_BLIND_K +#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 WOLFSSL_HAVE_ECC_KEY_GET_PRIV diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index cf7b8f2894..514b7110fd 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -996,6 +996,9 @@ MP_API int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m, MP_API int sp_addmod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r); #endif +#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) +MP_API void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r); +#endif MP_API int sp_lshd(sp_int* a, int s); #ifdef WOLFSSL_SP_MATH_ALL @@ -1144,6 +1147,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp); #define mp_submod sp_submod #define mp_addmod_ct sp_addmod_ct #define mp_submod_ct sp_submod_ct +#define mp_xor_ct sp_xor_ct #define mp_lshd sp_lshd #define mp_rshd sp_rshd #define mp_div sp_div