blob: ebdd2806274fa3764a7b1d28850bfb554bbbc5c3 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2010 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Andrew de los Reyes0c440052010-08-20 11:25:54 -070016
Alex Deymo923d8fa2014-07-15 17:58:51 -070017#include "update_engine/payload_generator/payload_signer.h"
18
Andrew de los Reyes0c440052010-08-20 11:25:54 -070019#include <string>
20#include <vector>
Alex Deymo923d8fa2014-07-15 17:58:51 -070021
22#include <base/logging.h>
Andrew de los Reyes0c440052010-08-20 11:25:54 -070023#include <gtest/gtest.h>
Alex Deymo923d8fa2014-07-15 17:58:51 -070024
Alex Deymo39910dc2015-11-09 17:04:30 -080025#include "update_engine/common/hash_calculator.h"
26#include "update_engine/common/utils.h"
27#include "update_engine/payload_consumer/payload_constants.h"
28#include "update_engine/payload_consumer/payload_verifier.h"
Sen Jiangaef1c6f2015-10-07 10:05:32 -070029#include "update_engine/payload_generator/payload_file.h"
Andrew de los Reyes0c440052010-08-20 11:25:54 -070030#include "update_engine/update_metadata.pb.h"
Andrew de los Reyes0c440052010-08-20 11:25:54 -070031
32using std::string;
33using std::vector;
34
35// Note: the test key was generated with the following command:
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070036// openssl genrsa -out unittest_key.pem 2048
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070037// The public-key version is created by the build system.
Andrew de los Reyes0c440052010-08-20 11:25:54 -070038
Andrew de los Reyes0c440052010-08-20 11:25:54 -070039namespace chromeos_update_engine {
40
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070041const char* kUnittestPrivateKeyPath = "unittest_key.pem";
Darin Petkovd7061ab2010-10-06 14:37:09 -070042const char* kUnittestPublicKeyPath = "unittest_key.pub.pem";
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070043const char* kUnittestPrivateKey2Path = "unittest_key2.pem";
44const char* kUnittestPublicKey2Path = "unittest_key2.pub.pem";
Darin Petkovd7061ab2010-10-06 14:37:09 -070045
46// Some data and its corresponding hash and signature:
47const char kDataToSign[] = "This is some data to sign.";
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070048
49// Generated by:
50// echo -n 'This is some data to sign.' | openssl dgst -sha256 -binary |
51// hexdump -v -e '" " 8/1 "0x%02x, " "\n"'
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080052const uint8_t kDataHash[] = {
Darin Petkovd7061ab2010-10-06 14:37:09 -070053 0x7a, 0x07, 0xa6, 0x44, 0x08, 0x86, 0x20, 0xa6,
54 0xc1, 0xf8, 0xd9, 0x02, 0x05, 0x63, 0x0d, 0xb7,
55 0xfc, 0x2b, 0xa0, 0xa9, 0x7c, 0x9d, 0x1d, 0x8c,
56 0x01, 0xf5, 0x78, 0x6d, 0xc5, 0x11, 0xb4, 0x06
57};
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070058
59// Generated with openssl 1.0, which at the time of this writing, you need
60// to download and install yourself. Here's my command:
61// echo -n 'This is some data to sign.' | openssl dgst -sha256 -binary |
62// ~/local/bin/openssl pkeyutl -sign -inkey unittest_key.pem -pkeyopt
63// digest:sha256 | hexdump -v -e '" " 8/1 "0x%02x, " "\n"'
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080064const uint8_t kDataSignature[] = {
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -070065 0x9f, 0x86, 0x25, 0x8b, 0xf3, 0xcc, 0xe3, 0x95,
66 0x5f, 0x45, 0x83, 0xb2, 0x66, 0xf0, 0x2a, 0xcf,
67 0xb7, 0xaa, 0x52, 0x25, 0x7a, 0xdd, 0x9d, 0x65,
68 0xe5, 0xd6, 0x02, 0x4b, 0x37, 0x99, 0x53, 0x06,
69 0xc2, 0xc9, 0x37, 0x36, 0x25, 0x62, 0x09, 0x4f,
70 0x6b, 0x22, 0xf8, 0xb3, 0x89, 0x14, 0x98, 0x1a,
71 0xbc, 0x30, 0x90, 0x4a, 0x43, 0xf5, 0xea, 0x2e,
72 0xf0, 0xa4, 0xba, 0xc3, 0xa7, 0xa3, 0x44, 0x70,
73 0xd6, 0xc4, 0x89, 0xd8, 0x45, 0x71, 0xbb, 0xee,
74 0x59, 0x87, 0x3d, 0xd5, 0xe5, 0x40, 0x22, 0x3d,
75 0x73, 0x7e, 0x2a, 0x58, 0x93, 0x8e, 0xcb, 0x9c,
76 0xf2, 0xbb, 0x4a, 0xc9, 0xd2, 0x2c, 0x52, 0x42,
77 0xb0, 0xd1, 0x13, 0x22, 0xa4, 0x78, 0xc7, 0xc6,
78 0x3e, 0xf1, 0xdc, 0x4c, 0x7b, 0x2d, 0x40, 0xda,
79 0x58, 0xac, 0x4a, 0x11, 0x96, 0x3d, 0xa0, 0x01,
80 0xf6, 0x96, 0x74, 0xf6, 0x6c, 0x0c, 0x49, 0x69,
81 0x4e, 0xc1, 0x7e, 0x9f, 0x2a, 0x42, 0xdd, 0x15,
82 0x6b, 0x37, 0x2e, 0x3a, 0xa7, 0xa7, 0x6d, 0x91,
83 0x13, 0xe8, 0x59, 0xde, 0xfe, 0x99, 0x07, 0xd9,
84 0x34, 0x0f, 0x17, 0xb3, 0x05, 0x4c, 0xd2, 0xc6,
85 0x82, 0xb7, 0x38, 0x36, 0x63, 0x1d, 0x9e, 0x21,
86 0xa6, 0x32, 0xef, 0xf1, 0x65, 0xe6, 0xed, 0x95,
87 0x25, 0x9b, 0x61, 0xe0, 0xba, 0x86, 0xa1, 0x7f,
88 0xf8, 0xa5, 0x4a, 0x32, 0x1f, 0x15, 0x20, 0x8a,
89 0x41, 0xc5, 0xb0, 0xd9, 0x4a, 0xda, 0x85, 0xf3,
90 0xdc, 0xa0, 0x98, 0x5d, 0x1d, 0x18, 0x9d, 0x2e,
91 0x42, 0xea, 0x69, 0x13, 0x74, 0x3c, 0x74, 0xf7,
92 0x6d, 0x43, 0xb0, 0x63, 0x90, 0xdb, 0x04, 0xd5,
93 0x05, 0xc9, 0x73, 0x1f, 0x6c, 0xd6, 0xfa, 0x46,
94 0x4e, 0x0f, 0x33, 0x58, 0x5b, 0x0d, 0x1b, 0x55,
95 0x39, 0xb9, 0x0f, 0x43, 0x37, 0xc0, 0x06, 0x0c,
96 0x29, 0x93, 0x43, 0xc7, 0x43, 0xb9, 0xab, 0x7d
Darin Petkovd7061ab2010-10-06 14:37:09 -070097};
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070098
Darin Petkovd7061ab2010-10-06 14:37:09 -070099namespace {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700100void SignSampleData(brillo::Blob* out_signature_blob,
Alex Deymob552a682015-09-30 09:36:49 -0700101 const vector<string>& private_keys) {
Sen Jiang720df3e2015-10-01 13:10:44 -0700102 brillo::Blob data_blob(std::begin(kDataToSign),
103 std::begin(kDataToSign) + strlen(kDataToSign));
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700104 uint64_t length = 0;
Alex Deymob552a682015-09-30 09:36:49 -0700105 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(private_keys, &length));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800106 EXPECT_GT(length, 0U);
Sen Jiang720df3e2015-10-01 13:10:44 -0700107 brillo::Blob hash_blob;
Alex Deymo39910dc2015-11-09 17:04:30 -0800108 EXPECT_TRUE(HashCalculator::RawHashOfBytes(data_blob.data(),
109 data_blob.size(),
110 &hash_blob));
Sen Jiang720df3e2015-10-01 13:10:44 -0700111 EXPECT_TRUE(PayloadSigner::SignHashWithKeys(
112 hash_blob,
Alex Deymob552a682015-09-30 09:36:49 -0700113 private_keys,
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700114 out_signature_blob));
Darin Petkovd7061ab2010-10-06 14:37:09 -0700115 EXPECT_EQ(length, out_signature_blob->size());
116}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700117} // namespace
Darin Petkovd7061ab2010-10-06 14:37:09 -0700118
Alex Deymob552a682015-09-30 09:36:49 -0700119class PayloadSignerTest : public ::testing::Test {
120 protected:
121 void SetUp() override {
122 PayloadVerifier::PadRSA2048SHA256Hash(&padded_hash_data_);
123 }
124
Sen Jiangaef1c6f2015-10-07 10:05:32 -0700125 void DoWriteAndLoadPayloadTest(const PayloadGenerationConfig& config) {
126 PayloadFile payload;
127 payload.Init(config);
128 string payload_path;
129 EXPECT_TRUE(utils::MakeTempFile("payload.XXXXXX", &payload_path, nullptr));
130 ScopedPathUnlinker payload_path_unlinker(payload_path);
131 uint64_t metadata_size;
132 EXPECT_TRUE(
133 payload.WritePayload(payload_path, "/dev/null", "", &metadata_size));
Alex Deymo98e691c2016-02-04 21:05:45 -0800134 brillo::Blob payload_metadata_blob;
Sen Jiangaef1c6f2015-10-07 10:05:32 -0700135 DeltaArchiveManifest manifest;
136 uint64_t load_metadata_size, load_major_version;
Alex Deymo98e691c2016-02-04 21:05:45 -0800137 EXPECT_TRUE(PayloadSigner::LoadPayloadMetadata(payload_path,
138 &payload_metadata_blob,
139 &manifest,
140 &load_major_version,
141 &load_metadata_size,
142 nullptr));
143 EXPECT_EQ(metadata_size, payload_metadata_blob.size());
Sen Jiangaef1c6f2015-10-07 10:05:32 -0700144 EXPECT_EQ(config.major_version, load_major_version);
145 EXPECT_EQ(metadata_size, load_metadata_size);
146 }
147
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700148 brillo::Blob padded_hash_data_{std::begin(kDataHash), std::end(kDataHash)};
Alex Deymob552a682015-09-30 09:36:49 -0700149};
150
Sen Jiangaef1c6f2015-10-07 10:05:32 -0700151TEST_F(PayloadSignerTest, LoadPayloadV1Test) {
152 PayloadGenerationConfig config;
153 config.major_version = kChromeOSMajorPayloadVersion;
154 DoWriteAndLoadPayloadTest(config);
155}
156
157TEST_F(PayloadSignerTest, LoadPayloadV2Test) {
158 PayloadGenerationConfig config;
159 config.major_version = kBrilloMajorPayloadVersion;
160 DoWriteAndLoadPayloadTest(config);
161}
162
Alex Deymob552a682015-09-30 09:36:49 -0700163TEST_F(PayloadSignerTest, SignSimpleTextTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700164 brillo::Blob signature_blob;
Alex Deymob552a682015-09-30 09:36:49 -0700165 SignSampleData(&signature_blob, {kUnittestPrivateKeyPath});
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700166
167 // Check the signature itself
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700168 Signatures signatures;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800169 EXPECT_TRUE(signatures.ParseFromArray(signature_blob.data(),
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700170 signature_blob.size()));
171 EXPECT_EQ(1, signatures.signatures_size());
172 const Signatures_Signature& signature = signatures.signatures(0);
Alex Deymo80f70ff2016-02-10 16:08:11 -0800173 EXPECT_EQ(1U, signature.version());
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700174 const string sig_data = signature.data();
Darin Petkovd7061ab2010-10-06 14:37:09 -0700175 ASSERT_EQ(arraysize(kDataSignature), sig_data.size());
176 for (size_t i = 0; i < arraysize(kDataSignature); i++) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800177 EXPECT_EQ(kDataSignature[i], static_cast<uint8_t>(sig_data[i]));
Darin Petkovd7061ab2010-10-06 14:37:09 -0700178 }
179}
180
Alex Deymob552a682015-09-30 09:36:49 -0700181TEST_F(PayloadSignerTest, VerifyAllSignatureTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700182 brillo::Blob signature_blob;
Alex Deymob552a682015-09-30 09:36:49 -0700183 SignSampleData(&signature_blob,
184 {kUnittestPrivateKeyPath, kUnittestPrivateKey2Path});
Darin Petkovd7061ab2010-10-06 14:37:09 -0700185
Alex Deymob552a682015-09-30 09:36:49 -0700186 // Either public key should pass the verification.
Alex Deymo923d8fa2014-07-15 17:58:51 -0700187 EXPECT_TRUE(PayloadVerifier::VerifySignature(signature_blob,
Alex Deymob552a682015-09-30 09:36:49 -0700188 kUnittestPublicKeyPath,
189 padded_hash_data_));
190 EXPECT_TRUE(PayloadVerifier::VerifySignature(signature_blob,
191 kUnittestPublicKey2Path,
192 padded_hash_data_));
193}
194
195TEST_F(PayloadSignerTest, VerifySignatureTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700196 brillo::Blob signature_blob;
Alex Deymob552a682015-09-30 09:36:49 -0700197 SignSampleData(&signature_blob, {kUnittestPrivateKeyPath});
198
199 EXPECT_TRUE(PayloadVerifier::VerifySignature(signature_blob,
200 kUnittestPublicKeyPath,
201 padded_hash_data_));
202 // Passing the invalid key should fail the verification.
203 EXPECT_FALSE(PayloadVerifier::VerifySignature(signature_blob,
204 kUnittestPublicKey2Path,
205 padded_hash_data_));
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700206}
207
Sen Jiang644f6182015-10-06 16:45:57 -0700208TEST_F(PayloadSignerTest, SkipMetadataSignatureTest) {
209 string payload_path;
210 EXPECT_TRUE(utils::MakeTempFile("payload.XXXXXX", &payload_path, nullptr));
211 ScopedPathUnlinker payload_path_unlinker(payload_path);
212
213 PayloadGenerationConfig config;
214 config.major_version = kBrilloMajorPayloadVersion;
215 PayloadFile payload;
216 EXPECT_TRUE(payload.Init(config));
217 uint64_t metadata_size;
218 EXPECT_TRUE(
219 payload.WritePayload(payload_path, "/dev/null", "", &metadata_size));
220 const vector<int> sizes = {256};
221 brillo::Blob unsigned_payload_hash, unsigned_metadata_hash;
222 EXPECT_TRUE(PayloadSigner::HashPayloadForSigning(
223 payload_path, sizes, &unsigned_payload_hash, &unsigned_metadata_hash));
224 EXPECT_TRUE(payload.WritePayload(
225 payload_path, "/dev/null", kUnittestPrivateKeyPath, &metadata_size));
226 brillo::Blob signed_payload_hash, signed_metadata_hash;
227 EXPECT_TRUE(PayloadSigner::HashPayloadForSigning(
228 payload_path, sizes, &signed_payload_hash, &signed_metadata_hash));
229 EXPECT_EQ(unsigned_payload_hash, signed_payload_hash);
230 EXPECT_EQ(unsigned_metadata_hash, signed_metadata_hash);
231}
232
233TEST_F(PayloadSignerTest, VerifySignedPayloadTest) {
234 string payload_path;
235 EXPECT_TRUE(utils::MakeTempFile("payload.XXXXXX", &payload_path, nullptr));
236 ScopedPathUnlinker payload_path_unlinker(payload_path);
237
238 PayloadGenerationConfig config;
239 config.major_version = kBrilloMajorPayloadVersion;
240 PayloadFile payload;
241 EXPECT_TRUE(payload.Init(config));
242 uint64_t metadata_size;
243 EXPECT_TRUE(payload.WritePayload(
244 payload_path, "/dev/null", kUnittestPrivateKeyPath, &metadata_size));
245 EXPECT_TRUE(PayloadSigner::VerifySignedPayload(payload_path,
246 kUnittestPublicKeyPath));
247}
248
Andrew de los Reyes0c440052010-08-20 11:25:54 -0700249} // namespace chromeos_update_engine