|  | // 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-mls-extensions.go generates test certs to test mls extension handling. | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "crypto/ecdsa" | 
|  | "crypto/rand" | 
|  | "crypto/x509" | 
|  | "crypto/x509/pkix" | 
|  | "encoding/asn1" | 
|  | "encoding/pem" | 
|  | "math/big" | 
|  | "os" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey | 
|  |  | 
|  | func init() { | 
|  | leafKey = mustParseECDSAKey(leafKeyPEM) | 
|  | intermediateKey = mustParseECDSAKey(intermediateKeyPEM) | 
|  | rootKey = mustParseECDSAKey(rootKeyPEM) | 
|  | } | 
|  |  | 
|  | type templateAndKey struct { | 
|  | template x509.Certificate | 
|  | key      *ecdsa.PrivateKey | 
|  | } | 
|  |  | 
|  | func mustGenerateCertificate(path string, subject, issuer *templateAndKey) []byte { | 
|  | cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | file, err := os.Create(path) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | defer file.Close() | 
|  | err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert}) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | return cert | 
|  | } | 
|  |  | 
|  | func main() { | 
|  | notBefore, err := time.Parse(time.RFC3339, "0000-01-01T00:00:00Z") | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | notAfter, err := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z") | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  |  | 
|  | root := templateAndKey{ | 
|  | template: x509.Certificate{ | 
|  | SerialNumber:          new(big.Int).SetInt64(1), | 
|  | Subject:               pkix.Name{CommonName: "MLS Cert Root"}, | 
|  | NotBefore:             notBefore, | 
|  | NotAfter:              notAfter, | 
|  | BasicConstraintsValid: true, | 
|  | IsCA:                  true, | 
|  | KeyUsage:              x509.KeyUsageCertSign, | 
|  | SignatureAlgorithm:    x509.ECDSAWithSHA256, | 
|  | SubjectKeyId:          []byte("root"), | 
|  | }, | 
|  | key: rootKey, | 
|  | } | 
|  | intermediate := templateAndKey{ | 
|  | template: x509.Certificate{ | 
|  | SerialNumber:          new(big.Int).SetInt64(2), | 
|  | Subject:               pkix.Name{CommonName: "MLS Cert Intermediate"}, | 
|  | NotBefore:             notBefore, | 
|  | NotAfter:              notAfter, | 
|  | BasicConstraintsValid: true, | 
|  | IsCA:                  true, | 
|  | KeyUsage:              x509.KeyUsageCertSign, | 
|  | SignatureAlgorithm:    x509.ECDSAWithSHA256, | 
|  | SubjectKeyId:          []byte("intermediate"), | 
|  | UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}}, | 
|  | }, | 
|  | key: intermediateKey, | 
|  | } | 
|  | leaf := templateAndKey{ | 
|  | template: x509.Certificate{ | 
|  | SerialNumber:          new(big.Int).SetInt64(3), | 
|  | Subject:               pkix.Name{CommonName: "MLS Cert Leaf"}, | 
|  | NotBefore:             notBefore, | 
|  | NotAfter:              notAfter, | 
|  | BasicConstraintsValid: true, | 
|  | IsCA:                  false, | 
|  | KeyUsage:              x509.KeyUsageDigitalSignature, | 
|  | SignatureAlgorithm:    x509.ECDSAWithSHA256, | 
|  | SubjectKeyId:          []byte("leaf"), | 
|  | UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}}, | 
|  | }, | 
|  | key: leafKey, | 
|  | } | 
|  |  | 
|  | // Generate a valid certificate chain from the templates. | 
|  | mustGenerateCertificate("mls_client_root.pem", &root, &root) | 
|  | mustGenerateCertificate("mls_client_intermediate.pem", &intermediate, &root) | 
|  | mustGenerateCertificate("mls_client_leaf.pem", &leaf, &intermediate) | 
|  | intermediateInvalid := intermediate | 
|  | intermediateInvalid.template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}, | 
|  | []int{2, 23, 133, 8, 1}} | 
|  | mustGenerateCertificate("mls_client_intermediate_extra_eku.pem", &intermediateInvalid, &root) | 
|  | leafInvalid := leaf | 
|  | leafInvalid.template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}, | 
|  | []int{2, 23, 133, 8, 1}} | 
|  | mustGenerateCertificate("mls_client_leaf_extra_eku.pem", &leafInvalid, &intermediateInvalid) | 
|  | } | 
|  |  | 
|  | const leafKeyPEM = `-----BEGIN PRIVATE KEY----- | 
|  | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk | 
|  | 024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5 | 
|  | w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X | 
|  | -----END PRIVATE KEY-----` | 
|  |  | 
|  | const intermediateKeyPEM = `-----BEGIN PRIVATE KEY----- | 
|  | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6 | 
|  | vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE | 
|  | Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw | 
|  | -----END PRIVATE KEY-----` | 
|  |  | 
|  | const rootKeyPEM = `-----BEGIN PRIVATE KEY----- | 
|  | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J | 
|  | Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq | 
|  | ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt | 
|  | -----END PRIVATE KEY-----` | 
|  |  | 
|  | func mustParseECDSAKey(in string) *ecdsa.PrivateKey { | 
|  | keyBlock, _ := pem.Decode([]byte(in)) | 
|  | if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" { | 
|  | panic("could not decode private key") | 
|  | } | 
|  | key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | return key.(*ecdsa.PrivateKey) | 
|  | } |