1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com). 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL. 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to. The following conditions 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA, 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed. 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used. 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package. 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in the 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * documentation and/or other materials provided with the distribution. 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * must display the following acknowledgement: 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes cryptographic software written by 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Eric Young (eay@cryptsoft.com)" 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The word 'cryptographic' can be left out if the rouines from the library 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * being used are not cryptographic related :-). 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the apps directory (application code) you must include an acknowledgement: 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE. 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed. i.e. this code cannot simply be 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */ 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1.h> 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1t.h> 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/evp.h> 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h> 63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/thread.h> 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509.h> 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../evp/internal.h" 6753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley#include "../internal.h" 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Minor tweak to operation: free up EVP_PKEY */ 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley void *exarg) 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (operation == ASN1_OP_FREE_POST) 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pubkey->pkey); 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 82d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 87d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyIMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY *pk=NULL; 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (x == NULL) return(0); 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((pk=X509_PUBKEY_new()) == NULL) goto error; 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pkey->ameth) 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pkey->ameth->pub_encode) 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkey->ameth->pub_encode(pk, pkey)) 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_PUBLIC_KEY_ENCODE_ERROR); 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley else 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_METHOD_NOT_SUPPORTED); 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley else 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_UNSUPPORTED_ALGORITHM); 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*x != NULL) 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY_free(*x); 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *x=pk; 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerror: 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pk != NULL) X509_PUBKEY_free(pk); 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 13053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of 13153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley * |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t| 13253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley * inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is 13353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley * not. */ 13453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langleystatic struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT; 13553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 136d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *ret=NULL; 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (key == NULL) goto error; 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 14253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock); 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (key->pkey != NULL) 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 14553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock); 146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return EVP_PKEY_up_ref(key->pkey); 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 14853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock); 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (key->public_key == NULL) goto error; 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((ret = EVP_PKEY_new()) == NULL) 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, ERR_R_MALLOC_FAILURE); 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_UNSUPPORTED_ALGORITHM); 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret->ameth->pub_decode) 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret->ameth->pub_decode(ret, key)) 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_PUBLIC_KEY_DECODE_ERROR); 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley else 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_METHOD_NOT_SUPPORTED); 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto error; 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Check to see if another thread set key->pkey first */ 17953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (key->pkey) 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 18253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock); 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(ret); 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = key->pkey; 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley else 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley key->pkey = ret; 18953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock); 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 192e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return EVP_PKEY_up_ref(ret); 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley error: 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret != NULL) 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(ret); 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return(NULL); 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Now two pseudo ASN1 routines that take an EVP_PKEY structure 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * and encode or decode as X509_PUBKEY 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 204d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley long length) 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY *xpk; 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pktmp; 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley xpk = d2i_X509_PUBKEY(NULL, pp, length); 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!xpk) return NULL; 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pktmp = X509_PUBKEY_get(xpk); 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY_free(xpk); 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!pktmp) return NULL; 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(a) 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(*a); 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *a = pktmp; 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return pktmp; 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp) 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY *xpk=NULL; 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!a) return 0; 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!X509_PUBKEY_set(&xpk, (EVP_PKEY*) a)) return 0; 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = i2d_X509_PUBKEY(xpk, pp); 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY_free(xpk); 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* The following are equivalents but which return RSA and DSA 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * keys 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 236d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyRSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley long length) 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pkey; 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley RSA *key; 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const unsigned char *q; 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley q = *pp; 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkey = d2i_PUBKEY(NULL, &q, length); 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkey) return NULL; 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley key = EVP_PKEY_get1_RSA(pkey); 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pkey); 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!key) return NULL; 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *pp = q; 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (a) 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley RSA_free(*a); 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *a = key; 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return key; 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp) 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pktmp; 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!a) return 0; 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pktmp = EVP_PKEY_new(); 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pktmp) 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, i2d_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_set1_RSA(pktmp, (RSA*) a); 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = i2d_PUBKEY(pktmp, pp); 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pktmp); 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#ifndef OPENSSL_NO_DSA 275d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyDSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley long length) 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pkey; 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley DSA *key; 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const unsigned char *q; 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley q = *pp; 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkey = d2i_PUBKEY(NULL, &q, length); 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkey) return NULL; 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley key = EVP_PKEY_get1_DSA(pkey); 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pkey); 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!key) return NULL; 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *pp = q; 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (a) 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley DSA_free(*a); 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *a = key; 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return key; 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp) 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pktmp; 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!a) return 0; 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pktmp = EVP_PKEY_new(); 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if(!pktmp) 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, i2d_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_set1_DSA(pktmp, (DSA*) a); 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = i2d_PUBKEY(pktmp, pp); 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pktmp); 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 314d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pkey; 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_KEY *key; 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const unsigned char *q; 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley q = *pp; 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pkey = d2i_PUBKEY(NULL, &q, length); 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!pkey) return(NULL); 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley key = EVP_PKEY_get1_EC_KEY(pkey); 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pkey); 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!key) return(NULL); 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *pp = q; 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (a) 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_KEY_free(*a); 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *a = key; 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return(key); 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp) 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY *pktmp; 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!a) return(0); 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((pktmp = EVP_PKEY_new()) == NULL) 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, i2d_EC_PUBKEY, ERR_R_MALLOC_FAILURE); 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return(0); 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY*) a); 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = i2d_PUBKEY(pktmp, pp); 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EVP_PKEY_free(pktmp); 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return(ret); 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj, 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ptype, void *pval, 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned char *penc, int penclen) 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (penc) 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pub->public_key->data) 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(pub->public_key->data); 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pub->public_key->data = penc; 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pub->public_key->length = penclen; 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Set number of unused bits to zero */ 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT; 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const unsigned char **pk, int *ppklen, 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_ALGOR **pa, 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_PUBKEY *pub) 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ppkalg) 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ppkalg = pub->algor->algorithm; 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pk) 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *pk = pub->public_key->data; 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ppklen = pub->public_key->length; 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (pa) 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *pa = pub->algor; 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 385