From 2cb871c30de8445d4e50d5b4db897e239fd26422 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Sat, 17 Oct 2020 10:44:27 +0900 Subject: [PATCH 1/4] PrivateKey in PemToDer. PR2939 --- src/ssl.c | 20 +++-- src/wolfio.c | 32 +++++--- tests/api.c | 183 +++++++++++++++++++++++++++++++++--------- wolfcrypt/src/asn.c | 152 +++++++++++++++++++++++++++++++---- wolfssl/openssl/ssl.h | 11 ++- wolfssl/ssl.h | 12 +++ wolfssl/wolfio.h | 6 ++ 7 files changed, 343 insertions(+), 73 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 24dd9a87bd4..76f9b38baea 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -29420,21 +29420,29 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, { WOLFSSL_EVP_PKEY* pkey = NULL; DerBuffer* der = NULL; - int eccFlag = 0; + int keyFormat = 0; + int type = -1; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey"); if (bio == NULL) return pkey; - if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &eccFlag, &der) >= 0) { - int type; + if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat, &der) >= 0) { const unsigned char* ptr = der->buffer; - if (eccFlag) - type = EVP_PKEY_EC; - else + if (keyFormat) { + /* keyFormat is Key_Sum enum */ + if (keyFormat == RSAk) + type = EVP_PKEY_RSA; + else if (keyFormat == ECDSAk) + type = EVP_PKEY_EC; + else if (keyFormat == DSAk) + type = EVP_PKEY_DSA; + } else { + /* Default to RSA if format is not set */ type = EVP_PKEY_RSA; + } /* handle case where reuse is attempted */ if (key != NULL && *key != NULL) diff --git a/src/wolfio.c b/src/wolfio.c index 3462e2b3ea2..61bc344d300 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -758,6 +758,10 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) SOCKADDR_IN *sin; #endif + if (sockfd == NULL || ip == NULL) { + return -1; + } + XMEMSET(&addr, 0, sizeof(addr)); #ifdef WOLFIO_DEBUG @@ -801,16 +805,14 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); #ifdef USE_WINDOWS_API - if (*sockfd == INVALID_SOCKET) { + if (*sockfd == SOCKET_INVALID) +#else + if (*sockfd <= SOCKET_INVALID) +#endif + { WOLFSSL_MSG("bad socket fd, out of fds?"); return -1; } -#else - if (*sockfd < 0) { - WOLFSSL_MSG("bad socket fd, out of fds?"); - return -1; - } -#endif #ifdef HAVE_IO_TIMEOUT /* if timeout value provided then set socket non-blocking */ @@ -835,6 +837,8 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) #endif if (ret != 0) { WOLFSSL_MSG("Responder tcp connect failed"); + CloseSocket(*sockfd); + *sockfd = SOCKET_INVALID; return -1; } return ret; @@ -1283,7 +1287,7 @@ int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, int EmbedOcspLookup(void* ctx, const char* url, int urlSz, byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) { - SOCKET_T sfd = 0; + SOCKET_T sfd = SOCKET_INVALID; word16 port; int ret = -1; #ifdef WOLFSSL_SMALL_STACK @@ -1329,7 +1333,7 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, httpBuf, httpBufSz); ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); - if ((ret != 0) || ((int)sfd < 0)) { + if (ret != 0) { WOLFSSL_MSG("OCSP Responder connection failed"); } else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != @@ -1345,7 +1349,8 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, HTTP_SCRATCH_BUFFER_SIZE, ctx); } - CloseSocket(sfd); + if (sfd != SOCKET_INVALID) + CloseSocket(sfd); XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP); } } @@ -1403,7 +1408,7 @@ int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) { - SOCKET_T sfd = 0; + SOCKET_T sfd = SOCKET_INVALID; word16 port; int ret = -1; #ifdef WOLFSSL_SMALL_STACK @@ -1435,7 +1440,7 @@ int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) httpBuf, httpBufSz); ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); - if ((ret != 0) || (sfd < 0)) { + if (ret != 0) { WOLFSSL_MSG("CRL connection failed"); } else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) @@ -1447,7 +1452,8 @@ int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) HTTP_SCRATCH_BUFFER_SIZE); } - CloseSocket(sfd); + if (sfd != SOCKET_INVALID) + CloseSocket(sfd); XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); } } diff --git a/tests/api.c b/tests/api.c index 6159ced48b3..b782d2d7d7c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2308,7 +2308,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) return 0; #endif } -#endif //defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ typedef int (*cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl); @@ -2701,7 +2701,7 @@ do { return; } -#endif //defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ @@ -3070,7 +3070,7 @@ static void test_wolfSSL_reuse_WOLFSSLobj(void) #endif } -#endif //defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ @@ -4151,7 +4151,7 @@ static void test_wolfSSL_PKCS12(void) */ #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) - byte buffer[5300]; + byte buffer[6000]; char file[] = "./certs/test-servercert.p12"; char order[] = "./certs/ecc-rsa-server.p12"; char pass[] = "a password"; @@ -4399,34 +4399,36 @@ static WC_INLINE int PKCS8TestCallBack(char* passwd, int sz, int rw, void* userd /* Testing functions dealing with PKCS8 */ static void test_wolfSSL_PKCS8(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) byte buffer[FOURK_BUF]; byte der[FOURK_BUF]; - const char eccPkcs8PrivKeyFile[] = "./certs/ecc-privkeyPkcs8.pem"; + const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; + #ifdef HAVE_ECC + const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; + #endif XFILE f; int bytes; + WOLFSSL_CTX* ctx; #ifdef HAVE_ECC int ret; ecc_key key; word32 x = 0; #endif -#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ - defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && \ - !defined(NO_PWDBASED) && !defined(NO_RSA) - #define TEST_PKCS8_ENC - const char serverKeyPkcs8EncFile[] = "./certs/server-keyPkcs8Enc.pem"; - int flag = 1; - WOLFSSL_CTX* ctx; +#ifdef TEST_PKCS8_ENC + #if !defined(NO_RSA) && !defined(NO_SHA) + const char serverKeyPkcs8EncPemFile[] = "./certs/server-keyPkcs8Enc.pem"; + const char serverKeyPkcs8EncDerFile[] = "./certs/server-keyPkcs8Enc.der"; + #endif + #if defined(HAVE_ECC) && !defined(NO_SHA) + const char eccPkcs8EncPrivKeyPemFile[] = "./certs/ecc-keyPkcs8Enc.pem"; + const char eccPkcs8EncPrivKeyDerFile[] = "./certs/ecc-keyPkcs8Enc.der"; + #endif + int flag; #endif printf(testingFmt, "wolfSSL_PKCS8()"); -#ifdef TEST_PKCS8_ENC - f = XFOPEN(serverKeyPkcs8EncFile, "rb"); - AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); - XFCLOSE(f); - #ifndef NO_WOLFSSL_CLIENT #ifndef WOLFSSL_NO_TLS12 AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); @@ -4440,49 +4442,131 @@ static void test_wolfSSL_PKCS8(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #endif - wolfSSL_CTX_set_default_passwd_cb(ctx, &PKCS8TestCallBack); + +#ifdef TEST_PKCS8_ENC + wolfSSL_CTX_set_default_passwd_cb(ctx, PKCS8TestCallBack); wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)&flag); + flag = 1; /* used by password callback as return code */ + + #if !defined(NO_RSA) && !defined(NO_SHA) + /* test loading PEM PKCS8 encrypted file */ + f = XFOPEN(serverKeyPkcs8EncPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, - SSL_FILETYPE_PEM), SSL_SUCCESS); + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); - /* this next case should fail if setting the user flag to a value other - * than 1 due to the password callback functions return value */ - flag = 0; - wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)&flag); + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, - SSL_FILETYPE_PEM), SSL_SUCCESS); + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); - wolfSSL_CTX_free(ctx); + /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ + AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "yassl123"), 0); + + /* test that error value is returned with a bad password */ + AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "bad"), 0); + + /* test loading PEM PKCS8 encrypted file */ + f = XFOPEN(serverKeyPkcs8EncDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + #endif /* !NO_RSA && !NO_SHA */ + + #if defined(HAVE_ECC) && !defined(NO_SHA) + /* test loading PEM PKCS8 encrypted ECC Key file */ + f = XFOPEN(eccPkcs8EncPrivKeyPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ - AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, FOURK_BUF, "yassl123"), 0); + AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "yassl123"), 0); /* test that error value is returned with a bad password */ - AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, FOURK_BUF, "bad"), 0); + AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "bad"), 0); + + /* test loading DER PKCS8 encrypted ECC Key file */ + f = XFOPEN(eccPkcs8EncPrivKeyDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* leave flag as "okay" */ + flag = 1; + #endif /* HAVE_ECC && !NO_SHA */ #endif /* TEST_PKCS8_ENC */ + /* Test PKCS8 PEM ECC key no crypt */ - f = XFOPEN(eccPkcs8PrivKeyFile, "rb"); + f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb"); AssertTrue((f != XBADFILE)); bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); XFCLOSE(f); - - /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ #ifdef HAVE_ECC - AssertIntGT((bytes = wc_KeyPemToDer(buffer, bytes, der, FOURK_BUF, NULL)), 0); + /* Test PKCS8 PEM ECC key no crypt */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* decrypt PKCS8 PEM to key in DER format */ + AssertIntGT((bytes = wc_KeyPemToDer(buffer, bytes, der, + (word32)sizeof(der), NULL)), 0); ret = wc_ecc_init(&key); if (ret == 0) { ret = wc_EccPrivateKeyDecode(der, &x, &key, bytes); wc_ecc_free(&key); } AssertIntEQ(ret, 0); + + /* Test PKCS8 DER ECC key no crypt */ + f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + + /* Test using a PKCS8 ECC PEM */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #else - AssertIntEQ((bytes = wc_KeyPemToDer(buffer, bytes, der, FOURK_BUF, NULL)), - ASN_NO_PEM_HEADER); -#endif + /* if HAVE_ECC is not defined then BEGIN EC PRIVATE KEY is not found */ + AssertIntEQ((bytes = wc_KeyPemToDer(buffer, bytes, der, + (word32)sizeof(der), NULL)), ASN_NO_PEM_HEADER); +#endif /* HAVE_ECC */ + + wolfSSL_CTX_free(ctx); printf(resultFmt, passed); -#endif /* !NO_FILESYSTEM && !NO_ASN */ +#endif /* !NO_FILESYSTEM && !NO_ASN && HAVE_PKCS8 */ } /* Testing functions dealing with PKCS5 */ @@ -17910,6 +17994,28 @@ static void test_wc_PemToDer(void) if (cert_buf) free(cert_buf); + #ifdef HAVE_ECC + { + const char* ecc_private_key = "./certs/ecc-privOnlyKey.pem"; + byte key_buf[256] = {0}; + + /* Test fail of loading a key with cert type */ + AssertIntEQ(load_file(ecc_private_key, &cert_buf, &cert_sz), 0); + key_buf[0] = '\n'; + XMEMCPY(key_buf + 1, cert_buf, cert_sz); + AssertIntNE((ret = wc_PemToDer(key_buf, cert_sz + 1, CERT_TYPE, + &pDer, NULL, &info, &eccKey)), 0); + + #ifdef OPENSSL_EXTRA + AssertIntEQ((ret = wc_PemToDer(key_buf, cert_sz + 1, PRIVATEKEY_TYPE, + &pDer, NULL, &info, &eccKey)), 0); + #endif + wc_FreeDer(&pDer); + if (cert_buf) + free(cert_buf); + } +#endif + printf(resultFmt, passed); #endif } @@ -20689,7 +20795,7 @@ static void test_wolfSSL_PKCS8_Compat(void) static void test_wolfSSL_PKCS8_d2i(void) { -#ifndef HAVE_FIPS +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) /* This test ends up using HMAC as a part of PBKDF2, and HMAC * requires a 12 byte password in FIPS mode. This test ends up * trying to use an 8 byte password. */ @@ -23477,7 +23583,6 @@ static void set_plain(unsigned char *plain, int rec) for(j=0; j #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #include +#endif + #ifdef WOLFSSL_DEBUG_ENCODING #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -135,6 +139,7 @@ extern int wc_InitRsaHw(RsaKey* key); #endif #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } +#define XSTR_SIZEOF(x) (sizeof(x) - 1) /* -1 to not count the null char */ #ifdef HAVE_SELFTEST #ifndef WOLFSSL_AES_KEY_SIZE_ENUM @@ -8759,6 +8764,11 @@ const char* const END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; const char* const BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* const END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; #endif +#ifdef OPENSSL_EXTRA + const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN"; + const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----"; + const char END_PRIV_KEY_PREFIX[] = "-----END"; +#endif const char* const BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* const END_PUB_KEY = "-----END PUBLIC KEY-----"; #ifdef HAVE_ED25519 @@ -9216,7 +9226,7 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, /* Remove PEM header/footer, convert to ASN1, store any encrypted data info->consumed tracks of PEM bytes consumed in case multiple parts */ int PemToDer(const unsigned char* buff, long longSz, int type, - DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey) + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat) { const char* header = NULL; const char* footer = NULL; @@ -9229,7 +9239,16 @@ int PemToDer(const unsigned char* buff, long longSz, int type, int sz = (int)longSz; int encrypted_key = 0; DerBuffer* der; +#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS) word32 algId = 0; + #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD) + int padVal = 0; + #endif +#endif +#ifdef OPENSSL_EXTRA + char beginBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */ + char endBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */ +#endif WOLFSSL_ENTER("PemToDer"); @@ -9260,7 +9279,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; } else #endif - #ifdef HAVE_ED25519 + #if defined(HAVE_ED25519) || defined(HAVE_ED448) #ifdef HAVE_ECC if (header == BEGIN_DSA_PRIV) #else @@ -9285,21 +9304,90 @@ int PemToDer(const unsigned char* buff, long longSz, int type, } if (!headerEnd) { +#ifdef OPENSSL_EXTRA + if (type == PRIVATEKEY_TYPE) { + char* beginEnd; + int endLen; + /* see if there is a -----BEGIN * PRIVATE KEY----- header */ + headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz); + if (headerEnd) { + beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX); + if (beginEnd >= (char*)buff + sz) { + return BUFFER_E; + } + + /* back up to BEGIN_PRIV_KEY_PREFIX */ + while (headerEnd > (char*)buff && + XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 && + *headerEnd != '\n') { + headerEnd--; + } + if (headerEnd <= (char*)buff || + XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 || + beginEnd - headerEnd > PEM_LINE_LEN) { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } + + /* headerEnd now points to beginning of header */ + XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd); + beginBuf[beginEnd - headerEnd] = '\0'; + /* look for matching footer */ + footer = XSTRNSTR(beginEnd, + beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX), + (unsigned int)((char*)buff + sz - beginEnd)); + if (!footer) { + WOLFSSL_MSG("Couldn't find PEM footer"); + return ASN_NO_PEM_HEADER; + } + + footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX); + if (footer > (char*)buff + sz - XSTR_SIZEOF(END_PRIV_KEY_PREFIX) + || XSTRNCMP(footer, END_PRIV_KEY_PREFIX, + XSTR_SIZEOF(END_PRIV_KEY_PREFIX)) != 0) { + WOLFSSL_MSG("Unexpected footer for PEM"); + return BUFFER_E; + } + + endLen = (unsigned int)(beginEnd - headerEnd - + (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) - + XSTR_SIZEOF(END_PRIV_KEY_PREFIX))); + XMEMCPY(endBuf, footer, endLen); + endBuf[endLen] = '\0'; + + header = beginBuf; + footer = endBuf; + headerEnd = beginEnd; + } + } + + if (!headerEnd) { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } +#else WOLFSSL_MSG("Couldn't find PEM header"); return ASN_NO_PEM_HEADER; +#endif + } else { + headerEnd += XSTRLEN(header); } - headerEnd += XSTRLEN(header); - /* eat end of line characters */ headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd); if (type == PRIVATEKEY_TYPE) { - if (eccKey) { + /* keyFormat is Key_Sum enum */ + if (keyFormat) { #ifdef HAVE_ECC - *eccKey = (header == BEGIN_EC_PRIV) ? 1 : 0; - #else - *eccKey = 0; + if (header == BEGIN_EC_PRIV) + *keyFormat = ECDSAk; + #endif + #if !defined(NO_DSA) + if (header == BEGIN_DSA_PRIV) + *keyFormat = DSAk; #endif } } @@ -9315,7 +9403,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #endif /* WOLFSSL_ENCRYPTED_KEYS */ /* find footer */ - footerEnd = XSTRNSTR((char*)buff, footer, sz); + footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd)); if (!footerEnd) { if (info) info->consumed = longSz; /* No more certs if no footer */ @@ -9351,18 +9439,26 @@ int PemToDer(const unsigned char* buff, long longSz, int type, return BUFFER_E; if ((header == BEGIN_PRIV_KEY +#ifdef OPENSSL_EXTRA + || header == beginBuf +#endif #ifdef HAVE_ECC || header == BEGIN_EC_PRIV #endif ) && !encrypted_key) { + #ifdef HAVE_PKCS8 /* pkcs8 key, convert and adjust length */ if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { der->length = ret; + if (keyFormat) { + *keyFormat = algId; + } } else { /* ignore failure here and assume key is not pkcs8 wrapped */ } + #endif return 0; } @@ -9401,8 +9497,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type, if (ret >= 0) { der->length = ret; - if ((algId == ECDSAk) && (eccKey != NULL)) { - *eccKey = 1; + if (keyFormat) { + *keyFormat = algId; } ret = 0; } @@ -9412,18 +9508,46 @@ int PemToDer(const unsigned char* buff, long longSz, int type, } /* decrypt the key */ else { - ret = wc_BufferKeyDecrypt(info, der->buffer, der->length, - (byte*)password, passwordSz, WC_MD5); + if (passwordSz == 0) { + /* The key is encrypted but does not have a password */ + WOLFSSL_MSG("No password for encrypted key"); + ret = NO_PASSWORD; + } + else { + ret = wc_BufferKeyDecrypt(info, der->buffer, der->length, + (byte*)password, passwordSz, WC_MD5); + +#ifndef NO_WOLFSSL_SKIP_TRAILING_PAD + #ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES3) { + padVal = der->buffer[der->length-1]; + if (padVal <= DES_BLOCK_SIZE) { + der->length -= padVal; + } + } + #endif /* !NO_DES3 */ +#endif /* !NO_WOLFSSL_SKIP_TRAILING_PAD */ + } + } +#ifdef OPENSSL_EXTRA + if (ret) { + PEMerr(0, PEM_R_BAD_DECRYPT); } +#endif ForceZero(password, passwordSz); } +#ifdef OPENSSL_EXTRA + else { + PEMerr(0, PEM_R_BAD_PASSWORD_READ); + } +#endif #ifdef WOLFSSL_SMALL_STACK XFREE(password, heap, DYNAMIC_TYPE_STRING); #endif } #endif /* WOLFSSL_ENCRYPTED_KEYS */ - + WOLFSSL_LEAVE("PemToDer", ret); return ret; } diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 26e3413e210..b820d18ef28 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -875,13 +875,22 @@ typedef STACK_OF(WOLFSSL_ASN1_OBJECT) GENERAL_NAMES; #define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg #define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg +/* Avoid wolfSSL error code range */ +#define PEM_R_NO_START_LINE (-MIN_CODE_E + 1) +#define PEM_R_PROBLEMS_GETTING_PASSWORD (-MIN_CODE_E + 2) +#define PEM_R_BAD_PASSWORD_READ (-MIN_CODE_E + 3) +#define PEM_R_BAD_DECRYPT (-MIN_CODE_E + 4) + +#define EVP_R_BAD_DECRYPT (-MIN_CODE_E + 100 + 1) +#define EVP_R_BN_DECODE_ERROR (-MIN_CODE_E + 100 + 2) +#define EVP_R_DECODE_ERROR (-MIN_CODE_E + 100 + 3) +#define EVP_R_PRIVATE_KEY_DECODE_ERROR (-MIN_CODE_E + 100 + 4) /* Nginx uses this to determine if reached end of certs in file. * PEM_read_bio_X509 is called and the return error is lost. * The error that needs to be detected is: SSL_NO_PEM_HEADER. */ #define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) -#define PEM_R_NO_START_LINE 108 #define ERR_LIB_PEM 9 #define ERR_LIB_X509 10 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 2357f056637..1bce1ca9ed6 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -100,6 +100,10 @@ #endif #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -2957,6 +2961,14 @@ WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); #endif +#ifndef WOLFCRYPT_ONLY +#define PEMerr(func, reason) wolfSSL_ERR_put_error(ERR_LIB_PEM, \ + (func), (reason), __FILE__, __LINE__) +#else +#define PEMerr(func, reason) WOLFSSL_ERROR_LINE((reason), \ + NULL, __LINE__, __FILE__, NULL) +#endif + #if defined(OPENSSL_ALL) \ || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) \ diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h index 27290d0dc6d..3fcd2ab17c4 100644 --- a/wolfssl/wolfio.h +++ b/wolfssl/wolfio.h @@ -278,8 +278,14 @@ #ifdef USE_WINDOWS_API typedef unsigned int SOCKET_T; + #ifndef SOCKET_INVALID + #define SOCKET_INVALID INVALID_SOCKET + #endif #else typedef int SOCKET_T; + #ifndef SOCKET_INVALID + #define SOCKET_INVALID -1 + #endif #endif #ifndef WOLFSSL_NO_SOCK From cb7559ebdfab9c056c84f7ee19e6361d7ead6728 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Sat, 17 Oct 2020 11:43:08 +0900 Subject: [PATCH 2/4] TSL1.3 client requires cert_vfy before finished. CVE-2020-24613, PR3171 --- src/tls13.c | 19 +++++++++++++++++-- wolfssl/internal.h | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index fbe3faf8bdf..d3e1aeded68 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5992,6 +5992,10 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; + #if !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_CERT_VERIFY_COMPLETE; + #endif } /* case TLS_ASYNC_FINALIZE */ case TLS_ASYNC_END: @@ -7142,8 +7146,19 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("Finished received out of order"); return OUT_OF_ORDER_E; } - if (ssl->options.serverState < + /* Must have seen certificate and verify from server except when + * using PSK. */ + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->arrays->psk_keySz != 0) { + if (ssl->options.serverState != SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + } + else + #endif + if (ssl->options.serverState != SERVER_CERT_VERIFY_COMPLETE) { WOLFSSL_MSG("Finished received out of order"); return OUT_OF_ORDER_E; } @@ -7151,7 +7166,7 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) #endif #ifndef NO_WOLFSSL_SERVER if (ssl->options.side == WOLFSSL_SERVER_END) { - if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + if (ssl->options.serverState != SERVER_FINISHED_COMPLETE) { WOLFSSL_MSG("Finished received out of order"); return OUT_OF_ORDER_E; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 892de666ca9..c809ccf4639 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -20,7 +20,6 @@ */ - #ifndef WOLFSSL_INT_H #define WOLFSSL_INT_H @@ -1543,6 +1542,7 @@ enum states { SERVER_HELLO_COMPLETE, SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, SERVER_CERT_COMPLETE, + SERVER_CERT_VERIFY_COMPLETE, SERVER_KEYEXCHANGE_COMPLETE, SERVER_HELLODONE_COMPLETE, SERVER_CHANGECIPHERSPEC_COMPLETE, From 05197a352e7bca4b4782d7dd1d10890d6f29f111 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Sat, 17 Oct 2020 11:54:50 +0900 Subject: [PATCH 3/4] In TLS 1.3, don't allow multiple ChangeCipherSpecs. CVE-2020-12457, PR2927# --- src/internal.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index cd01f7da0fb..a79bb2b10e3 100644 --- a/src/internal.c +++ b/src/internal.c @@ -20,7 +20,6 @@ */ - #ifdef HAVE_CONFIG_H #include #endif @@ -13680,6 +13679,7 @@ int ProcessReply(WOLFSSL* ssl) } else { #ifdef WOLFSSL_TLS13 + ssl->msgsReceived.got_change_cipher = 0; ret = DoTls13HandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, @@ -13742,6 +13742,13 @@ int ProcessReply(WOLFSSL* ssl) return UNKNOWN_RECORD_TYPE; } ssl->buffers.inputBuffer.idx++; + if (!ssl->msgsReceived.got_change_cipher) { + ssl->msgsReceived.got_change_cipher = 1; + } + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + return UNKNOWN_RECORD_TYPE; + } break; } #endif From d1ccb945f3bc92dc4b8d7d866b87cefec392de02 Mon Sep 17 00:00:00 2001 From: Takashi Kojo Date: Sat, 17 Oct 2020 11:20:29 +0900 Subject: [PATCH 4/4] ECC timing resistance CVE-2020-11713, PR2894 --- certs/ecc-privkeyPkcs8.der | Bin 0 -> 121 bytes wolfcrypt/src/ecc.c | 160 +++++++++++++++++------------------ wolfcrypt/src/wolfmath.c | 39 +++++++++ wolfssl/wolfcrypt/wolfmath.h | 2 + 4 files changed, 119 insertions(+), 82 deletions(-) create mode 100644 certs/ecc-privkeyPkcs8.der diff --git a/certs/ecc-privkeyPkcs8.der b/certs/ecc-privkeyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..a88d141e08cceb829f2bc756ffcabd7d8e8c0b79 GIT binary patch literal 121 zcmV-<0EYiCcLD(c1RzDWX##VcY=xmXTXN{=$E?HyjZ-xQ`fMoNG>ze?35=i$1_&yK zNX|V20SBQ(13~}x++j1?=l> (DIGIT_BIT - 1)) & 1; buf <<= 1; +#ifdef WC_NO_CACHE_RESISTANT if (mode == 0) { - mode = i; /* timing resistant - dummy operations */ if (err == MP_OKAY) err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus, mp); -#ifdef WC_NO_CACHE_RESISTANT if (err == MP_OKAY) err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); + } + else { + if (err == MP_OKAY) + err = ecc_projective_add_point(M[0], M[1], M[i^1], a, modulus, + mp); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); + } #else - /* instead of using M[i] for double, which leaks key bit to cache - * monitor, use M[2] as temp, make sure address calc is constant, - * keep M[0] and M[1] in cache */ - if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->x & wc_off_on_addr[i])), - M[2]->x); - if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->y & wc_off_on_addr[i])), - M[2]->y); - if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->z & wc_off_on_addr[i])), - M[2]->z); - if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); - /* copy M[2] back to M[i] */ - if (err == MP_OKAY) - err = mp_copy(M[2]->x, - (mp_int*) - ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) ); - if (err == MP_OKAY) - err = mp_copy(M[2]->y, - (mp_int*) - ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) ); - if (err == MP_OKAY) - err = mp_copy(M[2]->z, - (mp_int*) - ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) ); -#endif - if (err == MP_OKAY) - continue; - } + if (err == MP_OKAY) + err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, mp); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i, M[0]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i ^ 1, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i ^ 1, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i ^ 1, M[1]->z); if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[i^1], a, modulus, - mp); -#ifdef WC_NO_CACHE_RESISTANT + err = mp_cond_copy(M[0]->x, i ^ 1, M[2]->x); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); -#else - /* instead of using M[i] for double, which leaks key bit to cache - * monitor, use M[2] as temp, make sure address calc is constant, - * keep M[0] and M[1] in cache */ + err = mp_cond_copy(M[0]->y, i ^ 1, M[2]->y); if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->x & wc_off_on_addr[i])), - M[2]->x); + err = mp_cond_copy(M[0]->z, i ^ 1, M[2]->z); if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->y & wc_off_on_addr[i])), - M[2]->y); + err = mp_cond_copy(M[1]->x, i, M[2]->x); if (err == MP_OKAY) - err = mp_copy((mp_int*) - ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->z & wc_off_on_addr[i])), - M[2]->z); + err = mp_cond_copy(M[1]->y, i, M[2]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[1]->z, i, M[2]->z); + if (err == MP_OKAY) err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp); - /* copy M[2] back to M[i] */ if (err == MP_OKAY) - err = mp_copy(M[2]->x, - (mp_int*) - ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) ); + err = mp_cond_copy(M[2]->x, i ^ 1, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i ^ 1, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i ^ 1, M[0]->z); if (err == MP_OKAY) - err = mp_copy(M[2]->y, - (mp_int*) - ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) ); + err = mp_cond_copy(M[2]->x, i, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i, M[1]->z); + if (err == MP_OKAY) - err = mp_copy(M[2]->z, - (mp_int*) - ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + - ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) ); + err = mp_cond_copy(M[3]->x, (mode ^ 1) & i, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[3]->y, (mode ^ 1) & i, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[3]->z, (mode ^ 1) & i, M[0]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->x, (mode ^ 1) & i, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->y, (mode ^ 1) & i, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->z, (mode ^ 1) & i, M[1]->z); +#endif /* WC_NO_CACHE_RESISTANT */ + if (err != MP_OKAY) break; -#endif /* WC_NO_CACHE_RESISTANT */ + + mode |= i; + } /* end for */ } @@ -2935,7 +2926,12 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, (void)a; - return sp_ecc_mulmod_256(k, G, R, map, heap); +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_mulmod_256(k, G, R, map, heap); + } +#endif + return ECC_BAD_ARG_E; #endif } diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c index 04863dc8666..2cb756d543e 100644 --- a/wolfcrypt/src/wolfmath.c +++ b/wolfcrypt/src/wolfmath.c @@ -87,6 +87,45 @@ mp_digit get_digit(mp_int* a, int n) return (n >= a->used || n < 0) ? 0 : a->dp[n]; } +/* Conditionally copy a into b. Performed in constant time. + * + * a MP integer to copy. + * copy On 1, copy a into b. on 0 leave b unchanged. + * b MP integer to copy into. + * returns BAD_FUNC_ARG when a or b is NULL, MEMORY_E when growing b fails and + * MP_OKAY otherwise. + */ +int mp_cond_copy(mp_int* a, int copy, mp_int* b) +{ + int err = MP_OKAY; + int i; + mp_digit mask = (mp_digit)0 - copy; + + if (a == NULL || b == NULL) + err = BAD_FUNC_ARG; + + /* Ensure b has enough space to copy a into */ + if (err == MP_OKAY) + err = mp_grow(b, a->used + 1); + if (err == MP_OKAY) { + /* When mask 0, b is unchanged2 + * When mask all set, b ^ b ^ a = a + */ + /* Conditionaly copy all digits and then number of used diigits. + * get_digit() returns 0 when index greater than available digit. + */ + for (i = 0; i < a->used; i++) { + b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask; + } + for (; i < b->used; i++) { + b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask; + } + b->used ^= (a->used ^ b->used) & (int)mask; + } + + return err; +} + #ifndef WC_NO_RNG int get_rand_digit(WC_RNG* rng, mp_digit* d) { diff --git a/wolfssl/wolfcrypt/wolfmath.h b/wolfssl/wolfcrypt/wolfmath.h index 1db3223c6c1..079fff5e6cc 100644 --- a/wolfssl/wolfcrypt/wolfmath.h +++ b/wolfssl/wolfcrypt/wolfmath.h @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef __WOLFMATH_H__ #define __WOLFMATH_H__ @@ -54,6 +55,7 @@ MP_API int get_digit_count(mp_int* a); MP_API mp_digit get_digit(mp_int* a, int n); MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d); +WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b); WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng); enum {