#43, crypto/x509: don't allow too long serials

This commit is contained in:
Emman 2022-04-15 11:01:11 +08:00
parent db4ee8585a
commit b3f10b9a4c
2 changed files with 48 additions and 0 deletions

View File

@ -1284,6 +1284,18 @@ func CreateCertificate(rand io.Reader, template, parent *x509.Certificate, pub,
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")
}

View File

@ -2429,3 +2429,39 @@ func TestDisableSHA1ForCertOnly(t *testing.T) {
t.Errorf("unexpected error: %s", err)
}
}
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.asX509(), tmpl.asX509(), 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.asX509(), tmpl.asX509(), k.Public(), k)
if err == nil || err.Error() != expectedErr {
t.Errorf("CreateCertificate returned unexpected error: want %q, got %q", expectedErr, err)
}
}