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 13296465Sdelphij * 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 65160814Ssimonint EC_GROUP_get_basis_type(const EC_GROUP *group) 66296465Sdelphij{ 67296465Sdelphij int i = 0; 68160814Ssimon 69296465Sdelphij if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != 70296465Sdelphij NID_X9_62_characteristic_two_field) 71296465Sdelphij /* everything else is currently not supported */ 72296465Sdelphij return 0; 73160814Ssimon 74296465Sdelphij while (group->poly[i] != 0) 75296465Sdelphij i++; 76160814Ssimon 77296465Sdelphij if (i == 4) 78296465Sdelphij return NID_X9_62_ppBasis; 79296465Sdelphij else if (i == 2) 80296465Sdelphij return NID_X9_62_tpBasis; 81296465Sdelphij else 82296465Sdelphij /* everything else is currently not supported */ 83296465Sdelphij return 0; 84296465Sdelphij} 85160814Ssimon 86160814Ssimonint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) 87296465Sdelphij{ 88296465Sdelphij if (group == NULL) 89296465Sdelphij return 0; 90160814Ssimon 91296465Sdelphij if (EC_GROUP_method_of(group)->group_set_curve != 92296465Sdelphij ec_GF2m_simple_group_set_curve || !((group->poly[0] != 0) 93296465Sdelphij && (group->poly[1] != 0) 94296465Sdelphij && (group->poly[2] == 0))) { 95296465Sdelphij ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, 96296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 97296465Sdelphij return 0; 98296465Sdelphij } 99160814Ssimon 100296465Sdelphij if (k) 101296465Sdelphij *k = group->poly[1]; 102160814Ssimon 103296465Sdelphij return 1; 104296465Sdelphij} 105160814Ssimon 106160814Ssimonint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, 107296465Sdelphij unsigned int *k2, unsigned int *k3) 108296465Sdelphij{ 109296465Sdelphij if (group == NULL) 110296465Sdelphij return 0; 111160814Ssimon 112296465Sdelphij if (EC_GROUP_method_of(group)->group_set_curve != 113296465Sdelphij ec_GF2m_simple_group_set_curve || !((group->poly[0] != 0) 114296465Sdelphij && (group->poly[1] != 0) 115296465Sdelphij && (group->poly[2] != 0) 116296465Sdelphij && (group->poly[3] != 0) 117296465Sdelphij && (group->poly[4] == 0))) { 118296465Sdelphij ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, 119296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 120296465Sdelphij return 0; 121296465Sdelphij } 122160814Ssimon 123296465Sdelphij if (k1) 124296465Sdelphij *k1 = group->poly[3]; 125296465Sdelphij if (k2) 126296465Sdelphij *k2 = group->poly[2]; 127296465Sdelphij if (k3) 128296465Sdelphij *k3 = group->poly[1]; 129160814Ssimon 130296465Sdelphij return 1; 131296465Sdelphij} 132160814Ssimon 133160814Ssimon/* some structures needed for the asn1 encoding */ 134160814Ssimontypedef struct x9_62_pentanomial_st { 135296465Sdelphij long k1; 136296465Sdelphij long k2; 137296465Sdelphij long k3; 138296465Sdelphij} X9_62_PENTANOMIAL; 139160814Ssimon 140160814Ssimontypedef struct x9_62_characteristic_two_st { 141296465Sdelphij long m; 142296465Sdelphij ASN1_OBJECT *type; 143296465Sdelphij union { 144296465Sdelphij char *ptr; 145296465Sdelphij /* NID_X9_62_onBasis */ 146296465Sdelphij ASN1_NULL *onBasis; 147296465Sdelphij /* NID_X9_62_tpBasis */ 148296465Sdelphij ASN1_INTEGER *tpBasis; 149296465Sdelphij /* NID_X9_62_ppBasis */ 150296465Sdelphij X9_62_PENTANOMIAL *ppBasis; 151296465Sdelphij /* anything else */ 152296465Sdelphij ASN1_TYPE *other; 153296465Sdelphij } p; 154296465Sdelphij} X9_62_CHARACTERISTIC_TWO; 155160814Ssimon 156160814Ssimontypedef struct x9_62_fieldid_st { 157296465Sdelphij ASN1_OBJECT *fieldType; 158296465Sdelphij union { 159296465Sdelphij char *ptr; 160296465Sdelphij /* NID_X9_62_prime_field */ 161296465Sdelphij ASN1_INTEGER *prime; 162296465Sdelphij /* NID_X9_62_characteristic_two_field */ 163296465Sdelphij X9_62_CHARACTERISTIC_TWO *char_two; 164296465Sdelphij /* anything else */ 165296465Sdelphij ASN1_TYPE *other; 166296465Sdelphij } p; 167296465Sdelphij} X9_62_FIELDID; 168160814Ssimon 169160814Ssimontypedef struct x9_62_curve_st { 170296465Sdelphij ASN1_OCTET_STRING *a; 171296465Sdelphij ASN1_OCTET_STRING *b; 172296465Sdelphij ASN1_BIT_STRING *seed; 173296465Sdelphij} X9_62_CURVE; 174160814Ssimon 175160814Ssimontypedef struct ec_parameters_st { 176296465Sdelphij long version; 177296465Sdelphij X9_62_FIELDID *fieldID; 178296465Sdelphij X9_62_CURVE *curve; 179296465Sdelphij ASN1_OCTET_STRING *base; 180296465Sdelphij ASN1_INTEGER *order; 181296465Sdelphij ASN1_INTEGER *cofactor; 182296465Sdelphij} ECPARAMETERS; 183160814Ssimon 184160814Ssimonstruct ecpk_parameters_st { 185296465Sdelphij int type; 186296465Sdelphij union { 187296465Sdelphij ASN1_OBJECT *named_curve; 188296465Sdelphij ECPARAMETERS *parameters; 189296465Sdelphij ASN1_NULL *implicitlyCA; 190296465Sdelphij } value; 191296465Sdelphij} /* ECPKPARAMETERS */ ; 192160814Ssimon 193160814Ssimon/* SEC1 ECPrivateKey */ 194160814Ssimontypedef struct ec_privatekey_st { 195296465Sdelphij long version; 196296465Sdelphij ASN1_OCTET_STRING *privateKey; 197296465Sdelphij ECPKPARAMETERS *parameters; 198296465Sdelphij ASN1_BIT_STRING *publicKey; 199296465Sdelphij} EC_PRIVATEKEY; 200160814Ssimon 201160814Ssimon/* the OpenSSL ASN.1 definitions */ 202160814SsimonASN1_SEQUENCE(X9_62_PENTANOMIAL) = { 203296465Sdelphij ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), 204296465Sdelphij ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), 205296465Sdelphij ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) 206160814Ssimon} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) 207160814Ssimon 208160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) 209160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) 210160814Ssimon 211160814SsimonASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY); 212160814Ssimon 213160814SsimonASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { 214296465Sdelphij ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), 215296465Sdelphij ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), 216296465Sdelphij ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) 217160814Ssimon} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); 218160814Ssimon 219160814SsimonASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { 220296465Sdelphij ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), 221296465Sdelphij ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), 222296465Sdelphij ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) 223160814Ssimon} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) 224160814Ssimon 225160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) 226160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) 227160814Ssimon 228160814SsimonASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY); 229160814Ssimon 230160814SsimonASN1_ADB(X9_62_FIELDID) = { 231296465Sdelphij ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), 232296465Sdelphij ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) 233160814Ssimon} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL); 234160814Ssimon 235160814SsimonASN1_SEQUENCE(X9_62_FIELDID) = { 236296465Sdelphij ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), 237296465Sdelphij ASN1_ADB_OBJECT(X9_62_FIELDID) 238160814Ssimon} ASN1_SEQUENCE_END(X9_62_FIELDID) 239160814Ssimon 240160814SsimonASN1_SEQUENCE(X9_62_CURVE) = { 241296465Sdelphij ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), 242296465Sdelphij ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), 243296465Sdelphij ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) 244160814Ssimon} ASN1_SEQUENCE_END(X9_62_CURVE) 245160814Ssimon 246160814SsimonASN1_SEQUENCE(ECPARAMETERS) = { 247296465Sdelphij ASN1_SIMPLE(ECPARAMETERS, version, LONG), 248296465Sdelphij ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), 249296465Sdelphij ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), 250296465Sdelphij ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), 251296465Sdelphij ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), 252296465Sdelphij ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) 253160814Ssimon} ASN1_SEQUENCE_END(ECPARAMETERS) 254160814Ssimon 255160814SsimonDECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) 256160814SsimonIMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) 257160814Ssimon 258160814SsimonASN1_CHOICE(ECPKPARAMETERS) = { 259296465Sdelphij ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), 260296465Sdelphij ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), 261296465Sdelphij ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) 262160814Ssimon} ASN1_CHOICE_END(ECPKPARAMETERS) 263160814Ssimon 264160814SsimonDECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) 265160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) 266160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) 267160814Ssimon 268160814SsimonASN1_SEQUENCE(EC_PRIVATEKEY) = { 269296465Sdelphij ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), 270296465Sdelphij ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), 271296465Sdelphij ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), 272296465Sdelphij ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) 273160814Ssimon} ASN1_SEQUENCE_END(EC_PRIVATEKEY) 274160814Ssimon 275160814SsimonDECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) 276160814SsimonDECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) 277160814SsimonIMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) 278160814Ssimon 279160814Ssimon/* some declarations of internal function */ 280160814Ssimon 281296465Sdelphij/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ 282160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); 283296465Sdelphij/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ 284160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); 285296465Sdelphij/* 286296465Sdelphij * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS 287296465Sdelphij * object 288296465Sdelphij */ 289296465Sdelphijstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); 290296465Sdelphij/* 291296465Sdelphij * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP 292296465Sdelphij * object 293296465Sdelphij */ 294296465Sdelphijstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, 295296465Sdelphij ECPARAMETERS *); 296296465Sdelphij/* 297296465Sdelphij * ec_asn1_pkparameters2group() creates a EC_GROUP object from a 298296465Sdelphij * ECPKPARAMETERS object 299296465Sdelphij */ 300296465Sdelphijstatic EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); 301296465Sdelphij/* 302296465Sdelphij * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a 303296465Sdelphij * EC_GROUP object 304296465Sdelphij */ 305296465Sdelphijstatic ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, 306296465Sdelphij ECPKPARAMETERS *); 307160814Ssimon 308160814Ssimon/* the function definitions */ 309160814Ssimon 310160814Ssimonstatic int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) 311296465Sdelphij{ 312296465Sdelphij int ok = 0, nid; 313296465Sdelphij BIGNUM *tmp = NULL; 314160814Ssimon 315296465Sdelphij if (group == NULL || field == NULL) 316296465Sdelphij return 0; 317160814Ssimon 318296465Sdelphij /* clear the old values (if necessary) */ 319296465Sdelphij if (field->fieldType != NULL) 320296465Sdelphij ASN1_OBJECT_free(field->fieldType); 321296465Sdelphij if (field->p.other != NULL) 322296465Sdelphij ASN1_TYPE_free(field->p.other); 323160814Ssimon 324296465Sdelphij nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 325296465Sdelphij /* set OID for the field */ 326296465Sdelphij if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) { 327296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); 328296465Sdelphij goto err; 329296465Sdelphij } 330160814Ssimon 331296465Sdelphij if (nid == NID_X9_62_prime_field) { 332296465Sdelphij if ((tmp = BN_new()) == NULL) { 333296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 334296465Sdelphij goto err; 335296465Sdelphij } 336296465Sdelphij /* the parameters are specified by the prime number p */ 337296465Sdelphij if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) { 338296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); 339296465Sdelphij goto err; 340296465Sdelphij } 341296465Sdelphij /* set the prime number */ 342296465Sdelphij field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL); 343296465Sdelphij if (field->p.prime == NULL) { 344296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); 345296465Sdelphij goto err; 346296465Sdelphij } 347296465Sdelphij } else { /* nid == NID_X9_62_characteristic_two_field */ 348160814Ssimon 349296465Sdelphij int field_type; 350296465Sdelphij X9_62_CHARACTERISTIC_TWO *char_two; 351160814Ssimon 352296465Sdelphij field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); 353296465Sdelphij char_two = field->p.char_two; 354160814Ssimon 355296465Sdelphij if (char_two == NULL) { 356296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 357296465Sdelphij goto err; 358296465Sdelphij } 359160814Ssimon 360296465Sdelphij char_two->m = (long)EC_GROUP_get_degree(group); 361160814Ssimon 362296465Sdelphij field_type = EC_GROUP_get_basis_type(group); 363160814Ssimon 364296465Sdelphij if (field_type == 0) { 365296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); 366296465Sdelphij goto err; 367296465Sdelphij } 368296465Sdelphij /* set base type OID */ 369296465Sdelphij if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) { 370296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); 371296465Sdelphij goto err; 372296465Sdelphij } 373160814Ssimon 374296465Sdelphij if (field_type == NID_X9_62_tpBasis) { 375296465Sdelphij unsigned int k; 376160814Ssimon 377296465Sdelphij if (!EC_GROUP_get_trinomial_basis(group, &k)) 378296465Sdelphij goto err; 379160814Ssimon 380296465Sdelphij char_two->p.tpBasis = ASN1_INTEGER_new(); 381296465Sdelphij if (!char_two->p.tpBasis) { 382296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 383296465Sdelphij goto err; 384296465Sdelphij } 385296465Sdelphij if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { 386296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); 387296465Sdelphij goto err; 388296465Sdelphij } 389296465Sdelphij } else if (field_type == NID_X9_62_ppBasis) { 390296465Sdelphij unsigned int k1, k2, k3; 391160814Ssimon 392296465Sdelphij if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) 393296465Sdelphij goto err; 394160814Ssimon 395296465Sdelphij char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); 396296465Sdelphij if (!char_two->p.ppBasis) { 397296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 398296465Sdelphij goto err; 399296465Sdelphij } 400296465Sdelphij 401296465Sdelphij /* set k? values */ 402296465Sdelphij char_two->p.ppBasis->k1 = (long)k1; 403296465Sdelphij char_two->p.ppBasis->k2 = (long)k2; 404296465Sdelphij char_two->p.ppBasis->k3 = (long)k3; 405296465Sdelphij } else { /* field_type == NID_X9_62_onBasis */ 406296465Sdelphij 407296465Sdelphij /* for ONB the parameters are (asn1) NULL */ 408296465Sdelphij char_two->p.onBasis = ASN1_NULL_new(); 409296465Sdelphij if (!char_two->p.onBasis) { 410296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); 411296465Sdelphij goto err; 412296465Sdelphij } 413296465Sdelphij } 414296465Sdelphij } 415296465Sdelphij 416296465Sdelphij ok = 1; 417296465Sdelphij 418296465Sdelphij err:if (tmp) 419296465Sdelphij BN_free(tmp); 420296465Sdelphij return (ok); 421160814Ssimon} 422160814Ssimon 423160814Ssimonstatic int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) 424296465Sdelphij{ 425296465Sdelphij int ok = 0, nid; 426296465Sdelphij BIGNUM *tmp_1 = NULL, *tmp_2 = NULL; 427296465Sdelphij unsigned char *buffer_1 = NULL, *buffer_2 = NULL, 428296465Sdelphij *a_buf = NULL, *b_buf = NULL; 429296465Sdelphij size_t len_1, len_2; 430296465Sdelphij unsigned char char_zero = 0; 431160814Ssimon 432296465Sdelphij if (!group || !curve || !curve->a || !curve->b) 433296465Sdelphij return 0; 434160814Ssimon 435296465Sdelphij if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { 436296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 437296465Sdelphij goto err; 438296465Sdelphij } 439160814Ssimon 440296465Sdelphij nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 441160814Ssimon 442296465Sdelphij /* get a and b */ 443296465Sdelphij if (nid == NID_X9_62_prime_field) { 444296465Sdelphij if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) { 445296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); 446296465Sdelphij goto err; 447296465Sdelphij } 448296465Sdelphij } else { /* nid == NID_X9_62_characteristic_two_field */ 449160814Ssimon 450296465Sdelphij if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) { 451296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); 452296465Sdelphij goto err; 453296465Sdelphij } 454296465Sdelphij } 455160814Ssimon 456296465Sdelphij len_1 = (size_t)BN_num_bytes(tmp_1); 457296465Sdelphij len_2 = (size_t)BN_num_bytes(tmp_2); 458160814Ssimon 459296465Sdelphij if (len_1 == 0) { 460296465Sdelphij /* len_1 == 0 => a == 0 */ 461296465Sdelphij a_buf = &char_zero; 462296465Sdelphij len_1 = 1; 463296465Sdelphij } else { 464296465Sdelphij if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) { 465296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 466296465Sdelphij goto err; 467296465Sdelphij } 468296465Sdelphij if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) { 469296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); 470296465Sdelphij goto err; 471296465Sdelphij } 472296465Sdelphij a_buf = buffer_1; 473296465Sdelphij } 474160814Ssimon 475296465Sdelphij if (len_2 == 0) { 476296465Sdelphij /* len_2 == 0 => b == 0 */ 477296465Sdelphij b_buf = &char_zero; 478296465Sdelphij len_2 = 1; 479296465Sdelphij } else { 480296465Sdelphij if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) { 481296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 482296465Sdelphij goto err; 483296465Sdelphij } 484296465Sdelphij if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) { 485296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); 486296465Sdelphij goto err; 487296465Sdelphij } 488296465Sdelphij b_buf = buffer_2; 489296465Sdelphij } 490160814Ssimon 491296465Sdelphij /* set a and b */ 492296465Sdelphij if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) || 493296465Sdelphij !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) { 494296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); 495296465Sdelphij goto err; 496296465Sdelphij } 497160814Ssimon 498296465Sdelphij /* set the seed (optional) */ 499296465Sdelphij if (group->seed) { 500296465Sdelphij if (!curve->seed) 501296465Sdelphij if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { 502296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); 503296465Sdelphij goto err; 504296465Sdelphij } 505296465Sdelphij curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); 506296465Sdelphij curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; 507296465Sdelphij if (!ASN1_BIT_STRING_set(curve->seed, group->seed, 508296465Sdelphij (int)group->seed_len)) { 509296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); 510296465Sdelphij goto err; 511296465Sdelphij } 512296465Sdelphij } else { 513296465Sdelphij if (curve->seed) { 514296465Sdelphij ASN1_BIT_STRING_free(curve->seed); 515296465Sdelphij curve->seed = NULL; 516296465Sdelphij } 517296465Sdelphij } 518296465Sdelphij 519296465Sdelphij ok = 1; 520296465Sdelphij 521296465Sdelphij err:if (buffer_1) 522296465Sdelphij OPENSSL_free(buffer_1); 523296465Sdelphij if (buffer_2) 524296465Sdelphij OPENSSL_free(buffer_2); 525296465Sdelphij if (tmp_1) 526296465Sdelphij BN_free(tmp_1); 527296465Sdelphij if (tmp_2) 528296465Sdelphij BN_free(tmp_2); 529296465Sdelphij return (ok); 530296465Sdelphij} 531296465Sdelphij 532160814Ssimonstatic ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group, 533160814Ssimon ECPARAMETERS *param) 534296465Sdelphij{ 535296465Sdelphij int ok = 0; 536296465Sdelphij size_t len = 0; 537296465Sdelphij ECPARAMETERS *ret = NULL; 538296465Sdelphij BIGNUM *tmp = NULL; 539296465Sdelphij unsigned char *buffer = NULL; 540296465Sdelphij const EC_POINT *point = NULL; 541296465Sdelphij point_conversion_form_t form; 542160814Ssimon 543296465Sdelphij if ((tmp = BN_new()) == NULL) { 544296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 545296465Sdelphij goto err; 546296465Sdelphij } 547160814Ssimon 548296465Sdelphij if (param == NULL) { 549296465Sdelphij if ((ret = ECPARAMETERS_new()) == NULL) { 550296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 551296465Sdelphij goto err; 552296465Sdelphij } 553296465Sdelphij } else 554296465Sdelphij ret = param; 555160814Ssimon 556296465Sdelphij /* set the version (always one) */ 557296465Sdelphij ret->version = (long)0x1; 558160814Ssimon 559296465Sdelphij /* set the fieldID */ 560296465Sdelphij if (!ec_asn1_group2fieldid(group, ret->fieldID)) { 561296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 562296465Sdelphij goto err; 563296465Sdelphij } 564160814Ssimon 565296465Sdelphij /* set the curve */ 566296465Sdelphij if (!ec_asn1_group2curve(group, ret->curve)) { 567296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 568296465Sdelphij goto err; 569296465Sdelphij } 570160814Ssimon 571296465Sdelphij /* set the base point */ 572296465Sdelphij if ((point = EC_GROUP_get0_generator(group)) == NULL) { 573296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); 574296465Sdelphij goto err; 575296465Sdelphij } 576160814Ssimon 577296465Sdelphij form = EC_GROUP_get_point_conversion_form(group); 578160814Ssimon 579296465Sdelphij len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); 580296465Sdelphij if (len == 0) { 581296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 582296465Sdelphij goto err; 583296465Sdelphij } 584296465Sdelphij if ((buffer = OPENSSL_malloc(len)) == NULL) { 585296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 586296465Sdelphij goto err; 587296465Sdelphij } 588296465Sdelphij if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) { 589296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 590296465Sdelphij goto err; 591296465Sdelphij } 592296465Sdelphij if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { 593296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); 594296465Sdelphij goto err; 595296465Sdelphij } 596296465Sdelphij if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) { 597296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 598296465Sdelphij goto err; 599296465Sdelphij } 600160814Ssimon 601296465Sdelphij /* set the order */ 602296465Sdelphij if (!EC_GROUP_get_order(group, tmp, NULL)) { 603296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); 604296465Sdelphij goto err; 605296465Sdelphij } 606296465Sdelphij ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); 607296465Sdelphij if (ret->order == NULL) { 608296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 609296465Sdelphij goto err; 610296465Sdelphij } 611160814Ssimon 612296465Sdelphij /* set the cofactor (optional) */ 613296465Sdelphij if (EC_GROUP_get_cofactor(group, tmp, NULL)) { 614296465Sdelphij ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); 615296465Sdelphij if (ret->cofactor == NULL) { 616296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); 617296465Sdelphij goto err; 618296465Sdelphij } 619296465Sdelphij } 620160814Ssimon 621296465Sdelphij ok = 1; 622160814Ssimon 623296465Sdelphij err:if (!ok) { 624296465Sdelphij if (ret && !param) 625296465Sdelphij ECPARAMETERS_free(ret); 626296465Sdelphij ret = NULL; 627296465Sdelphij } 628296465Sdelphij if (tmp) 629296465Sdelphij BN_free(tmp); 630296465Sdelphij if (buffer) 631296465Sdelphij OPENSSL_free(buffer); 632296465Sdelphij return (ret); 633296465Sdelphij} 634160814Ssimon 635296465SdelphijECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, 636160814Ssimon ECPKPARAMETERS *params) 637296465Sdelphij{ 638296465Sdelphij int ok = 1, tmp; 639296465Sdelphij ECPKPARAMETERS *ret = params; 640160814Ssimon 641296465Sdelphij if (ret == NULL) { 642296465Sdelphij if ((ret = ECPKPARAMETERS_new()) == NULL) { 643296465Sdelphij ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE); 644296465Sdelphij return NULL; 645296465Sdelphij } 646296465Sdelphij } else { 647296465Sdelphij if (ret->type == 0 && ret->value.named_curve) 648296465Sdelphij ASN1_OBJECT_free(ret->value.named_curve); 649296465Sdelphij else if (ret->type == 1 && ret->value.parameters) 650296465Sdelphij ECPARAMETERS_free(ret->value.parameters); 651296465Sdelphij } 652160814Ssimon 653296465Sdelphij if (EC_GROUP_get_asn1_flag(group)) { 654296465Sdelphij /* 655296465Sdelphij * use the asn1 OID to describe the the elliptic curve parameters 656296465Sdelphij */ 657296465Sdelphij tmp = EC_GROUP_get_curve_name(group); 658296465Sdelphij if (tmp) { 659296465Sdelphij ret->type = 0; 660296465Sdelphij if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) 661296465Sdelphij ok = 0; 662296465Sdelphij } else 663296465Sdelphij /* we don't kmow the nid => ERROR */ 664296465Sdelphij ok = 0; 665296465Sdelphij } else { 666296465Sdelphij /* use the ECPARAMETERS structure */ 667296465Sdelphij ret->type = 1; 668296465Sdelphij if ((ret->value.parameters = 669296465Sdelphij ec_asn1_group2parameters(group, NULL)) == NULL) 670296465Sdelphij ok = 0; 671296465Sdelphij } 672160814Ssimon 673296465Sdelphij if (!ok) { 674296465Sdelphij ECPKPARAMETERS_free(ret); 675296465Sdelphij return NULL; 676296465Sdelphij } 677296465Sdelphij return ret; 678296465Sdelphij} 679160814Ssimon 680160814Ssimonstatic EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) 681296465Sdelphij{ 682296465Sdelphij int ok = 0, tmp; 683296465Sdelphij EC_GROUP *ret = NULL; 684296465Sdelphij BIGNUM *p = NULL, *a = NULL, *b = NULL; 685296465Sdelphij EC_POINT *point = NULL; 686296465Sdelphij long field_bits; 687160814Ssimon 688296465Sdelphij if (!params->fieldID || !params->fieldID->fieldType || 689296465Sdelphij !params->fieldID->p.ptr) { 690296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 691296465Sdelphij goto err; 692296465Sdelphij } 693160814Ssimon 694296465Sdelphij /* now extract the curve parameters a and b */ 695296465Sdelphij if (!params->curve || !params->curve->a || 696296465Sdelphij !params->curve->a->data || !params->curve->b || 697296465Sdelphij !params->curve->b->data) { 698296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 699296465Sdelphij goto err; 700296465Sdelphij } 701296465Sdelphij a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); 702296465Sdelphij if (a == NULL) { 703296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); 704296465Sdelphij goto err; 705296465Sdelphij } 706296465Sdelphij b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); 707296465Sdelphij if (b == NULL) { 708296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); 709296465Sdelphij goto err; 710296465Sdelphij } 711160814Ssimon 712296465Sdelphij /* get the field parameters */ 713296465Sdelphij tmp = OBJ_obj2nid(params->fieldID->fieldType); 714160814Ssimon 715296465Sdelphij if (tmp == NID_X9_62_characteristic_two_field) { 716296465Sdelphij X9_62_CHARACTERISTIC_TWO *char_two; 717160814Ssimon 718296465Sdelphij char_two = params->fieldID->p.char_two; 719160814Ssimon 720296465Sdelphij field_bits = char_two->m; 721296465Sdelphij if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { 722296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); 723296465Sdelphij goto err; 724296465Sdelphij } 725162911Ssimon 726296465Sdelphij if ((p = BN_new()) == NULL) { 727296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); 728296465Sdelphij goto err; 729296465Sdelphij } 730160814Ssimon 731296465Sdelphij /* get the base type */ 732296465Sdelphij tmp = OBJ_obj2nid(char_two->type); 733160814Ssimon 734296465Sdelphij if (tmp == NID_X9_62_tpBasis) { 735296465Sdelphij long tmp_long; 736160814Ssimon 737296465Sdelphij if (!char_two->p.tpBasis) { 738296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 739296465Sdelphij goto err; 740296465Sdelphij } 741160814Ssimon 742296465Sdelphij tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); 743162911Ssimon 744296465Sdelphij if (!(char_two->m > tmp_long && tmp_long > 0)) { 745296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, 746296465Sdelphij EC_R_INVALID_TRINOMIAL_BASIS); 747296465Sdelphij goto err; 748296465Sdelphij } 749160814Ssimon 750296465Sdelphij /* create the polynomial */ 751296465Sdelphij if (!BN_set_bit(p, (int)char_two->m)) 752296465Sdelphij goto err; 753296465Sdelphij if (!BN_set_bit(p, (int)tmp_long)) 754296465Sdelphij goto err; 755296465Sdelphij if (!BN_set_bit(p, 0)) 756296465Sdelphij goto err; 757296465Sdelphij } else if (tmp == NID_X9_62_ppBasis) { 758296465Sdelphij X9_62_PENTANOMIAL *penta; 759162911Ssimon 760296465Sdelphij penta = char_two->p.ppBasis; 761296465Sdelphij if (!penta) { 762296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 763296465Sdelphij goto err; 764296465Sdelphij } 765160814Ssimon 766296465Sdelphij if (! 767296465Sdelphij (char_two->m > penta->k3 && penta->k3 > penta->k2 768296465Sdelphij && penta->k2 > penta->k1 && penta->k1 > 0)) { 769296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, 770296465Sdelphij EC_R_INVALID_PENTANOMIAL_BASIS); 771296465Sdelphij goto err; 772296465Sdelphij } 773162911Ssimon 774296465Sdelphij /* create the polynomial */ 775296465Sdelphij if (!BN_set_bit(p, (int)char_two->m)) 776296465Sdelphij goto err; 777296465Sdelphij if (!BN_set_bit(p, (int)penta->k1)) 778296465Sdelphij goto err; 779296465Sdelphij if (!BN_set_bit(p, (int)penta->k2)) 780296465Sdelphij goto err; 781296465Sdelphij if (!BN_set_bit(p, (int)penta->k3)) 782296465Sdelphij goto err; 783296465Sdelphij if (!BN_set_bit(p, 0)) 784296465Sdelphij goto err; 785296465Sdelphij } else if (tmp == NID_X9_62_onBasis) { 786296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); 787296465Sdelphij goto err; 788296465Sdelphij } else { /* error */ 789162911Ssimon 790296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 791296465Sdelphij goto err; 792296465Sdelphij } 793162911Ssimon 794296465Sdelphij /* create the EC_GROUP structure */ 795296465Sdelphij ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); 796296465Sdelphij } else if (tmp == NID_X9_62_prime_field) { 797296465Sdelphij /* we have a curve over a prime field */ 798296465Sdelphij /* extract the prime number */ 799296465Sdelphij if (!params->fieldID->p.prime) { 800296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 801296465Sdelphij goto err; 802296465Sdelphij } 803296465Sdelphij p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); 804296465Sdelphij if (p == NULL) { 805296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 806296465Sdelphij goto err; 807296465Sdelphij } 808160814Ssimon 809296465Sdelphij if (BN_is_negative(p) || BN_is_zero(p)) { 810296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); 811296465Sdelphij goto err; 812296465Sdelphij } 813160814Ssimon 814296465Sdelphij field_bits = BN_num_bits(p); 815296465Sdelphij if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { 816296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); 817296465Sdelphij goto err; 818296465Sdelphij } 819160814Ssimon 820296465Sdelphij /* create the EC_GROUP structure */ 821296465Sdelphij ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); 822296465Sdelphij } else { 823296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); 824296465Sdelphij goto err; 825296465Sdelphij } 826160814Ssimon 827296465Sdelphij if (ret == NULL) { 828296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 829296465Sdelphij goto err; 830296465Sdelphij } 831160814Ssimon 832296465Sdelphij /* extract seed (optional) */ 833296465Sdelphij if (params->curve->seed != NULL) { 834296465Sdelphij if (ret->seed != NULL) 835296465Sdelphij OPENSSL_free(ret->seed); 836296465Sdelphij if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) { 837296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); 838296465Sdelphij goto err; 839296465Sdelphij } 840296465Sdelphij memcpy(ret->seed, params->curve->seed->data, 841296465Sdelphij params->curve->seed->length); 842296465Sdelphij ret->seed_len = params->curve->seed->length; 843296465Sdelphij } 844160814Ssimon 845296465Sdelphij if (!params->order || !params->base || !params->base->data) { 846296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); 847296465Sdelphij goto err; 848296465Sdelphij } 849160814Ssimon 850296465Sdelphij if ((point = EC_POINT_new(ret)) == NULL) 851296465Sdelphij goto err; 852160814Ssimon 853296465Sdelphij /* set the point conversion form */ 854296465Sdelphij EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) 855296465Sdelphij (params->base->data[0] & ~0x01)); 856160814Ssimon 857296465Sdelphij /* extract the ec point */ 858296465Sdelphij if (!EC_POINT_oct2point(ret, point, params->base->data, 859296465Sdelphij params->base->length, NULL)) { 860296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 861296465Sdelphij goto err; 862296465Sdelphij } 863160814Ssimon 864296465Sdelphij /* extract the order */ 865296465Sdelphij if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) { 866296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 867296465Sdelphij goto err; 868296465Sdelphij } 869296465Sdelphij if (BN_is_negative(a) || BN_is_zero(a)) { 870296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); 871296465Sdelphij goto err; 872296465Sdelphij } 873296465Sdelphij if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ 874296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); 875296465Sdelphij goto err; 876296465Sdelphij } 877296465Sdelphij 878296465Sdelphij /* extract the cofactor (optional) */ 879296465Sdelphij if (params->cofactor == NULL) { 880296465Sdelphij if (b) { 881296465Sdelphij BN_free(b); 882296465Sdelphij b = NULL; 883296465Sdelphij } 884296465Sdelphij } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) { 885296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); 886296465Sdelphij goto err; 887296465Sdelphij } 888296465Sdelphij /* set the generator, order and cofactor (if present) */ 889296465Sdelphij if (!EC_GROUP_set_generator(ret, point, a, b)) { 890296465Sdelphij ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); 891296465Sdelphij goto err; 892296465Sdelphij } 893296465Sdelphij 894296465Sdelphij ok = 1; 895296465Sdelphij 896296465Sdelphij err:if (!ok) { 897296465Sdelphij if (ret) 898296465Sdelphij EC_GROUP_clear_free(ret); 899296465Sdelphij ret = NULL; 900296465Sdelphij } 901296465Sdelphij 902296465Sdelphij if (p) 903296465Sdelphij BN_free(p); 904296465Sdelphij if (a) 905296465Sdelphij BN_free(a); 906296465Sdelphij if (b) 907296465Sdelphij BN_free(b); 908296465Sdelphij if (point) 909296465Sdelphij EC_POINT_free(point); 910296465Sdelphij return (ret); 911160814Ssimon} 912160814Ssimon 913160814SsimonEC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) 914296465Sdelphij{ 915296465Sdelphij EC_GROUP *ret = NULL; 916296465Sdelphij int tmp = 0; 917160814Ssimon 918296465Sdelphij if (params == NULL) { 919296465Sdelphij ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS); 920296465Sdelphij return NULL; 921296465Sdelphij } 922160814Ssimon 923296465Sdelphij if (params->type == 0) { /* the curve is given by an OID */ 924296465Sdelphij tmp = OBJ_obj2nid(params->value.named_curve); 925296465Sdelphij if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { 926296465Sdelphij ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, 927296465Sdelphij EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); 928296465Sdelphij return NULL; 929296465Sdelphij } 930296465Sdelphij EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); 931296465Sdelphij } else if (params->type == 1) { /* the parameters are given by a 932296465Sdelphij * ECPARAMETERS structure */ 933296465Sdelphij ret = ec_asn1_parameters2group(params->value.parameters); 934296465Sdelphij if (!ret) { 935296465Sdelphij ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); 936296465Sdelphij return NULL; 937296465Sdelphij } 938296465Sdelphij EC_GROUP_set_asn1_flag(ret, 0x0); 939296465Sdelphij } else if (params->type == 2) { /* implicitlyCA */ 940296465Sdelphij return NULL; 941296465Sdelphij } else { 942296465Sdelphij ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); 943296465Sdelphij return NULL; 944296465Sdelphij } 945160814Ssimon 946296465Sdelphij return ret; 947296465Sdelphij} 948160814Ssimon 949160814Ssimon/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ 950160814Ssimon 951160814SsimonEC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) 952296465Sdelphij{ 953296465Sdelphij EC_GROUP *group = NULL; 954296465Sdelphij ECPKPARAMETERS *params = NULL; 955160814Ssimon 956296465Sdelphij if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) { 957296465Sdelphij ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); 958296465Sdelphij ECPKPARAMETERS_free(params); 959296465Sdelphij return NULL; 960296465Sdelphij } 961160814Ssimon 962296465Sdelphij if ((group = ec_asn1_pkparameters2group(params)) == NULL) { 963296465Sdelphij ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); 964296465Sdelphij return NULL; 965296465Sdelphij } 966160814Ssimon 967296465Sdelphij if (a && *a) 968296465Sdelphij EC_GROUP_clear_free(*a); 969296465Sdelphij if (a) 970296465Sdelphij *a = group; 971160814Ssimon 972296465Sdelphij ECPKPARAMETERS_free(params); 973296465Sdelphij return (group); 974296465Sdelphij} 975296465Sdelphij 976160814Ssimonint i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) 977296465Sdelphij{ 978296465Sdelphij int ret = 0; 979296465Sdelphij ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); 980296465Sdelphij if (tmp == NULL) { 981296465Sdelphij ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); 982296465Sdelphij return 0; 983296465Sdelphij } 984296465Sdelphij if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { 985296465Sdelphij ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); 986296465Sdelphij ECPKPARAMETERS_free(tmp); 987296465Sdelphij return 0; 988296465Sdelphij } 989296465Sdelphij ECPKPARAMETERS_free(tmp); 990296465Sdelphij return (ret); 991296465Sdelphij} 992160814Ssimon 993160814Ssimon/* some EC_KEY functions */ 994160814Ssimon 995160814SsimonEC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) 996296465Sdelphij{ 997296465Sdelphij int ok = 0; 998296465Sdelphij EC_KEY *ret = NULL; 999296465Sdelphij EC_PRIVATEKEY *priv_key = NULL; 1000160814Ssimon 1001296465Sdelphij if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { 1002296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1003296465Sdelphij return NULL; 1004296465Sdelphij } 1005160814Ssimon 1006296465Sdelphij if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) { 1007296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1008296465Sdelphij EC_PRIVATEKEY_free(priv_key); 1009296465Sdelphij return NULL; 1010296465Sdelphij } 1011160814Ssimon 1012296465Sdelphij if (a == NULL || *a == NULL) { 1013296465Sdelphij if ((ret = EC_KEY_new()) == NULL) { 1014296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1015296465Sdelphij goto err; 1016296465Sdelphij } 1017296465Sdelphij } else 1018296465Sdelphij ret = *a; 1019160814Ssimon 1020296465Sdelphij if (priv_key->parameters) { 1021296465Sdelphij if (ret->group) 1022296465Sdelphij EC_GROUP_clear_free(ret->group); 1023296465Sdelphij ret->group = ec_asn1_pkparameters2group(priv_key->parameters); 1024296465Sdelphij } 1025160814Ssimon 1026296465Sdelphij if (ret->group == NULL) { 1027296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1028296465Sdelphij goto err; 1029296465Sdelphij } 1030160814Ssimon 1031296465Sdelphij ret->version = priv_key->version; 1032160814Ssimon 1033296465Sdelphij if (priv_key->privateKey) { 1034296465Sdelphij ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey), 1035296465Sdelphij M_ASN1_STRING_length(priv_key->privateKey), 1036296465Sdelphij ret->priv_key); 1037296465Sdelphij if (ret->priv_key == NULL) { 1038296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB); 1039296465Sdelphij goto err; 1040296465Sdelphij } 1041296465Sdelphij } else { 1042296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY); 1043296465Sdelphij goto err; 1044296465Sdelphij } 1045160814Ssimon 1046296465Sdelphij if (priv_key->publicKey) { 1047296465Sdelphij const unsigned char *pub_oct; 1048296465Sdelphij size_t pub_oct_len; 1049160814Ssimon 1050296465Sdelphij if (ret->pub_key) 1051296465Sdelphij EC_POINT_clear_free(ret->pub_key); 1052296465Sdelphij ret->pub_key = EC_POINT_new(ret->group); 1053296465Sdelphij if (ret->pub_key == NULL) { 1054296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1055296465Sdelphij goto err; 1056296465Sdelphij } 1057296465Sdelphij pub_oct = M_ASN1_STRING_data(priv_key->publicKey); 1058296465Sdelphij pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey); 1059296465Sdelphij /* save the point conversion form */ 1060296465Sdelphij ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01); 1061296465Sdelphij if (!EC_POINT_oct2point(ret->group, ret->pub_key, 1062296465Sdelphij pub_oct, pub_oct_len, NULL)) { 1063296465Sdelphij ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); 1064296465Sdelphij goto err; 1065296465Sdelphij } 1066296465Sdelphij } 1067160814Ssimon 1068296465Sdelphij if (a) 1069296465Sdelphij *a = ret; 1070296465Sdelphij ok = 1; 1071296465Sdelphij err: 1072296465Sdelphij if (!ok) { 1073296465Sdelphij if (ret && (a == NULL || *a != ret)) 1074296465Sdelphij EC_KEY_free(ret); 1075296465Sdelphij ret = NULL; 1076296465Sdelphij } 1077160814Ssimon 1078296465Sdelphij if (priv_key) 1079296465Sdelphij EC_PRIVATEKEY_free(priv_key); 1080160814Ssimon 1081296465Sdelphij return (ret); 1082296465Sdelphij} 1083160814Ssimon 1084296465Sdelphijint i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) 1085296465Sdelphij{ 1086296465Sdelphij int ret = 0, ok = 0; 1087296465Sdelphij unsigned char *buffer = NULL; 1088296465Sdelphij size_t buf_len = 0, tmp_len; 1089296465Sdelphij EC_PRIVATEKEY *priv_key = NULL; 1090160814Ssimon 1091296465Sdelphij if (a == NULL || a->group == NULL || a->priv_key == NULL) { 1092296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); 1093296465Sdelphij goto err; 1094296465Sdelphij } 1095160814Ssimon 1096296465Sdelphij if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { 1097296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1098296465Sdelphij goto err; 1099296465Sdelphij } 1100160814Ssimon 1101296465Sdelphij priv_key->version = a->version; 1102160814Ssimon 1103296465Sdelphij buf_len = (size_t)BN_num_bytes(a->priv_key); 1104296465Sdelphij buffer = OPENSSL_malloc(buf_len); 1105296465Sdelphij if (buffer == NULL) { 1106296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1107296465Sdelphij goto err; 1108296465Sdelphij } 1109160814Ssimon 1110296465Sdelphij if (!BN_bn2bin(a->priv_key, buffer)) { 1111296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); 1112296465Sdelphij goto err; 1113296465Sdelphij } 1114160814Ssimon 1115296465Sdelphij if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) { 1116296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); 1117296465Sdelphij goto err; 1118296465Sdelphij } 1119160814Ssimon 1120296465Sdelphij if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) { 1121296465Sdelphij if ((priv_key->parameters = 1122296465Sdelphij ec_asn1_group2pkparameters(a->group, 1123296465Sdelphij priv_key->parameters)) == NULL) { 1124296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1125296465Sdelphij goto err; 1126296465Sdelphij } 1127296465Sdelphij } 1128160814Ssimon 1129296465Sdelphij if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) { 1130296465Sdelphij priv_key->publicKey = M_ASN1_BIT_STRING_new(); 1131296465Sdelphij if (priv_key->publicKey == NULL) { 1132296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1133296465Sdelphij goto err; 1134296465Sdelphij } 1135160814Ssimon 1136296465Sdelphij tmp_len = EC_POINT_point2oct(a->group, a->pub_key, 1137296465Sdelphij a->conv_form, NULL, 0, NULL); 1138160814Ssimon 1139296465Sdelphij if (tmp_len > buf_len) { 1140296465Sdelphij unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); 1141296465Sdelphij if (!tmp_buffer) { 1142296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); 1143296465Sdelphij goto err; 1144296465Sdelphij } 1145296465Sdelphij buffer = tmp_buffer; 1146296465Sdelphij buf_len = tmp_len; 1147296465Sdelphij } 1148160814Ssimon 1149296465Sdelphij if (!EC_POINT_point2oct(a->group, a->pub_key, 1150296465Sdelphij a->conv_form, buffer, buf_len, NULL)) { 1151296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1152296465Sdelphij goto err; 1153296465Sdelphij } 1154160814Ssimon 1155296465Sdelphij priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); 1156296465Sdelphij priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; 1157296465Sdelphij if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) { 1158296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); 1159296465Sdelphij goto err; 1160296465Sdelphij } 1161296465Sdelphij } 1162160814Ssimon 1163296465Sdelphij if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { 1164296465Sdelphij ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); 1165296465Sdelphij goto err; 1166296465Sdelphij } 1167296465Sdelphij ok = 1; 1168296465Sdelphij err: 1169296465Sdelphij if (buffer) 1170296465Sdelphij OPENSSL_free(buffer); 1171296465Sdelphij if (priv_key) 1172296465Sdelphij EC_PRIVATEKEY_free(priv_key); 1173296465Sdelphij return (ok ? ret : 0); 1174296465Sdelphij} 1175296465Sdelphij 1176160814Ssimonint i2d_ECParameters(EC_KEY *a, unsigned char **out) 1177296465Sdelphij{ 1178296465Sdelphij if (a == NULL) { 1179296465Sdelphij ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); 1180296465Sdelphij return 0; 1181296465Sdelphij } 1182296465Sdelphij return i2d_ECPKParameters(a->group, out); 1183296465Sdelphij} 1184160814Ssimon 1185160814SsimonEC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) 1186296465Sdelphij{ 1187296465Sdelphij EC_KEY *ret; 1188160814Ssimon 1189296465Sdelphij if (in == NULL || *in == NULL) { 1190296465Sdelphij ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); 1191296465Sdelphij return NULL; 1192296465Sdelphij } 1193160814Ssimon 1194296465Sdelphij if (a == NULL || *a == NULL) { 1195296465Sdelphij if ((ret = EC_KEY_new()) == NULL) { 1196296465Sdelphij ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); 1197296465Sdelphij return NULL; 1198296465Sdelphij } 1199296465Sdelphij } else 1200296465Sdelphij ret = *a; 1201160814Ssimon 1202296465Sdelphij if (!d2i_ECPKParameters(&ret->group, in, len)) { 1203296465Sdelphij ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); 1204296465Sdelphij if (a == NULL || *a != ret) 1205296465Sdelphij EC_KEY_free(ret); 1206296465Sdelphij return NULL; 1207296465Sdelphij } 1208160814Ssimon 1209296465Sdelphij if (a) 1210296465Sdelphij *a = ret; 1211160814Ssimon 1212296465Sdelphij return ret; 1213296465Sdelphij} 1214296465Sdelphij 1215160814SsimonEC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) 1216296465Sdelphij{ 1217296465Sdelphij EC_KEY *ret = NULL; 1218160814Ssimon 1219296465Sdelphij if (a == NULL || (*a) == NULL || (*a)->group == NULL) { 1220296465Sdelphij /* 1221296465Sdelphij * sorry, but a EC_GROUP-structur is necessary to set the public key 1222296465Sdelphij */ 1223296465Sdelphij ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); 1224296465Sdelphij return 0; 1225296465Sdelphij } 1226296465Sdelphij ret = *a; 1227296465Sdelphij if (ret->pub_key == NULL && 1228296465Sdelphij (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { 1229296465Sdelphij ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); 1230296465Sdelphij return 0; 1231296465Sdelphij } 1232296465Sdelphij if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) { 1233296465Sdelphij ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); 1234296465Sdelphij return 0; 1235296465Sdelphij } 1236296465Sdelphij /* save the point conversion form */ 1237296465Sdelphij ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01); 1238296465Sdelphij *in += len; 1239296465Sdelphij return ret; 1240296465Sdelphij} 1241160814Ssimon 1242160814Ssimonint i2o_ECPublicKey(EC_KEY *a, unsigned char **out) 1243296465Sdelphij{ 1244296465Sdelphij size_t buf_len = 0; 1245296465Sdelphij int new_buffer = 0; 1246160814Ssimon 1247296465Sdelphij if (a == NULL) { 1248296465Sdelphij ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); 1249296465Sdelphij return 0; 1250296465Sdelphij } 1251160814Ssimon 1252296465Sdelphij buf_len = EC_POINT_point2oct(a->group, a->pub_key, 1253296465Sdelphij a->conv_form, NULL, 0, NULL); 1254160814Ssimon 1255296465Sdelphij if (out == NULL || buf_len == 0) 1256296465Sdelphij /* out == NULL => just return the length of the octet string */ 1257296465Sdelphij return buf_len; 1258160814Ssimon 1259296465Sdelphij if (*out == NULL) { 1260296465Sdelphij if ((*out = OPENSSL_malloc(buf_len)) == NULL) { 1261296465Sdelphij ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); 1262296465Sdelphij return 0; 1263296465Sdelphij } 1264296465Sdelphij new_buffer = 1; 1265296465Sdelphij } 1266296465Sdelphij if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, 1267296465Sdelphij *out, buf_len, NULL)) { 1268296465Sdelphij ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); 1269296465Sdelphij OPENSSL_free(*out); 1270296465Sdelphij *out = NULL; 1271296465Sdelphij return 0; 1272296465Sdelphij } 1273296465Sdelphij if (!new_buffer) 1274296465Sdelphij *out += buf_len; 1275296465Sdelphij return buf_len; 1276296465Sdelphij} 1277