in aws_signing_helper/tpm_signer.go [331:444]
func GetTPMv2Signer(opts GetTPMv2SignerOpts) (signer Signer, signingAlgorithm string, err error) {
var (
certificate *x509.Certificate
certificateChain []*x509.Certificate
keyPem *pem.Block
password string
emptyAuth bool
tpmData tpm2_TPMKey
handle tpmutil.Handle
public tpm2.Public
private []byte
)
certificate = opts.certificate
certificateChain = opts.certificateChain
keyPem = opts.keyPem
password = opts.password
emptyAuth = opts.emptyAuth
// If a handle is provided instead of a TPM key file
if opts.handle != "" {
handleParts := strings.Split(opts.handle, ":")
if len(handleParts) != 2 {
return nil, "", errors.New("invalid TPM handle format")
}
hexHandleStr := handleParts[1]
if strings.HasPrefix(hexHandleStr, "0x") {
hexHandleStr = hexHandleStr[2:]
}
handleValue, err := strconv.ParseUint(hexHandleStr, 16, 32)
if err != nil {
return nil, "", errors.New("invalid hex TPM handle value")
}
handle = tpmutil.Handle(handleValue)
// Read the public key from the loaded key within the TPM
rw, err := openTPM()
if err != nil {
return nil, "", err
}
defer rw.Close()
public, _, _, err = tpm2.ReadPublic(rw, handle)
if err != nil {
return nil, "", err
}
} else {
fixupEmptyAuth(&keyPem.Bytes)
_, err = asn1.Unmarshal(keyPem.Bytes, &tpmData)
if err != nil {
return nil, "", err
}
emptyAuth = tpmData.EmptyAuth
if emptyAuth && password != "" {
return nil, "", errors.New("password is provided but TPM key file indicates that one isn't required")
}
if !tpmData.Oid.Equal(oidLoadableKey) {
return nil, "", errors.New("invalid OID for TPMv2 key:" + tpmData.Oid.String())
}
if tpmData.Policy != nil || tpmData.AuthPolicy != nil {
return nil, "", errors.New("TPMv2 policy not implemented yet")
}
if tpmData.Secret != nil {
return nil, "", errors.New("TPMv2 key has 'secret' field which should not be set")
}
if !handleIsPersistent(tpmData.Parent) &&
tpmData.Parent != int(tpm2.HandleOwner) &&
tpmData.Parent != int(tpm2.HandleNull) &&
tpmData.Parent != int(tpm2.HandleEndorsement) &&
tpmData.Parent != int(tpm2.HandlePlatform) {
return nil, "", errors.New("invalid parent for TPMv2 key")
}
if len(tpmData.Pubkey) < 2 ||
len(tpmData.Pubkey)-2 != (int(tpmData.Pubkey[0])<<8)+int(tpmData.Pubkey[1]) {
return nil, "", errors.New("invalid length for TPMv2 PUBLIC blob")
}
public, err = tpm2.DecodePublic(tpmData.Pubkey[2:])
if err != nil {
return nil, "", err
}
if len(tpmData.Privkey) < 2 ||
len(tpmData.Privkey)-2 != (int(tpmData.Privkey[0])<<8)+int(tpmData.Privkey[1]) {
return nil, "", errors.New("invalid length for TPMv2 PRIVATE blob")
}
private = tpmData.Privkey[2:]
}
switch public.Type {
case tpm2.AlgRSA:
signingAlgorithm = aws4_x509_rsa_sha256
case tpm2.AlgECC:
signingAlgorithm = aws4_x509_ecdsa_sha256
default:
return nil, "", errors.New("unsupported TPMv2 key type")
}
return &TPMv2Signer{
certificate,
certificateChain,
tpmData,
public,
private,
password,
emptyAuth,
handle,
},
signingAlgorithm, nil
}