| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package pbkdf2 |
| |
| import ( |
| "crypto/internal/fips140" |
| "crypto/internal/fips140/hmac" |
| "errors" |
| "hash" |
| ) |
| |
| // divRoundUp divides x+y-1 by y, rounding up if the result is not whole. |
| // This function casts x and y to int64 in order to avoid cases where |
| // x+y would overflow int on systems where int is an int32. The result |
| // is an int, which is safe as (x+y-1)/y should always fit, regardless |
| // of the integer size. |
| func divRoundUp(x, y int) int { |
| return int((int64(x) + int64(y) - 1) / int64(y)) |
| } |
| |
| func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyLength int) ([]byte, error) { |
| setServiceIndicator(salt, keyLength) |
| |
| if keyLength <= 0 { |
| return nil, errors.New("pbkdf2: keyLength must be larger than 0") |
| } |
| |
| prf := hmac.New(h, []byte(password)) |
| hmac.MarkAsUsedInKDF(prf) |
| hashLen := prf.Size() |
| numBlocks := divRoundUp(keyLength, hashLen) |
| const maxBlocks = int64(1<<32 - 1) |
| if keyLength+hashLen < keyLength || int64(numBlocks) > maxBlocks { |
| return nil, errors.New("pbkdf2: keyLength too long") |
| } |
| |
| var buf [4]byte |
| dk := make([]byte, 0, numBlocks*hashLen) |
| U := make([]byte, hashLen) |
| for block := 1; block <= numBlocks; block++ { |
| // N.B.: || means concatenation, ^ means XOR |
| // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter |
| // U_1 = PRF(password, salt || uint(i)) |
| prf.Reset() |
| prf.Write(salt) |
| buf[0] = byte(block >> 24) |
| buf[1] = byte(block >> 16) |
| buf[2] = byte(block >> 8) |
| buf[3] = byte(block) |
| prf.Write(buf[:4]) |
| dk = prf.Sum(dk) |
| T := dk[len(dk)-hashLen:] |
| copy(U, T) |
| |
| // U_n = PRF(password, U_(n-1)) |
| for n := 2; n <= iter; n++ { |
| prf.Reset() |
| prf.Write(U) |
| U = U[:0] |
| U = prf.Sum(U) |
| for x := range U { |
| T[x] ^= U[x] |
| } |
| } |
| } |
| return dk[:keyLength], nil |
| } |
| |
| func setServiceIndicator(salt []byte, keyLength int) { |
| // The HMAC construction will handle the hash function considerations for the service |
| // indicator. The remaining PBKDF2 considerations outlined by SP 800-132 pertain to |
| // salt and keyLength. |
| |
| // The length of the randomly-generated portion of the salt shall be at least 128 bits. |
| if len(salt) < 128/8 { |
| fips140.RecordNonApproved() |
| } |
| |
| // Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for |
| // legacy use (i.e. verification only) and we don't support that. |
| if keyLength < 112/8 { |
| fips140.RecordNonApproved() |
| } |
| |
| fips140.RecordApproved() |
| } |