| // Copyright 2025 The BoringSSL Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| //go:build ignore |
| |
| // make_unusual_tbs.go refreshes the signatures on the unusual_tbs_*.pem |
| // certificates. |
| package main |
| |
| import ( |
| "crypto" |
| "crypto/rand" |
| _ "crypto/sha256" |
| "crypto/x509" |
| "encoding/pem" |
| "fmt" |
| "os" |
| |
| "golang.org/x/crypto/cryptobyte" |
| "golang.org/x/crypto/cryptobyte/asn1" |
| ) |
| |
| func updateSignature(path string, key crypto.Signer, opts crypto.SignerOpts) error { |
| inp, err := os.ReadFile(path) |
| if err != nil { |
| return err |
| } |
| block, _ := pem.Decode(inp) |
| if block == nil || block.Type != "CERTIFICATE" { |
| return fmt.Errorf("%q did not contain a PEM CERTIFICATE block", path) |
| } |
| |
| s := cryptobyte.String(block.Bytes) |
| var cert, tbsCert, sigAlg cryptobyte.String |
| if !s.ReadASN1(&cert, asn1.SEQUENCE) || |
| !cert.ReadASN1Element(&tbsCert, asn1.SEQUENCE) || |
| !cert.ReadASN1Element(&sigAlg, asn1.SEQUENCE) { |
| 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) |
| if err != nil { |
| return err |
| } |
| |
| b := cryptobyte.NewBuilder(nil) |
| b.AddASN1(asn1.SEQUENCE, func(child *cryptobyte.Builder) { |
| child.AddBytes(tbsCert) |
| child.AddBytes(sigAlg) |
| child.AddASN1BitString(signature) |
| }) |
| newCert, err := b.Bytes() |
| if err != nil { |
| return err |
| } |
| |
| newPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newCert}) |
| return os.WriteFile(path, newPEM, 0644) |
| } |
| |
| func loadPEMPrivateKey(path string) (crypto.Signer, error) { |
| inp, err := os.ReadFile(path) |
| if err != nil { |
| return nil, err |
| } |
| block, _ := pem.Decode(inp) |
| if block == nil || block.Type != "PRIVATE KEY" { |
| return nil, fmt.Errorf("%q did not contain a PEM PRIVATE KEY block", path) |
| } |
| key, err := x509.ParsePKCS8PrivateKey(block.Bytes) |
| if err != nil { |
| return nil, err |
| } |
| signer, ok := key.(crypto.Signer) |
| if !ok { |
| return nil, fmt.Errorf("key in %q was not a signing key", path) |
| } |
| return signer, nil |
| } |
| |
| func main() { |
| key, err := loadPEMPrivateKey("unusual_tbs_key.pem") |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "Error loading private key: %s\n", err) |
| os.Exit(1) |
| } |
| |
| paths := []string{ |
| "unusual_tbs_empty_extension_not_omitted.pem", |
| "unusual_tbs_null_sigalg_param.pem", |
| "unusual_tbs_uid_both.pem", |
| "unusual_tbs_uid_issuer.pem", |
| "unusual_tbs_uid_subject.pem", |
| "unusual_tbs_wrong_attribute_order.pem", |
| "unusual_tbs_v1_not_omitted.pem", |
| } |
| for _, path := range paths { |
| if err := updateSignature(path, key, crypto.SHA256); err != nil { |
| fmt.Fprintf(os.Stderr, "Error signing %q: %s\n", path, err) |
| os.Exit(1) |
| } |
| } |
| } |