in client-library/src/Attestation/AttestationClient/lib/TpmCertOperations.cpp [115:230]
AttestationResult TpmCertOperations::RenewAndReplaceAkCert() {
AttestationResult result = AttestationResult(AttestationResult::ErrorCode::SUCCESS);
try {
ImdsClient imds;
std::string vm_id = imds.GetVmId();
if (vm_id.empty()) {
CLIENT_LOG_ERROR("Failed to get vm id");
if(telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Failed to get vm id",
TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_VM_ID);
}
result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
result.description_ = "Failed to get VM id from IMDS";
return result;
}
Tpm tpm;
std::string request_id = attest::utils::Uuid();
std::string ak_cert;
if ((result = ReadAkCertFromTpm(ak_cert)).code_ != AttestationResult::ErrorCode::SUCCESS) {
CLIENT_LOG_ERROR("Failed to read AK Cert from TPM");
return result;
}
std::string ak_cert_renew_response = imds.RenewAkCert(ak_cert, vm_id, request_id, ak_renew_sync_api_version);
if (telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
ak_cert_renew_response, TelemetryReportingBase::EventLevel::AK_RENEW_RESPONSE);
}
std::string renewed_cert = std::string();
if (!ak_cert_renew_response.empty()) {
if (telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Successfully retrived AkCert response from Thim",
TelemetryReportingBase::EventLevel::AK_RENEW_GET_RESPONSE_SUCCESS);
}
renewed_cert = ParseAndGetAkCert(ak_cert_renew_response);
if (renewed_cert.empty()) {
CLIENT_LOG_ERROR("Failed to get AkCertPem from response.");
if (telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Failed to get AkCertPem from response",
TelemetryReportingBase::EventLevel::AK_RENEW_RESPONSE_PARSING_FAILURE);
}
result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
result.description_ = "Failed to get AkCert Pem from response";
return result;
}
} else {
CLIENT_LOG_ERROR("Failed to renew Ak cert using sync api");
if(telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Failed to renew Ak Cert using sync api",
TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_CERT_RESPONSE);
}
CLIENT_LOG_INFO("Retrying Ak renew using async api");
request_id = attest::utils::Uuid();
ak_cert_renew_response = imds.RenewAkCert(ak_cert, vm_id, request_id, ak_renew_async_api_version);
// sleep for 60 seconds
std::this_thread::sleep_for(std::chrono::seconds(QUERY_RENEWED_CERT_AFTER_SECONDS));
request_id = attest::utils::Uuid();
renewed_cert = imds.QueryAkCert(ak_cert_renew_response, vm_id, request_id);
if (renewed_cert.empty()) {
CLIENT_LOG_INFO("Failed to query Ak cert using async api");
if(telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Failed to query Ak Cert using async api",
TelemetryReportingBase::EventLevel::AK_RENEW_EMPTY_RENEWED_CERT);
}
result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
result.description_ = "Failed to query Ak cert using async api";
return result;
}
}
if (telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
renewed_cert,
TelemetryReportingBase::EventLevel::AK_RENEWED_CERT);
}
// write renewed cert to TPM
std::vector<unsigned char> cert_der = attest::base64::base64_to_binary(
RemoveCertHeaderAndFooter(renewed_cert));
tpm.WriteAikCert(cert_der);
CLIENT_LOG_INFO("Successfully renewed AK cert");
if(telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Successfully renewed Ak Cert",
TelemetryReportingBase::EventLevel::AK_RENEW_SUCCESS);
}
}
catch (const std::exception& e) {
CLIENT_LOG_ERROR("Unexpected error occured in RenewAndReplaceAkCert method %s", e.what());
if(telemetry_reporting.get() != nullptr) {
telemetry_reporting->UpdateEvent("AkRenew",
"Unexpted Error in RenewAndReplaceAkCert",
TelemetryReportingBase::EventLevel::AK_RENEW_UNEXPECTED_ERROR);
}
result.code_ = AttestationResult::ErrorCode::ERROR_AK_CERT_RENEW;
result.description_ = "Unexpected erropr in RenewAndReplaceAkCert";
}
return result;
}