github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/x509/boring_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build boringcrypto 6 7 package x509 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "crypto/internal/boring/fipstls" 13 "crypto/rand" 14 "crypto/rsa" 15 "crypto/x509/pkix" 16 "fmt" 17 "math/big" 18 "strings" 19 "testing" 20 "time" 21 ) 22 23 const ( 24 boringCertCA = iota 25 boringCertLeaf 26 boringCertFIPSOK = 0x80 27 ) 28 29 func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey { 30 k, err := rsa.GenerateKey(rand.Reader, size) 31 if err != nil { 32 t.Fatal(err) 33 } 34 return k 35 } 36 37 func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey { 38 k, err := ecdsa.GenerateKey(curve, rand.Reader) 39 if err != nil { 40 t.Fatal(err) 41 } 42 return k 43 } 44 45 type boringCertificate struct { 46 name string 47 org string 48 parentOrg string 49 der []byte 50 cert *Certificate 51 key interface{} 52 fipsOK bool 53 } 54 55 func TestBoringAllowCert(t *testing.T) { 56 R1 := testBoringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK) 57 R2 := testBoringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA) 58 59 M1_R1 := testBoringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK) 60 M2_R1 := testBoringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA) 61 62 I_R1 := testBoringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) 63 testBoringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) 64 testBoringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK) 65 testBoringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK) 66 67 testBoringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK) 68 testBoringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf) 69 } 70 71 func testBoringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate { 72 org := name 73 parentOrg := "" 74 if i := strings.Index(org, "_"); i >= 0 { 75 org = org[:i] 76 parentOrg = name[i+1:] 77 } 78 tmpl := &Certificate{ 79 SerialNumber: big.NewInt(1), 80 Subject: pkix.Name{ 81 Organization: []string{org}, 82 }, 83 NotBefore: time.Unix(0, 0), 84 NotAfter: time.Unix(0, 0), 85 86 KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature, 87 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, 88 BasicConstraintsValid: true, 89 } 90 if mode&^boringCertFIPSOK == boringCertLeaf { 91 tmpl.DNSNames = []string{"example.com"} 92 } else { 93 tmpl.IsCA = true 94 tmpl.KeyUsage |= KeyUsageCertSign 95 } 96 97 var pcert *Certificate 98 var pkey interface{} 99 if parent != nil { 100 pcert = parent.cert 101 pkey = parent.key 102 } else { 103 pcert = tmpl 104 pkey = key 105 } 106 107 var pub interface{} 108 var desc string 109 switch k := key.(type) { 110 case *rsa.PrivateKey: 111 pub = &k.PublicKey 112 desc = fmt.Sprintf("RSA-%d", k.N.BitLen()) 113 case *ecdsa.PrivateKey: 114 pub = &k.PublicKey 115 desc = "ECDSA-" + k.Curve.Params().Name 116 default: 117 t.Fatalf("invalid key %T", key) 118 } 119 120 der, err := CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) 121 if err != nil { 122 t.Fatal(err) 123 } 124 cert, err := ParseCertificate(der) 125 if err != nil { 126 t.Fatal(err) 127 } 128 129 // Tell isBoringCertificate to enforce FIPS restrictions for this check. 130 fipstls.Force() 131 defer fipstls.Abandon() 132 133 fipsOK := mode&boringCertFIPSOK != 0 134 if boringAllowCert(cert) != fipsOK { 135 t.Errorf("boringAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK) 136 } 137 return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} 138 }