Skip to content

Certify, CertifyEx, and CertifyCreation return partial signature data #236

@chrisfenner

Description

@chrisfenner

Here is the response description from the TPM 2.0 spec for the parameters returned from Certify and CertifyCreation:

Type Name Description
TPM2B_ATTEST certifyInfo the structure that was signed
TPMT_SIGNATURE signature the asymmetric signature ...

Here is decodeCertify which is used by all 3 of Certify, CertifyEx, and CertifyCreation:

go-tpm/tpm2/tpm2.go

Lines 1747 to 1778 in 1ff48da

func decodeCertify(resp []byte) ([]byte, []byte, error) {
var paramSize uint32
var attest, signature tpmutil.U16Bytes
var sigAlg, hashAlg Algorithm
buf := bytes.NewBuffer(resp)
if err := tpmutil.UnpackBuf(buf, &paramSize); err != nil {
return nil, nil, err
}
buf.Truncate(int(paramSize))
if err := tpmutil.UnpackBuf(buf, &attest, &sigAlg); err != nil {
return nil, nil, err
}
// If sigAlg is AlgNull, there will be no hashAlg or signature.
// This will happen if AlgNull was passed in the Certify() as
// the signing key (no need to sign the response).
// See TPM2 spec part4 pg227 SignAttestInfo()
if sigAlg != AlgNull {
if sigAlg == AlgECDSA {
var r, s tpmutil.U16Bytes
if err := tpmutil.UnpackBuf(buf, &hashAlg, &r, &s); err != nil {
return nil, nil, err
}
signature = append(r, s...)
} else {
if err := tpmutil.UnpackBuf(buf, &hashAlg, &signature); err != nil {
return nil, nil, err
}
}
}
return attest, signature, nil
}

In particular, note that the second parameter is signature which is the parsed raw RSA signature (exponentiated plaintext modulo key's modulus) or ECDSA signature (r, s pair). This is a loss of the following data:

  • sigAlg from TPMT_SIGNATURE
  • hash from TPMS_SIGNATURE_ECC if sigAlg indicated an ECC signature, or from TPMS_SIGNATURE_RSA if sigAlg indicated an RSA signature.

This means that a consumer of the output of the Certify command (via Certify or CertifyEx) or CertifyCreation command has to remember or guess the signature algorithm, as well as the hash algorithm that was used.

  • Guessing the sigAlg parameter is not trivially "if it's small, it's ECC, else RSA" because TPM supports multiple schemes per algorithm family (e.g., either PSS or PKCS1.5 for RSA). So throwing this data away harms potential users of the API.
  • Guessing the hash is reasonably done in 2021 by assuming it's SHA2-256, but this is subject to change and should be expected to as more TPMs support SHA2-384 and users become interested in that algorithm.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions