Vendor dependencies and expose control program binaries via nix build. Uses nixpkgs-unstable for Go 1.26 support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package tpm2
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/hmac"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
var (
|
|
labelStorage = "STORAGE"
|
|
labelIntegrity = "INTEGRITY"
|
|
|
|
ErrUnsupportedCipher = errors.New("unsupported block cipher")
|
|
ErrUnsupportedMode = errors.New("unsupported block cipher mode of operation")
|
|
)
|
|
|
|
// deriveAndEncrypt derives a symmetric key and uses it to encrypt the plaintext.
|
|
func deriveAndEncrypt(pub LabeledEncapsulationKey, seed []byte, context []byte, plaintext []byte) ([]byte, error) {
|
|
// Only AES is supported.
|
|
if pub.SymmetricParameters().Algorithm != TPMAlgAES {
|
|
return nil, fmt.Errorf("%w %v", ErrUnsupportedCipher, pub.SymmetricParameters().Algorithm)
|
|
}
|
|
mode, err := pub.SymmetricParameters().Mode.AES()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if *mode != TPMAlgCFB {
|
|
return nil, fmt.Errorf("%w %v", ErrUnsupportedMode, *mode)
|
|
}
|
|
bits, err := pub.SymmetricParameters().KeyBits.AES()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hash, err := pub.NameAlg().Hash()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
key, err := aes.NewCipher(KDFa(hash, seed, labelStorage, context, nil, int(*bits)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ciphertext := make([]byte, len(plaintext))
|
|
cipher.NewCFBEncrypter(key, make([]byte, key.BlockSize())).XORKeyStream(ciphertext, plaintext)
|
|
return ciphertext, nil
|
|
}
|
|
|
|
// deriveAndHMAC derives an HMAC key and uses it to HMAC the data, which can be provided in multiple chunks.
|
|
func deriveAndHMAC(pub LabeledEncapsulationKey, seed []byte, data ...[]byte) ([]byte, error) {
|
|
hash, err := pub.NameAlg().Hash()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
key := KDFa(hash, seed, labelIntegrity, nil, nil, hash.Size()*8)
|
|
hmac := hmac.New(hash.New, key)
|
|
for _, data := range data {
|
|
hmac.Write(data)
|
|
}
|
|
return hmac.Sum(nil), nil
|
|
}
|