Blame SOURCES/ec_curve.c

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