Skip to content

Commit

Permalink
CMS and PKCS7: add support for EdDSA with Edwards curves 25519 and 44…
Browse files Browse the repository at this point in the history
…8, simplifying code

fixes openssl#11915

fixes openssl#13523
  • Loading branch information
DDvO committed Oct 13, 2023
1 parent 729840d commit b3a3c80
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 151 deletions.
187 changes: 129 additions & 58 deletions crypto/cms/cms_sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
return -1;
}

/* Method to map any, incl. provider-implemented PKEY types to OIDs */
/* Method to map any (also provider-implemented) PKEY types to OIDs */
/* (EC)DSA and all provider-delivered signatures implementation is the same */
static int cms_generic_sign(CMS_SignerInfo *si, int verify)
{
Expand All @@ -234,23 +234,31 @@ static int cms_generic_sign(CMS_SignerInfo *si, int verify)

if (!verify) {
EVP_PKEY *pkey = si->pkey;
int snid, hnid, pknid = EVP_PKEY_get_id(pkey);
int snid, pknid = EVP_PKEY_get_id(pkey);
X509_ALGOR *alg1, *alg2;

CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2);
if (alg1 == NULL || alg1->algorithm == NULL)
return -1;
hnid = OBJ_obj2nid(alg1->algorithm);
if (hnid == NID_undef)
return -1;
if (pknid <= 0) { /* check whether a provider registered a NID */
const char *typename = EVP_PKEY_get0_type_name(pkey);

if (typename != NULL)
pknid = OBJ_txt2nid(typename);
if (pknid == NID_ED25519 || pknid == NID_ED448) {
/* special treatment for Edwards curves in CMS acc. to RFC 8419 */
snid = pknid;
} else {
int hnid = OBJ_obj2nid(alg1->algorithm);

if (hnid == NID_undef)
return -1;
if (pknid <= 0) { /* check whether a provider registered a NID */
const char *typename = EVP_PKEY_get0_type_name(pkey);

if (typename != NULL)
pknid = OBJ_txt2nid(typename);
}

if (!OBJ_find_sigid_by_algs(&snid, hnid, pknid))
return -1;
}
if (!OBJ_find_sigid_by_algs(&snid, hnid, pknid))
return -1;
return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL);
}
return 1;
Expand Down Expand Up @@ -331,6 +339,26 @@ static int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si,
return ret;
}

/* this is also used for PKCS7 */
const EVP_MD *ossl_cms_get_default_digest(EVP_PKEY *pkey) {
const EVP_MD *md;
int def_nid, pknid = EVP_PKEY_get_id(pkey);

/* special cases first, for Edwards curves in CMS according to RFC 8419 */
if (pknid == NID_ED25519)
def_nid = NID_sha3_512;
else if (pknid == NID_ED448)
def_nid = NID_shake256; /* TODO for CMS, output size MUST be 512 */
else if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
return NULL;
}
md = EVP_get_digestbynid(def_nid);
if (md == NULL)
ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
return md;
}

CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
unsigned int flags)
Expand Down Expand Up @@ -383,18 +411,8 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
if (!ossl_cms_set1_SignerIdentifier(si->sid, signer, type, ctx))
goto err;

if (md == NULL) {
int def_nid;

if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
goto err;
md = EVP_get_digestbynid(def_nid);
if (md == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
goto err;
}
}

if (md == NULL && (md = ossl_cms_get_default_digest(pk)) == NULL)
goto err;
X509_ALGOR_set_md(si->digestAlgorithm, md);

/* See if digest is present in digestAlgorithms */
Expand Down Expand Up @@ -759,7 +777,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
md = computed_md;
}
siglen = EVP_PKEY_get_size(si->pkey);
sig = OPENSSL_malloc(siglen);
sig = OPENSSL_malloc(siglen+64 /* workaround */);
if (sig == NULL)
goto err;
if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
Expand Down Expand Up @@ -818,31 +836,40 @@ int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain,

int CMS_SignerInfo_sign(CMS_SignerInfo *si)
{
#if 0
EVP_MD_CTX *mctx = si->mctx;
EVP_PKEY_CTX *pctx = NULL;
unsigned char *abuf = NULL;
int alen;
size_t siglen;
const CMS_CTX *ctx = si->cms_ctx;
char md_name[OSSL_MAX_NAME_SIZE];
int pknid = EVP_PKEY_get_id(si->pkey);

if (OBJ_obj2txt(md_name, sizeof(md_name),
si->digestAlgorithm->algorithm, 0) <= 0)
if (pknid != NID_ED25519 && pknid != NID_ED448
&& OBJ_obj2txt(md_name, sizeof(md_name),
si->digestAlgorithm->algorithm, 0) <= 0)
return 0;
#else
const EVP_MD *md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
#endif

if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
if (!cms_add1_signingTime(si, NULL))
goto err;
return 0;
}

if (!ossl_cms_si_check_attributes(si))
goto err;
return 0;

#if 0
if (si->pctx) {
pctx = si->pctx;
} else {
EVP_MD_CTX_reset(mctx);
if (EVP_DigestSignInit_ex(mctx, &pctx, md_name,
if (EVP_DigestSignInit_ex(mctx, &pctx,
pknid == NID_ED25519 || pknid == NID_ED448
? NULL : md_name,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx), si->pkey,
NULL) <= 0)
Expand All @@ -854,16 +881,29 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
ASN1_ITEM_rptr(CMS_Attributes_Sign));
if (!abuf)
goto err;
if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
goto err;
if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
goto err;
if (pknid == NID_ED25519 || pknid == NID_ED448) {
if (EVP_DigestSign(mctx, NULL, &siglen, abuf, alen) != 1)
goto err;
printf("DigestSign1 siglen=%zd\n", siglen);
siglen += 512 / 8; /* workaround */
printf("DigestSign2 siglen=%zd\n", siglen);
} else {
if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
goto err;
if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
goto err;
}
OPENSSL_free(abuf);
abuf = OPENSSL_malloc(siglen);
printf("DigestSign3 siglen for alloc=%zd\n", siglen);
abuf = OPENSSL_malloc(siglen+0*32 /* workaround */);
if (abuf == NULL)
goto err;
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
if ((pknid == NID_ED25519 || pknid == NID_ED448
? EVP_DigestSign(mctx, abuf, &siglen, abuf, alen)
: EVP_DigestSignFinal(mctx, abuf, &siglen))
<= 0)
goto err;
printf("DigestSign4 siglen output=%zd\n", siglen);

EVP_MD_CTX_reset(mctx);

Expand All @@ -875,20 +915,30 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
OPENSSL_free(abuf);
EVP_MD_CTX_reset(mctx);
return 0;
#else
return ASN1_item_sign_ex(ASN1_ITEM_rptr(CMS_Attributes_Sign), NULL,
NULL, si->signature /* sets the ASN1_BIT_STRING */,
si->signedAttrs, NULL, si->pkey, md,
ossl_cms_ctx_get0_libctx(si->cms_ctx),
ossl_cms_ctx_get0_propq(si->cms_ctx));

#endif
}

int CMS_SignerInfo_verify(CMS_SignerInfo *si)
{
#if 0
EVP_MD_CTX *mctx = NULL;
unsigned char *abuf = NULL;
int alen, r = -1;
char name[OSSL_MAX_NAME_SIZE];
const EVP_MD *md;
int pknid;
const EVP_MD *md = NULL;
EVP_MD *fetched_md = NULL;
const CMS_CTX *ctx = si->cms_ctx;
OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
const char *propq = ossl_cms_ctx_get0_propq(ctx);

#endif
if (si->pkey == NULL) {
ERR_raise(ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY);
return -1;
Expand All @@ -897,21 +947,27 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
if (!ossl_cms_si_check_attributes(si))
return -1;

OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0);
#if 0
pknid = EVP_PKEY_get_id(si->pkey);
if (pknid != NID_ED25519 && pknid != NID_ED448) {
char name[OSSL_MAX_NAME_SIZE];

(void)ERR_set_mark();
fetched_md = EVP_MD_fetch(libctx, name, propq);
OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0);

if (fetched_md != NULL)
md = fetched_md;
else
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
return -1;
(void)ERR_set_mark();
fetched_md = EVP_MD_fetch(libctx, name, propq);

if (fetched_md != NULL)
md = fetched_md;
else
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
return -1;
}
(void)ERR_pop_to_mark();
}
(void)ERR_pop_to_mark();

if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
Expand All @@ -921,28 +977,43 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
propq, si->pkey, NULL) <= 0)
goto err;


#endif
if (!cms_sd_asn1_ctrl(si, 1))
goto err;
return 0;

#if 0
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
ASN1_ITEM_rptr(CMS_Attributes_Verify));
if (abuf == NULL || alen < 0)
goto err;
r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
OPENSSL_free(abuf);
if (r <= 0) {
r = -1;
goto err;
if (pknid == NID_ED25519 || pknid == NID_ED448) {
r = EVP_DigestVerify(mctx, si->signature->data, si->signature->length,
abuf, alen) == 1;
printf("verify siglen=%d\n", si->signature->length);

} else {
r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
OPENSSL_free(abuf);
if (r <= 0) {
r = -1;
goto err;
}
r = EVP_DigestVerifyFinal(mctx,
si->signature->data, si->signature->length);
}
r = EVP_DigestVerifyFinal(mctx,
si->signature->data, si->signature->length);
if (r <= 0)
ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
err:
EVP_MD_free(fetched_md);
EVP_MD_CTX_reset(mctx);
return r;
#endif
return ASN1_item_verify_ex(ASN1_ITEM_rptr(CMS_Attributes_Sign),
si->signatureAlgorithm, si->signature,
si->signedAttrs, NULL, si->pkey,
ossl_cms_ctx_get0_libctx(si->cms_ctx),
ossl_cms_ctx_get0_propq(si->cms_ctx));
}

/* Create a chain of digest BIOs from a CMS ContentInfo */
Expand Down
Loading

0 comments on commit b3a3c80

Please sign in to comment.