Blame SOURCES/ec_curve.c

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