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  )
    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  		// N.B.: || means concatenation, ^ means XOR
    25  		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
    26  		// U_1 = PRF(password, salt || uint(i))
    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  		// U_n = PRF(password, U_(n-1))
    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  	// The HMAC construction will handle the hash function considerations for the service
    54  	// indicator. The remaining PBKDF2 considerations outlined by SP 800-132 pertain to
    55  	// salt and keyLength.
    56  
    57  	// The length of the randomly-generated portion of the salt shall be at least 128 bits.
    58  	if len(salt) < 128/8 {
    59  		fips140.RecordNonApproved()
    60  	}
    61  
    62  	// Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for
    63  	// legacy use (i.e. verification only) and we don't support that.
    64  	if keyLength < 112/8 {
    65  		fips140.RecordNonApproved()
    66  	}
    67  
    68  	fips140.RecordApproved()
    69  }
    70  

View as plain text