pbkdf2.mx raw

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