1238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2238384Sjkim * project 2006. 3238384Sjkim */ 4238384Sjkim/* ==================================================================== 5238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 6238384Sjkim * 7238384Sjkim * Redistribution and use in source and binary forms, with or without 8238384Sjkim * modification, are permitted provided that the following conditions 9238384Sjkim * are met: 10238384Sjkim * 11238384Sjkim * 1. Redistributions of source code must retain the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer. 13238384Sjkim * 14238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 15238384Sjkim * notice, this list of conditions and the following disclaimer in 16238384Sjkim * the documentation and/or other materials provided with the 17238384Sjkim * distribution. 18238384Sjkim * 19238384Sjkim * 3. All advertising materials mentioning features or use of this 20238384Sjkim * software must display the following acknowledgment: 21238384Sjkim * "This product includes software developed by the OpenSSL Project 22238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23238384Sjkim * 24238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25238384Sjkim * endorse or promote products derived from this software without 26238384Sjkim * prior written permission. For written permission, please contact 27238384Sjkim * licensing@OpenSSL.org. 28238384Sjkim * 29238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 30238384Sjkim * nor may "OpenSSL" appear in their names without prior written 31238384Sjkim * permission of the OpenSSL Project. 32238384Sjkim * 33238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 34238384Sjkim * acknowledgment: 35238384Sjkim * "This product includes software developed by the OpenSSL Project 36238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37238384Sjkim * 38238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 50238384Sjkim * ==================================================================== 51238384Sjkim * 52238384Sjkim * This product includes cryptographic software written by Eric Young 53238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 54238384Sjkim * Hudson (tjh@cryptsoft.com). 55238384Sjkim * 56238384Sjkim */ 57238384Sjkim 58238384Sjkim#include <stdio.h> 59238384Sjkim#include "cryptlib.h" 60238384Sjkim#include <openssl/asn1t.h> 61238384Sjkim#include <openssl/x509.h> 62238384Sjkim#include <openssl/ec.h> 63238384Sjkim#include <openssl/ecdsa.h> 64238384Sjkim#include <openssl/evp.h> 65238384Sjkim#include "evp_locl.h" 66238384Sjkim 67238384Sjkim/* EC pkey context structure */ 68238384Sjkim 69238384Sjkimtypedef struct 70238384Sjkim { 71238384Sjkim /* Key and paramgen group */ 72238384Sjkim EC_GROUP *gen_group; 73238384Sjkim /* message digest */ 74238384Sjkim const EVP_MD *md; 75238384Sjkim } EC_PKEY_CTX; 76238384Sjkim 77238384Sjkimstatic int pkey_ec_init(EVP_PKEY_CTX *ctx) 78238384Sjkim { 79238384Sjkim EC_PKEY_CTX *dctx; 80238384Sjkim dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); 81238384Sjkim if (!dctx) 82238384Sjkim return 0; 83238384Sjkim dctx->gen_group = NULL; 84238384Sjkim dctx->md = NULL; 85238384Sjkim 86238384Sjkim ctx->data = dctx; 87238384Sjkim 88238384Sjkim return 1; 89238384Sjkim } 90238384Sjkim 91238384Sjkimstatic int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 92238384Sjkim { 93238384Sjkim EC_PKEY_CTX *dctx, *sctx; 94238384Sjkim if (!pkey_ec_init(dst)) 95238384Sjkim return 0; 96238384Sjkim sctx = src->data; 97238384Sjkim dctx = dst->data; 98238384Sjkim if (sctx->gen_group) 99238384Sjkim { 100238384Sjkim dctx->gen_group = EC_GROUP_dup(sctx->gen_group); 101238384Sjkim if (!dctx->gen_group) 102238384Sjkim return 0; 103238384Sjkim } 104238384Sjkim dctx->md = sctx->md; 105238384Sjkim return 1; 106238384Sjkim } 107238384Sjkim 108238384Sjkimstatic void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) 109238384Sjkim { 110238384Sjkim EC_PKEY_CTX *dctx = ctx->data; 111238384Sjkim if (dctx) 112238384Sjkim { 113238384Sjkim if (dctx->gen_group) 114238384Sjkim EC_GROUP_free(dctx->gen_group); 115238384Sjkim OPENSSL_free(dctx); 116238384Sjkim } 117238384Sjkim } 118238384Sjkim 119238384Sjkimstatic int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 120238384Sjkim const unsigned char *tbs, size_t tbslen) 121238384Sjkim { 122238384Sjkim int ret, type; 123238384Sjkim unsigned int sltmp; 124238384Sjkim EC_PKEY_CTX *dctx = ctx->data; 125238384Sjkim EC_KEY *ec = ctx->pkey->pkey.ec; 126238384Sjkim 127238384Sjkim if (!sig) 128238384Sjkim { 129238384Sjkim *siglen = ECDSA_size(ec); 130238384Sjkim return 1; 131238384Sjkim } 132238384Sjkim else if(*siglen < (size_t)ECDSA_size(ec)) 133238384Sjkim { 134238384Sjkim ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); 135238384Sjkim return 0; 136238384Sjkim } 137238384Sjkim 138238384Sjkim if (dctx->md) 139238384Sjkim type = EVP_MD_type(dctx->md); 140238384Sjkim else 141238384Sjkim type = NID_sha1; 142238384Sjkim 143238384Sjkim 144238384Sjkim ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); 145238384Sjkim 146238384Sjkim if (ret <= 0) 147238384Sjkim return ret; 148238384Sjkim *siglen = (size_t)sltmp; 149238384Sjkim return 1; 150238384Sjkim } 151238384Sjkim 152238384Sjkimstatic int pkey_ec_verify(EVP_PKEY_CTX *ctx, 153238384Sjkim const unsigned char *sig, size_t siglen, 154238384Sjkim const unsigned char *tbs, size_t tbslen) 155238384Sjkim { 156238384Sjkim int ret, type; 157238384Sjkim EC_PKEY_CTX *dctx = ctx->data; 158238384Sjkim EC_KEY *ec = ctx->pkey->pkey.ec; 159238384Sjkim 160238384Sjkim if (dctx->md) 161238384Sjkim type = EVP_MD_type(dctx->md); 162238384Sjkim else 163238384Sjkim type = NID_sha1; 164238384Sjkim 165238384Sjkim ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); 166238384Sjkim 167238384Sjkim return ret; 168238384Sjkim } 169238384Sjkim 170279264Sdelphij#ifndef OPENSSL_NO_ECDH 171238384Sjkimstatic int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) 172238384Sjkim { 173238384Sjkim int ret; 174238384Sjkim size_t outlen; 175238384Sjkim const EC_POINT *pubkey = NULL; 176238384Sjkim if (!ctx->pkey || !ctx->peerkey) 177238384Sjkim { 178238384Sjkim ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); 179238384Sjkim return 0; 180238384Sjkim } 181238384Sjkim 182238384Sjkim if (!key) 183238384Sjkim { 184238384Sjkim const EC_GROUP *group; 185238384Sjkim group = EC_KEY_get0_group(ctx->pkey->pkey.ec); 186238384Sjkim *keylen = (EC_GROUP_get_degree(group) + 7)/8; 187238384Sjkim return 1; 188238384Sjkim } 189238384Sjkim 190238384Sjkim pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); 191238384Sjkim 192246772Sjkim /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is 193238384Sjkim * not an error, the result is truncated. 194238384Sjkim */ 195238384Sjkim 196238384Sjkim outlen = *keylen; 197238384Sjkim 198238384Sjkim ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); 199238384Sjkim if (ret < 0) 200238384Sjkim return ret; 201238384Sjkim *keylen = ret; 202238384Sjkim return 1; 203238384Sjkim } 204279264Sdelphij#endif 205238384Sjkim 206238384Sjkimstatic int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 207238384Sjkim { 208238384Sjkim EC_PKEY_CTX *dctx = ctx->data; 209238384Sjkim EC_GROUP *group; 210238384Sjkim switch (type) 211238384Sjkim { 212238384Sjkim case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 213238384Sjkim group = EC_GROUP_new_by_curve_name(p1); 214238384Sjkim if (group == NULL) 215238384Sjkim { 216238384Sjkim ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); 217238384Sjkim return 0; 218238384Sjkim } 219238384Sjkim if (dctx->gen_group) 220238384Sjkim EC_GROUP_free(dctx->gen_group); 221238384Sjkim dctx->gen_group = group; 222238384Sjkim return 1; 223238384Sjkim 224238384Sjkim case EVP_PKEY_CTRL_MD: 225238384Sjkim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 226238384Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && 227238384Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 228238384Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 229238384Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 230238384Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha512) 231238384Sjkim { 232238384Sjkim ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); 233238384Sjkim return 0; 234238384Sjkim } 235238384Sjkim dctx->md = p2; 236238384Sjkim return 1; 237238384Sjkim 238238384Sjkim case EVP_PKEY_CTRL_PEER_KEY: 239238384Sjkim /* Default behaviour is OK */ 240238384Sjkim case EVP_PKEY_CTRL_DIGESTINIT: 241238384Sjkim case EVP_PKEY_CTRL_PKCS7_SIGN: 242238384Sjkim case EVP_PKEY_CTRL_CMS_SIGN: 243238384Sjkim return 1; 244238384Sjkim 245238384Sjkim default: 246238384Sjkim return -2; 247238384Sjkim 248238384Sjkim } 249238384Sjkim } 250238384Sjkim 251238384Sjkimstatic int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, 252238384Sjkim const char *type, const char *value) 253238384Sjkim { 254238384Sjkim if (!strcmp(type, "ec_paramgen_curve")) 255238384Sjkim { 256238384Sjkim int nid; 257238384Sjkim nid = OBJ_sn2nid(value); 258238384Sjkim if (nid == NID_undef) 259238384Sjkim nid = OBJ_ln2nid(value); 260238384Sjkim if (nid == NID_undef) 261238384Sjkim { 262238384Sjkim ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); 263238384Sjkim return 0; 264238384Sjkim } 265238384Sjkim return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); 266238384Sjkim } 267238384Sjkim return -2; 268238384Sjkim } 269238384Sjkim 270238384Sjkimstatic int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 271238384Sjkim { 272238384Sjkim EC_KEY *ec = NULL; 273238384Sjkim EC_PKEY_CTX *dctx = ctx->data; 274238384Sjkim int ret = 0; 275238384Sjkim if (dctx->gen_group == NULL) 276238384Sjkim { 277238384Sjkim ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); 278238384Sjkim return 0; 279238384Sjkim } 280238384Sjkim ec = EC_KEY_new(); 281238384Sjkim if (!ec) 282238384Sjkim return 0; 283238384Sjkim ret = EC_KEY_set_group(ec, dctx->gen_group); 284238384Sjkim if (ret) 285238384Sjkim EVP_PKEY_assign_EC_KEY(pkey, ec); 286238384Sjkim else 287238384Sjkim EC_KEY_free(ec); 288238384Sjkim return ret; 289238384Sjkim } 290238384Sjkim 291238384Sjkimstatic int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 292238384Sjkim { 293238384Sjkim EC_KEY *ec = NULL; 294238384Sjkim if (ctx->pkey == NULL) 295238384Sjkim { 296238384Sjkim ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); 297238384Sjkim return 0; 298238384Sjkim } 299238384Sjkim ec = EC_KEY_new(); 300238384Sjkim if (!ec) 301238384Sjkim return 0; 302238384Sjkim EVP_PKEY_assign_EC_KEY(pkey, ec); 303238384Sjkim /* Note: if error return, pkey is freed by parent routine */ 304238384Sjkim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 305238384Sjkim return 0; 306238384Sjkim return EC_KEY_generate_key(pkey->pkey.ec); 307238384Sjkim } 308238384Sjkim 309238384Sjkimconst EVP_PKEY_METHOD ec_pkey_meth = 310238384Sjkim { 311238384Sjkim EVP_PKEY_EC, 312238384Sjkim 0, 313238384Sjkim pkey_ec_init, 314238384Sjkim pkey_ec_copy, 315238384Sjkim pkey_ec_cleanup, 316238384Sjkim 317238384Sjkim 0, 318238384Sjkim pkey_ec_paramgen, 319238384Sjkim 320238384Sjkim 0, 321238384Sjkim pkey_ec_keygen, 322238384Sjkim 323238384Sjkim 0, 324238384Sjkim pkey_ec_sign, 325238384Sjkim 326238384Sjkim 0, 327238384Sjkim pkey_ec_verify, 328238384Sjkim 329238384Sjkim 0,0, 330238384Sjkim 331238384Sjkim 0,0,0,0, 332238384Sjkim 333238384Sjkim 0,0, 334238384Sjkim 335238384Sjkim 0,0, 336238384Sjkim 337238384Sjkim 0, 338279264Sdelphij#ifndef OPENSSL_NO_ECDH 339238384Sjkim pkey_ec_derive, 340279264Sdelphij#else 341279264Sdelphij 0, 342279264Sdelphij#endif 343238384Sjkim 344238384Sjkim pkey_ec_ctrl, 345238384Sjkim pkey_ec_ctrl_str 346238384Sjkim 347238384Sjkim }; 348