summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2022-09-05 18:09:29 +0200
committerGuix Patches Tester <>2022-09-05 17:14:12 +0100
commit49b7a90045a6067926ebc6169c4c208c006ba32d (patch)
tree7f4fa434847ccf07ac3197dcbe7f53d704f2c9d7
parentaae98c297214f87eb45302863adb021078c41a6f (diff)
downloadguix-patches-49b7a90045a6067926ebc6169c4c208c006ba32d.tar
guix-patches-49b7a90045a6067926ebc6169c4c208c006ba32d.tar.gz
openpgp: Add support for ECDSA with NIST curves.
Fixes <https://issues.guix.gnu.org/57576>. Reported by Zhu Zihao <all_but_last@163.com>. * guix/openpgp.scm (verify-openpgp-signature): Add case for ecdsa. (get-signature): Likewise for PUBLIC-KEY-ECDSA. (get-public-key): Likewise. * tests/keys/secp384.pub, tests/keys/secp384.sec, tests/keys/secp521.pub, tests/keys/secp521.sec: New files. * Makefile.am (EXTRA_DIST): Add them. * tests/openpgp.scm (%secp384-key-id, %secp384-key-fingerprint) (%hello-signature/secp384/sha384) (%secp521-key-id, %secp521-key-fingerprint) (%hello-signature/secp521/sha521): New variables. * tests/openpgp.scm ("get-openpgp-detached-signature/ascii") ("verify-openpgp-signature, good signatures") ("verify-openpgp-signature, bad signature"): Check with the secp384 and secp521 curves.
-rw-r--r--Makefile.am4
-rw-r--r--guix/openpgp.scm41
-rw-r--r--tests/keys/secp384.pub11
-rw-r--r--tests/keys/secp384.sec12
-rw-r--r--tests/keys/secp521.pub13
-rw-r--r--tests/keys/secp521.sec14
-rw-r--r--tests/openpgp.scm66
7 files changed, 143 insertions, 18 deletions
diff --git a/Makefile.am b/Makefile.am
index a0c4e941c1..71c3bd4a98 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -702,6 +702,10 @@ EXTRA_DIST += \
tests/keys/ed25519-2.sec \
tests/keys/ed25519-3.pub \
tests/keys/ed25519-3.sec \
+ tests/keys/secp384.pub \
+ tests/keys/secp384.sec \
+ tests/keys/secp521.pub \
+ tests/keys/secp521.sec \
build-aux/config.rpath \
bootstrap \
doc/build.scm \
diff --git a/guix/openpgp.scm b/guix/openpgp.scm
index 9de7feb644..b999c30474 100644
--- a/guix/openpgp.scm
+++ b/guix/openpgp.scm
@@ -1,6 +1,6 @@
;; -*- mode: scheme; coding: utf-8 -*-
;; Copyright © 2010, 2012 Göran Weinholt <goran@weinholt.se>
-;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
+;; Copyright © 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;; Permission is hereby granted, free of charge, to any person obtaining a
;; copy of this software and associated documentation files (the "Software"),
@@ -290,7 +290,7 @@ hexadecimal format for fingerprints."
(define PUBLIC-KEY-ELGAMAL-ENCRYPT-ONLY 16)
(define PUBLIC-KEY-DSA 17)
(define PUBLIC-KEY-ECDH 18) ;RFC-6637
-(define PUBLIC-KEY-ECDSA 19) ;RFC-6639
+(define PUBLIC-KEY-ECDSA 19) ;RFC-6637
(define PUBLIC-KEY-ELGAMAL 20) ;encrypt + sign (legacy)
(define PUBLIC-KEY-EDDSA 22) ;"not yet assigned" says GPG
@@ -298,6 +298,7 @@ hexadecimal format for fingerprints."
(cond ((= id PUBLIC-KEY-RSA) 'rsa)
((= id PUBLIC-KEY-DSA) 'dsa)
((= id PUBLIC-KEY-ELGAMAL-ENCRYPT-ONLY) 'elgamal)
+ ((= id PUBLIC-KEY-ECDSA) 'ecdsa)
((= id PUBLIC-KEY-EDDSA) 'eddsa)
(else id)))
@@ -564,10 +565,16 @@ the issuer's OpenPGP public key extracted from KEYRING."
;; See "(gcrypt) Cryptographic Functions".
(sexp->canonical-sexp
(if (eq? key-type 'ecc)
- `(data
- (flags eddsa)
- (hash-algo sha512)
- (value ,hash))
+ (match (openpgp-signature-public-key-algorithm sig)
+ ('eddsa
+ `(data
+ (flags eddsa)
+ (hash-algo sha512)
+ (value ,hash)))
+ ('ecdsa
+ `(data
+ (hash-algo ,(openpgp-signature-hash-algorithm sig))
+ (value ,hash))))
`(data
(flags ,(match key-type
('rsa 'pkcs1)
@@ -615,7 +622,8 @@ FINGERPRINT, a bytevector."
(string->canonical-sexp
(format #f "(sig-val (dsa (r #~a#) (s #~a#)))"
(->hex r) (->hex s)))))
- ((= pkalg PUBLIC-KEY-EDDSA)
+ ((or (= pkalg PUBLIC-KEY-EDDSA)
+ (= pkalg PUBLIC-KEY-ECDSA))
(print "EdDSA signature")
(let ((r (get-mpi/bytevector p))
(s (get-mpi/bytevector p)))
@@ -630,7 +638,8 @@ FINGERPRINT, a bytevector."
str)))
(string->canonical-sexp
- (format #f "(sig-val (eddsa (r #~a#) (s #~a#)))"
+ (format #f "(sig-val (~a (r #~a#) (s #~a#)))"
+ (public-key-algorithm pkalg)
(bytevector->hex r) (bytevector->hex s)))))
(else
(list 'unsupported-algorithm
@@ -886,6 +895,22 @@ FINGERPRINT, a bytevector."
curve
(if (eq? curve 'Curve25519) 'djb-tweak 'eddsa)
(->hex q)))))
+ ((= alg PUBLIC-KEY-ECDSA)
+ (print "Public ECDSA key")
+ (let* ((len (get-u8 p))
+ (oid (bytevector->uint (get-bytevector-n p len)))
+ (q (get-mpi p)))
+ (define curve
+ ;; RFC 6637, Section 11.
+ (match oid
+ (#x2a8648ce3d030107 "NIST P-256")
+ (#x2b81040022 "NIST P-384")
+ (#x2b81040023 "NIST P-521")))
+
+ (string->canonical-sexp
+ (format #f "(public-key (ecc (curve \"~a\")(q #~a#)))"
+ curve
+ (->hex q)))))
(else
(list 'unsupported-algorithm ;FIXME: throw
(public-key-algorithm alg)
diff --git a/tests/keys/secp384.pub b/tests/keys/secp384.pub
new file mode 100644
index 0000000000..b90cf504e2
--- /dev/null
+++ b/tests/keys/secp384.pub
@@ -0,0 +1,11 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mG8EYxYF9RMFK4EEACIDAwTHYxcyBiiPz4ZZIkmXnVu0Yv9DHGrnbdCR6U/RT1S4
+wszaHdsSEHlPwmy3WGgTubBDOuJODf5kV/HLL7QEPsOTkIsObK+prEJO3CGpRVim
+a7nfVk2AH6D/GMkNacSXdwy0FTxleGFtcGxlQGV4YW1wbGUuY29tPoiwBBMTCQA4
+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEzLZ9Sx8EBzgp+PzwLydGMf8+
+bFsFAmMWB+sACgkQLydGMf8+bFuD3gF/SMEDQP3Bvu0yb8KxE6j8lhOiKT186wwG
+4hBsifRdEF+UHWEa7sx74tyc4R1B01FUAYC/4QqNup4EnPzQfSE3WyVvu+ja+xui
+3vppYCpUjkHzkATsLzsN98/nkZ3q3YA8/lo=
+=vIaC
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/keys/secp384.sec b/tests/keys/secp384.sec
new file mode 100644
index 0000000000..ae296dd9a1
--- /dev/null
+++ b/tests/keys/secp384.sec
@@ -0,0 +1,12 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lKQEYxYF9RMFK4EEACIDAwTHYxcyBiiPz4ZZIkmXnVu0Yv9DHGrnbdCR6U/RT1S4
+wszaHdsSEHlPwmy3WGgTubBDOuJODf5kV/HLL7QEPsOTkIsObK+prEJO3CGpRVim
+a7nfVk2AH6D/GMkNacSXdwwAAYC9iXZ9j+RWFB4rU103SCv6j68rS5Lmc7tHve9l
+B5nri/AR+OEJ61q+w6w0XO5GBBUYLrQVPGV4YW1wbGVAZXhhbXBsZS5jb20+iLAE
+ExMJADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTMtn1LHwQHOCn4/PAv
+J0Yx/z5sWwUCYxYH6wAKCRAvJ0Yx/z5sW4PeAX9IwQNA/cG+7TJvwrETqPyWE6Ip
+PXzrDAbiEGyJ9F0QX5QdYRruzHvi3JzhHUHTUVQBgL/hCo26ngSc/NB9ITdbJW+7
+6Nr7G6Le+mlgKlSOQfOQBOwvOw33z+eRnerdgDz+Wg==
+=B1Nl
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/keys/secp521.pub b/tests/keys/secp521.pub
new file mode 100644
index 0000000000..077e8e7df2
--- /dev/null
+++ b/tests/keys/secp521.pub
@@ -0,0 +1,13 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mJMEYxYamRMFK4EEACMEIwQB4EqA0zTAfhLeVjkNnzvTuSYs+TUlYdDaw9mYA7Gy
+AiNvxr2F1hJi88Wxxr3YNGKx9s0yJ2Vl0dHlCLmlQAFc9MMACZKWZN68mqbYfSVf
+qJxSG5F8qbF0+dGecwY+TjM4xdaUk4d0vD13/e+r/HLYNgwKrpO2SurNZX/isfkn
+rvNSHPi0HTxleGFtcGxlLXNlY3A1MjFAZXhhbXBsZS5jb20+iNoEExMKAD4WIQQ7
+r36YQGm2cfPDEWnoSxOgtOevGwUCYxYamQIbAwUJA8JnAAULCQgHAgYVCgkICwIE
+FgIDAQIeAQIXgAAKCRDoSxOgtOevG4GUAgkBN118FBDW896Iv+2U/29Fpfni4V6D
+Vp6HTE5qAqmJUtKOOSxmDAmiJ4sinybTP4YCLQT9fmMQqrJSSY0d/hVg4fYCCQGD
+Y6iRT8KPyxhlpsVVwdiUjOd4B5JUyJj0qOudY4yveyOl6c1bdxJALMbEHV4JREEE
+1+ylYN1KRfpaQh42Zoms9Q==
+=Nru3
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/keys/secp521.sec b/tests/keys/secp521.sec
new file mode 100644
index 0000000000..663dbeaa3c
--- /dev/null
+++ b/tests/keys/secp521.sec
@@ -0,0 +1,14 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lNoEYxYamRMFK4EEACMEIwQB4EqA0zTAfhLeVjkNnzvTuSYs+TUlYdDaw9mYA7Gy
+AiNvxr2F1hJi88Wxxr3YNGKx9s0yJ2Vl0dHlCLmlQAFc9MMACZKWZN68mqbYfSVf
+qJxSG5F8qbF0+dGecwY+TjM4xdaUk4d0vD13/e+r/HLYNgwKrpO2SurNZX/isfkn
+rvNSHPgAAgkBRPFeWJ3ZROkkbV7/dF8Z4LN6hlrSHWWS2sZmKxZprQy/j48eqWZz
+6eY9IvDxfP9ATpfummdgrjexVqA3o3/wr00h/LQdPGV4YW1wbGUtc2VjcDUyMUBl
+eGFtcGxlLmNvbT6I0gQTEwoAOAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYh
+BDuvfphAabZx88MRaehLE6C0568bBQJjFhroAAoJEOhLE6C0568bQl0CCNYMV2uF
+6LA4GF8RchFQee4ZZo8aquEQ7t7a6NDBc1TbVkGLR+TWxkomEytp5EUoEEU2cNtg
+TWRvti3aZvTbEMvdAgijAGTSiO3q5kjprGu1C35oc2JWj0q66XzHEJ0aEiTMQNrz
+sJReJPQRmMnBTtzjJCmNPws/VYSEs26m36QCqePtwQ==
+=/mn1
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp.scm b/tests/openpgp.scm
index 1f20466772..68439f7485 100644
--- a/tests/openpgp.scm
+++ b/tests/openpgp.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -63,7 +63,7 @@ vBSFjNSiVHsuAA==
#|
Test keys in ./tests/keys. They were generated in a container along these lines:
- guix environment -CP --ad-hoc gnupg pinentry coreutils
+ guix shell -CP-hoc gnupg pinentry coreutils
then, within the container:
mkdir ~/.gnupg && chmod -R og-rwx ~/.gnupg
gpg --batch --passphrase '' --quick-gen-key '<example@example.com>' ed25519
@@ -75,6 +75,8 @@ or similar.
(define %rsa-key-id #xAE25DA2A70DEED59) ;rsa.pub
(define %dsa-key-id #x587918047BE8BD2C) ;dsa.pub
(define %ed25519-key-id #x771F49CBFAAE072D) ;ed25519.pub
+(define %secp384-key-id #x2F274631FF3E6C5B) ;secp384.pub
+(define %secp521-key-id #xE84B13A0B4E7AF1B) ;secp521.pub
(define %rsa-key-fingerprint
(base16-string->bytevector
@@ -85,6 +87,12 @@ or similar.
(define %ed25519-key-fingerprint
(base16-string->bytevector
(string-downcase "44D31E21AF7138F9B632280A771F49CBFAAE072D")))
+(define %secp384-key-fingerprint
+ (base16-string->bytevector
+ (string-downcase "CCB67D4B1F04073829F8FCF02F274631FF3E6C5B")))
+(define %secp521-key-fingerprint
+ (base16-string->bytevector
+ (string-downcase "3BAF7E984069B671F3C31169E84B13A0B4E7AF1B")))
;;; The following are detached signatures created commands like:
@@ -148,6 +156,28 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
=AE4G
-----END PGP SIGNATURE-----")
+(define %hello-signature/secp384/sha384 ;digest-algo: sha384
+ "\
+-----BEGIN PGP SIGNATURE-----
+
+iJUEABMJAB0WIQTMtn1LHwQHOCn4/PAvJ0Yx/z5sWwUCYxYIKAAKCRAvJ0Yx/z5s
+WxD2AX0QMeTHLJvJxRKTBP8O9kGMY9Nz0kzRBO0OJG2gYyxu9sZ+NAEQF01jAOXl
+ApL2zVkBgLUyyleJtR24LKxK73waLJb51TA29NXJJZ2fiRZ50u/lNfrFR3PYnK7/
+gvSkL3Ldzw==
+=+7h3
+-----END PGP SIGNATURE-----")
+
+(define %hello-signature/secp521/sha512
+ "\
+-----BEGIN PGP SIGNATURE-----
+
+iLcEABMKAB0WIQQ7r36YQGm2cfPDEWnoSxOgtOevGwUCYxYb+wAKCRDoSxOgtOev
+G+ByAgdwIBTnCtzo+lFuahhMMScXZZeTH055IOhTsXmptZaE3MaazTsUw3en8C9i
+EWiy/GDQKaJEZMP3dwN1+3tNTl/NUAIIiV/BFly9Ha/cYJG+p3LG24JoHVfJx04q
+LfSXejfMIvu33h8wjMA2tRQSlqdDylMWKThJgp6GH6svp+Zr4z+Smnw=
+=1zW0
+-----END PGP SIGNATURE-----")
+
(test-begin "openpgp")
@@ -193,7 +223,9 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
`(,%rsa-key-id ,%rsa-key-fingerprint rsa sha256)
`(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha256)
`(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha512)
- `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha1))
+ `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha1)
+ `(,%secp384-key-id ,%secp384-key-fingerprint ecdsa sha384)
+ `(,%secp521-key-id ,%secp521-key-fingerprint ecdsa sha512))
(map (lambda (str)
(let ((signature (get-openpgp-detached-signature/ascii
(open-input-string str))))
@@ -205,7 +237,9 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
%hello-signature/rsa
%hello-signature/ed25519/sha256
%hello-signature/ed25519/sha512
- %hello-signature/ed25519/sha1)))
+ %hello-signature/ed25519/sha1
+ %hello-signature/secp384/sha384
+ %hello-signature/secp521/sha512)))
(test-equal "verify-openpgp-signature, missing key"
`(missing-key ,%rsa-key-fingerprint)
@@ -221,7 +255,9 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
(good-signature ,%dsa-key-id)
(good-signature ,%ed25519-key-id)
(good-signature ,%ed25519-key-id)
- (good-signature ,%ed25519-key-id))
+ (good-signature ,%ed25519-key-id)
+ (good-signature ,%secp384-key-id)
+ (good-signature ,%secp521-key-id))
(map (lambda (key signature)
(let* ((key (search-path %load-path key))
(keyring (get-openpgp-keyring
@@ -235,18 +271,24 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
(list "tests/keys/rsa.pub" "tests/keys/dsa.pub"
"tests/keys/ed25519.pub"
"tests/keys/ed25519.pub"
- "tests/keys/ed25519.pub")
+ "tests/keys/ed25519.pub"
+ "tests/keys/secp384.pub"
+ "tests/keys/secp521.pub")
(list %hello-signature/rsa %hello-signature/dsa
%hello-signature/ed25519/sha256
%hello-signature/ed25519/sha512
- %hello-signature/ed25519/sha1)))
+ %hello-signature/ed25519/sha1
+ %hello-signature/secp384/sha384
+ %hello-signature/secp521/sha512)))
(test-equal "verify-openpgp-signature, bad signature"
`((bad-signature ,%rsa-key-id)
(bad-signature ,%dsa-key-id)
(bad-signature ,%ed25519-key-id)
(bad-signature ,%ed25519-key-id)
- (bad-signature ,%ed25519-key-id))
+ (bad-signature ,%ed25519-key-id)
+ (bad-signature ,%secp384-key-id)
+ (bad-signature ,%secp521-key-id))
(let ((keyring (fold (lambda (key keyring)
(let ((key (search-path %load-path key)))
(get-openpgp-keyring
@@ -256,7 +298,9 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
%empty-keyring
'("tests/keys/rsa.pub" "tests/keys/dsa.pub"
"tests/keys/ed25519.pub" "tests/keys/ed25519.pub"
- "tests/keys/ed25519.pub"))))
+ "tests/keys/ed25519.pub"
+ "tests/keys/secp384.pub"
+ "tests/keys/secp521.pub"))))
(map (lambda (signature)
(let ((signature (string->openpgp-packet signature)))
(let-values (((status key)
@@ -266,6 +310,8 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0=
(list %hello-signature/rsa %hello-signature/dsa
%hello-signature/ed25519/sha256
%hello-signature/ed25519/sha512
- %hello-signature/ed25519/sha1))))
+ %hello-signature/ed25519/sha1
+ %hello-signature/secp384/sha384
+ %hello-signature/secp521/sha512))))
(test-end "openpgp")