Skip to content

Commit 0657d68

Browse files
authored
Implement ExpandHKDFOneShot (#224)
* implement ExpandHKDFOneShot * fix comment
1 parent 4f0359e commit 0657d68

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

hkdf.go

+37
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,43 @@ func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) {
151151
}
152152
}
153153

154+
// ExpandHKDFOneShot derives a key from the given hash, key, and optional context info.
155+
func ExpandHKDFOneShot(h func() hash.Hash, pseudorandomKey, info []byte, keyLength int) ([]byte, error) {
156+
if !SupportsHKDF() {
157+
return nil, errUnsupportedVersion()
158+
}
159+
160+
md, err := hashFuncToMD(h)
161+
if err != nil {
162+
return nil, err
163+
}
164+
165+
out := make([]byte, keyLength)
166+
switch vMajor {
167+
case 1:
168+
ctx, err := newHKDFCtx1(md, C.GO_EVP_KDF_HKDF_MODE_EXPAND_ONLY, nil, nil, pseudorandomKey, info)
169+
if err != nil {
170+
return nil, err
171+
}
172+
defer C.go_openssl_EVP_PKEY_CTX_free(ctx)
173+
if C.go_openssl_EVP_PKEY_derive_wrapper(ctx, base(out), C.size_t(keyLength)).result != 1 {
174+
return nil, newOpenSSLError("EVP_PKEY_derive")
175+
}
176+
case 3:
177+
ctx, err := newHKDFCtx3(md, C.GO_EVP_KDF_HKDF_MODE_EXPAND_ONLY, nil, nil, pseudorandomKey, info)
178+
if err != nil {
179+
return nil, err
180+
}
181+
defer C.go_openssl_EVP_KDF_CTX_free(ctx)
182+
if C.go_openssl_EVP_KDF_derive(ctx, base(out), C.size_t(keyLength), nil) != 1 {
183+
return nil, newOpenSSLError("EVP_KDF_derive")
184+
}
185+
default:
186+
panic(errUnsupportedVersion())
187+
}
188+
return out, nil
189+
}
190+
154191
func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) {
155192
if !SupportsHKDF() {
156193
return nil, errUnsupportedVersion()

hkdf_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,46 @@ func TestHKDFUnsupportedHash(t *testing.T) {
405405
t.Error("expected error for unsupported hash")
406406
}
407407
}
408+
func TestExpandHKDFOneShot(t *testing.T) {
409+
if !openssl.SupportsHKDF() {
410+
t.Skip("HKDF is not supported")
411+
}
412+
for i, tt := range hkdfTests {
413+
out, err := openssl.ExpandHKDFOneShot(tt.hash, tt.prk, tt.info, len(tt.out))
414+
if err != nil {
415+
t.Errorf("test %d: error expanding HKDF one-shot: %v.", i, err)
416+
continue
417+
}
418+
if !bytes.Equal(out, tt.out) {
419+
t.Errorf("test %d: incorrect output from ExpandHKDFOneShot: have %v, need %v.", i, out, tt.out)
420+
}
421+
}
422+
}
423+
424+
func TestExpandHKDFOneShotLimit(t *testing.T) {
425+
if !openssl.SupportsHKDF() {
426+
t.Skip("HKDF is not supported")
427+
}
428+
hash := openssl.NewSHA1
429+
master := []byte{0x00, 0x01, 0x02, 0x03}
430+
info := []byte{}
431+
432+
prk, err := openssl.ExtractHKDF(hash, master, nil)
433+
if err != nil {
434+
t.Fatalf("error extracting HKDF: %v.", err)
435+
}
436+
limit := hash().Size() * 255
437+
out, err := openssl.ExpandHKDFOneShot(hash, prk, info, limit)
438+
if err != nil {
439+
t.Errorf("error expanding HKDF one-shot: %v.", err)
440+
}
441+
if len(out) != limit {
442+
t.Errorf("incorrect output length: have %d, need %d.", len(out), limit)
443+
}
444+
445+
// Expanding one more byte should fail
446+
_, err = openssl.ExpandHKDFOneShot(hash, prk, info, limit+1)
447+
if err == nil {
448+
t.Errorf("expected error for key expansion overflow")
449+
}
450+
}

0 commit comments

Comments
 (0)