attest::Buffer Tss2Wrapper::DecryptWithEphemeralKey()

in client-library/src/Attestation/LinuxTpm/lib/Tss2Wrapper.cpp [631:685]


attest::Buffer Tss2Wrapper::DecryptWithEphemeralKey(const attest::PcrSet& pcrSet,
                                                    const attest::Buffer& encryptedBlob,
                                                    const attest::RsaScheme rsaWrapAlgId,
                                                    const attest::RsaHashAlg rsaHashAlgId) {
    // Create an ephemeral key here and then use that key to decrypted the encrypted blob.
    TPM2B_PUBLIC *outPublic = NULL;

    ESYS_TR primaryHandle = Tss2Util::CreateEphemeralKey(*ctx, pcrSet, &outPublic);

    // Store the object in a unique_c_ptr<> to manage clean up after use.
    unique_c_ptr<TPM2B_PUBLIC> outPubPtr(outPublic);

    Tss2Session session(this->ctx->Get());
    try {
        auto pcrDigest = Tss2Util::GeneratePcrDigest(pcrSet, pcrSet.hashAlg);
        auto pcrSelection = Tss2Util::GetTssPcrSelection(*ctx, pcrSet, pcrSet.hashAlg);
        session.Start(TPM2_SE_POLICY);
        session.PolicyPcr(*pcrDigest, *pcrSelection);
    }
    catch(...) {
        Tss2Util::FlushObjectContext(*ctx, primaryHandle);
        throw;
    }

    if(encryptedBlob.size() > TPM2_MAX_RSA_KEY_BYTES) {
        Tss2Util::FlushObjectContext(*ctx, primaryHandle);
        throw std::runtime_error("Encrypted data size larger than Max RSA key size");
    }
    TPM2B_PUBLIC_KEY_RSA cipher_msg;
    memcpy((void*)cipher_msg.buffer, (void*)encryptedBlob.data(), encryptedBlob.size());
    cipher_msg.size = static_cast<UINT16>(encryptedBlob.size());

    TPMT_RSA_DECRYPT scheme;
    scheme.scheme = rsaWrapAlgId;
    scheme.details.oaep.hashAlg = rsaHashAlgId;

    TPM2B_PUBLIC_KEY_RSA* decrypted = NULL;

    TSS2_RC ret = Esys_RSA_Decrypt(this->ctx->Get(), primaryHandle,
                         session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
                         &cipher_msg, &scheme, nullptr, &decrypted);
    if (ret != TSS2_RC_SUCCESS) {
        // Flush the key object from the tpm to make sure we are not consuming tpm memory.
        Tss2Util::FlushObjectContext(*ctx, primaryHandle);
        throw Tss2Exception("Failed to decrypt message", ret);
    }

    // Flush the key object from the tpm to make sure we are not consuming tpm memory.
    Tss2Util::FlushObjectContext(*ctx, primaryHandle);

    attest::Buffer decryptedBlob(decrypted->buffer, decrypted->buffer + decrypted->size);
    free(decrypted);

    return decryptedBlob;
}