diff --git a/src/ssl.c b/src/ssl.c index c14dac55f..84a191d81 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7430,7 +7430,7 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) else #endif { - ret = wc_CheckPrivateKey(buff, size, der); + ret = wc_CheckPrivateKeyCert(buff, size, der); if (ret == 1) { ret = WOLFSSL_SUCCESS; } @@ -8034,7 +8034,7 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl) } else #endif - ret = wc_CheckPrivateKey(buff, size, &der); + ret = wc_CheckPrivateKeyCert(buff, size, &der); FreeDecodedCert(&der); return ret; } @@ -19521,8 +19521,11 @@ static int wolfssl_conf_value_cmp(const WOLFSSL_CONF_VALUE *a, } } -/* Use MD5 for hashing as it is fast and should - * be good enough for database indexing */ +/* Use MD5 for hashing as OpenSSL uses a hash algorithm that is + * "not as good as MD5, but still good" so using MD5 should + * be good enough for this application. The produced hashes don't + * need to line up between OpenSSL and wolfSSL. The hashes are for + * internal indexing only */ unsigned long wolfSSL_LH_strhash(const char *str) { unsigned long ret = 0; @@ -42617,11 +42620,6 @@ err: int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key) { - DecodedCert dc; - byte* der; - int derSz; - int ret; - WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); if (!x509 || !key) { @@ -42629,24 +42627,9 @@ err: return WOLFSSL_FAILURE; } - der = (byte*)wolfSSL_X509_get_der(x509, &derSz); - if (der == NULL) { - WOLFSSL_MSG("wolfSSL_X509_get_der error"); - return WOLFSSL_FAILURE; - } - - InitDecodedCert(&dc, der, derSz, x509->heap); - - if (ParseCertRelative(&dc, CERT_TYPE, NO_VERIFY, NULL) != 0) { - FreeDecodedCert(&dc); - return WOLFSSL_FAILURE; - } - - der = (byte*)key->pkey.ptr; - derSz = key->pkey_sz; - ret = wc_CheckPrivateKey(der, derSz, &dc); - FreeDecodedCert(&dc); - return ret == 1 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + return wc_CheckPrivateKey((byte*)key->pkey.ptr, key->pkey_sz, + x509->pubKey.buffer, x509->pubKey.length, + x509->pubKeyOID) == 1 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } /* wolfSSL uses negative values for error states. This function returns an diff --git a/tests/api.c b/tests/api.c index 5d1f8f93c..5af0d206d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -38249,8 +38249,8 @@ static void test_wolfSSL_d2i_X509_REQ(void) AssertNotNull(at = X509_ATTRIBUTE_get0_type(attr, 0)); AssertNotNull(at->value.asn1_string); AssertStrEQ((char*)ASN1_STRING_data(at->value.asn1_string), "2xIE+qqp/rhyTXP+"); -#endif AssertIntEQ(X509_get_ext_by_NID(req, NID_subject_alt_name, -1), -1); +#endif X509_free(req); BIO_free(bio); @@ -38260,8 +38260,8 @@ static void test_wolfSSL_d2i_X509_REQ(void) #ifdef OPENSSL_ALL X509_ATTRIBUTE* attr; ASN1_TYPE *at; -#endif STACK_OF(X509_EXTENSION) *exts = NULL; +#endif AssertNotNull(bio = BIO_new_file(csrExtFile, "rb")); /* This CSR contains an Extension Request attribute so * we test extension parsing in a CSR attribute here. */ @@ -38277,10 +38277,10 @@ static void test_wolfSSL_d2i_X509_REQ(void) */ AssertIntEQ(X509_REQ_verify(req, pub_key), 1); +#ifdef OPENSSL_ALL AssertNotNull(exts = (STACK_OF(X509_EXTENSION)*)X509_REQ_get_extensions(req)); AssertIntEQ(sk_X509_EXTENSION_num(exts), 2); - -#ifdef OPENSSL_ALL + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); /* * Obtain the challenge password from the CSR */ @@ -38290,14 +38290,13 @@ static void test_wolfSSL_d2i_X509_REQ(void) AssertNotNull(at = X509_ATTRIBUTE_get0_type(attr, 0)); AssertNotNull(at->value.asn1_string); AssertStrEQ((char*)ASN1_STRING_data(at->value.asn1_string), "IGCu/xNL4/0/wOgo"); -#endif AssertIntGE(X509_get_ext_by_NID(req, NID_key_usage, -1), 0); AssertIntGE(X509_get_ext_by_NID(req, NID_subject_alt_name, -1), 0); +#endif X509_free(req); BIO_free(bio); EVP_PKEY_free(pub_key); - sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } #if !defined(NO_DSA) && !defined(HAVE_SELFTEST) { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9213d6821..f8cdfcd6a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2904,25 +2904,29 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, #endif /* HAVE_PKCS8 */ #if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY) -/* check that the private key is a pair for the public key in certificate +/* check that the private key is a pair for the public key * return 1 (true) on match * return 0 or negative value on failure/error * - * key : buffer holding DER format key - * keySz : size of key buffer - * der : a initialized and parsed DecodedCert holding a certificate */ -int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) + * privKey : buffer holding DER format private key + * privKeySz : size of private key buffer + * pubKey : buffer holding DER format public key + * pubKeySz : size of public key buffer + * ks : type of key */ +int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, + const byte* pubKey, word32 pubKeySz, enum Key_Sum ks) { int ret; - (void)keySz; + (void)privKeySz; + (void)pubKeySz; - if (key == NULL || der == NULL) { + if (privKey == NULL || pubKey == NULL) { return BAD_FUNC_ARG; } #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT) /* test if RSA key */ - if (der->keyOID == RSAk) { + if (ks == RSAk) { #ifdef WOLFSSL_SMALL_STACK RsaKey* a; RsaKey* b = NULL; @@ -2957,12 +2961,12 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif return ret; } - if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) { + if ((ret = wc_RsaPrivateKeyDecode(privKey, &keyIdx, a, privKeySz)) == 0) { WOLFSSL_MSG("Checking RSA key pair"); keyIdx = 0; /* reset to 0 for parsing public key */ - if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b, - der->pubKeySize)) == 0) { + if ((ret = wc_RsaPublicKeyDecode(pubKey, &keyIdx, b, + pubKeySz)) == 0) { /* limit for user RSA crypto because of RsaKey * dereference. */ #if defined(HAVE_USER_RSA) @@ -2991,7 +2995,7 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif /* !NO_RSA && !NO_ASN_CRYPT */ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) - if (der->keyOID == ECDSAk) { + if (ks == ECDSAk) { #ifdef WOLFSSL_SMALL_STACK ecc_key* key_pair; byte* privDer; @@ -3021,8 +3025,8 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) return ret; } - if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair, - keySz)) == 0) { + if ((ret = wc_EccPrivateKeyDecode(privKey, &keyIdx, key_pair, + privKeySz)) == 0) { WOLFSSL_MSG("Checking ECC key pair"); if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz)) @@ -3030,9 +3034,9 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) wc_ecc_free(key_pair); ret = wc_ecc_init(key_pair); if (ret == 0) { - ret = wc_ecc_import_private_key((const byte*)privDer, - privSz, (const byte*)der->publicKey, - der->pubKeySize, key_pair); + ret = wc_ecc_import_private_key(privDer, + privSz, pubKey, + pubKeySz, key_pair); } /* public and private extracted successfully now check if is @@ -3056,7 +3060,7 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT) - if (der->keyOID == ED25519k) { + if (ks == ED25519k) { #ifdef WOLFSSL_SMALL_STACK ed25519_key* key_pair; #else @@ -3077,12 +3081,12 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif return ret; } - if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair, - keySz)) == 0) { + if ((ret = wc_Ed25519PrivateKeyDecode(privKey, &keyIdx, key_pair, + privKeySz)) == 0) { WOLFSSL_MSG("Checking ED25519 key pair"); keyIdx = 0; - if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, - key_pair)) == 0) { + if ((ret = wc_ed25519_import_public(pubKey, pubKeySz, + key_pair)) == 0) { /* public and private extracted successfully no check if is * a pair and also do sanity checks on key. wc_ecc_check_key * checks that private * base generator equals pubkey */ @@ -3099,7 +3103,7 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */ #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT) - if (der->keyOID == ED448k) { + if (ks == ED448k) { #ifdef WOLFSSL_SMALL_STACK ed448_key* key_pair = NULL; #else @@ -3120,12 +3124,12 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif return ret; } - if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair, - keySz)) == 0) { + if ((ret = wc_Ed448PrivateKeyDecode(privKey, &keyIdx, key_pair, + privKeySz)) == 0) { WOLFSSL_MSG("Checking ED448 key pair"); keyIdx = 0; - if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize, - key_pair)) == 0) { + if ((ret = wc_ed448_import_public(pubKey, pubKeySz, + key_pair)) == 0) { /* public and private extracted successfully no check if is * a pair and also do sanity checks on key. wc_ecc_check_key * checks that private * base generator equals pubkey */ @@ -3144,11 +3148,26 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) ret = 0; } - (void)keySz; - return ret; } +/* check that the private key is a pair for the public key in certificate + * return 1 (true) on match + * return 0 or negative value on failure/error + * + * key : buffer holding DER format key + * keySz : size of key buffer + * der : a initialized and parsed DecodedCert holding a certificate */ +int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der) +{ + if (key == NULL || der == NULL) { + return BAD_FUNC_ARG; + } + + return wc_CheckPrivateKey(key, keySz, der->publicKey, + der->pubKeySize, (enum Key_Sum) der->keyOID); +} + #endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */ #ifndef NO_PWDBASED diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index ca9a4e53e..10bb8b3cc 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -948,7 +948,7 @@ static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { - if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { + if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, &DeCert) == 1) { WOLFSSL_MSG("Key Pair found"); *cert = current->buffer; *certSz = current->bufferSz; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 7f24efa4f..1537ccc7e 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1197,7 +1197,9 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx); WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx); -WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, + const byte* pubKey, word32 pubKeySz, enum Key_Sum ks); WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g); WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*);