b629b66
/*
5de6bbd
 * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
b629b66
 *
5de6bbd
 * Licensed under the OpenSSL license (the "License").  You may not use
5de6bbd
 * this file except in compliance with the License.  You can obtain a copy
5de6bbd
 * in the file LICENSE in the source distribution or at
5de6bbd
 * https://www.openssl.org/source/license.html
b629b66
 */
5de6bbd
b629b66
/* ====================================================================
b629b66
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
b629b66
 *
038bb32
 * Portions of the attached software ("Contribution") are developed by
b629b66
 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
b629b66
 *
b629b66
 * The Contribution is licensed pursuant to the OpenSSL open source
b629b66
 * license provided above.
b629b66
 *
038bb32
 * The elliptic curve binary polynomial software is originally written by
b629b66
 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
b629b66
 *
b629b66
 */
b629b66
038bb32
#include <string.h>
b629b66
#include "ec_lcl.h"
b629b66
#include <openssl/err.h>
b629b66
#include <openssl/obj_mac.h>
b629b66
#include <openssl/opensslconf.h>
5de6bbd
#include "e_os.h"
038bb32
b629b66
typedef struct {
038bb32
    int field_type,             /* either NID_X9_62_prime_field or
038bb32
                                 * NID_X9_62_characteristic_two_field */
038bb32
     seed_len, param_len;
038bb32
    unsigned int cofactor;      /* promoted to BN_ULONG */
b629b66
} EC_CURVE_DATA;
b629b66
038bb32
/* the nist prime curves */
038bb32
static const struct {
038bb32
    EC_CURVE_DATA h;
5de6bbd
    unsigned char data[20 + 28 * 6];
5de6bbd
} _EC_NIST_PRIME_224 = {
5de6bbd
    {
5de6bbd
        NID_X9_62_prime_field, 20, 28, 1
5de6bbd
    },
5de6bbd
    {
5de6bbd
        /* seed */
5de6bbd
        0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7, 0xFC, 0xDC, 0x45, 0xB5, 0x9F,
5de6bbd
        0xA3, 0xB9, 0xAB, 0x8F, 0x6A, 0x94, 0x8B, 0xC5,
5de6bbd
        /* p */
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        0x00, 0x00, 0x00, 0x01,
5de6bbd
        /* a */
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFE,
5de6bbd
        /* b */
5de6bbd
        0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
5de6bbd
        0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
5de6bbd
        0x23, 0x55, 0xFF, 0xB4,
5de6bbd
        /* x */
5de6bbd
        0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
5de6bbd
        0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
5de6bbd
        0x11, 0x5C, 0x1D, 0x21,
5de6bbd
        /* y */
5de6bbd
        0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
5de6bbd
        0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
5de6bbd
        0x85, 0x00, 0x7e, 0x34,
5de6bbd
        /* order */
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
5de6bbd
        0x5C, 0x5C, 0x2A, 0x3D
5de6bbd
    }
5de6bbd
};
5de6bbd
5de6bbd
static const struct {
5de6bbd
    EC_CURVE_DATA h;
038bb32
    unsigned char data[20 + 48 * 6];
038bb32
} _EC_NIST_PRIME_384 = {
038bb32
    {
038bb32
        NID_X9_62_prime_field, 20, 48, 1
038bb32
    },
038bb32
    {
038bb32
        /* seed */
038bb32
        0xA3, 0x35, 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00, 0x89, 0x6A,
038bb32
        0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD, 0xAC, 0x73,
038bb32
        /* p */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        /* a */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
038bb32
        /* b */
038bb32
        0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
038bb32
        0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
038bb32
        0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
038bb32
        0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
038bb32
        /* x */
038bb32
        0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
038bb32
        0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
038bb32
        0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
038bb32
        0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
038bb32
        /* y */
038bb32
        0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
038bb32
        0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
038bb32
        0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
038bb32
        0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
038bb32
        /* order */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
038bb32
        0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
038bb32
    }
038bb32
};
038bb32
038bb32
static const struct {
038bb32
    EC_CURVE_DATA h;
038bb32
    unsigned char data[20 + 66 * 6];
038bb32
} _EC_NIST_PRIME_521 = {
038bb32
    {
038bb32
        NID_X9_62_prime_field, 20, 66, 1
038bb32
    },
038bb32
    {
038bb32
        /* seed */
038bb32
        0xD0, 0x9E, 0x88, 0x00, 0x29, 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17,
038bb32
        0x39, 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA,
038bb32
        /* p */
038bb32
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        /* a */
038bb32
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
038bb32
        /* b */
038bb32
        0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
038bb32
        0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
038bb32
        0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
038bb32
        0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
038bb32
        0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
038bb32
        0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
038bb32
        /* x */
038bb32
        0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
038bb32
        0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
038bb32
        0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
038bb32
        0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
038bb32
        0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
038bb32
        0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
038bb32
        /* y */
038bb32
        0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
038bb32
        0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
038bb32
        0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
038bb32
        0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
038bb32
        0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
038bb32
        0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
038bb32
        /* order */
038bb32
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
038bb32
        0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
038bb32
        0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
038bb32
        0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
038bb32
    }
038bb32
};
038bb32
038bb32
static const struct {
038bb32
    EC_CURVE_DATA h;
038bb32
    unsigned char data[20 + 32 * 6];
038bb32
} _EC_X9_62_PRIME_256V1 = {
038bb32
    {
038bb32
        NID_X9_62_prime_field, 20, 32, 1
038bb32
    },
038bb32
    {
038bb32
        /* seed */
038bb32
        0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1,
038bb32
        0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90,
038bb32
        /* p */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
038bb32
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        /* a */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
038bb32
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
038bb32
        /* b */
038bb32
        0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
038bb32
        0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
038bb32
        0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
038bb32
        /* x */
038bb32
        0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
038bb32
        0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
038bb32
        0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
038bb32
        /* y */
038bb32
        0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
038bb32
        0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
038bb32
        0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
038bb32
        /* order */
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
038bb32
        0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
038bb32
        0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
038bb32
    }
038bb32
};
b629b66
5de6bbd
static const struct {
5de6bbd
    EC_CURVE_DATA h;
5de6bbd
    unsigned char data[0 + 32 * 6];
5de6bbd
} _EC_SECG_PRIME_256K1 = {
5de6bbd
    {
5de6bbd
        NID_X9_62_prime_field, 0, 32, 1
5de6bbd
    },
5de6bbd
    {
5de6bbd
        /* no seed */
5de6bbd
        /* p */
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
5de6bbd
        /* a */
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        /* b */
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5de6bbd
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
5de6bbd
        /* x */
5de6bbd
        0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,
5de6bbd
        0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
5de6bbd
        0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
5de6bbd
        /* y */
5de6bbd
        0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,
5de6bbd
        0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
5de6bbd
        0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,
5de6bbd
        /* order */
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5de6bbd
        0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
5de6bbd
        0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
5de6bbd
    }
5de6bbd
};
5de6bbd
b629b66
typedef struct _ec_list_element_st {
038bb32
    int nid;
038bb32
    const EC_CURVE_DATA *data;
038bb32
    const EC_METHOD *(*meth) (void);
038bb32
    const char *comment;
038bb32
} ec_list_element;
b629b66
b629b66
static const ec_list_element curve_list[] = {
038bb32
    /* prime field curves */
038bb32
    /* secg curves */
5de6bbd
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
5de6bbd
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
5de6bbd
     "NIST/SECG curve over a 224 bit prime field"},
5de6bbd
#else
5de6bbd
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
5de6bbd
     "NIST/SECG curve over a 224 bit prime field"},
5de6bbd
#endif
5de6bbd
    {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
5de6bbd
     "SECG curve over a 256 bit prime field"},
038bb32
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
038bb32
    {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
038bb32
     "NIST/SECG curve over a 384 bit prime field"},
b629b66
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
038bb32
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
038bb32
     "NIST/SECG curve over a 521 bit prime field"},
b629b66
#else
038bb32
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
038bb32
     "NIST/SECG curve over a 521 bit prime field"},
b629b66
#endif
038bb32
    /* X9.62 curves */
038bb32
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
038bb32
#if defined(ECP_NISTZ256_ASM)
038bb32
     EC_GFp_nistz256_method,
038bb32
#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
038bb32
     EC_GFp_nistp256_method,
b629b66
#else
038bb32
     0,
b629b66
#endif
038bb32
     "X9.62/SECG curve over a 256 bit prime field"},
b629b66
};
b629b66
5de6bbd
#define curve_list_length OSSL_NELEM(curve_list)
b629b66
b629b66
static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
038bb32
{
038bb32
    EC_GROUP *group = NULL;
038bb32
    EC_POINT *P = NULL;
038bb32
    BN_CTX *ctx = NULL;
038bb32
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order =
038bb32
        NULL;
038bb32
    int ok = 0;
038bb32
    int seed_len, param_len;
038bb32
    const EC_METHOD *meth;
038bb32
    const EC_CURVE_DATA *data;
038bb32
    const unsigned char *params;
038bb32
5de6bbd
    /* If no curve data curve method must handle everything */
5de6bbd
    if (curve.data == NULL)
5de6bbd
        return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL);
5de6bbd
038bb32
    if ((ctx = BN_CTX_new()) == NULL) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
038bb32
        goto err;
038bb32
    }
038bb32
038bb32
    data = curve.data;
038bb32
    seed_len = data->seed_len;
038bb32
    param_len = data->param_len;
038bb32
    params = (const unsigned char *)(data + 1); /* skip header */
038bb32
    params += seed_len;         /* skip seed */
038bb32
5de6bbd
    if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL
5de6bbd
        || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL
5de6bbd
        || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
038bb32
        goto err;
038bb32
    }
038bb32
038bb32
    if (curve.meth != 0) {
038bb32
        meth = curve.meth();
038bb32
        if (((group = EC_GROUP_new(meth)) == NULL) ||
038bb32
            (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
038bb32
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
            goto err;
038bb32
        }
038bb32
    } else if (data->field_type == NID_X9_62_prime_field) {
038bb32
        if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
038bb32
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
            goto err;
038bb32
        }
038bb32
    }
b629b66
#ifndef OPENSSL_NO_EC2M
038bb32
    else {                      /* field_type ==
038bb32
                                 * NID_X9_62_characteristic_two_field */
038bb32
038bb32
        if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) {
038bb32
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
            goto err;
038bb32
        }
038bb32
    }
b629b66
#endif
b629b66
038bb32
    if ((P = EC_POINT_new(group)) == NULL) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
        goto err;
038bb32
    }
038bb32
5de6bbd
    if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL
5de6bbd
        || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
038bb32
        goto err;
038bb32
    }
038bb32
    if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
        goto err;
038bb32
    }
5de6bbd
    if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL
038bb32
        || !BN_set_word(x, (BN_ULONG)data->cofactor)) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
038bb32
        goto err;
038bb32
    }
038bb32
    if (!EC_GROUP_set_generator(group, P, order, x)) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
        goto err;
038bb32
    }
038bb32
    if (seed_len) {
038bb32
        if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
038bb32
            ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
038bb32
            goto err;
038bb32
        }
038bb32
    }
038bb32
    ok = 1;
038bb32
 err:
038bb32
    if (!ok) {
038bb32
        EC_GROUP_free(group);
038bb32
        group = NULL;
038bb32
    }
5de6bbd
    EC_POINT_free(P);
5de6bbd
    BN_CTX_free(ctx);
5de6bbd
    BN_free(p);
5de6bbd
    BN_free(a);
5de6bbd
    BN_free(b);
5de6bbd
    BN_free(order);
5de6bbd
    BN_free(x);
5de6bbd
    BN_free(y);
038bb32
    return group;
038bb32
}
b629b66
b629b66
EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
038bb32
{
038bb32
    size_t i;
038bb32
    EC_GROUP *ret = NULL;
b629b66
038bb32
    if (nid <= 0)
038bb32
        return NULL;
b629b66
038bb32
    for (i = 0; i < curve_list_length; i++)
038bb32
        if (curve_list[i].nid == nid) {
038bb32
            ret = ec_group_new_from_data(curve_list[i]);
038bb32
            break;
038bb32
        }
b629b66
038bb32
    if (ret == NULL) {
038bb32
        ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
038bb32
        return NULL;
038bb32
    }
b629b66
038bb32
    EC_GROUP_set_curve_name(ret, nid);
b629b66
038bb32
    return ret;
038bb32
}
b629b66
b629b66
size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
038bb32
{
038bb32
    size_t i, min;
038bb32
038bb32
    if (r == NULL || nitems == 0)
038bb32
        return curve_list_length;
038bb32
038bb32
    min = nitems < curve_list_length ? nitems : curve_list_length;
b629b66
038bb32
    for (i = 0; i < min; i++) {
038bb32
        r[i].nid = curve_list[i].nid;
038bb32
        r[i].comment = curve_list[i].comment;
038bb32
    }
b629b66
038bb32
    return curve_list_length;
038bb32
}
038bb32
038bb32
/* Functions to translate between common NIST curve names and NIDs */
038bb32
038bb32
typedef struct {
038bb32
    const char *name;           /* NIST Name of curve */
038bb32
    int nid;                    /* Curve NID */
038bb32
} EC_NIST_NAME;
038bb32
038bb32
static EC_NIST_NAME nist_curves[] = {
038bb32
    {"B-163", NID_sect163r2},
038bb32
    {"B-233", NID_sect233r1},
038bb32
    {"B-283", NID_sect283r1},
038bb32
    {"B-409", NID_sect409r1},
038bb32
    {"B-571", NID_sect571r1},
038bb32
    {"K-163", NID_sect163k1},
038bb32
    {"K-233", NID_sect233k1},
038bb32
    {"K-283", NID_sect283k1},
038bb32
    {"K-409", NID_sect409k1},
038bb32
    {"K-571", NID_sect571k1},
038bb32
    {"P-192", NID_X9_62_prime192v1},
038bb32
    {"P-224", NID_secp224r1},
038bb32
    {"P-256", NID_X9_62_prime256v1},
038bb32
    {"P-384", NID_secp384r1},
038bb32
    {"P-521", NID_secp521r1}
038bb32
};
b629b66
038bb32
const char *EC_curve_nid2nist(int nid)
038bb32
{
038bb32
    size_t i;
5de6bbd
    for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
038bb32
        if (nist_curves[i].nid == nid)
038bb32
            return nist_curves[i].name;
038bb32
    }
038bb32
    return NULL;
038bb32
}
b629b66
038bb32
int EC_curve_nist2nid(const char *name)
038bb32
{
038bb32
    size_t i;
5de6bbd
    for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
5de6bbd
        if (strcmp(nist_curves[i].name, name) == 0)
038bb32
            return nist_curves[i].nid;
038bb32
    }
038bb32
    return NID_undef;
038bb32
}