From 9662c08e764590ec43b61abddc646689698d928c Mon Sep 17 00:00:00 2001 From: CAFB385655BEB1060E85B6C080B432F8EB2A2AF78459BD6532124977B933154A <133057011+iadgovuser59@users.noreply.github.com> Date: Thu, 24 Oct 2024 20:14:10 +0000 Subject: [PATCH] Improve output for ACA-signed certificates (#859) --- .../persist/provision/AbstractProcessor.java | 2 +- .../CertificateRequestProcessor.java | 21 +++++++-------- .../provision/helper/ProvisionUtils.java | 26 +++++++++++++++++++ .../hirs/Resources/ProvisionerTpm2.proto | 4 +-- .../hirs/src/provisioner/Provisioner.cs | 14 +++++----- .../src/provisioner/ProvisionerTests.cs | 4 +-- .../src/ProvisionerTpm2.proto | 4 +-- 7 files changed, 49 insertions(+), 26 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java index 0f59637a..a98663dd 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java @@ -116,7 +116,7 @@ public class AbstractProcessor { + "Unable to issue certificates"); } - ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSA") + ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA") .setProvider("BC").build(getPrivateKey()); X509CertificateHolder holder = builder.build(signer); return new JcaX509CertificateConverter() diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java index 571e8ae0..e5c3ba0e 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java @@ -160,16 +160,14 @@ public class CertificateRequestProcessor extends AbstractProcessor { attestationCertificate); byte[] derEncodedLdevidCertificate = ProvisionUtils.getDerEncodedCertificate( ldevidCertificate); + String pemEncodedAttestationCertificate = ProvisionUtils.getPemEncodedCertificate( + attestationCertificate); + String pemEncodedLdevidCertificate = ProvisionUtils.getPemEncodedCertificate( + ldevidCertificate); // We validated the nonce and made use of the identity claim so state can be deleted tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState); - // Package the signed certificates into a response - ByteString certificateBytes = ByteString - .copyFrom(derEncodedAttestationCertificate); - ByteString ldevidCertificateBytes = ByteString - .copyFrom(derEncodedLdevidCertificate); - boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate, endorsementCredential, platformCredentials, device, false); boolean generateLDevID = saveAttestationCertificate(certificateRepository, derEncodedLdevidCertificate, @@ -178,10 +176,10 @@ public class CertificateRequestProcessor extends AbstractProcessor { ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse. newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS); if (generateAtt) { - builder = builder.setCertificate(certificateBytes); + builder = builder.setCertificate(pemEncodedAttestationCertificate); } if (generateLDevID) { - builder = builder.setLdevidCertificate(ldevidCertificateBytes); + builder = builder.setLdevidCertificate(pemEncodedLdevidCertificate); } ProvisionerTpm2.CertificateResponse response = builder.build(); @@ -190,20 +188,19 @@ public class CertificateRequestProcessor extends AbstractProcessor { else { byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate( attestationCertificate); + String pemEncodedAttestationCertificate = ProvisionUtils.getPemEncodedCertificate( + attestationCertificate); // We validated the nonce and made use of the identity claim so state can be deleted tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState); - // Package the signed certificates into a response - ByteString certificateBytes = ByteString - .copyFrom(derEncodedAttestationCertificate); ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse. newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS); boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate, endorsementCredential, platformCredentials, device, false); if (generateAtt) { - builder = builder.setCertificate(certificateBytes); + builder = builder.setCertificate(pemEncodedAttestationCertificate); } ProvisionerTpm2.CertificateResponse response = builder.build(); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/ProvisionUtils.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/ProvisionUtils.java index fd131138..4181b09d 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/ProvisionUtils.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/ProvisionUtils.java @@ -18,6 +18,7 @@ import hirs.utils.enums.DeviceInfoEnums; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.ArrayUtils; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -28,6 +29,8 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.io.StringWriter; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -107,6 +110,29 @@ public final class ProvisionUtils { } } + /** + * Helper method to extract a PEM encoded certificate from an X509 certificate. + * + * @param certificate the X509 certificate to be converted to PEM encoding + * @throws {@link UnexpectedServerException} if error occurs during encoding retrieval + * @return the string representing the PEM encoded certificate + */ + public static String getPemEncodedCertificate(final X509Certificate certificate) { + try { + final StringWriter stringWriter = new StringWriter(); + final JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter); + pemWriter.writeObject(certificate); + pemWriter.flush(); + pemWriter.close(); + return stringWriter.toString(); + } catch (IOException ioEx) { + log.error("Error converting certificate to PEM Encoding.", ioEx); + throw new UnexpectedServerException( + "Encountered error while converting X509 Certificate to PEM Encoding: " + + ioEx.getMessage(), ioEx); + } + } + /** * Parse public key from public data segment generated by TPM 2.0. * @param publicArea the public area segment to parse diff --git a/HIRS_Provisioner.NET/hirs/Resources/ProvisionerTpm2.proto b/HIRS_Provisioner.NET/hirs/Resources/ProvisionerTpm2.proto index 53e12525..7e11e11d 100644 --- a/HIRS_Provisioner.NET/hirs/Resources/ProvisionerTpm2.proto +++ b/HIRS_Provisioner.NET/hirs/Resources/ProvisionerTpm2.proto @@ -95,8 +95,8 @@ message CertificateRequest { } message CertificateResponse { - optional bytes certificate = 1; + optional string certificate = 1; optional ResponseStatus status = 2 [default = FAIL]; - optional bytes ldevidCertificate = 3; + optional string ldevidCertificate = 3; } diff --git a/HIRS_Provisioner.NET/hirs/src/provisioner/Provisioner.cs b/HIRS_Provisioner.NET/hirs/src/provisioner/Provisioner.cs index 065244e7..1aba17d8 100644 --- a/HIRS_Provisioner.NET/hirs/src/provisioner/Provisioner.cs +++ b/HIRS_Provisioner.NET/hirs/src/provisioner/Provisioner.cs @@ -297,7 +297,7 @@ namespace hirs { tpm.GetQuote(CommandTpm.DefaultAkHandle, Tpm2Lib.TpmAlgId.Sha256, recoveredSecret, out CommandTpmQuoteResponse ctqr, selectPcrs); Log.Information("----> Nonce successfully decrypted. Sending attestation certificate request"); CertificateRequest akCertReq = acaClient.CreateAkCertificateRequest(recoveredSecret, ctqr); - byte[] certificate; + string certificate; Log.Debug("Communicate certificate request to the ACA."); CertificateResponse cr = await acaClient.PostCertificateRequest(akCertReq); Log.Debug("Response received from the ACA regarding the certificate request."); @@ -311,34 +311,34 @@ namespace hirs { } } if (cr.HasCertificate) { - certificate = cr.Certificate.ToByteArray(); // contains certificate + certificate = cr.Certificate.ToString(); // contains certificate String certificateDirPath = settings.certificate_output_directory; if (certificateDirPath != null) { String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultAKCertFileName); try { - File.WriteAllBytes(certificateFilePath, certificate); + File.WriteAllText(certificateFilePath, certificate); Log.Debug("Attestation key certificate written to local file system: {0}", certificateFilePath); } catch (Exception) { Log.Debug("Failed to write attestation key certificate to local file system."); } } - Log.Debug("Printing attestation key certificate: " + BitConverter.ToString(certificate)); + Log.Debug("Printing attestation key certificate: " + certificate); } if (cr.HasLdevidCertificate) { - certificate = cr.LdevidCertificate.ToByteArray(); // contains certificate + certificate = cr.LdevidCertificate.ToString(); // contains certificate String certificateDirPath = settings.certificate_output_directory; if (certificateDirPath != null) { String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultLDevIDCertFileName); try { - File.WriteAllBytes(certificateFilePath, certificate); + File.WriteAllText(certificateFilePath, certificate); Log.Debug("LDevID certificate written to local file system: {0}", certificateFilePath); } catch (Exception) { Log.Debug("Failed to write LDevID certificate to local file system."); } } - Log.Debug("Printing LDevID certificate: " + BitConverter.ToString(certificate)); + Log.Debug("Printing LDevID certificate: " + certificate); } } else { result = ClientExitCodes.MAKE_CREDENTIAL_BLOB_MALFORMED; diff --git a/HIRS_Provisioner.NET/hirsTest/src/provisioner/ProvisionerTests.cs b/HIRS_Provisioner.NET/hirsTest/src/provisioner/ProvisionerTests.cs index ca44e6b5..41f5a6ac 100644 --- a/HIRS_Provisioner.NET/hirsTest/src/provisioner/ProvisionerTests.cs +++ b/HIRS_Provisioner.NET/hirsTest/src/provisioner/ProvisionerTests.cs @@ -14,7 +14,7 @@ namespace hirsTest { const string address = "https://127.0.0.1:8443/"; byte[] ekCert = Encoding.UTF8.GetBytes("EK CERTIFICATE"); byte[] secret = Encoding.UTF8.GetBytes("AuthCredential Secret"); - byte[] acaIssuedCert = Encoding.UTF8.GetBytes("ACA ISSUED CERTIFICATE"); + string acaIssuedCert = "ACA ISSUED CERTIFICATE"; byte[] integrityHMAC = Convert.FromBase64String("VAtedc1RlNA1w0XfrtwmhE0ILBlILP6163Tur5HRIo0="); byte[] encIdentity = Convert.FromBase64String("6e2oGBsK3H9Vzbj667ZsjnVOtvpSpQ=="); byte[] encryptedSecret = Convert.FromBase64String("NekvnOX8RPRdyd0/cxBI4FTCuNkiu0KAnS28yT7yYJUL5Lwfcv5ctEK6zQA0fq0IsX5TlAYSidGKxrAilOSwALJmJ+m7sMiXwMKrZn1cd4gzXObZEQimQoWgSEQbPO7rfpUn1UfI8K5SzmUFUTxc5X3D8zFonaEBp6QCjtdLegKGgioCDcQFdz20Y0PFAa1Itug7YbZdCFpfit570eQQinmqdVryiNyn6CLQdMgIejuBxoEpoTSWszB5eFKEdn5g/+8wcvhp6RpNBQ0hikF+6688TOVK/j8n3JDwKVltJ/WNHjVO+lxa2aLIMJRgs5ZRuzuz6OSMf10KqJjSWZE04w=="); @@ -34,7 +34,7 @@ namespace hirsTest { idClaimResp.CredentialBlob = Google.Protobuf.ByteString.CopyFrom(credentialBlob); CertificateResponse certResp = new(); certResp.Status = ResponseStatus.Pass; - certResp.Certificate = Google.Protobuf.ByteString.CopyFrom(acaIssuedCert); + certResp.Certificate = acaIssuedCert; IHirsAcaTpm tpm = A.Fake(); byte[] name = null, qualifiedName = null; diff --git a/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto b/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto index aa432b9e..d84ba52f 100644 --- a/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto +++ b/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto @@ -95,8 +95,8 @@ message CertificateRequest { } message CertificateResponse { - optional bytes certificate = 1; + optional string certificate = 1; optional ResponseStatus status = 2 [default = FAIL]; - optional bytes ldevidCertificate = 3; + optional string ldevidCertificate = 3; }