diff options
author | Pete Bentley <prb@google.com> | 2021-07-27 09:43:47 +0100 |
---|---|---|
committer | Pete Bentley <prb@google.com> | 2021-07-27 09:44:51 +0100 |
commit | f9e0b0e17fabac35627f18f94a8954c3857784ac (patch) | |
tree | 1556b1e473a6987114ecdcb92428de3d5609a30e | |
parent | 00a7c4040a2a6f6242d962a19cb9963f7f420818 (diff) | |
download | boringssl-android-s-beta-5.tar.gz |
external/boringssl: Sync to c1571feb5faf5cce844354c63d0f3e842464bea3.android-s-beta-5android-s-beta-5
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/7a817f48bafee508b2d23ad278f892ee1cb32b91..c1571feb5faf5cce844354c63d0f3e842464bea3
* acvp: add HKDF support.
Bug: 194209538
Test: atest CtsLibcoreTestCases CtsLibcoreOkHttpTestCases
Change-Id: I4bf41abbe28b97ecf21732f5088d3ec3f4518abd
-rw-r--r-- | BORINGSSL_REVISION | 2 | ||||
-rw-r--r-- | src/util/fipstools/acvp/ACVP.md | 1 | ||||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/subprocess/hkdf.go | 203 | ||||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/subprocess/subprocess.go | 1 | ||||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/test/expected/KAS-KDF.bz2 | bin | 0 -> 808 bytes | |||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/test/tests.json | 1 | ||||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/test/vectors/KAS-KDF.bz2 | bin | 0 -> 4401 bytes | |||
-rw-r--r-- | src/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go | 58 |
8 files changed, 265 insertions, 1 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION index 396e7a74..a2129df1 100644 --- a/BORINGSSL_REVISION +++ b/BORINGSSL_REVISION @@ -1 +1 @@ -7a817f48bafee508b2d23ad278f892ee1cb32b91 +c1571feb5faf5cce844354c63d0f3e842464bea3 diff --git a/src/util/fipstools/acvp/ACVP.md b/src/util/fipstools/acvp/ACVP.md index 97ec4233..c9570c6f 100644 --- a/src/util/fipstools/acvp/ACVP.md +++ b/src/util/fipstools/acvp/ACVP.md @@ -72,6 +72,7 @@ The other commands are as follows. (Note that you only need to implement the com | ECDSA/sigGen | Curve name, private key, hash name, message | R, S | | ECDSA/sigVer | Curve name, hash name, message, X, Y, R, S | Single-byte validity flag | | FFDH | p, q, g, peer public key, local private key (or empty), local public key (or empty) | Local public key, shared key | +| HKDF/<HASH> | key, salt, info, num output bytes | Key | | HMAC-SHA-1 | Value to hash, key | Digest | | HMAC-SHA2-224 | Value to hash, key | Digest | | HMAC-SHA2-256 | Value to hash, key | Digest | diff --git a/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go b/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go new file mode 100644 index 00000000..21ebca6f --- /dev/null +++ b/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go @@ -0,0 +1,203 @@ +// Copyright (c) 2021, 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 ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "strings" +) + +// The following structures reflect the JSON of ACVP KAS KDF tests. See +// https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-kdf-twostep.html + +type hkdfTestVectorSet struct { + Groups []hkdfTestGroup `json:"testGroups"` +} + +type hkdfTestGroup struct { + ID uint64 `json:"tgId"` + Type string `json:"testType"` // AFT or VAL + Config hkdfConfiguration `json:"kdfConfiguration"` + Tests []hkdfTest `json:"tests"` +} + +type hkdfTest struct { + ID uint64 `json:"tcId"` + Params hkdfParameters `json:"kdfParameter"` + PartyU hkdfPartyInfo `json:"fixedInfoPartyU"` + PartyV hkdfPartyInfo `json:"fixedInfoPartyV"` + ExpectedHex string `json:"dkm"` +} + +type hkdfConfiguration struct { + Type string `json:"kdfType"` + AdditionalNonce bool `json:"requiresAdditionalNoncePair"` + OutputBits uint32 `json:"l"` + FixedInfoPattern string `json:"fixedInfoPattern"` + FixedInputEncoding string `json:"fixedInfoEncoding"` + KDFMode string `json:"kdfMode"` + MACMode string `json:"macMode"` + CounterLocation string `json:"counterLocation"` + CounterBits uint `json:"counterLen"` +} + +func (c *hkdfConfiguration) extract() (outBytes uint32, hashName string, err error) { + if c.Type != "twoStep" || + c.AdditionalNonce || + c.FixedInfoPattern != "uPartyInfo||vPartyInfo" || + c.FixedInputEncoding != "concatenation" || + c.KDFMode != "feedback" || + c.CounterLocation != "after fixed data" || + c.CounterBits != 8 || + c.OutputBits%8 != 0 { + return 0, "", fmt.Errorf("KAS-KDF not configured for HKDF: %#v", c) + } + + if !strings.HasPrefix(c.MACMode, "HMAC-") { + return 0, "", fmt.Errorf("MAC mode %q does't start with 'HMAC-'", c.MACMode) + } + + return c.OutputBits / 8, c.MACMode[5:], nil +} + +type hkdfParameters struct { + SaltHex string `json:"salt"` + KeyHex string `json:"z"` +} + +func (p *hkdfParameters) extract() (key, salt []byte, err error) { + salt, err = hex.DecodeString(p.SaltHex) + if err != nil { + return nil, nil, err + } + + key, err = hex.DecodeString(p.KeyHex) + if err != nil { + return nil, nil, err + } + + return key, salt, nil +} + +type hkdfPartyInfo struct { + IDHex string `json:"partyId"` + ExtraHex string `json:"ephemeralData"` +} + +func (p *hkdfPartyInfo) data() ([]byte, error) { + ret, err := hex.DecodeString(p.IDHex) + if err != nil { + return nil, err + } + + if len(p.ExtraHex) > 0 { + extra, err := hex.DecodeString(p.ExtraHex) + if err != nil { + return nil, err + } + ret = append(ret, extra...) + } + + return ret, nil +} + +type hkdfTestGroupResponse struct { + ID uint64 `json:"tgId"` + Tests []hkdfTestResponse `json:"tests"` +} + +type hkdfTestResponse struct { + ID uint64 `json:"tcId"` + KeyOut string `json:"dkm,omitempty"` + Passed *bool `json:"testPassed,omitempty"` +} + +type hkdf struct{} + +func (k *hkdf) Process(vectorSet []byte, m Transactable) (interface{}, error) { + var parsed hkdfTestVectorSet + if err := json.Unmarshal(vectorSet, &parsed); err != nil { + return nil, err + } + + var respGroups []hkdfTestGroupResponse + for _, group := range parsed.Groups { + groupResp := hkdfTestGroupResponse{ID: group.ID} + + var isValidationTest bool + switch group.Type { + case "VAL": + isValidationTest = true + case "AFT": + isValidationTest = false + default: + return nil, fmt.Errorf("unknown test type %q", group.Type) + } + + outBytes, hashName, err := group.Config.extract() + if err != nil { + return nil, err + } + + for _, test := range group.Tests { + testResp := hkdfTestResponse{ID: test.ID} + + key, salt, err := test.Params.extract() + if err != nil { + return nil, err + } + uData, err := test.PartyU.data() + if err != nil { + return nil, err + } + vData, err := test.PartyV.data() + if err != nil { + return nil, err + } + + var expected []byte + if isValidationTest { + expected, err = hex.DecodeString(test.ExpectedHex) + if err != nil { + return nil, err + } + } + + info := make([]byte, 0, len(uData)+len(vData)) + info = append(info, uData...) + info = append(info, vData...) + + resp, err := m.Transact("HKDF/"+hashName, 1, key, salt, info, uint32le(outBytes)) + if err != nil { + return nil, fmt.Errorf("HKDF operation failed: %s", err) + } + + if isValidationTest { + passed := bytes.Equal(expected, resp[0]) + testResp.Passed = &passed + } else { + testResp.KeyOut = hex.EncodeToString(resp[0]) + } + + groupResp.Tests = append(groupResp.Tests, testResp) + } + respGroups = append(respGroups, groupResp) + } + + return respGroups, nil +} diff --git a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go index 5256b1ee..fe74993d 100644 --- a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go +++ b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go @@ -96,6 +96,7 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess "ctrDRBG": &drbg{"ctrDRBG", map[string]bool{"AES-128": true, "AES-192": true, "AES-256": true}}, "hmacDRBG": &drbg{"hmacDRBG", map[string]bool{"SHA-1": true, "SHA2-224": true, "SHA2-256": true, "SHA2-384": true, "SHA2-512": true}}, "KDF": &kdfPrimitive{}, + "KAS-KDF": &hkdf{}, "CMAC-AES": &keyedMACPrimitive{"CMAC-AES"}, "RSA": &rsa{}, "kdf-components": &tlsKDF{}, diff --git a/src/util/fipstools/acvp/acvptool/test/expected/KAS-KDF.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/KAS-KDF.bz2 Binary files differnew file mode 100644 index 00000000..df3edf56 --- /dev/null +++ b/src/util/fipstools/acvp/acvptool/test/expected/KAS-KDF.bz2 diff --git a/src/util/fipstools/acvp/acvptool/test/tests.json b/src/util/fipstools/acvp/acvptool/test/tests.json index 6cf549d2..dfbaac54 100644 --- a/src/util/fipstools/acvp/acvptool/test/tests.json +++ b/src/util/fipstools/acvp/acvptool/test/tests.json @@ -18,6 +18,7 @@ {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-256.bz2", "Out": "expected/HMAC-SHA2-256.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-384.bz2", "Out": "expected/HMAC-SHA2-384.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-512.bz2", "Out": "expected/HMAC-SHA2-512.bz2"}, +{"Wrapper": "testmodulewrapper", "In": "vectors/KAS-KDF.bz2", "Out": "expected/KAS-KDF.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/KAS-ECC-SSC.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/KAS-FFC-SSC.bz2"}, {"Wrapper": "testmodulewrapper", "In": "vectors/KDF.bz2"}, diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/KAS-KDF.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/KAS-KDF.bz2 Binary files differnew file mode 100644 index 00000000..eadbc7e2 --- /dev/null +++ b/src/util/fipstools/acvp/acvptool/test/vectors/KAS-KDF.bz2 diff --git a/src/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go b/src/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go index 00c32ab9..e9894617 100644 --- a/src/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go +++ b/src/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go @@ -16,6 +16,7 @@ import ( "io" "os" + "golang.org/x/crypto/hkdf" "golang.org/x/crypto/xts" ) @@ -24,6 +25,7 @@ var handlers = map[string]func([][]byte) error{ "KDF-counter": kdfCounter, "AES-XTS/encrypt": xtsEncrypt, "AES-XTS/decrypt": xtsDecrypt, + "HKDF/SHA2-256": hkdfMAC, } func getConfig(args [][]byte) error { @@ -69,6 +71,39 @@ func getConfig(args [][]byte) error { "tweakMode": [ "number" ] + }, { + "algorithm": "KAS-KDF", + "mode": "TwoStep", + "revision": "Sp800-56Cr2", + "capabilities": [{ + "macSaltMethods": [ + "random", + "default" + ], + "fixedInfoPattern": "uPartyInfo||vPartyInfo", + "encoding": [ + "concatenation" + ], + "kdfMode": "feedback", + "macMode": [ + "HMAC-SHA2-256" + ], + "supportedLengths": [{ + "min": 128, + "max": 512, + "increment": 64 + }], + "fixedDataOrder": [ + "after fixed data" + ], + "counterLength": [ + 8 + ], + "requiresEmptyIv": true, + "supportsEmptyIv": true + }], + "l": 256, + "z": [256, 384] } ]`)) } @@ -188,6 +223,29 @@ func doXTS(args [][]byte, decrypt bool) error { return reply(msg) } +func hkdfMAC(args [][]byte) error { + if len(args) != 4 { + return fmt.Errorf("HKDF received %d args, wanted 4", len(args)) + } + + key := args[0] + salt := args[1] + info := args[2] + lengthBytes := args[3] + + if len(lengthBytes) != 4 { + return fmt.Errorf("uint32 length was %d bytes long", len(lengthBytes)) + } + + length := binary.LittleEndian.Uint32(lengthBytes) + + mac := hkdf.New(sha256.New, key, salt, info) + ret := make([]byte, length) + mac.Read(ret) + + return reply(ret) +} + const ( maxArgs = 8 maxArgLength = 1 << 20 |