return nil, errors.New("x509: no SerialNumber given")
}
+ // RFC 5280 Section 4.1.2.2: serial number must not be longer than 20 octets
+ //
+ // We cannot simply check for len(serialBytes) > 20, because encoding/asn1 may
+ // pad the slice in order to prevent the integer being mistaken for a negative
+ // number (DER uses the high bit of the left-most byte to indicate the sign.),
+ // so we need to double check the composition of the serial if it is exactly
+ // 20 bytes.
+ serialBytes := template.SerialNumber.Bytes()
+ if len(serialBytes) > 20 || (len(serialBytes) == 20 && serialBytes[0]&0x80 != 0) {
+ return nil, errors.New("x509: serial number exceeds 20 octets")
+ }
+
if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) {
return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen")
}
t.Error("DER encoding contains the an empty extensions SEQUENCE")
}
}
+
+func TestCreateCertificateLongSerial(t *testing.T) {
+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ serialBytes := make([]byte, 21)
+ serialBytes[0] = 0x80
+ serialBytes[20] = 1
+ tooLong := big.NewInt(0).SetBytes(serialBytes)
+
+ tmpl := &Certificate{
+ SerialNumber: tooLong,
+ Subject: pkix.Name{
+ CommonName: ":)",
+ },
+ NotAfter: time.Now().Add(time.Hour),
+ NotBefore: time.Now().Add(-time.Hour),
+ }
+
+ expectedErr := "x509: serial number exceeds 20 octets"
+
+ _, err = CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
+ if err == nil || err.Error() != expectedErr {
+ t.Errorf("CreateCertificate returned unexpected error: want %q, got %q", expectedErr, err)
+ }
+
+ serialBytes = serialBytes[:20]
+ tmpl.SerialNumber = big.NewInt(0).SetBytes(serialBytes)
+
+ _, err = CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
+ if err == nil || err.Error() != expectedErr {
+ t.Errorf("CreateCertificate returned unexpected error: want %q, got %q", expectedErr, err)
+ }
+}