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