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