Loading crypto/ec/ec.h +66 −0 Original line number Diff line number Diff line Loading @@ -973,8 +973,69 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) #define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) #define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) #define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) #define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) #define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)md) #define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)pmd) #define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) #define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, (void *)plen) #define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)p) #define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p) #define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) #define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) #define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) #define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) #define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) #define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) #define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) #define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) #define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) #define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) /* KDF types */ #define EVP_PKEY_ECDH_KDF_NONE 1 #define EVP_PKEY_ECDH_KDF_X9_62 2 /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading @@ -991,6 +1052,8 @@ void ERR_load_EC_strings(void); #define EC_F_D2I_ECPKPARAMETERS 145 #define EC_F_D2I_ECPRIVATEKEY 146 #define EC_F_DO_EC_KEY_PRINT 221 #define EC_F_ECDH_CMS_DECRYPT 238 #define EC_F_ECDH_CMS_SET_SHARED_INFO 239 #define EC_F_ECKEY_PARAM2TYPE 223 #define EC_F_ECKEY_PARAM_DECODE 212 #define EC_F_ECKEY_PRIV_DECODE 213 Loading Loading @@ -1149,6 +1212,7 @@ void ERR_load_EC_strings(void); #define EC_R_INVALID_PENTANOMIAL_BASIS 132 #define EC_R_INVALID_PRIVATE_KEY 123 #define EC_R_INVALID_TRINOMIAL_BASIS 137 #define EC_R_KDF_PARAMETER_ERROR 148 #define EC_R_KEYS_NOT_SET 140 #define EC_R_MISSING_PARAMETERS 124 #define EC_R_MISSING_PRIVATE_KEY 125 Loading @@ -1159,9 +1223,11 @@ void ERR_load_EC_strings(void); #define EC_R_NO_FIELD_MOD 133 #define EC_R_NO_PARAMETERS_SET 139 #define EC_R_PASSED_NULL_PARAMETER 134 #define EC_R_PEER_KEY_ERROR 149 #define EC_R_PKPARAMETERS2GROUP_FAILURE 127 #define EC_R_POINT_AT_INFINITY 106 #define EC_R_POINT_IS_NOT_ON_CURVE 107 #define EC_R_SHARED_INFO_ERROR 150 #define EC_R_SLOT_FULL 108 #define EC_R_UNDEFINED_GENERATOR 113 #define EC_R_UNDEFINED_ORDER 128 Loading crypto/ec/ec_pmeth.c +175 −4 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ #include <openssl/asn1t.h> #include <openssl/x509.h> #include <openssl/ec.h> #include "ec_lcl.h" #include <openssl/ecdsa.h> #include <openssl/evp.h> #include "evp_locl.h" Loading @@ -72,6 +73,20 @@ typedef struct EC_GROUP *gen_group; /* message digest */ const EVP_MD *md; /* Duplicate key if custom cofactor needed */ EC_KEY *co_key; /* Cofactor mode */ char cofactor_mode; /* KDF (if any) to use for ECDH */ char kdf_type; /* Message digest to use for key derivation */ const EVP_MD *kdf_md; /* User key material */ unsigned char *kdf_ukm; size_t kdf_ukmlen; /* KDF output length */ size_t kdf_outlen; } EC_PKEY_CTX; static int pkey_ec_init(EVP_PKEY_CTX *ctx) Loading @@ -83,6 +98,14 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) dctx->gen_group = NULL; dctx->md = NULL; dctx->cofactor_mode = -1; dctx->co_key = NULL; dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; dctx->kdf_md = NULL; dctx->kdf_outlen = 0; dctx->kdf_ukm = NULL; dctx->kdf_ukmlen = 0; ctx->data = dctx; return 1; Loading @@ -102,6 +125,25 @@ static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) return 0; } dctx->md = sctx->md; if (sctx->co_key) { dctx->co_key = EC_KEY_dup(sctx->co_key); if (!dctx->co_key) return 0; } dctx->kdf_type = sctx->kdf_type; dctx->kdf_md = sctx->kdf_md; dctx->kdf_outlen = sctx->kdf_outlen; if (sctx->kdf_ukm) { dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); if (!dctx->kdf_ukm) return 0; } else dctx->kdf_ukm = NULL; dctx->kdf_ukmlen = sctx->kdf_ukmlen; return 1; } Loading @@ -112,6 +154,10 @@ static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { if (dctx->gen_group) EC_GROUP_free(dctx->gen_group); if (dctx->co_key) EC_KEY_free(dctx->co_key); if (dctx->kdf_ukm) OPENSSL_free(dctx->kdf_ukm); OPENSSL_free(dctx); } } Loading Loading @@ -172,20 +218,23 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) int ret; size_t outlen; const EC_POINT *pubkey = NULL; EC_KEY *eckey; EC_PKEY_CTX *dctx = ctx->data; if (!ctx->pkey || !ctx->peerkey) { ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); return 0; } eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; if (!key) { const EC_GROUP *group; group = EC_KEY_get0_group(ctx->pkey->pkey.ec); group = EC_KEY_get0_group(eckey); *keylen = (EC_GROUP_get_degree(group) + 7)/8; return 1; } pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is Loading @@ -194,13 +243,52 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) outlen = *keylen; ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); if (ret < 0) return ret; *keylen = ret; return 1; } static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { EC_PKEY_CTX *dctx = ctx->data; unsigned char *ktmp = NULL; size_t ktmplen; int rv = 0; if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) return pkey_ec_derive(ctx, key, keylen); if (!key) { *keylen = dctx->kdf_outlen; return 1; } if (*keylen != dctx->kdf_outlen) return 0; if (!pkey_ec_derive(ctx, NULL, &ktmplen)) return 0; ktmp = OPENSSL_malloc(ktmplen); if (!ktmp) return 0; if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) goto err; /* Do KDF stuff */ if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) goto err; rv = 1; err: if (ktmp) { OPENSSL_cleanse(ktmp, ktmplen); OPENSSL_free(ktmp); } return rv; } static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { EC_PKEY_CTX *dctx = ctx->data; Loading Loading @@ -228,6 +316,89 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) EC_GROUP_set_asn1_flag(dctx->gen_group, p1); return 1; case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: if (p1 == -2) { if (dctx->co_key) return dctx->cofactor_mode; else { EC_KEY *ec_key = ctx->pkey->pkey.ec; return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0; } } else if (p1 < -1 || p1 > 1) return -2; dctx->cofactor_mode = p1; if (p1 != -1) { EC_KEY *ec_key = ctx->pkey->pkey.ec; if (!ec_key->group) return -2; /* If cofactor is 1 cofactor mode does nothing */ if (BN_is_one(&ec_key->group->cofactor)) return 1; if (!dctx->co_key) { dctx->co_key = EC_KEY_dup(ec_key); if (!dctx->co_key) return 0; } if (p1) EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); else EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); } else if (dctx->co_key) { EC_KEY_free(dctx->co_key); dctx->co_key = NULL; } return 1; case EVP_PKEY_CTRL_EC_KDF_TYPE: if (p1 == -2) return dctx->kdf_type; if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) return -2; dctx->kdf_type = p1; return 1; case EVP_PKEY_CTRL_EC_KDF_MD: dctx->kdf_md = p2; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_MD: *(const EVP_MD **)p2 = dctx->kdf_md; return 1; case EVP_PKEY_CTRL_EC_KDF_OUTLEN: if (p1 <= 0) return -2; dctx->kdf_outlen = (size_t)p1; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: *(int *)p2 = dctx->kdf_outlen; return 1; case EVP_PKEY_CTRL_EC_KDF_UKM: if (dctx->kdf_ukm) OPENSSL_free(dctx->kdf_ukm); dctx->kdf_ukm = p2; if (p2) dctx->kdf_ukmlen = p1; else dctx->kdf_ukmlen = 0; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_UKM: *(unsigned char **)p2 = dctx->kdf_ukm; return dctx->kdf_ukmlen; case EVP_PKEY_CTRL_MD: if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && Loading Loading @@ -369,7 +540,7 @@ const EVP_PKEY_METHOD ec_pkey_meth = 0,0, 0, pkey_ec_derive, pkey_ec_kdf_derive, pkey_ec_ctrl, pkey_ec_ctrl_str Loading crypto/ecdh/Makefile +2 −2 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ TEST=ecdhtest.c APPS= LIB=$(TOP)/libcrypto.a LIBSRC= ech_lib.c ech_ossl.c ech_key.c ech_err.c LIBSRC= ech_lib.c ech_ossl.c ech_key.c ech_err.c ech_kdf.c LIBOBJ= ech_lib.o ech_ossl.o ech_key.o ech_err.o LIBOBJ= ech_lib.o ech_ossl.o ech_key.o ech_err.o ech_kdf.o SRC= $(LIBSRC) Loading crypto/ecdh/ecdh.h +5 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,11 @@ int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg); void *ECDH_get_ex_data(EC_KEY *d, int idx); int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading crypto/ecdh/ech_kdf.c 0 → 100644 +116 −0 Original line number Diff line number Diff line /* crypto/ecdh/ec_kdf.c */ /* * Written by Stephen Henson for the OpenSSL project. */ /* ==================================================================== * Copyright (c) 2013 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ #define OPENSSL_FIPSAPI #include <string.h> #include <openssl/ecdh.h> #include <openssl/evp.h> /* Key derivation function from X9.62/SECG */ #define ECDH_KDF_MAX (1L << 31) int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md) { EVP_MD_CTX mctx; int rv = 0; unsigned int i; size_t mdlen; unsigned char ctr[4]; if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX || Zlen > ECDH_KDF_MAX) return 0; mdlen = EVP_MD_size(md); EVP_MD_CTX_init(&mctx); for (i = 1;;i++) { unsigned char mtmp[EVP_MAX_MD_SIZE]; EVP_DigestInit_ex(&mctx, md, NULL); ctr[3] = i & 0xFF; ctr[2] = (i >> 8) & 0xFF; ctr[1] = (i >> 16) & 0xFF; ctr[0] = (i >> 24) & 0xFF; if (!EVP_DigestUpdate(&mctx, Z, Zlen)) goto err; if (!EVP_DigestUpdate(&mctx, ctr, sizeof(ctr))) goto err; if (!EVP_DigestUpdate(&mctx, sinfo, sinfolen)) goto err; if (outlen > mdlen) { if (!EVP_DigestFinal(&mctx, out, NULL)) goto err; outlen -= mdlen; if (outlen == 0) break; out += mdlen; } else { if (!EVP_DigestFinal(&mctx, mtmp, NULL)) goto err; memcpy(out, mtmp, outlen); OPENSSL_cleanse(mtmp, mdlen); break; } } rv = 1; err: EVP_MD_CTX_cleanup(&mctx); return rv; } Loading
crypto/ec/ec.h +66 −0 Original line number Diff line number Diff line Loading @@ -973,8 +973,69 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) #define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) #define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) #define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) #define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) #define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)md) #define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)pmd) #define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) #define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, (void *)plen) #define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)p) #define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p) #define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) #define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) #define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) #define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) #define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) #define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) #define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) #define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) #define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) #define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) /* KDF types */ #define EVP_PKEY_ECDH_KDF_NONE 1 #define EVP_PKEY_ECDH_KDF_X9_62 2 /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading @@ -991,6 +1052,8 @@ void ERR_load_EC_strings(void); #define EC_F_D2I_ECPKPARAMETERS 145 #define EC_F_D2I_ECPRIVATEKEY 146 #define EC_F_DO_EC_KEY_PRINT 221 #define EC_F_ECDH_CMS_DECRYPT 238 #define EC_F_ECDH_CMS_SET_SHARED_INFO 239 #define EC_F_ECKEY_PARAM2TYPE 223 #define EC_F_ECKEY_PARAM_DECODE 212 #define EC_F_ECKEY_PRIV_DECODE 213 Loading Loading @@ -1149,6 +1212,7 @@ void ERR_load_EC_strings(void); #define EC_R_INVALID_PENTANOMIAL_BASIS 132 #define EC_R_INVALID_PRIVATE_KEY 123 #define EC_R_INVALID_TRINOMIAL_BASIS 137 #define EC_R_KDF_PARAMETER_ERROR 148 #define EC_R_KEYS_NOT_SET 140 #define EC_R_MISSING_PARAMETERS 124 #define EC_R_MISSING_PRIVATE_KEY 125 Loading @@ -1159,9 +1223,11 @@ void ERR_load_EC_strings(void); #define EC_R_NO_FIELD_MOD 133 #define EC_R_NO_PARAMETERS_SET 139 #define EC_R_PASSED_NULL_PARAMETER 134 #define EC_R_PEER_KEY_ERROR 149 #define EC_R_PKPARAMETERS2GROUP_FAILURE 127 #define EC_R_POINT_AT_INFINITY 106 #define EC_R_POINT_IS_NOT_ON_CURVE 107 #define EC_R_SHARED_INFO_ERROR 150 #define EC_R_SLOT_FULL 108 #define EC_R_UNDEFINED_GENERATOR 113 #define EC_R_UNDEFINED_ORDER 128 Loading
crypto/ec/ec_pmeth.c +175 −4 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ #include <openssl/asn1t.h> #include <openssl/x509.h> #include <openssl/ec.h> #include "ec_lcl.h" #include <openssl/ecdsa.h> #include <openssl/evp.h> #include "evp_locl.h" Loading @@ -72,6 +73,20 @@ typedef struct EC_GROUP *gen_group; /* message digest */ const EVP_MD *md; /* Duplicate key if custom cofactor needed */ EC_KEY *co_key; /* Cofactor mode */ char cofactor_mode; /* KDF (if any) to use for ECDH */ char kdf_type; /* Message digest to use for key derivation */ const EVP_MD *kdf_md; /* User key material */ unsigned char *kdf_ukm; size_t kdf_ukmlen; /* KDF output length */ size_t kdf_outlen; } EC_PKEY_CTX; static int pkey_ec_init(EVP_PKEY_CTX *ctx) Loading @@ -83,6 +98,14 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) dctx->gen_group = NULL; dctx->md = NULL; dctx->cofactor_mode = -1; dctx->co_key = NULL; dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; dctx->kdf_md = NULL; dctx->kdf_outlen = 0; dctx->kdf_ukm = NULL; dctx->kdf_ukmlen = 0; ctx->data = dctx; return 1; Loading @@ -102,6 +125,25 @@ static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) return 0; } dctx->md = sctx->md; if (sctx->co_key) { dctx->co_key = EC_KEY_dup(sctx->co_key); if (!dctx->co_key) return 0; } dctx->kdf_type = sctx->kdf_type; dctx->kdf_md = sctx->kdf_md; dctx->kdf_outlen = sctx->kdf_outlen; if (sctx->kdf_ukm) { dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); if (!dctx->kdf_ukm) return 0; } else dctx->kdf_ukm = NULL; dctx->kdf_ukmlen = sctx->kdf_ukmlen; return 1; } Loading @@ -112,6 +154,10 @@ static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { if (dctx->gen_group) EC_GROUP_free(dctx->gen_group); if (dctx->co_key) EC_KEY_free(dctx->co_key); if (dctx->kdf_ukm) OPENSSL_free(dctx->kdf_ukm); OPENSSL_free(dctx); } } Loading Loading @@ -172,20 +218,23 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) int ret; size_t outlen; const EC_POINT *pubkey = NULL; EC_KEY *eckey; EC_PKEY_CTX *dctx = ctx->data; if (!ctx->pkey || !ctx->peerkey) { ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); return 0; } eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; if (!key) { const EC_GROUP *group; group = EC_KEY_get0_group(ctx->pkey->pkey.ec); group = EC_KEY_get0_group(eckey); *keylen = (EC_GROUP_get_degree(group) + 7)/8; return 1; } pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is Loading @@ -194,13 +243,52 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) outlen = *keylen; ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); if (ret < 0) return ret; *keylen = ret; return 1; } static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { EC_PKEY_CTX *dctx = ctx->data; unsigned char *ktmp = NULL; size_t ktmplen; int rv = 0; if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) return pkey_ec_derive(ctx, key, keylen); if (!key) { *keylen = dctx->kdf_outlen; return 1; } if (*keylen != dctx->kdf_outlen) return 0; if (!pkey_ec_derive(ctx, NULL, &ktmplen)) return 0; ktmp = OPENSSL_malloc(ktmplen); if (!ktmp) return 0; if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) goto err; /* Do KDF stuff */ if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) goto err; rv = 1; err: if (ktmp) { OPENSSL_cleanse(ktmp, ktmplen); OPENSSL_free(ktmp); } return rv; } static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { EC_PKEY_CTX *dctx = ctx->data; Loading Loading @@ -228,6 +316,89 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) EC_GROUP_set_asn1_flag(dctx->gen_group, p1); return 1; case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: if (p1 == -2) { if (dctx->co_key) return dctx->cofactor_mode; else { EC_KEY *ec_key = ctx->pkey->pkey.ec; return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0; } } else if (p1 < -1 || p1 > 1) return -2; dctx->cofactor_mode = p1; if (p1 != -1) { EC_KEY *ec_key = ctx->pkey->pkey.ec; if (!ec_key->group) return -2; /* If cofactor is 1 cofactor mode does nothing */ if (BN_is_one(&ec_key->group->cofactor)) return 1; if (!dctx->co_key) { dctx->co_key = EC_KEY_dup(ec_key); if (!dctx->co_key) return 0; } if (p1) EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); else EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); } else if (dctx->co_key) { EC_KEY_free(dctx->co_key); dctx->co_key = NULL; } return 1; case EVP_PKEY_CTRL_EC_KDF_TYPE: if (p1 == -2) return dctx->kdf_type; if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) return -2; dctx->kdf_type = p1; return 1; case EVP_PKEY_CTRL_EC_KDF_MD: dctx->kdf_md = p2; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_MD: *(const EVP_MD **)p2 = dctx->kdf_md; return 1; case EVP_PKEY_CTRL_EC_KDF_OUTLEN: if (p1 <= 0) return -2; dctx->kdf_outlen = (size_t)p1; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: *(int *)p2 = dctx->kdf_outlen; return 1; case EVP_PKEY_CTRL_EC_KDF_UKM: if (dctx->kdf_ukm) OPENSSL_free(dctx->kdf_ukm); dctx->kdf_ukm = p2; if (p2) dctx->kdf_ukmlen = p1; else dctx->kdf_ukmlen = 0; return 1; case EVP_PKEY_CTRL_GET_EC_KDF_UKM: *(unsigned char **)p2 = dctx->kdf_ukm; return dctx->kdf_ukmlen; case EVP_PKEY_CTRL_MD: if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && Loading Loading @@ -369,7 +540,7 @@ const EVP_PKEY_METHOD ec_pkey_meth = 0,0, 0, pkey_ec_derive, pkey_ec_kdf_derive, pkey_ec_ctrl, pkey_ec_ctrl_str Loading
crypto/ecdh/Makefile +2 −2 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ TEST=ecdhtest.c APPS= LIB=$(TOP)/libcrypto.a LIBSRC= ech_lib.c ech_ossl.c ech_key.c ech_err.c LIBSRC= ech_lib.c ech_ossl.c ech_key.c ech_err.c ech_kdf.c LIBOBJ= ech_lib.o ech_ossl.o ech_key.o ech_err.o LIBOBJ= ech_lib.o ech_ossl.o ech_key.o ech_err.o ech_kdf.o SRC= $(LIBSRC) Loading
crypto/ecdh/ecdh.h +5 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,11 @@ int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg); void *ECDH_get_ex_data(EC_KEY *d, int idx); int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading
crypto/ecdh/ech_kdf.c 0 → 100644 +116 −0 Original line number Diff line number Diff line /* crypto/ecdh/ec_kdf.c */ /* * Written by Stephen Henson for the OpenSSL project. */ /* ==================================================================== * Copyright (c) 2013 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ #define OPENSSL_FIPSAPI #include <string.h> #include <openssl/ecdh.h> #include <openssl/evp.h> /* Key derivation function from X9.62/SECG */ #define ECDH_KDF_MAX (1L << 31) int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md) { EVP_MD_CTX mctx; int rv = 0; unsigned int i; size_t mdlen; unsigned char ctr[4]; if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX || Zlen > ECDH_KDF_MAX) return 0; mdlen = EVP_MD_size(md); EVP_MD_CTX_init(&mctx); for (i = 1;;i++) { unsigned char mtmp[EVP_MAX_MD_SIZE]; EVP_DigestInit_ex(&mctx, md, NULL); ctr[3] = i & 0xFF; ctr[2] = (i >> 8) & 0xFF; ctr[1] = (i >> 16) & 0xFF; ctr[0] = (i >> 24) & 0xFF; if (!EVP_DigestUpdate(&mctx, Z, Zlen)) goto err; if (!EVP_DigestUpdate(&mctx, ctr, sizeof(ctr))) goto err; if (!EVP_DigestUpdate(&mctx, sinfo, sinfolen)) goto err; if (outlen > mdlen) { if (!EVP_DigestFinal(&mctx, out, NULL)) goto err; outlen -= mdlen; if (outlen == 0) break; out += mdlen; } else { if (!EVP_DigestFinal(&mctx, mtmp, NULL)) goto err; memcpy(out, mtmp, outlen); OPENSSL_cleanse(mtmp, mdlen); break; } } rv = 1; err: EVP_MD_CTX_cleanup(&mctx); return rv; }