linux/tpm_keys.go (129 lines of code) (raw):
// +build linux
// Copyright (c) Facebook, Inc. and its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package linux
import (
"errors"
"reflect"
"github.com/facebookincubator/sks/utils"
"github.com/facebookincubator/flog"
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpmutil"
)
// This file contains all functions for working with keys generated by a
// cryptographic processor (using the Cryptoprocessor interface).
func (key *tpmKey) IsEmpty() bool {
return key == nil || reflect.DeepEqual(key.PublicArea, tpm2.Public{}) || key.PublicBytes == nil
}
func (key *tpmKey) Close() error {
key.loadedHandle = 0
key.CreationData = nil
key.CreationHash = nil
key.PrivateArea = tpm2.Private{}
key.PublicBytes = nil
key.PublicArea = tpm2.Public{}
key.PrivateBytes = nil
key.Name = tpm2.Name{}
return nil
}
func (key *tpmKey) GetECPublicKey() (*utils.ECCPublicKey, error) {
params := key.PublicArea.ECCParameters
if params == nil || reflect.DeepEqual(params, tpm2.ECCParams{}) {
return nil, errors.New("key does not have valid ECC parameters")
}
pubKey := &utils.ECCPublicKey{
X: params.Point.X(),
Y: params.Point.Y(),
}
return pubKey, nil
}
func (key *tpmKey) GetHandle() tpmutil.Handle {
return key.Handle
}
func (key *tpmKey) GetLoadedHandle() tpmutil.Handle {
return key.loadedHandle
}
func (key *tpmKey) SetLoadedHandle(handle tpmutil.Handle) {
key.loadedHandle = handle
}
func (key *tpmKey) GetPublicArea() tpm2.Public {
return key.PublicArea
}
func (key *tpmKey) GetPublicBytes() []byte {
if key.IsEmpty() {
flog.Warningf("Empty key. Cannot get public bytes.")
return nil
}
if key.PublicBytes != nil {
return key.PublicBytes
}
rawBytes, err := key.PublicArea.Encode()
if err != nil {
flog.Warningf("Got error decoding key public area: %v", err)
return nil
}
return rawBytes
}
func (key *tpmKey) GetPrivateArea() tpm2.Private {
return key.PrivateArea
}
func (key *tpmKey) GetPrivateBytes() []byte {
if key.PrivateBytes != nil {
return key.PrivateBytes
}
if !reflect.DeepEqual(key.PrivateArea, tpm2.Private{}) {
rawBytes, err := key.PrivateArea.Encode()
if err == nil {
return rawBytes
}
flog.Warningf("Got error decoding key private area: %v", err)
}
return nil
}
func (key *tpmKey) FillKeyData(publicBytes, privateBytes, creationData, keyName []byte) error {
var err error
if publicBytes != nil {
key.PublicBytes = publicBytes
key.PublicArea, err = tpm2.DecodePublic(publicBytes)
if err != nil {
return err
}
flog.Debug("Decoded key public area")
}
if privateBytes != nil {
key.PrivateBytes = privateBytes
}
if creationData != nil {
key.CreationData, err = tpm2.DecodeCreationData(creationData)
if err != nil {
return err
}
flog.Debug("Decoded key creation data")
}
if keyName != nil {
key.Name = tpm2.Name{
Digest: &tpm2.HashValue{},
}
byteCount, err := tpmutil.Unpack(keyName, &key.Name.Digest.Alg)
if err != nil {
flog.Warningf("Got error decoding key name, ignoring: %+v", err)
key.Name = tpm2.Name{}
} else {
key.Name.Digest.Value = keyName[byteCount:]
// Validate the key name digest value
hashFunc, err := key.Name.Digest.Alg.Hash()
if err != nil {
flog.Warningf(
"Failed to get key digest algorithm hash constructor, ignoring: %+v",
err,
)
key.Name = tpm2.Name{}
} else {
if hashFunc.Size() != len(key.Name.Digest.Value) {
flog.Warningf(
"Failed to validate key name value: expected digest length %d, got %d; ignoring name",
hashFunc.Size(),
len(key.Name.Digest.Value),
)
key.Name = tpm2.Name{}
}
}
flog.Debug("Key name set")
}
}
return nil
}