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_lcl.h" 15 16 17 static 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 30 static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method; 31 32 const EC_KEY_METHOD *EC_KEY_OpenSSL(void) 33 { 34 return &openssl_ec_key_method; 35 } 36 37 const EC_KEY_METHOD *EC_KEY_get_default_method(void) 38 { 39 return default_ec_key_meth; 40 } 41 42 void 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 50 const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key) 51 { 52 return key->meth; 53 } 54 55 int 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 73 EC_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 127 int 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 155 EC_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 167 void EC_KEY_METHOD_free(EC_KEY_METHOD *meth) 168 { 169 if (meth->flags & EC_KEY_METHOD_DYNAMIC) 170 OPENSSL_free(meth); 171 } 172 173 void 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 191 void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, 192 int (*keygen)(EC_KEY *key)) 193 { 194 meth->keygen = keygen; 195 } 196 197 void 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 206 void 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 225 void 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 239 void 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 264 void 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 271 void 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 281 void 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 303 void 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