gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/gmtls/prf.go (about) 1 // Copyright (c) 2022 zhaochun 2 // core-gm is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 /* 10 gmtls是基于`golang/go`的`tls`包实现的国密改造版本。 11 对应版权声明: thrid_licenses/github.com/golang/go/LICENSE 12 */ 13 14 package gmtls 15 16 import ( 17 "crypto" 18 "crypto/hmac" 19 "crypto/md5" 20 "crypto/sha1" 21 "crypto/sha256" 22 "crypto/sha512" 23 "errors" 24 "fmt" 25 "hash" 26 27 "gitee.com/ks-custle/core-gm/x509" 28 ) 29 30 // Split a premaster secret in two as specified in RFC 4346, Section 5. 31 func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { 32 s1 = secret[0 : (len(secret)+1)/2] 33 s2 = secret[len(secret)/2:] 34 return 35 } 36 37 // pHash implements the P_hash function, as defined in RFC 4346, Section 5. 38 func pHash(result, secret, seed []byte, hash func() hash.Hash) { 39 h := hmac.New(hash, secret) 40 h.Write(seed) 41 a := h.Sum(nil) 42 43 j := 0 44 for j < len(result) { 45 h.Reset() 46 h.Write(a) 47 h.Write(seed) 48 b := h.Sum(nil) 49 copy(result[j:], b) 50 j += len(b) 51 52 h.Reset() 53 h.Write(a) 54 a = h.Sum(nil) 55 } 56 } 57 58 // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. 59 func prf10(result, secret, label, seed []byte) { 60 hashSHA1 := sha1.New 61 hashMD5 := md5.New 62 63 labelAndSeed := make([]byte, len(label)+len(seed)) 64 copy(labelAndSeed, label) 65 copy(labelAndSeed[len(label):], seed) 66 67 s1, s2 := splitPreMasterSecret(secret) 68 pHash(result, s1, labelAndSeed, hashMD5) 69 result2 := make([]byte, len(result)) 70 pHash(result2, s2, labelAndSeed, hashSHA1) 71 72 for i, b := range result2 { 73 result[i] ^= b 74 } 75 } 76 77 // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. 78 func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { 79 return func(result, secret, label, seed []byte) { 80 labelAndSeed := make([]byte, len(label)+len(seed)) 81 copy(labelAndSeed, label) 82 copy(labelAndSeed[len(label):], seed) 83 84 pHash(result, secret, labelAndSeed, hashFunc) 85 } 86 } 87 88 const ( 89 masterSecretLength = 48 // Length of a master secret in TLS 1.1. 90 finishedVerifyLength = 12 // Length of verify_data in a Finished message. 91 ) 92 93 var masterSecretLabel = []byte("master secret") 94 var keyExpansionLabel = []byte("key expansion") 95 var clientFinishedLabel = []byte("client finished") 96 var serverFinishedLabel = []byte("server finished") 97 98 func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { 99 switch version { 100 case VersionTLS10, VersionTLS11: 101 return prf10, crypto.Hash(0) 102 case VersionTLS12: 103 if suite.flags&suiteSHA384 != 0 { 104 return prf12(sha512.New384), crypto.SHA384 105 } 106 return prf12(sha256.New), crypto.SHA256 107 default: 108 panic("unknown version") 109 } 110 } 111 112 func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { 113 prf, _ := prfAndHashForVersion(version, suite) 114 return prf 115 } 116 117 // 根据预主密钥计算主密钥 118 // 119 // 算法使用PRF函数; 120 // 使用clientRandom与serverRandom拼接起来的随机数作为种子; 121 // 122 // masterFromPreMasterSecret generates the master secret from the pre-master 123 // secret. See RFC 5246, Section 8.1. 124 func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { 125 seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) 126 seed = append(seed, clientRandom...) 127 seed = append(seed, serverRandom...) 128 129 masterSecret := make([]byte, masterSecretLength) 130 prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) 131 return masterSecret 132 } 133 134 // 根据主密钥派生出会话密钥 135 // 136 // 算法使用PRF函数; 137 // 使用clientRandom与serverRandom拼接起来的随机数作为种子; 138 // 派生出六个会话密钥:clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV 139 // 140 // keysFromMasterSecret generates the connection keys from the master 141 // secret, given the lengths of the MAC key, cipher key and IV, as defined in 142 // RFC 2246, Section 6.3. 143 func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { 144 seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) 145 seed = append(seed, serverRandom...) 146 seed = append(seed, clientRandom...) 147 148 n := 2*macLen + 2*keyLen + 2*ivLen 149 keyMaterial := make([]byte, n) 150 prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) 151 clientMAC = keyMaterial[:macLen] 152 keyMaterial = keyMaterial[macLen:] 153 serverMAC = keyMaterial[:macLen] 154 keyMaterial = keyMaterial[macLen:] 155 clientKey = keyMaterial[:keyLen] 156 keyMaterial = keyMaterial[keyLen:] 157 serverKey = keyMaterial[:keyLen] 158 keyMaterial = keyMaterial[keyLen:] 159 clientIV = keyMaterial[:ivLen] 160 keyMaterial = keyMaterial[ivLen:] 161 serverIV = keyMaterial[:ivLen] 162 return 163 } 164 165 func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { 166 var buffer []byte 167 if version >= VersionTLS12 { 168 buffer = []byte{} 169 } 170 171 prf, hashVal := prfAndHashForVersion(version, cipherSuite) 172 if hashVal != 0 { 173 return finishedHash{hashVal.New(), hashVal.New(), nil, nil, buffer, version, prf} 174 } 175 176 return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} 177 } 178 179 // A finishedHash calculates the hash of a set of handshake messages suitable 180 // for including in a Finished message. 181 type finishedHash struct { 182 client hash.Hash 183 server hash.Hash 184 185 // Prior to TLS 1.2, an additional MD5 hash is required. 186 clientMD5 hash.Hash 187 serverMD5 hash.Hash 188 189 // In TLS 1.2, a full buffer is sadly required. 190 buffer []byte 191 192 version uint16 193 prf func(result, secret, label, seed []byte) 194 } 195 196 //goland:noinspection GoMixedReceiverTypes 197 func (h *finishedHash) Write(msg []byte) (n int, err error) { 198 h.client.Write(msg) 199 h.server.Write(msg) 200 201 if h.version < VersionTLS12 { 202 h.clientMD5.Write(msg) 203 h.serverMD5.Write(msg) 204 } 205 206 if h.buffer != nil { 207 h.buffer = append(h.buffer, msg...) 208 } 209 210 return len(msg), nil 211 } 212 213 //goland:noinspection GoMixedReceiverTypes 214 func (h finishedHash) Sum() []byte { 215 if h.version >= VersionTLS12 { 216 return h.client.Sum(nil) 217 } 218 219 out := make([]byte, 0, md5.Size+sha1.Size) 220 out = h.clientMD5.Sum(out) 221 return h.client.Sum(out) 222 } 223 224 // clientSum returns the contents of the verify_data member of a client's 225 // Finished message. 226 // 227 //goland:noinspection GoMixedReceiverTypes 228 func (h finishedHash) clientSum(masterSecret []byte) []byte { 229 out := make([]byte, finishedVerifyLength) 230 h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) 231 return out 232 } 233 234 // serverSum returns the contents of the verify_data member of a server's 235 // Finished message. 236 // 237 //goland:noinspection GoMixedReceiverTypes 238 func (h finishedHash) serverSum(masterSecret []byte) []byte { 239 out := make([]byte, finishedVerifyLength) 240 h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) 241 return out 242 } 243 244 // hashForClientCertificate returns the handshake messages so far, pre-hashed if 245 // necessary, suitable for signing by a TLS client certificate. 246 // 247 //goland:noinspection GoMixedReceiverTypes,GoUnusedParameter 248 func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg x509.Hash, masterSecret []byte) []byte { 249 if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { 250 panic("gmtls: handshake hash for a client certificate requested after discarding the handshake buffer") 251 } 252 253 if sigType == signatureEd25519 { 254 return h.buffer 255 } 256 257 if h.version >= VersionTLS12 { 258 hashVal := hashAlg.New() 259 hashVal.Write(h.buffer) 260 return hashVal.Sum(nil) 261 } 262 263 if sigType == signatureECDSA || sigType == signatureECDSAEXT { 264 return h.server.Sum(nil) 265 } 266 267 return h.Sum() 268 } 269 270 // discardHandshakeBuffer is called when there is no more need to 271 // buffer the entirety of the handshake messages. 272 // 273 //goland:noinspection GoMixedReceiverTypes 274 func (h *finishedHash) discardHandshakeBuffer() { 275 h.buffer = nil 276 } 277 278 // noExportedKeyingMaterial is used as a value of 279 // ConnectionState.ekm when renegotiation is enabled and thus 280 // we wish to fail all key-material export requests. 281 // 282 //goland:noinspection GoUnusedParameter 283 func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { 284 return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") 285 } 286 287 // ekmFromMasterSecret generates exported keying material as defined in RFC 5705. 288 func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { 289 return func(label string, context []byte, length int) ([]byte, error) { 290 switch label { 291 case "client finished", "server finished", "master secret", "key expansion": 292 // These values are reserved and may not be used. 293 return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) 294 } 295 296 seedLen := len(serverRandom) + len(clientRandom) 297 if context != nil { 298 seedLen += 2 + len(context) 299 } 300 seed := make([]byte, 0, seedLen) 301 302 seed = append(seed, clientRandom...) 303 seed = append(seed, serverRandom...) 304 305 if context != nil { 306 if len(context) >= 1<<16 { 307 return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") 308 } 309 seed = append(seed, byte(len(context)>>8), byte(len(context))) 310 seed = append(seed, context...) 311 } 312 313 keyMaterial := make([]byte, length) 314 prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) 315 return keyMaterial, nil 316 } 317 }