summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2024-03-29 06:41:58 +0000
committertb <>2024-03-29 06:41:58 +0000
commitba67e7951125ac5d622f4ac87f8bd3dcb50690aa (patch)
tree9e3cf5441b7d3f91c3005a042dbb01a1c6413df4
parent646ebf1438fc66591f5d7b009fb80de96daa7d8f (diff)
downloadopenbsd-ba67e7951125ac5d622f4ac87f8bd3dcb50690aa.tar.gz
openbsd-ba67e7951125ac5d622f4ac87f8bd3dcb50690aa.tar.bz2
openbsd-ba67e7951125ac5d622f4ac87f8bd3dcb50690aa.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
-rw-r--r--src/lib/libcrypto/cms/cms_sd.c84
-rw-r--r--src/lib/libcrypto/ec/ecx_methods.c63
2 files changed, 126 insertions, 21 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
280static const EVP_MD *
281cms_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
309static const EVP_MD *
310cms_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
280CMS_SignerInfo * 338CMS_SignerInfo *
281CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, 339CMS_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) {
diff --git a/src/lib/libcrypto/ec/ecx_methods.c b/src/lib/libcrypto/ec/ecx_methods.c
index cd512a447f..ab299a8d6b 100644
--- a/src/lib/libcrypto/ec/ecx_methods.c
+++ b/src/lib/libcrypto/ec/ecx_methods.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecx_methods.c,v 1.11 2024/01/04 17:01:26 tb Exp $ */ 1/* $OpenBSD: ecx_methods.c,v 1.12 2024/03/29 06:41:58 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -17,6 +17,7 @@
17 17
18#include <string.h> 18#include <string.h>
19 19
20#include <openssl/cms.h>
20#include <openssl/curve25519.h> 21#include <openssl/curve25519.h>
21#include <openssl/ec.h> 22#include <openssl/ec.h>
22#include <openssl/err.h> 23#include <openssl/err.h>
@@ -530,10 +531,67 @@ ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
530 return -2; 531 return -2;
531} 532}
532 533
534#ifndef OPENSSL_NO_CMS
535static int
536ecx_cms_sign_or_verify(EVP_PKEY *pkey, long verify, CMS_SignerInfo *si)
537{
538 X509_ALGOR *digestAlgorithm, *signatureAlgorithm;
539 ASN1_OBJECT *aobj;
540
541 if (verify != 0 && verify != 1)
542 return -1;
543
544 /* Check that we have an Ed25519 public key. */
545 if (EVP_PKEY_id(pkey) != NID_ED25519)
546 return -1;
547
548 CMS_SignerInfo_get0_algs(si, NULL, NULL, &digestAlgorithm,
549 &signatureAlgorithm);
550
551 /* RFC 8419, section 2.3: digestAlgorithm MUST be SHA-512. */
552 if (digestAlgorithm == NULL)
553 return -1;
554 if (OBJ_obj2nid(digestAlgorithm->algorithm) != NID_sha512)
555 return -1;
556
557 /*
558 * RFC 8419, section 2.4: signatureAlgorithm MUST be Ed25519, and the
559 * parameters MUST be absent. For verification check that this is the
560 * case, for signing set the signatureAlgorithm accordingly.
561 */
562 if (verify) {
563 const ASN1_OBJECT *obj;
564 int param_type;
565
566 if (signatureAlgorithm == NULL)
567 return -1;
568
569 X509_ALGOR_get0(&obj, &param_type, NULL, signatureAlgorithm);
570 if (OBJ_obj2nid(obj) != NID_ED25519)
571 return -1;
572 if (param_type != V_ASN1_UNDEF)
573 return -1;
574
575 return 1;
576 }
577
578 if ((aobj = OBJ_nid2obj(NID_ED25519)) == NULL)
579 return -1;
580 if (!X509_ALGOR_set0(signatureAlgorithm, aobj, V_ASN1_UNDEF, NULL))
581 return -1;
582
583 return 1;
584}
585#endif
586
533static int 587static int
534ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) 588ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
535{ 589{
536 switch (op) { 590 switch (op) {
591#ifndef OPENSSL_NO_CMS
592 case ASN1_PKEY_CTRL_CMS_SIGN:
593 return ecx_cms_sign_or_verify(pkey, arg1, arg2);
594#endif
537 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 595 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
538 /* PureEdDSA does its own hashing. */ 596 /* PureEdDSA does its own hashing. */
539 *(int *)arg2 = NID_undef; 597 *(int *)arg2 = NID_undef;
@@ -806,6 +864,9 @@ pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
806 } 864 }
807 return 1; 865 return 1;
808 866
867#ifndef OPENSSL_NO_CMS
868 case EVP_PKEY_CTRL_CMS_SIGN:
869#endif
809 case EVP_PKEY_CTRL_DIGESTINIT: 870 case EVP_PKEY_CTRL_DIGESTINIT:
810 return 1; 871 return 1;
811 } 872 }