1// Copyright 2019 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 5package cpu 6 7const ( 8 // bit mask values from /usr/include/bits/hwcap.h 9 hwcap_ZARCH = 2 10 hwcap_STFLE = 4 11 hwcap_MSA = 8 12 hwcap_LDISP = 16 13 hwcap_EIMM = 32 14 hwcap_DFP = 64 15 hwcap_ETF3EH = 256 16 hwcap_VX = 2048 17 hwcap_VXE = 8192 18) 19 20// bitIsSet reports whether the bit at index is set. The bit index 21// is in big endian order, so bit index 0 is the leftmost bit. 22func bitIsSet(bits []uint64, index uint) bool { 23 return bits[index/64]&((1<<63)>>(index%64)) != 0 24} 25 26// function is the code for the named cryptographic function. 27type function uint8 28 29const ( 30 // KM{,A,C,CTR} function codes 31 aes128 function = 18 // AES-128 32 aes192 function = 19 // AES-192 33 aes256 function = 20 // AES-256 34 35 // K{I,L}MD function codes 36 sha1 function = 1 // SHA-1 37 sha256 function = 2 // SHA-256 38 sha512 function = 3 // SHA-512 39 sha3_224 function = 32 // SHA3-224 40 sha3_256 function = 33 // SHA3-256 41 sha3_384 function = 34 // SHA3-384 42 sha3_512 function = 35 // SHA3-512 43 shake128 function = 36 // SHAKE-128 44 shake256 function = 37 // SHAKE-256 45 46 // KLMD function codes 47 ghash function = 65 // GHASH 48) 49 50// queryResult contains the result of a Query function 51// call. Bits are numbered in big endian order so the 52// leftmost bit (the MSB) is at index 0. 53type queryResult struct { 54 bits [2]uint64 55} 56 57// Has reports whether the given functions are present. 58func (q *queryResult) Has(fns ...function) bool { 59 if len(fns) == 0 { 60 panic("no function codes provided") 61 } 62 for _, f := range fns { 63 if !bitIsSet(q.bits[:], uint(f)) { 64 return false 65 } 66 } 67 return true 68} 69 70// facility is a bit index for the named facility. 71type facility uint8 72 73const ( 74 // cryptography facilities 75 msa4 facility = 77 // message-security-assist extension 4 76 msa8 facility = 146 // message-security-assist extension 8 77) 78 79// facilityList contains the result of an STFLE call. 80// Bits are numbered in big endian order so the 81// leftmost bit (the MSB) is at index 0. 82type facilityList struct { 83 bits [4]uint64 84} 85 86// Has reports whether the given facilities are present. 87func (s *facilityList) Has(fs ...facility) bool { 88 if len(fs) == 0 { 89 panic("no facility bits provided") 90 } 91 for _, f := range fs { 92 if !bitIsSet(s.bits[:], uint(f)) { 93 return false 94 } 95 } 96 return true 97} 98 99func doinit() { 100 // test HWCAP bit vector 101 has := func(featureMask uint) bool { 102 return hwCap&featureMask == featureMask 103 } 104 105 // mandatory 106 S390X.HasZARCH = has(hwcap_ZARCH) 107 108 // optional 109 S390X.HasSTFLE = has(hwcap_STFLE) 110 S390X.HasLDISP = has(hwcap_LDISP) 111 S390X.HasEIMM = has(hwcap_EIMM) 112 S390X.HasETF3EH = has(hwcap_ETF3EH) 113 S390X.HasDFP = has(hwcap_DFP) 114 S390X.HasMSA = has(hwcap_MSA) 115 S390X.HasVX = has(hwcap_VX) 116 if S390X.HasVX { 117 S390X.HasVXE = has(hwcap_VXE) 118 } 119 120 // We need implementations of stfle, km and so on 121 // to detect cryptographic features. 122 if !haveAsmFunctions() { 123 return 124 } 125 126 // optional cryptographic functions 127 if S390X.HasMSA { 128 aes := []function{aes128, aes192, aes256} 129 130 // cipher message 131 km, kmc := kmQuery(), kmcQuery() 132 S390X.HasAES = km.Has(aes...) 133 S390X.HasAESCBC = kmc.Has(aes...) 134 if S390X.HasSTFLE { 135 facilities := stfle() 136 if facilities.Has(msa4) { 137 kmctr := kmctrQuery() 138 S390X.HasAESCTR = kmctr.Has(aes...) 139 } 140 if facilities.Has(msa8) { 141 kma := kmaQuery() 142 S390X.HasAESGCM = kma.Has(aes...) 143 } 144 } 145 146 // compute message digest 147 kimd := kimdQuery() // intermediate (no padding) 148 klmd := klmdQuery() // last (padding) 149 S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) 150 S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) 151 S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) 152 S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist 153 sha3 := []function{ 154 sha3_224, sha3_256, sha3_384, sha3_512, 155 shake128, shake256, 156 } 157 S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) 158 } 159} 160