Blame SOURCES/ec_curve.c

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