X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fp_lib.c;h=154ef788e8afc713688828970d0dc3274cf575a4;hp=0d3a69b48a42862e12fef4266826a488f6de0cb9;hb=b8d77c9bd675b4128aeeafb4a738938460477a2e;hpb=db98bbc1144cb7ac412562a54aaba0e4d2cde080 diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 0d3a69b48a..154ef788e8 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1,246 +1,507 @@ -/* crypto/evp/p_lib.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. 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.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include -#include "cryptlib.h" +#include "internal/cryptlib.h" +#include "internal/refcount.h" #include #include #include #include -#include #include -#ifndef OPENSSL_NO_RSA #include -#endif -#ifndef OPENSSL_NO_DSA #include -#endif -#ifndef OPENSSL_NO_DH #include -#endif +#include +#include -#include "asn1_locl.h" +#include "internal/asn1_int.h" +#include "internal/evp_int.h" static void EVP_PKEY_free_it(EVP_PKEY *x); -int EVP_PKEY_bits(EVP_PKEY *pkey) - { - if (pkey && pkey->ameth && pkey->ameth->pkey_bits) - return pkey->ameth->pkey_bits(pkey); - return 0; - } +int EVP_PKEY_bits(const EVP_PKEY *pkey) +{ + if (pkey && pkey->ameth && pkey->ameth->pkey_bits) + return pkey->ameth->pkey_bits(pkey); + return 0; +} + +int EVP_PKEY_security_bits(const EVP_PKEY *pkey) +{ + if (pkey == NULL) + return 0; + if (!pkey->ameth || !pkey->ameth->pkey_security_bits) + return -2; + return pkey->ameth->pkey_security_bits(pkey); +} int EVP_PKEY_size(EVP_PKEY *pkey) - { - if (pkey && pkey->ameth && pkey->ameth->pkey_size) - return pkey->ameth->pkey_size(pkey); - return 0; - } +{ + if (pkey && pkey->ameth && pkey->ameth->pkey_size) + return pkey->ameth->pkey_size(pkey); + return 0; +} int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) - { +{ #ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - { - int ret=pkey->save_parameters; - - if (mode >= 0) - pkey->save_parameters=mode; - return(ret); - } + if (pkey->type == EVP_PKEY_DSA) { + int ret = pkey->save_parameters; + + if (mode >= 0) + pkey->save_parameters = mode; + return ret; + } #endif #ifndef OPENSSL_NO_EC - if (pkey->type == EVP_PKEY_EC) - { - int ret = pkey->save_parameters; - - if (mode >= 0) - pkey->save_parameters = mode; - return(ret); - } + if (pkey->type == EVP_PKEY_EC) { + int ret = pkey->save_parameters; + + if (mode >= 0) + pkey->save_parameters = mode; + return ret; + } #endif - return(0); - } + return 0; +} int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) - { - if (to->type != from->type) - { - EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_DIFFERENT_KEY_TYPES); - goto err; - } - - if (EVP_PKEY_missing_parameters(from)) - { - EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_MISSING_PARAMETERS); - goto err; - } - if (from->ameth && from->ameth->param_copy) - return from->ameth->param_copy(to, from); -err: - return 0; - } +{ + if (to->type == EVP_PKEY_NONE) { + if (EVP_PKEY_set_type(to, from->type) == 0) + return 0; + } else if (to->type != from->type) { + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES); + goto err; + } + + if (EVP_PKEY_missing_parameters(from)) { + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS); + goto err; + } + + if (!EVP_PKEY_missing_parameters(to)) { + if (EVP_PKEY_cmp_parameters(to, from) == 1) + return 1; + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS); + return 0; + } + + if (from->ameth && from->ameth->param_copy) + return from->ameth->param_copy(to, from); + err: + return 0; +} int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) - { - if (pkey->ameth && pkey->ameth->param_missing) - return pkey->ameth->param_missing(pkey); - return 0; - } +{ + if (pkey->ameth && pkey->ameth->param_missing) + return pkey->ameth->param_missing(pkey); + return 0; +} int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) - { - if (a->type != b->type) - return -1; - if (a->ameth && a->ameth->param_cmp) - return a->ameth->param_cmp(a, b); - return -1; - } +{ + if (a->type != b->type) + return -1; + if (a->ameth && a->ameth->param_cmp) + return a->ameth->param_cmp(a, b); + return -2; +} int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) - { - if (a->type != b->type) - return -1; +{ + if (a->type != b->type) + return -1; + + if (a->ameth) { + int ret; + /* Compare parameters if the algorithm has them */ + if (a->ameth->param_cmp) { + ret = a->ameth->param_cmp(a, b); + if (ret <= 0) + return ret; + } + + if (a->ameth->pub_cmp) + return a->ameth->pub_cmp(a, b); + } + + return -2; +} - if (EVP_PKEY_cmp_parameters(a, b) == 0) - return 0; +EVP_PKEY *EVP_PKEY_new(void) +{ + EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = EVP_PKEY_NONE; + ret->save_type = EVP_PKEY_NONE; + ret->references = 1; + ret->save_parameters = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} - if (a->ameth && a->ameth->pub_cmp) - return a->ameth->pub_cmp(a, b); +int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ + int i; - return -2; - } + if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) + return 0; -EVP_PKEY *EVP_PKEY_new(void) - { - EVP_PKEY *ret; - - ret=(EVP_PKEY *)OPENSSL_malloc(sizeof(EVP_PKEY)); - if (ret == NULL) - { - EVPerr(EVP_F_EVP_PKEY_NEW,ERR_R_MALLOC_FAILURE); - return(NULL); - } - ret->type=EVP_PKEY_NONE; - ret->references=1; - ret->ameth=NULL; - ret->pkey.ptr=NULL; - ret->attributes=NULL; - ret->save_parameters=1; - return(ret); - } - -int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) - { - const EVP_PKEY_ASN1_METHOD *ameth; - if (pkey == NULL) return(0); - if (pkey->pkey.ptr != NULL) - EVP_PKEY_free_it(pkey); - ameth = EVP_PKEY_asn1_find(type); - pkey->ameth = ameth; - pkey->type = ameth->pkey_id; - pkey->save_type=type; - pkey->pkey.ptr=key; - return(key != NULL); - } - -void *EVP_PKEY_get0(EVP_PKEY *pkey) - { - return pkey->pkey.ptr; - } + REF_PRINT_COUNT("EVP_PKEY", pkey); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +/* + * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey + * is NULL just return 1 or 0 if the algorithm exists. + */ + +static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, + int len) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE **eptr = (e == NULL) ? &e : NULL; + + if (pkey) { + if (pkey->pkey.ptr) + EVP_PKEY_free_it(pkey); + /* + * If key type matches and a method exists then this lookup has + * succeeded once so just indicate success. + */ + if ((type == pkey->save_type) && pkey->ameth) + return 1; +#ifndef OPENSSL_NO_ENGINE + /* If we have ENGINEs release them */ + ENGINE_finish(pkey->engine); + pkey->engine = NULL; + ENGINE_finish(pkey->pmeth_engine); + pkey->pmeth_engine = NULL; +#endif + } + if (str) + ameth = EVP_PKEY_asn1_find_str(eptr, str, len); + else + ameth = EVP_PKEY_asn1_find(eptr, type); +#ifndef OPENSSL_NO_ENGINE + if (pkey == NULL && eptr != NULL) + ENGINE_finish(e); +#endif + if (ameth == NULL) { + EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + if (pkey) { + pkey->ameth = ameth; + pkey->engine = e; + + pkey->type = pkey->ameth->pkey_id; + pkey->save_type = type; + } + return 1; +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len) +{ + EVP_PKEY *ret = EVP_PKEY_new(); + + if (ret == NULL + || !pkey_set_type(ret, e, type, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (ret->ameth->set_priv_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!ret->ameth->set_priv_key(ret, priv, len)) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + return ret; + + err: + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, + const unsigned char *pub, + size_t len) +{ + EVP_PKEY *ret = EVP_PKEY_new(); + + if (ret == NULL + || !pkey_set_type(ret, e, type, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (ret->ameth->set_pub_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!ret->ameth->set_pub_key(ret, pub, len)) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + return ret; + + err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + if (pkey->ameth->get_priv_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (!pkey->ameth->get_priv_key(pkey, priv, len)) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED); + return 0; + } + + return 1; +} + +int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, + size_t *len) +{ + if (pkey->ameth->get_pub_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (!pkey->ameth->get_pub_key(pkey, pub, len)) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED); + return 0; + } + + return 1; +} + +EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, + size_t len, const EVP_CIPHER *cipher) +{ +#ifndef OPENSSL_NO_CMAC + EVP_PKEY *ret = EVP_PKEY_new(); + EVP_MAC_CTX *cmctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC); + + if (ret == NULL + || cmctx == NULL + || !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_ENGINE, e) <= 0 + || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_CIPHER, cipher) <= 0 + || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_KEY, priv, len) <= 0) { + EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + ret->pkey.ptr = cmctx; + return ret; + + err: + EVP_PKEY_free(ret); + EVP_MAC_CTX_free(cmctx); + return NULL; +#else + EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return NULL; +#endif +} + +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) +{ + return pkey_set_type(pkey, NULL, type, NULL, -1); +} + +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) +{ + return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len); +} + +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) +{ + if (pkey->type == type) { + return 1; /* it already is that type */ + } + + /* + * The application is requesting to alias this to a different pkey type, + * but not one that resolves to the base type. + */ + if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) { + EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + pkey->type = type; + return 1; +} + +#ifndef OPENSSL_NO_ENGINE +int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) +{ + if (e != NULL) { + if (!ENGINE_init(e)) { + EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB); + return 0; + } + if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) { + ENGINE_finish(e); + EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + } + ENGINE_finish(pkey->pmeth_engine); + pkey->pmeth_engine = e; + return 1; +} +#endif +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) +{ + if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) + return 0; + pkey->pkey.ptr = key; + return (key != NULL); +} + +void *EVP_PKEY_get0(const EVP_PKEY *pkey) +{ + return pkey->pkey.ptr; +} + +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + if (pkey->type != EVP_PKEY_HMAC) { + EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} + +#ifndef OPENSSL_NO_POLY1305 +const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + if (pkey->type != EVP_PKEY_POLY1305) { + EVPerr(EVP_F_EVP_PKEY_GET0_POLY1305, EVP_R_EXPECTING_A_POLY1305_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} +#endif + +#ifndef OPENSSL_NO_SIPHASH +const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + + if (pkey->type != EVP_PKEY_SIPHASH) { + EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} +#endif #ifndef OPENSSL_NO_RSA int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { - int ret = EVP_PKEY_assign_RSA(pkey, key); - if(ret) - RSA_up_ref(key); - return ret; + int ret = EVP_PKEY_assign_RSA(pkey, key); + if (ret) + RSA_up_ref(key); + return ret; +} + +RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_RSA) { + EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY); + return NULL; + } + return pkey->pkey.rsa; } RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) - { - if(pkey->type != EVP_PKEY_RSA) { - EVPerr(EVP_F_EVP_PKEY_GET1_RSA, EVP_R_EXPECTING_AN_RSA_KEY); - return NULL; - } - RSA_up_ref(pkey->pkey.rsa); - return pkey->pkey.rsa; +{ + RSA *ret = EVP_PKEY_get0_RSA(pkey); + if (ret != NULL) + RSA_up_ref(ret); + return ret; } #endif #ifndef OPENSSL_NO_DSA int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { - int ret = EVP_PKEY_assign_DSA(pkey, key); - if(ret) - DSA_up_ref(key); - return ret; + int ret = EVP_PKEY_assign_DSA(pkey, key); + if (ret) + DSA_up_ref(key); + return ret; +} + +DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_DSA) { + EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY); + return NULL; + } + return pkey->pkey.dsa; } DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) - { - if(pkey->type != EVP_PKEY_DSA) { - EVPerr(EVP_F_EVP_PKEY_GET1_DSA, EVP_R_EXPECTING_A_DSA_KEY); - return NULL; - } - DSA_up_ref(pkey->pkey.dsa); - return pkey->pkey.dsa; +{ + DSA *ret = EVP_PKEY_get0_DSA(pkey); + if (ret != NULL) + DSA_up_ref(ret); + return ret; } #endif @@ -248,116 +509,180 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { - int ret = EVP_PKEY_assign_EC_KEY(pkey,key); - if (ret) - EC_KEY_up_ref(key); - return ret; + int ret = EVP_PKEY_assign_EC_KEY(pkey, key); + if (ret) + EC_KEY_up_ref(key); + return ret; +} + +EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) { + EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); + return NULL; + } + return pkey->pkey.ec; } EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_EC) - { - EVPerr(EVP_F_EVP_PKEY_GET1_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); - return NULL; - } - EC_KEY_up_ref(pkey->pkey.ec); - return pkey->pkey.ec; + EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey); + if (ret != NULL) + EC_KEY_up_ref(ret); + return ret; } #endif - #ifndef OPENSSL_NO_DH int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) { - int ret = EVP_PKEY_assign_DH(pkey, key); - if(ret) - DH_up_ref(key); - return ret; + int ret = EVP_PKEY_assign_DH(pkey, key); + if (ret) + DH_up_ref(key); + return ret; +} + +DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) { + EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY); + return NULL; + } + return pkey->pkey.dh; } DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) - { - if(pkey->type != EVP_PKEY_DH) { - EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY); - return NULL; - } - DH_up_ref(pkey->pkey.dh); - return pkey->pkey.dh; +{ + DH *ret = EVP_PKEY_get0_DH(pkey); + if (ret != NULL) + DH_up_ref(ret); + return ret; } #endif int EVP_PKEY_type(int type) - { - const EVP_PKEY_ASN1_METHOD *ameth; - ameth = EVP_PKEY_asn1_find(type); - if (ameth) - return ameth->pkey_id; - return NID_undef; - } +{ + int ret; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *e; + ameth = EVP_PKEY_asn1_find(&e, type); + if (ameth) + ret = ameth->pkey_id; + else + ret = NID_undef; +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(e); +#endif + return ret; +} -void EVP_PKEY_free(EVP_PKEY *x) - { - int i; +int EVP_PKEY_id(const EVP_PKEY *pkey) +{ + return pkey->type; +} - if (x == NULL) return; +int EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + return EVP_PKEY_type(pkey->type); +} - i=CRYPTO_add(&x->references,-1,CRYPTO_LOCK_EVP_PKEY); -#ifdef REF_PRINT - REF_PRINT("EVP_PKEY",x); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"EVP_PKEY_free, bad reference count\n"); - abort(); - } -#endif - EVP_PKEY_free_it(x); - if (x->attributes) - sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); - OPENSSL_free(x); - } +void EVP_PKEY_free(EVP_PKEY *x) +{ + int i; + + if (x == NULL) + return; + + CRYPTO_DOWN_REF(&x->references, &i, x->lock); + REF_PRINT_COUNT("EVP_PKEY", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + EVP_PKEY_free_it(x); + CRYPTO_THREAD_lock_free(x->lock); + sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); + OPENSSL_free(x); +} static void EVP_PKEY_free_it(EVP_PKEY *x) - { - if (x->ameth && x->ameth->pkey_free) - x->ameth->pkey_free(x); - } +{ + /* internal function; x is never NULL */ + if (x->ameth && x->ameth->pkey_free) { + x->ameth->pkey_free(x); + x->pkey.ptr = NULL; + } +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(x->engine); + x->engine = NULL; + ENGINE_finish(x->pmeth_engine); + x->pmeth_engine = NULL; +#endif +} static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, - const char *kstr) - { - BIO_indent(out, indent, 128); - BIO_printf(out, "%s %s, algorithm, unsupported\n", - OBJ_nid2ln(pkey->type), kstr); - return 1; - } + const char *kstr) +{ + BIO_indent(out, indent, 128); + BIO_printf(out, "%s algorithm \"%s\" unsupported\n", + kstr, OBJ_nid2ln(pkey->type)); + return 1; +} int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, - int indent, ASN1_PCTX *pctx) - { - if (pkey->ameth && pkey->ameth->pub_print) - return pkey->ameth->pub_print(out, pkey, indent, pctx); - - return unsup_alg(out, pkey, indent, "Public Key"); - } + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->pub_print) + return pkey->ameth->pub_print(out, pkey, indent, pctx); + + return unsup_alg(out, pkey, indent, "Public Key"); +} int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, - int indent, ASN1_PCTX *pctx) - { - if (pkey->ameth && pkey->ameth->priv_print) - return pkey->ameth->priv_print(out, pkey, indent, pctx); - - return unsup_alg(out, pkey, indent, "Private Key"); - } + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->priv_print) + return pkey->ameth->priv_print(out, pkey, indent, pctx); + + return unsup_alg(out, pkey, indent, "Private Key"); +} int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, - int indent, ASN1_PCTX *pctx) - { - if (pkey->ameth && pkey->ameth->param_print) - return pkey->ameth->param_print(out, pkey, indent, pctx); - return unsup_alg(out, pkey, indent, "Parameters"); - } + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->param_print) + return pkey->ameth->param_print(out, pkey, indent, pctx); + return unsup_alg(out, pkey, indent, "Parameters"); +} + +static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2) +{ + if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) + return -2; + return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2); +} + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) +{ + return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid); +} + +int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, + const unsigned char *pt, size_t ptlen) +{ + if (ptlen > INT_MAX) + return 0; + if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen, + (void *)pt) <= 0) + return 0; + return 1; +} + +size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) +{ + int rv; + rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt); + if (rv <= 0) + return 0; + return rv; +}