Home | History | Annotate | Download | only in evp
      1 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) 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 
     74 typedef 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 
     95 static 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 
    110 static 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 
    147 static 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 
    165 static 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 
    192 static 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 
    206 static 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 
    242 static 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 
    274 err:
    275   if (ktmp) {
    276     OPENSSL_cleanse(ktmp, ktmplen);
    277     OPENSSL_free(ktmp);
    278   }
    279   return rv;
    280 }
    281 
    282 static 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 
    365 static 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 
    387 static 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 
    412 const 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