a5ef24
/* crypto/ec/ec_curve.c */
a5ef24
/*
a5ef24
 * Written by Nils Larsch for the OpenSSL project.
a5ef24
 */
a5ef24
/* ====================================================================
a5ef24
 * Copyright (c) 1998-2010 The OpenSSL Project.  All rights reserved.
a5ef24
 *
a5ef24
 * Redistribution and use in source and binary forms, with or without
a5ef24
 * modification, are permitted provided that the following conditions
a5ef24
 * are met:
a5ef24
 *
a5ef24
 * 1. Redistributions of source code must retain the above copyright
cfec1a
 *    notice, this list of conditions and the following disclaimer.
a5ef24
 *
a5ef24
 * 2. Redistributions in binary form must reproduce the above copyright
a5ef24
 *    notice, this list of conditions and the following disclaimer in
a5ef24
 *    the documentation and/or other materials provided with the
a5ef24
 *    distribution.
a5ef24
 *
a5ef24
 * 3. All advertising materials mentioning features or use of this
a5ef24
 *    software must display the following acknowledgment:
a5ef24
 *    "This product includes software developed by the OpenSSL Project
a5ef24
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
a5ef24
 *
a5ef24
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
a5ef24
 *    endorse or promote products derived from this software without
a5ef24
 *    prior written permission. For written permission, please contact
a5ef24
 *    openssl-core@openssl.org.
a5ef24
 *
a5ef24
 * 5. Products derived from this software may not be called "OpenSSL"
a5ef24
 *    nor may "OpenSSL" appear in their names without prior written
a5ef24
 *    permission of the OpenSSL Project.
a5ef24
 *
a5ef24
 * 6. Redistributions of any form whatsoever must retain the following
a5ef24
 *    acknowledgment:
a5ef24
 *    "This product includes software developed by the OpenSSL Project
a5ef24
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
a5ef24
 *
a5ef24
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
a5ef24
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
a5ef24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
a5ef24
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
a5ef24
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
a5ef24
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
a5ef24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
a5ef24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
a5ef24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
a5ef24
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
a5ef24
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
a5ef24
 * OF THE POSSIBILITY OF SUCH DAMAGE.
a5ef24
 * ====================================================================
a5ef24
 *
a5ef24
 * This product includes cryptographic software written by Eric Young
a5ef24
 * (eay@cryptsoft.com).  This product includes software written by Tim
a5ef24
 * Hudson (tjh@cryptsoft.com).
a5ef24
 *
a5ef24
 */
a5ef24
/* ====================================================================
a5ef24
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
a5ef24
 *
cfec1a
 * Portions of the attached software ("Contribution") are developed by
a5ef24
 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
a5ef24
 *
a5ef24
 * The Contribution is licensed pursuant to the OpenSSL open source
a5ef24
 * license provided above.
a5ef24
 *
cfec1a
 * The elliptic curve binary polynomial software is originally written by
a5ef24
 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
a5ef24
 *
a5ef24
 */
a5ef24
cfec1a
#include <string.h>
a5ef24
#include "ec_lcl.h"
a5ef24
#include <openssl/err.h>
a5ef24
#include <openssl/obj_mac.h>
a5ef24
#include <openssl/opensslconf.h>
a5ef24
cfec1a
#ifdef OPENSSL_FIPS
cfec1a
# include <openssl/fips.h>
cfec1a
#endif
cfec1a
a5ef24
typedef struct {
cfec1a
    int field_type,             /* either NID_X9_62_prime_field or
cfec1a
                                 * NID_X9_62_characteristic_two_field */
cfec1a
     seed_len, param_len;
cfec1a
    unsigned int cofactor;      /* promoted to BN_ULONG */
a5ef24
} EC_CURVE_DATA;
a5ef24
cfec1a
/* the nist prime curves */
cfec1a
static const struct {
cfec1a
    EC_CURVE_DATA h;
cfec1a
    unsigned char data[20 + 48 * 6];
cfec1a
} _EC_NIST_PRIME_384 = {
cfec1a
    {
cfec1a
        NID_X9_62_prime_field, 20, 48, 1
cfec1a
    },
cfec1a
    {
cfec1a
        /* seed */
cfec1a
        0xA3, 0x35, 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00, 0x89, 0x6A,
cfec1a
        0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD, 0xAC, 0x73,
cfec1a
        /* p */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        /* a */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
cfec1a
        /* b */
cfec1a
        0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
cfec1a
        0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
cfec1a
        0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
cfec1a
        0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
cfec1a
        /* x */
cfec1a
        0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
cfec1a
        0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
cfec1a
        0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
cfec1a
        0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
cfec1a
        /* y */
cfec1a
        0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
cfec1a
        0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
cfec1a
        0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
cfec1a
        0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
cfec1a
        /* order */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
cfec1a
        0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
cfec1a
    }
cfec1a
};
cfec1a
cfec1a
static const struct {
cfec1a
    EC_CURVE_DATA h;
cfec1a
    unsigned char data[20 + 66 * 6];
cfec1a
} _EC_NIST_PRIME_521 = {
cfec1a
    {
cfec1a
        NID_X9_62_prime_field, 20, 66, 1
cfec1a
    },
cfec1a
    {
cfec1a
        /* seed */
cfec1a
        0xD0, 0x9E, 0x88, 0x00, 0x29, 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17,
cfec1a
        0x39, 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA,
cfec1a
        /* p */
cfec1a
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        /* a */
cfec1a
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
cfec1a
        /* b */
cfec1a
        0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
cfec1a
        0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
cfec1a
        0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
cfec1a
        0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
cfec1a
        0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
cfec1a
        0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
cfec1a
        /* x */
cfec1a
        0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
cfec1a
        0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
cfec1a
        0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
cfec1a
        0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
cfec1a
        0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
cfec1a
        0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
cfec1a
        /* y */
cfec1a
        0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
cfec1a
        0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
cfec1a
        0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
cfec1a
        0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
cfec1a
        0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
cfec1a
        0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
cfec1a
        /* order */
cfec1a
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
cfec1a
        0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
cfec1a
        0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
cfec1a
        0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
cfec1a
    }
cfec1a
};
cfec1a
cfec1a
static const struct {
cfec1a
    EC_CURVE_DATA h;
cfec1a
    unsigned char data[20 + 32 * 6];
cfec1a
} _EC_X9_62_PRIME_256V1 = {
cfec1a
    {
cfec1a
        NID_X9_62_prime_field, 20, 32, 1
cfec1a
    },
cfec1a
    {
cfec1a
        /* seed */
cfec1a
        0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1,
cfec1a
        0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90,
cfec1a
        /* p */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
cfec1a
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        /* a */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
cfec1a
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
cfec1a
        /* b */
cfec1a
        0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
cfec1a
        0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
cfec1a
        0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
cfec1a
        /* x */
cfec1a
        0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
cfec1a
        0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
cfec1a
        0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
cfec1a
        /* y */
cfec1a
        0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
cfec1a
        0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
cfec1a
        0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
cfec1a
        /* order */
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
cfec1a
        0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
cfec1a
        0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
cfec1a
    }
cfec1a
};
a5ef24
a5ef24
typedef struct _ec_list_element_st {
cfec1a
    int nid;
cfec1a
    const EC_CURVE_DATA *data;
cfec1a
    const EC_METHOD *(*meth) (void);
cfec1a
    const char *comment;
cfec1a
} ec_list_element;
a5ef24
a5ef24
static const ec_list_element curve_list[] = {
cfec1a
    /* prime field curves */
cfec1a
    /* secg curves */
cfec1a
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
cfec1a
    {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
cfec1a
     "NIST/SECG curve over a 384 bit prime field"},
a5ef24
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
cfec1a
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
cfec1a
     "NIST/SECG curve over a 521 bit prime field"},
a5ef24
#else
cfec1a
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
cfec1a
     "NIST/SECG curve over a 521 bit prime field"},
a5ef24
#endif
cfec1a
    /* X9.62 curves */
cfec1a
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
cfec1a
#if defined(ECP_NISTZ256_ASM)
cfec1a
     EC_GFp_nistz256_method,
cfec1a
#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
cfec1a
     EC_GFp_nistp256_method,
a5ef24
#else
cfec1a
     0,
a5ef24
#endif
cfec1a
     "X9.62/SECG curve over a 256 bit prime field"},
a5ef24
};
a5ef24
a5ef24
#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element))
a5ef24
a5ef24
static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
cfec1a
{
cfec1a
    EC_GROUP *group = NULL;
cfec1a
    EC_POINT *P = NULL;
cfec1a
    BN_CTX *ctx = NULL;
cfec1a
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order =
cfec1a
        NULL;
cfec1a
    int ok = 0;
cfec1a
    int seed_len, param_len;
cfec1a
    const EC_METHOD *meth;
cfec1a
    const EC_CURVE_DATA *data;
cfec1a
    const unsigned char *params;
cfec1a
cfec1a
    if ((ctx = BN_CTX_new()) == NULL) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
cfec1a
        goto err;
cfec1a
    }
cfec1a
cfec1a
    data = curve.data;
cfec1a
    seed_len = data->seed_len;
cfec1a
    param_len = data->param_len;
cfec1a
    params = (const unsigned char *)(data + 1); /* skip header */
cfec1a
    params += seed_len;         /* skip seed */
cfec1a
cfec1a
    if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL))
cfec1a
        || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL))
cfec1a
        || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
cfec1a
    if (curve.meth != 0) {
cfec1a
        meth = curve.meth();
cfec1a
        if (((group = EC_GROUP_new(meth)) == NULL) ||
cfec1a
            (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
cfec1a
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
            goto err;
cfec1a
        }
cfec1a
    } else if (data->field_type == NID_X9_62_prime_field) {
cfec1a
        if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
cfec1a
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
            goto err;
cfec1a
        }
cfec1a
    }
a5ef24
#ifndef OPENSSL_NO_EC2M
cfec1a
    else {                      /* field_type ==
cfec1a
                                 * NID_X9_62_characteristic_two_field */
cfec1a
cfec1a
        if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) {
cfec1a
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
            goto err;
cfec1a
        }
cfec1a
    }
a5ef24
#endif
a5ef24
cfec1a
    if ((P = EC_POINT_new(group)) == NULL) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
cfec1a
    if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL))
cfec1a
        || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
    if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
    if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL))
cfec1a
        || !BN_set_word(x, (BN_ULONG)data->cofactor)) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
    if (!EC_GROUP_set_generator(group, P, order, x)) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
        goto err;
cfec1a
    }
cfec1a
    if (seed_len) {
cfec1a
        if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
cfec1a
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
cfec1a
            goto err;
cfec1a
        }
cfec1a
    }
cfec1a
    ok = 1;
cfec1a
 err:
cfec1a
    if (!ok) {
cfec1a
        EC_GROUP_free(group);
cfec1a
        group = NULL;
cfec1a
    }
cfec1a
    if (P)
cfec1a
        EC_POINT_free(P);
cfec1a
    if (ctx)
cfec1a
        BN_CTX_free(ctx);
cfec1a
    if (p)
cfec1a
        BN_free(p);
cfec1a
    if (a)
cfec1a
        BN_free(a);
cfec1a
    if (b)
cfec1a
        BN_free(b);
cfec1a
    if (order)
cfec1a
        BN_free(order);
cfec1a
    if (x)
cfec1a
        BN_free(x);
cfec1a
    if (y)
cfec1a
        BN_free(y);
cfec1a
    return group;
cfec1a
}
a5ef24
a5ef24
EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
cfec1a
{
cfec1a
    size_t i;
cfec1a
    EC_GROUP *ret = NULL;
a5ef24
cfec1a
    if (nid <= 0)
cfec1a
        return NULL;
a5ef24
cfec1a
    for (i = 0; i < curve_list_length; i++)
cfec1a
        if (curve_list[i].nid == nid) {
cfec1a
            ret = ec_group_new_from_data(curve_list[i]);
cfec1a
            break;
cfec1a
        }
a5ef24
cfec1a
    if (ret == NULL) {
cfec1a
        ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
cfec1a
        return NULL;
cfec1a
    }
a5ef24
cfec1a
    EC_GROUP_set_curve_name(ret, nid);
a5ef24
cfec1a
    return ret;
cfec1a
}
a5ef24
a5ef24
size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
cfec1a
{
cfec1a
    size_t i, min;
cfec1a
cfec1a
    if (r == NULL || nitems == 0)
cfec1a
        return curve_list_length;
cfec1a
cfec1a
    min = nitems < curve_list_length ? nitems : curve_list_length;
a5ef24
cfec1a
    for (i = 0; i < min; i++) {
cfec1a
        r[i].nid = curve_list[i].nid;
cfec1a
        r[i].comment = curve_list[i].comment;
cfec1a
    }
a5ef24
cfec1a
    return curve_list_length;
cfec1a
}
cfec1a
cfec1a
/* Functions to translate between common NIST curve names and NIDs */
cfec1a
cfec1a
typedef struct {
cfec1a
    const char *name;           /* NIST Name of curve */
cfec1a
    int nid;                    /* Curve NID */
cfec1a
} EC_NIST_NAME;
cfec1a
cfec1a
static EC_NIST_NAME nist_curves[] = {
cfec1a
    {"B-163", NID_sect163r2},
cfec1a
    {"B-233", NID_sect233r1},
cfec1a
    {"B-283", NID_sect283r1},
cfec1a
    {"B-409", NID_sect409r1},
cfec1a
    {"B-571", NID_sect571r1},
cfec1a
    {"K-163", NID_sect163k1},
cfec1a
    {"K-233", NID_sect233k1},
cfec1a
    {"K-283", NID_sect283k1},
cfec1a
    {"K-409", NID_sect409k1},
cfec1a
    {"K-571", NID_sect571k1},
cfec1a
    {"P-192", NID_X9_62_prime192v1},
cfec1a
    {"P-224", NID_secp224r1},
cfec1a
    {"P-256", NID_X9_62_prime256v1},
cfec1a
    {"P-384", NID_secp384r1},
cfec1a
    {"P-521", NID_secp521r1}
cfec1a
};
a5ef24
cfec1a
const char *EC_curve_nid2nist(int nid)
cfec1a
{
cfec1a
    size_t i;
cfec1a
    for (i = 0; i < sizeof(nist_curves) / sizeof(EC_NIST_NAME); i++) {
cfec1a
        if (nist_curves[i].nid == nid)
cfec1a
            return nist_curves[i].name;
cfec1a
    }
cfec1a
    return NULL;
cfec1a
}
a5ef24
cfec1a
int EC_curve_nist2nid(const char *name)
cfec1a
{
cfec1a
    size_t i;
cfec1a
    for (i = 0; i < sizeof(nist_curves) / sizeof(EC_NIST_NAME); i++) {
cfec1a
        if (!strcmp(nist_curves[i].name, name))
cfec1a
            return nist_curves[i].nid;
cfec1a
    }
cfec1a
    return NID_undef;
cfec1a
}