-
Notifications
You must be signed in to change notification settings - Fork 1k
X509: cache decoded public key, give get0_pubkey borrowed semantics #11428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
f818bba
59a8c0a
e0fcedd
ecb575e
d644d97
187b101
a7f3c5c
6bf0c44
38df5de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6386,19 +6386,19 @@ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, | |
| return (textSz - 1); /* do not include null character in size */ | ||
| } | ||
|
|
||
| /* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509 | ||
| /* Decodes the public key of x509 into a new WOLFSSL_EVP_PKEY. | ||
| * | ||
| * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail | ||
| */ | ||
| WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) | ||
| static WOLFSSL_EVP_PKEY* X509DecodePubKey(WOLFSSL_X509* x509) | ||
| { | ||
| WOLFSSL_EVP_PKEY* key = NULL; | ||
| int ret = 0; | ||
|
|
||
| (void)ret; | ||
|
|
||
| WOLFSSL_ENTER("wolfSSL_X509_get_pubkey"); | ||
| if (x509 != NULL) { | ||
| if (x509 != NULL && x509->pubKey.buffer != NULL && | ||
| x509->pubKey.length > 0) { | ||
| key = wolfSSL_EVP_PKEY_new_ex(x509->heap); | ||
| if (key != NULL) { | ||
| if (x509->pubKeyOID == RSAk) { | ||
|
|
@@ -6543,6 +6543,60 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) | |
| } | ||
| return key; | ||
| } | ||
|
|
||
| /* Returns the public key cached in x509, decoding it on first use. | ||
| * The key is owned by x509 and freed with it. */ | ||
| static WOLFSSL_EVP_PKEY* X509CachedPubKey(WOLFSSL_X509* x509) | ||
| { | ||
| WOLFSSL_EVP_PKEY* key; | ||
|
|
||
| if (x509 == NULL) | ||
| return NULL; | ||
| key = x509->key.pkey; | ||
| if (key == NULL) { | ||
| key = X509DecodePubKey(x509); | ||
| if (key != NULL) { | ||
| x509->key.pubKeyOID = x509->pubKeyOID; | ||
| x509->key.pkey = key; | ||
| } | ||
| } | ||
| return key; | ||
| } | ||
|
|
||
| /* Returns the public key of x509 with a new reference. | ||
| * | ||
| * returns a pointer to the WOLFSSL_EVP_PKEY on success and NULL on fail. | ||
| * The caller frees it with wolfSSL_EVP_PKEY_free(). | ||
| */ | ||
| WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) | ||
| { | ||
| WOLFSSL_EVP_PKEY* key; | ||
|
|
||
| WOLFSSL_ENTER("wolfSSL_X509_get_pubkey"); | ||
| key = X509CachedPubKey(x509); | ||
| if (key != NULL) { | ||
| int ret; | ||
| wolfSSL_RefInc(&key->ref, &ret); | ||
| if (ret != 0) { | ||
| WOLFSSL_MSG("Failed to lock pkey mutex"); | ||
| key = NULL; | ||
| } | ||
| } | ||
| return key; | ||
| } | ||
|
|
||
| /* Returns the public key of x509 without a new reference. | ||
| * | ||
| * returns a pointer to the WOLFSSL_EVP_PKEY on success and NULL on fail. | ||
| * The key must not be freed. It is valid until x509 is freed or its public | ||
| * key is changed. | ||
| */ | ||
| WOLFSSL_EVP_PKEY* wolfSSL_X509_get0_pubkey(const WOLFSSL_X509* x509) | ||
| { | ||
| WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey"); | ||
| /* Only the lazily decoded key cache is written. */ | ||
| return X509CachedPubKey((WOLFSSL_X509*)x509); | ||
| } | ||
| #endif /* OPENSSL_EXTRA_X509_SMALL */ | ||
|
|
||
| /* End of smaller subset of X509 compatibility functions. Avoid increasing the | ||
|
|
@@ -11578,6 +11632,10 @@ WOLFSSL_X509_PUBKEY* wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509) | |
| return NULL; | ||
| } | ||
|
|
||
| /* OpenSSL also takes a const X509 and returns a mutable X509_PUBKEY. | ||
| * Only the lazily decoded key cache is written here. */ | ||
| (void)X509CachedPubKey((WOLFSSL_X509*)x509); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line casts away
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| return (WOLFSSL_X509_PUBKEY*)&x509->key; | ||
| } | ||
|
|
||
|
|
@@ -11593,16 +11651,26 @@ int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, | |
| WOLFSSL_MSG("X509_PUBKEY struct not populated"); | ||
| return WOLFSSL_FAILURE; | ||
| } | ||
| if ((pk || ppklen) && !pub->pkey) { | ||
| WOLFSSL_MSG("X509_PUBKEY has no decoded key"); | ||
| return WOLFSSL_FAILURE; | ||
| } | ||
|
|
||
| if (!pub->algor) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AI says there is now a race condition in this block since |
||
| if (!(pub->algor = wolfSSL_X509_ALGOR_new())) { | ||
| /* Build the algorithm fully before storing it, so a failure | ||
| * never leaves a half built one behind. */ | ||
| WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new(); | ||
| if (algor == NULL) { | ||
| return WOLFSSL_FAILURE; | ||
| } | ||
| pub->algor->algorithm = wolfSSL_OBJ_nid2obj(pub->pubKeyOID); | ||
| if (pub->algor->algorithm == NULL) { | ||
| algor->algorithm = wolfSSL_OBJ_nid2obj( | ||
| oid2nid((word32)pub->pubKeyOID, oidKeyType)); | ||
| if (algor->algorithm == NULL) { | ||
| WOLFSSL_MSG("Failed to create object from NID"); | ||
| wolfSSL_X509_ALGOR_free(algor); | ||
| return WOLFSSL_FAILURE; | ||
| } | ||
| pub->algor = algor; | ||
| } | ||
|
|
||
| if (pa) | ||
|
|
@@ -11633,6 +11701,15 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key) | |
| return key->pkey; | ||
| } | ||
|
|
||
| /* Returns the pkey without a new reference. */ | ||
| WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get0(const WOLFSSL_X509_PUBKEY* key) | ||
| { | ||
| WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get0"); | ||
| if (key == NULL) | ||
| return NULL; | ||
| return key->pkey; | ||
| } | ||
|
|
||
| int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key) | ||
| { | ||
| WOLFSSL_X509_PUBKEY *pk = NULL; | ||
|
|
@@ -16846,6 +16923,7 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) | |
| return WOLFSSL_FAILURE; | ||
| } | ||
| cert->pubKeyOID = ECDSAk; | ||
| cert->pkCurveOID = ecc->dp->oidSum; | ||
| } | ||
| break; | ||
| #endif | ||
|
|
@@ -16963,6 +17041,19 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) | |
| XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); | ||
| cert->pubKey.buffer = p; | ||
| cert->pubKey.length = (unsigned int)derSz; | ||
| /* Drop what was decoded from the previous public key, unless the caller | ||
| * passed that very key. */ | ||
| if (cert->key.pkey != pkey) { | ||
| wolfSSL_EVP_PKEY_free(cert->key.pkey); | ||
| cert->key.pkey = NULL; | ||
| } | ||
| cert->key.pubKeyOID = cert->pubKeyOID; | ||
| #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ | ||
| defined(WOLFSSL_APACHE_HTTPD) || defined(WOLFSSL_HAPROXY) || \ | ||
| defined(WOLFSSL_WPAS) | ||
| wolfSSL_X509_ALGOR_free(cert->key.algor); | ||
| cert->key.algor = NULL; | ||
| #endif | ||
|
|
||
| return WOLFSSL_SUCCESS; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.