-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support importing HMAC keys and operations #249
Comments
maybe something like this
// CmdHmacStart tpmutil.Command = 0x0000015B
func HmacStart(rw io.ReadWriter, sequenceAuth string, handle tpmutil.Handle, hashAlg Algorithm) (seqHandle tpmutil.Handle, err error) {
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(sequenceAuth)})
if err != nil {
return 0, err
}
out, err := tpmutil.Pack(handle)
if err != nil {
return 0, err
}
Cmd, err := concat(out, auth)
if err != nil {
return 0, err
}
resp, err := runCommand(rw, TagSessions, CmdHmacStart, tpmutil.RawBytes(Cmd), tpmutil.U16Bytes(sequenceAuth), hashAlg)
if err != nil {
return 0, err
}
var rhandle tpmutil.Handle
_, err = tpmutil.Unpack(resp, &rhandle)
return rhandle, err
} then load an hmac key (the following loads and signs one package main
import (
"crypto"
"crypto/rand"
"encoding/hex"
"flag"
"fmt"
"io"
"os"
"github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpmutil"
)
const (
emptyPassword = ""
)
var (
tpmPath = flag.String("tpm-path", "/dev/tpm0", "Path to the TPM device (character device or a Unix socket).")
handleNames = map[string][]tpm2.HandleType{
"all": []tpm2.HandleType{tpm2.HandleTypeLoadedSession, tpm2.HandleTypeSavedSession, tpm2.HandleTypeTransient},
"loaded": []tpm2.HandleType{tpm2.HandleTypeLoadedSession},
"saved": []tpm2.HandleType{tpm2.HandleTypeSavedSession},
"transient": []tpm2.HandleType{tpm2.HandleTypeTransient},
}
defaultKeyParams = tpm2.Public{
Type: tpm2.AlgRSA,
NameAlg: tpm2.AlgSHA256,
Attributes: tpm2.FlagDecrypt | tpm2.FlagRestricted | tpm2.FlagFixedTPM |
tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth,
AuthPolicy: []byte{},
RSAParameters: &tpm2.RSAParams{
Symmetric: &tpm2.SymScheme{
Alg: tpm2.AlgAES,
KeyBits: 128,
Mode: tpm2.AlgCFB,
},
KeyBits: 2048,
},
}
secret = []byte("change this password to a secret")
data = []byte("foo")
)
func main() {
flag.Parse()
rwc, err := tpm2.OpenTPM(*tpmPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Can't open TPM %s: %v", *tpmPath, err)
os.Exit(1)
}
defer func() {
if err := rwc.Close(); err != nil {
fmt.Fprintf(os.Stderr, "can't close TPM %s: %v", *tpmPath, err)
os.Exit(1)
}
}()
totalHandles := 0
for _, handleType := range handleNames["all"] {
handles, err := client.Handles(rwc, handleType)
if err != nil {
fmt.Fprintf(os.Stderr, "error getting handles", *tpmPath, err)
os.Exit(1)
}
for _, handle := range handles {
if err = tpm2.FlushContext(rwc, handle); err != nil {
fmt.Fprintf(os.Stderr, "Error flushing handle 0x%x: %v\n", handle, err)
os.Exit(1)
}
fmt.Printf("Handle 0x%x flushed\n", handle)
totalHandles++
}
}
pcrList := []int{}
pcrSelection := tpm2.PCRSelection{Hash: tpm2.AlgSHA256, PCRs: pcrList}
pkh, _, err := tpm2.CreatePrimary(rwc, tpm2.HandleOwner, pcrSelection, emptyPassword, emptyPassword, defaultKeyParams)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating Primary %v\n", err)
os.Exit(1)
}
defer tpm2.FlushContext(rwc, pkh)
inBuff := []byte(secret)
// Create a private area containing the input
private := tpm2.Private{
Type: tpm2.AlgKeyedHash,
AuthValue: nil,
SeedValue: make([]byte, 32),
Sensitive: inBuff,
}
io.ReadFull(rand.Reader, private.SeedValue)
privArea, err := private.Encode()
if err != nil {
fmt.Fprintf(os.Stderr, "Error encoding private %v\n", err)
os.Exit(1)
}
duplicate, err := tpmutil.Pack(tpmutil.U16Bytes(privArea))
if err != nil {
fmt.Fprintf(os.Stderr, "Error encoding dulicate %v\n", err)
os.Exit(1)
}
privHash := crypto.SHA256.New()
privHash.Write(private.SeedValue)
privHash.Write(private.Sensitive)
public := tpm2.Public{
Type: tpm2.AlgKeyedHash,
NameAlg: tpm2.AlgSHA256,
// Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth | tpm2.FlagSign, // gives "parameter 2, error code 0x2 : inconsistent attributes"
Attributes: tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth | tpm2.FlagSign, // works
KeyedHashParameters: &tpm2.KeyedHashParams{
Alg: tpm2.AlgHMAC,
Hash: tpm2.AlgSHA256,
Unique: privHash.Sum(nil),
},
}
pubArea, err := public.Encode()
if err != nil {
fmt.Fprintf(os.Stderr, "Error encoding public %v\n", err)
os.Exit(1)
}
emptyAuth := tpm2.AuthCommand{Session: tpm2.HandlePasswordSession, Attributes: tpm2.AttrContinueSession}
privInternal, err := tpm2.Import(rwc, pkh, emptyAuth, pubArea, duplicate, nil, nil, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "Error Importing hash key %v\n", err)
os.Exit(1)
}
newHandle, _, err := tpm2.Load(rwc, pkh, "", pubArea, privInternal)
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading hash key %v\n", err)
os.Exit(1)
}
defer tpm2.FlushContext(rwc, newHandle)
// pHandle := tpmutil.Handle(0x81010002)
// err = tpm2.EvictControl(rwc, emptyPassword, tpm2.HandleOwner, newHandle, pHandle)
// if err != nil {
// fmt.Fprintf(os.Stderr,"Error persisting hash key %v\n", err)
// os.Exit(1)
// }
// defer tpm2.FlushContext(rwc, pHandle)
maxDigestBuffer := 1024
seqAuth := ""
seq, err := tpm2.HmacStart(rwc, seqAuth, newHandle, tpm2.AlgSHA256)
if err != nil {
fmt.Fprintf(os.Stderr, "Error starting hash sequence %v\n", err)
os.Exit(1)
}
defer tpm2.FlushContext(rwc, seq)
for len(data) > maxDigestBuffer {
if err = tpm2.SequenceUpdate(rwc, seqAuth, seq, data[:maxDigestBuffer]); err != nil {
fmt.Fprintf(os.Stderr, "Error updating hash sequence %v\n", err)
os.Exit(1)
}
data = data[maxDigestBuffer:]
}
digest, _, err := tpm2.SequenceComplete(rwc, seqAuth, seq, tpm2.HandleNull, data)
if err != nil {
fmt.Fprintf(os.Stderr, "Error completing hash sequence %v\n", err)
os.Exit(1)
}
fmt.Printf("digest %s\n", hex.EncodeToString(digest))
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FR to support
to quote offline thread
go-tpm does not support
tpm2_hmac_start
yet, but it does support hash sequences (so the only command that needs to be added is tpm2_hmac_start).With tpm2_hmac_start in hand, you could import a key and use it for hmacs through the
tpm2_hmac_start/tpm2_sequenceupdate/tpm2_sequencecomplete
flows. Implementing this should be pretty similar to this PR.tpm2_tools
currently does not support importing hmac but does support ::The text was updated successfully, but these errors were encountered: