x509: create CRLs with Issuer.RawSubject

This commit is contained in:
Sun Yimin 2022-11-18 11:45:46 +08:00 committed by GitHub
parent 7448a5de1e
commit 9805aa448a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 4 deletions

View File

@ -1669,7 +1669,7 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error)
if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil { if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil {
return nil, err return nil, err
} }
for _, ext := range extensions { for _, ext := range extensions {
oidStr := ext.Id.String() oidStr := ext.Id.String()
if requestedExts[oidStr] { if requestedExts[oidStr] {
@ -1943,6 +1943,29 @@ func (c *CertificateRequest) CheckSignature() error {
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey, true) return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey, true)
} }
// These structures reflect the ASN.1 structure of X.509 CRLs better than
// the existing crypto/x509/pkix variants do. These mirror the existing
// certificate structs in this file.
//
// Notably, we include issuer as an asn1.RawValue, mirroring the behavior of
// tbsCertificate and allowing raw (unparsed) subjects to be passed cleanly.
type certificateList struct {
TBSCertList tbsCertificateList
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}
type tbsCertificateList struct {
Raw asn1.RawContent
Version int `asn1:"optional,default:0"`
Signature pkix.AlgorithmIdentifier
Issuer asn1.RawValue
ThisUpdate time.Time
NextUpdate time.Time `asn1:"optional"`
RevokedCertificates []pkix.RevokedCertificate `asn1:"optional"`
Extensions []pkix.Extension `asn1:"tag:0,optional,explicit"`
}
// CreateRevocationList creates a new X.509 v2 Certificate Revocation List, // CreateRevocationList creates a new X.509 v2 Certificate Revocation List,
// according to RFC 5280, based on template. // according to RFC 5280, based on template.
// //
@ -1999,10 +2022,16 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
return nil, err return nil, err
} }
tbsCertList := pkix.TBSCertificateList{ // Correctly use the issuer's subject sequence if one is specified.
issuerSubject, err := subjectBytes(issuer.asX509())
if err != nil {
return nil, err
}
tbsCertList := tbsCertificateList{
Version: 1, // v2 Version: 1, // v2
Signature: signatureAlgorithm, Signature: signatureAlgorithm,
Issuer: issuer.Subject.ToRDNSequence(), Issuer: asn1.RawValue{FullBytes: issuerSubject},
ThisUpdate: template.ThisUpdate.UTC(), ThisUpdate: template.ThisUpdate.UTC(),
NextUpdate: template.NextUpdate.UTC(), NextUpdate: template.NextUpdate.UTC(),
Extensions: []pkix.Extension{ Extensions: []pkix.Extension{
@ -2029,6 +2058,10 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
return nil, err return nil, err
} }
// Optimization to only marshal this struct once, when signing and
// then embedding in certificateList below.
tbsCertList.Raw = tbsCertListContents
input := tbsCertListContents input := tbsCertListContents
if hashFunc != 0 { if hashFunc != 0 {
h := hashFunc.New() h := hashFunc.New()
@ -2050,7 +2083,7 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
return nil, err return nil, err
} }
return asn1.Marshal(pkix.CertificateList{ return asn1.Marshal(certificateList{
TBSCertList: tbsCertList, TBSCertList: tbsCertList,
SignatureAlgorithm: signatureAlgorithm, SignatureAlgorithm: signatureAlgorithm,
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},

View File

@ -2211,6 +2211,18 @@ func TestCreateRevocationList(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to generate Ed25519 key: %s", err) t.Fatalf("Failed to generate Ed25519 key: %s", err)
} }
// Generation command:
// openssl req -x509 -newkey rsa -keyout key.pem -out cert.pem -days 365 -nodes -subj '/C=US/ST=California/L=San Francisco/O=Internet Widgets, Inc./OU=WWW/CN=Root/emailAddress=admin@example.com' -sha256 -addext basicConstraints=CA:TRUE -addext "keyUsage = digitalSignature, keyEncipherment, dataEncipherment, cRLSign, keyCertSign" -utf8
utf8CAStr := "MIIEITCCAwmgAwIBAgIUXHXy7NdtDv+ClaHvIvlwCYiI4a4wDQYJKoZIhvcNAQELBQAwgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMR8wHQYDVQQKDBZJbnRlcm5ldCBXaWRnZXRzLCBJbmMuMQwwCgYDVQQLDANXV1cxDTALBgNVBAMMBFJvb3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMB4XDTIyMDcwODE1MzgyMFoXDTIzMDcwODE1MzgyMFowgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMR8wHQYDVQQKDBZJbnRlcm5ldCBXaWRnZXRzLCBJbmMuMQwwCgYDVQQLDANXV1cxDTALBgNVBAMMBFJvb3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmXvp0WNjsZzySWT7Ce5zewQNKq8ujeZGphJ44Vdrwut/b6TcC4iYENds5+7/3PYwBllp3K5TRpCcafSxdhJsvA7/zWlHHNRcJhJLNt9qsKWP6ukI2Iw6OmFMg6kJQ8f67RXkT8HR3v0UqE+lWrA0g+oRuj4erLtfOtSpnl4nsE/Rs2qxbELFWAf7F5qMqH4dUyveWKrNT8eI6YQN+wBg0MAjoKRvDJnBhuo+IvvXX8Aq1QWUcBGPK3or/Ehxy5f/gEmSUXyEU1Ht/vATt2op+eRaEEpBdGRvO+DrKjlcQV2XMN18A9LAX6hCzH43sGye87dj7RZ9yj+waOYNaM7kFQIDAQABo10wWzAdBgNVHQ4EFgQUtbSlrW4hGL2kNjviM6wcCRwvOEEwHwYDVR0jBBgwFoAUtbSlrW4hGL2kNjviM6wcCRwvOEEwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAbYwDQYJKoZIhvcNAQELBQADggEBAAko82YNNI2n/45L3ya21vufP6nZihIOIxgcRPUMX+IDJZk16qsFdcLgH3KAP8uiVLn8sULuCj35HpViR4IcAk2d+DqfG11l8kY+e5P7nYsViRfy0AatF59/sYlWf+3RdmPXfL70x4mE9OqlMdDm0kR2obps8rng83VLDNvj3R5sBnQwdw6LKLGzaE+RiCTmkH0+P6vnbOJ33su9+9al1+HvJUg3UM1Xq5Bw7TE8DQTetMV3c2Q35RQaJB9pQ4blJOnW9hfnt8yQzU6TU1bU4mRctTm1o1f8btPqUpi+/blhi5MUJK0/myj1XD00pmyfp8QAFl1EfqmTMIBMLg633A0="
utf8CABytes, _ := base64.StdEncoding.DecodeString(utf8CAStr)
utf8CA, _ := ParseCertificate(utf8CABytes)
utf8KeyStr := "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZe+nRY2OxnPJJZPsJ7nN7BA0qry6N5kamEnjhV2vC639vpNwLiJgQ12zn7v/c9jAGWWncrlNGkJxp9LF2Emy8Dv/NaUcc1FwmEks232qwpY/q6QjYjDo6YUyDqQlDx/rtFeRPwdHe/RSoT6VasDSD6hG6Ph6su1861KmeXiewT9GzarFsQsVYB/sXmoyofh1TK95Yqs1Px4jphA37AGDQwCOgpG8MmcGG6j4i+9dfwCrVBZRwEY8reiv8SHHLl/+ASZJRfIRTUe3+8BO3ain55FoQSkF0ZG874OsqOVxBXZcw3XwD0sBfqELMfjewbJ7zt2PtFn3KP7Bo5g1ozuQVAgMBAAECggEAIscjKiD9PAe2Fs9c2tk/LYazfRKI1/pv072nylfGwToffCq8+ZgP7PEDamKLc4QNScME685MbFbkOlYJyBlQriQv7lmGlY/A+Zd3l410XWaGf9IiAP91Sjk13zd0M/micApf23qtlXt/LMwvSadXnvRw4+SjirxCTdBWRt5K2/ZAN550v7bHFk1EZc3UBF6sOoNsjQWh9Ek79UmQYJBPiZDBHO7O2fh2GSIbUutTma+Tb2i1QUZzg+AG3cseF3p1i3uhNrCh+p+01bJSzGTQsRod2xpD1tpWwR3kIftCOmD1XnhpaBQi7PXjEuNbfucaftnoYj2ShDdmgD5RkkbTAQKBgQC8Ghu5MQ/yIeqXg9IpcSxuWtUEAEfK33/cC/IvuntgbNEnWQm5Lif4D6a9zjkxiCS+9HhrUu5U2EV8NxOyaqmtub3Np1Z5mPuI9oiZ119bjUJd4X+jKOTaePWvOv/rL/pTHYqzXohVMrXy+DaTIq4lOcv3n72SuhuTcKU95rhKtQKBgQDQ4t+HsRZd5fJzoCgRQhlNK3EbXQDv2zXqMW3GfpF7GaDP18I530inRURSJa++rvi7/MCFg/TXVS3QC4HXtbzTYTqhE+VHzSr+/OcsqpLE8b0jKBDv/SBkz811PUJDs3LsX31DT3K0zUpMpNSd/5SYTyJKef9L6mxmwlC1S2Yv4QKBgQC57SiYDdnQIRwrtZ2nXvlm/xttAAX2jqJoU9qIuNA4yHaYaRcGVowlUvsiw9OelQ6VPTpGA0wWy0src5lhkrKzSFRHEe+U89U1VVJCljLoYKFIAJvUH5jOJh/am/vYca0COMIfeAJUDHLyfcwb9XyiyRVGZzvP62tUelSq8gIZvQKBgCAHeaDzzWsudCO4ngwvZ3PGwnwgoaElqrmzRJLYG3SVtGvKOJTpINnNLDGwZ6dEaw1gLyEJ38QY4oJxEULDMiXzVasXQuPkmMAqhUP7D7A1JPw8C4TQ+mOa3XUppHx/CpMl/S4SA5OnmsnvyE5Fv0IveCGVXUkFtAN5rihuXEfhAoGANUkuGU3A0Upk2mzv0JTGP4H95JFG93cqnyPNrYs30M6RkZNgTW27yyr+Nhs4/cMdrg1AYTB0+6ItQWSDmYLs7JEbBE/8L8fdD1irIcygjIHE9nJh96TgZCt61kVGLE8758lOdmoB2rZOpGwi16QIhdQb+IyozYqfX+lQUojL/W0="
utf8KeyBytes, _ := base64.StdEncoding.DecodeString(utf8KeyStr)
utf8KeyRaw, _ := ParsePKCS8PrivateKey(utf8KeyBytes)
utf8Key := utf8KeyRaw.(crypto.Signer)
tests := []struct { tests := []struct {
name string name string
key crypto.Signer key crypto.Signer
@ -2451,6 +2463,16 @@ func TestCreateRevocationList(t *testing.T) {
NextUpdate: time.Time{}.Add(time.Hour * 48), NextUpdate: time.Time{}.Add(time.Hour * 48),
}, },
}, },
{
name: "valid CA with utf8 Subject fields including Email, empty list",
key: utf8Key,
issuer: utf8CA.asX509(),
template: &x509.RevocationList{
Number: big.NewInt(5),
ThisUpdate: time.Time{}.Add(time.Hour * 24),
NextUpdate: time.Time{}.Add(time.Hour * 48),
},
},
} }
for _, tc := range tests { for _, tc := range tests {