|
2 | 2 | // Use of this source code is governed by a BSD-style
|
3 | 3 | // license that can be found in the LICENSE file.
|
4 | 4 |
|
5 |
| -package fipstest_test |
6 |
| - |
7 |
| -// TODO(fips, #61477): move this to crypto/hkdf once it exists. |
| 5 | +package hkdf |
8 | 6 |
|
9 | 7 | import (
|
10 | 8 | "bytes"
|
11 | 9 | "crypto/internal/boring"
|
12 | 10 | "crypto/internal/fips140"
|
13 |
| - "crypto/internal/fips140/hkdf" |
14 | 11 | "crypto/md5"
|
15 | 12 | "crypto/sha1"
|
16 | 13 | "crypto/sha256"
|
@@ -301,92 +298,113 @@ var hkdfTests = []hkdfTest{
|
301 | 298 |
|
302 | 299 | func TestHKDF(t *testing.T) {
|
303 | 300 | for i, tt := range hkdfTests {
|
304 |
| - prk := hkdf.Extract(tt.hash, tt.master, tt.salt) |
| 301 | + prk, err := Extract(tt.hash, tt.master, tt.salt) |
| 302 | + if err != nil { |
| 303 | + t.Errorf("test %d: PRK extraction failed: %v", i, err) |
| 304 | + } |
305 | 305 | if !bytes.Equal(prk, tt.prk) {
|
306 | 306 | t.Errorf("test %d: incorrect PRK: have %v, need %v.", i, prk, tt.prk)
|
307 | 307 | }
|
308 | 308 |
|
309 |
| - out := hkdf.Key(tt.hash, tt.master, tt.salt, tt.info, len(tt.out)) |
310 |
| - if !bytes.Equal(out, tt.out) { |
311 |
| - t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) |
| 309 | + key, err := Key(tt.hash, tt.master, tt.salt, string(tt.info), len(tt.out)) |
| 310 | + if err != nil { |
| 311 | + t.Errorf("test %d: key derivation failed: %v", i, err) |
| 312 | + } |
| 313 | + |
| 314 | + if !bytes.Equal(key, tt.out) { |
| 315 | + t.Errorf("test %d: incorrect output: have %v, need %v.", i, key, tt.out) |
312 | 316 | }
|
313 | 317 |
|
314 |
| - out = hkdf.Expand(tt.hash, prk, tt.info, len(tt.out)) |
315 |
| - if !bytes.Equal(out, tt.out) { |
316 |
| - t.Errorf("test %d: incorrect output from Expand: have %v, need %v.", i, out, tt.out) |
| 318 | + expanded, err := Expand(tt.hash, prk, string(tt.info), len(tt.out)) |
| 319 | + if err != nil { |
| 320 | + t.Errorf("test %d: key expansion failed: %v", i, err) |
| 321 | + } |
| 322 | + |
| 323 | + if !bytes.Equal(expanded, tt.out) { |
| 324 | + t.Errorf("test %d: incorrect output from Expand: have %v, need %v.", i, expanded, tt.out) |
317 | 325 | }
|
318 | 326 | }
|
319 | 327 | }
|
320 | 328 |
|
321 | 329 | func TestHKDFLimit(t *testing.T) {
|
322 | 330 | hash := sha1.New
|
323 | 331 | master := []byte{0x00, 0x01, 0x02, 0x03}
|
324 |
| - info := []byte{} |
325 |
| - |
326 |
| - // The maximum output bytes should be extractable |
| 332 | + info := "" |
327 | 333 | limit := hash().Size() * 255
|
328 |
| - hkdf.Key(hash, master, nil, info, limit) |
329 |
| - |
330 |
| - // Reading one more should panic |
331 |
| - defer func() { |
332 |
| - if err := recover(); err == nil { |
333 |
| - t.Error("expected panic") |
334 |
| - } |
335 |
| - }() |
336 |
| - hkdf.Key(hash, master, nil, info, limit+1) |
337 |
| -} |
338 |
| - |
339 |
| -func TestFIPSServiceIndicator(t *testing.T) { |
340 |
| - if boring.Enabled { |
341 |
| - t.Skip("in BoringCrypto mode HMAC is not from the Go FIPS module") |
342 |
| - } |
343 |
| - |
344 |
| - fips140.ResetServiceIndicator() |
345 |
| - hkdf.Key(sha256.New, []byte("YELLOW SUBMARINE"), nil, nil, 32) |
346 |
| - if !fips140.ServiceIndicator() { |
347 |
| - t.Error("FIPS service indicator should be set") |
348 |
| - } |
349 | 334 |
|
350 |
| - // Key too short. |
351 |
| - fips140.ResetServiceIndicator() |
352 |
| - hkdf.Key(sha256.New, []byte("key"), nil, nil, 32) |
353 |
| - if fips140.ServiceIndicator() { |
354 |
| - t.Error("FIPS service indicator should not be set") |
| 335 | + // The maximum output bytes should be extractable |
| 336 | + out, err := Key(hash, master, nil, info, limit) |
| 337 | + if err != nil || len(out) != limit { |
| 338 | + t.Errorf("key derivation failed: %v", err) |
355 | 339 | }
|
356 | 340 |
|
357 |
| - // Salt and info are short, which is ok, but translates to a short HMAC key. |
358 |
| - fips140.ResetServiceIndicator() |
359 |
| - hkdf.Key(sha256.New, []byte("YELLOW SUBMARINE"), []byte("salt"), []byte("info"), 32) |
360 |
| - if !fips140.ServiceIndicator() { |
361 |
| - t.Error("FIPS service indicator should be set") |
| 341 | + // Reading one more should return an error |
| 342 | + _, err = Key(hash, master, nil, info, limit+1) |
| 343 | + if err == nil { |
| 344 | + t.Error("expected key derivation to fail, but it succeeded") |
362 | 345 | }
|
363 | 346 | }
|
364 | 347 |
|
365 | 348 | func Benchmark16ByteMD5Single(b *testing.B) {
|
366 |
| - benchmarkHKDFSingle(md5.New, 16, b) |
| 349 | + benchmarkHKDF(md5.New, 16, b) |
367 | 350 | }
|
368 | 351 |
|
369 | 352 | func Benchmark20ByteSHA1Single(b *testing.B) {
|
370 |
| - benchmarkHKDFSingle(sha1.New, 20, b) |
| 353 | + benchmarkHKDF(sha1.New, 20, b) |
371 | 354 | }
|
372 | 355 |
|
373 | 356 | func Benchmark32ByteSHA256Single(b *testing.B) {
|
374 |
| - benchmarkHKDFSingle(sha256.New, 32, b) |
| 357 | + benchmarkHKDF(sha256.New, 32, b) |
375 | 358 | }
|
376 | 359 |
|
377 | 360 | func Benchmark64ByteSHA512Single(b *testing.B) {
|
378 |
| - benchmarkHKDFSingle(sha512.New, 64, b) |
| 361 | + benchmarkHKDF(sha512.New, 64, b) |
379 | 362 | }
|
380 | 363 |
|
381 |
| -func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) { |
| 364 | +func benchmarkHKDF(hasher func() hash.Hash, block int, b *testing.B) { |
382 | 365 | master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
|
383 | 366 | salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
|
384 |
| - info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} |
| 367 | + info := string([]byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}) |
385 | 368 |
|
386 | 369 | b.SetBytes(int64(block))
|
387 | 370 | b.ResetTimer()
|
388 | 371 |
|
389 | 372 | for i := 0; i < b.N; i++ {
|
390 |
| - hkdf.Key(hasher, master, salt, info, block) |
| 373 | + _, err := Key(hasher, master, salt, info, hasher().Size()) |
| 374 | + if err != nil { |
| 375 | + b.Errorf("failed to derive key: %v", err) |
| 376 | + } |
| 377 | + } |
| 378 | +} |
| 379 | + |
| 380 | +func TestFIPSServiceIndicator(t *testing.T) { |
| 381 | + if boring.Enabled { |
| 382 | + t.Skip("in BoringCrypto mode HMAC is not from the Go FIPS module") |
| 383 | + } |
| 384 | + |
| 385 | + fips140.ResetServiceIndicator() |
| 386 | + _, err := Key(sha256.New, []byte("YELLOW SUBMARINE"), nil, "", 32) |
| 387 | + if err != nil { |
| 388 | + panic(err) |
| 389 | + } |
| 390 | + if !fips140.ServiceIndicator() { |
| 391 | + t.Error("FIPS service indicator should be set") |
| 392 | + } |
| 393 | + |
| 394 | + // Key too short. |
| 395 | + fips140.ResetServiceIndicator() |
| 396 | + _, err = Key(sha256.New, []byte("key"), nil, "", 32) |
| 397 | + if err != nil { |
| 398 | + panic(err) |
| 399 | + } |
| 400 | + if fips140.ServiceIndicator() { |
| 401 | + t.Error("FIPS service indicator should not be set") |
| 402 | + } |
| 403 | + |
| 404 | + // Salt and info are short, which is ok, but translates to a short HMAC key. |
| 405 | + fips140.ResetServiceIndicator() |
| 406 | + _, err = Key(sha256.New, []byte("YELLOW SUBMARINE"), []byte("salt"), "info", 32) |
| 407 | + if !fips140.ServiceIndicator() { |
| 408 | + t.Error("FIPS service indicator should be set") |
391 | 409 | }
|
392 | 410 | }
|
0 commit comments