Cleaned up attestation certificate chain formatting.

If only a single certificate is provided, then the chain is simply that
certificate in PEM format.

BUG=chromium:240301
TEST=unit

Change-Id: I00abcd9b25139a5e39ea11441ce5e1faeed2d555
Reviewed-on: https://chromium-review.googlesource.com/180498
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: Darren Krahn <dkrahn@chromium.org>
Tested-by: Darren Krahn <dkrahn@chromium.org>
diff --git a/attestation.cc b/attestation.cc
index 845684d..e53f182 100644
--- a/attestation.cc
+++ b/attestation.cc
@@ -1360,11 +1360,17 @@
 bool Attestation::CreatePEMCertificateChain(const string& leaf_certificate,
                                             const string& intermediate_ca_cert,
                                             SecureBlob* certificate_chain) {
-  string leaf_pem = CreatePEMCertificate(leaf_certificate);
-  string ca_pem = CreatePEMCertificate(intermediate_ca_cert);
-  *certificate_chain = ConvertStringToBlob(leaf_pem + "\n" + ca_pem);
-  ClearString(&leaf_pem);
-  ClearString(&ca_pem);
+  if (leaf_certificate.empty()) {
+    LOG(ERROR) << "Certificate is empty.";
+    return false;
+  }
+  string pem = CreatePEMCertificate(leaf_certificate);
+  if (!intermediate_ca_cert.empty()) {
+    pem += "\n";
+    pem += CreatePEMCertificate(intermediate_ca_cert);
+  }
+  *certificate_chain = ConvertStringToBlob(pem);
+  ClearString(&pem);
   return true;
 }
 
diff --git a/attestation_unittest.cc b/attestation_unittest.cc
index 0edc68f..5505a08 100644
--- a/attestation_unittest.cc
+++ b/attestation_unittest.cc
@@ -119,10 +119,11 @@
     return SecureBlob(tmp.data(), tmp.length());
   }
 
-  SecureBlob GetCertifiedKeyBlob(const string& payload) {
+  SecureBlob GetCertifiedKeyBlob(const string& payload, bool include_ca_cert) {
     CertifiedKey pb;
     pb.set_certified_key_credential("stored_cert");
-    pb.set_intermediate_ca_cert("stored_ca_cert");
+    if (include_ca_cert)
+      pb.set_intermediate_ca_cert("stored_ca_cert");
     pb.set_public_key(ConvertBlobToString(GetPKCS1PublicKey()));
     pb.set_payload(payload);
     string tmp;
@@ -139,9 +140,12 @@
   string EncodeCertChain(const string& cert1, const string& cert2) {
     string chain = "-----BEGIN CERTIFICATE-----\n";
     chain += CryptoLib::Base64Encode(cert1, true);
-    chain += "-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n";
-    chain += CryptoLib::Base64Encode(cert2, true);
     chain += "-----END CERTIFICATE-----";
+    if (!cert2.empty()) {
+      chain += "\n-----BEGIN CERTIFICATE-----\n";
+      chain += CryptoLib::Base64Encode(cert2, true);
+      chain += "-----END CERTIFICATE-----";
+    }
     return chain;
   }
 
@@ -321,7 +325,7 @@
   EXPECT_CALL(key_store_, Read(kTestUser, "test", _))
       .WillOnce(Return(false))
       .WillRepeatedly(DoAll(
-          SetArgumentPointee<2>(GetCertifiedKeyBlob("")),
+          SetArgumentPointee<2>(GetCertifiedKeyBlob("", true)),
           Return(true)));
   SecureBlob blob;
   attestation_.PrepareForEnrollment();
@@ -431,7 +435,7 @@
                             Return(true)));
   EXPECT_CALL(key_store_, Read(kTestUser, "test", _))
       .WillRepeatedly(DoAll(
-          SetArgumentPointee<2>(GetCertifiedKeyBlob("")),
+          SetArgumentPointee<2>(GetCertifiedKeyBlob("", true)),
           Return(true)));
   chromeos::SecureBlob blob;
   SecureBlob challenge = GetEnterpriseChallenge("EnterpriseKeyChallenge", true);
@@ -454,11 +458,11 @@
 
 TEST_F(AttestationTest, Payload) {
   EXPECT_CALL(key_store_, Write(kTestUser, "test",
-                                GetCertifiedKeyBlob("test_payload")))
+                                GetCertifiedKeyBlob("test_payload", true)))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(key_store_, Read(kTestUser, "test", _))
       .WillRepeatedly(DoAll(
-          SetArgumentPointee<2>(GetCertifiedKeyBlob("stored_payload")),
+          SetArgumentPointee<2>(GetCertifiedKeyBlob("stored_payload", true)),
           Return(true)));
   EXPECT_CALL(tpm_, CreateCertifiedKey(_, _, _, _, _, _, _))
       .WillRepeatedly(DoAll(SetArgumentPointee<3>(GetPKCS1PublicKey()),
@@ -560,4 +564,15 @@
               !db.credentials().has_endorsement_credential());
 }
 
+TEST_F(AttestationTest, CertChainWithNoIntermediateCA) {
+  EXPECT_CALL(key_store_, Read(kTestUser, "test", _))
+      .WillRepeatedly(DoAll(
+          SetArgumentPointee<2>(GetCertifiedKeyBlob("", false)),
+          Return(true)));
+  SecureBlob blob;
+  EXPECT_TRUE(attestation_.GetCertificateChain(true, kTestUser, "test",
+                                               &blob));
+  EXPECT_TRUE(CompareBlob(blob, EncodeCertChain("stored_cert", "")));
+}
+
 }  // namespace cryptohome