10f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 20f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * project 2006. 30f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com */ 40f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com/* ==================================================================== 50f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 60f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 78fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com * Redistribution and use in source and binary forms, with or without 80f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * modification, are permitted provided that the following conditions 90f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * are met: 108fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com * 118fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com * 1. Redistributions of source code must retain the above copyright 120f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * notice, this list of conditions and the following disclaimer. 130b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang * 140b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang * 2. Redistributions in binary form must reproduce the above copyright 150b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang * notice, this list of conditions and the following disclaimer in 160b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang * the documentation and/or other materials provided with the 17312404870905e1eff46e21632c1c2f2143af4694daniel@transgaming.com * distribution. 180f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 190f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 3. All advertising materials mentioning features or use of this 200f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * software must display the following acknowledgment: 210f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * "This product includes software developed by the OpenSSL Project 220f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 230f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 240f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 250f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * endorse or promote products derived from this software without 260f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * prior written permission. For written permission, please contact 270f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * licensing@OpenSSL.org. 280f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 290f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 5. Products derived from this software may not be called "OpenSSL" 300f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * nor may "OpenSSL" appear in their names without prior written 310f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * permission of the OpenSSL Project. 320f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 330f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 6. Redistributions of any form whatsoever must retain the following 340f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * acknowledgment: 350f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * "This product includes software developed by the OpenSSL Project 360f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 370f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 380f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 390f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 400f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 410f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 420f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 430f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 440f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 450f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 460f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 470f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 480f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 490f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * OF THE POSSIBILITY OF SUCH DAMAGE. 500f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * ==================================================================== 510f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * 520f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * This product includes cryptographic software written by Eric Young 530f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * (eay@cryptsoft.com). This product includes software written by Tim 540f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * Hudson (tjh@cryptsoft.com). */ 550f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 560f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/evp.h> 570f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 580f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/asn1t.h> 590f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/bn.h> 600f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/ec.h> 610f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/err.h> 620f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/mem.h> 630f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/obj.h> 640f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include <openssl/x509.h> 650f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 660f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com#include "internal.h" 670f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 680f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 690f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstatic int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) { 700f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com const EC_GROUP *group; 710f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com int nid; 720f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 730f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { 740f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_param2type, EVP_R_MISSING_PARAMETERS); 750f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 760f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 770f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 780f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com nid = EC_GROUP_get_curve_name(group); 790f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (nid == NID_undef) { 800f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_param2type, EVP_R_NO_NID_FOR_CURVE); 810f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 820f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 830f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 840f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com *ppval = (void*) OBJ_nid2obj(nid); 850f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com *pptype = V_ASN1_OBJECT; 860f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 1; 870f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com} 880f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 890f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstatic int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { 900f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com EC_KEY *ec_key = pkey->pkey.ec; 910f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com void *pval = NULL; 920f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com int ptype; 930f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com uint8_t *penc = NULL, *p; 940f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com int penclen; 950f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 960f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (!eckey_param2type(&ptype, &pval, ec_key)) { 970f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_pub_encode, ERR_R_EC_LIB); 980f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 990f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1000f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com penclen = i2o_ECPublicKey(ec_key, NULL); 1010f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (penclen <= 0) { 1020f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1030f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1040f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com penc = OPENSSL_malloc(penclen); 1050f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (!penc) { 1060f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1070f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1080f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com p = penc; 1090f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com penclen = i2o_ECPublicKey(ec_key, &p); 1100f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (penclen <= 0) { 1110f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1120f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1130f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc, 1140f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com penclen)) { 1150f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 1; 1160f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1170f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1180f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comerr: 1190f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (ptype == V_ASN1_OBJECT) { 1200f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com ASN1_OBJECT_free(pval); 1210f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } else { 1220f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com ASN1_STRING_free(pval); 1230f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 12413881545ced98cd2ec7b175389c95bf23574bf53daniel@transgaming.com if (penc) { 1250f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_free(penc); 1260f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1270f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 1280f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com} 1290f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1300f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstatic EC_KEY *eckey_type2param(int ptype, void *pval) { 1310f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com EC_KEY *eckey = NULL; 1320f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1330f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (ptype == V_ASN1_SEQUENCE) { 1340f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com ASN1_STRING *pstr = pval; 1350f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com const uint8_t *pm = pstr->data; 1360f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com int pmlen = pstr->length; 1370f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1380f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com eckey = d2i_ECParameters(NULL, &pm, pmlen); 1390f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (eckey == NULL) { 1400f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_type2param, EVP_R_DECODE_ERROR); 1410f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1420f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1430f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } else if (ptype == V_ASN1_OBJECT) { 1440f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com ASN1_OBJECT *poid = pval; 1450f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com EC_GROUP *group; 1460f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1470f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com /* type == V_ASN1_OBJECT => the parameters are given 1480f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com * by an asn1 OID */ 1490f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com eckey = EC_KEY_new(); 1500f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (eckey == NULL) { 1510f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_type2param, ERR_R_MALLOC_FAILURE); 1520f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1530f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1540f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); 1550f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (group == NULL) { 1560f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1570f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1580f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (EC_KEY_set_group(eckey, group) == 0) { 1590f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com goto err; 1600f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 16145965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang EC_GROUP_free(group); 1620f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } else { 16345965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang OPENSSL_PUT_ERROR(EVP, eckey_type2param, EVP_R_DECODE_ERROR); 16445965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang goto err; 1650f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1660f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 16745965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang return eckey; 1680f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1690f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comerr: 1700f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (eckey) { 1710f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com EC_KEY_free(eckey); 1720f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1730f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return NULL; 1740f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com} 1750f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1760f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstatic int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { 1770f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com const uint8_t *p = NULL; 1780f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com void *pval; 1790f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com int ptype, pklen; 1800f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com EC_KEY *eckey = NULL; 1810f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com X509_ALGOR *palg; 1820f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1830f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) { 1840f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 185c21c227174ae9b23d4b719ca42694646d8dea122daniel@transgaming.com } 1860f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com X509_ALGOR_get0(NULL, &ptype, &pval, palg); 1870f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1880f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com eckey = eckey_type2param(ptype, pval); 189c21c227174ae9b23d4b719ca42694646d8dea122daniel@transgaming.com if (!eckey) { 1900f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_pub_decode, ERR_R_EC_LIB); 1910f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com return 0; 1920f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com } 1930f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com 1940f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com /* We have parameters now set public key */ 1950f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com if (!o2i_ECPublicKey(&eckey, &p, pklen)) { 1960f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com OPENSSL_PUT_ERROR(EVP, eckey_pub_decode, EVP_R_DECODE_ERROR); 1978fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com goto err; 198 } 199 200 EVP_PKEY_assign_EC_KEY(pkey, eckey); 201 return 1; 202 203err: 204 if (eckey) 205 EC_KEY_free(eckey); 206 return 0; 207} 208 209static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { 210 int r; 211 const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); 212 const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), 213 *pb = EC_KEY_get0_public_key(b->pkey.ec); 214 r = EC_POINT_cmp(group, pa, pb, NULL); 215 if (r == 0) { 216 return 1; 217 } else if (r == 1) { 218 return 0; 219 } else { 220 return -2; 221 } 222} 223 224static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) { 225 const uint8_t *p = NULL; 226 void *pval; 227 int ptype, pklen; 228 EC_KEY *eckey = NULL; 229 X509_ALGOR *palg; 230 231 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) { 232 return 0; 233 } 234 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 235 236 eckey = eckey_type2param(ptype, pval); 237 238 if (!eckey) 239 goto ecliberr; 240 241 /* We have parameters now set private key */ 242 if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { 243 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, EVP_R_DECODE_ERROR); 244 goto ecerr; 245 } 246 247 /* calculate public key (if necessary) */ 248 if (EC_KEY_get0_public_key(eckey) == NULL) { 249 const BIGNUM *priv_key; 250 const EC_GROUP *group; 251 EC_POINT *pub_key; 252 /* the public key was not included in the SEC1 private 253 * key => calculate the public key */ 254 group = EC_KEY_get0_group(eckey); 255 pub_key = EC_POINT_new(group); 256 if (pub_key == NULL) { 257 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB); 258 goto ecliberr; 259 } 260 if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { 261 EC_POINT_free(pub_key); 262 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB); 263 goto ecliberr; 264 } 265 priv_key = EC_KEY_get0_private_key(eckey); 266 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { 267 EC_POINT_free(pub_key); 268 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB); 269 goto ecliberr; 270 } 271 if (EC_KEY_set_public_key(eckey, pub_key) == 0) { 272 EC_POINT_free(pub_key); 273 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB); 274 goto ecliberr; 275 } 276 EC_POINT_free(pub_key); 277 } 278 279 EVP_PKEY_assign_EC_KEY(pkey, eckey); 280 return 1; 281 282ecliberr: 283 OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB); 284ecerr: 285 if (eckey) 286 EC_KEY_free(eckey); 287 return 0; 288} 289 290static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { 291 EC_KEY *ec_key; 292 uint8_t *ep, *p; 293 int eplen, ptype; 294 void *pval; 295 unsigned int tmp_flags, old_flags; 296 297 ec_key = pkey->pkey.ec; 298 299 if (!eckey_param2type(&ptype, &pval, ec_key)) { 300 OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, EVP_R_DECODE_ERROR); 301 return 0; 302 } 303 304 /* set the private key */ 305 306 /* do not include the parameters in the SEC1 private key 307 * see PKCS#11 12.11 */ 308 old_flags = EC_KEY_get_enc_flags(ec_key); 309 tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; 310 EC_KEY_set_enc_flags(ec_key, tmp_flags); 311 eplen = i2d_ECPrivateKey(ec_key, NULL); 312 if (!eplen) { 313 EC_KEY_set_enc_flags(ec_key, old_flags); 314 OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_EC_LIB); 315 return 0; 316 } 317 ep = (uint8_t *)OPENSSL_malloc(eplen); 318 if (!ep) { 319 EC_KEY_set_enc_flags(ec_key, old_flags); 320 OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_MALLOC_FAILURE); 321 return 0; 322 } 323 p = ep; 324 if (!i2d_ECPrivateKey(ec_key, &p)) { 325 EC_KEY_set_enc_flags(ec_key, old_flags); 326 OPENSSL_free(ep); 327 OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_EC_LIB); 328 return 0; 329 } 330 /* restore old encoding flags */ 331 EC_KEY_set_enc_flags(ec_key, old_flags); 332 333 if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 334 0, ptype, pval, ep, eplen)) { 335 return 0; 336 } 337 338 return 1; 339} 340 341static int int_ec_size(const EVP_PKEY *pkey) { 342 return ECDSA_size(pkey->pkey.ec); 343} 344 345static int ec_bits(const EVP_PKEY *pkey) { 346 BIGNUM *order = BN_new(); 347 const EC_GROUP *group; 348 int ret; 349 350 if (!order) { 351 ERR_clear_error(); 352 return 0; 353 } 354 group = EC_KEY_get0_group(pkey->pkey.ec); 355 if (!EC_GROUP_get_order(group, order, NULL)) { 356 ERR_clear_error(); 357 return 0; 358 } 359 360 ret = BN_num_bits(order); 361 BN_free(order); 362 return ret; 363} 364 365static int ec_missing_parameters(const EVP_PKEY *pkey) { 366 return EC_KEY_get0_group(pkey->pkey.ec) == NULL; 367} 368 369static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { 370 EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); 371 if (group == NULL || 372 EC_KEY_set_group(to->pkey.ec, group) == 0) { 373 return 0; 374 } 375 EC_GROUP_free(group); 376 return 1; 377} 378 379static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { 380 const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), 381 *group_b = EC_KEY_get0_group(b->pkey.ec); 382 return EC_GROUP_cmp(group_a, group_b); 383} 384 385static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); } 386 387static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { 388 uint8_t *buffer = NULL; 389 const char *ecstr; 390 size_t buf_len = 0, i; 391 int ret = 0, reason = ERR_R_BIO_LIB; 392 BIGNUM *order = NULL; 393 BN_CTX *ctx = NULL; 394 const EC_GROUP *group; 395 const EC_POINT *public_key; 396 const BIGNUM *priv_key; 397 uint8_t *pub_key_bytes = NULL; 398 size_t pub_key_bytes_len = 0; 399 400 if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { 401 reason = ERR_R_PASSED_NULL_PARAMETER; 402 goto err; 403 } 404 405 ctx = BN_CTX_new(); 406 if (ctx == NULL) { 407 reason = ERR_R_MALLOC_FAILURE; 408 goto err; 409 } 410 411 if (ktype > 0) { 412 public_key = EC_KEY_get0_public_key(x); 413 if (public_key != NULL) { 414 pub_key_bytes_len = EC_POINT_point2oct( 415 group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx); 416 if (pub_key_bytes_len == 0) { 417 reason = ERR_R_MALLOC_FAILURE; 418 goto err; 419 } 420 pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len); 421 if (pub_key_bytes == NULL) { 422 reason = ERR_R_MALLOC_FAILURE; 423 goto err; 424 } 425 pub_key_bytes_len = 426 EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x), 427 pub_key_bytes, pub_key_bytes_len, ctx); 428 if (pub_key_bytes_len == 0) { 429 reason = ERR_R_MALLOC_FAILURE; 430 goto err; 431 } 432 buf_len = pub_key_bytes_len; 433 } 434 } 435 436 if (ktype == 2) { 437 priv_key = EC_KEY_get0_private_key(x); 438 if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) 439 buf_len = i; 440 } else 441 priv_key = NULL; 442 443 if (ktype > 0) { 444 buf_len += 10; 445 if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { 446 reason = ERR_R_MALLOC_FAILURE; 447 goto err; 448 } 449 } 450 if (ktype == 2) 451 ecstr = "Private-Key"; 452 else if (ktype == 1) 453 ecstr = "Public-Key"; 454 else 455 ecstr = "ECDSA-Parameters"; 456 457 if (!BIO_indent(bp, off, 128)) 458 goto err; 459 if ((order = BN_new()) == NULL) 460 goto err; 461 if (!EC_GROUP_get_order(group, order, NULL)) 462 goto err; 463 if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) 464 goto err; 465 466 if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) 467 goto err; 468 if (pub_key_bytes != NULL) { 469 BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off); 470 } 471 /* TODO(fork): implement */ 472 /* 473 if (!ECPKParameters_print(bp, group, off)) 474 goto err; */ 475 ret = 1; 476 477err: 478 if (!ret) 479 OPENSSL_PUT_ERROR(EVP, do_EC_KEY_print, reason); 480 if (pub_key_bytes) 481 OPENSSL_free(pub_key_bytes); 482 if (order) 483 BN_free(order); 484 if (ctx) 485 BN_CTX_free(ctx); 486 if (buffer != NULL) 487 OPENSSL_free(buffer); 488 return ret; 489} 490 491static int eckey_param_decode(EVP_PKEY *pkey, const uint8_t **pder, 492 int derlen) { 493 EC_KEY *eckey; 494 if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) { 495 OPENSSL_PUT_ERROR(EVP, eckey_param_decode, ERR_R_EC_LIB); 496 return 0; 497 } 498 EVP_PKEY_assign_EC_KEY(pkey, eckey); 499 return 1; 500} 501 502static int eckey_param_encode(const EVP_PKEY *pkey, uint8_t **pder) { 503 return i2d_ECParameters(pkey->pkey.ec, pder); 504} 505 506static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, 507 ASN1_PCTX *ctx) { 508 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); 509} 510 511static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, 512 ASN1_PCTX *ctx) { 513 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); 514} 515 516 517static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, 518 ASN1_PCTX *ctx) { 519 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); 520} 521 522static int eckey_opaque(const EVP_PKEY *pkey) { 523 return EC_KEY_is_opaque(pkey->pkey.ec); 524} 525 526static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder, 527 int derlen) { 528 EC_KEY *ec; 529 if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) { 530 OPENSSL_PUT_ERROR(EVP, old_ec_priv_decode, EVP_R_DECODE_ERROR); 531 return 0; 532 } 533 EVP_PKEY_assign_EC_KEY(pkey, ec); 534 return 1; 535} 536 537static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) { 538 return i2d_ECPrivateKey(pkey->pkey.ec, pder); 539} 540 541static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) { 542 switch (op) { 543 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 544 *(int *)arg2 = NID_sha1; 545 return 2; 546 547 default: 548 return -2; 549 } 550} 551 552const EVP_PKEY_ASN1_METHOD ec_asn1_meth = { 553 EVP_PKEY_EC, 554 EVP_PKEY_EC, 555 0, 556 "EC", 557 "OpenSSL EC algorithm", 558 559 eckey_pub_decode, 560 eckey_pub_encode, 561 eckey_pub_cmp, 562 eckey_pub_print, 563 564 eckey_priv_decode, 565 eckey_priv_encode, 566 eckey_priv_print, 567 568 eckey_opaque, 569 570 int_ec_size, 571 ec_bits, 572 573 eckey_param_decode, 574 eckey_param_encode, 575 ec_missing_parameters, 576 ec_copy_parameters, 577 ec_cmp_parameters, 578 eckey_param_print, 579 0, 580 581 int_ec_free, 582 ec_pkey_ctrl, 583 old_ec_priv_decode, 584 old_ec_priv_encode 585}; 586