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 10160814Ssimon * 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 59160814Ssimon#include <openssl/engine.h> 60160814Ssimon#endif 61160814Ssimon#include <openssl/err.h> 62160814Ssimon#include <openssl/bn.h> 63238405Sjkim#ifdef OPENSSL_FIPS 64238405Sjkim#include <openssl/fips.h> 65238405Sjkim#endif 66160814Ssimon 67167612Ssimonconst 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 *); 73160814Ssimonstatic void ecdsa_data_free(void *); 74160814Ssimon 75160814Ssimonvoid ECDSA_set_default_method(const ECDSA_METHOD *meth) 76160814Ssimon{ 77160814Ssimon default_ECDSA_method = meth; 78160814Ssimon} 79160814Ssimon 80160814Ssimonconst ECDSA_METHOD *ECDSA_get_default_method(void) 81160814Ssimon{ 82160814Ssimon if(!default_ECDSA_method) 83238405Sjkim { 84238405Sjkim#ifdef OPENSSL_FIPS 85238405Sjkim if (FIPS_mode()) 86238405Sjkim return FIPS_ecdsa_openssl(); 87238405Sjkim else 88238405Sjkim return ECDSA_OpenSSL(); 89238405Sjkim#else 90160814Ssimon default_ECDSA_method = ECDSA_OpenSSL(); 91238405Sjkim#endif 92238405Sjkim } 93160814Ssimon return default_ECDSA_method; 94160814Ssimon} 95160814Ssimon 96160814Ssimonint ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth) 97160814Ssimon{ 98160814Ssimon ECDSA_DATA *ecdsa; 99160814Ssimon 100160814Ssimon ecdsa = ecdsa_check(eckey); 101160814Ssimon 102160814Ssimon if (ecdsa == NULL) 103160814Ssimon return 0; 104160814Ssimon 105160814Ssimon#ifndef OPENSSL_NO_ENGINE 106160814Ssimon if (ecdsa->engine) 107160814Ssimon { 108160814Ssimon ENGINE_finish(ecdsa->engine); 109160814Ssimon ecdsa->engine = NULL; 110160814Ssimon } 111160814Ssimon#endif 112160814Ssimon ecdsa->meth = meth; 113160814Ssimon 114160814Ssimon return 1; 115160814Ssimon} 116160814Ssimon 117160814Ssimonstatic ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine) 118160814Ssimon{ 119160814Ssimon ECDSA_DATA *ret; 120160814Ssimon 121160814Ssimon ret=(ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA)); 122160814Ssimon if (ret == NULL) 123160814Ssimon { 124160814Ssimon ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE); 125160814Ssimon return(NULL); 126160814Ssimon } 127160814Ssimon 128160814Ssimon ret->init = NULL; 129160814Ssimon 130160814Ssimon ret->meth = ECDSA_get_default_method(); 131160814Ssimon ret->engine = engine; 132160814Ssimon#ifndef OPENSSL_NO_ENGINE 133160814Ssimon if (!ret->engine) 134160814Ssimon ret->engine = ENGINE_get_default_ECDSA(); 135160814Ssimon if (ret->engine) 136160814Ssimon { 137160814Ssimon ret->meth = ENGINE_get_ECDSA(ret->engine); 138160814Ssimon if (!ret->meth) 139160814Ssimon { 140160814Ssimon ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); 141160814Ssimon ENGINE_finish(ret->engine); 142160814Ssimon OPENSSL_free(ret); 143160814Ssimon return NULL; 144160814Ssimon } 145160814Ssimon } 146160814Ssimon#endif 147160814Ssimon 148160814Ssimon ret->flags = ret->meth->flags; 149160814Ssimon CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); 150160814Ssimon#if 0 151160814Ssimon if ((ret->meth->init != NULL) && !ret->meth->init(ret)) 152160814Ssimon { 153160814Ssimon CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data); 154160814Ssimon OPENSSL_free(ret); 155160814Ssimon ret=NULL; 156160814Ssimon } 157160814Ssimon#endif 158160814Ssimon return(ret); 159160814Ssimon} 160160814Ssimon 161160814Ssimonstatic void *ecdsa_data_new(void) 162160814Ssimon{ 163160814Ssimon return (void *)ECDSA_DATA_new_method(NULL); 164160814Ssimon} 165160814Ssimon 166160814Ssimonstatic void *ecdsa_data_dup(void *data) 167160814Ssimon{ 168160814Ssimon ECDSA_DATA *r = (ECDSA_DATA *)data; 169160814Ssimon 170160814Ssimon /* XXX: dummy operation */ 171160814Ssimon if (r == NULL) 172160814Ssimon return NULL; 173160814Ssimon 174160814Ssimon return ecdsa_data_new(); 175160814Ssimon} 176160814Ssimon 177160814Ssimonstatic void ecdsa_data_free(void *data) 178160814Ssimon{ 179160814Ssimon ECDSA_DATA *r = (ECDSA_DATA *)data; 180160814Ssimon 181160814Ssimon#ifndef OPENSSL_NO_ENGINE 182160814Ssimon if (r->engine) 183160814Ssimon ENGINE_finish(r->engine); 184160814Ssimon#endif 185160814Ssimon CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data); 186160814Ssimon 187160814Ssimon OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA)); 188160814Ssimon 189160814Ssimon OPENSSL_free(r); 190160814Ssimon} 191160814Ssimon 192160814SsimonECDSA_DATA *ecdsa_check(EC_KEY *key) 193160814Ssimon{ 194160814Ssimon ECDSA_DATA *ecdsa_data; 195160814Ssimon 196160814Ssimon void *data = EC_KEY_get_key_method_data(key, ecdsa_data_dup, 197160814Ssimon ecdsa_data_free, ecdsa_data_free); 198160814Ssimon if (data == NULL) 199160814Ssimon { 200160814Ssimon ecdsa_data = (ECDSA_DATA *)ecdsa_data_new(); 201160814Ssimon if (ecdsa_data == NULL) 202160814Ssimon return NULL; 203246772Sjkim data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, 204246772Sjkim ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free); 205246772Sjkim if (data != NULL) 206246772Sjkim { 207246772Sjkim /* Another thread raced us to install the key_method 208246772Sjkim * data and won. */ 209246772Sjkim ecdsa_data_free(ecdsa_data); 210246772Sjkim ecdsa_data = (ECDSA_DATA *)data; 211246772Sjkim } 212160814Ssimon } 213160814Ssimon else 214160814Ssimon ecdsa_data = (ECDSA_DATA *)data; 215238405Sjkim#ifdef OPENSSL_FIPS 216238405Sjkim if (FIPS_mode() && !(ecdsa_data->flags & ECDSA_FLAG_FIPS_METHOD) 217238405Sjkim && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW)) 218238405Sjkim { 219238405Sjkim ECDSAerr(ECDSA_F_ECDSA_CHECK, ECDSA_R_NON_FIPS_METHOD); 220238405Sjkim return NULL; 221238405Sjkim } 222238405Sjkim#endif 223160814Ssimon 224160814Ssimon return ecdsa_data; 225160814Ssimon} 226160814Ssimon 227160814Ssimonint ECDSA_size(const EC_KEY *r) 228160814Ssimon{ 229160814Ssimon int ret,i; 230160814Ssimon ASN1_INTEGER bs; 231160814Ssimon BIGNUM *order=NULL; 232160814Ssimon unsigned char buf[4]; 233160814Ssimon const EC_GROUP *group; 234160814Ssimon 235160814Ssimon if (r == NULL) 236160814Ssimon return 0; 237160814Ssimon group = EC_KEY_get0_group(r); 238160814Ssimon if (group == NULL) 239160814Ssimon return 0; 240160814Ssimon 241160814Ssimon if ((order = BN_new()) == NULL) return 0; 242160814Ssimon if (!EC_GROUP_get_order(group,order,NULL)) 243160814Ssimon { 244160814Ssimon BN_clear_free(order); 245160814Ssimon return 0; 246160814Ssimon } 247160814Ssimon i=BN_num_bits(order); 248160814Ssimon bs.length=(i+7)/8; 249160814Ssimon bs.data=buf; 250160814Ssimon bs.type=V_ASN1_INTEGER; 251160814Ssimon /* If the top bit is set the asn1 encoding is 1 larger. */ 252160814Ssimon buf[0]=0xff; 253160814Ssimon 254160814Ssimon i=i2d_ASN1_INTEGER(&bs,NULL); 255160814Ssimon i+=i; /* r and s */ 256160814Ssimon ret=ASN1_object_size(1,i,V_ASN1_SEQUENCE); 257160814Ssimon BN_clear_free(order); 258160814Ssimon return(ret); 259160814Ssimon} 260160814Ssimon 261160814Ssimon 262160814Ssimonint ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 263160814Ssimon CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 264160814Ssimon{ 265160814Ssimon return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDSA, argl, argp, 266160814Ssimon new_func, dup_func, free_func); 267160814Ssimon} 268160814Ssimon 269160814Ssimonint ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg) 270160814Ssimon{ 271160814Ssimon ECDSA_DATA *ecdsa; 272160814Ssimon ecdsa = ecdsa_check(d); 273160814Ssimon if (ecdsa == NULL) 274160814Ssimon return 0; 275160814Ssimon return(CRYPTO_set_ex_data(&ecdsa->ex_data,idx,arg)); 276160814Ssimon} 277160814Ssimon 278160814Ssimonvoid *ECDSA_get_ex_data(EC_KEY *d, int idx) 279160814Ssimon{ 280160814Ssimon ECDSA_DATA *ecdsa; 281160814Ssimon ecdsa = ecdsa_check(d); 282160814Ssimon if (ecdsa == NULL) 283160814Ssimon return NULL; 284160814Ssimon return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx)); 285160814Ssimon} 286