Check all signatures regardless of the version.
The update_engine daemon had a fixed version number for the public key
used to verify both the metadata and whole payload signatures. The
public key itself is installed by the signer, implying that the source
code and the signer need to be in sync if we ever need to roll the
payload key.
This situation becomes more of a problem if we don't control when the
version number included in the source code is updated in the built
image sent for payload generation and signing.
This patch makes update_engine ignore the version number associated
with a signature and instead tries to verify all the signatures
included in the payload against the public key found in the code. This
effectively deprecates the key version number. To be compatible with
old versions, the version number 1 is included in all signatures.
Bug: 23601118
Test: Added unittests.
Change-Id: I4f96cc207ad6b9c011def5ce586d0e0e85af28ab
diff --git a/payload_generator/payload_signer.cc b/payload_generator/payload_signer.cc
index 218b432..4a2bb95 100644
--- a/payload_generator/payload_signer.cc
+++ b/payload_generator/payload_signer.cc
@@ -38,22 +38,21 @@
namespace {
+// The payload verifier will check all the signatures included in the payload
+// regardless of the version field. Old version of the verifier require the
+// version field to be included and be 1.
+const uint32_t kSignatureMessageLegacyVersion = 1;
+
// Given raw |signatures|, packs them into a protobuf and serializes it into a
// binary blob. Returns true on success, false otherwise.
bool ConvertSignatureToProtobufBlob(const vector<chromeos::Blob>& signatures,
chromeos::Blob* out_signature_blob) {
// Pack it into a protobuf
Signatures out_message;
- uint32_t version = kSignatureMessageOriginalVersion;
- LOG_IF(WARNING, kSignatureMessageCurrentVersion -
- kSignatureMessageOriginalVersion + 1 < signatures.size())
- << "You may want to support clients in the range ["
- << kSignatureMessageOriginalVersion << ", "
- << kSignatureMessageCurrentVersion << "] inclusive, but you only "
- << "provided " << signatures.size() << " signatures.";
for (const chromeos::Blob& signature : signatures) {
Signatures_Signature* sig_message = out_message.add_signatures();
- sig_message->set_version(version++);
+ // Set all the signatures with the same version number.
+ sig_message->set_version(kSignatureMessageLegacyVersion);
sig_message->set_data(signature.data(), signature.size());
}
@@ -156,16 +155,10 @@
padded_hash.data(),
padded_hash.size()));
- // This runs on the server, so it's okay to cop out and call openssl
- // executable rather than properly use the library
- vector<string> cmd;
- base::SplitString("openssl rsautl -raw -sign -inkey x -in x -out x",
- ' ',
- &cmd);
- cmd[cmd.size() - 5] = private_key_path;
- cmd[cmd.size() - 3] = hash_path;
- cmd[cmd.size() - 1] = sig_path;
-
+ // This runs on the server, so it's okay to copy out and call openssl
+ // executable rather than properly use the library.
+ vector<string> cmd = {"openssl", "rsautl", "-raw", "-sign", "-inkey",
+ private_key_path, "-in", hash_path, "-out", sig_path};
int return_code = 0;
TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code,
nullptr));