Change-Id: I32a40a73f96e029ac9096af826d15b22d9dcad28 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/58745 Auto-Submit: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com>fips-20230428
parent
d3acd45456
commit
480344d4fa
12 changed files with 392 additions and 22 deletions
@ -0,0 +1,240 @@ |
||||
// Copyright (c) 2023, Google Inc.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package subprocess |
||||
|
||||
import ( |
||||
"crypto/sha256" |
||||
"crypto/sha512" |
||||
"encoding/hex" |
||||
"encoding/json" |
||||
"fmt" |
||||
) |
||||
|
||||
// The following structures reflect the JSON of TLS 1.3 tests. See
|
||||
// https://pages.nist.gov/ACVP/draft-hammett-acvp-kdf-tls-v1.3.html
|
||||
|
||||
type tls13TestVectorSet struct { |
||||
Groups []tls13TestGroup `json:"testGroups"` |
||||
} |
||||
|
||||
type tls13TestGroup struct { |
||||
ID uint64 `json:"tgId"` |
||||
HashFunc string `json:"hmacAlg"` |
||||
Tests []tls13Test `json:"tests"` |
||||
} |
||||
|
||||
type tls13Test struct { |
||||
ID uint64 `json:"tcId"` |
||||
// Although ACVP refers to these as client and server randoms, these
|
||||
// fields are misnamed and really contain portions of the handshake
|
||||
// transcript. Concatenated in order, they give the transcript up to
|
||||
// the named message. In case of HelloRetryRequest, ClientHelloHex
|
||||
// includes up to the second ClientHello.
|
||||
ClientHelloHex string `json:"helloClientRandom"` |
||||
ServerHelloHex string `json:"helloServerRandom"` |
||||
ServerFinishedHex string `json:"finishedServerRandom"` |
||||
ClientFinishedHex string `json:"finishedClientRandom"` |
||||
DHEInputHex string `json:"dhe"` |
||||
PSKInputHex string `json:"psk"` |
||||
} |
||||
|
||||
type tls13TestGroupResponse struct { |
||||
ID uint64 `json:"tgId"` |
||||
Tests []tls13TestResponse `json:"tests"` |
||||
} |
||||
|
||||
type tls13TestResponse struct { |
||||
ID uint64 `json:"tcId"` |
||||
ClientEarlyTrafficSecretHex string `json:"clientEarlyTrafficSecret"` |
||||
EarlyExporterMasterSecretHex string `json:"earlyExporterMasterSecret"` |
||||
ClientHandshakeTrafficSecretHex string `json:"clientHandshakeTrafficSecret"` |
||||
ServerHandshakeTrafficSecretHex string `json:"serverHandshakeTrafficSecret"` |
||||
ClientApplicationTrafficSecretHex string `json:"clientApplicationTrafficSecret"` |
||||
ServerApplicationTrafficSecretHex string `json:"serverApplicationTrafficSecret"` |
||||
ExporterMasterSecretHex string `json:"exporterMasterSecret"` |
||||
ResumptionMasterSecretHex string `json:"resumptionMasterSecret"` |
||||
} |
||||
|
||||
type tls13 struct{} |
||||
|
||||
func (k *tls13) Process(vectorSet []byte, m Transactable) (interface{}, error) { |
||||
var parsed tls13TestVectorSet |
||||
if err := json.Unmarshal(vectorSet, &parsed); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
var respGroups []tls13TestGroupResponse |
||||
for _, group := range parsed.Groups { |
||||
groupResp := tls13TestGroupResponse{ID: group.ID} |
||||
|
||||
for _, test := range group.Tests { |
||||
testResp := tls13TestResponse{ID: test.ID} |
||||
|
||||
clientHello, err := hex.DecodeString(test.ClientHelloHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
serverHello, err := hex.DecodeString(test.ServerHelloHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
serverFinished, err := hex.DecodeString(test.ServerFinishedHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
clientFinished, err := hex.DecodeString(test.ClientFinishedHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
// See https://www.rfc-editor.org/rfc/rfc8446#section-7.1
|
||||
var hashLen int |
||||
var emptyHash []byte |
||||
switch group.HashFunc { |
||||
case "SHA2-256": |
||||
hashLen = 256 / 8 |
||||
digest := sha256.Sum256(nil) |
||||
emptyHash = digest[:] |
||||
case "SHA2-384": |
||||
hashLen = 384 / 8 |
||||
digest := sha512.Sum384(nil) |
||||
emptyHash = digest[:] |
||||
default: |
||||
return nil, fmt.Errorf("hash function %q is not supported for TLS v1.3", group.HashFunc) |
||||
} |
||||
hashLenBytes := uint32le(uint32(hashLen)) |
||||
|
||||
psk, err := hex.DecodeString(test.PSKInputHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
if len(psk) == 0 { |
||||
psk = make([]byte, hashLen) |
||||
} |
||||
|
||||
dhe, err := hex.DecodeString(test.DHEInputHex) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
if len(dhe) == 0 { |
||||
dhe = make([]byte, hashLen) |
||||
} |
||||
|
||||
zeros := make([]byte, hashLen) |
||||
earlySecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, psk, zeros) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) |
||||
} |
||||
|
||||
hashedToClientHello, err := m.Transact(group.HashFunc, 1, clientHello) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) |
||||
} |
||||
hashedToServerHello, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello)) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) |
||||
} |
||||
hashedToServerFinished, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished)) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) |
||||
} |
||||
hashedMessages, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished, clientFinished)) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err) |
||||
} |
||||
|
||||
clientEarlyTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("c e traffic"), hashedToClientHello[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ClientEarlyTrafficSecretHex = hex.EncodeToString(clientEarlyTrafficSecret[0]) |
||||
|
||||
earlyExporter, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("e exp master"), hashedToClientHello[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.EarlyExporterMasterSecretHex = hex.EncodeToString(earlyExporter[0]) |
||||
|
||||
derivedSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("derived"), emptyHash[:]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
|
||||
handshakeSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, dhe, derivedSecret[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) |
||||
} |
||||
|
||||
clientHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("c hs traffic"), hashedToServerHello[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ClientHandshakeTrafficSecretHex = hex.EncodeToString(clientHandshakeTrafficSecret[0]) |
||||
|
||||
serverHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("s hs traffic"), hashedToServerHello[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ServerHandshakeTrafficSecretHex = hex.EncodeToString(serverHandshakeTrafficSecret[0]) |
||||
|
||||
derivedSecret, err = m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("derived"), emptyHash[:]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
|
||||
masterSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, zeros, derivedSecret[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExtract operation failed: %s", err) |
||||
} |
||||
|
||||
clientAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("c ap traffic"), hashedToServerFinished[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ClientApplicationTrafficSecretHex = hex.EncodeToString(clientAppTrafficSecret[0]) |
||||
|
||||
serverAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("s ap traffic"), hashedToServerFinished[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ServerApplicationTrafficSecretHex = hex.EncodeToString(serverAppTrafficSecret[0]) |
||||
|
||||
exporterSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("exp master"), hashedToServerFinished[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ExporterMasterSecretHex = hex.EncodeToString(exporterSecret[0]) |
||||
|
||||
resumptionSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("res master"), hashedMessages[0]) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err) |
||||
} |
||||
testResp.ResumptionMasterSecretHex = hex.EncodeToString(resumptionSecret[0]) |
||||
|
||||
groupResp.Tests = append(groupResp.Tests, testResp) |
||||
} |
||||
respGroups = append(respGroups, groupResp) |
||||
} |
||||
|
||||
return respGroups, nil |
||||
} |
||||
|
||||
func concat(slices ...[]byte) []byte { |
||||
var ret []byte |
||||
for _, slice := range slices { |
||||
ret = append(ret, slice...) |
||||
} |
||||
return ret |
||||
} |
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue