diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index e0e8f6125f..cd87044d17 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -1008,22 +1008,22 @@ func ParseRevocationList(der []byte) (*RevocationList, error) { // we can populate RevocationList.Raw, before unwrapping the // SEQUENCE so it can be operated on if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) { - return nil, errors.New("x509: malformed certificate") + return nil, errors.New("x509: malformed crl") } rl.Raw = input if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) { - return nil, errors.New("x509: malformed certificate") + return nil, errors.New("x509: malformed crl") } var tbs cryptobyte.String // do the same trick again as above to extract the raw // bytes for Certificate.RawTBSCertificate if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) { - return nil, errors.New("x509: malformed tbs certificate") + return nil, errors.New("x509: malformed tbs crl") } rl.RawTBSRevocationList = tbs if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) { - return nil, errors.New("x509: malformed tbs certificate") + return nil, errors.New("x509: malformed tbs crl") } var version int @@ -1148,6 +1148,15 @@ func ParseRevocationList(der []byte) (*RevocationList, error) { if err != nil { return nil, err } + if ext.Id.Equal(oidExtensionAuthorityKeyId) { + rl.AuthorityKeyId = ext.Value + } else if ext.Id.Equal(oidExtensionCRLNumber) { + value := cryptobyte.String(ext.Value) + rl.Number = new(big.Int) + if !value.ReadASN1Integer(rl.Number) { + return nil, errors.New("x509: malformed crl number") + } + } rl.Extensions = append(rl.Extensions, ext) } } diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 87eb1f7720..7dcebfa5f1 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -2109,7 +2109,9 @@ type RevocationList struct { // Issuer contains the DN of the issuing certificate. Issuer pkix.Name // AuthorityKeyId is used to identify the public key associated with the - // issuing certificate. + // issuing certificate. It is populated from the authorityKeyIdentifier + // extension when parsing a CRL. It is ignored when creating a CRL; the + // extension is populated from the issuing certificate itself. AuthorityKeyId []byte Signature []byte @@ -2125,7 +2127,8 @@ type RevocationList struct { // Number is used to populate the X.509 v2 cRLNumber extension in the CRL, // which should be a monotonically increasing sequence number for a given - // CRL scope and CRL issuer. + // CRL scope and CRL issuer. It is also populated from the cRLNumber + // extension when parsing a CRL. Number *big.Int // ThisUpdate is used to populate the thisUpdate field in the CRL, which diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 8ef6115df4..594ee1dceb 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -2681,6 +2681,19 @@ func TestCreateRevocationList(t *testing.T) { t.Fatalf("Extensions mismatch: got %v; want %v.", parsedCRL.Extensions[2:], tc.template.ExtraExtensions) } + + if tc.template.Number != nil && parsedCRL.Number == nil { + t.Fatalf("Generated CRL missing Number: got nil, want %s", + tc.template.Number.String()) + } + if tc.template.Number != nil && tc.template.Number.Cmp(parsedCRL.Number) != 0 { + t.Fatalf("Generated CRL has wrong Number: got %s, want %s", + parsedCRL.Number.String(), tc.template.Number.String()) + } + if !bytes.Equal(parsedCRL.AuthorityKeyId, expectedAKI) { + t.Fatalf("Generated CRL has wrong Number: got %x, want %x", + parsedCRL.AuthorityKeyId, expectedAKI) + } }) } }