Make make_unusual_tbs.go test data idempotent

If the signature is already valid, don't bother regenerating the test
data. It's somewhat irksome that there isn't a crypto.Verifier to mirror
crypto.Signer, but ah well.

I've only added ECDSA support for now, but we can extend it later if we
want to. (In principle we could use this to generate more of our test
certs, not just the "unusual TBS" ones. This is automating the annoying
step of
https://github.com/google/der-ascii/blob/main/samples/certificates.md )

Change-Id: I0c3dac566a9a0f808b6e91de4d521f794d0503a8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/82007
Reviewed-by: Lily Chen <chlily@google.com>
Commit-Queue: Lily Chen <chlily@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/test/make_unusual_tbs.go b/crypto/x509/test/make_unusual_tbs.go
index eec602d..2ce33ed 100644
--- a/crypto/x509/test/make_unusual_tbs.go
+++ b/crypto/x509/test/make_unusual_tbs.go
@@ -20,6 +20,7 @@
 
 import (
 	"crypto"
+	"crypto/ecdsa"
 	"crypto/rand"
 	_ "crypto/sha256"
 	"crypto/x509"
@@ -31,6 +32,21 @@
 	"golang.org/x/crypto/cryptobyte/asn1"
 )
 
+func digest(hash crypto.Hash, in []byte) []byte {
+	h := hash.New()
+	h.Write(in)
+	return h.Sum(nil)
+}
+
+func verifySignature(key crypto.PublicKey, in, sig []byte, opts crypto.SignerOpts) bool {
+	switch k := key.(type) {
+	case *ecdsa.PublicKey:
+		return ecdsa.VerifyASN1(k, digest(opts.HashFunc(), in), sig)
+	default:
+		panic(fmt.Sprintf("unknown key type %T", k))
+	}
+}
+
 func updateSignature(path string, key crypto.Signer, opts crypto.SignerOpts) error {
 	inp, err := os.ReadFile(path)
 	if err != nil {
@@ -43,16 +59,21 @@
 
 	s := cryptobyte.String(block.Bytes)
 	var cert, tbsCert, sigAlg cryptobyte.String
+	var sig []byte
 	if !s.ReadASN1(&cert, asn1.SEQUENCE) ||
 		!cert.ReadASN1Element(&tbsCert, asn1.SEQUENCE) ||
-		!cert.ReadASN1Element(&sigAlg, asn1.SEQUENCE) {
+		!cert.ReadASN1Element(&sigAlg, asn1.SEQUENCE) ||
+		!cert.ReadASN1BitStringAsBytes(&sig) ||
+		!cert.Empty() {
 		return fmt.Errorf("could not parse certificate in %q", path)
 	}
 
-	h := opts.HashFunc().New()
-	h.Write(tbsCert)
-	digest := h.Sum(nil)
-	signature, err := key.Sign(rand.Reader, digest, opts)
+	// Check if the signature is already valid.
+	if verifySignature(key.Public(), tbsCert, sig, opts) {
+		return nil
+	}
+
+	newSig, err := key.Sign(rand.Reader, digest(opts.HashFunc(), tbsCert), opts)
 	if err != nil {
 		return err
 	}
@@ -61,7 +82,7 @@
 	b.AddASN1(asn1.SEQUENCE, func(child *cryptobyte.Builder) {
 		child.AddBytes(tbsCert)
 		child.AddBytes(sigAlg)
-		child.AddASN1BitString(signature)
+		child.AddASN1BitString(newSig)
 	})
 	newCert, err := b.Bytes()
 	if err != nil {