in linux/sks.go [81:126]
func (tpm *tpmDevice) SignWithKey(keyID string, digest []byte) ([]byte, error) {
// First get the org root key so the requested child key can be loaded and
// used.
orgRootKey, err := tpm.GetOrgRootKey()
if err != nil {
return nil, fmt.Errorf("error while getting root key: %w", err)
}
defer tpm.FlushKey(orgRootKey, true)
// Next get the requested key, or bail if it can't be loaded.
key, err := tpm.LoadKey(keyID, orgRootKey.GetHandle(), 0, nil)
if err != nil {
return nil, fmt.Errorf("could not load requested key %q: %w", keyID, err)
}
defer tpm.FlushKey(key, true)
signature, err := tpm2.Sign(
tpm.rwc,
key.GetLoadedHandle(),
"",
digest,
nil,
&tpm2.SigScheme{
Alg: tpm2.AlgECDSA,
Hash: tpm2.AlgSHA256,
},
)
if err != nil {
return nil, fmt.Errorf("could not sign with key %q: %w", keyID, err)
}
// The standard elliptic Marshal includes more data than needed, which
// causes signature validation problems. Create a simple struct with just
// the EC points and marshal that in ASN.1 format.
basicSig := utils.ECCSignature{
R: signature.ECC.R,
S: signature.ECC.S,
}
derBytes, err := asn1.Marshal(basicSig)
if err != nil {
return nil, fmt.Errorf("failed to marshal ECC signature: %w", err)
}
return derBytes, nil
}