///
/// Copyright (c) 2018 xdx. All rights reserved.
///
/// \file: kdf.go
///
/// \brief: SM2和SM9标准中定义的密钥扩展函数，哈希函数使用SM3。
///
/// \author: xdx
///

package kdf

import (
	"encoding/binary"

	"xdx.jelly/xgcl/sm/sm3"
)

type smKDF struct {
}

// Kdf 密钥派生函数
// 省略了检查len(out)-out是调用者已分配好，几乎不会出现len(out)=128G的情况。
// const maxKDFLen = 0x1fffffffe0 //( (1 << 32) - 1 ) * 32
// out必须分配好空间。KDF填充out[:len(out)],输入ins可以包括多组
// 函数内部不会对out的底层数组做重分配
// 目前不返回错误
func (*smKDF) Kdf(out []byte, inputs ...[]byte) error {
	s0 := sm3.NewDigest()
	for _, in := range inputs {
		s0.Write(in)
	}

	buf := make([]byte, 4)
	var ct uint32 = 1
	pos := 0
	s := sm3.NewDigest()
	for pos <= int(len(out))-sm3.Size {
		// make a copy
		*s = *s0
		binary.BigEndian.PutUint32(buf, ct)
		ct++
		s.Write(buf[:4])
		s.Sum(out[:pos])
		pos += sm3.Size
	}
	if pos < len(out) {
		binary.BigEndian.PutUint32(buf, ct)
		s0.Write(buf[:4])
		d := s0.Sum(nil)
		copy(out[pos:], d)
	}
	return nil
}
