github.com/pion/dtls/v2@v2.2.12/pkg/crypto/prf/prf.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package prf implements TLS 1.2 Pseudorandom functions 5 package prf 6 7 import ( //nolint:gci 8 ellipticStdlib "crypto/elliptic" 9 "crypto/hmac" 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "hash" 14 "math" 15 16 "github.com/pion/dtls/v2/pkg/crypto/elliptic" 17 "github.com/pion/dtls/v2/pkg/protocol" 18 "golang.org/x/crypto/curve25519" 19 ) 20 21 const ( 22 masterSecretLabel = "master secret" 23 extendedMasterSecretLabel = "extended master secret" 24 keyExpansionLabel = "key expansion" 25 verifyDataClientLabel = "client finished" 26 verifyDataServerLabel = "server finished" 27 ) 28 29 // HashFunc allows callers to decide what hash is used in PRF 30 type HashFunc func() hash.Hash 31 32 // EncryptionKeys is all the state needed for a TLS CipherSuite 33 type EncryptionKeys struct { 34 MasterSecret []byte 35 ClientMACKey []byte 36 ServerMACKey []byte 37 ClientWriteKey []byte 38 ServerWriteKey []byte 39 ClientWriteIV []byte 40 ServerWriteIV []byte 41 } 42 43 var errInvalidNamedCurve = &protocol.FatalError{Err: errors.New("invalid named curve")} //nolint:goerr113 44 45 func (e *EncryptionKeys) String() string { 46 return fmt.Sprintf(`encryptionKeys: 47 - masterSecret: %#v 48 - clientMACKey: %#v 49 - serverMACKey: %#v 50 - clientWriteKey: %#v 51 - serverWriteKey: %#v 52 - clientWriteIV: %#v 53 - serverWriteIV: %#v 54 `, 55 e.MasterSecret, 56 e.ClientMACKey, 57 e.ServerMACKey, 58 e.ClientWriteKey, 59 e.ServerWriteKey, 60 e.ClientWriteIV, 61 e.ServerWriteIV) 62 } 63 64 // PSKPreMasterSecret generates the PSK Premaster Secret 65 // The premaster secret is formed as follows: if the PSK is N octets 66 // long, concatenate a uint16 with the value N, N zero octets, a second 67 // uint16 with the value N, and the PSK itself. 68 // 69 // https://tools.ietf.org/html/rfc4279#section-2 70 func PSKPreMasterSecret(psk []byte) []byte { 71 pskLen := uint16(len(psk)) 72 73 out := append(make([]byte, 2+pskLen+2), psk...) 74 binary.BigEndian.PutUint16(out, pskLen) 75 binary.BigEndian.PutUint16(out[2+pskLen:], pskLen) 76 77 return out 78 } 79 80 // EcdhePSKPreMasterSecret implements TLS 1.2 Premaster Secret generation given a psk, a keypair and a curve 81 // 82 // https://datatracker.ietf.org/doc/html/rfc5489#section-2 83 func EcdhePSKPreMasterSecret(psk, publicKey, privateKey []byte, curve elliptic.Curve) ([]byte, error) { 84 preMasterSecret, err := PreMasterSecret(publicKey, privateKey, curve) 85 if err != nil { 86 return nil, err 87 } 88 out := make([]byte, 2+len(preMasterSecret)+2+len(psk)) 89 90 // write preMasterSecret length 91 offset := 0 92 binary.BigEndian.PutUint16(out[offset:], uint16(len(preMasterSecret))) 93 offset += 2 94 95 // write preMasterSecret 96 copy(out[offset:], preMasterSecret) 97 offset += len(preMasterSecret) 98 99 // write psk length 100 binary.BigEndian.PutUint16(out[offset:], uint16(len(psk))) 101 offset += 2 102 103 // write psk 104 copy(out[offset:], psk) 105 return out, nil 106 } 107 108 // PreMasterSecret implements TLS 1.2 Premaster Secret generation given a keypair and a curve 109 func PreMasterSecret(publicKey, privateKey []byte, curve elliptic.Curve) ([]byte, error) { 110 switch curve { 111 case elliptic.X25519: 112 return curve25519.X25519(privateKey, publicKey) 113 case elliptic.P256: 114 return ellipticCurvePreMasterSecret(publicKey, privateKey, ellipticStdlib.P256(), ellipticStdlib.P256()) 115 case elliptic.P384: 116 return ellipticCurvePreMasterSecret(publicKey, privateKey, ellipticStdlib.P384(), ellipticStdlib.P384()) 117 default: 118 return nil, errInvalidNamedCurve 119 } 120 } 121 122 func ellipticCurvePreMasterSecret(publicKey, privateKey []byte, c1, c2 ellipticStdlib.Curve) ([]byte, error) { 123 x, y := ellipticStdlib.Unmarshal(c1, publicKey) 124 if x == nil || y == nil { 125 return nil, errInvalidNamedCurve 126 } 127 128 result, _ := c2.ScalarMult(x, y, privateKey) 129 preMasterSecret := make([]byte, (c2.Params().BitSize+7)>>3) 130 resultBytes := result.Bytes() 131 copy(preMasterSecret[len(preMasterSecret)-len(resultBytes):], resultBytes) 132 return preMasterSecret, nil 133 } 134 135 // PHash is PRF is the SHA-256 hash function is used for all cipher suites 136 // defined in this TLS 1.2 document and in TLS documents published prior to this 137 // document when TLS 1.2 is negotiated. New cipher suites MUST explicitly 138 // specify a PRF and, in general, SHOULD use the TLS PRF with SHA-256 or a 139 // stronger standard hash function. 140 // 141 // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + 142 // HMAC_hash(secret, A(2) + seed) + 143 // HMAC_hash(secret, A(3) + seed) + ... 144 // 145 // A() is defined as: 146 // 147 // A(0) = seed 148 // A(i) = HMAC_hash(secret, A(i-1)) 149 // 150 // P_hash can be iterated as many times as necessary to produce the 151 // required quantity of data. For example, if P_SHA256 is being used to 152 // create 80 bytes of data, it will have to be iterated three times 153 // (through A(3)), creating 96 bytes of output data; the last 16 bytes 154 // of the final iteration will then be discarded, leaving 80 bytes of 155 // output data. 156 // 157 // https://tools.ietf.org/html/rfc4346w 158 func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) { 159 hmacSHA256 := func(key, data []byte) ([]byte, error) { 160 mac := hmac.New(h, key) 161 if _, err := mac.Write(data); err != nil { 162 return nil, err 163 } 164 return mac.Sum(nil), nil 165 } 166 167 var err error 168 lastRound := seed 169 out := []byte{} 170 171 iterations := int(math.Ceil(float64(requestedLength) / float64(h().Size()))) 172 for i := 0; i < iterations; i++ { 173 lastRound, err = hmacSHA256(secret, lastRound) 174 if err != nil { 175 return nil, err 176 } 177 withSecret, err := hmacSHA256(secret, append(lastRound, seed...)) 178 if err != nil { 179 return nil, err 180 } 181 out = append(out, withSecret...) 182 } 183 184 return out[:requestedLength], nil 185 } 186 187 // ExtendedMasterSecret generates a Extended MasterSecret as defined in 188 // https://tools.ietf.org/html/rfc7627 189 func ExtendedMasterSecret(preMasterSecret, sessionHash []byte, h HashFunc) ([]byte, error) { 190 seed := append([]byte(extendedMasterSecretLabel), sessionHash...) 191 return PHash(preMasterSecret, seed, 48, h) 192 } 193 194 // MasterSecret generates a TLS 1.2 MasterSecret 195 func MasterSecret(preMasterSecret, clientRandom, serverRandom []byte, h HashFunc) ([]byte, error) { 196 seed := append(append([]byte(masterSecretLabel), clientRandom...), serverRandom...) 197 return PHash(preMasterSecret, seed, 48, h) 198 } 199 200 // GenerateEncryptionKeys is the final step TLS 1.2 PRF. Given all state generated so far generates 201 // the final keys need for encryption 202 func GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int, h HashFunc) (*EncryptionKeys, error) { 203 seed := append(append([]byte(keyExpansionLabel), serverRandom...), clientRandom...) 204 keyMaterial, err := PHash(masterSecret, seed, (2*macLen)+(2*keyLen)+(2*ivLen), h) 205 if err != nil { 206 return nil, err 207 } 208 209 clientMACKey := keyMaterial[:macLen] 210 keyMaterial = keyMaterial[macLen:] 211 212 serverMACKey := keyMaterial[:macLen] 213 keyMaterial = keyMaterial[macLen:] 214 215 clientWriteKey := keyMaterial[:keyLen] 216 keyMaterial = keyMaterial[keyLen:] 217 218 serverWriteKey := keyMaterial[:keyLen] 219 keyMaterial = keyMaterial[keyLen:] 220 221 clientWriteIV := keyMaterial[:ivLen] 222 keyMaterial = keyMaterial[ivLen:] 223 224 serverWriteIV := keyMaterial[:ivLen] 225 226 return &EncryptionKeys{ 227 MasterSecret: masterSecret, 228 ClientMACKey: clientMACKey, 229 ServerMACKey: serverMACKey, 230 ClientWriteKey: clientWriteKey, 231 ServerWriteKey: serverWriteKey, 232 ClientWriteIV: clientWriteIV, 233 ServerWriteIV: serverWriteIV, 234 }, nil 235 } 236 237 func prfVerifyData(masterSecret, handshakeBodies []byte, label string, hashFunc HashFunc) ([]byte, error) { 238 h := hashFunc() 239 if _, err := h.Write(handshakeBodies); err != nil { 240 return nil, err 241 } 242 243 seed := append([]byte(label), h.Sum(nil)...) 244 return PHash(masterSecret, seed, 12, hashFunc) 245 } 246 247 // VerifyDataClient is caled on the Client Side to either verify or generate the VerifyData message 248 func VerifyDataClient(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { 249 return prfVerifyData(masterSecret, handshakeBodies, verifyDataClientLabel, h) 250 } 251 252 // VerifyDataServer is caled on the Server Side to either verify or generate the VerifyData message 253 func VerifyDataServer(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { 254 return prfVerifyData(masterSecret, handshakeBodies, verifyDataServerLabel, h) 255 }