Blame SOURCES/ec_curve.c

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