in aws_signing_helper/tpm_signer.go [117:245]
func (tpmv2Signer *TPMv2Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
var (
keyHandle tpmutil.Handle
)
rw, err := openTPM()
if err != nil {
return nil, err
}
defer rw.Close()
if tpmv2Signer.handle != 0 {
keyHandle = tpmv2Signer.handle
} else {
parentHandle := tpmutil.Handle(tpmv2Signer.tpmData.Parent)
if !handleIsPersistent(tpmv2Signer.tpmData.Parent) {
// Parent and owner passwords aren't supported currently when creating a primary given a persistent handle for the parent
parentHandle, _, err = tpm2.CreatePrimary(rw, tpmutil.Handle(tpmv2Signer.tpmData.Parent), tpm2.PCRSelection{}, "", "", primaryParams)
if err != nil {
return nil, err
}
defer tpm2.FlushContext(rw, parentHandle)
}
keyHandle, _, err = tpm2.Load(rw, parentHandle, "", tpmv2Signer.tpmData.Pubkey[2:], tpmv2Signer.tpmData.Privkey[2:])
if err != nil {
return nil, err
}
defer tpm2.FlushContext(rw, keyHandle)
}
var algo tpm2.Algorithm
var shadigest []byte
switch opts.HashFunc() {
case crypto.SHA256:
sha256digest := sha256.Sum256(digest)
shadigest = sha256digest[:]
algo = tpm2.AlgSHA256
case crypto.SHA384:
sha384digest := sha512.Sum384(digest)
shadigest = sha384digest[:]
algo = tpm2.AlgSHA384
case crypto.SHA512:
sha512digest := sha512.Sum512(digest)
shadigest = sha512digest[:]
algo = tpm2.AlgSHA512
}
if tpmv2Signer.public.Type == tpm2.AlgECC {
// Check to see that ECDSA is supported for signing
err = checkCapability(rw, tpm2.AlgECC)
if err != nil {
return nil, err
}
// For an EC key we lie to the TPM about what the hash is.
// It doesn't actually matter what the original digest was;
// the algo we feed to the TPM is *purely* based on the
// size of the curve itself. We truncate the actual digest,
// or pad with zeroes, to the byte size of the key.
pubKey, err := tpmv2Signer.public.Key()
if err != nil {
return nil, err
}
ecPubKey, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("failed to obtain ecdsa.PublicKey")
}
bitSize := ecPubKey.Curve.Params().BitSize
byteSize := (bitSize + 7) / 8
if byteSize > sha512.Size {
byteSize = sha512.Size
}
switch byteSize {
case sha512.Size:
algo = tpm2.AlgSHA512
case sha512.Size384:
algo = tpm2.AlgSHA384
case sha512.Size256:
algo = tpm2.AlgSHA256
case sha1.Size:
algo = tpm2.AlgSHA1
default:
return nil, errors.New("unsupported curve")
}
if len(shadigest) > byteSize {
shadigest = shadigest[:byteSize]
}
for len(shadigest) < byteSize {
shadigest = append([]byte{0}, shadigest...)
}
sig, err := tpmv2Signer.signHelper(rw, keyHandle, shadigest,
&tpm2.SigScheme{Alg: tpm2.AlgECDSA, Hash: algo})
if err != nil {
return nil, err
}
signature, err = asn1.Marshal(struct {
R *big.Int
S *big.Int
}{sig.ECC.R, sig.ECC.S})
if err != nil {
return nil, err
}
} else {
// Check to see that the requested hash function is supported
err = checkCapability(rw, algo)
if err != nil {
return nil, err
}
// Check to see that RSASSA is supported for signing
err = checkCapability(rw, tpm2.AlgRSASSA)
if err != nil {
return nil, err
}
sig, err := tpmv2Signer.signHelper(rw, keyHandle, shadigest,
&tpm2.SigScheme{Alg: tpm2.AlgRSASSA, Hash: algo})
if err != nil {
return nil, err
}
signature = sig.RSA.Signature
}
return signature, nil
}