1160814Ssimon/* crypto/ecdsa/ecs_lib.c */ 2160814Ssimon/* ==================================================================== 3160814Ssimon * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4160814Ssimon * 5160814Ssimon * Redistribution and use in source and binary forms, with or without 6160814Ssimon * modification, are permitted provided that the following conditions 7160814Ssimon * are met: 8160814Ssimon * 9160814Ssimon * 1. Redistributions of source code must retain the above copyright 10280304Sjkim * notice, this list of conditions and the following disclaimer. 11160814Ssimon * 12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer in 14160814Ssimon * the documentation and/or other materials provided with the 15160814Ssimon * distribution. 16160814Ssimon * 17160814Ssimon * 3. All advertising materials mentioning features or use of this 18160814Ssimon * software must display the following acknowledgment: 19160814Ssimon * "This product includes software developed by the OpenSSL Project 20160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 21160814Ssimon * 22160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23160814Ssimon * endorse or promote products derived from this software without 24160814Ssimon * prior written permission. For written permission, please contact 25160814Ssimon * openssl-core@OpenSSL.org. 26160814Ssimon * 27160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 28160814Ssimon * nor may "OpenSSL" appear in their names without prior written 29160814Ssimon * permission of the OpenSSL Project. 30160814Ssimon * 31160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 32160814Ssimon * acknowledgment: 33160814Ssimon * "This product includes software developed by the OpenSSL Project 34160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 35160814Ssimon * 36160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 48160814Ssimon * ==================================================================== 49160814Ssimon * 50160814Ssimon * This product includes cryptographic software written by Eric Young 51160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 52160814Ssimon * Hudson (tjh@cryptsoft.com). 53160814Ssimon * 54160814Ssimon */ 55160814Ssimon 56160814Ssimon#include <string.h> 57160814Ssimon#include "ecs_locl.h" 58160814Ssimon#ifndef OPENSSL_NO_ENGINE 59280304Sjkim# include <openssl/engine.h> 60160814Ssimon#endif 61160814Ssimon#include <openssl/err.h> 62160814Ssimon#include <openssl/bn.h> 63238405Sjkim#ifdef OPENSSL_FIPS 64280304Sjkim# include <openssl/fips.h> 65238405Sjkim#endif 66160814Ssimon 67280304Sjkimconst char ECDSA_version[] = "ECDSA" OPENSSL_VERSION_PTEXT; 68160814Ssimon 69160814Ssimonstatic const ECDSA_METHOD *default_ECDSA_method = NULL; 70160814Ssimon 71160814Ssimonstatic void *ecdsa_data_new(void); 72160814Ssimonstatic void *ecdsa_data_dup(void *); 73280304Sjkimstatic void ecdsa_data_free(void *); 74160814Ssimon 75160814Ssimonvoid ECDSA_set_default_method(const ECDSA_METHOD *meth) 76160814Ssimon{ 77280304Sjkim default_ECDSA_method = meth; 78160814Ssimon} 79160814Ssimon 80160814Ssimonconst ECDSA_METHOD *ECDSA_get_default_method(void) 81160814Ssimon{ 82280304Sjkim if (!default_ECDSA_method) { 83238405Sjkim#ifdef OPENSSL_FIPS 84280304Sjkim if (FIPS_mode()) 85280304Sjkim return FIPS_ecdsa_openssl(); 86280304Sjkim else 87280304Sjkim return ECDSA_OpenSSL(); 88238405Sjkim#else 89280304Sjkim default_ECDSA_method = ECDSA_OpenSSL(); 90238405Sjkim#endif 91280304Sjkim } 92280304Sjkim return default_ECDSA_method; 93160814Ssimon} 94160814Ssimon 95160814Ssimonint ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth) 96160814Ssimon{ 97280304Sjkim ECDSA_DATA *ecdsa; 98160814Ssimon 99280304Sjkim ecdsa = ecdsa_check(eckey); 100160814Ssimon 101280304Sjkim if (ecdsa == NULL) 102280304Sjkim return 0; 103160814Ssimon 104160814Ssimon#ifndef OPENSSL_NO_ENGINE 105280304Sjkim if (ecdsa->engine) { 106280304Sjkim ENGINE_finish(ecdsa->engine); 107280304Sjkim ecdsa->engine = NULL; 108280304Sjkim } 109160814Ssimon#endif 110280304Sjkim ecdsa->meth = meth; 111160814Ssimon 112280304Sjkim return 1; 113160814Ssimon} 114160814Ssimon 115160814Ssimonstatic ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine) 116160814Ssimon{ 117280304Sjkim ECDSA_DATA *ret; 118160814Ssimon 119280304Sjkim ret = (ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA)); 120280304Sjkim if (ret == NULL) { 121280304Sjkim ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE); 122280304Sjkim return (NULL); 123280304Sjkim } 124160814Ssimon 125280304Sjkim ret->init = NULL; 126160814Ssimon 127280304Sjkim ret->meth = ECDSA_get_default_method(); 128280304Sjkim ret->engine = engine; 129160814Ssimon#ifndef OPENSSL_NO_ENGINE 130280304Sjkim if (!ret->engine) 131280304Sjkim ret->engine = ENGINE_get_default_ECDSA(); 132280304Sjkim if (ret->engine) { 133280304Sjkim ret->meth = ENGINE_get_ECDSA(ret->engine); 134280304Sjkim if (!ret->meth) { 135280304Sjkim ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); 136280304Sjkim ENGINE_finish(ret->engine); 137280304Sjkim OPENSSL_free(ret); 138280304Sjkim return NULL; 139280304Sjkim } 140280304Sjkim } 141160814Ssimon#endif 142160814Ssimon 143280304Sjkim ret->flags = ret->meth->flags; 144280304Sjkim CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); 145160814Ssimon#if 0 146280304Sjkim if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { 147280304Sjkim CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); 148280304Sjkim OPENSSL_free(ret); 149280304Sjkim ret = NULL; 150280304Sjkim } 151280304Sjkim#endif 152280304Sjkim return (ret); 153160814Ssimon} 154160814Ssimon 155160814Ssimonstatic void *ecdsa_data_new(void) 156160814Ssimon{ 157280304Sjkim return (void *)ECDSA_DATA_new_method(NULL); 158160814Ssimon} 159160814Ssimon 160160814Ssimonstatic void *ecdsa_data_dup(void *data) 161160814Ssimon{ 162280304Sjkim ECDSA_DATA *r = (ECDSA_DATA *)data; 163160814Ssimon 164280304Sjkim /* XXX: dummy operation */ 165280304Sjkim if (r == NULL) 166280304Sjkim return NULL; 167160814Ssimon 168280304Sjkim return ecdsa_data_new(); 169160814Ssimon} 170160814Ssimon 171160814Ssimonstatic void ecdsa_data_free(void *data) 172160814Ssimon{ 173280304Sjkim ECDSA_DATA *r = (ECDSA_DATA *)data; 174160814Ssimon 175160814Ssimon#ifndef OPENSSL_NO_ENGINE 176280304Sjkim if (r->engine) 177280304Sjkim ENGINE_finish(r->engine); 178160814Ssimon#endif 179280304Sjkim CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data); 180160814Ssimon 181280304Sjkim OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA)); 182160814Ssimon 183280304Sjkim OPENSSL_free(r); 184160814Ssimon} 185160814Ssimon 186160814SsimonECDSA_DATA *ecdsa_check(EC_KEY *key) 187160814Ssimon{ 188280304Sjkim ECDSA_DATA *ecdsa_data; 189280304Sjkim 190280304Sjkim void *data = EC_KEY_get_key_method_data(key, ecdsa_data_dup, 191280304Sjkim ecdsa_data_free, ecdsa_data_free); 192280304Sjkim if (data == NULL) { 193280304Sjkim ecdsa_data = (ECDSA_DATA *)ecdsa_data_new(); 194280304Sjkim if (ecdsa_data == NULL) 195280304Sjkim return NULL; 196280304Sjkim data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, 197280304Sjkim ecdsa_data_dup, ecdsa_data_free, 198280304Sjkim ecdsa_data_free); 199280304Sjkim if (data != NULL) { 200280304Sjkim /* 201280304Sjkim * Another thread raced us to install the key_method data and 202280304Sjkim * won. 203280304Sjkim */ 204280304Sjkim ecdsa_data_free(ecdsa_data); 205280304Sjkim ecdsa_data = (ECDSA_DATA *)data; 206280304Sjkim } 207280304Sjkim } else 208280304Sjkim ecdsa_data = (ECDSA_DATA *)data; 209238405Sjkim#ifdef OPENSSL_FIPS 210280304Sjkim if (FIPS_mode() && !(ecdsa_data->flags & ECDSA_FLAG_FIPS_METHOD) 211280304Sjkim && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW)) { 212280304Sjkim ECDSAerr(ECDSA_F_ECDSA_CHECK, ECDSA_R_NON_FIPS_METHOD); 213280304Sjkim return NULL; 214280304Sjkim } 215238405Sjkim#endif 216160814Ssimon 217280304Sjkim return ecdsa_data; 218160814Ssimon} 219160814Ssimon 220160814Ssimonint ECDSA_size(const EC_KEY *r) 221160814Ssimon{ 222280304Sjkim int ret, i; 223280304Sjkim ASN1_INTEGER bs; 224280304Sjkim BIGNUM *order = NULL; 225280304Sjkim unsigned char buf[4]; 226280304Sjkim const EC_GROUP *group; 227160814Ssimon 228280304Sjkim if (r == NULL) 229280304Sjkim return 0; 230280304Sjkim group = EC_KEY_get0_group(r); 231280304Sjkim if (group == NULL) 232280304Sjkim return 0; 233160814Ssimon 234280304Sjkim if ((order = BN_new()) == NULL) 235280304Sjkim return 0; 236280304Sjkim if (!EC_GROUP_get_order(group, order, NULL)) { 237280304Sjkim BN_clear_free(order); 238280304Sjkim return 0; 239280304Sjkim } 240280304Sjkim i = BN_num_bits(order); 241280304Sjkim bs.length = (i + 7) / 8; 242280304Sjkim bs.data = buf; 243280304Sjkim bs.type = V_ASN1_INTEGER; 244280304Sjkim /* If the top bit is set the asn1 encoding is 1 larger. */ 245280304Sjkim buf[0] = 0xff; 246160814Ssimon 247280304Sjkim i = i2d_ASN1_INTEGER(&bs, NULL); 248280304Sjkim i += i; /* r and s */ 249280304Sjkim ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); 250280304Sjkim BN_clear_free(order); 251280304Sjkim return (ret); 252160814Ssimon} 253160814Ssimon 254160814Ssimonint ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 255280304Sjkim CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 256160814Ssimon{ 257280304Sjkim return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDSA, argl, argp, 258280304Sjkim new_func, dup_func, free_func); 259160814Ssimon} 260160814Ssimon 261160814Ssimonint ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg) 262160814Ssimon{ 263280304Sjkim ECDSA_DATA *ecdsa; 264280304Sjkim ecdsa = ecdsa_check(d); 265280304Sjkim if (ecdsa == NULL) 266280304Sjkim return 0; 267280304Sjkim return (CRYPTO_set_ex_data(&ecdsa->ex_data, idx, arg)); 268160814Ssimon} 269160814Ssimon 270160814Ssimonvoid *ECDSA_get_ex_data(EC_KEY *d, int idx) 271160814Ssimon{ 272280304Sjkim ECDSA_DATA *ecdsa; 273280304Sjkim ecdsa = ecdsa_check(d); 274280304Sjkim if (ecdsa == NULL) 275280304Sjkim return NULL; 276280304Sjkim return (CRYPTO_get_ex_data(&ecdsa->ex_data, idx)); 277160814Ssimon} 278