From 91829e456c998eb9c2e565307b8f1022481049ce Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 22 Mar 2016 12:45:58 +0000 Subject: move x_pubkey.c to crypto/x509 Reviewed-by: Matt Caswell --- crypto/asn1/Makefile.in | 4 +- crypto/asn1/build.info | 2 +- crypto/asn1/x_pubkey.c | 377 ------------------------------------------------ crypto/x509/Makefile.in | 4 +- crypto/x509/build.info | 2 +- crypto/x509/x_pubkey.c | 377 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 383 insertions(+), 383 deletions(-) delete mode 100644 crypto/asn1/x_pubkey.c create mode 100644 crypto/x509/x_pubkey.c diff --git a/crypto/asn1/Makefile.in b/crypto/asn1/Makefile.in index fd8ffcfd99..282bd45727 100644 --- a/crypto/asn1/Makefile.in +++ b/crypto/asn1/Makefile.in @@ -18,7 +18,7 @@ LIB=$(TOP)/libcrypto.a LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ - x_algor.c x_val.c x_pubkey.c x_sig.c x_bignum.c \ + x_algor.c x_val.c x_sig.c x_bignum.c \ x_long.c x_info.c x_spki.c nsseq.c \ d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ t_pkey.c t_spki.c t_bitst.c \ @@ -32,7 +32,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ a_print.o a_type.o a_dup.o a_d2i_fp.o a_i2d_fp.o \ a_utf8.o a_sign.o a_digest.o a_verify.o a_mbstr.o a_strex.o \ - x_algor.o x_val.o x_pubkey.o x_sig.o x_bignum.o \ + x_algor.o x_val.o x_sig.o x_bignum.o \ x_long.o x_info.o x_spki.o nsseq.o \ d2i_pu.o d2i_pr.o i2d_pu.o i2d_pr.o \ t_pkey.o t_spki.o t_bitst.o \ diff --git a/crypto/asn1/build.info b/crypto/asn1/build.info index d4b9b008cd..02d1120b8c 100644 --- a/crypto/asn1/build.info +++ b/crypto/asn1/build.info @@ -3,7 +3,7 @@ SOURCE[../../libcrypto]=\ a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ - x_algor.c x_val.c x_pubkey.c x_sig.c x_bignum.c \ + x_algor.c x_val.c x_sig.c x_bignum.c \ x_long.c x_info.c x_spki.c nsseq.c \ d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ t_pkey.c t_spki.c t_bitst.c \ diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c deleted file mode 100644 index 158d1d26af..0000000000 --- a/crypto/asn1/x_pubkey.c +++ /dev/null @@ -1,377 +0,0 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include "internal/asn1_int.h" -#include "internal/evp_int.h" -#include -#include - -/* Minor tweak to operation: free up EVP_PKEY */ -static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) -{ - if (operation == ASN1_OP_NEW_POST) { - X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; - pubkey->lock = CRYPTO_THREAD_lock_new(); - if (pubkey->lock == NULL) - return 0; - } - if (operation == ASN1_OP_FREE_POST) { - X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; - CRYPTO_THREAD_lock_free(pubkey->lock); - EVP_PKEY_free(pubkey->pkey); - } - return 1; -} - -ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { - ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), - ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) - -IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) - -int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) -{ - X509_PUBKEY *pk = NULL; - - if (x == NULL) - return (0); - - if ((pk = X509_PUBKEY_new()) == NULL) - goto error; - - if (pkey->ameth) { - if (pkey->ameth->pub_encode) { - if (!pkey->ameth->pub_encode(pk, pkey)) { - X509err(X509_F_X509_PUBKEY_SET, - X509_R_PUBLIC_KEY_ENCODE_ERROR); - goto error; - } - } else { - X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED); - goto error; - } - } else { - X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM); - goto error; - } - - X509_PUBKEY_free(*x); - *x = pk; - return 1; - - error: - X509_PUBKEY_free(pk); - return 0; -} - -EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) -{ - EVP_PKEY *ret = NULL; - - if (key == NULL) - goto error; - - 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_GET0, ERR_R_MALLOC_FAILURE); - goto error; - } - - if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->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_GET0, X509_R_PUBLIC_KEY_DECODE_ERROR); - goto error; - } - } else { - X509err(X509_F_X509_PUBKEY_GET0, X509_R_METHOD_NOT_SUPPORTED); - goto error; - } - - /* Check to see if another thread set key->pkey first */ - CRYPTO_THREAD_write_lock(key->lock); - if (key->pkey) { - CRYPTO_THREAD_unlock(key->lock); - EVP_PKEY_free(ret); - ret = key->pkey; - } else { - key->pkey = ret; - CRYPTO_THREAD_unlock(key->lock); - } - - return ret; - - error: - EVP_PKEY_free(ret); - 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 - */ - -EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) -{ - X509_PUBKEY *xpk; - EVP_PKEY *pktmp; - const unsigned char *q; - q = *pp; - xpk = d2i_X509_PUBKEY(NULL, &q, length); - if (!xpk) - return NULL; - pktmp = X509_PUBKEY_get(xpk); - X509_PUBKEY_free(xpk); - if (!pktmp) - return NULL; - *pp = q; - if (a) { - EVP_PKEY_free(*a); - *a = pktmp; - } - return pktmp; -} - -int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) -{ - X509_PUBKEY *xpk = NULL; - int ret; - if (!a) - return 0; - if (!X509_PUBKEY_set(&xpk, a)) - return 0; - ret = i2d_X509_PUBKEY(xpk, pp); - X509_PUBKEY_free(xpk); - return ret; -} - -/* - * The following are equivalents but which return RSA and DSA keys - */ -#ifndef OPENSSL_NO_RSA -RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) -{ - EVP_PKEY *pkey; - RSA *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return NULL; - key = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); - if (!key) - return NULL; - *pp = q; - if (a) { - RSA_free(*a); - *a = key; - } - return key; -} - -int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) -{ - EVP_PKEY *pktmp; - int ret; - if (!a) - return 0; - pktmp = EVP_PKEY_new(); - if (pktmp == NULL) { - ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); - return 0; - } - EVP_PKEY_set1_RSA(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return ret; -} -#endif - -#ifndef OPENSSL_NO_DSA -DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) -{ - EVP_PKEY *pkey; - DSA *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return NULL; - key = EVP_PKEY_get1_DSA(pkey); - EVP_PKEY_free(pkey); - if (!key) - return NULL; - *pp = q; - if (a) { - DSA_free(*a); - *a = key; - } - return key; -} - -int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) -{ - EVP_PKEY *pktmp; - int ret; - if (!a) - return 0; - pktmp = EVP_PKEY_new(); - if (pktmp == NULL) { - ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); - return 0; - } - EVP_PKEY_set1_DSA(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return ret; -} -#endif - -#ifndef OPENSSL_NO_EC -EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) -{ - EVP_PKEY *pkey; - EC_KEY *key; - const unsigned char *q; - q = *pp; - pkey = d2i_PUBKEY(NULL, &q, length); - if (!pkey) - return (NULL); - key = EVP_PKEY_get1_EC_KEY(pkey); - EVP_PKEY_free(pkey); - if (!key) - return (NULL); - *pp = q; - if (a) { - EC_KEY_free(*a); - *a = key; - } - return (key); -} - -int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) -{ - EVP_PKEY *pktmp; - int ret; - if (!a) - return (0); - if ((pktmp = EVP_PKEY_new()) == NULL) { - ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); - return (0); - } - EVP_PKEY_set1_EC_KEY(pktmp, a); - ret = i2d_PUBKEY(pktmp, pp); - EVP_PKEY_free(pktmp); - return (ret); -} -#endif - -int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, - int ptype, void *pval, - unsigned char *penc, int penclen) -{ - if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) - return 0; - if (penc) { - OPENSSL_free(pub->public_key->data); - pub->public_key->data = penc; - pub->public_key->length = penclen; - /* Set number of unused bits to zero */ - pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - } - return 1; -} - -int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, - const unsigned char **pk, int *ppklen, - X509_ALGOR **pa, X509_PUBKEY *pub) -{ - if (ppkalg) - *ppkalg = pub->algor->algorithm; - if (pk) { - *pk = pub->public_key->data; - *ppklen = pub->public_key->length; - } - if (pa) - *pa = pub->algor; - return 1; -} diff --git a/crypto/x509/Makefile.in b/crypto/x509/Makefile.in index c1a173e5f0..8b11dc436d 100644 --- a/crypto/x509/Makefile.in +++ b/crypto/x509/Makefile.in @@ -22,7 +22,7 @@ LIBSRC= x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \ x509type.c x509_lu.c x_all.c x509_txt.c \ x509_trs.c by_file.c by_dir.c x509_vpm.c \ x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \ - x_x509a.c x_attrib.c x_exten.c x_name.c + x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \ x509_obj.o x509_req.o x509spki.o x509_vfy.o \ x509_set.o x509cset.o x509rset.o x509_err.o \ @@ -30,7 +30,7 @@ LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \ x509type.o x509_lu.o x_all.o x509_txt.o \ x509_trs.o by_file.o by_dir.o x509_vpm.o \ x_crl.o t_crl.o x_req.o t_req.o x_x509.o t_x509.o \ - x_x509a.o x_attrib.o x_exten.o x_name.o + x_pubkey.o x_x509a.o x_attrib.o x_exten.o x_name.o SRC= $(LIBSRC) diff --git a/crypto/x509/build.info b/crypto/x509/build.info index 336687c865..7fc4b45048 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -7,4 +7,4 @@ SOURCE[../../libcrypto]=\ x509type.c x509_lu.c x_all.c x509_txt.c \ x509_trs.c by_file.c by_dir.c x509_vpm.c \ x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \ - x_x509a.c x_attrib.c x_exten.c x_name.c + x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c new file mode 100644 index 0000000000..158d1d26af --- /dev/null +++ b/crypto/x509/x_pubkey.c @@ -0,0 +1,377 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include +#include + +/* Minor tweak to operation: free up EVP_PKEY */ +static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_NEW_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + pubkey->lock = CRYPTO_THREAD_lock_new(); + if (pubkey->lock == NULL) + return 0; + } + if (operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + CRYPTO_THREAD_lock_free(pubkey->lock); + EVP_PKEY_free(pubkey->pkey); + } + return 1; +} + +ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) +{ + X509_PUBKEY *pk = NULL; + + if (x == NULL) + return (0); + + if ((pk = X509_PUBKEY_new()) == NULL) + goto error; + + if (pkey->ameth) { + if (pkey->ameth->pub_encode) { + if (!pkey->ameth->pub_encode(pk, pkey)) { + X509err(X509_F_X509_PUBKEY_SET, + X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM); + goto error; + } + + X509_PUBKEY_free(*x); + *x = pk; + return 1; + + error: + X509_PUBKEY_free(pk); + return 0; +} + +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) +{ + EVP_PKEY *ret = NULL; + + if (key == NULL) + goto error; + + 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_GET0, ERR_R_MALLOC_FAILURE); + goto error; + } + + if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->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_GET0, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_GET0, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + + /* Check to see if another thread set key->pkey first */ + CRYPTO_THREAD_write_lock(key->lock); + if (key->pkey) { + CRYPTO_THREAD_unlock(key->lock); + EVP_PKEY_free(ret); + ret = key->pkey; + } else { + key->pkey = ret; + CRYPTO_THREAD_unlock(key->lock); + } + + return ret; + + error: + EVP_PKEY_free(ret); + 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 + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + const unsigned char *q; + q = *pp; + xpk = d2i_X509_PUBKEY(NULL, &q, length); + if (!xpk) + return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if (!pktmp) + return NULL; + *pp = q; + if (a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk = NULL; + int ret; + if (!a) + return 0; + if (!X509_PUBKEY_set(&xpk, a)) + return 0; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* + * The following are equivalents but which return RSA and DSA keys + */ +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + RSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_RSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_DSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + EC_KEY *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return (NULL); + key = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + if (!key) + return (NULL); + *pp = q; + if (a) { + EC_KEY_free(*a); + *a = key; + } + return (key); +} + +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return (0); + if ((pktmp = EVP_PKEY_new()) == NULL) { + ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); + return (0); + } + EVP_PKEY_set1_EC_KEY(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return (ret); +} +#endif + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen) +{ + if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) + return 0; + if (penc) { + OPENSSL_free(pub->public_key->data); + pub->public_key->data = penc; + pub->public_key->length = penclen; + /* Set number of unused bits to zero */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + return 1; +} + +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub) +{ + if (ppkalg) + *ppkalg = pub->algor->algorithm; + if (pk) { + *pk = pub->public_key->data; + *ppklen = pub->public_key->length; + } + if (pa) + *pa = pub->algor; + return 1; +} -- cgit v1.2.3