From ad7ce3911f4947b4cccb435b6374e3808f0062db Mon Sep 17 00:00:00 2001 From: Lorenz Brun Date: Wed, 30 Oct 2019 02:29:23 +0000 Subject: [PATCH] crypto/x509: fix CreateCRL for Ed25519 CAs This makes Ed25519 certificates work for CreateCRL(). This previously failed (panic: crypto: requested hash function #0 is unavailable) because the hash could not be skipped, but Ed25519 uses no hash. A similar fix has been applied in a few other places when Ed25519 was added when Ed25519 certificates were originally introduced, but was missed here. Change-Id: I16fcfcd53ba3bb8f773e5de972b8fedde1f6350e Change-Id: I16fcfcd53ba3bb8f773e5de972b8fedde1f6350e GitHub-Last-Rev: bf7f1458f850d01605c619c3f53f86649477dd4d GitHub-Pull-Request: golang/go#35241 Reviewed-on: https://go-review.googlesource.com/c/go/+/204046 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda --- src/crypto/x509/x509.go | 11 +++-- src/crypto/x509/x509_test.go | 94 +++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index cc382e52c6..013f1c996d 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -2256,12 +2256,15 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [ return } - h := hashFunc.New() - h.Write(tbsCertListContents) - digest := h.Sum(nil) + signed := tbsCertListContents + if hashFunc != 0 { + h := hashFunc.New() + h.Write(signed) + signed = h.Sum(nil) + } var signature []byte - signature, err = key.Sign(rand, digest, hashFunc) + signature, err = key.Sign(rand, signed, hashFunc) if err != nil { return } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index d5b168e78f..9e15b8adbf 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1193,11 +1193,77 @@ KVcg7fBd484ht/sS+l0dsB4KDOSpd8JzVDMF8OZqlaydizoJO0yWr9GbCN1+OKq5 EhLrEqU= -----END CERTIFICATE-----` +const ed25519CRLCertificate = ` +Certificate: +Data: + Version: 3 (0x2) + Serial Number: + 7a:07:a0:9d:14:04:16:fc:1f:d8:e5:fe:d1:1d:1f:8d + Signature Algorithm: ED25519 + Issuer: CN = Ed25519 CRL Test CA + Validity + Not Before: Oct 30 01:20:20 2019 GMT + Not After : Dec 31 23:59:59 9999 GMT + Subject: CN = Ed25519 CRL Test CA + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 95:73:3b:b0:06:2a:31:5a:b6:a7:a6:6e:ef:71:df: + ac:6f:6b:39:03:85:5e:63:4b:f8:a6:0f:68:c6:6f: + 75:21 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Client Authentication, TLS Web Server Authentication, OCSP Signing + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60 + X509v3 Authority Key Identifier: + keyid:B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60 + +Signature Algorithm: ED25519 + fc:3e:14:ea:bb:70:c2:6f:38:34:70:bc:c8:a7:f4:7c:0d:1e: + 28:d7:2a:9f:22:8a:45:e8:02:76:84:1e:2d:64:2d:1e:09:b5: + 29:71:1f:95:8a:4e:79:87:51:60:9a:e7:86:40:f6:60:c7:d1: + ee:68:76:17:1d:90:cc:92:93:07 +-----BEGIN CERTIFICATE----- +MIIBijCCATygAwIBAgIQegegnRQEFvwf2OX+0R0fjTAFBgMrZXAwHjEcMBoGA1UE +AxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAgFw0xOTEwMzAwMTIwMjBaGA85OTk5MTIz +MTIzNTk1OVowHjEcMBoGA1UEAxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAqMAUGAytl +cAMhAJVzO7AGKjFatqembu9x36xvazkDhV5jS/imD2jGb3Uho4GNMIGKMA4GA1Ud +DwEB/wQEAwIBhjAnBgNVHSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwEGCCsGAQUF +BwMJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLcX2hbqxe0fGElE09LjoDUK +gZNgMB8GA1UdIwQYMBaAFLcX2hbqxe0fGElE09LjoDUKgZNgMAUGAytlcANBAPw+ +FOq7cMJvODRwvMin9HwNHijXKp8iikXoAnaEHi1kLR4JtSlxH5WKTnmHUWCa54ZA +9mDH0e5odhcdkMySkwc= +-----END CERTIFICATE-----` + +const ed25519CRLKey = `-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEINdKh2096vUBYu4EIFpjShsUSh3vimKya1sQ1YTT4RZG +-----END PRIVATE KEY-----` + func TestCRLCreation(t *testing.T) { block, _ := pem.Decode([]byte(pemPrivateKey)) - priv, _ := ParsePKCS1PrivateKey(block.Bytes) + privRSA, _ := ParsePKCS1PrivateKey(block.Bytes) block, _ = pem.Decode([]byte(pemCertificate)) - cert, _ := ParseCertificate(block.Bytes) + certRSA, _ := ParseCertificate(block.Bytes) + + block, _ = pem.Decode([]byte(ed25519CRLKey)) + privEd25519, _ := ParsePKCS8PrivateKey(block.Bytes) + block, _ = pem.Decode([]byte(ed25519CRLCertificate)) + certEd25519, _ := ParseCertificate(block.Bytes) + + tests := []struct { + name string + priv interface{} + cert *Certificate + }{ + {"RSA CA", privRSA, certRSA}, + {"Ed25519 CA", privEd25519, certEd25519}, + } loc := time.FixedZone("Oz/Atlantis", int((2 * time.Hour).Seconds())) @@ -1227,18 +1293,20 @@ func TestCRLCreation(t *testing.T) { }, } - crlBytes, err := cert.CreateCRL(rand.Reader, priv, revokedCerts, now, expiry) - if err != nil { - t.Errorf("error creating CRL: %s", err) - } + for _, test := range tests { + crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry) + if err != nil { + t.Errorf("%s: error creating CRL: %s", test.name, err) + } - parsedCRL, err := ParseDERCRL(crlBytes) - if err != nil { - t.Errorf("error reparsing CRL: %s", err) - } - if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) { - t.Errorf("RevokedCertificates mismatch: got %v; want %v.", - parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) + parsedCRL, err := ParseDERCRL(crlBytes) + if err != nil { + t.Errorf("%s: error reparsing CRL: %s", test.name, err) + } + if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) { + t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name, + parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) + } } } -- 2.48.1