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 }