bool attest::DecryptJwt()

in client-library/src/Attestation/AttestationClient/lib/TpmUnseal.cpp [195:329]


bool attest::DecryptJwt(const EncryptionParameters& encryption_params,
                        const attest::Buffer& decryption_key,
                        const attest::Buffer& jwt_encrypted,
                        std::string& jwt_decrypted,
                        std::string& err) {
    err.clear();

    if(encryption_params.block_mode != attest::BlockCipherMode::CHAINING_MODE_GCM) {
        CLIENT_LOG_ERROR("Unsupported block mode");
        err = std::string("Error: Unsupported block mode");
        return false;
    }
    if(encryption_params.block_padding != attest::BlockCipherPadding::PKCS7) {
        CLIENT_LOG_ERROR("Unsupported block padding");
        err = std::string("Error: Unsupported block padding");
        return false;
    }
    if(encryption_params.cipher_alg != attest::CipherAlgorithm::AES) {
        CLIENT_LOG_ERROR("Unsupported decryption algorithm");
        err = std::string("Error: Unsupported decryption algorithm");
        return false;
    }

    EVP_CIPHER_CTX *ctx;

    // Create and initialise the context
    if(!(ctx = EVP_CIPHER_CTX_new())) {
        CLIENT_LOG_ERROR("Openssl Error: Failed to initialize evp cipher");
        err = std::string("Openssl Error: Failed to initialize evp cipher");
        return false;
    }

    const EVP_CIPHER* alg = _GetOpenSslAesGcmAlg(decryption_key.size());
    if(alg == nullptr) {
        CLIENT_LOG_ERROR("Openssl Error: Failed to get decryption algorithm");
        err = std::string("Openssl Error: Failed to get decryption algorithm");
        return false;
    }

    //Initialise the decryption operation.
    if(!EVP_DecryptInit_ex(ctx, alg, NULL, NULL, NULL)) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    // Set IV length. Not necessary if this is 12 bytes (96 bits)
    if(!EVP_CIPHER_CTX_ctrl(ctx,
                            EVP_CTRL_GCM_SET_IVLEN,
                            static_cast<int>(encryption_params.iv.size()),
                            NULL)) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    // Initialise key and IV
    if(!EVP_DecryptInit_ex(ctx,
                           NULL,
                           NULL,
                           decryption_key.data(),
                           encryption_params.iv.data())) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    attest::Buffer auth_data{'T','r','a','n','s','p','o','r','t',' ','K','e','y'};
    int out_bytes = 0;
    /*
     * Provide any AAD data. This can be called zero or more times as
     * required
    */
    if(!EVP_DecryptUpdate(ctx,
                          NULL,
                          &out_bytes,
                          auth_data.data(),
                          static_cast<int>(auth_data.size()))) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());;
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    attest::Buffer plain_text(jwt_encrypted.size());

    /*
     * Provide the message to be decrypted, and obtain the plaintext output.
     * EVP_DecryptUpdate can be called multiple times if necessary
    */
    if(!EVP_DecryptUpdate(ctx,
                          plain_text.data(),
                          &out_bytes,
                          (const unsigned char*)jwt_encrypted.data(),
                          static_cast<int>(jwt_encrypted.size()))) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    // Set expected tag value. Works in OpenSSL 1.0.1d and later
    if(!EVP_CIPHER_CTX_ctrl(ctx,
                            EVP_CTRL_GCM_SET_TAG,
                            static_cast<int>(encryption_params.authentication_data.size()),
                            (void *)encryption_params.authentication_data.data())) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    /*
     * Finalise the decryption. A positive return value indicates success,
     * anything else is a failure - the plaintext is not trustworthy.
    */
    int ret = EVP_DecryptFinal_ex(ctx,
                                  plain_text.data(),
                                  &out_bytes);
    if(ret <= 0) {
        std::string error_str(ERR_error_string(ERR_get_error(), nullptr));
        CLIENT_LOG_ERROR("Openssl Error:%s", error_str.c_str());
        err = std::string("Openssl Error:") + error_str;
        return false;
    }

    // Clean up
    EVP_CIPHER_CTX_free(ctx);

    jwt_decrypted.assign(plain_text.begin(), plain_text.end());
    return true;
}