1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2 * project 2006. 3 */ 4/* ==================================================================== 5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. All advertising materials mentioning features or use of this 20 * software must display the following acknowledgment: 21 * "This product includes software developed by the OpenSSL Project 22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23 * 24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25 * endorse or promote products derived from this software without 26 * prior written permission. For written permission, please contact 27 * licensing@OpenSSL.org. 28 * 29 * 5. Products derived from this software may not be called "OpenSSL" 30 * nor may "OpenSSL" appear in their names without prior written 31 * permission of the OpenSSL Project. 32 * 33 * 6. Redistributions of any form whatsoever must retain the following 34 * acknowledgment: 35 * "This product includes software developed by the OpenSSL Project 36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49 * OF THE POSSIBILITY OF SUCH DAMAGE. 50 * ==================================================================== 51 * 52 * This product includes cryptographic software written by Eric Young 53 * (eay@cryptsoft.com). This product includes software written by Tim 54 * Hudson (tjh@cryptsoft.com). */ 55 56#include <openssl/evp.h> 57 58#include <openssl/asn1.h> 59#include <openssl/bn.h> 60#include <openssl/buf.h> 61#include <openssl/digest.h> 62#include <openssl/ec.h> 63#include <openssl/ec_key.h> 64#include <openssl/ecdh.h> 65#include <openssl/ecdsa.h> 66#include <openssl/err.h> 67#include <openssl/mem.h> 68#include <openssl/obj.h> 69 70#include "internal.h" 71#include "../ec/internal.h" 72 73 74typedef struct { 75 /* Key and paramgen group */ 76 EC_GROUP *gen_group; 77 /* message digest */ 78 const EVP_MD *md; 79 /* Duplicate key if custom cofactor needed */ 80 EC_KEY *co_key; 81 /* Cofactor mode */ 82 signed char cofactor_mode; 83 /* KDF (if any) to use for ECDH */ 84 char kdf_type; 85 /* Message digest to use for key derivation */ 86 const EVP_MD *kdf_md; 87 /* User key material */ 88 unsigned char *kdf_ukm; 89 size_t kdf_ukmlen; 90 /* KDF output length */ 91 size_t kdf_outlen; 92} EC_PKEY_CTX; 93 94 95static int pkey_ec_init(EVP_PKEY_CTX *ctx) { 96 EC_PKEY_CTX *dctx; 97 dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); 98 if (!dctx) { 99 return 0; 100 } 101 memset(dctx, 0, sizeof(EC_PKEY_CTX)); 102 dctx->cofactor_mode = -1; 103 dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; 104 105 ctx->data = dctx; 106 107 return 1; 108} 109 110static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { 111 EC_PKEY_CTX *dctx, *sctx; 112 if (!pkey_ec_init(dst)) { 113 return 0; 114 } 115 sctx = src->data; 116 dctx = dst->data; 117 118 if (sctx->gen_group) { 119 dctx->gen_group = EC_GROUP_dup(sctx->gen_group); 120 if (!dctx->gen_group) { 121 return 0; 122 } 123 } 124 dctx->md = sctx->md; 125 126 if (sctx->co_key) { 127 dctx->co_key = EC_KEY_dup(sctx->co_key); 128 if (!dctx->co_key) { 129 return 0; 130 } 131 } 132 dctx->kdf_type = sctx->kdf_type; 133 dctx->kdf_md = sctx->kdf_md; 134 dctx->kdf_outlen = sctx->kdf_outlen; 135 if (sctx->kdf_ukm) { 136 dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); 137 if (!dctx->kdf_ukm) { 138 return 0; 139 } 140 } else { 141 dctx->kdf_ukm = NULL; 142 } 143 dctx->kdf_ukmlen = sctx->kdf_ukmlen; 144 return 1; 145} 146 147static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { 148 EC_PKEY_CTX *dctx = ctx->data; 149 if (!dctx) { 150 return; 151 } 152 153 if (dctx->gen_group) { 154 EC_GROUP_free(dctx->gen_group); 155 } 156 if (dctx->co_key) { 157 EC_KEY_free(dctx->co_key); 158 } 159 if (dctx->kdf_ukm) { 160 OPENSSL_free(dctx->kdf_ukm); 161 } 162 OPENSSL_free(dctx); 163} 164 165static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, 166 const uint8_t *tbs, size_t tbslen) { 167 int type; 168 unsigned int sltmp; 169 EC_PKEY_CTX *dctx = ctx->data; 170 EC_KEY *ec = ctx->pkey->pkey.ec; 171 172 if (!sig) { 173 *siglen = ECDSA_size(ec); 174 return 1; 175 } else if (*siglen < (size_t)ECDSA_size(ec)) { 176 OPENSSL_PUT_ERROR(EVP, pkey_ec_sign, EVP_R_BUFFER_TOO_SMALL); 177 return 0; 178 } 179 180 type = NID_sha1; 181 if (dctx->md) { 182 type = EVP_MD_type(dctx->md); 183 } 184 185 if (!ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec)) { 186 return 0; 187 } 188 *siglen = (size_t)sltmp; 189 return 1; 190} 191 192static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, 193 const uint8_t *tbs, size_t tbslen) { 194 int type; 195 EC_PKEY_CTX *dctx = ctx->data; 196 EC_KEY *ec = ctx->pkey->pkey.ec; 197 198 type = NID_sha1; 199 if (dctx->md) { 200 type = EVP_MD_type(dctx->md); 201 } 202 203 return ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); 204} 205 206static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key, 207 size_t *keylen) { 208 int ret; 209 size_t outlen; 210 const EC_POINT *pubkey = NULL; 211 EC_KEY *eckey; 212 EC_PKEY_CTX *dctx = ctx->data; 213 214 if (!ctx->pkey || !ctx->peerkey) { 215 OPENSSL_PUT_ERROR(EVP, pkey_ec_derive, EVP_R_KEYS_NOT_SET); 216 return 0; 217 } 218 219 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; 220 221 if (!key) { 222 const EC_GROUP *group; 223 group = EC_KEY_get0_group(eckey); 224 *keylen = (EC_GROUP_get_degree(group) + 7) / 8; 225 return 1; 226 } 227 pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); 228 229 /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is 230 * not an error, the result is truncated. */ 231 232 outlen = *keylen; 233 234 ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); 235 if (ret < 0) { 236 return 0; 237 } 238 *keylen = ret; 239 return 1; 240} 241 242static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, uint8_t *key, 243 size_t *keylen) { 244 EC_PKEY_CTX *dctx = ctx->data; 245 uint8_t *ktmp = NULL; 246 size_t ktmplen; 247 int rv = 0; 248 249 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) { 250 return pkey_ec_derive(ctx, key, keylen); 251 } 252 if (!key) { 253 *keylen = dctx->kdf_outlen; 254 return 1; 255 } 256 if (*keylen != dctx->kdf_outlen || 257 !pkey_ec_derive(ctx, NULL, &ktmplen)) { 258 return 0; 259 } 260 ktmp = OPENSSL_malloc(ktmplen); 261 if (!ktmp) { 262 return 0; 263 } 264 if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) { 265 goto err; 266 } 267 268 if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm, 269 dctx->kdf_ukmlen, dctx->kdf_md)) { 270 goto err; 271 } 272 rv = 1; 273 274err: 275 if (ktmp) { 276 OPENSSL_cleanse(ktmp, ktmplen); 277 OPENSSL_free(ktmp); 278 } 279 return rv; 280} 281 282static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { 283 EC_PKEY_CTX *dctx = ctx->data; 284 EC_GROUP *group; 285 286 switch (type) { 287 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 288 group = EC_GROUP_new_by_curve_name(p1); 289 if (group == NULL) { 290 OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_CURVE); 291 return 0; 292 } 293 if (dctx->gen_group) 294 EC_GROUP_free(dctx->gen_group); 295 dctx->gen_group = group; 296 return 1; 297 298 case EVP_PKEY_CTRL_EC_KDF_TYPE: 299 if (p1 == -2) 300 return dctx->kdf_type; 301 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) 302 return -2; 303 dctx->kdf_type = p1; 304 return 1; 305 306 case EVP_PKEY_CTRL_EC_KDF_MD: 307 dctx->kdf_md = p2; 308 return 1; 309 310 case EVP_PKEY_CTRL_GET_EC_KDF_MD: 311 *(const EVP_MD **)p2 = dctx->kdf_md; 312 return 1; 313 314 case EVP_PKEY_CTRL_EC_KDF_OUTLEN: 315 if (p1 <= 0) 316 return -2; 317 dctx->kdf_outlen = (size_t)p1; 318 return 1; 319 320 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: 321 *(int *)p2 = dctx->kdf_outlen; 322 return 1; 323 324 case EVP_PKEY_CTRL_EC_KDF_UKM: 325 if (dctx->kdf_ukm) 326 OPENSSL_free(dctx->kdf_ukm); 327 dctx->kdf_ukm = p2; 328 if (p2) 329 dctx->kdf_ukmlen = p1; 330 else 331 dctx->kdf_ukmlen = 0; 332 return 1; 333 334 case EVP_PKEY_CTRL_GET_EC_KDF_UKM: 335 *(unsigned char **)p2 = dctx->kdf_ukm; 336 return dctx->kdf_ukmlen; 337 338 case EVP_PKEY_CTRL_MD: 339 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 340 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && 341 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 342 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 343 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 344 EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 345 OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_DIGEST_TYPE); 346 return 0; 347 } 348 dctx->md = p2; 349 return 1; 350 351 case EVP_PKEY_CTRL_GET_MD: 352 *(const EVP_MD **)p2 = dctx->md; 353 return 1; 354 355 case EVP_PKEY_CTRL_PEER_KEY: 356 /* Default behaviour is OK */ 357 case EVP_PKEY_CTRL_DIGESTINIT: 358 return 1; 359 360 default: 361 return -2; 362 } 363} 364 365static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { 366 EC_KEY *ec = NULL; 367 EC_PKEY_CTX *dctx = ctx->data; 368 int ret = 0; 369 370 if (dctx->gen_group == NULL) { 371 OPENSSL_PUT_ERROR(EVP, pkey_ec_paramgen, EVP_R_NO_PARAMETERS_SET); 372 return 0; 373 } 374 ec = EC_KEY_new(); 375 if (!ec) { 376 return 0; 377 } 378 ret = EC_KEY_set_group(ec, dctx->gen_group); 379 if (ret) { 380 EVP_PKEY_assign_EC_KEY(pkey, ec); 381 } else { 382 EC_KEY_free(ec); 383 } 384 return ret; 385} 386 387static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { 388 EC_KEY *ec = NULL; 389 EC_PKEY_CTX *dctx = ctx->data; 390 if (ctx->pkey == NULL && dctx->gen_group == NULL) { 391 OPENSSL_PUT_ERROR(EVP, pkey_ec_keygen, EVP_R_NO_PARAMETERS_SET); 392 return 0; 393 } 394 ec = EC_KEY_new(); 395 if (!ec) { 396 return 0; 397 } 398 EVP_PKEY_assign_EC_KEY(pkey, ec); 399 if (ctx->pkey) { 400 /* Note: if error return, pkey is freed by parent routine */ 401 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) { 402 return 0; 403 } 404 } else { 405 if (!EC_KEY_set_group(ec, dctx->gen_group)) { 406 return 0; 407 } 408 } 409 return EC_KEY_generate_key(pkey->pkey.ec); 410} 411 412const EVP_PKEY_METHOD ec_pkey_meth = { 413 EVP_PKEY_EC, 0 /* flags */, pkey_ec_init, 414 pkey_ec_copy, pkey_ec_cleanup, 0 /* paramgen_init */, 415 pkey_ec_paramgen, 0 /* keygen_init */, pkey_ec_keygen, 416 0 /* sign_init */, pkey_ec_sign, 0 /* verify_init */, 417 pkey_ec_verify, 0 /* signctx_init */, 0 /* signctx */, 418 0 /* verifyctx_init */, 0 /* verifyctx */, 0 /* encrypt_init */, 419 0 /* encrypt */, 0 /* decrypt_init */, 0 /* decrypt */, 420 0 /* derive_init */, pkey_ec_kdf_derive, pkey_ec_ctrl, 421}; 422