Source file src/crypto/internal/fips140/pbkdf2/pbkdf2.go

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package pbkdf2
     6  
     7  import (
     8  	"crypto/internal/fips140"
     9  	"crypto/internal/fips140/hmac"
    10  	"errors"
    11  )
    12  
    13  // divRoundUp divides x+y-1 by y, rounding up if the result is not whole.
    14  // This function casts x and y to int64 in order to avoid cases where
    15  // x+y would overflow int on systems where int is an int32. The result
    16  // is an int, which is safe as (x+y-1)/y should always fit, regardless
    17  // of the integer size.
    18  func divRoundUp(x, y int) int {
    19  	return int((int64(x) + int64(y) - 1) / int64(y))
    20  }
    21  
    22  func Key[Hash fips140.Hash](h func() Hash, password string, salt []byte, iter, keyLength int) ([]byte, error) {
    23  	setServiceIndicator(salt, keyLength)
    24  
    25  	if keyLength <= 0 {
    26  		return nil, errors.New("pkbdf2: keyLength must be larger than 0")
    27  	}
    28  
    29  	prf := hmac.New(h, []byte(password))
    30  	hmac.MarkAsUsedInKDF(prf)
    31  	hashLen := prf.Size()
    32  	numBlocks := divRoundUp(keyLength, hashLen)
    33  	const maxBlocks = int64(1<<32 - 1)
    34  	if keyLength+hashLen < keyLength || int64(numBlocks) > maxBlocks {
    35  		return nil, errors.New("pbkdf2: keyLength too long")
    36  	}
    37  
    38  	var buf [4]byte
    39  	dk := make([]byte, 0, numBlocks*hashLen)
    40  	U := make([]byte, hashLen)
    41  	for block := 1; block <= numBlocks; block++ {
    42  		// N.B.: || means concatenation, ^ means XOR
    43  		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
    44  		// U_1 = PRF(password, salt || uint(i))
    45  		prf.Reset()
    46  		prf.Write(salt)
    47  		buf[0] = byte(block >> 24)
    48  		buf[1] = byte(block >> 16)
    49  		buf[2] = byte(block >> 8)
    50  		buf[3] = byte(block)
    51  		prf.Write(buf[:4])
    52  		dk = prf.Sum(dk)
    53  		T := dk[len(dk)-hashLen:]
    54  		copy(U, T)
    55  
    56  		// U_n = PRF(password, U_(n-1))
    57  		for n := 2; n <= iter; n++ {
    58  			prf.Reset()
    59  			prf.Write(U)
    60  			U = U[:0]
    61  			U = prf.Sum(U)
    62  			for x := range U {
    63  				T[x] ^= U[x]
    64  			}
    65  		}
    66  	}
    67  	return dk[:keyLength], nil
    68  }
    69  
    70  func setServiceIndicator(salt []byte, keyLength int) {
    71  	// The HMAC construction will handle the hash function considerations for the service
    72  	// indicator. The remaining PBKDF2 considerations outlined by SP 800-132 pertain to
    73  	// salt and keyLength.
    74  
    75  	// The length of the randomly-generated portion of the salt shall be at least 128 bits.
    76  	if len(salt) < 128/8 {
    77  		fips140.RecordNonApproved()
    78  	}
    79  
    80  	// Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for
    81  	// legacy use (i.e. verification only) and we don't support that.
    82  	if keyLength < 112/8 {
    83  		fips140.RecordNonApproved()
    84  	}
    85  
    86  	fips140.RecordApproved()
    87  }
    88  

View as plain text