From c01ff880d47392b82cce2f93ac4a9bb8c68f8cc7 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 14 Dec 2015 13:13:32 +0000 Subject: [PATCH] New function X509_get0_pubkey Reviewed-by: Viktor Dukhovni --- apps/ca.c | 6 ++---- apps/crl.c | 3 +-- apps/s_cb.c | 3 +-- apps/s_client.c | 3 +-- apps/x509.c | 9 +++------ crypto/asn1/x_pubkey.c | 23 ++++++++++++++--------- crypto/x509/t_x509.c | 3 +-- crypto/x509/x509_cmp.c | 18 +++++++++++------- crypto/x509/x509_err.c | 2 +- crypto/x509/x509_vfy.c | 19 +++++-------------- doc/crypto/X509_get_pubkey.pod | 11 +++++++---- include/openssl/x509.h | 4 +++- 12 files changed, 50 insertions(+), 54 deletions(-) diff --git a/apps/ca.c b/apps/ca.c index 535526ce30..6404e48507 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1402,12 +1402,11 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Check that the request matches the signature\n"); - if ((pktmp = X509_get_pubkey(req)) == NULL) { + if ((pktmp = X509_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } i = X509_verify(req, pktmp); - EVP_PKEY_free(pktmp); if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); @@ -1890,11 +1889,10 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } } - pktmp = X509_get_pubkey(ret); + pktmp = X509_get0_pubkey(ret); if (EVP_PKEY_missing_parameters(pktmp) && !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp, pkey); - EVP_PKEY_free(pktmp); if (!do_X509_sign(ret, pkey, dgst, sigopts)) goto end; diff --git a/apps/crl.c b/apps/crl.c index b2a5d7f54d..3f64cdd57a 100644 --- a/apps/crl.c +++ b/apps/crl.c @@ -253,14 +253,13 @@ int crl_main(int argc, char **argv) BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } - pkey = X509_get_pubkey(xobj.data.x509); + pkey = X509_get0_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); - EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) diff --git a/apps/s_cb.c b/apps/s_cb.c index 734d57fda4..7a4bf297cc 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -1402,13 +1402,12 @@ static int security_callback_debug(SSL *s, SSL_CTX *ctx, int sig_nid = X509_get_signature_nid(other); BIO_puts(sdb->out, OBJ_nid2sn(sig_nid)); } else { - EVP_PKEY *pkey = X509_get_pubkey(other); + EVP_PKEY *pkey = X509_get0_pubkey(other); const char *algname = ""; EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &algname, EVP_PKEY_get0_asn1(pkey)); BIO_printf(sdb->out, "%s, bits=%d", algname, EVP_PKEY_bits(pkey)); - EVP_PKEY_free(pkey); } break; } diff --git a/apps/s_client.c b/apps/s_client.c index f93ae35f56..5aa1adc51e 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -2206,10 +2206,9 @@ static void print_stuff(BIO *bio, SSL *s, int full) SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); if (peer != NULL) { EVP_PKEY *pktmp; - pktmp = X509_get_pubkey(peer); + pktmp = X509_get0_pubkey(peer); BIO_printf(bio, "Server public key is %d bit\n", EVP_PKEY_bits(pktmp)); - EVP_PKEY_free(pktmp); } BIO_printf(bio, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); diff --git a/apps/x509.c b/apps/x509.c index 7155b33246..1677ba5fda 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -723,7 +723,7 @@ int x509_main(int argc, char **argv) } else if (modulus == i) { EVP_PKEY *pkey; - pkey = X509_get_pubkey(x); + pkey = X509_get0_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Modulus=unavailable\n"); ERR_print_errors(bio_err); @@ -742,18 +742,16 @@ int x509_main(int argc, char **argv) #endif BIO_printf(out, "Wrong Algorithm type"); BIO_printf(out, "\n"); - EVP_PKEY_free(pkey); } else if (pubkey == i) { EVP_PKEY *pkey; - pkey = X509_get_pubkey(x); + pkey = X509_get0_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(out, pkey); - EVP_PKEY_free(pkey); } else if (C == i) { unsigned char *d; char *m; @@ -991,9 +989,8 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509_STORE_CTX xsc; EVP_PKEY *upkey; - upkey = X509_get_pubkey(xca); + upkey = X509_get0_pubkey(xca); EVP_PKEY_copy_parameters(upkey, pkey); - EVP_PKEY_free(upkey); if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c index d20019005c..36a130d6aa 100644 --- a/crypto/asn1/x_pubkey.c +++ b/crypto/asn1/x_pubkey.c @@ -121,38 +121,36 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) return 0; } -EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) { EVP_PKEY *ret = NULL; if (key == NULL) goto error; - if (key->pkey != NULL) { - CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + if (key->pkey != NULL) return key->pkey; - } if (key->public_key == NULL) goto error; if ((ret = EVP_PKEY_new()) == NULL) { - X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); + X509err(X509_F_X509_PUBKEY_GET0, ERR_R_MALLOC_FAILURE); goto error; } if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) { - X509err(X509_F_X509_PUBKEY_GET, X509_R_UNSUPPORTED_ALGORITHM); + X509err(X509_F_X509_PUBKEY_GET0, X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (ret->ameth->pub_decode) { if (!ret->ameth->pub_decode(ret, key)) { - X509err(X509_F_X509_PUBKEY_GET, X509_R_PUBLIC_KEY_DECODE_ERROR); + X509err(X509_F_X509_PUBKEY_GET0, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { - X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED); + X509err(X509_F_X509_PUBKEY_GET0, X509_R_METHOD_NOT_SUPPORTED); goto error; } @@ -166,7 +164,6 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) key->pkey = ret; CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); } - CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return ret; @@ -175,6 +172,14 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) return (NULL); } +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +{ + EVP_PKEY *ret = X509_PUBKEY_get0(key); + if (ret != NULL) + EVP_PKEY_up_ref(ret); + return ret; +} + /* * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or * decode as X509_PUBKEY diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c index 3a29f4082a..204aed417c 100644 --- a/crypto/x509/t_x509.c +++ b/crypto/x509/t_x509.c @@ -209,13 +209,12 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, if (BIO_puts(bp, "\n") <= 0) goto err; - pkey = X509_get_pubkey(x); + pkey = X509_get0_pubkey(x); if (pkey == NULL) { BIO_printf(bp, "%12sUnable to load Public Key\n", ""); ERR_print_errors(bp); } else { EVP_PKEY_print_public(bp, pkey, 16, NULL); - EVP_PKEY_free(pkey); } } diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 5c3ac6a66f..9d9ea4b605 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -305,11 +305,18 @@ X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) return (NULL); } +EVP_PKEY *X509_get0_pubkey(X509 *x) +{ + if (x == NULL) + return NULL; + return X509_PUBKEY_get0(x->cert_info.key); +} + EVP_PKEY *X509_get_pubkey(X509 *x) { if (x == NULL) - return (NULL); - return (X509_PUBKEY_get(x->cert_info.key)); + return NULL; + return X509_PUBKEY_get(x->cert_info.key); } ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) @@ -324,7 +331,7 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k) EVP_PKEY *xk; int ret; - xk = X509_get_pubkey(x); + xk = X509_get0_pubkey(x); if (xk) ret = EVP_PKEY_cmp(xk, k); @@ -343,7 +350,6 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k) case -2: X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); } - EVP_PKEY_free(xk); if (ret > 0) return 1; return 0; @@ -411,7 +417,7 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, goto end; } - pk = X509_get_pubkey(x); + pk = X509_get0_pubkey(x); /* Check EE key only */ rv = check_suite_b(pk, -1, &tflags); if (rv != X509_V_OK) { @@ -426,7 +432,6 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, rv = X509_V_ERR_SUITE_B_INVALID_VERSION; goto end; } - EVP_PKEY_free(pk); pk = X509_get_pubkey(x); rv = check_suite_b(pk, sign_nid, &tflags); if (rv != X509_V_OK) @@ -436,7 +441,6 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, /* Final check: root CA signature */ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); end: - EVP_PKEY_free(pk); if (rv != X509_V_OK) { /* Invalid signature or LOS errors are for previous cert */ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index a6fae614e5..25f90ea584 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -109,7 +109,7 @@ static ERR_STRING_DATA X509_str_functs[] = { {ERR_FUNC(X509_F_X509_NAME_ONELINE), "X509_NAME_oneline"}, {ERR_FUNC(X509_F_X509_NAME_PRINT), "X509_NAME_print"}, {ERR_FUNC(X509_F_X509_PRINT_EX_FP), "X509_print_ex_fp"}, - {ERR_FUNC(X509_F_X509_PUBKEY_GET), "X509_PUBKEY_get"}, + {ERR_FUNC(X509_F_X509_PUBKEY_GET0), "X509_PUBKEY_get0"}, {ERR_FUNC(X509_F_X509_PUBKEY_SET), "X509_PUBKEY_set"}, {ERR_FUNC(X509_F_X509_REQ_CHECK_PRIVATE_KEY), "X509_REQ_check_private_key"}, diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 3156e04225..3acb374a54 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1559,7 +1559,7 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) } /* Attempt to get issuer certificate public key */ - ikey = X509_get_pubkey(issuer); + ikey = X509_get0_pubkey(issuer); if (!ikey) { ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; @@ -1588,7 +1588,6 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) ok = 1; err: - EVP_PKEY_free(ikey); return ok; } @@ -1769,7 +1768,7 @@ static int internal_verify(X509_STORE_CTX *ctx) if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) { - if ((pkey = X509_get_pubkey(xi)) == NULL) { + if ((pkey = X509_get0_pubkey(xi)) == NULL) { ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; ctx->current_cert = xi; ok = (*cb) (0, ctx); @@ -1779,13 +1778,9 @@ static int internal_verify(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; ctx->current_cert = xs; ok = (*cb) (0, ctx); - if (!ok) { - EVP_PKEY_free(pkey); + if (!ok) goto end; - } } - EVP_PKEY_free(pkey); - pkey = NULL; } xs->valid = 1; @@ -1973,7 +1968,7 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) return 1; for (i = 0; i < sk_X509_num(chain); i++) { - ktmp = X509_get_pubkey(sk_X509_value(chain, i)); + ktmp = X509_get0_pubkey(sk_X509_value(chain, i)); if (ktmp == NULL) { X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); @@ -1981,8 +1976,6 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) } if (!EVP_PKEY_missing_parameters(ktmp)) break; - EVP_PKEY_free(ktmp); - ktmp = NULL; } if (ktmp == NULL) { X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, @@ -1992,14 +1985,12 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) /* first, populate the other certs */ for (j = i - 1; j >= 0; j--) { - ktmp2 = X509_get_pubkey(sk_X509_value(chain, j)); + ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j)); EVP_PKEY_copy_parameters(ktmp2, ktmp); - EVP_PKEY_free(ktmp2); } if (pkey != NULL) EVP_PKEY_copy_parameters(pkey, ktmp); - EVP_PKEY_free(ktmp); return 1; } diff --git a/doc/crypto/X509_get_pubkey.pod b/doc/crypto/X509_get_pubkey.pod index c59ce2a735..2740f98386 100644 --- a/doc/crypto/X509_get_pubkey.pod +++ b/doc/crypto/X509_get_pubkey.pod @@ -2,7 +2,7 @@ =head1 NAME -X509_get_pubkey, X509_set_pubkey, X509_get_X509_PUBKEY, +X509_get_pubkey, X509_get0_pubkey, X509_set_pubkey, X509_get_X509_PUBKEY, X509_REQ_get_pubkey, X509_REQ_set_pubkey, X509_REQ_get_X509_PUBKEY - get or set certificate or certificate request public key. @@ -11,6 +11,7 @@ set certificate or certificate request public key. #include EVP_PKEY *X509_get_pubkey(X509 *x); + EVP_PKEY *X509_get0_pubkey(X509 *x); int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); X509_PUBKEY *X509_get_X509_PUBKEY(X509 *x); @@ -23,6 +24,8 @@ set certificate or certificate request public key. X509_get_pubkey() attempts to decode the public key for certificate B. If successful it returns the public key as an B pointer with its reference count incremented: this means the returned key must be freed up +after use. X509_get0_pubkey() is similar except it does B increment +the reference count of the returned B so it must not be freed up after use. X509_get_X509_PUBKEY() returns an internal pointer to the B @@ -44,9 +47,9 @@ improve performance. =head1 RETURN VALUES -X509_get_pubkey(), X509_get_X509_PUBKEY(), X509_REQ_get_pubkey() and -X509_REQ_get_X509_PUBKEY() return a public key or B if an error -occurred. +X509_get_pubkey(), X509_get0_pubkey(), X509_get_X509_PUBKEY(), +X509_REQ_get_pubkey() and X509_REQ_get_X509_PUBKEY() return a public key or +B if an error occurred. X509_set_pubkey() and X509_REQ_set_pubkey() rerturn 1 for success and 0 for failure. diff --git a/include/openssl/x509.h b/include/openssl/x509.h index d33bcec5e1..167aae89b5 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -575,6 +575,7 @@ DECLARE_ASN1_FUNCTIONS(X509_VAL) DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key); EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp); @@ -708,6 +709,7 @@ STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); void X509_get0_uids(ASN1_BIT_STRING **piuid, ASN1_BIT_STRING **psuid, X509 *x); X509_ALGOR *X509_get0_tbs_sigalg(X509 *x); +EVP_PKEY *X509_get0_pubkey(X509 *x); EVP_PKEY *X509_get_pubkey(X509 *x); ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); int X509_certificate_type(X509 *x, EVP_PKEY *pubkey /* optional */ ); @@ -1097,7 +1099,7 @@ void ERR_load_X509_strings(void); # define X509_F_X509_NAME_ONELINE 116 # define X509_F_X509_NAME_PRINT 117 # define X509_F_X509_PRINT_EX_FP 118 -# define X509_F_X509_PUBKEY_GET 119 +# define X509_F_X509_PUBKEY_GET0 119 # define X509_F_X509_PUBKEY_SET 120 # define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 # define X509_F_X509_REQ_PRINT_EX 121 -- 2.25.1