X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fdh%2Fdh_pmeth.c;h=93bada0058eaec5e00622b1b5d50dbcdafae7a52;hb=007c80eae4e1f36e28a9645c485c14ec61baed4e;hp=095227bc2f85769209be3723e5b072f37392e357;hpb=3909087801729bebb3a1182936a855a47e4ee9c9;p=oweals%2Fopenssl.git diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 095227bc2f..93bada0058 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -1,5 +1,6 @@ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 2006. +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. @@ -9,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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 @@ -56,387 +57,491 @@ */ #include -#include "cryptlib.h" +#include "internal/cryptlib.h" #include #include #include #include #include -#ifndef OPENSSL_NO_DSA #include -#endif -#include "evp_locl.h" +#include +#include "internal/evp_int.h" /* DH pkey context structure */ -typedef struct - { - /* Parameter gen parameters */ - int prime_len; - int generator; - int use_dsa; - int subprime_len; - const EVP_MD *md; - int rfc5114_param; - /* Keygen callback info */ - int gentmp[2]; - /* message digest */ - } DH_PKEY_CTX; +typedef struct { + /* Parameter gen parameters */ + int prime_len; + int generator; + int use_dsa; + int subprime_len; + /* message digest used for parameter generation */ + const EVP_MD *md; + int rfc5114_param; + /* Keygen callback info */ + int gentmp[2]; + /* KDF (if any) to use for DH */ + char kdf_type; + /* OID to use for KDF */ + ASN1_OBJECT *kdf_oid; + /* 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; +} DH_PKEY_CTX; static int pkey_dh_init(EVP_PKEY_CTX *ctx) - { - DH_PKEY_CTX *dctx; - dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); - if (!dctx) - return 0; - dctx->prime_len = 1024; - dctx->subprime_len = -1; - dctx->generator = 2; - dctx->use_dsa = 0; - dctx->md = NULL; - dctx->rfc5114_param = 0; - - ctx->data = dctx; - ctx->keygen_info = dctx->gentmp; - ctx->keygen_info_count = 2; - - return 1; - } +{ + DH_PKEY_CTX *dctx; + + dctx = OPENSSL_zalloc(sizeof(*dctx)); + if (dctx == NULL) + return 0; + dctx->prime_len = 1024; + dctx->subprime_len = -1; + dctx->generator = 2; + dctx->kdf_type = EVP_PKEY_DH_KDF_NONE; + + ctx->data = dctx; + ctx->keygen_info = dctx->gentmp; + ctx->keygen_info_count = 2; + + return 1; +} static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) - { - DH_PKEY_CTX *dctx, *sctx; - if (!pkey_dh_init(dst)) - return 0; - sctx = src->data; - dctx = dst->data; - dctx->prime_len = sctx->prime_len; - dctx->subprime_len = sctx->subprime_len; - dctx->generator = sctx->generator; - dctx->use_dsa = sctx->use_dsa; - dctx->md = sctx->md; - dctx->rfc5114_param = sctx->rfc5114_param; - return 1; - } +{ + DH_PKEY_CTX *dctx, *sctx; + if (!pkey_dh_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + dctx->prime_len = sctx->prime_len; + dctx->subprime_len = sctx->subprime_len; + dctx->generator = sctx->generator; + dctx->use_dsa = sctx->use_dsa; + dctx->md = sctx->md; + dctx->rfc5114_param = sctx->rfc5114_param; + + dctx->kdf_type = sctx->kdf_type; + dctx->kdf_oid = OBJ_dup(sctx->kdf_oid); + if (!dctx->kdf_oid) + return 0; + dctx->kdf_md = sctx->kdf_md; + if (dctx->kdf_ukm) { + dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); + dctx->kdf_ukmlen = sctx->kdf_ukmlen; + } + dctx->kdf_outlen = sctx->kdf_outlen; + return 1; +} static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) - { - DH_PKEY_CTX *dctx = ctx->data; - if (dctx) - OPENSSL_free(dctx); - } +{ + DH_PKEY_CTX *dctx = ctx->data; + if (dctx) { + OPENSSL_free(dctx->kdf_ukm); + ASN1_OBJECT_free(dctx->kdf_oid); + OPENSSL_free(dctx); + } +} static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) - { - DH_PKEY_CTX *dctx = ctx->data; - switch (type) - { - case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: - if (p1 < 256) - return -2; - dctx->prime_len = p1; - return 1; - - case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: - if (dctx->use_dsa == 0) - return -2; - dctx->subprime_len = p1; - return 1; - - case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: - if (dctx->use_dsa) - return -2; - dctx->generator = p1; - return 1; - - case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: +{ + DH_PKEY_CTX *dctx = ctx->data; + switch (type) { + case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: + if (p1 < 256) + return -2; + dctx->prime_len = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: + if (dctx->use_dsa == 0) + return -2; + dctx->subprime_len = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: + if (dctx->use_dsa) + return -2; + dctx->generator = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: #ifdef OPENSSL_NO_DSA - if (p1 != 0) - return -2; + if (p1 != 0) + return -2; #else - if (p1 < 0 || p1 > 2) - return -2; + if (p1 < 0 || p1 > 2) + return -2; #endif - dctx->use_dsa = p1; - return 1; - - case EVP_PKEY_CTRL_DH_RFC5114: - if (p1 < 1 || p1 > 3) - return -2; - dctx->rfc5114_param = p1; - return 1; - - case EVP_PKEY_CTRL_PEER_KEY: - /* Default behaviour is OK */ - return 1; - - default: - return -2; - - } - } - + dctx->use_dsa = p1; + return 1; + + case EVP_PKEY_CTRL_DH_RFC5114: + if (p1 < 1 || p1 > 3) + return -2; + dctx->rfc5114_param = p1; + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + /* Default behaviour is OK */ + return 1; + + case EVP_PKEY_CTRL_DH_KDF_TYPE: + if (p1 == -2) + return dctx->kdf_type; +#ifdef OPENSSL_NO_CMS + if (p1 != EVP_PKEY_DH_KDF_NONE) +#else + if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42) +#endif + return -2; + dctx->kdf_type = p1; + return 1; + + case EVP_PKEY_CTRL_DH_KDF_MD: + dctx->kdf_md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_MD: + *(const EVP_MD **)p2 = dctx->kdf_md; + return 1; + + case EVP_PKEY_CTRL_DH_KDF_OUTLEN: + if (p1 <= 0) + return -2; + dctx->kdf_outlen = (size_t)p1; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN: + *(int *)p2 = dctx->kdf_outlen; + return 1; + + case EVP_PKEY_CTRL_DH_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_DH_KDF_UKM: + *(unsigned char **)p2 = dctx->kdf_ukm; + return dctx->kdf_ukmlen; + + case EVP_PKEY_CTRL_DH_KDF_OID: + ASN1_OBJECT_free(dctx->kdf_oid); + dctx->kdf_oid = p2; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_OID: + *(ASN1_OBJECT **)p2 = dctx->kdf_oid; + return 1; + + default: + return -2; + + } +} static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) - { - if (!strcmp(type, "dh_paramgen_prime_len")) - { - int len; - len = atoi(value); - return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); - } - if (!strcmp(type, "dh_rfc5114")) - { - DH_PKEY_CTX *dctx = ctx->data; - int len; - len = atoi(value); - if (len < 0 || len > 3) - return -2; - dctx->rfc5114_param = len; - return 1; - } - if (!strcmp(type, "dh_paramgen_generator")) - { - int len; - len = atoi(value); - return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); - } - if (!strcmp(type, "dh_paramgen_subprime_len")) - { - int len; - len = atoi(value); - return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len); - } - if (!strcmp(type, "dh_paramgen_type")) - { - int typ; - typ = atoi(value); - return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ); - } - return -2; - } + const char *type, const char *value) +{ + if (strcmp(type, "dh_paramgen_prime_len") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); + } + if (strcmp(type, "dh_rfc5114") == 0) { + DH_PKEY_CTX *dctx = ctx->data; + int len; + len = atoi(value); + if (len < 0 || len > 3) + return -2; + dctx->rfc5114_param = len; + return 1; + } + if (strcmp(type, "dh_paramgen_generator") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); + } + if (strcmp(type, "dh_paramgen_subprime_len") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len); + } + if (strcmp(type, "dh_paramgen_type") == 0) { + int typ; + typ = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ); + } + return -2; +} #ifndef OPENSSL_NO_DSA extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, - const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len, - unsigned char *seed_out, - int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); + const EVP_MD *evpmd, + const unsigned char *seed_in, size_t seed_len, + unsigned char *seed_out, int *counter_ret, + unsigned long *h_ret, BN_GENCB *cb); extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, - const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len, - int idx, unsigned char *seed_out, - int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); + const EVP_MD *evpmd, + const unsigned char *seed_in, + size_t seed_len, int idx, + unsigned char *seed_out, int *counter_ret, + unsigned long *h_ret, BN_GENCB *cb); static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb) - { - DSA *ret; - int rv = 0; - int prime_len = dctx->prime_len; - int subprime_len = dctx->subprime_len; - const EVP_MD *md = dctx->md; - if (dctx->use_dsa > 2) - return NULL; - ret = DSA_new(); - if (!ret) - return NULL; - if (subprime_len == -1) - { - if (prime_len >= 2048) - subprime_len = 256; - else - subprime_len = 160; - } - if (md == NULL) - { - if (prime_len >= 2048) - md = EVP_sha256(); - else - md = EVP_sha1(); - } - if (dctx->use_dsa == 1) - rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md, - NULL, 0, NULL, NULL, NULL, pcb); - else if(dctx->use_dsa == 2) - rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md, - NULL, 0, -1, NULL, NULL, NULL, pcb); - if (rv <= 0) - { - DSA_free(ret); - return NULL; - } - return ret; - } +{ + DSA *ret; + int rv = 0; + int prime_len = dctx->prime_len; + int subprime_len = dctx->subprime_len; + const EVP_MD *md = dctx->md; + if (dctx->use_dsa > 2) + return NULL; + ret = DSA_new(); + if (ret == NULL) + return NULL; + if (subprime_len == -1) { + if (prime_len >= 2048) + subprime_len = 256; + else + subprime_len = 160; + } + if (md == NULL) { + if (prime_len >= 2048) + md = EVP_sha256(); + else + md = EVP_sha1(); + } + if (dctx->use_dsa == 1) + rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md, + NULL, 0, NULL, NULL, NULL, pcb); + else if (dctx->use_dsa == 2) + rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md, + NULL, 0, -1, NULL, NULL, NULL, pcb); + if (rv <= 0) { + DSA_free(ret); + return NULL; + } + return ret; +} #endif static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - DH *dh = NULL; - DH_PKEY_CTX *dctx = ctx->data; - BN_GENCB *pcb, cb; - int ret; - if (dctx->rfc5114_param) - { - switch (dctx->rfc5114_param) - { - case 1: - dh = DH_get_1024_160(); - break; - - case 2: - dh = DH_get_2048_224(); - break; - - case 3: - dh = DH_get_2048_256(); - break; - - default: - return -2; - } - EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); - return 1; - } - - if (ctx->pkey_gencb) - { - pcb = &cb; - evp_pkey_set_cb_translate(pcb, ctx); - } - else - pcb = NULL; +{ + DH *dh = NULL; + DH_PKEY_CTX *dctx = ctx->data; + BN_GENCB *pcb; + int ret; + if (dctx->rfc5114_param) { + switch (dctx->rfc5114_param) { + case 1: + dh = DH_get_1024_160(); + break; + + case 2: + dh = DH_get_2048_224(); + break; + + case 3: + dh = DH_get_2048_256(); + break; + + default: + return -2; + } + EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); + return 1; + } + + if (ctx->pkey_gencb) { + pcb = BN_GENCB_new(); + if (pcb == NULL) + return 0; + evp_pkey_set_cb_translate(pcb, ctx); + } else + pcb = NULL; #ifndef OPENSSL_NO_DSA - if (dctx->use_dsa) - { - DSA *dsa_dh; - dsa_dh = dsa_dh_generate(dctx, pcb); - if (!dsa_dh) - return 0; - dh = DSA_dup_DH(dsa_dh); - DSA_free(dsa_dh); - if (!dh) - return 0; - EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); - return 1; - } + if (dctx->use_dsa) { + DSA *dsa_dh; + dsa_dh = dsa_dh_generate(dctx, pcb); + BN_GENCB_free(pcb); + if (dsa_dh == NULL) + return 0; + dh = DSA_dup_DH(dsa_dh); + DSA_free(dsa_dh); + if (!dh) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); + return 1; + } #endif - dh = DH_new(); - if (!dh) - return 0; - ret = DH_generate_parameters_ex(dh, - dctx->prime_len, dctx->generator, pcb); - - if (ret) - EVP_PKEY_assign_DH(pkey, dh); - else - DH_free(dh); - return ret; - } + dh = DH_new(); + if (dh == NULL) { + BN_GENCB_free(pcb); + return 0; + } + ret = DH_generate_parameters_ex(dh, + dctx->prime_len, dctx->generator, pcb); + BN_GENCB_free(pcb); + if (ret) + EVP_PKEY_assign_DH(pkey, dh); + else + DH_free(dh); + return ret; +} static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - DH *dh = NULL; - if (ctx->pkey == NULL) - { - DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); - return 0; - } - dh = DH_new(); - if (!dh) - return 0; - EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); - /* Note: if error return, pkey is freed by parent routine */ - if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) - return 0; - return DH_generate_key(pkey->pkey.dh); - } - -static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) - { - int ret; - if (!ctx->pkey || !ctx->peerkey) - { - DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); - return 0; - } - ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key, - ctx->pkey->pkey.dh); - if (ret < 0) - return ret; - *keylen = ret; - return 1; - } - -const EVP_PKEY_METHOD dh_pkey_meth = - { - EVP_PKEY_DH, - EVP_PKEY_FLAG_AUTOARGLEN, - pkey_dh_init, - pkey_dh_copy, - pkey_dh_cleanup, - - 0, - pkey_dh_paramgen, - - 0, - pkey_dh_keygen, - - 0, - 0, - - 0, - 0, - - 0,0, - - 0,0,0,0, - - 0,0, - - 0,0, - - 0, - pkey_dh_derive, - - pkey_dh_ctrl, - pkey_dh_ctrl_str - - }; - -const EVP_PKEY_METHOD dhx_pkey_meth = - { - EVP_PKEY_DHX, - EVP_PKEY_FLAG_AUTOARGLEN, - pkey_dh_init, - pkey_dh_copy, - pkey_dh_cleanup, - - 0, - pkey_dh_paramgen, - - 0, - pkey_dh_keygen, - - 0, - 0, - - 0, - 0, - - 0,0, - - 0,0,0,0, - - 0,0, - - 0,0, - - 0, - pkey_dh_derive, - - pkey_dh_ctrl, - pkey_dh_ctrl_str +{ + DH *dh = NULL; + if (ctx->pkey == NULL) { + DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); + return 0; + } + dh = DH_new(); + if (dh == NULL) + return 0; + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); + /* Note: if error return, pkey is freed by parent routine */ + if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) + return 0; + return DH_generate_key(pkey->pkey.dh); +} + +static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + int ret; + DH *dh; + DH_PKEY_CTX *dctx = ctx->data; + BIGNUM *dhpub; + if (!ctx->pkey || !ctx->peerkey) { + DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); + return 0; + } + dh = ctx->pkey->pkey.dh; + dhpub = ctx->peerkey->pkey.dh->pub_key; + if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) { + if (key == NULL) { + *keylen = DH_size(dh); + return 1; + } + ret = DH_compute_key(key, dhpub, dh); + if (ret < 0) + return ret; + *keylen = ret; + return 1; + } +#ifndef OPENSSL_NO_CMS + else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { + + unsigned char *Z = NULL; + size_t Zlen = 0; + if (!dctx->kdf_outlen || !dctx->kdf_oid) + return 0; + if (key == NULL) { + *keylen = dctx->kdf_outlen; + return 1; + } + if (*keylen != dctx->kdf_outlen) + return 0; + ret = 0; + Zlen = DH_size(dh); + Z = OPENSSL_malloc(Zlen); + if (Z == NULL) { + goto err; + } + if (DH_compute_key_padded(Z, dhpub, dh) <= 0) + goto err; + if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid, + dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) + goto err; + *keylen = dctx->kdf_outlen; + ret = 1; + err: + OPENSSL_clear_free(Z, Zlen); + return ret; + } +#endif + return 0; +} + +const EVP_PKEY_METHOD dh_pkey_meth = { + EVP_PKEY_DH, + 0, + pkey_dh_init, + pkey_dh_copy, + pkey_dh_cleanup, + + 0, + pkey_dh_paramgen, + + 0, + pkey_dh_keygen, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_dh_derive, + + pkey_dh_ctrl, + pkey_dh_ctrl_str +}; + +const EVP_PKEY_METHOD dhx_pkey_meth = { + EVP_PKEY_DHX, + 0, + pkey_dh_init, + pkey_dh_copy, + pkey_dh_cleanup, + + 0, + pkey_dh_paramgen, + + 0, + pkey_dh_keygen, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_dh_derive, - }; + pkey_dh_ctrl, + pkey_dh_ctrl_str +};