blob: 19a923004dcd328c6267e46b1218e7fa9f51827c [file] [log] [blame]
Darin Petkov85d02b72011-05-17 13:25:51 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes0c440052010-08-20 11:25:54 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/payload_signer.h"
6
Darin Petkovb039d502010-12-03 09:08:04 -08007#include <base/logging.h>
Chris Masoned903c3b2011-05-12 15:35:46 -07008#include <base/string_split.h>
Darin Petkovb039d502010-12-03 09:08:04 -08009#include <base/string_util.h>
10#include <openssl/pem.h>
11
Darin Petkov9574f7e2011-01-13 10:48:12 -080012#include "update_engine/delta_diff_generator.h"
13#include "update_engine/delta_performer.h"
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070014#include "update_engine/omaha_hash_calculator.h"
Andrew de los Reyes0c440052010-08-20 11:25:54 -070015#include "update_engine/subprocess.h"
16#include "update_engine/update_metadata.pb.h"
17#include "update_engine/utils.h"
18
19using std::string;
20using std::vector;
21
22namespace chromeos_update_engine {
23
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070024const uint32_t kSignatureMessageOriginalVersion = 1;
25const uint32_t kSignatureMessageCurrentVersion = 1;
Andrew de los Reyes0c440052010-08-20 11:25:54 -070026
Darin Petkov9574f7e2011-01-13 10:48:12 -080027namespace {
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070028
Han Shen2643cb72012-06-26 14:45:33 -070029const unsigned char kRSA2048SHA256Padding[] = {
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070030 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
46 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
47 0x00, 0x04, 0x20
48};
49
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070050// Given raw |signatures|, packs them into a protobuf and serializes it into a
Darin Petkov9574f7e2011-01-13 10:48:12 -080051// binary blob. Returns true on success, false otherwise.
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070052bool ConvertSignatureToProtobufBlob(const vector<vector<char> >& signatures,
Darin Petkov9574f7e2011-01-13 10:48:12 -080053 vector<char>* out_signature_blob) {
54 // Pack it into a protobuf
55 Signatures out_message;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070056 uint32_t version = kSignatureMessageOriginalVersion;
57 LOG_IF(WARNING, kSignatureMessageCurrentVersion -
58 kSignatureMessageOriginalVersion + 1 < signatures.size())
Jay Srinivasan51dcf262012-09-13 17:24:32 -070059 << "You may want to support clients in the range ["
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070060 << kSignatureMessageOriginalVersion << ", "
61 << kSignatureMessageCurrentVersion << "] inclusive, but you only "
62 << "provided " << signatures.size() << " signatures.";
63 for (vector<vector<char> >::const_iterator it = signatures.begin(),
64 e = signatures.end(); it != e; ++it) {
65 const vector<char>& signature = *it;
66 Signatures_Signature* sig_message = out_message.add_signatures();
67 sig_message->set_version(version++);
68 sig_message->set_data(signature.data(), signature.size());
69 }
Darin Petkov9574f7e2011-01-13 10:48:12 -080070
71 // Serialize protobuf
72 string serialized;
73 TEST_AND_RETURN_FALSE(out_message.AppendToString(&serialized));
74 out_signature_blob->insert(out_signature_blob->end(),
75 serialized.begin(),
76 serialized.end());
77 LOG(INFO) << "Signature blob size: " << out_signature_blob->size();
78 return true;
79}
80
Darin Petkovadb3cef2011-01-13 16:16:08 -080081bool LoadPayload(const string& payload_path,
82 vector<char>* out_payload,
83 DeltaArchiveManifest* out_manifest,
84 uint64_t* out_metadata_size) {
85 vector<char> payload;
86 // Loads the payload and parses the manifest.
87 TEST_AND_RETURN_FALSE(utils::ReadFile(payload_path, &payload));
88 LOG(INFO) << "Payload size: " << payload.size();
Jay Srinivasan51dcf262012-09-13 17:24:32 -070089 ActionExitCode error = kActionCodeSuccess;
90 InstallPlan install_plan;
91 DeltaPerformer delta_performer(NULL, &install_plan);
92 TEST_AND_RETURN_FALSE(delta_performer.ParsePayloadMetadata(
93 payload, out_manifest, out_metadata_size, &error) ==
Darin Petkovadb3cef2011-01-13 16:16:08 -080094 DeltaPerformer::kMetadataParseSuccess);
95 LOG(INFO) << "Metadata size: " << *out_metadata_size;
96 out_payload->swap(payload);
97 return true;
98}
99
Darin Petkov9574f7e2011-01-13 10:48:12 -0800100// Given an unsigned payload under |payload_path| and the |signature_blob_size|
101// generates an updated payload that includes a dummy signature op in its
102// manifest. Returns true on success, false otherwise.
Darin Petkovadb3cef2011-01-13 16:16:08 -0800103bool AddSignatureOpToPayload(const string& payload_path,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800104 int signature_blob_size,
105 vector<char>* out_payload) {
106 const int kProtobufOffset = 20;
107 const int kProtobufSizeOffset = 12;
108
Darin Petkovadb3cef2011-01-13 16:16:08 -0800109 // Loads the payload.
Darin Petkov9574f7e2011-01-13 10:48:12 -0800110 vector<char> payload;
Darin Petkov9574f7e2011-01-13 10:48:12 -0800111 DeltaArchiveManifest manifest;
Darin Petkovadb3cef2011-01-13 16:16:08 -0800112 uint64_t metadata_size;
113 TEST_AND_RETURN_FALSE(LoadPayload(
114 payload_path, &payload, &manifest, &metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800115 TEST_AND_RETURN_FALSE(!manifest.has_signatures_offset() &&
116 !manifest.has_signatures_size());
117
118 // Updates the manifest to include the signature operation.
119 DeltaDiffGenerator::AddSignatureOp(payload.size() - metadata_size,
120 signature_blob_size,
121 &manifest);
122
123 // Updates the payload to include the new manifest.
124 string serialized_manifest;
125 TEST_AND_RETURN_FALSE(manifest.AppendToString(&serialized_manifest));
126 LOG(INFO) << "Updated protobuf size: " << serialized_manifest.size();
127 payload.erase(payload.begin() + kProtobufOffset,
128 payload.begin() + metadata_size);
129 payload.insert(payload.begin() + kProtobufOffset,
130 serialized_manifest.begin(),
131 serialized_manifest.end());
132
133 // Updates the protobuf size.
134 uint64_t size_be = htobe64(serialized_manifest.size());
135 memcpy(&payload[kProtobufSizeOffset], &size_be, sizeof(size_be));
136 LOG(INFO) << "Updated payload size: " << payload.size();
137 out_payload->swap(payload);
138 return true;
139}
140} // namespace {}
141
142bool PayloadSigner::SignHash(const vector<char>& hash,
143 const string& private_key_path,
144 vector<char>* out_signature) {
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700145 LOG(INFO) << "Signing hash with private key: " << private_key_path;
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700146 string sig_path;
147 TEST_AND_RETURN_FALSE(
148 utils::MakeTempFile("/tmp/signature.XXXXXX", &sig_path, NULL));
149 ScopedPathUnlinker sig_path_unlinker(sig_path);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700150
151 string hash_path;
152 TEST_AND_RETURN_FALSE(
153 utils::MakeTempFile("/tmp/hash.XXXXXX", &hash_path, NULL));
154 ScopedPathUnlinker hash_path_unlinker(hash_path);
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700155 // We expect unpadded SHA256 hash coming in
156 TEST_AND_RETURN_FALSE(hash.size() == 32);
157 vector<char> padded_hash(hash);
158 PadRSA2048SHA256Hash(&padded_hash);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700159 TEST_AND_RETURN_FALSE(utils::WriteFile(hash_path.c_str(),
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700160 padded_hash.data(),
161 padded_hash.size()));
Darin Petkovd22cb292010-09-29 10:02:29 -0700162
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700163 // This runs on the server, so it's okay to cop out and call openssl
164 // executable rather than properly use the library
165 vector<string> cmd;
Mike Frysinger2149be42012-03-12 19:23:47 -0400166 base::SplitString("openssl rsautl -raw -sign -inkey x -in x -out x",
Chris Masoned903c3b2011-05-12 15:35:46 -0700167 ' ',
168 &cmd);
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700169 cmd[cmd.size() - 5] = private_key_path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700170 cmd[cmd.size() - 3] = hash_path;
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700171 cmd[cmd.size() - 1] = sig_path;
Darin Petkovd22cb292010-09-29 10:02:29 -0700172
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700173 int return_code = 0;
Darin Petkov85d02b72011-05-17 13:25:51 -0700174 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code, NULL));
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700175 TEST_AND_RETURN_FALSE(return_code == 0);
Darin Petkovd22cb292010-09-29 10:02:29 -0700176
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700177 vector<char> signature;
178 TEST_AND_RETURN_FALSE(utils::ReadFile(sig_path, &signature));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800179 out_signature->swap(signature);
180 return true;
181}
Darin Petkovd22cb292010-09-29 10:02:29 -0700182
Darin Petkov9574f7e2011-01-13 10:48:12 -0800183bool PayloadSigner::SignPayload(const string& unsigned_payload_path,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700184 const vector<string>& private_key_paths,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800185 vector<char>* out_signature_blob) {
186 vector<char> hash_data;
187 TEST_AND_RETURN_FALSE(OmahaHashCalculator::RawHashOfFile(
188 unsigned_payload_path, -1, &hash_data) ==
189 utils::FileSize(unsigned_payload_path));
Darin Petkovd22cb292010-09-29 10:02:29 -0700190
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700191 vector<vector<char> > signatures;
192 for (vector<string>::const_iterator it = private_key_paths.begin(),
193 e = private_key_paths.end(); it != e; ++it) {
194 vector<char> signature;
195 TEST_AND_RETURN_FALSE(SignHash(hash_data, *it, &signature));
196 signatures.push_back(signature);
197 }
198 TEST_AND_RETURN_FALSE(ConvertSignatureToProtobufBlob(signatures,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800199 out_signature_blob));
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700200 return true;
201}
202
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700203bool PayloadSigner::SignatureBlobLength(const vector<string>& private_key_paths,
204 uint64_t* out_length) {
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700205 DCHECK(out_length);
Darin Petkovd22cb292010-09-29 10:02:29 -0700206
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700207 string x_path;
208 TEST_AND_RETURN_FALSE(
209 utils::MakeTempFile("/tmp/signed_data.XXXXXX", &x_path, NULL));
210 ScopedPathUnlinker x_path_unlinker(x_path);
211 TEST_AND_RETURN_FALSE(utils::WriteFile(x_path.c_str(), "x", 1));
212
213 vector<char> sig_blob;
214 TEST_AND_RETURN_FALSE(PayloadSigner::SignPayload(x_path,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700215 private_key_paths,
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700216 &sig_blob));
217 *out_length = sig_blob.size();
218 return true;
219}
220
Darin Petkovd7061ab2010-10-06 14:37:09 -0700221bool PayloadSigner::VerifySignature(const std::vector<char>& signature_blob,
222 const std::string& public_key_path,
223 std::vector<char>* out_hash_data) {
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700224 return VerifySignatureBlob(signature_blob, public_key_path,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700225 kSignatureMessageCurrentVersion, out_hash_data);
226}
227
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700228bool PayloadSigner::VerifySignatureBlob(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700229 const std::vector<char>& signature_blob,
230 const std::string& public_key_path,
231 uint32_t client_version,
232 std::vector<char>* out_hash_data) {
Darin Petkovd7061ab2010-10-06 14:37:09 -0700233 TEST_AND_RETURN_FALSE(!public_key_path.empty());
234
235 Signatures signatures;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700236 LOG(INFO) << "signature size = " << signature_blob.size();
Darin Petkovd7061ab2010-10-06 14:37:09 -0700237 TEST_AND_RETURN_FALSE(signatures.ParseFromArray(&signature_blob[0],
238 signature_blob.size()));
239
240 // Finds a signature that matches the current version.
241 int sig_index = 0;
242 for (; sig_index < signatures.signatures_size(); sig_index++) {
243 const Signatures_Signature& signature = signatures.signatures(sig_index);
244 if (signature.has_version() &&
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700245 signature.version() == client_version) {
Darin Petkovd7061ab2010-10-06 14:37:09 -0700246 break;
247 }
248 }
249 TEST_AND_RETURN_FALSE(sig_index < signatures.signatures_size());
250
251 const Signatures_Signature& signature = signatures.signatures(sig_index);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700252 vector<char> sig_data(signature.data().begin(), signature.data().end());
253
254 return GetRawHashFromSignature(sig_data, public_key_path, out_hash_data);
255}
256
257
258bool PayloadSigner::GetRawHashFromSignature(
259 const std::vector<char>& sig_data,
260 const std::string& public_key_path,
261 std::vector<char>* out_hash_data) {
262 TEST_AND_RETURN_FALSE(!public_key_path.empty());
Darin Petkovd7061ab2010-10-06 14:37:09 -0700263
Darin Petkovb039d502010-12-03 09:08:04 -0800264 // The code below executes the equivalent of:
265 //
266 // openssl rsautl -verify -pubin -inkey |public_key_path|
267 // -in |sig_data| -out |out_hash_data|
Darin Petkovd7061ab2010-10-06 14:37:09 -0700268
Darin Petkovb039d502010-12-03 09:08:04 -0800269 // Loads the public key.
270 FILE* fpubkey = fopen(public_key_path.c_str(), "rb");
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700271 if (!fpubkey) {
272 LOG(ERROR) << "Unable to open public key file: " << public_key_path;
273 return false;
274 }
275
Darin Petkovb039d502010-12-03 09:08:04 -0800276 char dummy_password[] = { ' ', 0 }; // Ensure no password is read from stdin.
277 RSA* rsa = PEM_read_RSA_PUBKEY(fpubkey, NULL, NULL, dummy_password);
278 fclose(fpubkey);
279 TEST_AND_RETURN_FALSE(rsa != NULL);
280 unsigned int keysize = RSA_size(rsa);
281 if (sig_data.size() > 2 * keysize) {
282 LOG(ERROR) << "Signature size is too big for public key size.";
283 RSA_free(rsa);
284 return false;
285 }
Darin Petkovd7061ab2010-10-06 14:37:09 -0700286
Darin Petkovb039d502010-12-03 09:08:04 -0800287 // Decrypts the signature.
288 vector<char> hash_data(keysize);
289 int decrypt_size = RSA_public_decrypt(
290 sig_data.size(),
291 reinterpret_cast<const unsigned char*>(sig_data.data()),
292 reinterpret_cast<unsigned char*>(hash_data.data()),
293 rsa,
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700294 RSA_NO_PADDING);
Darin Petkovb039d502010-12-03 09:08:04 -0800295 RSA_free(rsa);
296 TEST_AND_RETURN_FALSE(decrypt_size > 0 &&
297 decrypt_size <= static_cast<int>(hash_data.size()));
298 hash_data.resize(decrypt_size);
299 out_hash_data->swap(hash_data);
Darin Petkovd7061ab2010-10-06 14:37:09 -0700300 return true;
301}
302
Darin Petkovadb3cef2011-01-13 16:16:08 -0800303bool PayloadSigner::VerifySignedPayload(const std::string& payload_path,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700304 const std::string& public_key_path,
305 uint32_t client_key_check_version) {
Darin Petkovadb3cef2011-01-13 16:16:08 -0800306 vector<char> payload;
307 DeltaArchiveManifest manifest;
308 uint64_t metadata_size;
309 TEST_AND_RETURN_FALSE(LoadPayload(
310 payload_path, &payload, &manifest, &metadata_size));
311 TEST_AND_RETURN_FALSE(manifest.has_signatures_offset() &&
312 manifest.has_signatures_size());
313 CHECK_EQ(payload.size(),
314 metadata_size + manifest.signatures_offset() +
315 manifest.signatures_size());
316 vector<char> signature_blob(
317 payload.begin() + metadata_size + manifest.signatures_offset(),
318 payload.end());
319 vector<char> signed_hash;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700320 TEST_AND_RETURN_FALSE(VerifySignatureBlob(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700321 signature_blob, public_key_path, client_key_check_version, &signed_hash));
Darin Petkovadb3cef2011-01-13 16:16:08 -0800322 TEST_AND_RETURN_FALSE(!signed_hash.empty());
323 vector<char> hash;
324 TEST_AND_RETURN_FALSE(OmahaHashCalculator::RawHashOfBytes(
325 payload.data(), metadata_size + manifest.signatures_offset(), &hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700326 PadRSA2048SHA256Hash(&hash);
Darin Petkovadb3cef2011-01-13 16:16:08 -0800327 TEST_AND_RETURN_FALSE(hash == signed_hash);
328 return true;
329}
330
Darin Petkov9574f7e2011-01-13 10:48:12 -0800331bool PayloadSigner::HashPayloadForSigning(const std::string& payload_path,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700332 const vector<int>& signature_sizes,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800333 vector<char>* out_hash_data) {
334 // TODO(petkov): Reduce memory usage -- the payload is manipulated in memory.
335
336 // Loads the payload and adds the signature op to it.
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700337 vector<vector<char> > signatures;
338 for (vector<int>::const_iterator it = signature_sizes.begin(),
339 e = signature_sizes.end(); it != e; ++it) {
340 vector<char> signature(*it, 0);
341 signatures.push_back(signature);
342 }
Darin Petkov9574f7e2011-01-13 10:48:12 -0800343 vector<char> signature_blob;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700344 TEST_AND_RETURN_FALSE(ConvertSignatureToProtobufBlob(signatures,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800345 &signature_blob));
346 vector<char> payload;
347 TEST_AND_RETURN_FALSE(AddSignatureOpToPayload(payload_path,
348 signature_blob.size(),
349 &payload));
350 // Calculates the hash on the updated payload. Note that the payload includes
351 // the signature op but doesn't include the signature blob at the end.
352 TEST_AND_RETURN_FALSE(OmahaHashCalculator::RawHashOfData(payload,
353 out_hash_data));
354 return true;
355}
356
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700357bool PayloadSigner::AddSignatureToPayload(
358 const string& payload_path,
359 const vector<vector<char> >& signatures,
360 const string& signed_payload_path) {
Darin Petkov9574f7e2011-01-13 10:48:12 -0800361 // TODO(petkov): Reduce memory usage -- the payload is manipulated in memory.
362
363 // Loads the payload and adds the signature op to it.
364 vector<char> signature_blob;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700365 TEST_AND_RETURN_FALSE(ConvertSignatureToProtobufBlob(signatures,
Darin Petkov9574f7e2011-01-13 10:48:12 -0800366 &signature_blob));
367 vector<char> payload;
368 TEST_AND_RETURN_FALSE(AddSignatureOpToPayload(payload_path,
369 signature_blob.size(),
370 &payload));
371 // Appends the signature blob to the end of the payload and writes the new
372 // payload.
373 payload.insert(payload.end(), signature_blob.begin(), signature_blob.end());
374 LOG(INFO) << "Signed payload size: " << payload.size();
375 TEST_AND_RETURN_FALSE(utils::WriteFile(signed_payload_path.c_str(),
376 payload.data(),
377 payload.size()));
378 return true;
379}
380
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700381bool PayloadSigner::PadRSA2048SHA256Hash(std::vector<char>* hash) {
382 TEST_AND_RETURN_FALSE(hash->size() == 32);
383 hash->insert(hash->begin(),
Han Shen2643cb72012-06-26 14:45:33 -0700384 reinterpret_cast<const char*>(kRSA2048SHA256Padding),
385 reinterpret_cast<const char*>(kRSA2048SHA256Padding +
386 sizeof(kRSA2048SHA256Padding)));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700387 TEST_AND_RETURN_FALSE(hash->size() == 256);
388 return true;
389}
390
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700391bool PayloadSigner::GetManifestSignature(const char* manifest,
392 size_t manifest_size,
393 const string& private_key_path,
394 string* out_signature) {
395 // Calculates the hash on the updated payload. Note that the payload includes
396 // the signature op but doesn't include the signature blob at the end.
397 vector<char> manifest_hash;
398 TEST_AND_RETURN_FALSE(OmahaHashCalculator::RawHashOfBytes(manifest,
399 manifest_size,
400 &manifest_hash));
401
402 vector<char> signature;
403 TEST_AND_RETURN_FALSE(SignHash(manifest_hash,
404 private_key_path,
405 &signature));
406
407 TEST_AND_RETURN_FALSE(OmahaHashCalculator::Base64Encode(&signature[0],
408 signature.size(),
409 out_signature));
410 return true;
411}
412
413
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700414} // namespace chromeos_update_engine