Blame SOURCES/ec_curve.c

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