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
26using std::string;
27
28namespace chromeos_update_engine {
29
30namespace {
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//  }
51const 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
87bool 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
129bool 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
173bool 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