1// Copyright 2023 The BoringSSL Authors 2// 3// Permission to use, copy, modify, and/or distribute this software for any 4// purpose with or without fee is hereby granted, provided that the above 5// copyright notice and this permission notice appear in all copies. 6// 7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15package subprocess 16 17import ( 18 "crypto/sha256" 19 "crypto/sha512" 20 "encoding/hex" 21 "encoding/json" 22 "fmt" 23) 24 25// The following structures reflect the JSON of TLS 1.3 tests. See 26// https://pages.nist.gov/ACVP/draft-hammett-acvp-kdf-tls-v1.3.html 27 28type tls13TestVectorSet struct { 29 Groups []tls13TestGroup `json:"testGroups"` 30} 31 32type tls13TestGroup struct { 33 ID uint64 `json:"tgId"` 34 HashFunc string `json:"hmacAlg"` 35 Tests []tls13Test `json:"tests"` 36} 37 38type tls13Test struct { 39 ID uint64 `json:"tcId"` 40 // Although ACVP refers to these as client and server randoms, these 41 // fields are misnamed and really contain portions of the handshake 42 // transcript. Concatenated in order, they give the transcript up to 43 // the named message. In case of HelloRetryRequest, ClientHelloHex 44 // includes up to the second ClientHello. 45 ClientHelloHex string `json:"helloClientRandom"` 46 ServerHelloHex string `json:"helloServerRandom"` 47 ServerFinishedHex string `json:"finishedServerRandom"` 48 ClientFinishedHex string `json:"finishedClientRandom"` 49 DHEInputHex string `json:"dhe"` 50 PSKInputHex string `json:"psk"` 51} 52 53type tls13TestGroupResponse struct { 54 ID uint64 `json:"tgId"` 55 Tests []tls13TestResponse `json:"tests"` 56} 57 58type tls13TestResponse struct { 59 ID uint64 `json:"tcId"` 60 ClientEarlyTrafficSecretHex string `json:"clientEarlyTrafficSecret"` 61 EarlyExporterMasterSecretHex string `json:"earlyExporterMasterSecret"` 62 ClientHandshakeTrafficSecretHex string `json:"clientHandshakeTrafficSecret"` 63 ServerHandshakeTrafficSecretHex string `json:"serverHandshakeTrafficSecret"` 64 ClientApplicationTrafficSecretHex string `json:"clientApplicationTrafficSecret"` 65 ServerApplicationTrafficSecretHex string `json:"serverApplicationTrafficSecret"` 66 ExporterMasterSecretHex string `json:"exporterMasterSecret"` 67 ResumptionMasterSecretHex string `json:"resumptionMasterSecret"` 68} 69 70type tls13 struct{} 71 72func (k *tls13) Process(vectorSet []byte, m Transactable) (any, error) { 73 var parsed tls13TestVectorSet 74 if err := json.Unmarshal(vectorSet, &parsed); err != nil { 75 return nil, err 76 } 77 78 var respGroups []tls13TestGroupResponse 79 for _, group := range parsed.Groups { 80 group := group 81 groupResp := tls13TestGroupResponse{ID: group.ID} 82 83 for _, test := range group.Tests { 84 test := test 85 testResp := tls13TestResponse{ID: test.ID} 86 87 clientHello, err := hex.DecodeString(test.ClientHelloHex) 88 if err != nil { 89 return nil, err 90 } 91 serverHello, err := hex.DecodeString(test.ServerHelloHex) 92 if err != nil { 93 return nil, err 94 } 95 serverFinished, err := hex.DecodeString(test.ServerFinishedHex) 96 if err != nil { 97 return nil, err 98 } 99 clientFinished, err := hex.DecodeString(test.ClientFinishedHex) 100 if err != nil { 101 return nil, err 102 } 103 104 // See https://www.rfc-editor.org/rfc/rfc8446#section-7.1 105 var hashLen int 106 var emptyHash []byte 107 switch group.HashFunc { 108 case "SHA2-256": 109 hashLen = 256 / 8 110 digest := sha256.Sum256(nil) 111 emptyHash = digest[:] 112 case "SHA2-384": 113 hashLen = 384 / 8 114 digest := sha512.Sum384(nil) 115 emptyHash = digest[:] 116 default: 117 return nil, fmt.Errorf("hash function %q is not supported for TLS v1.3", group.HashFunc) 118 } 119 hashLenBytes := uint32le(uint32(hashLen)) 120 121 psk, err := hex.DecodeString(test.PSKInputHex) 122 if err != nil { 123 return nil, err 124 } 125 if len(psk) == 0 { 126 psk = make([]byte, hashLen) 127 } 128 129 dhe, err := hex.DecodeString(test.DHEInputHex) 130 if err != nil { 131 return nil, err 132 } 133 if len(dhe) == 0 { 134 dhe = make([]byte, hashLen) 135 } 136 137 zeros := make([]byte, hashLen) 138 earlySecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, psk, zeros) 139 if err != nil { 140 return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) 141 } 142 143 hashedToClientHello, err := m.Transact(group.HashFunc, 1, clientHello) 144 if err != nil { 145 return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) 146 } 147 hashedToServerHello, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello)) 148 if err != nil { 149 return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) 150 } 151 hashedToServerFinished, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished)) 152 if err != nil { 153 return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) 154 } 155 hashedMessages, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished, clientFinished)) 156 if err != nil { 157 return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) 158 } 159 160 clientEarlyTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("c e traffic"), hashedToClientHello[0]) 161 if err != nil { 162 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 163 } 164 testResp.ClientEarlyTrafficSecretHex = hex.EncodeToString(clientEarlyTrafficSecret[0]) 165 166 earlyExporter, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("e exp master"), hashedToClientHello[0]) 167 if err != nil { 168 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 169 } 170 testResp.EarlyExporterMasterSecretHex = hex.EncodeToString(earlyExporter[0]) 171 172 derivedSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("derived"), emptyHash[:]) 173 if err != nil { 174 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 175 } 176 177 handshakeSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, dhe, derivedSecret[0]) 178 if err != nil { 179 return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) 180 } 181 182 clientHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("c hs traffic"), hashedToServerHello[0]) 183 if err != nil { 184 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 185 } 186 testResp.ClientHandshakeTrafficSecretHex = hex.EncodeToString(clientHandshakeTrafficSecret[0]) 187 188 serverHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("s hs traffic"), hashedToServerHello[0]) 189 if err != nil { 190 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 191 } 192 testResp.ServerHandshakeTrafficSecretHex = hex.EncodeToString(serverHandshakeTrafficSecret[0]) 193 194 derivedSecret, err = m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("derived"), emptyHash[:]) 195 if err != nil { 196 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 197 } 198 199 masterSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, zeros, derivedSecret[0]) 200 if err != nil { 201 return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) 202 } 203 204 clientAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("c ap traffic"), hashedToServerFinished[0]) 205 if err != nil { 206 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 207 } 208 testResp.ClientApplicationTrafficSecretHex = hex.EncodeToString(clientAppTrafficSecret[0]) 209 210 serverAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("s ap traffic"), hashedToServerFinished[0]) 211 if err != nil { 212 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 213 } 214 testResp.ServerApplicationTrafficSecretHex = hex.EncodeToString(serverAppTrafficSecret[0]) 215 216 exporterSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("exp master"), hashedToServerFinished[0]) 217 if err != nil { 218 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 219 } 220 testResp.ExporterMasterSecretHex = hex.EncodeToString(exporterSecret[0]) 221 222 resumptionSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("res master"), hashedMessages[0]) 223 if err != nil { 224 return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) 225 } 226 testResp.ResumptionMasterSecretHex = hex.EncodeToString(resumptionSecret[0]) 227 228 groupResp.Tests = append(groupResp.Tests, testResp) 229 } 230 respGroups = append(respGroups, groupResp) 231 } 232 233 return respGroups, nil 234} 235 236func concat(slices ...[]byte) []byte { 237 var ret []byte 238 for _, slice := range slices { 239 ret = append(ret, slice...) 240 } 241 return ret 242} 243