From 575a82f42751db0536be2e9e7f3a308212b773b3 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 26 Apr 2024 08:31:40 +0200 Subject: [PATCH] Actively self-sign the certificate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Self-sign the certificate and don’t rely on the go implementation to do it - Add the SKI also as the `AuthorityKeyId` --- cert/cert.go | 53 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/cert/cert.go b/cert/cert.go index 93bc74d..4a4dc89 100644 --- a/cert/cert.go +++ b/cert/cert.go @@ -28,19 +28,18 @@ var CipherSuites = []uint16{ // commonName is the CN of the certificate // Example for commonName: "deviceModel-deviceSerialNumber" func CreateCertificate(organizationalUnit, organization, country, commonName string) (tls.Certificate, error) { - privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + rootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return tls.Certificate{}, err } - // Create the EEBUS service SKI using the private key - asn1, err := x509.MarshalECPrivateKey(privateKey) + // Create a random serial big int value + maxValue := new(big.Int) + maxValue.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxValue, big.NewInt(1)) + serialNumber, err := rand.Int(rand.Reader, maxValue) if err != nil { return tls.Certificate{}, err } - // SHIP 12.2: Required to be created according to RFC 3280 4.2.1.2 - // #nosec G401 - ski := sha1.Sum(asn1) subject := pkix.Name{ OrganizationalUnit: []string{organizationalUnit}, @@ -49,27 +48,55 @@ func CreateCertificate(organizationalUnit, organization, country, commonName str CommonName: commonName, } - // Create a random serial big int value - maxValue := new(big.Int) - maxValue.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxValue, big.NewInt(1)) - serialNumber, err := rand.Int(rand.Reader, maxValue) + rootTemplate := &x509.Certificate{ + SignatureAlgorithm: x509.ECDSAWithSHA256, + SerialNumber: serialNumber, + Subject: subject, + NotBefore: time.Now(), // Valid starting now + NotAfter: time.Now().Add(time.Hour * 24 * 365 * 10), // Valid for 10 years + KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + IsCA: true, + } + + rootCertBytes, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, &rootKey.PublicKey, rootKey) + if err != nil { + return tls.Certificate{}, err + } + + rootCert, err := x509.ParseCertificate(rootCertBytes) + if err != nil { + return tls.Certificate{}, err + } + + privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return tls.Certificate{}, err + } + + // Create the EEBUS service SKI using the private key + asn1, err := x509.MarshalECPrivateKey(privateKey) if err != nil { return tls.Certificate{}, err } + // SHIP 12.2: Required to be created according to RFC 3280 4.2.1.2 + // #nosec G401 + ski := sha1.Sum(asn1) - template := x509.Certificate{ + template := &x509.Certificate{ SignatureAlgorithm: x509.ECDSAWithSHA256, SerialNumber: serialNumber, Subject: subject, NotBefore: time.Now(), // Valid starting now NotAfter: time.Now().Add(time.Hour * 24 * 365 * 10), // Valid for 10 years - KeyUsage: x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, IsCA: true, SubjectKeyId: ski[:], + AuthorityKeyId: ski[:], } - certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) + certBytes, err := x509.CreateCertificate(rand.Reader, template, rootCert, &privateKey.PublicKey, rootKey) if err != nil { return tls.Certificate{}, err }