Blame SOURCES/ec_curve.c

2871ff
/*
2871ff
 * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
2871ff
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
2871ff
 *
2871ff
 * Licensed under the Apache License 2.0 (the "License").  You may not use
2871ff
 * this file except in compliance with the License.  You can obtain a copy
2871ff
 * in the file LICENSE in the source distribution or at
2871ff
 * https://www.openssl.org/source/license.html
2871ff
 */
2871ff
2871ff
/*
2871ff
 * ECDSA low level APIs are deprecated for public use, but still ok for
2871ff
 * internal use.
2871ff
 */
2871ff
#include "internal/deprecated.h"
2871ff
2871ff
#include <string.h>
2871ff
#include "ec_local.h"
2871ff
#include <openssl/err.h>
2871ff
#include <openssl/obj_mac.h>
2871ff
#include <openssl/objects.h>
2871ff
#include <openssl/opensslconf.h>
2871ff
#include "internal/nelem.h"
2871ff
2871ff
typedef struct {
2871ff
    int field_type,             /* either NID_X9_62_prime_field or
2871ff
                                 * NID_X9_62_characteristic_two_field */
2871ff
     seed_len, param_len;
2871ff
    unsigned int cofactor;      /* promoted to BN_ULONG */
2871ff
} EC_CURVE_DATA;
2871ff
2871ff
/* the nist prime curves */
2871ff
static const struct {
2871ff
    EC_CURVE_DATA h;
2871ff
    unsigned char data[20 + 28 * 6];
2871ff
} _EC_NIST_PRIME_224 = {
2871ff
    {
2871ff
        NID_X9_62_prime_field, 20, 28, 1
2871ff
    },
2871ff
    {
2871ff
        /* seed */
2871ff
        0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7, 0xFC, 0xDC, 0x45, 0xB5, 0x9F,
2871ff
        0xA3, 0xB9, 0xAB, 0x8F, 0x6A, 0x94, 0x8B, 0xC5,
2871ff
        /* p */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x01,
2871ff
        /* a */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFE,
2871ff
        /* b */
2871ff
        0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
2871ff
        0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
2871ff
        0x23, 0x55, 0xFF, 0xB4,
2871ff
        /* x */
2871ff
        0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
2871ff
        0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
2871ff
        0x11, 0x5C, 0x1D, 0x21,
2871ff
        /* y */
2871ff
        0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
2871ff
        0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
2871ff
        0x85, 0x00, 0x7e, 0x34,
2871ff
        /* order */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
2871ff
        0x5C, 0x5C, 0x2A, 0x3D
2871ff
    }
2871ff
};
2871ff
2871ff
static const struct {
2871ff
    EC_CURVE_DATA h;
2871ff
    unsigned char data[20 + 48 * 6];
2871ff
} _EC_NIST_PRIME_384 = {
2871ff
    {
2871ff
        NID_X9_62_prime_field, 20, 48, 1
2871ff
    },
2871ff
    {
2871ff
        /* seed */
2871ff
        0xA3, 0x35, 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00, 0x89, 0x6A,
2871ff
        0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD, 0xAC, 0x73,
2871ff
        /* p */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        /* a */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
2871ff
        /* b */
2871ff
        0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
2871ff
        0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
2871ff
        0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
2871ff
        0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
2871ff
        /* x */
2871ff
        0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
2871ff
        0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
2871ff
        0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
2871ff
        0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
2871ff
        /* y */
2871ff
        0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
2871ff
        0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
2871ff
        0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
2871ff
        0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
2871ff
        /* order */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
2871ff
        0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
2871ff
    }
2871ff
};
2871ff
2871ff
static const struct {
2871ff
    EC_CURVE_DATA h;
2871ff
    unsigned char data[20 + 66 * 6];
2871ff
} _EC_NIST_PRIME_521 = {
2871ff
    {
2871ff
        NID_X9_62_prime_field, 20, 66, 1
2871ff
    },
2871ff
    {
2871ff
        /* seed */
2871ff
        0xD0, 0x9E, 0x88, 0x00, 0x29, 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17,
2871ff
        0x39, 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA,
2871ff
        /* p */
2871ff
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        /* a */
2871ff
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
2871ff
        /* b */
2871ff
        0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
2871ff
        0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
2871ff
        0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
2871ff
        0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
2871ff
        0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
2871ff
        0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
2871ff
        /* x */
2871ff
        0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
2871ff
        0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
2871ff
        0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
2871ff
        0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
2871ff
        0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
2871ff
        0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
2871ff
        /* y */
2871ff
        0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
2871ff
        0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
2871ff
        0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
2871ff
        0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
2871ff
        0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
2871ff
        0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
2871ff
        /* order */
2871ff
        0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
2871ff
        0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
2871ff
        0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
2871ff
        0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
2871ff
    }
2871ff
};
2871ff
2871ff
static const struct {
2871ff
    EC_CURVE_DATA h;
2871ff
    unsigned char data[20 + 32 * 6];
2871ff
} _EC_X9_62_PRIME_256V1 = {
2871ff
    {
2871ff
        NID_X9_62_prime_field, 20, 32, 1
2871ff
    },
2871ff
    {
2871ff
        /* seed */
2871ff
        0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1,
2871ff
        0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90,
2871ff
        /* p */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        /* a */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
2871ff
        /* b */
2871ff
        0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
2871ff
        0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
2871ff
        0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
2871ff
        /* x */
2871ff
        0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
2871ff
        0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
2871ff
        0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
2871ff
        /* y */
2871ff
        0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
2871ff
        0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
2871ff
        0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
2871ff
        /* order */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
2871ff
        0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
2871ff
    }
2871ff
};
2871ff
2871ff
static const struct {
2871ff
    EC_CURVE_DATA h;
2871ff
    unsigned char data[0 + 32 * 6];
2871ff
} _EC_SECG_PRIME_256K1 = {
2871ff
    {
2871ff
        NID_X9_62_prime_field, 0, 32, 1
2871ff
    },
2871ff
    {
2871ff
        /* no seed */
2871ff
        /* p */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
2871ff
        /* a */
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        /* b */
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871ff
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
2871ff
        /* x */
2871ff
        0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,
2871ff
        0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
2871ff
        0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
2871ff
        /* y */
2871ff
        0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,
2871ff
        0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
2871ff
        0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,
2871ff
        /* order */
2871ff
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2871ff
        0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
2871ff
        0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
2871ff
    }
2871ff
};
2871ff
2871ff
typedef struct _ec_list_element_st {
2871ff
    int nid;
2871ff
    const EC_CURVE_DATA *data;
2871ff
    const EC_METHOD *(*meth) (void);
2871ff
    const char *comment;
2871ff
} ec_list_element;
2871ff
2871ff
#ifdef FIPS_MODULE
2871ff
static const ec_list_element curve_list[] = {
2871ff
    /* prime field curves */
2871ff
    /* secg curves */
2871ff
    {NID_secp224r1, &_EC_NIST_PRIME_224.h,
2871ff
# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
2871ff
     EC_GFp_nistp224_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "NIST/SECG curve over a 224 bit prime field"},
2871ff
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
2871ff
    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
2871ff
# if defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp384_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "NIST/SECG curve over a 384 bit prime field"},
2871ff
2871ff
    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
2871ff
# if defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp521_method,
2871ff
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
2871ff
     EC_GFp_nistp521_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "NIST/SECG curve over a 521 bit prime field"},
2871ff
2871ff
    /* X9.62 curves */
2871ff
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
2871ff
# if defined(ECP_NISTZ256_ASM)
2871ff
     EC_GFp_nistz256_method,
2871ff
# elif defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp256_method,
2871ff
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
2871ff
     EC_GFp_nistp256_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "X9.62/SECG curve over a 256 bit prime field"},
2871ff
};
2871ff
2871ff
#else
2871ff
2871ff
static const ec_list_element curve_list[] = {
2871ff
    /* prime field curves */
2871ff
    /* secg curves */
2871ff
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
2871ff
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
2871ff
     "NIST/SECG curve over a 224 bit prime field"},
2871ff
# else
2871ff
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
2871ff
     "NIST/SECG curve over a 224 bit prime field"},
2871ff
# endif
2871ff
    {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
2871ff
     "SECG curve over a 256 bit prime field"},
2871ff
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
2871ff
    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
2871ff
# if defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp384_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "NIST/SECG curve over a 384 bit prime field"},
2871ff
    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
2871ff
# if defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp521_method,
2871ff
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
2871ff
     EC_GFp_nistp521_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "NIST/SECG curve over a 521 bit prime field"},
2871ff
    /* X9.62 curves */
2871ff
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
2871ff
# if defined(ECP_NISTZ256_ASM)
2871ff
     EC_GFp_nistz256_method,
2871ff
# elif defined(S390X_EC_ASM)
2871ff
     EC_GFp_s390x_nistp256_method,
2871ff
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
2871ff
     EC_GFp_nistp256_method,
2871ff
# else
2871ff
     0,
2871ff
# endif
2871ff
     "X9.62/SECG curve over a 256 bit prime field"},
2871ff
};
2871ff
#endif /* FIPS_MODULE */
2871ff
2871ff
#define curve_list_length OSSL_NELEM(curve_list)
2871ff
2871ff
static const ec_list_element *ec_curve_nid2curve(int nid)
2871ff
{
2871ff
    size_t i;
2871ff
2871ff
    if (nid <= 0)
2871ff
        return NULL;
2871ff
2871ff
    for (i = 0; i < curve_list_length; i++) {
2871ff
        if (curve_list[i].nid == nid)
2871ff
            return &curve_list[i];
2871ff
    }
2871ff
    return NULL;
2871ff
}
2871ff
2871ff
static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx,
2871ff
                                        const char *propq,
2871ff
                                        const ec_list_element curve)
2871ff
{
2871ff
    EC_GROUP *group = NULL;
2871ff
    EC_POINT *P = NULL;
2871ff
    BN_CTX *ctx = NULL;
2871ff
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order =
2871ff
        NULL;
2871ff
    int ok = 0;
2871ff
    int seed_len, param_len;
2871ff
    const EC_METHOD *meth;
2871ff
    const EC_CURVE_DATA *data;
2871ff
    const unsigned char *params;
2871ff
2871ff
    /* If no curve data curve method must handle everything */
2871ff
    if (curve.data == NULL)
2871ff
        return ossl_ec_group_new_ex(libctx, propq,
2871ff
                                    curve.meth != NULL ? curve.meth() : NULL);
2871ff
2871ff
    if ((ctx = BN_CTX_new_ex(libctx)) == NULL) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
2871ff
        goto err;
2871ff
    }
2871ff
2871ff
    data = curve.data;
2871ff
    seed_len = data->seed_len;
2871ff
    param_len = data->param_len;
2871ff
    params = (const unsigned char *)(data + 1); /* skip header */
2871ff
    params += seed_len;         /* skip seed */
2871ff
2871ff
    if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL
2871ff
        || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL
2871ff
        || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
2871ff
    if (curve.meth != 0) {
2871ff
        meth = curve.meth();
2871ff
        if (((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) ||
2871ff
            (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
2871ff
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
            goto err;
2871ff
        }
2871ff
    } else if (data->field_type == NID_X9_62_prime_field) {
2871ff
        if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
2871ff
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
            goto err;
2871ff
        }
2871ff
    }
2871ff
#ifndef OPENSSL_NO_EC2M
2871ff
    else {                      /* field_type ==
2871ff
                                 * NID_X9_62_characteristic_two_field */
2871ff
2871ff
        if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) {
2871ff
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
            goto err;
2871ff
        }
2871ff
    }
2871ff
#endif
2871ff
2871ff
    EC_GROUP_set_curve_name(group, curve.nid);
2871ff
2871ff
    if ((P = EC_POINT_new(group)) == NULL) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
2871ff
    if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL
2871ff
        || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
    if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
    if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL
2871ff
        || !BN_set_word(x, (BN_ULONG)data->cofactor)) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
    if (!EC_GROUP_set_generator(group, P, order, x)) {
2871ff
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
        goto err;
2871ff
    }
2871ff
    if (seed_len) {
2871ff
        if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) {
2871ff
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
2871ff
            goto err;
2871ff
        }
2871ff
    }
2871ff
    ok = 1;
2871ff
 err:
2871ff
    if (!ok) {
2871ff
        EC_GROUP_free(group);
2871ff
        group = NULL;
2871ff
    }
2871ff
    EC_POINT_free(P);
2871ff
    BN_CTX_free(ctx);
2871ff
    BN_free(p);
2871ff
    BN_free(a);
2871ff
    BN_free(b);
2871ff
    BN_free(order);
2871ff
    BN_free(x);
2871ff
    BN_free(y);
2871ff
    return group;
2871ff
}
2871ff
2871ff
EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq,
2871ff
                                        int nid)
2871ff
{
2871ff
    EC_GROUP *ret = NULL;
2871ff
    const ec_list_element *curve;
2871ff
2871ff
    if ((curve = ec_curve_nid2curve(nid)) == NULL
2871ff
        || (ret = ec_group_new_from_data(libctx, propq, *curve)) == NULL) {
2871ff
#ifndef FIPS_MODULE
2871ff
        ERR_raise_data(ERR_LIB_EC, EC_R_UNKNOWN_GROUP,
2871ff
                       "name=%s", OBJ_nid2sn(nid));
2871ff
#else
2871ff
        ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_GROUP);
2871ff
#endif
2871ff
        return NULL;
2871ff
    }
2871ff
2871ff
    return ret;
2871ff
}
2871ff
2871ff
#ifndef FIPS_MODULE
2871ff
EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
2871ff
{
2871ff
    return EC_GROUP_new_by_curve_name_ex(NULL, NULL, nid);
2871ff
}
2871ff
#endif
2871ff
2871ff
size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
2871ff
{
2871ff
    size_t i, min;
2871ff
2871ff
    if (r == NULL || nitems == 0)
2871ff
        return curve_list_length;
2871ff
2871ff
    min = nitems < curve_list_length ? nitems : curve_list_length;
2871ff
2871ff
    for (i = 0; i < min; i++) {
2871ff
        r[i].nid = curve_list[i].nid;
2871ff
        r[i].comment = curve_list[i].comment;
2871ff
    }
2871ff
2871ff
    return curve_list_length;
2871ff
}
2871ff
2871ff
const char *EC_curve_nid2nist(int nid)
2871ff
{
2871ff
    return ossl_ec_curve_nid2nist_int(nid);
2871ff
}
2871ff
2871ff
int EC_curve_nist2nid(const char *name)
2871ff
{
2871ff
    return ossl_ec_curve_nist2nid_int(name);
2871ff
}
2871ff
2871ff
#define NUM_BN_FIELDS 6
2871ff
/*
2871ff
 * Validates EC domain parameter data for known named curves.
2871ff
 * This can be used when a curve is loaded explicitly (without a curve
2871ff
 * name) or to validate that domain parameters have not been modified.
2871ff
 *
2871ff
 * Returns: The nid associated with the found named curve, or NID_undef
2871ff
 *          if not found. If there was an error it returns -1.
2871ff
 */
2871ff
int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx)
2871ff
{
2871ff
    int ret = -1, nid, len, field_type, param_len;
2871ff
    size_t i, seed_len;
2871ff
    const unsigned char *seed, *params_seed, *params;
2871ff
    unsigned char *param_bytes = NULL;
2871ff
    const EC_CURVE_DATA *data;
2871ff
    const EC_POINT *generator = NULL;
2871ff
    const BIGNUM *cofactor = NULL;
2871ff
    /* An array of BIGNUMs for (p, a, b, x, y, order) */
2871ff
    BIGNUM *bn[NUM_BN_FIELDS] = {NULL, NULL, NULL, NULL, NULL, NULL};
2871ff
2871ff
    /* Use the optional named curve nid as a search field */
2871ff
    nid = EC_GROUP_get_curve_name(group);
2871ff
    field_type = EC_GROUP_get_field_type(group);
2871ff
    seed_len = EC_GROUP_get_seed_len(group);
2871ff
    seed = EC_GROUP_get0_seed(group);
2871ff
    cofactor = EC_GROUP_get0_cofactor(group);
2871ff
2871ff
    BN_CTX_start(ctx);
2871ff
2871ff
    /*
2871ff
     * The built-in curves contains data fields (p, a, b, x, y, order) that are
2871ff
     * all zero-padded to be the same size. The size of the padding is
2871ff
     * determined by either the number of bytes in the field modulus (p) or the
2871ff
     * EC group order, whichever is larger.
2871ff
     */
2871ff
    param_len = BN_num_bytes(group->order);
2871ff
    len = BN_num_bytes(group->field);
2871ff
    if (len > param_len)
2871ff
        param_len = len;
2871ff
2871ff
    /* Allocate space to store the padded data for (p, a, b, x, y, order)  */
2871ff
    param_bytes = OPENSSL_malloc(param_len * NUM_BN_FIELDS);
2871ff
    if (param_bytes == NULL)
2871ff
        goto end;
2871ff
2871ff
    /* Create the bignums */
2871ff
    for (i = 0; i < NUM_BN_FIELDS; ++i) {
2871ff
        if ((bn[i] = BN_CTX_get(ctx)) == NULL)
2871ff
            goto end;
2871ff
    }
2871ff
    /*
2871ff
     * Fill in the bn array with the same values as the internal curves
2871ff
     * i.e. the values are p, a, b, x, y, order.
2871ff
     */
2871ff
    /* Get p, a & b */
2871ff
    if (!(EC_GROUP_get_curve(group, bn[0], bn[1], bn[2], ctx)
2871ff
        && ((generator = EC_GROUP_get0_generator(group)) != NULL)
2871ff
        /* Get x & y */
2871ff
        && EC_POINT_get_affine_coordinates(group, generator, bn[3], bn[4], ctx)
2871ff
        /* Get order */
2871ff
        && EC_GROUP_get_order(group, bn[5], ctx)))
2871ff
        goto end;
2871ff
2871ff
   /*
2871ff
     * Convert the bignum array to bytes that are joined together to form
2871ff
     * a single buffer that contains data for all fields.
2871ff
     * (p, a, b, x, y, order) are all zero padded to be the same size.
2871ff
     */
2871ff
    for (i = 0; i < NUM_BN_FIELDS; ++i) {
2871ff
        if (BN_bn2binpad(bn[i], &param_bytes[i*param_len], param_len) <= 0)
2871ff
            goto end;
2871ff
    }
2871ff
2871ff
    for (i = 0; i < curve_list_length; i++) {
2871ff
        const ec_list_element curve = curve_list[i];
2871ff
2871ff
        data = curve.data;
2871ff
        /* Get the raw order byte data */
2871ff
        params_seed = (const unsigned char *)(data + 1); /* skip header */
2871ff
        params = params_seed + data->seed_len;
2871ff
2871ff
        /* Look for unique fields in the fixed curve data */
2871ff
        if (data->field_type == field_type
2871ff
            && param_len == data->param_len
2871ff
            && (nid <= 0 || nid == curve.nid)
2871ff
            /* check the optional cofactor (ignore if its zero) */
2871ff
            && (BN_is_zero(cofactor)
2871ff
                || BN_is_word(cofactor, (const BN_ULONG)curve.data->cofactor))
2871ff
            /* Check the optional seed (ignore if its not set) */
2871ff
            && (data->seed_len == 0 || seed_len == 0
2871ff
                || ((size_t)data->seed_len == seed_len
2871ff
                     && memcmp(params_seed, seed, seed_len) == 0))
2871ff
            /* Check that the groups params match the built-in curve params */
2871ff
            && memcmp(param_bytes, params, param_len * NUM_BN_FIELDS)
2871ff
                             == 0) {
2871ff
            ret = curve.nid;
2871ff
            goto end;
2871ff
        }
2871ff
    }
2871ff
    /* Gets here if the group was not found */
2871ff
    ret = NID_undef;
2871ff
end:
2871ff
    OPENSSL_free(param_bytes);
2871ff
    BN_CTX_end(ctx);
2871ff
    return ret;
2871ff
}