1160814Ssimon/* crypto/ecdh/ech_lib.c */ 2160814Ssimon/* ==================================================================== 3160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 4160814Ssimon * 5160814Ssimon * The Elliptic Curve Public-Key Crypto Library (ECC Code) included 6160814Ssimon * herein is developed by SUN MICROSYSTEMS, INC., and is contributed 7160814Ssimon * to the OpenSSL project. 8160814Ssimon * 9160814Ssimon * The ECC Code is licensed pursuant to the OpenSSL open source 10160814Ssimon * license provided below. 11160814Ssimon * 12160814Ssimon * The ECDH software is originally written by Douglas Stebila of 13160814Ssimon * Sun Microsystems Laboratories. 14160814Ssimon * 15160814Ssimon */ 16160814Ssimon/* ==================================================================== 17160814Ssimon * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 18160814Ssimon * 19160814Ssimon * Redistribution and use in source and binary forms, with or without 20160814Ssimon * modification, are permitted provided that the following conditions 21160814Ssimon * are met: 22160814Ssimon * 23160814Ssimon * 1. Redistributions of source code must retain the above copyright 24160814Ssimon * notice, this list of conditions and the following disclaimer. 25160814Ssimon * 26160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 27160814Ssimon * notice, this list of conditions and the following disclaimer in 28160814Ssimon * the documentation and/or other materials provided with the 29160814Ssimon * distribution. 30160814Ssimon * 31160814Ssimon * 3. All advertising materials mentioning features or use of this 32160814Ssimon * software must display the following acknowledgment: 33160814Ssimon * "This product includes software developed by the OpenSSL Project 34160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 35160814Ssimon * 36160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 37160814Ssimon * endorse or promote products derived from this software without 38160814Ssimon * prior written permission. For written permission, please contact 39160814Ssimon * openssl-core@OpenSSL.org. 40160814Ssimon * 41160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 42160814Ssimon * nor may "OpenSSL" appear in their names without prior written 43160814Ssimon * permission of the OpenSSL Project. 44160814Ssimon * 45160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 46160814Ssimon * acknowledgment: 47160814Ssimon * "This product includes software developed by the OpenSSL Project 48160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 49160814Ssimon * 50160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 51160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 54160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 61160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 62160814Ssimon * ==================================================================== 63160814Ssimon * 64160814Ssimon * This product includes cryptographic software written by Eric Young 65160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 66160814Ssimon * Hudson (tjh@cryptsoft.com). 67160814Ssimon * 68160814Ssimon */ 69160814Ssimon 70160814Ssimon#include "ech_locl.h" 71160814Ssimon#include <string.h> 72160814Ssimon#ifndef OPENSSL_NO_ENGINE 73160814Ssimon#include <openssl/engine.h> 74160814Ssimon#endif 75160814Ssimon#include <openssl/err.h> 76238405Sjkim#ifdef OPENSSL_FIPS 77238405Sjkim#include <openssl/fips.h> 78238405Sjkim#endif 79160814Ssimon 80167612Ssimonconst char ECDH_version[]="ECDH" OPENSSL_VERSION_PTEXT; 81160814Ssimon 82160814Ssimonstatic const ECDH_METHOD *default_ECDH_method = NULL; 83160814Ssimon 84160814Ssimonstatic void *ecdh_data_new(void); 85160814Ssimonstatic void *ecdh_data_dup(void *); 86160814Ssimonstatic void ecdh_data_free(void *); 87160814Ssimon 88160814Ssimonvoid ECDH_set_default_method(const ECDH_METHOD *meth) 89160814Ssimon { 90160814Ssimon default_ECDH_method = meth; 91160814Ssimon } 92160814Ssimon 93160814Ssimonconst ECDH_METHOD *ECDH_get_default_method(void) 94160814Ssimon { 95160814Ssimon if(!default_ECDH_method) 96238405Sjkim { 97238405Sjkim#ifdef OPENSSL_FIPS 98238405Sjkim if (FIPS_mode()) 99238405Sjkim return FIPS_ecdh_openssl(); 100238405Sjkim else 101238405Sjkim return ECDH_OpenSSL(); 102238405Sjkim#else 103160814Ssimon default_ECDH_method = ECDH_OpenSSL(); 104238405Sjkim#endif 105238405Sjkim } 106160814Ssimon return default_ECDH_method; 107160814Ssimon } 108160814Ssimon 109160814Ssimonint ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth) 110160814Ssimon { 111160814Ssimon ECDH_DATA *ecdh; 112160814Ssimon 113160814Ssimon ecdh = ecdh_check(eckey); 114160814Ssimon 115160814Ssimon if (ecdh == NULL) 116160814Ssimon return 0; 117160814Ssimon 118238405Sjkim#if 0 119238405Sjkim mtmp = ecdh->meth; 120238405Sjkim if (mtmp->finish) 121238405Sjkim mtmp->finish(eckey); 122238405Sjkim#endif 123160814Ssimon#ifndef OPENSSL_NO_ENGINE 124160814Ssimon if (ecdh->engine) 125160814Ssimon { 126160814Ssimon ENGINE_finish(ecdh->engine); 127160814Ssimon ecdh->engine = NULL; 128160814Ssimon } 129160814Ssimon#endif 130160814Ssimon ecdh->meth = meth; 131160814Ssimon#if 0 132160814Ssimon if (meth->init) 133160814Ssimon meth->init(eckey); 134160814Ssimon#endif 135160814Ssimon return 1; 136160814Ssimon } 137160814Ssimon 138160814Ssimonstatic ECDH_DATA *ECDH_DATA_new_method(ENGINE *engine) 139160814Ssimon { 140160814Ssimon ECDH_DATA *ret; 141160814Ssimon 142160814Ssimon ret=(ECDH_DATA *)OPENSSL_malloc(sizeof(ECDH_DATA)); 143160814Ssimon if (ret == NULL) 144160814Ssimon { 145160814Ssimon ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE); 146160814Ssimon return(NULL); 147160814Ssimon } 148160814Ssimon 149160814Ssimon ret->init = NULL; 150160814Ssimon 151160814Ssimon ret->meth = ECDH_get_default_method(); 152160814Ssimon ret->engine = engine; 153160814Ssimon#ifndef OPENSSL_NO_ENGINE 154160814Ssimon if (!ret->engine) 155160814Ssimon ret->engine = ENGINE_get_default_ECDH(); 156160814Ssimon if (ret->engine) 157160814Ssimon { 158160814Ssimon ret->meth = ENGINE_get_ECDH(ret->engine); 159160814Ssimon if (!ret->meth) 160160814Ssimon { 161160814Ssimon ECDHerr(ECDH_F_ECDH_DATA_NEW_METHOD, ERR_R_ENGINE_LIB); 162160814Ssimon ENGINE_finish(ret->engine); 163160814Ssimon OPENSSL_free(ret); 164160814Ssimon return NULL; 165160814Ssimon } 166160814Ssimon } 167160814Ssimon#endif 168160814Ssimon 169160814Ssimon ret->flags = ret->meth->flags; 170160814Ssimon CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data); 171160814Ssimon#if 0 172160814Ssimon if ((ret->meth->init != NULL) && !ret->meth->init(ret)) 173160814Ssimon { 174160814Ssimon CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data); 175160814Ssimon OPENSSL_free(ret); 176160814Ssimon ret=NULL; 177160814Ssimon } 178160814Ssimon#endif 179160814Ssimon return(ret); 180160814Ssimon } 181160814Ssimon 182160814Ssimonstatic void *ecdh_data_new(void) 183160814Ssimon { 184160814Ssimon return (void *)ECDH_DATA_new_method(NULL); 185160814Ssimon } 186160814Ssimon 187160814Ssimonstatic void *ecdh_data_dup(void *data) 188160814Ssimon{ 189160814Ssimon ECDH_DATA *r = (ECDH_DATA *)data; 190160814Ssimon 191160814Ssimon /* XXX: dummy operation */ 192160814Ssimon if (r == NULL) 193160814Ssimon return NULL; 194160814Ssimon 195160814Ssimon return (void *)ecdh_data_new(); 196160814Ssimon} 197160814Ssimon 198160814Ssimonvoid ecdh_data_free(void *data) 199160814Ssimon { 200160814Ssimon ECDH_DATA *r = (ECDH_DATA *)data; 201160814Ssimon 202160814Ssimon#ifndef OPENSSL_NO_ENGINE 203160814Ssimon if (r->engine) 204160814Ssimon ENGINE_finish(r->engine); 205160814Ssimon#endif 206160814Ssimon 207160814Ssimon CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, r, &r->ex_data); 208160814Ssimon 209160814Ssimon OPENSSL_cleanse((void *)r, sizeof(ECDH_DATA)); 210160814Ssimon 211160814Ssimon OPENSSL_free(r); 212160814Ssimon } 213160814Ssimon 214160814SsimonECDH_DATA *ecdh_check(EC_KEY *key) 215160814Ssimon { 216160814Ssimon ECDH_DATA *ecdh_data; 217160814Ssimon 218160814Ssimon void *data = EC_KEY_get_key_method_data(key, ecdh_data_dup, 219160814Ssimon ecdh_data_free, ecdh_data_free); 220160814Ssimon if (data == NULL) 221160814Ssimon { 222160814Ssimon ecdh_data = (ECDH_DATA *)ecdh_data_new(); 223160814Ssimon if (ecdh_data == NULL) 224160814Ssimon return NULL; 225246772Sjkim data = EC_KEY_insert_key_method_data(key, (void *)ecdh_data, 226246772Sjkim ecdh_data_dup, ecdh_data_free, ecdh_data_free); 227246772Sjkim if (data != NULL) 228246772Sjkim { 229246772Sjkim /* Another thread raced us to install the key_method 230246772Sjkim * data and won. */ 231246772Sjkim ecdh_data_free(ecdh_data); 232246772Sjkim ecdh_data = (ECDH_DATA *)data; 233246772Sjkim } 234160814Ssimon } 235160814Ssimon else 236160814Ssimon ecdh_data = (ECDH_DATA *)data; 237238405Sjkim#ifdef OPENSSL_FIPS 238238405Sjkim if (FIPS_mode() && !(ecdh_data->flags & ECDH_FLAG_FIPS_METHOD) 239238405Sjkim && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW)) 240238405Sjkim { 241238405Sjkim ECDHerr(ECDH_F_ECDH_CHECK, ECDH_R_NON_FIPS_METHOD); 242238405Sjkim return NULL; 243238405Sjkim } 244238405Sjkim#endif 245160814Ssimon 246160814Ssimon 247160814Ssimon return ecdh_data; 248160814Ssimon } 249160814Ssimon 250160814Ssimonint ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 251160814Ssimon CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 252160814Ssimon { 253160814Ssimon return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDH, argl, argp, 254160814Ssimon new_func, dup_func, free_func); 255160814Ssimon } 256160814Ssimon 257160814Ssimonint ECDH_set_ex_data(EC_KEY *d, int idx, void *arg) 258160814Ssimon { 259160814Ssimon ECDH_DATA *ecdh; 260160814Ssimon ecdh = ecdh_check(d); 261160814Ssimon if (ecdh == NULL) 262160814Ssimon return 0; 263160814Ssimon return(CRYPTO_set_ex_data(&ecdh->ex_data,idx,arg)); 264160814Ssimon } 265160814Ssimon 266160814Ssimonvoid *ECDH_get_ex_data(EC_KEY *d, int idx) 267160814Ssimon { 268160814Ssimon ECDH_DATA *ecdh; 269160814Ssimon ecdh = ecdh_check(d); 270160814Ssimon if (ecdh == NULL) 271160814Ssimon return NULL; 272160814Ssimon return(CRYPTO_get_ex_data(&ecdh->ex_data,idx)); 273160814Ssimon } 274