Blame SOURCES/ec_curve.c

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