1 //
2 // Copyright (C) 2014 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 //
16
17 #include "update_engine/payload_consumer/payload_verifier.h"
18
19 #include <base/logging.h>
20 #include <openssl/pem.h>
21
22 #include "update_engine/common/hash_calculator.h"
23 #include "update_engine/common/utils.h"
24 #include "update_engine/update_metadata.pb.h"
25
26 using std::string;
27
28 namespace chromeos_update_engine {
29
30 namespace {
31
32 // The following is a standard PKCS1-v1_5 padding for SHA256 signatures, as
33 // defined in RFC3447. It is prepended to the actual signature (32 bytes) to
34 // form a sequence of 256 bytes (2048 bits) that is amenable to RSA signing. The
35 // padded hash will look as follows:
36 //
37 // 0x00 0x01 0xff ... 0xff 0x00 ASN1HEADER SHA256HASH
38 // |--------------205-----------||----19----||----32----|
39 //
40 // where ASN1HEADER is the ASN.1 description of the signed data. The complete 51
41 // bytes of actual data (i.e. the ASN.1 header complete with the hash) are
42 // packed as follows:
43 //
44 // SEQUENCE(2+49) {
45 // SEQUENCE(2+13) {
46 // OBJECT(2+9) id-sha256
47 // NULL(2+0)
48 // }
49 // OCTET STRING(2+32) <actual signature bytes...>
50 // }
51 const uint8_t kRSA2048SHA256Padding[] = {
52 // PKCS1-v1_5 padding
53 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
62 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78 0xff, 0xff, 0xff, 0xff, 0x00,
79 // ASN.1 header
80 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
81 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
82 0x00, 0x04, 0x20,
83 };
84
85 } // namespace
86
VerifySignature(const brillo::Blob & signature_blob,const string & public_key_path,const brillo::Blob & hash_data)87 bool PayloadVerifier::VerifySignature(const brillo::Blob& signature_blob,
88 const string& public_key_path,
89 const brillo::Blob& hash_data) {
90 TEST_AND_RETURN_FALSE(!public_key_path.empty());
91
92 Signatures signatures;
93 LOG(INFO) << "signature blob size = " << signature_blob.size();
94 TEST_AND_RETURN_FALSE(signatures.ParseFromArray(signature_blob.data(),
95 signature_blob.size()));
96
97 if (!signatures.signatures_size()) {
98 LOG(ERROR) << "No signatures stored in the blob.";
99 return false;
100 }
101
102 std::vector<brillo::Blob> tested_hashes;
103 // Tries every signature in the signature blob.
104 for (int i = 0; i < signatures.signatures_size(); i++) {
105 const Signatures_Signature& signature = signatures.signatures(i);
106 brillo::Blob sig_data(signature.data().begin(), signature.data().end());
107 brillo::Blob sig_hash_data;
108 if (!GetRawHashFromSignature(sig_data, public_key_path, &sig_hash_data))
109 continue;
110
111 if (hash_data == sig_hash_data) {
112 LOG(INFO) << "Verified correct signature " << i + 1 << " out of "
113 << signatures.signatures_size() << " signatures.";
114 return true;
115 }
116 tested_hashes.push_back(sig_hash_data);
117 }
118 LOG(ERROR) << "None of the " << signatures.signatures_size()
119 << " signatures is correct. Expected:";
120 utils::HexDumpVector(hash_data);
121 LOG(ERROR) << "But found decrypted hashes:";
122 for (const auto& sig_hash_data : tested_hashes) {
123 utils::HexDumpVector(sig_hash_data);
124 }
125 return false;
126 }
127
128
GetRawHashFromSignature(const brillo::Blob & sig_data,const string & public_key_path,brillo::Blob * out_hash_data)129 bool PayloadVerifier::GetRawHashFromSignature(
130 const brillo::Blob& sig_data,
131 const string& public_key_path,
132 brillo::Blob* out_hash_data) {
133 TEST_AND_RETURN_FALSE(!public_key_path.empty());
134
135 // The code below executes the equivalent of:
136 //
137 // openssl rsautl -verify -pubin -inkey |public_key_path|
138 // -in |sig_data| -out |out_hash_data|
139
140 // Loads the public key.
141 FILE* fpubkey = fopen(public_key_path.c_str(), "rb");
142 if (!fpubkey) {
143 LOG(ERROR) << "Unable to open public key file: " << public_key_path;
144 return false;
145 }
146
147 char dummy_password[] = { ' ', 0 }; // Ensure no password is read from stdin.
148 RSA* rsa = PEM_read_RSA_PUBKEY(fpubkey, nullptr, nullptr, dummy_password);
149 fclose(fpubkey);
150 TEST_AND_RETURN_FALSE(rsa != nullptr);
151 unsigned int keysize = RSA_size(rsa);
152 if (sig_data.size() > 2 * keysize) {
153 LOG(ERROR) << "Signature size is too big for public key size.";
154 RSA_free(rsa);
155 return false;
156 }
157
158 // Decrypts the signature.
159 brillo::Blob hash_data(keysize);
160 int decrypt_size = RSA_public_decrypt(sig_data.size(),
161 sig_data.data(),
162 hash_data.data(),
163 rsa,
164 RSA_NO_PADDING);
165 RSA_free(rsa);
166 TEST_AND_RETURN_FALSE(decrypt_size > 0 &&
167 decrypt_size <= static_cast<int>(hash_data.size()));
168 hash_data.resize(decrypt_size);
169 out_hash_data->swap(hash_data);
170 return true;
171 }
172
PadRSA2048SHA256Hash(brillo::Blob * hash)173 bool PayloadVerifier::PadRSA2048SHA256Hash(brillo::Blob* hash) {
174 TEST_AND_RETURN_FALSE(hash->size() == 32);
175 hash->insert(hash->begin(),
176 reinterpret_cast<const char*>(kRSA2048SHA256Padding),
177 reinterpret_cast<const char*>(kRSA2048SHA256Padding +
178 sizeof(kRSA2048SHA256Padding)));
179 TEST_AND_RETURN_FALSE(hash->size() == 256);
180 return true;
181 }
182
183 } // namespace chromeos_update_engine
184