1/* 2 * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <string.h> 11#include <openssl/ec.h> 12#include <openssl/engine.h> 13#include <openssl/err.h> 14#include "ec_local.h" 15 16 17static const EC_KEY_METHOD openssl_ec_key_method = { 18 "OpenSSL EC_KEY method", 19 0, 20 0,0,0,0,0,0, 21 ossl_ec_key_gen, 22 ossl_ecdh_compute_key, 23 ossl_ecdsa_sign, 24 ossl_ecdsa_sign_setup, 25 ossl_ecdsa_sign_sig, 26 ossl_ecdsa_verify, 27 ossl_ecdsa_verify_sig 28}; 29 30static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method; 31 32const EC_KEY_METHOD *EC_KEY_OpenSSL(void) 33{ 34 return &openssl_ec_key_method; 35} 36 37const EC_KEY_METHOD *EC_KEY_get_default_method(void) 38{ 39 return default_ec_key_meth; 40} 41 42void EC_KEY_set_default_method(const EC_KEY_METHOD *meth) 43{ 44 if (meth == NULL) 45 default_ec_key_meth = &openssl_ec_key_method; 46 else 47 default_ec_key_meth = meth; 48} 49 50const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key) 51{ 52 return key->meth; 53} 54 55int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) 56{ 57 void (*finish)(EC_KEY *key) = key->meth->finish; 58 59 if (finish != NULL) 60 finish(key); 61 62#ifndef OPENSSL_NO_ENGINE 63 ENGINE_finish(key->engine); 64 key->engine = NULL; 65#endif 66 67 key->meth = meth; 68 if (meth->init != NULL) 69 return meth->init(key); 70 return 1; 71} 72 73EC_KEY *EC_KEY_new_method(ENGINE *engine) 74{ 75 EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); 76 77 if (ret == NULL) { 78 ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); 79 return NULL; 80 } 81 82 ret->references = 1; 83 ret->lock = CRYPTO_THREAD_lock_new(); 84 if (ret->lock == NULL) { 85 ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); 86 OPENSSL_free(ret); 87 return NULL; 88 } 89 90 ret->meth = EC_KEY_get_default_method(); 91#ifndef OPENSSL_NO_ENGINE 92 if (engine != NULL) { 93 if (!ENGINE_init(engine)) { 94 ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); 95 goto err; 96 } 97 ret->engine = engine; 98 } else 99 ret->engine = ENGINE_get_default_EC(); 100 if (ret->engine != NULL) { 101 ret->meth = ENGINE_get_EC(ret->engine); 102 if (ret->meth == NULL) { 103 ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); 104 goto err; 105 } 106 } 107#endif 108 109 ret->version = 1; 110 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 111 112 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { 113 goto err; 114 } 115 116 if (ret->meth->init != NULL && ret->meth->init(ret) == 0) { 117 ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL); 118 goto err; 119 } 120 return ret; 121 122 err: 123 EC_KEY_free(ret); 124 return NULL; 125} 126 127int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, 128 const EC_KEY *eckey, 129 void *(*KDF) (const void *in, size_t inlen, void *out, 130 size_t *outlen)) 131{ 132 unsigned char *sec = NULL; 133 size_t seclen; 134 if (eckey->meth->compute_key == NULL) { 135 ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED); 136 return 0; 137 } 138 if (outlen > INT_MAX) { 139 ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH); 140 return 0; 141 } 142 if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey)) 143 return 0; 144 if (KDF != NULL) { 145 KDF(sec, seclen, out, &outlen); 146 } else { 147 if (outlen > seclen) 148 outlen = seclen; 149 memcpy(out, sec, outlen); 150 } 151 OPENSSL_clear_free(sec, seclen); 152 return outlen; 153} 154 155EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth) 156{ 157 EC_KEY_METHOD *ret = OPENSSL_zalloc(sizeof(*meth)); 158 159 if (ret == NULL) 160 return NULL; 161 if (meth != NULL) 162 *ret = *meth; 163 ret->flags |= EC_KEY_METHOD_DYNAMIC; 164 return ret; 165} 166 167void EC_KEY_METHOD_free(EC_KEY_METHOD *meth) 168{ 169 if (meth->flags & EC_KEY_METHOD_DYNAMIC) 170 OPENSSL_free(meth); 171} 172 173void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, 174 int (*init)(EC_KEY *key), 175 void (*finish)(EC_KEY *key), 176 int (*copy)(EC_KEY *dest, const EC_KEY *src), 177 int (*set_group)(EC_KEY *key, const EC_GROUP *grp), 178 int (*set_private)(EC_KEY *key, 179 const BIGNUM *priv_key), 180 int (*set_public)(EC_KEY *key, 181 const EC_POINT *pub_key)) 182{ 183 meth->init = init; 184 meth->finish = finish; 185 meth->copy = copy; 186 meth->set_group = set_group; 187 meth->set_private = set_private; 188 meth->set_public = set_public; 189} 190 191void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, 192 int (*keygen)(EC_KEY *key)) 193{ 194 meth->keygen = keygen; 195} 196 197void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, 198 int (*ckey)(unsigned char **psec, 199 size_t *pseclen, 200 const EC_POINT *pub_key, 201 const EC_KEY *ecdh)) 202{ 203 meth->compute_key = ckey; 204} 205 206void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, 207 int (*sign)(int type, const unsigned char *dgst, 208 int dlen, unsigned char *sig, 209 unsigned int *siglen, 210 const BIGNUM *kinv, const BIGNUM *r, 211 EC_KEY *eckey), 212 int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, 213 BIGNUM **kinvp, BIGNUM **rp), 214 ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, 215 int dgst_len, 216 const BIGNUM *in_kinv, 217 const BIGNUM *in_r, 218 EC_KEY *eckey)) 219{ 220 meth->sign = sign; 221 meth->sign_setup = sign_setup; 222 meth->sign_sig = sign_sig; 223} 224 225void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, 226 int (*verify)(int type, const unsigned 227 char *dgst, int dgst_len, 228 const unsigned char *sigbuf, 229 int sig_len, EC_KEY *eckey), 230 int (*verify_sig)(const unsigned char *dgst, 231 int dgst_len, 232 const ECDSA_SIG *sig, 233 EC_KEY *eckey)) 234{ 235 meth->verify = verify; 236 meth->verify_sig = verify_sig; 237} 238 239void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, 240 int (**pinit)(EC_KEY *key), 241 void (**pfinish)(EC_KEY *key), 242 int (**pcopy)(EC_KEY *dest, const EC_KEY *src), 243 int (**pset_group)(EC_KEY *key, 244 const EC_GROUP *grp), 245 int (**pset_private)(EC_KEY *key, 246 const BIGNUM *priv_key), 247 int (**pset_public)(EC_KEY *key, 248 const EC_POINT *pub_key)) 249{ 250 if (pinit != NULL) 251 *pinit = meth->init; 252 if (pfinish != NULL) 253 *pfinish = meth->finish; 254 if (pcopy != NULL) 255 *pcopy = meth->copy; 256 if (pset_group != NULL) 257 *pset_group = meth->set_group; 258 if (pset_private != NULL) 259 *pset_private = meth->set_private; 260 if (pset_public != NULL) 261 *pset_public = meth->set_public; 262} 263 264void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, 265 int (**pkeygen)(EC_KEY *key)) 266{ 267 if (pkeygen != NULL) 268 *pkeygen = meth->keygen; 269} 270 271void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, 272 int (**pck)(unsigned char **pout, 273 size_t *poutlen, 274 const EC_POINT *pub_key, 275 const EC_KEY *ecdh)) 276{ 277 if (pck != NULL) 278 *pck = meth->compute_key; 279} 280 281void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, 282 int (**psign)(int type, const unsigned char *dgst, 283 int dlen, unsigned char *sig, 284 unsigned int *siglen, 285 const BIGNUM *kinv, const BIGNUM *r, 286 EC_KEY *eckey), 287 int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, 288 BIGNUM **kinvp, BIGNUM **rp), 289 ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, 290 int dgst_len, 291 const BIGNUM *in_kinv, 292 const BIGNUM *in_r, 293 EC_KEY *eckey)) 294{ 295 if (psign != NULL) 296 *psign = meth->sign; 297 if (psign_setup != NULL) 298 *psign_setup = meth->sign_setup; 299 if (psign_sig != NULL) 300 *psign_sig = meth->sign_sig; 301} 302 303void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, 304 int (**pverify)(int type, const unsigned 305 char *dgst, int dgst_len, 306 const unsigned char *sigbuf, 307 int sig_len, EC_KEY *eckey), 308 int (**pverify_sig)(const unsigned char *dgst, 309 int dgst_len, 310 const ECDSA_SIG *sig, 311 EC_KEY *eckey)) 312{ 313 if (pverify != NULL) 314 *pverify = meth->verify; 315 if (pverify_sig != NULL) 316 *pverify_sig = meth->verify_sig; 317} 318