]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/x509: check the private key passed to CreateCertificate
authorFilippo Valsorda <filippo@golang.org>
Thu, 19 Mar 2020 21:59:45 +0000 (17:59 -0400)
committerFilippo Valsorda <filippo@golang.org>
Sun, 9 May 2021 00:07:34 +0000 (00:07 +0000)
Unfortunately, we can't improve the function signature to refer to
crypto.PrivateKey and crypto.PublicKey, even if they are both
interface{}, because it would break assignments to function types.

Fixes #37845

Change-Id: I627f2ac1e1ba98b128dac5382f9cc2524eaef378
Reviewed-on: https://go-review.googlesource.com/c/go/+/224157
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
src/crypto/x509/x509.go

index ff37b361d75b5ff60e4ea51a67b759ddc8efa062..4304ab54e1a7052f7a7c40e6eb589900db7c56e9 100644 (file)
@@ -1413,8 +1413,8 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
 // just an empty SEQUENCE.
 var emptyASN1Subject = []byte{0x30, 0}
 
-// CreateCertificate creates a new X.509v3 certificate based on a template.
-// The following members of template are used:
+// CreateCertificate creates a new X.509 v3 certificate based on a template.
+// The following members of template are currently used:
 //
 //  - AuthorityKeyId
 //  - BasicConstraintsValid
@@ -1451,7 +1451,7 @@ var emptyASN1Subject = []byte{0x30, 0}
 //
 // The certificate is signed by parent. If parent is equal to template then the
 // certificate is self-signed. The parameter pub is the public key of the
-// signee and priv is the private key of the signer.
+// certificate to be generated and priv is the private key of the signer.
 //
 // The returned slice is the certificate in DER encoding.
 //
@@ -1465,7 +1465,7 @@ var emptyASN1Subject = []byte{0x30, 0}
 //
 // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId
 // will be generated from the hash of the public key.
-func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) {
+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) ([]byte, error) {
        key, ok := priv.(crypto.Signer)
        if !ok {
                return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
@@ -1491,12 +1491,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
 
        asn1Issuer, err := subjectBytes(parent)
        if err != nil {
-               return
+               return nil, err
        }
 
        asn1Subject, err := subjectBytes(template)
        if err != nil {
-               return
+               return nil, err
        }
 
        authorityKeyId := template.AuthorityKeyId
@@ -1514,9 +1514,19 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
                subjectKeyId = h[:]
        }
 
+       // Check that the signer's public key matches the private key, if available.
+       type privateKey interface {
+               Equal(crypto.PublicKey) bool
+       }
+       if privPub, ok := key.Public().(privateKey); !ok {
+               return nil, errors.New("x509: internal error: supported public key does not implement Equal")
+       } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) {
+               return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey")
+       }
+
        extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId)
        if err != nil {
-               return
+               return nil, err
        }
 
        encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
@@ -1533,7 +1543,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
 
        tbsCertContents, err := asn1.Marshal(c)
        if err != nil {
-               return
+               return nil, err
        }
        c.Raw = tbsCertContents
 
@@ -1555,7 +1565,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
        var signature []byte
        signature, err = key.Sign(rand, signed, signerOpts)
        if err != nil {
-               return
+               return nil, err
        }
 
        signedCert, err := asn1.Marshal(certificate{