github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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, 512), nil, boringCertCA) 58 R3 := testBoringCert(t, "R3", boringRSAKey(t, 4096), nil, boringCertCA|boringCertFIPSOK) 59 60 M1_R1 := testBoringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK) 61 M2_R1 := testBoringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA) 62 63 I_R1 := testBoringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) 64 testBoringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) 65 testBoringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK) 66 testBoringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK) 67 68 I_R3 := testBoringCert(t, "I_R3", boringRSAKey(t, 3072), R3, boringCertCA|boringCertFIPSOK) 69 testBoringCert(t, "I_R3", I_R3.key, R3, boringCertCA|boringCertFIPSOK) 70 71 testBoringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK) 72 testBoringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf) 73 } 74 75 func testBoringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate { 76 org := name 77 parentOrg := "" 78 if i := strings.Index(org, "_"); i >= 0 { 79 org = org[:i] 80 parentOrg = name[i+1:] 81 } 82 tmpl := &Certificate{ 83 SerialNumber: big.NewInt(1), 84 Subject: pkix.Name{ 85 Organization: []string{org}, 86 }, 87 NotBefore: time.Unix(0, 0), 88 NotAfter: time.Unix(0, 0), 89 90 KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature, 91 ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, 92 BasicConstraintsValid: true, 93 } 94 if mode&^boringCertFIPSOK == boringCertLeaf { 95 tmpl.DNSNames = []string{"example.com"} 96 } else { 97 tmpl.IsCA = true 98 tmpl.KeyUsage |= KeyUsageCertSign 99 } 100 101 var pcert *Certificate 102 var pkey interface{} 103 if parent != nil { 104 pcert = parent.cert 105 pkey = parent.key 106 } else { 107 pcert = tmpl 108 pkey = key 109 } 110 111 var pub interface{} 112 var desc string 113 switch k := key.(type) { 114 case *rsa.PrivateKey: 115 pub = &k.PublicKey 116 desc = fmt.Sprintf("RSA-%d", k.N.BitLen()) 117 case *ecdsa.PrivateKey: 118 pub = &k.PublicKey 119 desc = "ECDSA-" + k.Curve.Params().Name 120 default: 121 t.Fatalf("invalid key %T", key) 122 } 123 124 der, err := CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) 125 if err != nil { 126 t.Fatal(err) 127 } 128 cert, err := ParseCertificate(der) 129 if err != nil { 130 t.Fatal(err) 131 } 132 133 // Tell isBoringCertificate to enforce FIPS restrictions for this check. 134 fipstls.Force() 135 defer fipstls.Abandon() 136 137 fipsOK := mode&boringCertFIPSOK != 0 138 if boringAllowCert(cert) != fipsOK { 139 t.Errorf("boringAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK) 140 } 141 return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} 142 }