xref: /aosp_15_r20/external/tink/go/subtle/hkdf.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2020 Google LLC
2*e7b1675dSTing-Kang Chang//
3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang//
7*e7b1675dSTing-Kang Chang//      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang//
9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang// limitations under the License.
14*e7b1675dSTing-Kang Chang//
15*e7b1675dSTing-Kang Chang////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Changpackage subtle
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Changimport (
20*e7b1675dSTing-Kang Chang	"errors"
21*e7b1675dSTing-Kang Chang	"fmt"
22*e7b1675dSTing-Kang Chang	"io"
23*e7b1675dSTing-Kang Chang
24*e7b1675dSTing-Kang Chang	"golang.org/x/crypto/hkdf"
25*e7b1675dSTing-Kang Chang)
26*e7b1675dSTing-Kang Chang
27*e7b1675dSTing-Kang Changconst (
28*e7b1675dSTing-Kang Chang	// Minimum tag size in bytes. This provides minimum 80-bit security strength.
29*e7b1675dSTing-Kang Chang	minTagSizeInBytes = uint32(10)
30*e7b1675dSTing-Kang Chang)
31*e7b1675dSTing-Kang Chang
32*e7b1675dSTing-Kang Changvar errHKDFInvalidInput = errors.New("HKDF: invalid input")
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Chang// validateHKDFParams validates parameters of HKDF constructor.
35*e7b1675dSTing-Kang Changfunc validateHKDFParams(hash string, keySize uint32, tagSize uint32) error {
36*e7b1675dSTing-Kang Chang	// validate tag size
37*e7b1675dSTing-Kang Chang	digestSize, err := GetHashDigestSize(hash)
38*e7b1675dSTing-Kang Chang	if err != nil {
39*e7b1675dSTing-Kang Chang		return err
40*e7b1675dSTing-Kang Chang	}
41*e7b1675dSTing-Kang Chang	if tagSize > 255*digestSize {
42*e7b1675dSTing-Kang Chang		return fmt.Errorf("tag size too big")
43*e7b1675dSTing-Kang Chang	}
44*e7b1675dSTing-Kang Chang	if tagSize < minTagSizeInBytes {
45*e7b1675dSTing-Kang Chang		return fmt.Errorf("tag size too small")
46*e7b1675dSTing-Kang Chang	}
47*e7b1675dSTing-Kang Chang	return nil
48*e7b1675dSTing-Kang Chang}
49*e7b1675dSTing-Kang Chang
50*e7b1675dSTing-Kang Chang// ComputeHKDF extracts a pseudorandom key.
51*e7b1675dSTing-Kang Changfunc ComputeHKDF(hashAlg string, key []byte, salt []byte, info []byte, tagSize uint32) ([]byte, error) {
52*e7b1675dSTing-Kang Chang	keySize := uint32(len(key))
53*e7b1675dSTing-Kang Chang	if err := validateHKDFParams(hashAlg, keySize, tagSize); err != nil {
54*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("hkdf: %s", err)
55*e7b1675dSTing-Kang Chang	}
56*e7b1675dSTing-Kang Chang	hashFunc := GetHashFunc(hashAlg)
57*e7b1675dSTing-Kang Chang	if hashFunc == nil {
58*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("hkdf: invalid hash algorithm")
59*e7b1675dSTing-Kang Chang	}
60*e7b1675dSTing-Kang Chang	if len(salt) == 0 {
61*e7b1675dSTing-Kang Chang		salt = make([]byte, hashFunc().Size())
62*e7b1675dSTing-Kang Chang	}
63*e7b1675dSTing-Kang Chang
64*e7b1675dSTing-Kang Chang	result := make([]byte, tagSize)
65*e7b1675dSTing-Kang Chang	kdf := hkdf.New(hashFunc, key, salt, info)
66*e7b1675dSTing-Kang Chang	n, err := io.ReadFull(kdf, result)
67*e7b1675dSTing-Kang Chang	if n != len(result) || err != nil {
68*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("compute of hkdf failed")
69*e7b1675dSTing-Kang Chang	}
70*e7b1675dSTing-Kang Chang	return result, nil
71*e7b1675dSTing-Kang Chang}
72