X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fec%2Fec_asn1.c;h=6d72c711f03ce8458f7d13c35e63120b35baaa2a;hb=436ad81f056cd88de374ea4a27da39b4cafb4b27;hp=87cc334444c6186b26f151a6fb13e78492acb053;hpb=f422a51486a3ab415153eccdc3c3746c53da01f4;p=openssl.git diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 87cc334444..6d72c711f0 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -1,59 +1,10 @@ -/* crypto/ec/ec_asn1.c */ /* - * Written by Nils Larsch for the OpenSSL project. - */ -/* ==================================================================== - * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include @@ -61,18 +12,22 @@ #include #include #include +#include "internal/nelem.h" int EC_GROUP_get_basis_type(const EC_GROUP *group) { - int i = 0; + int i; if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_characteristic_two_field) /* everything else is currently not supported */ return 0; - while (group->poly[i] != 0) - i++; + /* Find the last non-zero element of group->poly[] */ + for (i = 0; + i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0; + i++) + continue; if (i == 4) return NID_X9_62_ppBasis; @@ -133,13 +88,13 @@ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, /* some structures needed for the asn1 encoding */ typedef struct x9_62_pentanomial_st { - long k1; - long k2; - long k3; + int32_t k1; + int32_t k2; + int32_t k3; } X9_62_PENTANOMIAL; typedef struct x9_62_characteristic_two_st { - long m; + int32_t m; ASN1_OBJECT *type; union { char *ptr; @@ -173,14 +128,14 @@ typedef struct x9_62_curve_st { ASN1_BIT_STRING *seed; } X9_62_CURVE; -typedef struct ec_parameters_st { - long version; +struct ec_parameters_st { + int32_t version; X9_62_FIELDID *fieldID; X9_62_CURVE *curve; ASN1_OCTET_STRING *base; ASN1_INTEGER *order; ASN1_INTEGER *cofactor; -} ECPARAMETERS; +} /* ECPARAMETERS */ ; struct ecpk_parameters_st { int type; @@ -193,7 +148,7 @@ struct ecpk_parameters_st { /* SEC1 ECPrivateKey */ typedef struct ec_privatekey_st { - long version; + int32_t version; ASN1_OCTET_STRING *privateKey; ECPKPARAMETERS *parameters; ASN1_BIT_STRING *publicKey; @@ -201,10 +156,10 @@ typedef struct ec_privatekey_st { /* the OpenSSL ASN.1 definitions */ ASN1_SEQUENCE(X9_62_PENTANOMIAL) = { - ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), - ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), - ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) -} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) + ASN1_EMBED(X9_62_PENTANOMIAL, k1, INT32), + ASN1_EMBED(X9_62_PENTANOMIAL, k2, INT32), + ASN1_EMBED(X9_62_PENTANOMIAL, k3, INT32) +} static_ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) @@ -218,10 +173,10 @@ ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { } ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { - ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), + ASN1_EMBED(X9_62_CHARACTERISTIC_TWO, m, INT32), ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) -} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) +} static_ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) @@ -236,16 +191,16 @@ ASN1_ADB(X9_62_FIELDID) = { ASN1_SEQUENCE(X9_62_FIELDID) = { ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), ASN1_ADB_OBJECT(X9_62_FIELDID) -} ASN1_SEQUENCE_END(X9_62_FIELDID) +} static_ASN1_SEQUENCE_END(X9_62_FIELDID) ASN1_SEQUENCE(X9_62_CURVE) = { ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END(X9_62_CURVE) +} static_ASN1_SEQUENCE_END(X9_62_CURVE) ASN1_SEQUENCE(ECPARAMETERS) = { - ASN1_SIMPLE(ECPARAMETERS, version, LONG), + ASN1_EMBED(ECPARAMETERS, version, INT32), ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), @@ -267,11 +222,11 @@ DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) ASN1_SEQUENCE(EC_PRIVATEKEY) = { - ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), + ASN1_EMBED(EC_PRIVATEKEY, version, INT32), ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) -} ASN1_SEQUENCE_END(EC_PRIVATEKEY) +} static_ASN1_SEQUENCE_END(EC_PRIVATEKEY) DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) @@ -283,28 +238,6 @@ IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); /* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); -/* - * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS - * object - */ -static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); -/* - * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP - * object - */ -static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, - ECPARAMETERS *); -/* - * ec_asn1_pkparameters2group() creates a EC_GROUP object from a - * ECPKPARAMETERS object - */ -static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); -/* - * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a - * EC_GROUP object - */ -static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, - ECPKPARAMETERS *); /* the function definitions */ @@ -317,10 +250,8 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) return 0; /* clear the old values (if necessary) */ - if (field->fieldType != NULL) - ASN1_OBJECT_free(field->fieldType); - if (field->p.other != NULL) - ASN1_TYPE_free(field->p.other); + ASN1_OBJECT_free(field->fieldType); + ASN1_TYPE_free(field->p.other); nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); /* set OID for the field */ @@ -345,7 +276,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); goto err; } - } else /* nid == NID_X9_62_characteristic_two_field */ + } else if (nid == NID_X9_62_characteristic_two_field) #ifdef OPENSSL_NO_EC2M { ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); @@ -385,7 +316,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) goto err; char_two->p.tpBasis = ASN1_INTEGER_new(); - if (!char_two->p.tpBasis) { + if (char_two->p.tpBasis == NULL) { ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); goto err; } @@ -400,7 +331,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) goto err; char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); - if (!char_two->p.ppBasis) { + if (char_two->p.ppBasis == NULL) { ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); goto err; } @@ -413,19 +344,23 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) /* for ONB the parameters are (asn1) NULL */ char_two->p.onBasis = ASN1_NULL_new(); - if (!char_two->p.onBasis) { + if (char_two->p.onBasis == NULL) { ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); goto err; } } } #endif + else { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_UNSUPPORTED_FIELD); + goto err; + } ok = 1; - err:if (tmp) - BN_free(tmp); - return (ok); + err: + BN_free(tmp); + return ok; } static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) @@ -520,141 +455,116 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) goto err; } } else { - if (curve->seed) { - ASN1_BIT_STRING_free(curve->seed); - curve->seed = NULL; - } + ASN1_BIT_STRING_free(curve->seed); + curve->seed = NULL; } ok = 1; - err:if (buffer_1) - OPENSSL_free(buffer_1); - if (buffer_2) - OPENSSL_free(buffer_2); - if (tmp_1) - BN_free(tmp_1); - if (tmp_2) - BN_free(tmp_2); - return (ok); + err: + OPENSSL_free(buffer_1); + OPENSSL_free(buffer_2); + BN_free(tmp_1); + BN_free(tmp_2); + return ok; } -static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group, - ECPARAMETERS *param) +ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, + ECPARAMETERS *params) { - int ok = 0; size_t len = 0; ECPARAMETERS *ret = NULL; - BIGNUM *tmp = NULL; + const BIGNUM *tmp; unsigned char *buffer = NULL; const EC_POINT *point = NULL; point_conversion_form_t form; - if ((tmp = BN_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (param == NULL) { + if (params == NULL) { if ((ret = ECPARAMETERS_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); goto err; } } else - ret = param; + ret = params; /* set the version (always one) */ ret->version = (long)0x1; /* set the fieldID */ if (!ec_asn1_group2fieldid(group, ret->fieldID)) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); goto err; } /* set the curve */ if (!ec_asn1_group2curve(group, ret->curve)) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); goto err; } /* set the base point */ if ((point = EC_GROUP_get0_generator(group)) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, EC_R_UNDEFINED_GENERATOR); goto err; } form = EC_GROUP_get_point_conversion_form(group); - len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); + len = EC_POINT_point2buf(group, point, form, &buffer, NULL); if (len == 0) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - if ((buffer = OPENSSL_malloc(len)) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); goto err; } if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + OPENSSL_free(buffer); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); goto err; } + ASN1_STRING_set0(ret->base, buffer, len); /* set the order */ - if (!EC_GROUP_get_order(group, tmp, NULL)) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + tmp = EC_GROUP_get0_order(group); + if (tmp == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); goto err; } ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); if (ret->order == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); goto err; } /* set the cofactor (optional) */ - if (EC_GROUP_get_cofactor(group, tmp, NULL)) { + tmp = EC_GROUP_get0_cofactor(group); + if (tmp != NULL) { ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); if (ret->cofactor == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); goto err; } } - ok = 1; + return ret; - err:if (!ok) { - if (ret && !param) - ECPARAMETERS_free(ret); - ret = NULL; - } - if (tmp) - BN_free(tmp); - if (buffer) - OPENSSL_free(buffer); - return (ret); + err: + if (params == NULL) + ECPARAMETERS_free(ret); + return NULL; } -ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, - ECPKPARAMETERS *params) +ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, + ECPKPARAMETERS *params) { int ok = 1, tmp; ECPKPARAMETERS *ret = params; if (ret == NULL) { if ((ret = ECPKPARAMETERS_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE); + ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, ERR_R_MALLOC_FAILURE); return NULL; } } else { - if (ret->type == 0 && ret->value.named_curve) + if (ret->type == 0) ASN1_OBJECT_free(ret->value.named_curve); else if (ret->type == 1 && ret->value.parameters) ECPARAMETERS_free(ret->value.parameters); @@ -662,7 +572,7 @@ ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, if (EC_GROUP_get_asn1_flag(group)) { /* - * use the asn1 OID to describe the the elliptic curve parameters + * use the asn1 OID to describe the elliptic curve parameters */ tmp = EC_GROUP_get_curve_name(group); if (tmp) { @@ -670,13 +580,13 @@ ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) ok = 0; } else - /* we don't kmow the nid => ERROR */ + /* we don't know the nid => ERROR */ ok = 0; } else { /* use the ECPARAMETERS structure */ ret->type = 1; if ((ret->value.parameters = - ec_asn1_group2parameters(group, NULL)) == NULL) + EC_GROUP_get_ecparameters(group, NULL)) == NULL) ok = 0; } @@ -687,7 +597,7 @@ ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, return ret; } -static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) +EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) { int ok = 0, tmp; EC_GROUP *ret = NULL; @@ -697,7 +607,7 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) if (!params->fieldID || !params->fieldID->fieldType || !params->fieldID->p.ptr) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } @@ -705,17 +615,17 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) if (!params->curve || !params->curve->a || !params->curve->a->data || !params->curve->b || !params->curve->b->data) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); if (a == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); goto err; } b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); if (b == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); goto err; } @@ -724,7 +634,7 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) if (tmp == NID_X9_62_characteristic_two_field) #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_GF2M_NOT_SUPPORTED); goto err; } #else @@ -735,12 +645,12 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) field_bits = char_two->m; if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); goto err; } if ((p = BN_new()) == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); goto err; } @@ -751,14 +661,14 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) long tmp_long; if (!char_two->p.tpBasis) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); if (!(char_two->m > tmp_long && tmp_long > 0)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_TRINOMIAL_BASIS); goto err; } @@ -775,14 +685,14 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) penta = char_two->p.ppBasis; if (!penta) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } if (! (char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_PENTANOMIAL_BASIS); goto err; } @@ -799,11 +709,11 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) if (!BN_set_bit(p, 0)) goto err; } else if (tmp == NID_X9_62_onBasis) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_NOT_IMPLEMENTED); goto err; } else { /* error */ - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } @@ -815,44 +725,43 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) /* we have a curve over a prime field */ /* extract the prime number */ if (!params->fieldID->p.prime) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); if (p == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(p) || BN_is_zero(p)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); goto err; } field_bits = BN_num_bits(p); if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); goto err; } /* create the EC_GROUP structure */ ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); } else { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); goto err; } if (ret == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); goto err; } /* extract seed (optional) */ if (params->curve->seed != NULL) { - if (ret->seed != NULL) - OPENSSL_free(ret->seed); - if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret->seed); + if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); goto err; } memcpy(ret->seed, params->curve->seed->data, @@ -861,7 +770,7 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) } if (!params->order || !params->base || !params->base->data) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); goto err; } @@ -875,89 +784,83 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) /* extract the ec point */ if (!EC_POINT_oct2point(ret, point, params->base->data, params->base->length, NULL)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); goto err; } /* extract the order */ if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(a) || BN_is_zero(a)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); goto err; } if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); goto err; } /* extract the cofactor (optional) */ if (params->cofactor == NULL) { - if (b) { - BN_free(b); - b = NULL; - } + BN_free(b); + b = NULL; } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); goto err; } /* set the generator, order and cofactor (if present) */ if (!EC_GROUP_set_generator(ret, point, a, b)) { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); goto err; } ok = 1; - err:if (!ok) { - if (ret) - EC_GROUP_clear_free(ret); + err: + if (!ok) { + EC_GROUP_clear_free(ret); ret = NULL; } - if (p) - BN_free(p); - if (a) - BN_free(a); - if (b) - BN_free(b); - if (point) - EC_POINT_free(point); - return (ret); + BN_free(p); + BN_free(a); + BN_free(b); + EC_POINT_free(point); + return ret; } -EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) +EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) { EC_GROUP *ret = NULL; int tmp = 0; if (params == NULL) { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_MISSING_PARAMETERS); return NULL; } if (params->type == 0) { /* the curve is given by an OID */ tmp = OBJ_obj2nid(params->value.named_curve); if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); return NULL; } EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); } else if (params->type == 1) { /* the parameters are given by a * ECPARAMETERS structure */ - ret = ec_asn1_parameters2group(params->value.parameters); + ret = EC_GROUP_new_from_ecparameters(params->value.parameters); if (!ret) { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB); return NULL; } EC_GROUP_set_asn1_flag(ret, 0x0); } else if (params->type == 2) { /* implicitlyCA */ return NULL; } else { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_ASN1_ERROR); return NULL; } @@ -970,32 +873,34 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) { EC_GROUP *group = NULL; ECPKPARAMETERS *params = NULL; + const unsigned char *p = *in; - if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) { + if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) { ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); ECPKPARAMETERS_free(params); return NULL; } - if ((group = ec_asn1_pkparameters2group(params)) == NULL) { + if ((group = EC_GROUP_new_from_ecpkparameters(params)) == NULL) { ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); ECPKPARAMETERS_free(params); return NULL; } - if (a && *a) + if (a) { EC_GROUP_clear_free(*a); - if (a) *a = group; + } ECPKPARAMETERS_free(params); - return (group); + *in = p; + return group; } int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) { int ret = 0; - ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); + ECPKPARAMETERS *tmp = EC_GROUP_get_ecpkparameters(a, NULL); if (tmp == NULL) { ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); return 0; @@ -1006,18 +911,18 @@ int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) return 0; } ECPKPARAMETERS_free(tmp); - return (ret); + return ret; } /* some EC_KEY functions */ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) { - int ok = 0; EC_KEY *ret = NULL; EC_PRIVATEKEY *priv_key = NULL; + const unsigned char *p = *in; - if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) { + if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) { ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); return NULL; } @@ -1031,9 +936,8 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) ret = *a; if (priv_key->parameters) { - if (ret->group) - EC_GROUP_clear_free(ret->group); - ret->group = ec_asn1_pkparameters2group(priv_key->parameters); + EC_GROUP_clear_free(ret->group); + ret->group = EC_GROUP_new_from_ecpkparameters(priv_key->parameters); } if (ret->group == NULL) { @@ -1044,20 +948,16 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) ret->version = priv_key->version; if (priv_key->privateKey) { - ret->priv_key = BN_bin2bn(ASN1_STRING_data(priv_key->privateKey), - ASN1_STRING_length(priv_key->privateKey), - ret->priv_key); - if (ret->priv_key == NULL) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB); + ASN1_OCTET_STRING *pkey = priv_key->privateKey; + if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey), + ASN1_STRING_length(pkey)) == 0) goto err; - } } else { ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY); goto err; } - if (ret->pub_key) - EC_POINT_clear_free(ret->pub_key); + EC_POINT_clear_free(ret->pub_key); ret->pub_key = EC_POINT_new(ret->group); if (ret->pub_key == NULL) { ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); @@ -1068,56 +968,42 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) const unsigned char *pub_oct; int pub_oct_len; - pub_oct = ASN1_STRING_data(priv_key->publicKey); + pub_oct = ASN1_STRING_get0_data(priv_key->publicKey); pub_oct_len = ASN1_STRING_length(priv_key->publicKey); - /* - * The first byte - point conversion form - must be present. - */ - if (pub_oct_len <= 0) { - ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); - goto err; - } - /* Save the point conversion form. */ - ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01); - if (!EC_POINT_oct2point(ret->group, ret->pub_key, - pub_oct, (size_t)(pub_oct_len), NULL)) { + if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) { ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; } } else { - if (!EC_POINT_mul - (ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } + if (ret->group->meth->keygenpub == NULL + || ret->group->meth->keygenpub(ret) == 0) + goto err; /* Remember the original private-key-only encoding. */ ret->enc_flag |= EC_PKEY_NO_PUBKEY; } if (a) *a = ret; - ok = 1; - err: - if (!ok) { - if (ret && (a == NULL || *a != ret)) - EC_KEY_free(ret); - ret = NULL; - } - - if (priv_key) - EC_PRIVATEKEY_free(priv_key); + EC_PRIVATEKEY_free(priv_key); + *in = p; + return ret; - return (ret); + err: + if (a == NULL || *a != ret) + EC_KEY_free(ret); + EC_PRIVATEKEY_free(priv_key); + return NULL; } int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) { int ret = 0, ok = 0; - unsigned char *buffer = NULL; - size_t buf_len = 0, tmp_len; + unsigned char *priv= NULL, *pub= NULL; + size_t privlen = 0, publen = 0; + EC_PRIVATEKEY *priv_key = NULL; - if (a == NULL || a->group == NULL || a->priv_key == NULL || + if (a == NULL || a->group == NULL || (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); goto err; @@ -1130,26 +1016,19 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) priv_key->version = a->version; - buf_len = (size_t)BN_num_bytes(a->priv_key); - buffer = OPENSSL_malloc(buf_len); - if (buffer == NULL) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - goto err; - } + privlen = EC_KEY_priv2buf(a, &priv); - if (!BN_bn2bin(a->priv_key, buffer)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); + if (privlen == 0) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; } - if (!ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } + ASN1_STRING_set0(priv_key->privateKey, priv, privlen); + priv = NULL; if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) { if ((priv_key->parameters = - ec_asn1_group2pkparameters(a->group, + EC_GROUP_get_ecpkparameters(a->group, priv_key->parameters)) == NULL) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; @@ -1163,31 +1042,17 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) goto err; } - tmp_len = EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, NULL, 0, NULL); + publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL); - if (tmp_len > buf_len) { - unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); - if (!tmp_buffer) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - goto err; - } - buffer = tmp_buffer; - buf_len = tmp_len; - } - - if (!EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, buffer, buf_len, NULL)) { + if (publen == 0) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; } priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (!ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } + ASN1_STRING_set0(priv_key->publicKey, pub, publen); + pub = NULL; } if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { @@ -1196,10 +1061,9 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) } ok = 1; err: - if (buffer) - OPENSSL_free(buffer); - if (priv_key) - EC_PRIVATEKEY_free(priv_key); + OPENSSL_clear_free(priv, privlen); + OPENSSL_free(pub); + EC_PRIVATEKEY_free(priv_key); return (ok ? ret : 0); } @@ -1248,28 +1112,21 @@ EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) if (a == NULL || (*a) == NULL || (*a)->group == NULL) { /* - * sorry, but a EC_GROUP-structur is necessary to set the public key + * sorry, but a EC_GROUP-structure is necessary to set the public key */ ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } ret = *a; - if (ret->pub_key == NULL && - (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) { + if (!EC_KEY_oct2key(ret, *in, len, NULL)) { ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); return 0; } - /* save the point conversion form */ - ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01); *in += len; return ret; } -int i2o_ECPublicKey(EC_KEY *a, unsigned char **out) +int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) { size_t buf_len = 0; int new_buffer = 0; @@ -1306,3 +1163,76 @@ int i2o_ECPublicKey(EC_KEY *a, unsigned char **out) *out += buf_len; return buf_len; } + +ASN1_SEQUENCE(ECDSA_SIG) = { + ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM), + ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM) +} static_ASN1_SEQUENCE_END(ECDSA_SIG) + +DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG) + +ECDSA_SIG *ECDSA_SIG_new(void) +{ + ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); + if (sig == NULL) + ECerr(EC_F_ECDSA_SIG_NEW, ERR_R_MALLOC_FAILURE); + return sig; +} + +void ECDSA_SIG_free(ECDSA_SIG *sig) +{ + if (sig == NULL) + return; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + OPENSSL_free(sig); +} + +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +int ECDSA_size(const EC_KEY *r) +{ + int ret, i; + ASN1_INTEGER bs; + unsigned char buf[4]; + const EC_GROUP *group; + + if (r == NULL) + return 0; + group = EC_KEY_get0_group(r); + if (group == NULL) + return 0; + + i = EC_GROUP_order_bits(group); + if (i == 0) + return 0; + bs.length = (i + 7) / 8; + bs.data = buf; + bs.type = V_ASN1_INTEGER; + /* If the top bit is set the asn1 encoding is 1 larger. */ + buf[0] = 0xff; + + i = i2d_ASN1_INTEGER(&bs, NULL); + i += i; /* r and s */ + ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); + return ret; +}