b355146
/*
510bcc2
 * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
b355146
 *
510bcc2
 * Licensed under the OpenSSL license (the "License").  You may not use
510bcc2
 * this file except in compliance with the License.  You can obtain a copy
510bcc2
 * in the file LICENSE in the source distribution or at
510bcc2
 * https://www.openssl.org/source/license.html
b355146
 */
510bcc2
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>
510bcc2
#include "e_os.h"
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;
e443a79
    unsigned char data[20 + 28 * 6];
e443a79
} _EC_NIST_PRIME_224 = {
e443a79
    {
e443a79
        NID_X9_62_prime_field, 20, 28, 1
e443a79
    },
e443a79
    {
e443a79
        /* seed */
e443a79
        0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7, 0xFC, 0xDC, 0x45, 0xB5, 0x9F,
e443a79
        0xA3, 0xB9, 0xAB, 0x8F, 0x6A, 0x94, 0x8B, 0xC5,
e443a79
        /* p */
e443a79
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
e443a79
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
e443a79
        0x00, 0x00, 0x00, 0x01,
e443a79
        /* a */
e443a79
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
e443a79
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
e443a79
        0xFF, 0xFF, 0xFF, 0xFE,
e443a79
        /* b */
e443a79
        0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
e443a79
        0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
e443a79
        0x23, 0x55, 0xFF, 0xB4,
e443a79
        /* x */
e443a79
        0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
e443a79
        0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
e443a79
        0x11, 0x5C, 0x1D, 0x21,
e443a79
        /* y */
e443a79
        0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
e443a79
        0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
e443a79
        0x85, 0x00, 0x7e, 0x34,
e443a79
        /* order */
e443a79
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
e443a79
        0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
e443a79
        0x5C, 0x5C, 0x2A, 0x3D
e443a79
    }
e443a79
};
e443a79
e443a79
static const struct {
e443a79
    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
510bcc2
static const struct {
510bcc2
    EC_CURVE_DATA h;
510bcc2
    unsigned char data[0 + 32 * 6];
510bcc2
} _EC_SECG_PRIME_256K1 = {
510bcc2
    {
510bcc2
        NID_X9_62_prime_field, 0, 32, 1
510bcc2
    },
510bcc2
    {
510bcc2
        /* no seed */
510bcc2
        /* p */
510bcc2
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
510bcc2
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
510bcc2
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
510bcc2
        /* a */
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510bcc2
        /* b */
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510bcc2
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
510bcc2
        /* x */
510bcc2
        0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,
510bcc2
        0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
510bcc2
        0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
510bcc2
        /* y */
510bcc2
        0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,
510bcc2
        0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
510bcc2
        0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,
510bcc2
        /* order */
510bcc2
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
510bcc2
        0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
510bcc2
        0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
510bcc2
    }
510bcc2
};
510bcc2
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 */
e443a79
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
e443a79
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
e443a79
     "NIST/SECG curve over a 224 bit prime field"},
e443a79
#else
e443a79
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
e443a79
     "NIST/SECG curve over a 224 bit prime field"},
e443a79
#endif
510bcc2
    {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
510bcc2
     "SECG curve over a 256 bit prime field"},
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
510bcc2
#define curve_list_length OSSL_NELEM(curve_list)
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
510bcc2
    /* If no curve data curve method must handle everything */
510bcc2
    if (curve.data == NULL)
510bcc2
        return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL);
510bcc2
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
510bcc2
    if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL
510bcc2
        || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL
510bcc2
        || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == 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
510bcc2
    if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL
510bcc2
        || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == 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
    }
510bcc2
    if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == 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
    }
510bcc2
    EC_POINT_free(P);
510bcc2
    BN_CTX_free(ctx);
510bcc2
    BN_free(p);
510bcc2
    BN_free(a);
510bcc2
    BN_free(b);
510bcc2
    BN_free(order);
510bcc2
    BN_free(x);
510bcc2
    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;
510bcc2
    for (i = 0; i < OSSL_NELEM(nist_curves); 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;
510bcc2
    for (i = 0; i < OSSL_NELEM(nist_curves); i++) {
510bcc2
        if (strcmp(nist_curves[i].name, name) == 0)
a1fb602
            return nist_curves[i].nid;
a1fb602
    }
a1fb602
    return NID_undef;
a1fb602
}