ec_asn1.c revision 160814
1160814Ssimon/* crypto/ec/ec_asn1.c */ 2160814Ssimon/* 3160814Ssimon * Written by Nils Larsch for the OpenSSL project. 4160814Ssimon */ 5160814Ssimon/* ==================================================================== 6160814Ssimon * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. 7160814Ssimon * 8160814Ssimon * Redistribution and use in source and binary forms, with or without 9160814Ssimon * modification, are permitted provided that the following conditions 10160814Ssimon * are met: 11160814Ssimon * 12160814Ssimon * 1. Redistributions of source code must retain the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer. 14160814Ssimon * 15160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 16160814Ssimon * notice, this list of conditions and the following disclaimer in 17160814Ssimon * the documentation and/or other materials provided with the 18160814Ssimon * distribution. 19160814Ssimon * 20160814Ssimon * 3. All advertising materials mentioning features or use of this 21160814Ssimon * software must display the following acknowledgment: 22160814Ssimon * "This product includes software developed by the OpenSSL Project 23160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24160814Ssimon * 25160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26160814Ssimon * endorse or promote products derived from this software without 27160814Ssimon * prior written permission. For written permission, please contact 28160814Ssimon * licensing@OpenSSL.org. 29160814Ssimon * 30160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 31160814Ssimon * nor may "OpenSSL" appear in their names without prior written 32160814Ssimon * permission of the OpenSSL Project. 33160814Ssimon * 34160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 35160814Ssimon * acknowledgment: 36160814Ssimon * "This product includes software developed by the OpenSSL Project 37160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38160814Ssimon * 39160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 51160814Ssimon * ==================================================================== 52160814Ssimon * 53160814Ssimon * This product includes cryptographic software written by Eric Young 54160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 55160814Ssimon * Hudson (tjh@cryptsoft.com). 56160814Ssimon * 57160814Ssimon */ 58160814Ssimon 59160814Ssimon#include <string.h> 60160814Ssimon#include "ec_lcl.h" 61160814Ssimon#include <openssl/err.h> 62160814Ssimon#include <openssl/asn1t.h> 63160814Ssimon#include <openssl/objects.h> 64160814Ssimon 65160814Ssimon 66160814Ssimonint EC_GROUP_get_basis_type(const EC_GROUP *group) 67160814Ssimon { 68160814Ssimon int i=0; 69160814Ssimon 70160814Ssimon if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != 71160814Ssimon NID_X9_62_characteristic_two_field) 72160814Ssimon /* everything else is currently not supported */ 73160814Ssimon return 0; 74160814Ssimon 75160814Ssimon while (group->poly[i] != 0) 76160814Ssimon i++; 77160814Ssimon 78160814Ssimon if (i == 4) 79160814Ssimon return NID_X9_62_ppBasis; 80160814Ssimon else if (i == 2) 81160814Ssimon return NID_X9_62_tpBasis; 82160814Ssimon else 83160814Ssimon /* everything else is currently not supported */ 84160814Ssimon return 0; 85160814Ssimon } 86160814Ssimon 87160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) 88160814Ssimon { 89160814Ssimon if (group == NULL) 90160814Ssimon return 0; 91160814Ssimon 92160814Ssimon if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve 93160814Ssimon || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0))) 94160814Ssimon { 95160814Ssimon ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 96160814Ssimon return 0; 97160814Ssimon } 98160814Ssimon 99160814Ssimon if (k) 100160814Ssimon *k = group->poly[1]; 101160814Ssimon 102160814Ssimon return 1; 103160814Ssimon } 104160814Ssimon 105160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, 106160814Ssimon unsigned int *k2, unsigned int *k3) 107160814Ssimon { 108160814Ssimon if (group == NULL) 109160814Ssimon return 0; 110160814Ssimon 111160814Ssimon if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve 112160814Ssimon || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0))) 113160814Ssimon { 114160814Ssimon ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 115160814Ssimon return 0; 116160814Ssimon } 117160814Ssimon 118160814Ssimon if (k1) 119160814Ssimon *k1 = group->poly[3]; 120160814Ssimon if (k2) 121160814Ssimon *k2 = group->poly[2]; 122160814Ssimon if (k3) 123160814Ssimon *k3 = group->poly[1]; 124160814Ssimon 125160814Ssimon return 1; 126160814Ssimon } 127160814Ssimon 128160814Ssimon 129160814Ssimon 130160814Ssimon/* some structures needed for the asn1 encoding */ 131160814Ssimontypedef struct x9_62_pentanomial_st { 132160814Ssimon long k1; 133160814Ssimon long k2; 134160814Ssimon long k3; 135160814Ssimon } X9_62_PENTANOMIAL; 136160814Ssimon 137160814Ssimontypedef struct x9_62_characteristic_two_st { 138160814Ssimon long m; 139160814Ssimon ASN1_OBJECT *type; 140160814Ssimon union { 141160814Ssimon char *ptr; 142160814Ssimon /* NID_X9_62_onBasis */ 143160814Ssimon ASN1_NULL *onBasis; 144160814Ssimon /* NID_X9_62_tpBasis */ 145160814Ssimon ASN1_INTEGER *tpBasis; 146160814Ssimon /* NID_X9_62_ppBasis */ 147160814Ssimon X9_62_PENTANOMIAL *ppBasis; 148160814Ssimon /* anything else */ 149160814Ssimon ASN1_TYPE *other; 150160814Ssimon } p; 151160814Ssimon } X9_62_CHARACTERISTIC_TWO; 152160814Ssimon 153160814Ssimontypedef struct x9_62_fieldid_st { 154160814Ssimon ASN1_OBJECT *fieldType; 155160814Ssimon union { 156160814Ssimon char *ptr; 157160814Ssimon /* NID_X9_62_prime_field */ 158160814Ssimon ASN1_INTEGER *prime; 159160814Ssimon /* NID_X9_62_characteristic_two_field */ 160160814Ssimon X9_62_CHARACTERISTIC_TWO *char_two; 161160814Ssimon /* anything else */ 162160814Ssimon ASN1_TYPE *other; 163160814Ssimon } p; 164160814Ssimon } X9_62_FIELDID; 165160814Ssimon 166160814Ssimontypedef struct x9_62_curve_st { 167160814Ssimon ASN1_OCTET_STRING *a; 168160814Ssimon ASN1_OCTET_STRING *b; 169160814Ssimon ASN1_BIT_STRING *seed; 170160814Ssimon } X9_62_CURVE; 171160814Ssimon 172160814Ssimontypedef struct ec_parameters_st { 173160814Ssimon long version; 174160814Ssimon X9_62_FIELDID *fieldID; 175160814Ssimon X9_62_CURVE *curve; 176160814Ssimon ASN1_OCTET_STRING *base; 177160814Ssimon ASN1_INTEGER *order; 178160814Ssimon ASN1_INTEGER *cofactor; 179160814Ssimon } ECPARAMETERS; 180160814Ssimon 181160814Ssimonstruct ecpk_parameters_st { 182160814Ssimon int type; 183160814Ssimon union { 184160814Ssimon ASN1_OBJECT *named_curve; 185160814Ssimon ECPARAMETERS *parameters; 186160814Ssimon ASN1_NULL *implicitlyCA; 187160814Ssimon } value; 188160814Ssimon }/* ECPKPARAMETERS */; 189160814Ssimon 190160814Ssimon/* SEC1 ECPrivateKey */ 191160814Ssimontypedef struct ec_privatekey_st { 192160814Ssimon long version; 193160814Ssimon ASN1_OCTET_STRING *privateKey; 194160814Ssimon ECPKPARAMETERS *parameters; 195160814Ssimon ASN1_BIT_STRING *publicKey; 196160814Ssimon } EC_PRIVATEKEY; 197160814Ssimon 198160814Ssimon/* the OpenSSL ASN.1 definitions */ 199160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = { 200160814Ssimon ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), 201160814Ssimon ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), 202160814Ssimon ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) 203160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) 204160814Ssimon 205160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) 206160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) 207160814Ssimon 208160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY); 209160814Ssimon 210160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { 211160814Ssimon ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), 212160814Ssimon ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), 213160814Ssimon ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) 214160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); 215160814Ssimon 216160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { 217160814Ssimon ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), 218160814Ssimon ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), 219160814Ssimon ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) 220160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) 221160814Ssimon 222160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) 223160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) 224160814Ssimon 225160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY); 226160814Ssimon 227160814SsimonASN1_ADB(X9_62_FIELDID) = { 228160814Ssimon ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), 229160814Ssimon ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) 230160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL); 231160814Ssimon 232160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = { 233160814Ssimon ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), 234160814Ssimon ASN1_ADB_OBJECT(X9_62_FIELDID) 235160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID) 236160814Ssimon 237160814SsimonASN1_SEQUENCE(X9_62_CURVE) = { 238160814Ssimon ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), 239160814Ssimon ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), 240160814Ssimon ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) 241160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE) 242160814Ssimon 243160814SsimonASN1_SEQUENCE(ECPARAMETERS) = { 244160814Ssimon ASN1_SIMPLE(ECPARAMETERS, version, LONG), 245160814Ssimon ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), 246160814Ssimon ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), 247160814Ssimon ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), 248160814Ssimon ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), 249160814Ssimon ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) 250160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS) 251160814Ssimon 252160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) 253160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) 254160814Ssimon 255160814SsimonASN1_CHOICE(ECPKPARAMETERS) = { 256160814Ssimon ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), 257160814Ssimon ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), 258160814Ssimon ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) 259160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS) 260160814Ssimon 261160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) 262160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) 263160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) 264160814Ssimon 265160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = { 266160814Ssimon ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), 267160814Ssimon ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), 268160814Ssimon ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), 269160814Ssimon ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) 270160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY) 271160814Ssimon 272160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) 273160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) 274160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) 275160814Ssimon 276160814Ssimon/* some declarations of internal function */ 277160814Ssimon 278160814Ssimon/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ 279160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); 280160814Ssimon/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ 281160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); 282160814Ssimon/* ec_asn1_parameters2group() creates a EC_GROUP object from a 283160814Ssimon * ECPARAMETERS object */ 284160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); 285160814Ssimon/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a 286160814Ssimon * EC_GROUP object */ 287160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *); 288160814Ssimon/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a 289160814Ssimon * ECPKPARAMETERS object */ 290160814Ssimonstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); 291160814Ssimon/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a 292160814Ssimon * EC_GROUP object */ 293160814Ssimonstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, 294160814Ssimon ECPKPARAMETERS *); 295160814Ssimon 296160814Ssimon 297160814Ssimon/* the function definitions */ 298160814Ssimon 299160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) 300160814Ssimon { 301160814Ssimon int ok=0, nid; 302160814Ssimon BIGNUM *tmp = NULL; 303160814Ssimon 304160814Ssimon if (group == NULL || field == NULL) 305160814Ssimon return 0; 306160814Ssimon 307160814Ssimon /* clear the old values (if necessary) */ 308160814Ssimon if (field->fieldType != NULL) 309160814Ssimon ASN1_OBJECT_free(field->fieldType); 310160814Ssimon if (field->p.other != NULL) 311160814Ssimon ASN1_TYPE_free(field->p.other); 312160814Ssimon 313160814Ssimon nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 314160814Ssimon /* set OID for the field */ 315160814Ssimon if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) 316160814Ssimon { 317160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); 318160814Ssimon goto err; 319160814Ssimon } 320160814Ssimon 321160814Ssimon if (nid == NID_X9_62_prime_field) 322160814Ssimon { 323160814Ssimon if ((tmp = BN_new()) == NULL) 324160814Ssimon { 325160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 326160814Ssimon goto err; 327160814Ssimon } 328160814Ssimon /* the parameters are specified by the prime number p */ 329160814Ssimon if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) 330160814Ssimon { 331160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); 332160814Ssimon goto err; 333160814Ssimon } 334160814Ssimon /* set the prime number */ 335160814Ssimon field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL); 336160814Ssimon if (field->p.prime == NULL) 337160814Ssimon { 338160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); 339160814Ssimon goto err; 340160814Ssimon } 341160814Ssimon } 342160814Ssimon else /* nid == NID_X9_62_characteristic_two_field */ 343160814Ssimon { 344160814Ssimon int field_type; 345160814Ssimon X9_62_CHARACTERISTIC_TWO *char_two; 346160814Ssimon 347160814Ssimon field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); 348160814Ssimon char_two = field->p.char_two; 349160814Ssimon 350160814Ssimon if (char_two == NULL) 351160814Ssimon { 352160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 353160814Ssimon goto err; 354160814Ssimon } 355160814Ssimon 356160814Ssimon char_two->m = (long)EC_GROUP_get_degree(group); 357160814Ssimon 358160814Ssimon field_type = EC_GROUP_get_basis_type(group); 359160814Ssimon 360160814Ssimon if (field_type == 0) 361160814Ssimon { 362160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); 363160814Ssimon goto err; 364160814Ssimon } 365160814Ssimon /* set base type OID */ 366160814Ssimon if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) 367160814Ssimon { 368160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); 369160814Ssimon goto err; 370160814Ssimon } 371160814Ssimon 372160814Ssimon if (field_type == NID_X9_62_tpBasis) 373160814Ssimon { 374160814Ssimon unsigned int k; 375160814Ssimon 376160814Ssimon if (!EC_GROUP_get_trinomial_basis(group, &k)) 377160814Ssimon goto err; 378160814Ssimon 379160814Ssimon char_two->p.tpBasis = ASN1_INTEGER_new(); 380160814Ssimon if (!char_two->p.tpBasis) 381160814Ssimon { 382160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 383160814Ssimon goto err; 384160814Ssimon } 385160814Ssimon if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) 386160814Ssimon { 387160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, 388160814Ssimon ERR_R_ASN1_LIB); 389160814Ssimon goto err; 390160814Ssimon } 391160814Ssimon } 392160814Ssimon else if (field_type == NID_X9_62_ppBasis) 393160814Ssimon { 394160814Ssimon unsigned int k1, k2, k3; 395160814Ssimon 396160814Ssimon if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) 397160814Ssimon goto err; 398160814Ssimon 399160814Ssimon char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); 400160814Ssimon if (!char_two->p.ppBasis) 401160814Ssimon { 402160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 403160814Ssimon goto err; 404160814Ssimon } 405160814Ssimon 406160814Ssimon /* set k? values */ 407160814Ssimon char_two->p.ppBasis->k1 = (long)k1; 408160814Ssimon char_two->p.ppBasis->k2 = (long)k2; 409160814Ssimon char_two->p.ppBasis->k3 = (long)k3; 410160814Ssimon } 411160814Ssimon else /* field_type == NID_X9_62_onBasis */ 412160814Ssimon { 413160814Ssimon /* for ONB the parameters are (asn1) NULL */ 414160814Ssimon char_two->p.onBasis = ASN1_NULL_new(); 415160814Ssimon if (!char_two->p.onBasis) 416160814Ssimon { 417160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 418160814Ssimon goto err; 419160814Ssimon } 420160814Ssimon } 421160814Ssimon } 422160814Ssimon 423160814Ssimon ok = 1; 424160814Ssimon 425160814Ssimonerr : if (tmp) 426160814Ssimon BN_free(tmp); 427160814Ssimon return(ok); 428160814Ssimon} 429160814Ssimon 430160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) 431160814Ssimon { 432160814Ssimon int ok=0, nid; 433160814Ssimon BIGNUM *tmp_1=NULL, *tmp_2=NULL; 434160814Ssimon unsigned char *buffer_1=NULL, *buffer_2=NULL, 435160814Ssimon *a_buf=NULL, *b_buf=NULL; 436160814Ssimon size_t len_1, len_2; 437160814Ssimon unsigned char char_zero = 0; 438160814Ssimon 439160814Ssimon if (!group || !curve || !curve->a || !curve->b) 440160814Ssimon return 0; 441160814Ssimon 442160814Ssimon if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) 443160814Ssimon { 444160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 445160814Ssimon goto err; 446160814Ssimon } 447160814Ssimon 448160814Ssimon nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 449160814Ssimon 450160814Ssimon /* get a and b */ 451160814Ssimon if (nid == NID_X9_62_prime_field) 452160814Ssimon { 453160814Ssimon if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) 454160814Ssimon { 455160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); 456160814Ssimon goto err; 457160814Ssimon } 458160814Ssimon } 459160814Ssimon else /* nid == NID_X9_62_characteristic_two_field */ 460160814Ssimon { 461160814Ssimon if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) 462160814Ssimon { 463160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); 464160814Ssimon goto err; 465160814Ssimon } 466160814Ssimon } 467160814Ssimon 468160814Ssimon len_1 = (size_t)BN_num_bytes(tmp_1); 469160814Ssimon len_2 = (size_t)BN_num_bytes(tmp_2); 470160814Ssimon 471160814Ssimon if (len_1 == 0) 472160814Ssimon { 473160814Ssimon /* len_1 == 0 => a == 0 */ 474160814Ssimon a_buf = &char_zero; 475160814Ssimon len_1 = 1; 476160814Ssimon } 477160814Ssimon else 478160814Ssimon { 479160814Ssimon if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) 480160814Ssimon { 481160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, 482160814Ssimon ERR_R_MALLOC_FAILURE); 483160814Ssimon goto err; 484160814Ssimon } 485160814Ssimon if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) 486160814Ssimon { 487160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); 488160814Ssimon goto err; 489160814Ssimon } 490160814Ssimon a_buf = buffer_1; 491160814Ssimon } 492160814Ssimon 493160814Ssimon if (len_2 == 0) 494160814Ssimon { 495160814Ssimon /* len_2 == 0 => b == 0 */ 496160814Ssimon b_buf = &char_zero; 497160814Ssimon len_2 = 1; 498160814Ssimon } 499160814Ssimon else 500160814Ssimon { 501160814Ssimon if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) 502160814Ssimon { 503160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, 504160814Ssimon ERR_R_MALLOC_FAILURE); 505160814Ssimon goto err; 506160814Ssimon } 507160814Ssimon if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) 508160814Ssimon { 509160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); 510160814Ssimon goto err; 511160814Ssimon } 512160814Ssimon b_buf = buffer_2; 513160814Ssimon } 514160814Ssimon 515160814Ssimon /* set a and b */ 516160814Ssimon if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) || 517160814Ssimon !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) 518160814Ssimon { 519160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); 520160814Ssimon goto err; 521160814Ssimon } 522160814Ssimon 523160814Ssimon /* set the seed (optional) */ 524160814Ssimon if (group->seed) 525160814Ssimon { 526160814Ssimon if (!curve->seed) 527160814Ssimon if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) 528160814Ssimon { 529160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 530160814Ssimon goto err; 531160814Ssimon } 532160814Ssimon if (!ASN1_BIT_STRING_set(curve->seed, group->seed, 533160814Ssimon (int)group->seed_len)) 534160814Ssimon { 535160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); 536160814Ssimon goto err; 537160814Ssimon } 538160814Ssimon } 539160814Ssimon else 540160814Ssimon { 541160814Ssimon if (curve->seed) 542160814Ssimon { 543160814Ssimon ASN1_BIT_STRING_free(curve->seed); 544160814Ssimon curve->seed = NULL; 545160814Ssimon } 546160814Ssimon } 547160814Ssimon 548160814Ssimon ok = 1; 549160814Ssimon 550160814Ssimonerr: if (buffer_1) 551160814Ssimon OPENSSL_free(buffer_1); 552160814Ssimon if (buffer_2) 553160814Ssimon OPENSSL_free(buffer_2); 554160814Ssimon if (tmp_1) 555160814Ssimon BN_free(tmp_1); 556160814Ssimon if (tmp_2) 557160814Ssimon BN_free(tmp_2); 558160814Ssimon return(ok); 559160814Ssimon } 560160814Ssimon 561160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group, 562160814Ssimon ECPARAMETERS *param) 563160814Ssimon { 564160814Ssimon int ok=0; 565160814Ssimon size_t len=0; 566160814Ssimon ECPARAMETERS *ret=NULL; 567160814Ssimon BIGNUM *tmp=NULL; 568160814Ssimon unsigned char *buffer=NULL; 569160814Ssimon const EC_POINT *point=NULL; 570160814Ssimon point_conversion_form_t form; 571160814Ssimon 572160814Ssimon if ((tmp = BN_new()) == NULL) 573160814Ssimon { 574160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 575160814Ssimon goto err; 576160814Ssimon } 577160814Ssimon 578160814Ssimon if (param == NULL) 579160814Ssimon { 580160814Ssimon if ((ret = ECPARAMETERS_new()) == NULL) 581160814Ssimon { 582160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, 583160814Ssimon ERR_R_MALLOC_FAILURE); 584160814Ssimon goto err; 585160814Ssimon } 586160814Ssimon } 587160814Ssimon else 588160814Ssimon ret = param; 589160814Ssimon 590160814Ssimon /* set the version (always one) */ 591160814Ssimon ret->version = (long)0x1; 592160814Ssimon 593160814Ssimon /* set the fieldID */ 594160814Ssimon if (!ec_asn1_group2fieldid(group, ret->fieldID)) 595160814Ssimon { 596160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 597160814Ssimon goto err; 598160814Ssimon } 599160814Ssimon 600160814Ssimon /* set the curve */ 601160814Ssimon if (!ec_asn1_group2curve(group, ret->curve)) 602160814Ssimon { 603160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 604160814Ssimon goto err; 605160814Ssimon } 606160814Ssimon 607160814Ssimon /* set the base point */ 608160814Ssimon if ((point = EC_GROUP_get0_generator(group)) == NULL) 609160814Ssimon { 610160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); 611160814Ssimon goto err; 612160814Ssimon } 613160814Ssimon 614160814Ssimon form = EC_GROUP_get_point_conversion_form(group); 615160814Ssimon 616160814Ssimon len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); 617160814Ssimon if (len == 0) 618160814Ssimon { 619160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 620160814Ssimon goto err; 621160814Ssimon } 622160814Ssimon if ((buffer = OPENSSL_malloc(len)) == NULL) 623160814Ssimon { 624160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 625160814Ssimon goto err; 626160814Ssimon } 627160814Ssimon if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) 628160814Ssimon { 629160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 630160814Ssimon goto err; 631160814Ssimon } 632160814Ssimon if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) 633160814Ssimon { 634160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 635160814Ssimon goto err; 636160814Ssimon } 637160814Ssimon if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) 638160814Ssimon { 639160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 640160814Ssimon goto err; 641160814Ssimon } 642160814Ssimon 643160814Ssimon /* set the order */ 644160814Ssimon if (!EC_GROUP_get_order(group, tmp, NULL)) 645160814Ssimon { 646160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 647160814Ssimon goto err; 648160814Ssimon } 649160814Ssimon ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); 650160814Ssimon if (ret->order == NULL) 651160814Ssimon { 652160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 653160814Ssimon goto err; 654160814Ssimon } 655160814Ssimon 656160814Ssimon /* set the cofactor (optional) */ 657160814Ssimon if (EC_GROUP_get_cofactor(group, tmp, NULL)) 658160814Ssimon { 659160814Ssimon ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); 660160814Ssimon if (ret->cofactor == NULL) 661160814Ssimon { 662160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 663160814Ssimon goto err; 664160814Ssimon } 665160814Ssimon } 666160814Ssimon 667160814Ssimon ok = 1; 668160814Ssimon 669160814Ssimonerr : if(!ok) 670160814Ssimon { 671160814Ssimon if (ret && !param) 672160814Ssimon ECPARAMETERS_free(ret); 673160814Ssimon ret = NULL; 674160814Ssimon } 675160814Ssimon if (tmp) 676160814Ssimon BN_free(tmp); 677160814Ssimon if (buffer) 678160814Ssimon OPENSSL_free(buffer); 679160814Ssimon return(ret); 680160814Ssimon } 681160814Ssimon 682160814SsimonECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, 683160814Ssimon ECPKPARAMETERS *params) 684160814Ssimon { 685160814Ssimon int ok = 1, tmp; 686160814Ssimon ECPKPARAMETERS *ret = params; 687160814Ssimon 688160814Ssimon if (ret == NULL) 689160814Ssimon { 690160814Ssimon if ((ret = ECPKPARAMETERS_new()) == NULL) 691160814Ssimon { 692160814Ssimon ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, 693160814Ssimon ERR_R_MALLOC_FAILURE); 694160814Ssimon return NULL; 695160814Ssimon } 696160814Ssimon } 697160814Ssimon else 698160814Ssimon { 699160814Ssimon if (ret->type == 0 && ret->value.named_curve) 700160814Ssimon ASN1_OBJECT_free(ret->value.named_curve); 701160814Ssimon else if (ret->type == 1 && ret->value.parameters) 702160814Ssimon ECPARAMETERS_free(ret->value.parameters); 703160814Ssimon } 704160814Ssimon 705160814Ssimon if (EC_GROUP_get_asn1_flag(group)) 706160814Ssimon { 707160814Ssimon /* use the asn1 OID to describe the 708160814Ssimon * the elliptic curve parameters 709160814Ssimon */ 710160814Ssimon tmp = EC_GROUP_get_curve_name(group); 711160814Ssimon if (tmp) 712160814Ssimon { 713160814Ssimon ret->type = 0; 714160814Ssimon if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) 715160814Ssimon ok = 0; 716160814Ssimon } 717160814Ssimon else 718160814Ssimon /* we don't kmow the nid => ERROR */ 719160814Ssimon ok = 0; 720160814Ssimon } 721160814Ssimon else 722160814Ssimon { 723160814Ssimon /* use the ECPARAMETERS structure */ 724160814Ssimon ret->type = 1; 725160814Ssimon if ((ret->value.parameters = ec_asn1_group2parameters( 726160814Ssimon group, NULL)) == NULL) 727160814Ssimon ok = 0; 728160814Ssimon } 729160814Ssimon 730160814Ssimon if (!ok) 731160814Ssimon { 732160814Ssimon ECPKPARAMETERS_free(ret); 733160814Ssimon return NULL; 734160814Ssimon } 735160814Ssimon return ret; 736160814Ssimon } 737160814Ssimon 738160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) 739160814Ssimon { 740160814Ssimon int ok = 0, tmp; 741160814Ssimon EC_GROUP *ret = NULL; 742160814Ssimon BIGNUM *p = NULL, *a = NULL, *b = NULL; 743160814Ssimon EC_POINT *point=NULL; 744160814Ssimon 745160814Ssimon if (!params->fieldID || !params->fieldID->fieldType || 746160814Ssimon !params->fieldID->p.ptr) 747160814Ssimon { 748160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 749160814Ssimon goto err; 750160814Ssimon } 751160814Ssimon 752160814Ssimon /* now extract the curve parameters a and b */ 753160814Ssimon if (!params->curve || !params->curve->a || 754160814Ssimon !params->curve->a->data || !params->curve->b || 755160814Ssimon !params->curve->b->data) 756160814Ssimon { 757160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 758160814Ssimon goto err; 759160814Ssimon } 760160814Ssimon a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); 761160814Ssimon if (a == NULL) 762160814Ssimon { 763160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); 764160814Ssimon goto err; 765160814Ssimon } 766160814Ssimon b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); 767160814Ssimon if (b == NULL) 768160814Ssimon { 769160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); 770160814Ssimon goto err; 771160814Ssimon } 772160814Ssimon 773160814Ssimon /* get the field parameters */ 774160814Ssimon tmp = OBJ_obj2nid(params->fieldID->fieldType); 775160814Ssimon 776160814Ssimon if (tmp == NID_X9_62_characteristic_two_field) 777160814Ssimon { 778160814Ssimon X9_62_CHARACTERISTIC_TWO *char_two; 779160814Ssimon 780160814Ssimon char_two = params->fieldID->p.char_two; 781160814Ssimon 782160814Ssimon if ((p = BN_new()) == NULL) 783160814Ssimon { 784160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); 785160814Ssimon goto err; 786160814Ssimon } 787160814Ssimon 788160814Ssimon /* get the base type */ 789160814Ssimon tmp = OBJ_obj2nid(char_two->type); 790160814Ssimon 791160814Ssimon if (tmp == NID_X9_62_tpBasis) 792160814Ssimon { 793160814Ssimon long tmp_long; 794160814Ssimon 795160814Ssimon if (!char_two->p.tpBasis) 796160814Ssimon { 797160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 798160814Ssimon goto err; 799160814Ssimon } 800160814Ssimon 801160814Ssimon tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); 802160814Ssimon /* create the polynomial */ 803160814Ssimon if (!BN_set_bit(p, (int)char_two->m)) 804160814Ssimon goto err; 805160814Ssimon if (!BN_set_bit(p, (int)tmp_long)) 806160814Ssimon goto err; 807160814Ssimon if (!BN_set_bit(p, 0)) 808160814Ssimon goto err; 809160814Ssimon } 810160814Ssimon else if (tmp == NID_X9_62_ppBasis) 811160814Ssimon { 812160814Ssimon X9_62_PENTANOMIAL *penta; 813160814Ssimon 814160814Ssimon penta = char_two->p.ppBasis; 815160814Ssimon if (!penta) 816160814Ssimon { 817160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 818160814Ssimon goto err; 819160814Ssimon } 820160814Ssimon /* create the polynomial */ 821160814Ssimon if (!BN_set_bit(p, (int)char_two->m)) goto err; 822160814Ssimon if (!BN_set_bit(p, (int)penta->k1)) goto err; 823160814Ssimon if (!BN_set_bit(p, (int)penta->k2)) goto err; 824160814Ssimon if (!BN_set_bit(p, (int)penta->k3)) goto err; 825160814Ssimon if (!BN_set_bit(p, 0)) goto err; 826160814Ssimon } 827160814Ssimon else if (tmp == NID_X9_62_onBasis) 828160814Ssimon { 829160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); 830160814Ssimon goto err; 831160814Ssimon } 832160814Ssimon else /* error */ 833160814Ssimon { 834160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 835160814Ssimon goto err; 836160814Ssimon } 837160814Ssimon 838160814Ssimon /* create the EC_GROUP structure */ 839160814Ssimon ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); 840160814Ssimon } 841160814Ssimon else if (tmp == NID_X9_62_prime_field) 842160814Ssimon { 843160814Ssimon /* we have a curve over a prime field */ 844160814Ssimon /* extract the prime number */ 845160814Ssimon if (!params->fieldID->p.prime) 846160814Ssimon { 847160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 848160814Ssimon goto err; 849160814Ssimon } 850160814Ssimon p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); 851160814Ssimon if (p == NULL) 852160814Ssimon { 853160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 854160814Ssimon goto err; 855160814Ssimon } 856160814Ssimon /* create the EC_GROUP structure */ 857160814Ssimon ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); 858160814Ssimon } 859160814Ssimon else 860160814Ssimon { 861160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); 862160814Ssimon goto err; 863160814Ssimon } 864160814Ssimon 865160814Ssimon if (ret == NULL) 866160814Ssimon { 867160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 868160814Ssimon goto err; 869160814Ssimon } 870160814Ssimon 871160814Ssimon /* extract seed (optional) */ 872160814Ssimon if (params->curve->seed != NULL) 873160814Ssimon { 874160814Ssimon if (ret->seed != NULL) 875160814Ssimon OPENSSL_free(ret->seed); 876160814Ssimon if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) 877160814Ssimon { 878160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, 879160814Ssimon ERR_R_MALLOC_FAILURE); 880160814Ssimon goto err; 881160814Ssimon } 882160814Ssimon memcpy(ret->seed, params->curve->seed->data, 883160814Ssimon params->curve->seed->length); 884160814Ssimon ret->seed_len = params->curve->seed->length; 885160814Ssimon } 886160814Ssimon 887160814Ssimon if (!params->order || !params->base || !params->base->data) 888160814Ssimon { 889160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 890160814Ssimon goto err; 891160814Ssimon } 892160814Ssimon 893160814Ssimon if ((point = EC_POINT_new(ret)) == NULL) goto err; 894160814Ssimon 895160814Ssimon /* set the point conversion form */ 896160814Ssimon EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) 897160814Ssimon (params->base->data[0] & ~0x01)); 898160814Ssimon 899160814Ssimon /* extract the ec point */ 900160814Ssimon if (!EC_POINT_oct2point(ret, point, params->base->data, 901160814Ssimon params->base->length, NULL)) 902160814Ssimon { 903160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 904160814Ssimon goto err; 905160814Ssimon } 906160814Ssimon 907160814Ssimon /* extract the order */ 908160814Ssimon if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) 909160814Ssimon { 910160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 911160814Ssimon goto err; 912160814Ssimon } 913160814Ssimon 914160814Ssimon /* extract the cofactor (optional) */ 915160814Ssimon if (params->cofactor == NULL) 916160814Ssimon { 917160814Ssimon if (b) 918160814Ssimon { 919160814Ssimon BN_free(b); 920160814Ssimon b = NULL; 921160814Ssimon } 922160814Ssimon } 923160814Ssimon else 924160814Ssimon if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) 925160814Ssimon { 926160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 927160814Ssimon goto err; 928160814Ssimon } 929160814Ssimon /* set the generator, order and cofactor (if present) */ 930160814Ssimon if (!EC_GROUP_set_generator(ret, point, a, b)) 931160814Ssimon { 932160814Ssimon ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 933160814Ssimon goto err; 934160814Ssimon } 935160814Ssimon 936160814Ssimon ok = 1; 937160814Ssimon 938160814Ssimonerr: if (!ok) 939160814Ssimon { 940160814Ssimon if (ret) 941160814Ssimon EC_GROUP_clear_free(ret); 942160814Ssimon ret = NULL; 943160814Ssimon } 944160814Ssimon 945160814Ssimon if (p) 946160814Ssimon BN_free(p); 947160814Ssimon if (a) 948160814Ssimon BN_free(a); 949160814Ssimon if (b) 950160814Ssimon BN_free(b); 951160814Ssimon if (point) 952160814Ssimon EC_POINT_free(point); 953160814Ssimon return(ret); 954160814Ssimon} 955160814Ssimon 956160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) 957160814Ssimon { 958160814Ssimon EC_GROUP *ret=NULL; 959160814Ssimon int tmp=0; 960160814Ssimon 961160814Ssimon if (params == NULL) 962160814Ssimon { 963160814Ssimon ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, 964160814Ssimon EC_R_MISSING_PARAMETERS); 965160814Ssimon return NULL; 966160814Ssimon } 967160814Ssimon 968160814Ssimon if (params->type == 0) 969160814Ssimon { /* the curve is given by an OID */ 970160814Ssimon tmp = OBJ_obj2nid(params->value.named_curve); 971160814Ssimon if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) 972160814Ssimon { 973160814Ssimon ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, 974160814Ssimon EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); 975160814Ssimon return NULL; 976160814Ssimon } 977160814Ssimon EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); 978160814Ssimon } 979160814Ssimon else if (params->type == 1) 980160814Ssimon { /* the parameters are given by a ECPARAMETERS 981160814Ssimon * structure */ 982160814Ssimon ret = ec_asn1_parameters2group(params->value.parameters); 983160814Ssimon if (!ret) 984160814Ssimon { 985160814Ssimon ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); 986160814Ssimon return NULL; 987160814Ssimon } 988160814Ssimon EC_GROUP_set_asn1_flag(ret, 0x0); 989160814Ssimon } 990160814Ssimon else if (params->type == 2) 991160814Ssimon { /* implicitlyCA */ 992160814Ssimon return NULL; 993160814Ssimon } 994160814Ssimon else 995160814Ssimon { 996160814Ssimon ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); 997160814Ssimon return NULL; 998160814Ssimon } 999160814Ssimon 1000160814Ssimon return ret; 1001160814Ssimon } 1002160814Ssimon 1003160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ 1004160814Ssimon 1005160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) 1006160814Ssimon { 1007160814Ssimon EC_GROUP *group = NULL; 1008160814Ssimon ECPKPARAMETERS *params = NULL; 1009160814Ssimon 1010160814Ssimon if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) 1011160814Ssimon { 1012160814Ssimon ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); 1013160814Ssimon ECPKPARAMETERS_free(params); 1014160814Ssimon return NULL; 1015160814Ssimon } 1016160814Ssimon 1017160814Ssimon if ((group = ec_asn1_pkparameters2group(params)) == NULL) 1018160814Ssimon { 1019160814Ssimon ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); 1020160814Ssimon return NULL; 1021160814Ssimon } 1022160814Ssimon 1023160814Ssimon 1024160814Ssimon if (a && *a) 1025160814Ssimon EC_GROUP_clear_free(*a); 1026160814Ssimon if (a) 1027160814Ssimon *a = group; 1028160814Ssimon 1029160814Ssimon ECPKPARAMETERS_free(params); 1030160814Ssimon return(group); 1031160814Ssimon } 1032160814Ssimon 1033160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) 1034160814Ssimon { 1035160814Ssimon int ret=0; 1036160814Ssimon ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); 1037160814Ssimon if (tmp == NULL) 1038160814Ssimon { 1039160814Ssimon ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); 1040160814Ssimon return 0; 1041160814Ssimon } 1042160814Ssimon if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) 1043160814Ssimon { 1044160814Ssimon ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); 1045160814Ssimon ECPKPARAMETERS_free(tmp); 1046160814Ssimon return 0; 1047160814Ssimon } 1048160814Ssimon ECPKPARAMETERS_free(tmp); 1049160814Ssimon return(ret); 1050160814Ssimon } 1051160814Ssimon 1052160814Ssimon/* some EC_KEY functions */ 1053160814Ssimon 1054160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) 1055160814Ssimon { 1056160814Ssimon int ok=0; 1057160814Ssimon EC_KEY *ret=NULL; 1058160814Ssimon EC_PRIVATEKEY *priv_key=NULL; 1059160814Ssimon 1060160814Ssimon if ((priv_key = EC_PRIVATEKEY_new()) == NULL) 1061160814Ssimon { 1062160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1063160814Ssimon return NULL; 1064160814Ssimon } 1065160814Ssimon 1066160814Ssimon if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) 1067160814Ssimon { 1068160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1069160814Ssimon EC_PRIVATEKEY_free(priv_key); 1070160814Ssimon return NULL; 1071160814Ssimon } 1072160814Ssimon 1073160814Ssimon if (a == NULL || *a == NULL) 1074160814Ssimon { 1075160814Ssimon if ((ret = EC_KEY_new()) == NULL) 1076160814Ssimon { 1077160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, 1078160814Ssimon ERR_R_MALLOC_FAILURE); 1079160814Ssimon goto err; 1080160814Ssimon } 1081160814Ssimon if (a) 1082160814Ssimon *a = ret; 1083160814Ssimon } 1084160814Ssimon else 1085160814Ssimon ret = *a; 1086160814Ssimon 1087160814Ssimon if (priv_key->parameters) 1088160814Ssimon { 1089160814Ssimon if (ret->group) 1090160814Ssimon EC_GROUP_clear_free(ret->group); 1091160814Ssimon ret->group = ec_asn1_pkparameters2group(priv_key->parameters); 1092160814Ssimon } 1093160814Ssimon 1094160814Ssimon if (ret->group == NULL) 1095160814Ssimon { 1096160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1097160814Ssimon goto err; 1098160814Ssimon } 1099160814Ssimon 1100160814Ssimon ret->version = priv_key->version; 1101160814Ssimon 1102160814Ssimon if (priv_key->privateKey) 1103160814Ssimon { 1104160814Ssimon ret->priv_key = BN_bin2bn( 1105160814Ssimon M_ASN1_STRING_data(priv_key->privateKey), 1106160814Ssimon M_ASN1_STRING_length(priv_key->privateKey), 1107160814Ssimon ret->priv_key); 1108160814Ssimon if (ret->priv_key == NULL) 1109160814Ssimon { 1110160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, 1111160814Ssimon ERR_R_BN_LIB); 1112160814Ssimon goto err; 1113160814Ssimon } 1114160814Ssimon } 1115160814Ssimon else 1116160814Ssimon { 1117160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, 1118160814Ssimon EC_R_MISSING_PRIVATE_KEY); 1119160814Ssimon goto err; 1120160814Ssimon } 1121160814Ssimon 1122160814Ssimon if (priv_key->publicKey) 1123160814Ssimon { 1124160814Ssimon const unsigned char *pub_oct; 1125160814Ssimon size_t pub_oct_len; 1126160814Ssimon 1127160814Ssimon if (ret->pub_key) 1128160814Ssimon EC_POINT_clear_free(ret->pub_key); 1129160814Ssimon ret->pub_key = EC_POINT_new(ret->group); 1130160814Ssimon if (ret->pub_key == NULL) 1131160814Ssimon { 1132160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1133160814Ssimon goto err; 1134160814Ssimon } 1135160814Ssimon pub_oct = M_ASN1_STRING_data(priv_key->publicKey); 1136160814Ssimon pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey); 1137160814Ssimon /* save the point conversion form */ 1138160814Ssimon ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01); 1139160814Ssimon if (!EC_POINT_oct2point(ret->group, ret->pub_key, 1140160814Ssimon pub_oct, pub_oct_len, NULL)) 1141160814Ssimon { 1142160814Ssimon ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1143160814Ssimon goto err; 1144160814Ssimon } 1145160814Ssimon } 1146160814Ssimon 1147160814Ssimon ok = 1; 1148160814Ssimonerr: 1149160814Ssimon if (!ok) 1150160814Ssimon { 1151160814Ssimon if (ret) 1152160814Ssimon EC_KEY_free(ret); 1153160814Ssimon ret = NULL; 1154160814Ssimon } 1155160814Ssimon 1156160814Ssimon if (priv_key) 1157160814Ssimon EC_PRIVATEKEY_free(priv_key); 1158160814Ssimon 1159160814Ssimon return(ret); 1160160814Ssimon } 1161160814Ssimon 1162160814Ssimonint i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) 1163160814Ssimon { 1164160814Ssimon int ret=0, ok=0; 1165160814Ssimon unsigned char *buffer=NULL; 1166160814Ssimon size_t buf_len=0, tmp_len; 1167160814Ssimon EC_PRIVATEKEY *priv_key=NULL; 1168160814Ssimon 1169160814Ssimon if (a == NULL || a->group == NULL || a->priv_key == NULL) 1170160814Ssimon { 1171160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, 1172160814Ssimon ERR_R_PASSED_NULL_PARAMETER); 1173160814Ssimon goto err; 1174160814Ssimon } 1175160814Ssimon 1176160814Ssimon if ((priv_key = EC_PRIVATEKEY_new()) == NULL) 1177160814Ssimon { 1178160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, 1179160814Ssimon ERR_R_MALLOC_FAILURE); 1180160814Ssimon goto err; 1181160814Ssimon } 1182160814Ssimon 1183160814Ssimon priv_key->version = a->version; 1184160814Ssimon 1185160814Ssimon buf_len = (size_t)BN_num_bytes(a->priv_key); 1186160814Ssimon buffer = OPENSSL_malloc(buf_len); 1187160814Ssimon if (buffer == NULL) 1188160814Ssimon { 1189160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, 1190160814Ssimon ERR_R_MALLOC_FAILURE); 1191160814Ssimon goto err; 1192160814Ssimon } 1193160814Ssimon 1194160814Ssimon if (!BN_bn2bin(a->priv_key, buffer)) 1195160814Ssimon { 1196160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); 1197160814Ssimon goto err; 1198160814Ssimon } 1199160814Ssimon 1200160814Ssimon if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) 1201160814Ssimon { 1202160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); 1203160814Ssimon goto err; 1204160814Ssimon } 1205160814Ssimon 1206160814Ssimon if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) 1207160814Ssimon { 1208160814Ssimon if ((priv_key->parameters = ec_asn1_group2pkparameters( 1209160814Ssimon a->group, priv_key->parameters)) == NULL) 1210160814Ssimon { 1211160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1212160814Ssimon goto err; 1213160814Ssimon } 1214160814Ssimon } 1215160814Ssimon 1216160814Ssimon if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) 1217160814Ssimon { 1218160814Ssimon priv_key->publicKey = M_ASN1_BIT_STRING_new(); 1219160814Ssimon if (priv_key->publicKey == NULL) 1220160814Ssimon { 1221160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, 1222160814Ssimon ERR_R_MALLOC_FAILURE); 1223160814Ssimon goto err; 1224160814Ssimon } 1225160814Ssimon 1226160814Ssimon tmp_len = EC_POINT_point2oct(a->group, a->pub_key, 1227160814Ssimon a->conv_form, NULL, 0, NULL); 1228160814Ssimon 1229160814Ssimon if (tmp_len > buf_len) 1230160814Ssimon { 1231160814Ssimon unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); 1232160814Ssimon if (!tmp_buffer) 1233160814Ssimon { 1234160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1235160814Ssimon goto err; 1236160814Ssimon } 1237160814Ssimon buffer = tmp_buffer; 1238160814Ssimon buf_len = tmp_len; 1239160814Ssimon } 1240160814Ssimon 1241160814Ssimon if (!EC_POINT_point2oct(a->group, a->pub_key, 1242160814Ssimon a->conv_form, buffer, buf_len, NULL)) 1243160814Ssimon { 1244160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1245160814Ssimon goto err; 1246160814Ssimon } 1247160814Ssimon 1248160814Ssimon if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, 1249160814Ssimon buf_len)) 1250160814Ssimon { 1251160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); 1252160814Ssimon goto err; 1253160814Ssimon } 1254160814Ssimon } 1255160814Ssimon 1256160814Ssimon if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) 1257160814Ssimon { 1258160814Ssimon ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1259160814Ssimon goto err; 1260160814Ssimon } 1261160814Ssimon ok=1; 1262160814Ssimonerr: 1263160814Ssimon if (buffer) 1264160814Ssimon OPENSSL_free(buffer); 1265160814Ssimon if (priv_key) 1266160814Ssimon EC_PRIVATEKEY_free(priv_key); 1267160814Ssimon return(ok?ret:0); 1268160814Ssimon } 1269160814Ssimon 1270160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out) 1271160814Ssimon { 1272160814Ssimon if (a == NULL) 1273160814Ssimon { 1274160814Ssimon ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); 1275160814Ssimon return 0; 1276160814Ssimon } 1277160814Ssimon return i2d_ECPKParameters(a->group, out); 1278160814Ssimon } 1279160814Ssimon 1280160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) 1281160814Ssimon { 1282160814Ssimon EC_KEY *ret; 1283160814Ssimon 1284160814Ssimon if (in == NULL || *in == NULL) 1285160814Ssimon { 1286160814Ssimon ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); 1287160814Ssimon return NULL; 1288160814Ssimon } 1289160814Ssimon 1290160814Ssimon if (a == NULL || *a == NULL) 1291160814Ssimon { 1292160814Ssimon if ((ret = EC_KEY_new()) == NULL) 1293160814Ssimon { 1294160814Ssimon ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); 1295160814Ssimon return NULL; 1296160814Ssimon } 1297160814Ssimon if (a) 1298160814Ssimon *a = ret; 1299160814Ssimon } 1300160814Ssimon else 1301160814Ssimon ret = *a; 1302160814Ssimon 1303160814Ssimon if (!d2i_ECPKParameters(&ret->group, in, len)) 1304160814Ssimon { 1305160814Ssimon ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); 1306160814Ssimon return NULL; 1307160814Ssimon } 1308160814Ssimon 1309160814Ssimon return ret; 1310160814Ssimon } 1311160814Ssimon 1312160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) 1313160814Ssimon { 1314160814Ssimon EC_KEY *ret=NULL; 1315160814Ssimon 1316160814Ssimon if (a == NULL || (*a) == NULL || (*a)->group == NULL) 1317160814Ssimon { 1318160814Ssimon /* sorry, but a EC_GROUP-structur is necessary 1319160814Ssimon * to set the public key */ 1320160814Ssimon ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); 1321160814Ssimon return 0; 1322160814Ssimon } 1323160814Ssimon ret = *a; 1324160814Ssimon if (ret->pub_key == NULL && 1325160814Ssimon (ret->pub_key = EC_POINT_new(ret->group)) == NULL) 1326160814Ssimon { 1327160814Ssimon ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); 1328160814Ssimon return 0; 1329160814Ssimon } 1330160814Ssimon if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) 1331160814Ssimon { 1332160814Ssimon ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); 1333160814Ssimon return 0; 1334160814Ssimon } 1335160814Ssimon /* save the point conversion form */ 1336160814Ssimon ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01); 1337160814Ssimon *in += len; 1338160814Ssimon return ret; 1339160814Ssimon } 1340160814Ssimon 1341160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out) 1342160814Ssimon { 1343160814Ssimon size_t buf_len=0; 1344160814Ssimon int new_buffer = 0; 1345160814Ssimon 1346160814Ssimon if (a == NULL) 1347160814Ssimon { 1348160814Ssimon ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); 1349160814Ssimon return 0; 1350160814Ssimon } 1351160814Ssimon 1352160814Ssimon buf_len = EC_POINT_point2oct(a->group, a->pub_key, 1353160814Ssimon a->conv_form, NULL, 0, NULL); 1354160814Ssimon 1355160814Ssimon if (out == NULL || buf_len == 0) 1356160814Ssimon /* out == NULL => just return the length of the octet string */ 1357160814Ssimon return buf_len; 1358160814Ssimon 1359160814Ssimon if (*out == NULL) 1360160814Ssimon { 1361160814Ssimon if ((*out = OPENSSL_malloc(buf_len)) == NULL) 1362160814Ssimon { 1363160814Ssimon ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); 1364160814Ssimon return 0; 1365160814Ssimon } 1366160814Ssimon new_buffer = 1; 1367160814Ssimon } 1368160814Ssimon if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, 1369160814Ssimon *out, buf_len, NULL)) 1370160814Ssimon { 1371160814Ssimon ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); 1372160814Ssimon OPENSSL_free(*out); 1373160814Ssimon *out = NULL; 1374160814Ssimon return 0; 1375160814Ssimon } 1376160814Ssimon if (!new_buffer) 1377160814Ssimon *out += buf_len; 1378160814Ssimon return buf_len; 1379160814Ssimon } 1380