diff options
author | tb <> | 2024-03-29 06:41:58 +0000 |
---|---|---|
committer | tb <> | 2024-03-29 06:41:58 +0000 |
commit | 207bd9bb06ecc406c0e992892c96391e5f299077 (patch) | |
tree | 9e3cf5441b7d3f91c3005a042dbb01a1c6413df4 /src/lib/libcrypto/cms/cms_sd.c | |
parent | 5d94d0325a5b03c1ba85b2e0d51af503a072cc2a (diff) | |
download | openbsd-207bd9bb06ecc406c0e992892c96391e5f299077.tar.gz openbsd-207bd9bb06ecc406c0e992892c96391e5f299077.tar.bz2 openbsd-207bd9bb06ecc406c0e992892c96391e5f299077.zip |
Implement Ed25519 signatures for CMS (RFC 8419)
This adds support for Edwards curve digital signature algorithms in the
cryptographic message syntax, as specified in RFC 8419. Only Ed25519 is
supported since that is the only EdDSA algorithm that LibreSSL supports
(this is unlikely to change ever, but, as they say - never is a very
long time).
This has the usual curly interactions between EVP and CMS with poorly
documented interfaces and lots of confusing magic return values and
controls. This improves upon existing control handlers by documenting
what is being done and why. Unlike other (draft) implementations we
also happen to use the correct hashing algorithm.
There are no plans to implement RFC 8418.
joint work with job at p2k23
ok jsing
Diffstat (limited to 'src/lib/libcrypto/cms/cms_sd.c')
-rw-r--r-- | src/lib/libcrypto/cms/cms_sd.c | 84 |
1 files changed, 64 insertions, 20 deletions
diff --git a/src/lib/libcrypto/cms/cms_sd.c b/src/lib/libcrypto/cms/cms_sd.c index b644717bbb..5a38bf59aa 100644 --- a/src/lib/libcrypto/cms/cms_sd.c +++ b/src/lib/libcrypto/cms/cms_sd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cms_sd.c,v 1.30 2024/02/02 14:13:11 tb Exp $ */ | 1 | /* $OpenBSD: cms_sd.c,v 1.31 2024/03/29 06:41:58 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
4 | * project. | 4 | * project. |
@@ -277,6 +277,64 @@ cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) | |||
277 | return 1; | 277 | return 1; |
278 | } | 278 | } |
279 | 279 | ||
280 | static const EVP_MD * | ||
281 | cms_SignerInfo_default_digest_md(const CMS_SignerInfo *si) | ||
282 | { | ||
283 | int rv, nid; | ||
284 | |||
285 | if (si->pkey == NULL) { | ||
286 | CMSerror(CMS_R_NO_PUBLIC_KEY); | ||
287 | return NULL; | ||
288 | } | ||
289 | |||
290 | /* On failure or unsupported operation, give up. */ | ||
291 | if ((rv = EVP_PKEY_get_default_digest_nid(si->pkey, &nid)) <= 0) | ||
292 | return NULL; | ||
293 | if (rv > 2) | ||
294 | return NULL; | ||
295 | |||
296 | /* | ||
297 | * XXX - we need to identify EdDSA in a better way. Figure out where | ||
298 | * and how. This mimics EdDSA checks in openssl/ca.c and openssl/req.c. | ||
299 | */ | ||
300 | |||
301 | /* The digest md is required to be EVP_sha512() (EdDSA). */ | ||
302 | if (rv == 2 && nid == NID_undef) | ||
303 | return EVP_sha512(); | ||
304 | |||
305 | /* Use mandatory or default digest. */ | ||
306 | return EVP_get_digestbynid(nid); | ||
307 | } | ||
308 | |||
309 | static const EVP_MD * | ||
310 | cms_SignerInfo_signature_md(const CMS_SignerInfo *si) | ||
311 | { | ||
312 | int rv, nid; | ||
313 | |||
314 | if (si->pkey == NULL) { | ||
315 | CMSerror(CMS_R_NO_PUBLIC_KEY); | ||
316 | return NULL; | ||
317 | } | ||
318 | |||
319 | /* Fall back to digestAlgorithm unless pkey has a mandatory digest. */ | ||
320 | if ((rv = EVP_PKEY_get_default_digest_nid(si->pkey, &nid)) <= 1) | ||
321 | return EVP_get_digestbyobj(si->digestAlgorithm->algorithm); | ||
322 | if (rv > 2) | ||
323 | return NULL; | ||
324 | |||
325 | /* | ||
326 | * XXX - we need to identify EdDSA in a better way. Figure out where | ||
327 | * and how. This mimics EdDSA checks in openssl/ca.c and openssl/req.c. | ||
328 | */ | ||
329 | |||
330 | /* The signature md is required to be EVP_md_null() (EdDSA). */ | ||
331 | if (nid == NID_undef) | ||
332 | return EVP_md_null(); | ||
333 | |||
334 | /* Use mandatory digest. */ | ||
335 | return EVP_get_digestbynid(nid); | ||
336 | } | ||
337 | |||
280 | CMS_SignerInfo * | 338 | CMS_SignerInfo * |
281 | CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, | 339 | CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, |
282 | const EVP_MD *md, unsigned int flags) | 340 | const EVP_MD *md, unsigned int flags) |
@@ -325,19 +383,10 @@ CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, | |||
325 | if (!cms_set1_SignerIdentifier(si->sid, signer, type)) | 383 | if (!cms_set1_SignerIdentifier(si->sid, signer, type)) |
326 | goto err; | 384 | goto err; |
327 | 385 | ||
386 | if (md == NULL) | ||
387 | md = cms_SignerInfo_default_digest_md(si); | ||
328 | if (md == NULL) { | 388 | if (md == NULL) { |
329 | int def_nid; | 389 | CMSerror(CMS_R_NO_DEFAULT_DIGEST); |
330 | if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) | ||
331 | goto err; | ||
332 | md = EVP_get_digestbynid(def_nid); | ||
333 | if (md == NULL) { | ||
334 | CMSerror(CMS_R_NO_DEFAULT_DIGEST); | ||
335 | goto err; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | if (!md) { | ||
340 | CMSerror(CMS_R_NO_DIGEST_SET); | ||
341 | goto err; | 390 | goto err; |
342 | } | 391 | } |
343 | 392 | ||
@@ -735,7 +784,7 @@ CMS_SignerInfo_sign(CMS_SignerInfo *si) | |||
735 | size_t sig_len = 0; | 784 | size_t sig_len = 0; |
736 | int ret = 0; | 785 | int ret = 0; |
737 | 786 | ||
738 | if ((md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)) == NULL) | 787 | if ((md = cms_SignerInfo_signature_md(si)) == NULL) |
739 | goto err; | 788 | goto err; |
740 | 789 | ||
741 | if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { | 790 | if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { |
@@ -795,14 +844,9 @@ CMS_SignerInfo_verify(CMS_SignerInfo *si) | |||
795 | int buf_len = 0; | 844 | int buf_len = 0; |
796 | int ret = -1; | 845 | int ret = -1; |
797 | 846 | ||
798 | if ((md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)) == NULL) | 847 | if ((md = cms_SignerInfo_signature_md(si)) == NULL) |
799 | goto err; | 848 | goto err; |
800 | 849 | ||
801 | if (si->pkey == NULL) { | ||
802 | CMSerror(CMS_R_NO_PUBLIC_KEY); | ||
803 | goto err; | ||
804 | } | ||
805 | |||
806 | if (si->mctx == NULL) | 850 | if (si->mctx == NULL) |
807 | si->mctx = EVP_MD_CTX_new(); | 851 | si->mctx = EVP_MD_CTX_new(); |
808 | if (si->mctx == NULL) { | 852 | if (si->mctx == NULL) { |