1
2
3
4
5 package pbkdf2
6
7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/hmac"
10 )
11
12 func Key[Hash fips140.Hash](h func() Hash, password string, salt []byte, iter, keyLength int) ([]byte, error) {
13 setServiceIndicator(salt, keyLength)
14
15 prf := hmac.New(h, []byte(password))
16 hmac.MarkAsUsedInKDF(prf)
17 hashLen := prf.Size()
18 numBlocks := (keyLength + hashLen - 1) / hashLen
19
20 var buf [4]byte
21 dk := make([]byte, 0, numBlocks*hashLen)
22 U := make([]byte, hashLen)
23 for block := 1; block <= numBlocks; block++ {
24
25
26
27 prf.Reset()
28 prf.Write(salt)
29 buf[0] = byte(block >> 24)
30 buf[1] = byte(block >> 16)
31 buf[2] = byte(block >> 8)
32 buf[3] = byte(block)
33 prf.Write(buf[:4])
34 dk = prf.Sum(dk)
35 T := dk[len(dk)-hashLen:]
36 copy(U, T)
37
38
39 for n := 2; n <= iter; n++ {
40 prf.Reset()
41 prf.Write(U)
42 U = U[:0]
43 U = prf.Sum(U)
44 for x := range U {
45 T[x] ^= U[x]
46 }
47 }
48 }
49 return dk[:keyLength], nil
50 }
51
52 func setServiceIndicator(salt []byte, keyLength int) {
53
54
55
56
57
58 if len(salt) < 128/8 {
59 fips140.RecordNonApproved()
60 }
61
62
63
64 if keyLength < 112/8 {
65 fips140.RecordNonApproved()
66 }
67
68 fips140.RecordApproved()
69 }
70
View as plain text