1280304Sjkim/* 2280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3280304Sjkim * 2006. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13280304Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * licensing@OpenSSL.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim * 53238384Sjkim * This product includes cryptographic software written by Eric Young 54238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 55238384Sjkim * Hudson (tjh@cryptsoft.com). 56238384Sjkim * 57238384Sjkim */ 58238384Sjkim 59238384Sjkim#include <stdio.h> 60238384Sjkim#include "cryptlib.h" 61238384Sjkim#include <openssl/asn1t.h> 62238384Sjkim#include <openssl/x509.h> 63238384Sjkim#include <openssl/ec.h> 64238384Sjkim#include <openssl/ecdsa.h> 65238384Sjkim#include <openssl/evp.h> 66238384Sjkim#include "evp_locl.h" 67238384Sjkim 68238384Sjkim/* EC pkey context structure */ 69238384Sjkim 70280304Sjkimtypedef struct { 71280304Sjkim /* Key and paramgen group */ 72280304Sjkim EC_GROUP *gen_group; 73280304Sjkim /* message digest */ 74280304Sjkim const EVP_MD *md; 75280304Sjkim} EC_PKEY_CTX; 76238384Sjkim 77238384Sjkimstatic int pkey_ec_init(EVP_PKEY_CTX *ctx) 78280304Sjkim{ 79280304Sjkim EC_PKEY_CTX *dctx; 80280304Sjkim dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); 81280304Sjkim if (!dctx) 82280304Sjkim return 0; 83280304Sjkim dctx->gen_group = NULL; 84280304Sjkim dctx->md = NULL; 85238384Sjkim 86280304Sjkim ctx->data = dctx; 87238384Sjkim 88280304Sjkim return 1; 89280304Sjkim} 90238384Sjkim 91238384Sjkimstatic int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 92280304Sjkim{ 93280304Sjkim EC_PKEY_CTX *dctx, *sctx; 94280304Sjkim if (!pkey_ec_init(dst)) 95280304Sjkim return 0; 96280304Sjkim sctx = src->data; 97280304Sjkim dctx = dst->data; 98280304Sjkim if (sctx->gen_group) { 99280304Sjkim dctx->gen_group = EC_GROUP_dup(sctx->gen_group); 100280304Sjkim if (!dctx->gen_group) 101280304Sjkim return 0; 102280304Sjkim } 103280304Sjkim dctx->md = sctx->md; 104280304Sjkim return 1; 105280304Sjkim} 106238384Sjkim 107238384Sjkimstatic void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) 108280304Sjkim{ 109280304Sjkim EC_PKEY_CTX *dctx = ctx->data; 110280304Sjkim if (dctx) { 111280304Sjkim if (dctx->gen_group) 112280304Sjkim EC_GROUP_free(dctx->gen_group); 113280304Sjkim OPENSSL_free(dctx); 114280304Sjkim } 115280304Sjkim} 116238384Sjkim 117238384Sjkimstatic int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 118280304Sjkim const unsigned char *tbs, size_t tbslen) 119280304Sjkim{ 120280304Sjkim int ret, type; 121280304Sjkim unsigned int sltmp; 122280304Sjkim EC_PKEY_CTX *dctx = ctx->data; 123280304Sjkim EC_KEY *ec = ctx->pkey->pkey.ec; 124238384Sjkim 125280304Sjkim if (!sig) { 126280304Sjkim *siglen = ECDSA_size(ec); 127280304Sjkim return 1; 128280304Sjkim } else if (*siglen < (size_t)ECDSA_size(ec)) { 129280304Sjkim ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); 130280304Sjkim return 0; 131280304Sjkim } 132238384Sjkim 133280304Sjkim if (dctx->md) 134280304Sjkim type = EVP_MD_type(dctx->md); 135280304Sjkim else 136280304Sjkim type = NID_sha1; 137238384Sjkim 138280304Sjkim ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); 139238384Sjkim 140280304Sjkim if (ret <= 0) 141280304Sjkim return ret; 142280304Sjkim *siglen = (size_t)sltmp; 143280304Sjkim return 1; 144280304Sjkim} 145238384Sjkim 146238384Sjkimstatic int pkey_ec_verify(EVP_PKEY_CTX *ctx, 147280304Sjkim const unsigned char *sig, size_t siglen, 148280304Sjkim const unsigned char *tbs, size_t tbslen) 149280304Sjkim{ 150280304Sjkim int ret, type; 151280304Sjkim EC_PKEY_CTX *dctx = ctx->data; 152280304Sjkim EC_KEY *ec = ctx->pkey->pkey.ec; 153238384Sjkim 154280304Sjkim if (dctx->md) 155280304Sjkim type = EVP_MD_type(dctx->md); 156280304Sjkim else 157280304Sjkim type = NID_sha1; 158238384Sjkim 159280304Sjkim ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); 160238384Sjkim 161280304Sjkim return ret; 162280304Sjkim} 163238384Sjkim 164276864Sjkim#ifndef OPENSSL_NO_ECDH 165280304Sjkimstatic int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 166280304Sjkim size_t *keylen) 167280304Sjkim{ 168280304Sjkim int ret; 169280304Sjkim size_t outlen; 170280304Sjkim const EC_POINT *pubkey = NULL; 171280304Sjkim if (!ctx->pkey || !ctx->peerkey) { 172280304Sjkim ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); 173280304Sjkim return 0; 174280304Sjkim } 175238384Sjkim 176280304Sjkim if (!key) { 177280304Sjkim const EC_GROUP *group; 178280304Sjkim group = EC_KEY_get0_group(ctx->pkey->pkey.ec); 179280304Sjkim *keylen = (EC_GROUP_get_degree(group) + 7) / 8; 180280304Sjkim return 1; 181280304Sjkim } 182238384Sjkim 183280304Sjkim pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); 184238384Sjkim 185280304Sjkim /* 186280304Sjkim * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not 187280304Sjkim * an error, the result is truncated. 188280304Sjkim */ 189238384Sjkim 190280304Sjkim outlen = *keylen; 191280304Sjkim 192280304Sjkim ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); 193280304Sjkim if (ret < 0) 194280304Sjkim return ret; 195280304Sjkim *keylen = ret; 196280304Sjkim return 1; 197280304Sjkim} 198276864Sjkim#endif 199238384Sjkim 200238384Sjkimstatic int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 201280304Sjkim{ 202280304Sjkim EC_PKEY_CTX *dctx = ctx->data; 203280304Sjkim EC_GROUP *group; 204280304Sjkim switch (type) { 205280304Sjkim case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 206280304Sjkim group = EC_GROUP_new_by_curve_name(p1); 207280304Sjkim if (group == NULL) { 208280304Sjkim ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); 209280304Sjkim return 0; 210280304Sjkim } 211280304Sjkim if (dctx->gen_group) 212280304Sjkim EC_GROUP_free(dctx->gen_group); 213280304Sjkim dctx->gen_group = group; 214280304Sjkim return 1; 215238384Sjkim 216280304Sjkim case EVP_PKEY_CTRL_MD: 217280304Sjkim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 218280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && 219280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 220280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 221280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 222280304Sjkim EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 223280304Sjkim ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); 224280304Sjkim return 0; 225280304Sjkim } 226280304Sjkim dctx->md = p2; 227280304Sjkim return 1; 228238384Sjkim 229280304Sjkim case EVP_PKEY_CTRL_PEER_KEY: 230280304Sjkim /* Default behaviour is OK */ 231280304Sjkim case EVP_PKEY_CTRL_DIGESTINIT: 232280304Sjkim case EVP_PKEY_CTRL_PKCS7_SIGN: 233280304Sjkim case EVP_PKEY_CTRL_CMS_SIGN: 234280304Sjkim return 1; 235238384Sjkim 236280304Sjkim default: 237280304Sjkim return -2; 238238384Sjkim 239280304Sjkim } 240280304Sjkim} 241280304Sjkim 242238384Sjkimstatic int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, 243280304Sjkim const char *type, const char *value) 244280304Sjkim{ 245280304Sjkim if (!strcmp(type, "ec_paramgen_curve")) { 246280304Sjkim int nid; 247280304Sjkim nid = OBJ_sn2nid(value); 248280304Sjkim if (nid == NID_undef) 249280304Sjkim nid = OBJ_ln2nid(value); 250280304Sjkim if (nid == NID_undef) { 251280304Sjkim ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); 252280304Sjkim return 0; 253280304Sjkim } 254280304Sjkim return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); 255280304Sjkim } 256280304Sjkim return -2; 257280304Sjkim} 258238384Sjkim 259238384Sjkimstatic int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 260280304Sjkim{ 261280304Sjkim EC_KEY *ec = NULL; 262280304Sjkim EC_PKEY_CTX *dctx = ctx->data; 263280304Sjkim int ret = 0; 264280304Sjkim if (dctx->gen_group == NULL) { 265280304Sjkim ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); 266280304Sjkim return 0; 267280304Sjkim } 268280304Sjkim ec = EC_KEY_new(); 269280304Sjkim if (!ec) 270280304Sjkim return 0; 271280304Sjkim ret = EC_KEY_set_group(ec, dctx->gen_group); 272280304Sjkim if (ret) 273280304Sjkim EVP_PKEY_assign_EC_KEY(pkey, ec); 274280304Sjkim else 275280304Sjkim EC_KEY_free(ec); 276280304Sjkim return ret; 277280304Sjkim} 278238384Sjkim 279238384Sjkimstatic int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 280280304Sjkim{ 281280304Sjkim EC_KEY *ec = NULL; 282280304Sjkim if (ctx->pkey == NULL) { 283280304Sjkim ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); 284280304Sjkim return 0; 285280304Sjkim } 286280304Sjkim ec = EC_KEY_new(); 287280304Sjkim if (!ec) 288280304Sjkim return 0; 289280304Sjkim EVP_PKEY_assign_EC_KEY(pkey, ec); 290280304Sjkim /* Note: if error return, pkey is freed by parent routine */ 291280304Sjkim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 292280304Sjkim return 0; 293280304Sjkim return EC_KEY_generate_key(pkey->pkey.ec); 294280304Sjkim} 295238384Sjkim 296280304Sjkimconst EVP_PKEY_METHOD ec_pkey_meth = { 297280304Sjkim EVP_PKEY_EC, 298280304Sjkim 0, 299280304Sjkim pkey_ec_init, 300280304Sjkim pkey_ec_copy, 301280304Sjkim pkey_ec_cleanup, 302238384Sjkim 303280304Sjkim 0, 304280304Sjkim pkey_ec_paramgen, 305238384Sjkim 306280304Sjkim 0, 307280304Sjkim pkey_ec_keygen, 308238384Sjkim 309280304Sjkim 0, 310280304Sjkim pkey_ec_sign, 311238384Sjkim 312280304Sjkim 0, 313280304Sjkim pkey_ec_verify, 314238384Sjkim 315280304Sjkim 0, 0, 316238384Sjkim 317280304Sjkim 0, 0, 0, 0, 318238384Sjkim 319280304Sjkim 0, 0, 320238384Sjkim 321280304Sjkim 0, 0, 322238384Sjkim 323280304Sjkim 0, 324276864Sjkim#ifndef OPENSSL_NO_ECDH 325280304Sjkim pkey_ec_derive, 326276864Sjkim#else 327280304Sjkim 0, 328276864Sjkim#endif 329238384Sjkim 330280304Sjkim pkey_ec_ctrl, 331280304Sjkim pkey_ec_ctrl_str 332280304Sjkim}; 333