github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/gmtls/prf.go (about) 1 /* 2 Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package gmtls 17 18 import ( 19 "crypto" 20 "crypto/hmac" 21 "crypto/md5" 22 "crypto/sha1" 23 "crypto/sha256" 24 "crypto/sha512" 25 "errors" 26 "fmt" 27 "github.com/Hyperledger-TWGC/tjfoc-gm/sm3" 28 "hash" 29 ) 30 31 // Split a premaster secret in two as specified in RFC 4346, section 5. 32 func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { 33 s1 = secret[0 : (len(secret)+1)/2] 34 s2 = secret[len(secret)/2:] 35 return 36 } 37 38 // pHash implements the P_hash function, as defined in RFC 4346, section 5. 39 func pHash(result, secret, seed []byte, hash func() hash.Hash) { 40 h := hmac.New(hash, secret) 41 h.Write(seed) 42 a := h.Sum(nil) 43 44 j := 0 45 for j < len(result) { 46 h.Reset() 47 h.Write(a) 48 h.Write(seed) 49 b := h.Sum(nil) 50 todo := len(b) 51 if j+todo > len(result) { 52 todo = len(result) - j 53 } 54 copy(result[j:j+todo], b) 55 j += todo 56 57 h.Reset() 58 h.Write(a) 59 a = h.Sum(nil) 60 } 61 } 62 63 // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5. 64 func prf10(result, secret, label, seed []byte) { 65 hashSHA1 := sha1.New 66 hashMD5 := md5.New 67 68 labelAndSeed := make([]byte, len(label)+len(seed)) 69 copy(labelAndSeed, label) 70 copy(labelAndSeed[len(label):], seed) 71 72 s1, s2 := splitPreMasterSecret(secret) 73 pHash(result, s1, labelAndSeed, hashMD5) 74 result2 := make([]byte, len(result)) 75 pHash(result2, s2, labelAndSeed, hashSHA1) 76 77 for i, b := range result2 { 78 result[i] ^= b 79 } 80 } 81 82 // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5. 83 func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { 84 return func(result, secret, label, seed []byte) { 85 labelAndSeed := make([]byte, len(label)+len(seed)) 86 copy(labelAndSeed, label) 87 copy(labelAndSeed[len(label):], seed) 88 89 pHash(result, secret, labelAndSeed, hashFunc) 90 } 91 } 92 93 // prf30 implements the SSL 3.0 pseudo-random function, as defined in 94 // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6. 95 func prf30(result, secret, label, seed []byte) { 96 hashSHA1 := sha1.New() 97 hashMD5 := md5.New() 98 99 done := 0 100 i := 0 101 // RFC 5246 section 6.3 says that the largest PRF output needed is 128 102 // bytes. Since no more ciphersuites will be added to SSLv3, this will 103 // remain true. Each iteration gives us 16 bytes so 10 iterations will 104 // be sufficient. 105 var b [11]byte 106 for done < len(result) { 107 for j := 0; j <= i; j++ { 108 b[j] = 'A' + byte(i) 109 } 110 111 hashSHA1.Reset() 112 hashSHA1.Write(b[:i+1]) 113 hashSHA1.Write(secret) 114 hashSHA1.Write(seed) 115 digest := hashSHA1.Sum(nil) 116 117 hashMD5.Reset() 118 hashMD5.Write(secret) 119 hashMD5.Write(digest) 120 121 done += copy(result[done:], hashMD5.Sum(nil)) 122 i++ 123 } 124 } 125 126 const ( 127 tlsRandomLength = 32 // Length of a random nonce in TLS 1.1. 128 masterSecretLength = 48 // Length of a master secret in TLS 1.1. 129 finishedVerifyLength = 12 // Length of verify_data in a Finished message. 130 ) 131 132 var masterSecretLabel = []byte("master secret") 133 var keyExpansionLabel = []byte("key expansion") 134 var clientFinishedLabel = []byte("client finished") 135 var serverFinishedLabel = []byte("server finished") 136 137 func prfAndHashForGM() func(result, secret, label, seed []byte) { 138 return prf12(sm3.New) 139 } 140 141 func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { 142 switch version { 143 case VersionSSL30: 144 return prf30, crypto.Hash(0) 145 case VersionTLS10, VersionTLS11: 146 return prf10, crypto.Hash(0) 147 case VersionTLS12: 148 if suite.flags&suiteSHA384 != 0 { 149 return prf12(sha512.New384), crypto.SHA384 150 } 151 return prf12(sha256.New), crypto.SHA256 152 default: 153 panic("unknown version") 154 } 155 } 156 157 func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { 158 var prf func(result, secret, label, seed []byte) 159 if version == VersionGMSSL { 160 prf = prfAndHashForGM() 161 } else { 162 prf, _ = prfAndHashForVersion(version, suite) 163 } 164 return prf 165 } 166 167 // masterFromPreMasterSecret generates the master secret from the pre-master 168 // secret. See http://tools.ietf.org/html/rfc5246#section-8.1 169 func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { 170 seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) 171 seed = append(seed, clientRandom...) 172 seed = append(seed, serverRandom...) 173 174 masterSecret := make([]byte, masterSecretLength) 175 prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) 176 return masterSecret 177 } 178 179 // keysFromMasterSecret generates the connection keys from the master 180 // secret, given the lengths of the MAC key, cipher key and IV, as defined in 181 // RFC 2246, section 6.3. 182 func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { 183 seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) 184 seed = append(seed, serverRandom...) 185 seed = append(seed, clientRandom...) 186 187 n := 2*macLen + 2*keyLen + 2*ivLen 188 keyMaterial := make([]byte, n) 189 prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) 190 clientMAC = keyMaterial[:macLen] 191 keyMaterial = keyMaterial[macLen:] 192 serverMAC = keyMaterial[:macLen] 193 keyMaterial = keyMaterial[macLen:] 194 clientKey = keyMaterial[:keyLen] 195 keyMaterial = keyMaterial[keyLen:] 196 serverKey = keyMaterial[:keyLen] 197 keyMaterial = keyMaterial[keyLen:] 198 clientIV = keyMaterial[:ivLen] 199 keyMaterial = keyMaterial[ivLen:] 200 serverIV = keyMaterial[:ivLen] 201 return 202 } 203 204 // lookupTLSHash looks up the corresponding crypto.Hash for a given 205 // TLS hash identifier. 206 func lookupTLSHash(signatureAlgorithm SignatureScheme) (crypto.Hash, error) { 207 switch signatureAlgorithm { 208 case PKCS1WithSHA1, ECDSAWithSHA1: 209 return crypto.SHA1, nil 210 case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256: 211 return crypto.SHA256, nil 212 case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384: 213 return crypto.SHA384, nil 214 case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512: 215 return crypto.SHA512, nil 216 default: 217 return 0, fmt.Errorf("tls: unsupported signature algorithm: %#04x", signatureAlgorithm) 218 } 219 } 220 func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { 221 var buffer []byte 222 if version == VersionSSL30 || version >= VersionTLS12 { 223 buffer = []byte{} 224 } 225 226 var prf func(result, secret, label, seed []byte) 227 228 if version == VersionGMSSL { 229 prf = prfAndHashForGM() 230 return finishedHash{sm3.New(), sm3.New(), nil, nil, buffer, version, prf} 231 } else { 232 prf, hash := prfAndHashForVersion(version, cipherSuite) 233 if hash != 0 { 234 return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} 235 } 236 } 237 238 return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} 239 } 240 241 // A finishedHash calculates the hash of a set of handshake messages suitable 242 // for including in a Finished message. 243 type finishedHash struct { 244 client hash.Hash 245 server hash.Hash 246 247 // Prior to TLS 1.2, an additional MD5 hash is required. 248 clientMD5 hash.Hash 249 serverMD5 hash.Hash 250 251 // In TLS 1.2, a full buffer is sadly required. 252 buffer []byte 253 254 version uint16 255 prf func(result, secret, label, seed []byte) 256 } 257 258 func (h *finishedHash) Write(msg []byte) (n int, err error) { 259 h.client.Write(msg) 260 h.server.Write(msg) 261 262 if h.version < VersionTLS12 { 263 h.clientMD5.Write(msg) 264 h.serverMD5.Write(msg) 265 } 266 267 if h.buffer != nil { 268 h.buffer = append(h.buffer, msg...) 269 } 270 271 return len(msg), nil 272 } 273 274 func (h finishedHash) Sum() []byte { 275 if h.version >= VersionTLS12 || h.version == VersionGMSSL { 276 return h.client.Sum(nil) 277 } 278 279 out := make([]byte, 0, md5.Size+sha1.Size) 280 out = h.clientMD5.Sum(out) 281 return h.client.Sum(out) 282 } 283 284 // finishedSum30 calculates the contents of the verify_data member of a SSLv3 285 // Finished message given the MD5 and SHA1 hashes of a set of handshake 286 // messages. 287 func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte { 288 md5.Write(magic) 289 md5.Write(masterSecret) 290 md5.Write(ssl30Pad1[:]) 291 md5Digest := md5.Sum(nil) 292 293 md5.Reset() 294 md5.Write(masterSecret) 295 md5.Write(ssl30Pad2[:]) 296 md5.Write(md5Digest) 297 md5Digest = md5.Sum(nil) 298 299 sha1.Write(magic) 300 sha1.Write(masterSecret) 301 sha1.Write(ssl30Pad1[:40]) 302 sha1Digest := sha1.Sum(nil) 303 304 sha1.Reset() 305 sha1.Write(masterSecret) 306 sha1.Write(ssl30Pad2[:40]) 307 sha1.Write(sha1Digest) 308 sha1Digest = sha1.Sum(nil) 309 310 ret := make([]byte, len(md5Digest)+len(sha1Digest)) 311 copy(ret, md5Digest) 312 copy(ret[len(md5Digest):], sha1Digest) 313 return ret 314 } 315 316 var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54} 317 var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52} 318 319 // clientSum returns the contents of the verify_data member of a client's 320 // Finished message. 321 func (h finishedHash) clientSum(masterSecret []byte) []byte { 322 if h.version == VersionSSL30 { 323 return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:]) 324 } 325 326 out := make([]byte, finishedVerifyLength) 327 h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) 328 return out 329 } 330 331 // serverSum returns the contents of the verify_data member of a server's 332 // Finished message. 333 func (h finishedHash) serverSum(masterSecret []byte) []byte { 334 if h.version == VersionSSL30 { 335 return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:]) 336 } 337 338 out := make([]byte, finishedVerifyLength) 339 h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) 340 return out 341 } 342 343 // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash 344 // id suitable for signing by a TLS client certificate. 345 func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) ([]byte, error) { 346 if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil { 347 panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer") 348 } 349 350 if h.version == VersionSSL30 { 351 if sigType != signaturePKCS1v15 { 352 return nil, errors.New("tls: unsupported signature type for client certificate") 353 } 354 355 md5Hash := md5.New() 356 md5Hash.Write(h.buffer) 357 sha1Hash := sha1.New() 358 sha1Hash.Write(h.buffer) 359 return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), nil 360 } 361 if h.version >= VersionTLS12 { 362 hash := hashAlg.New() 363 hash.Write(h.buffer) 364 return hash.Sum(nil), nil 365 } 366 367 if sigType == signatureECDSA { 368 return h.server.Sum(nil), nil 369 } 370 371 return h.Sum(), nil 372 } 373 374 // discardHandshakeBuffer is called when there is no more need to 375 // buffer the entirety of the handshake messages. 376 func (h *finishedHash) discardHandshakeBuffer() { 377 h.buffer = nil 378 } 379 380 // noExportedKeyingMaterial is used as a value of 381 // ConnectionState.ekm when renegotation is enabled and thus 382 // we wish to fail all key-material export requests. 383 func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { 384 return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") 385 } 386 387 // ekmFromMasterSecret generates exported keying material as defined in 388 // https://tools.ietf.org/html/rfc5705. 389 func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { 390 return func(label string, context []byte, length int) ([]byte, error) { 391 switch label { 392 case "client finished", "server finished", "master secret", "key expansion": 393 // These values are reserved and may not be used. 394 return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) 395 } 396 397 seedLen := len(serverRandom) + len(clientRandom) 398 if context != nil { 399 seedLen += 2 + len(context) 400 } 401 seed := make([]byte, 0, seedLen) 402 403 seed = append(seed, clientRandom...) 404 seed = append(seed, serverRandom...) 405 406 if context != nil { 407 if len(context) >= 1<<16 { 408 return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") 409 } 410 seed = append(seed, byte(len(context)>>8), byte(len(context))) 411 seed = append(seed, context...) 412 } 413 414 keyMaterial := make([]byte, length) 415 prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) 416 return keyMaterial, nil 417 } 418 }