CMS RFC2631 X9.42 DH enveloped data support.
(cherry picked from commit bd59f2b91d
)
Conflicts:
crypto/dh/dh.h
crypto/dh/dh_err.c
Sync error codes with 1.0.1.
This commit is contained in:
parent
ecf9ceb90d
commit
aaf74259ec
4 changed files with 565 additions and 9 deletions
|
@ -263,11 +263,74 @@ int DH_KDF_X9_42(unsigned char *out, size_t outlen,
|
|||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
|
||||
EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
|
||||
|
||||
#define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL)
|
||||
|
||||
#define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL)
|
||||
|
||||
#define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)oid)
|
||||
|
||||
#define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)poid)
|
||||
|
||||
#define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)md)
|
||||
|
||||
#define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)pmd)
|
||||
|
||||
#define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL)
|
||||
|
||||
#define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)plen)
|
||||
|
||||
#define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)p)
|
||||
|
||||
#define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \
|
||||
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
|
||||
EVP_PKEY_OP_DERIVE, \
|
||||
EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)p)
|
||||
|
||||
#define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1)
|
||||
#define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2)
|
||||
#define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3)
|
||||
#define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4)
|
||||
#define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5)
|
||||
#define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6)
|
||||
#define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7)
|
||||
#define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8)
|
||||
#define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9)
|
||||
#define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10)
|
||||
#define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11)
|
||||
#define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12)
|
||||
#define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13)
|
||||
#define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14)
|
||||
|
||||
/* KDF types */
|
||||
#define EVP_PKEY_DH_KDF_NONE 1
|
||||
#define EVP_PKEY_DH_KDF_X9_42 2
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
|
@ -281,6 +344,9 @@ void ERR_load_DH_strings(void);
|
|||
#define DH_F_COMPUTE_KEY 102
|
||||
#define DH_F_DHPARAMS_PRINT_FP 101
|
||||
#define DH_F_DH_BUILTIN_GENPARAMS 106
|
||||
#define DH_F_DH_CMS_DECRYPT 117
|
||||
#define DH_F_DH_CMS_SET_PEERKEY 118
|
||||
#define DH_F_DH_CMS_SET_SHARED_INFO 119
|
||||
#define DH_F_DH_COMPUTE_KEY 114
|
||||
#define DH_F_DH_GENERATE_KEY 115
|
||||
#define DH_F_DH_GENERATE_PARAMETERS_EX 116
|
||||
|
@ -302,6 +368,7 @@ void ERR_load_DH_strings(void);
|
|||
#define DH_R_BN_ERROR 106
|
||||
#define DH_R_DECODE_ERROR 104
|
||||
#define DH_R_INVALID_PUBKEY 102
|
||||
#define DH_R_KDF_PARAMETER_ERROR 112
|
||||
#define DH_R_KEYS_NOT_SET 108
|
||||
#define DH_R_KEY_SIZE_TOO_SMALL 110
|
||||
#define DH_R_MODULUS_TOO_LARGE 103
|
||||
|
@ -309,6 +376,8 @@ void ERR_load_DH_strings(void);
|
|||
#define DH_R_NO_PARAMETERS_SET 107
|
||||
#define DH_R_NO_PRIVATE_VALUE 100
|
||||
#define DH_R_PARAMETER_ENCODING_ERROR 105
|
||||
#define DH_R_PEER_KEY_ERROR 113
|
||||
#define DH_R_SHARED_INFO_ERROR 114
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "asn1_locl.h"
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
#include <openssl/cms.h>
|
||||
#endif
|
||||
|
||||
extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
|
||||
|
||||
|
@ -569,6 +572,34 @@ int DHparams_print(BIO *bp, const DH *x)
|
|||
return do_dh_print(bp, x, 4, NULL, 0);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static int dh_cms_decrypt(CMS_RecipientInfo *ri);
|
||||
static int dh_cms_encrypt(CMS_RecipientInfo *ri);
|
||||
#endif
|
||||
|
||||
static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
|
||||
if (arg1 == 1)
|
||||
return dh_cms_decrypt(arg2);
|
||||
else if (arg1 == 0)
|
||||
return dh_cms_encrypt(arg2);
|
||||
return -2;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
|
||||
*(int *)arg2 = CMS_RECIPINFO_AGREE;
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dh_asn1_meth =
|
||||
{
|
||||
EVP_PKEY_DH,
|
||||
|
@ -632,6 +663,323 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth =
|
|||
0,
|
||||
|
||||
int_dh_free,
|
||||
0
|
||||
dh_pkey_ctrl
|
||||
};
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
|
||||
X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
|
||||
{
|
||||
ASN1_OBJECT *aoid;
|
||||
int atype;
|
||||
void *aval;
|
||||
ASN1_INTEGER *public_key;
|
||||
int rv = 0;
|
||||
EVP_PKEY *pkpeer = NULL, *pk = NULL;
|
||||
DH *dhpeer = NULL;
|
||||
const unsigned char *p;
|
||||
int plen;
|
||||
X509_ALGOR_get0(&aoid, &atype, &aval, alg);
|
||||
if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
|
||||
goto err;
|
||||
/* Only absent parameters allowed in RFC XXXX */
|
||||
if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
|
||||
goto err;
|
||||
|
||||
pk = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (!pk)
|
||||
goto err;
|
||||
if (pk->type != EVP_PKEY_DHX)
|
||||
goto err;
|
||||
/* Get parameters from parent key */
|
||||
dhpeer = DHparams_dup(pk->pkey.dh);
|
||||
/* We have parameters now set public key */
|
||||
plen = ASN1_STRING_length(pubkey);
|
||||
p = ASN1_STRING_data(pubkey);
|
||||
if (!p || !plen)
|
||||
goto err;
|
||||
|
||||
if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, plen)))
|
||||
{
|
||||
DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We have parameters now set public key */
|
||||
if (!(dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
|
||||
{
|
||||
DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkpeer = EVP_PKEY_new();
|
||||
if (!pkpeer)
|
||||
goto err;
|
||||
EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer);
|
||||
dhpeer = NULL;
|
||||
if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
|
||||
rv = 1;
|
||||
err:
|
||||
if (public_key)
|
||||
ASN1_INTEGER_free(public_key);
|
||||
if (pkpeer)
|
||||
EVP_PKEY_free(pkpeer);
|
||||
if (dhpeer)
|
||||
DH_free(dhpeer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
X509_ALGOR *alg, *kekalg = NULL;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
const unsigned char *p;
|
||||
unsigned char *dukm = NULL;
|
||||
size_t dukmlen;
|
||||
int keylen, plen;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
EVP_CIPHER_CTX *kekctx;
|
||||
|
||||
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
|
||||
goto err;
|
||||
|
||||
/* For DH we only have one OID permissible. If ever any more get
|
||||
* defined we will need something cleverer.
|
||||
*/
|
||||
if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH)
|
||||
{
|
||||
DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
|
||||
goto err;
|
||||
|
||||
if (alg->parameter->type != V_ASN1_SEQUENCE)
|
||||
goto err;
|
||||
|
||||
p = alg->parameter->value.sequence->data;
|
||||
plen = alg->parameter->value.sequence->length;
|
||||
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
|
||||
if (!kekalg)
|
||||
goto err;
|
||||
kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
if (!kekctx)
|
||||
goto err;
|
||||
kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
|
||||
if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
|
||||
goto err;
|
||||
if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
|
||||
goto err;
|
||||
if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
|
||||
goto err;
|
||||
|
||||
keylen = EVP_CIPHER_CTX_key_length(kekctx);
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
|
||||
goto err;
|
||||
/* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
|
||||
if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
|
||||
OBJ_nid2obj(EVP_CIPHER_type(kekcipher))) <= 0)
|
||||
goto err;
|
||||
|
||||
if (ukm)
|
||||
{
|
||||
dukmlen = ASN1_STRING_length(ukm);
|
||||
dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
|
||||
if (!dukm)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
|
||||
goto err;
|
||||
dukm = NULL;
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
if (kekalg)
|
||||
X509_ALGOR_free(kekalg);
|
||||
if (dukm)
|
||||
OPENSSL_free(dukm);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int dh_cms_decrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pctx)
|
||||
return 0;
|
||||
/* See if we need to set peer key */
|
||||
if (!EVP_PKEY_CTX_get0_peerkey(pctx))
|
||||
{
|
||||
X509_ALGOR *alg;
|
||||
ASN1_BIT_STRING *pubkey;
|
||||
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
|
||||
NULL, NULL, NULL))
|
||||
return 0;
|
||||
if (!alg || !pubkey)
|
||||
return 0;
|
||||
if (!dh_cms_set_peerkey(pctx, alg, pubkey))
|
||||
{
|
||||
DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Set DH derivation parameters and initialise unwrap context */
|
||||
if (!dh_cms_set_shared_info(pctx, ri))
|
||||
{
|
||||
DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dh_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
EVP_PKEY *pkey;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int keylen;
|
||||
X509_ALGOR *talg, *wrap_alg = NULL;
|
||||
ASN1_OBJECT *aoid;
|
||||
ASN1_BIT_STRING *pubkey;
|
||||
ASN1_STRING *wrap_str;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
unsigned char *penc = NULL, *dukm = NULL;
|
||||
int penclen;
|
||||
size_t dukmlen;
|
||||
int rv = 0;
|
||||
int kdf_type, wrap_nid;
|
||||
const EVP_MD *kdf_md;
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pctx)
|
||||
return 0;
|
||||
/* Get ephemeral key */
|
||||
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
|
||||
NULL, NULL, NULL))
|
||||
goto err;
|
||||
X509_ALGOR_get0(&aoid, NULL, NULL, talg);
|
||||
/* Is everything uninitialised? */
|
||||
if (aoid == OBJ_nid2obj(NID_undef))
|
||||
{
|
||||
ASN1_INTEGER *pubk;
|
||||
pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
|
||||
if (!pubk)
|
||||
goto err;
|
||||
/* Set the key */
|
||||
|
||||
penclen = i2d_ASN1_INTEGER(pubk, &penc);
|
||||
ASN1_INTEGER_free(pubk);
|
||||
if (penclen <= 0)
|
||||
goto err;
|
||||
ASN1_STRING_set0(pubkey, penc, penclen);
|
||||
pubkey->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
|
||||
pubkey->flags|=ASN1_STRING_FLAG_BITS_LEFT;
|
||||
|
||||
penc = NULL;
|
||||
X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
|
||||
V_ASN1_UNDEF, NULL);
|
||||
}
|
||||
|
||||
/* See if custom paraneters set */
|
||||
kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
|
||||
if (kdf_type <= 0)
|
||||
goto err;
|
||||
if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
|
||||
goto err;
|
||||
|
||||
if (kdf_type == EVP_PKEY_DH_KDF_NONE)
|
||||
{
|
||||
kdf_type = EVP_PKEY_DH_KDF_X9_42;
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
|
||||
goto err;
|
||||
}
|
||||
else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
|
||||
/* Unknown KDF */
|
||||
goto err;
|
||||
if (kdf_md == NULL)
|
||||
{
|
||||
/* Only SHA1 supported */
|
||||
kdf_md = EVP_sha1();
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
|
||||
goto err;
|
||||
}
|
||||
else if (EVP_MD_type(kdf_md) != NID_sha1)
|
||||
/* Unsupported digest */
|
||||
goto err;
|
||||
|
||||
if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
|
||||
goto err;
|
||||
|
||||
/* Get wrap NID */
|
||||
ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
wrap_nid = EVP_CIPHER_CTX_type(ctx);
|
||||
if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
|
||||
goto err;
|
||||
keylen = EVP_CIPHER_CTX_key_length(ctx);
|
||||
|
||||
/* Package wrap algorithm in an AlgorithmIdentifier */
|
||||
|
||||
wrap_alg = X509_ALGOR_new();
|
||||
if (!wrap_alg)
|
||||
goto err;
|
||||
wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
|
||||
wrap_alg->parameter = ASN1_TYPE_new();
|
||||
if (!wrap_alg->parameter)
|
||||
goto err;
|
||||
if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
|
||||
goto err;
|
||||
if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef)
|
||||
{
|
||||
ASN1_TYPE_free(wrap_alg->parameter);
|
||||
wrap_alg->parameter = NULL;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (ukm)
|
||||
{
|
||||
dukmlen = ASN1_STRING_length(ukm);
|
||||
dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
|
||||
if (!dukm)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
|
||||
goto err;
|
||||
dukm = NULL;
|
||||
|
||||
/* Now need to wrap encoding of wrap AlgorithmIdentifier into
|
||||
* parameter of another AlgorithmIdentifier.
|
||||
*/
|
||||
penc = NULL;
|
||||
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
|
||||
if (!penc || !penclen)
|
||||
goto err;
|
||||
wrap_str = ASN1_STRING_new();
|
||||
if (!wrap_str)
|
||||
goto err;
|
||||
ASN1_STRING_set0(wrap_str, penc, penclen);
|
||||
penc = NULL;
|
||||
X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
|
||||
V_ASN1_SEQUENCE, wrap_str);
|
||||
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
if (penc)
|
||||
OPENSSL_free(penc);
|
||||
if (wrap_alg)
|
||||
X509_ALGOR_free(wrap_alg);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* crypto/dh/dh_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1999-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
|
||||
|
@ -73,6 +73,9 @@ static ERR_STRING_DATA DH_str_functs[]=
|
|||
{ERR_FUNC(DH_F_COMPUTE_KEY), "COMPUTE_KEY"},
|
||||
{ERR_FUNC(DH_F_DHPARAMS_PRINT_FP), "DHparams_print_fp"},
|
||||
{ERR_FUNC(DH_F_DH_BUILTIN_GENPARAMS), "DH_BUILTIN_GENPARAMS"},
|
||||
{ERR_FUNC(DH_F_DH_CMS_DECRYPT), "DH_CMS_DECRYPT"},
|
||||
{ERR_FUNC(DH_F_DH_CMS_SET_PEERKEY), "DH_CMS_SET_PEERKEY"},
|
||||
{ERR_FUNC(DH_F_DH_CMS_SET_SHARED_INFO), "DH_CMS_SET_SHARED_INFO"},
|
||||
{ERR_FUNC(DH_F_DH_COMPUTE_KEY), "DH_compute_key"},
|
||||
{ERR_FUNC(DH_F_DH_GENERATE_KEY), "DH_generate_key"},
|
||||
{ERR_FUNC(DH_F_DH_GENERATE_PARAMETERS_EX), "DH_generate_parameters_ex"},
|
||||
|
@ -97,6 +100,7 @@ static ERR_STRING_DATA DH_str_reasons[]=
|
|||
{ERR_REASON(DH_R_BN_ERROR) ,"bn error"},
|
||||
{ERR_REASON(DH_R_DECODE_ERROR) ,"decode error"},
|
||||
{ERR_REASON(DH_R_INVALID_PUBKEY) ,"invalid public key"},
|
||||
{ERR_REASON(DH_R_KDF_PARAMETER_ERROR) ,"kdf parameter error"},
|
||||
{ERR_REASON(DH_R_KEYS_NOT_SET) ,"keys not set"},
|
||||
{ERR_REASON(DH_R_KEY_SIZE_TOO_SMALL) ,"key size too small"},
|
||||
{ERR_REASON(DH_R_MODULUS_TOO_LARGE) ,"modulus too large"},
|
||||
|
@ -104,6 +108,8 @@ static ERR_STRING_DATA DH_str_reasons[]=
|
|||
{ERR_REASON(DH_R_NO_PARAMETERS_SET) ,"no parameters set"},
|
||||
{ERR_REASON(DH_R_NO_PRIVATE_VALUE) ,"no private value"},
|
||||
{ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
|
||||
{ERR_REASON(DH_R_PEER_KEY_ERROR) ,"peer key error"},
|
||||
{ERR_REASON(DH_R_SHARED_INFO_ERROR) ,"shared info error"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#ifndef OPENSSL_NO_DSA
|
||||
#include <openssl/dsa.h>
|
||||
#endif
|
||||
#include <openssl/objects.h>
|
||||
#include "evp_locl.h"
|
||||
|
||||
/* DH pkey context structure */
|
||||
|
@ -76,11 +77,22 @@ typedef struct
|
|||
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];
|
||||
/* message digest */
|
||||
/* 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)
|
||||
|
@ -96,6 +108,13 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
|
|||
dctx->md = NULL;
|
||||
dctx->rfc5114_param = 0;
|
||||
|
||||
dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
|
||||
dctx->kdf_oid = NULL;
|
||||
dctx->kdf_md = NULL;
|
||||
dctx->kdf_ukm = NULL;
|
||||
dctx->kdf_ukmlen = 0;
|
||||
dctx->kdf_outlen = 0;
|
||||
|
||||
ctx->data = dctx;
|
||||
ctx->keygen_info = dctx->gentmp;
|
||||
ctx->keygen_info_count = 2;
|
||||
|
@ -116,6 +135,18 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
|||
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 = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
|
||||
dctx->kdf_ukmlen = sctx->kdf_ukmlen;
|
||||
}
|
||||
dctx->kdf_outlen = sctx->kdf_outlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -123,7 +154,13 @@ static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
|
|||
{
|
||||
DH_PKEY_CTX *dctx = ctx->data;
|
||||
if (dctx)
|
||||
{
|
||||
if (dctx->kdf_ukm)
|
||||
OPENSSL_free(dctx->kdf_ukm);
|
||||
if (dctx->kdf_oid)
|
||||
ASN1_OBJECT_free(dctx->kdf_oid);
|
||||
OPENSSL_free(dctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
|
@ -170,6 +207,57 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|||
/* Default behaviour is OK */
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_DH_KDF_TYPE:
|
||||
if (p1 == -2)
|
||||
return dctx->kdf_type;
|
||||
if (p1 != EVP_PKEY_DH_KDF_NONE &&
|
||||
p1 != EVP_PKEY_DH_KDF_X9_42)
|
||||
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:
|
||||
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_DH_KDF_UKM:
|
||||
*(unsigned char **)p2 = dctx->kdf_ukm;
|
||||
return dctx->kdf_ukmlen;
|
||||
|
||||
case EVP_PKEY_CTRL_DH_KDF_OID:
|
||||
if (dctx->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;
|
||||
|
||||
|
@ -356,23 +444,68 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
|||
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;
|
||||
}
|
||||
ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
|
||||
ctx->pkey->pkey.dh);
|
||||
if (ret < 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;
|
||||
}
|
||||
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 (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:
|
||||
if (Z)
|
||||
{
|
||||
OPENSSL_cleanse(Z, Zlen);
|
||||
OPENSSL_free(Z);
|
||||
}
|
||||
return ret;
|
||||
*keylen = ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD dh_pkey_meth =
|
||||
{
|
||||
EVP_PKEY_DH,
|
||||
EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
0,
|
||||
pkey_dh_init,
|
||||
pkey_dh_copy,
|
||||
pkey_dh_cleanup,
|
||||
|
@ -408,7 +541,7 @@ const EVP_PKEY_METHOD dh_pkey_meth =
|
|||
const EVP_PKEY_METHOD dhx_pkey_meth =
|
||||
{
|
||||
EVP_PKEY_DHX,
|
||||
EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
0,
|
||||
pkey_dh_init,
|
||||
pkey_dh_copy,
|
||||
pkey_dh_cleanup,
|
||||
|
|
Loading…
Reference in a new issue