On-device signing: Verify signature of odsign.info.

This was left to be implemented with RSA_verify.

Bug: 165630556
Test: signature matches
Change-Id: Iaa66baa54c0479d35ced7a95afccb0328baa4394
diff --git a/ondevice-signing/CertUtils.cpp b/ondevice-signing/CertUtils.cpp
index e74fe9d..cbd1942 100644
--- a/ondevice-signing/CertUtils.cpp
+++ b/ondevice-signing/CertUtils.cpp
@@ -55,6 +55,33 @@
     return true;
 }
 
+Result<bssl::UniquePtr<RSA>> getRsa(const std::vector<uint8_t>& publicKey) {
+    bssl::UniquePtr<RSA> rsaPubkey(RSA_new());
+    rsaPubkey->n = BN_new();
+    rsaPubkey->e = BN_new();
+
+    BN_bin2bn(publicKey.data(), publicKey.size(), rsaPubkey->n);
+    BN_set_word(rsaPubkey->e, kRsaKeyExponent);
+
+    return rsaPubkey;
+}
+
+Result<void> verifySignature(const std::string& message, const std::string& signature,
+                             const std::vector<uint8_t>& publicKey) {
+    auto rsaKey = getRsa(publicKey);
+    uint8_t hashBuf[SHA256_DIGEST_LENGTH];
+    SHA256(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(message.c_str())),
+           message.length(), hashBuf);
+
+    bool success = RSA_verify(NID_sha256, hashBuf, sizeof(hashBuf),
+                              (const uint8_t*)signature.c_str(), signature.length(), rsaKey->get());
+
+    if (!success) {
+        return Error() << "Failed to verify signature.";
+    }
+    return {};
+}
+
 Result<void> createSelfSignedCertificate(
     const std::vector<uint8_t>& publicKey,
     const std::function<Result<std::string>(const std::string&)>& signFunction,
@@ -71,15 +98,10 @@
 
     // "publicKey" corresponds to the raw public key bytes - need to create
     // a new RSA key with the correct exponent.
-    RSA* rsaPubkey = RSA_new();
-    rsaPubkey->n = BN_new();
-    rsaPubkey->e = BN_new();
-
-    BN_bin2bn(publicKey.data(), publicKey.size(), rsaPubkey->n);
-    BN_set_word(rsaPubkey->e, kRsaKeyExponent);
+    auto rsaPubkey = getRsa(publicKey);
 
     EVP_PKEY* public_key = EVP_PKEY_new();
-    EVP_PKEY_assign_RSA(public_key, rsaPubkey);
+    EVP_PKEY_assign_RSA(public_key, rsaPubkey->release());
 
     if (!X509_set_pubkey(x509.get(), public_key)) {
         return Error() << "Unable to set x509 public key";
diff --git a/ondevice-signing/CertUtils.h b/ondevice-signing/CertUtils.h
index ca06f33..66dff04 100644
--- a/ondevice-signing/CertUtils.h
+++ b/ondevice-signing/CertUtils.h
@@ -29,3 +29,7 @@
 android::base::Result<std::vector<uint8_t>>
 extractPublicKeyFromSubjectPublicKeyInfo(const std::vector<uint8_t>& subjectKeyInfo);
 android::base::Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path);
+
+android::base::Result<void> verifySignature(const std::string& message,
+                                            const std::string& signature,
+                                            const std::vector<uint8_t>& publicKey);
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 853f349..eeef868 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -178,7 +178,7 @@
     return verifyDigests(*result, trusted_digests);
 }
 
-Result<OdsignInfo> getOdsignInfo(const SigningKey& /* key */) {
+Result<OdsignInfo> getOdsignInfo(const SigningKey& key) {
     std::string persistedSignature;
     OdsignInfo odsignInfo;
 
@@ -190,24 +190,20 @@
     if (!odsign_info) {
         return Error() << "Failed to open " << kOdsignInfo;
     }
+    odsign_info.seekg(0);
     // Verify the hash
     std::string odsign_info_str((std::istreambuf_iterator<char>(odsign_info)),
                                 std::istreambuf_iterator<char>());
 
-    // TODO: this is way too slow - replace with a local RSA_verify implementation.
-    /*
-    auto verifiedSignature = key.sign(odsign_info_str);
-    if (!verifiedSignature.ok()) {
-        return Error() << "Failed to sign " << kOdsignInfo;
-    }
-
-    if (*verifiedSignature != persistedSignature) {
+    auto publicKey = key.getPublicKey();
+    auto signResult = verifySignature(odsign_info_str, persistedSignature, *publicKey);
+    if (!signResult.ok()) {
         return Error() << kOdsignInfoSignature << " does not match.";
     } else {
         LOG(INFO) << kOdsignInfoSignature << " matches.";
     }
-    */
 
+    odsign_info.seekg(0);
     if (!odsignInfo.ParseFromIstream(&odsign_info)) {
         return Error() << "Failed to parse " << kOdsignInfo;
     }
@@ -223,19 +219,20 @@
     auto map = signInfo.mutable_file_hashes();
     *map = proto_hashes;
 
-    std::fstream odsign_info(kOdsignInfo, std::ios::out | std::ios::trunc | std::ios::binary);
+    std::fstream odsign_info(kOdsignInfo,
+                             std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
     if (!signInfo.SerializeToOstream(&odsign_info)) {
         return Error() << "Failed to persist root hashes in " << kOdsignInfo;
     }
 
-    odsign_info.seekg(0);
+    // Sign the signatures with our key itself, and write that to storage
+    odsign_info.seekg(0, std::ios::beg);
     std::string odsign_info_str((std::istreambuf_iterator<char>(odsign_info)),
                                 std::istreambuf_iterator<char>());
     auto signResult = key.sign(odsign_info_str);
     if (!signResult.ok()) {
         return Error() << "Failed to sign " << kOdsignInfo;
     }
-    // Sign the files with our key itself, and write that to storage
     android::base::WriteStringToFile(*signResult, kOdsignInfoSignature);
     return {};
 }