xref: /aosp_15_r20/external/tink/go/prf/subtle/hkdf.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package subtle
18
19import (
20	"fmt"
21	"hash"
22	"io"
23
24	"golang.org/x/crypto/hkdf"
25	"github.com/google/tink/go/subtle"
26)
27
28const (
29	// We use a somewhat larger minimum key size than usual, because PRFs might be
30	// used by many users, in which case the security can degrade by a factor
31	// depending on the number of users. (Discussed for example in
32	// https://eprint.iacr.org/2012/159)
33	minHKDFKeySizeInBytes = uint32(32)
34)
35
36// HKDFPRF is a type that can be used to compute several HKDFs with the same key material.
37type HKDFPRF struct {
38	h    func() hash.Hash
39	key  []byte
40	salt []byte
41}
42
43// NewHKDFPRF creates a new HKDFPRF object and initializes it with the correct key material.
44func NewHKDFPRF(hashAlg string, key []byte, salt []byte) (*HKDFPRF, error) {
45	h := &HKDFPRF{}
46	hashFunc := subtle.GetHashFunc(hashAlg)
47	if hashFunc == nil {
48		return nil, fmt.Errorf("hkdf: invalid hash algorithm")
49	}
50	h.h = hashFunc
51	h.key = key
52	h.salt = salt
53	return h, nil
54}
55
56// ValidateHKDFPRFParams validates parameters of HKDF constructor.
57func ValidateHKDFPRFParams(hash string, keySize uint32, salt []byte) error {
58	// validate key size
59	if keySize < minHKDFKeySizeInBytes {
60		return fmt.Errorf("key too short")
61	}
62	if subtle.GetHashFunc(hash) == nil {
63		return fmt.Errorf("invalid hash function")
64	}
65	if hash != "SHA256" && hash != "SHA512" {
66		return fmt.Errorf("Only SHA-256 and SHA-512 currently allowed for HKDF")
67	}
68	return nil
69}
70
71// ComputePRF computes the HKDF for the given key and data, returning outputLength bytes.
72func (h HKDFPRF) ComputePRF(data []byte, outputLength uint32) ([]byte, error) {
73	kdf := hkdf.New(h.h, h.key, h.salt, data)
74	output := make([]byte, outputLength)
75	_, err := io.ReadAtLeast(kdf, output, int(outputLength))
76	if err != nil {
77		return nil, fmt.Errorf("Error computing HKDF: %v", err)
78	}
79	return output[:outputLength], nil
80}
81