b355146
/*
347681c
 * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
9189f03
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
b355146
 *
347681c
 * Licensed under the Apache License 2.0 (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
347681c
/*
347681c
 * ECDSA low level APIs are deprecated for public use, but still ok for
347681c
 * internal use.
347681c
 */
347681c
#include "internal/deprecated.h"
347681c
a1fb602
#include <string.h>
c11b71f
#include "ec_local.h"
b355146
#include <openssl/err.h>
b355146
#include <openssl/obj_mac.h>
347681c
#include <openssl/objects.h>
b355146
#include <openssl/opensslconf.h>
9189f03
#include "internal/nelem.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
347681c
#ifdef FIPS_MODULE
b355146
static const ec_list_element curve_list[] = {
a1fb602
    /* prime field curves */
a1fb602
    /* secg curves */
347681c
    {NID_secp224r1, &_EC_NIST_PRIME_224.h,
347681c
# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
347681c
     EC_GFp_nistp224_method,
347681c
# else
347681c
     0,
347681c
# endif
e443a79
     "NIST/SECG curve over a 224 bit prime field"},
347681c
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
347681c
    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
347681c
# if defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp384_method,
347681c
# else
347681c
     0,
347681c
# endif
347681c
     "NIST/SECG curve over a 384 bit prime field"},
347681c
347681c
    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
347681c
# if defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp521_method,
347681c
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
347681c
     EC_GFp_nistp521_method,
347681c
# else
347681c
     0,
347681c
# endif
347681c
     "NIST/SECG curve over a 521 bit prime field"},
347681c
347681c
    /* X9.62 curves */
347681c
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
347681c
# if defined(ECP_NISTZ256_ASM)
347681c
     EC_GFp_nistz256_method,
347681c
# elif defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp256_method,
347681c
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
347681c
     EC_GFp_nistp256_method,
347681c
# else
347681c
     0,
347681c
# endif
347681c
     "X9.62/SECG curve over a 256 bit prime field"},
347681c
};
347681c
e443a79
#else
347681c
347681c
static const ec_list_element curve_list[] = {
347681c
    /* prime field curves */
347681c
    /* secg curves */
347681c
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
347681c
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
347681c
     "NIST/SECG curve over a 224 bit prime field"},
347681c
# else
e443a79
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
e443a79
     "NIST/SECG curve over a 224 bit prime field"},
347681c
# 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 */
347681c
    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
347681c
# if defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp384_method,
347681c
# else
347681c
     0,
347681c
# endif
a1fb602
     "NIST/SECG curve over a 384 bit prime field"},
347681c
    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
347681c
# if defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp521_method,
347681c
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
347681c
     EC_GFp_nistp521_method,
347681c
# else
347681c
     0,
347681c
# endif
a1fb602
     "NIST/SECG curve over a 521 bit prime field"},
a1fb602
    /* X9.62 curves */
a1fb602
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
347681c
# if defined(ECP_NISTZ256_ASM)
a1fb602
     EC_GFp_nistz256_method,
347681c
# elif defined(S390X_EC_ASM)
347681c
     EC_GFp_s390x_nistp256_method,
347681c
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
a1fb602
     EC_GFp_nistp256_method,
347681c
# else
a1fb602
     0,
347681c
# endif
a1fb602
     "X9.62/SECG curve over a 256 bit prime field"},
b355146
};
347681c
#endif /* FIPS_MODULE */
b355146
510bcc2
#define curve_list_length OSSL_NELEM(curve_list)
b355146
347681c
static const ec_list_element *ec_curve_nid2curve(int nid)
347681c
{
347681c
    size_t i;
347681c
347681c
    if (nid <= 0)
347681c
        return NULL;
347681c
347681c
    for (i = 0; i < curve_list_length; i++) {
347681c
        if (curve_list[i].nid == nid)
347681c
            return &curve_list[i];
347681c
    }
347681c
    return NULL;
347681c
}
347681c
347681c
static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx,
347681c
                                        const char *propq,
347681c
                                        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)
347681c
        return ossl_ec_group_new_ex(libctx, propq,
347681c
                                    curve.meth != NULL ? curve.meth() : NULL);
510bcc2
347681c
    if ((ctx = BN_CTX_new_ex(libctx)) == NULL) {
347681c
        ERR_raise(ERR_LIB_EC, 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) {
347681c
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
a1fb602
        goto err;
a1fb602
    }
a1fb602
a1fb602
    if (curve.meth != 0) {
a1fb602
        meth = curve.meth();
347681c
        if (((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) ||
a1fb602
            (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
347681c
            ERR_raise(ERR_LIB_EC, 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) {
347681c
            ERR_raise(ERR_LIB_EC, 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) {
347681c
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
a1fb602
            goto err;
a1fb602
        }
a1fb602
    }
b355146
#endif
b355146
9189f03
    EC_GROUP_set_curve_name(group, curve.nid);
9189f03
a1fb602
    if ((P = EC_POINT_new(group)) == NULL) {
347681c
        ERR_raise(ERR_LIB_EC, 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) {
347681c
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
a1fb602
        goto err;
a1fb602
    }
62ec0f1
    if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) {
347681c
        ERR_raise(ERR_LIB_EC, 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)) {
347681c
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
a1fb602
        goto err;
a1fb602
    }
a1fb602
    if (!EC_GROUP_set_generator(group, P, order, x)) {
347681c
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
a1fb602
        goto err;
a1fb602
    }
a1fb602
    if (seed_len) {
a1fb602
        if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
347681c
            ERR_raise(ERR_LIB_EC, 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
347681c
EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq,
347681c
                                        int nid)
a1fb602
{
a1fb602
    EC_GROUP *ret = NULL;
347681c
    const ec_list_element *curve;
b355146
347681c
    if ((curve = ec_curve_nid2curve(nid)) == NULL
347681c
        || (ret = ec_group_new_from_data(libctx, propq, *curve)) == NULL) {
347681c
#ifndef FIPS_MODULE
347681c
        ERR_raise_data(ERR_LIB_EC, EC_R_UNKNOWN_GROUP,
347681c
                       "name=%s", OBJ_nid2sn(nid));
347681c
#else
347681c
        ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_GROUP);
347681c
#endif
a1fb602
        return NULL;
a1fb602
    }
b355146
a1fb602
    return ret;
a1fb602
}
b355146
347681c
#ifndef FIPS_MODULE
347681c
EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
347681c
{
347681c
    return EC_GROUP_new_by_curve_name_ex(NULL, NULL, nid);
347681c
}
347681c
#endif
347681c
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
const char *EC_curve_nid2nist(int nid)
a1fb602
{
347681c
    return ossl_ec_curve_nid2nist_int(nid);
a1fb602
}
b355146
a1fb602
int EC_curve_nist2nid(const char *name)
a1fb602
{
347681c
    return ossl_ec_curve_nist2nid_int(name);
a1fb602
}
f6a62c4
f6a62c4
#define NUM_BN_FIELDS 6
f6a62c4
/*
f6a62c4
 * Validates EC domain parameter data for known named curves.
f6a62c4
 * This can be used when a curve is loaded explicitly (without a curve
f6a62c4
 * name) or to validate that domain parameters have not been modified.
f6a62c4
 *
f6a62c4
 * Returns: The nid associated with the found named curve, or NID_undef
f6a62c4
 *          if not found. If there was an error it returns -1.
f6a62c4
 */
347681c
int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
f6a62c4
{
f6a62c4
    int ret = -1, nid, len, field_type, param_len;
f6a62c4
    size_t i, seed_len;
f6a62c4
    const unsigned char *seed, *params_seed, *params;
f6a62c4
    unsigned char *param_bytes = NULL;
f6a62c4
    const EC_CURVE_DATA *data;
f6a62c4
    const EC_POINT *generator = NULL;
f6a62c4
    const BIGNUM *cofactor = NULL;
f6a62c4
    /* An array of BIGNUMs for (p, a, b, x, y, order) */
f6a62c4
    BIGNUM *bn[NUM_BN_FIELDS] = {NULL, NULL, NULL, NULL, NULL, NULL};
f6a62c4
f6a62c4
    /* Use the optional named curve nid as a search field */
f6a62c4
    nid = EC_GROUP_get_curve_name(group);
347681c
    field_type = EC_GROUP_get_field_type(group);
f6a62c4
    seed_len = EC_GROUP_get_seed_len(group);
f6a62c4
    seed = EC_GROUP_get0_seed(group);
f6a62c4
    cofactor = EC_GROUP_get0_cofactor(group);
f6a62c4
f6a62c4
    BN_CTX_start(ctx);
f6a62c4
f6a62c4
    /*
f6a62c4
     * The built-in curves contains data fields (p, a, b, x, y, order) that are
f6a62c4
     * all zero-padded to be the same size. The size of the padding is
f6a62c4
     * determined by either the number of bytes in the field modulus (p) or the
f6a62c4
     * EC group order, whichever is larger.
f6a62c4
     */
f6a62c4
    param_len = BN_num_bytes(group->order);
f6a62c4
    len = BN_num_bytes(group->field);
f6a62c4
    if (len > param_len)
f6a62c4
        param_len = len;
f6a62c4
f6a62c4
    /* Allocate space to store the padded data for (p, a, b, x, y, order)  */
f6a62c4
    param_bytes = OPENSSL_malloc(param_len * NUM_BN_FIELDS);
f6a62c4
    if (param_bytes == NULL)
f6a62c4
        goto end;
f6a62c4
f6a62c4
    /* Create the bignums */
f6a62c4
    for (i = 0; i < NUM_BN_FIELDS; ++i) {
f6a62c4
        if ((bn[i] = BN_CTX_get(ctx)) == NULL)
f6a62c4
            goto end;
f6a62c4
    }
f6a62c4
    /*
f6a62c4
     * Fill in the bn array with the same values as the internal curves
f6a62c4
     * i.e. the values are p, a, b, x, y, order.
f6a62c4
     */
f6a62c4
    /* Get p, a & b */
f6a62c4
    if (!(EC_GROUP_get_curve(group, bn[0], bn[1], bn[2], ctx)
f6a62c4
        && ((generator = EC_GROUP_get0_generator(group)) != NULL)
f6a62c4
        /* Get x & y */
f6a62c4
        && EC_POINT_get_affine_coordinates(group, generator, bn[3], bn[4], ctx)
f6a62c4
        /* Get order */
f6a62c4
        && EC_GROUP_get_order(group, bn[5], ctx)))
f6a62c4
        goto end;
f6a62c4
f6a62c4
   /*
f6a62c4
     * Convert the bignum array to bytes that are joined together to form
f6a62c4
     * a single buffer that contains data for all fields.
f6a62c4
     * (p, a, b, x, y, order) are all zero padded to be the same size.
f6a62c4
     */
f6a62c4
    for (i = 0; i < NUM_BN_FIELDS; ++i) {
f6a62c4
        if (BN_bn2binpad(bn[i], &param_bytes[i*param_len], param_len) <= 0)
f6a62c4
            goto end;
f6a62c4
    }
f6a62c4
f6a62c4
    for (i = 0; i < curve_list_length; i++) {
f6a62c4
        const ec_list_element curve = curve_list[i];
f6a62c4
f6a62c4
        data = curve.data;
f6a62c4
        /* Get the raw order byte data */
f6a62c4
        params_seed = (const unsigned char *)(data + 1); /* skip header */
f6a62c4
        params = params_seed + data->seed_len;
f6a62c4
f6a62c4
        /* Look for unique fields in the fixed curve data */
f6a62c4
        if (data->field_type == field_type
f6a62c4
            && param_len == data->param_len
f6a62c4
            && (nid <= 0 || nid == curve.nid)
f6a62c4
            /* check the optional cofactor (ignore if its zero) */
f6a62c4
            && (BN_is_zero(cofactor)
f6a62c4
                || BN_is_word(cofactor, (const BN_ULONG)curve.data->cofactor))
f6a62c4
            /* Check the optional seed (ignore if its not set) */
f6a62c4
            && (data->seed_len == 0 || seed_len == 0
f6a62c4
                || ((size_t)data->seed_len == seed_len
f6a62c4
                     && memcmp(params_seed, seed, seed_len) == 0))
f6a62c4
            /* Check that the groups params match the built-in curve params */
f6a62c4
            && memcmp(param_bytes, params, param_len * NUM_BN_FIELDS)
f6a62c4
                             == 0) {
f6a62c4
            ret = curve.nid;
f6a62c4
            goto end;
f6a62c4
        }
f6a62c4
    }
f6a62c4
    /* Gets here if the group was not found */
f6a62c4
    ret = NID_undef;
f6a62c4
end:
f6a62c4
    OPENSSL_free(param_bytes);
f6a62c4
    BN_CTX_end(ctx);
f6a62c4
    return ret;
f6a62c4
}