From a673d02458b1b7d897084266b93d5c610e36bd17 Mon Sep 17 00:00:00 2001 From: Daniel McArdle Date: Wed, 26 Aug 2020 11:10:45 -0400 Subject: [PATCH] Add PSK variants of HPKE setup functions to BoGo. Change-Id: Ie0bef08f80aca60cfa2f94fdc4219c51d038b559 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42684 Reviewed-by: David Benjamin Commit-Queue: David Benjamin --- ssl/test/runner/hpke/hpke.go | 52 ++++++++++++++++++++++++---- ssl/test/runner/hpke/hpke_test.go | 56 +++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/ssl/test/runner/hpke/hpke.go b/ssl/test/runner/hpke/hpke.go index c2ed28ec0..d5081323b 100644 --- a/ssl/test/runner/hpke/hpke.go +++ b/ssl/test/runner/hpke/hpke.go @@ -48,6 +48,7 @@ const ( // Internal constants. const ( hpkeModeBase uint8 = 0 + hpkeModePSK uint8 = 1 ) type GenerateKeyPairFunc func() (public []byte, secret []byte, e error) @@ -73,7 +74,7 @@ func SetupBaseSenderX25519(kdfID, aeadID uint16, publicKeyR, info []byte, ephemK if err != nil { return nil, nil, err } - context, err = keySchedule(X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info) + context, err = keySchedule(hpkeModeBase, X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info, nil, nil) return } @@ -84,7 +85,32 @@ func SetupBaseReceiverX25519(kdfID, aeadID uint16, enc, secretKeyR, info []byte) if err != nil { return nil, err } - return keySchedule(X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info) + return keySchedule(hpkeModeBase, X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info, nil, nil) +} + +// SetupPSKSenderX25519 corresponds to the spec's SetupPSKS(), but only supports +// X25519. +func SetupPSKSenderX25519(kdfID, aeadID uint16, publicKeyR, info, psk, pskID []byte, ephemKeygen GenerateKeyPairFunc) (context *Context, enc []byte, err error) { + sharedSecret, enc, err := x25519Encap(publicKeyR, ephemKeygen) + if err != nil { + return nil, nil, err + } + context, err = keySchedule(hpkeModePSK, X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info, psk, pskID) + return +} + +// SetupPSKReceiverX25519 corresponds to the spec's SetupPSKR(), but only +// supports X25519. +func SetupPSKReceiverX25519(kdfID, aeadID uint16, enc, secretKeyR, info, psk, pskID []byte) (context *Context, err error) { + sharedSecret, err := x25519Decap(enc, secretKeyR) + if err != nil { + return nil, err + } + context, err = keySchedule(hpkeModePSK, X25519WithHKDFSHA256, kdfID, aeadID, sharedSecret, info, psk, pskID) + if err != nil { + return nil, err + } + return context, nil } func (c *Context) Seal(additionalData, plaintext []byte) []byte { @@ -142,18 +168,32 @@ func newAEAD(aeadID uint16, key []byte) (cipher.AEAD, error) { return nil, errors.New("unsupported AEAD") } -func keySchedule(kemID, kdfID, aeadID uint16, sharedSecret, info []byte) (*Context, error) { +func keySchedule(mode uint8, kemID, kdfID, aeadID uint16, sharedSecret, info, psk, pskID []byte) (*Context, error) { + // Verify the PSK inputs. + switch mode { + case hpkeModeBase: + if len(psk) > 0 || len(pskID) > 0 { + panic("unnecessary psk inputs were provided") + } + case hpkeModePSK: + if len(psk) == 0 || len(pskID) == 0 { + panic("missing psk inputs") + } + default: + panic("unknown mode") + } + kdfHash := getKDFHash(kdfID) suiteID := buildSuiteID(kemID, kdfID, aeadID) - pskIDHash := labeledExtract(kdfHash, nil, suiteID, []byte("psk_id_hash"), nil) + pskIDHash := labeledExtract(kdfHash, nil, suiteID, []byte("psk_id_hash"), pskID) infoHash := labeledExtract(kdfHash, nil, suiteID, []byte("info_hash"), info) keyScheduleContext := make([]byte, 0) - keyScheduleContext = append(keyScheduleContext, hpkeModeBase) + keyScheduleContext = append(keyScheduleContext, mode) keyScheduleContext = append(keyScheduleContext, pskIDHash...) keyScheduleContext = append(keyScheduleContext, infoHash...) - pskHash := labeledExtract(kdfHash, nil, suiteID, []byte("psk_hash"), nil) + pskHash := labeledExtract(kdfHash, nil, suiteID, []byte("psk_hash"), psk) secret := labeledExtract(kdfHash, pskHash, suiteID, []byte("secret"), sharedSecret) key := labeledExpand(kdfHash, secret, suiteID, []byte("key"), keyScheduleContext, expectedKeyLength(aeadID)) diff --git a/ssl/test/runner/hpke/hpke_test.go b/ssl/test/runner/hpke/hpke_test.go index 25da3d950..c1c9bf452 100644 --- a/ssl/test/runner/hpke/hpke_test.go +++ b/ssl/test/runner/hpke/hpke_test.go @@ -71,6 +71,8 @@ type HpkeTestVector struct { KDF uint16 `json:"kdf_id"` AEAD uint16 `json:"aead_id"` Info HexString `json:"info"` + PSK HexString `json:"psk"` + PSKID HexString `json:"psk_id"` SecretKeyR HexString `json:"skRm"` SecretKeyE HexString `json:"skEm"` PublicKeyR HexString `json:"pkRm"` @@ -110,27 +112,53 @@ func TestVectors(t *testing.T) { for testNum, testVec := range testVectors { // Skip this vector if it specifies an unsupported KEM or Mode. if testVec.KEM != X25519WithHKDFSHA256 || - testVec.Mode != hpkeModeBase { + (testVec.Mode != hpkeModeBase && testVec.Mode != hpkeModePSK) { numSkippedTests++ continue } testVec := testVec // capture the range variable t.Run(fmt.Sprintf("test%d,KDF=%d,AEAD=%d", testNum, testVec.KDF, testVec.AEAD), func(t *testing.T) { - senderContext, enc, err := SetupBaseSenderX25519(testVec.KDF, testVec.AEAD, testVec.PublicKeyR, testVec.Info, - func() ([]byte, []byte, error) { - return testVec.PublicKeyE, testVec.SecretKeyE, nil - }) - if err != nil { - t.Errorf("failed to set up sender: %s", err) - return - } - checkBytesEqual(t, "sender enc", enc, testVec.Enc) + var senderContext *Context + var receiverContext *Context + var enc []byte + var err error + + switch testVec.Mode { + case hpkeModeBase: + senderContext, enc, err = SetupBaseSenderX25519(testVec.KDF, testVec.AEAD, testVec.PublicKeyR, testVec.Info, + func() ([]byte, []byte, error) { + return testVec.PublicKeyE, testVec.SecretKeyE, nil + }) + if err != nil { + t.Errorf("failed to set up sender: %s", err) + return + } + checkBytesEqual(t, "sender enc", enc, testVec.Enc) + + receiverContext, err = SetupBaseReceiverX25519(testVec.KDF, testVec.AEAD, enc, testVec.SecretKeyR, testVec.Info) + if err != nil { + t.Errorf("failed to set up receiver: %s", err) + return + } + case hpkeModePSK: + senderContext, enc, err = SetupPSKSenderX25519(testVec.KDF, testVec.AEAD, testVec.PublicKeyR, testVec.Info, testVec.PSK, testVec.PSKID, + func() ([]byte, []byte, error) { + return testVec.PublicKeyE, testVec.SecretKeyE, nil + }) + if err != nil { + t.Errorf("failed to set up sender: %s", err) + return + } + checkBytesEqual(t, "sender enc", enc, testVec.Enc) - receiverContext, err := SetupBaseReceiverX25519(testVec.KDF, testVec.AEAD, enc, testVec.SecretKeyR, testVec.Info) - if err != nil { - t.Errorf("failed to set up receiver: %s", err) - return + receiverContext, err = SetupPSKReceiverX25519(testVec.KDF, testVec.AEAD, enc, testVec.SecretKeyR, testVec.Info, testVec.PSK, testVec.PSKID) + if err != nil { + t.Errorf("failed to set up receiver: %s", err) + return + } + default: + panic("unsupported mode") } for encryptionNum, e := range testVec.Encryptions {