1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/payload_verifier.h"
18923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
19923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo#include <base/logging.h>
20923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo#include <openssl/pem.h>
21923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
2239910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/hash_calculator.h"
2339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
24923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo#include "update_engine/update_metadata.pb.h"
25923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
26923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymousing std::string;
27923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
28923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymonamespace chromeos_update_engine {
29923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
30923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymonamespace {
31923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
32923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// The following is a standard PKCS1-v1_5 padding for SHA256 signatures, as
33923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// defined in RFC3447. It is prepended to the actual signature (32 bytes) to
34923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// form a sequence of 256 bytes (2048 bits) that is amenable to RSA signing. The
35923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// padded hash will look as follows:
36923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//
37923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//    0x00 0x01 0xff ... 0xff 0x00  ASN1HEADER  SHA256HASH
38923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//   |--------------205-----------||----19----||----32----|
39923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//
40923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// where ASN1HEADER is the ASN.1 description of the signed data. The complete 51
41923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// bytes of actual data (i.e. the ASN.1 header complete with the hash) are
42923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo// packed as follows:
43923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//
44923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//  SEQUENCE(2+49) {
45923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//   SEQUENCE(2+13) {
46923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//    OBJECT(2+9) id-sha256
47923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//    NULL(2+0)
48923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//   }
49923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//   OCTET STRING(2+32) <actual signature bytes...>
50923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo//  }
51f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkoconst uint8_t kRSA2048SHA256Padding[] = {
52923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // PKCS1-v1_5 padding
53923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
62923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0xff, 0xff, 0xff, 0xff, 0x00,
79923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // ASN.1 header
80923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
81923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
82923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  0x00, 0x04, 0x20,
83923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo};
84923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
85923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo}  // namespace
86923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
873f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool PayloadVerifier::VerifySignature(const brillo::Blob& signature_blob,
88f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                                      const string& public_key_path,
893f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko                                      const brillo::Blob& hash_data) {
90923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  TEST_AND_RETURN_FALSE(!public_key_path.empty());
91923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
92923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  Signatures signatures;
93b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  LOG(INFO) << "signature blob size = " <<  signature_blob.size();
94f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  TEST_AND_RETURN_FALSE(signatures.ParseFromArray(signature_blob.data(),
95923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo                                                  signature_blob.size()));
96923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
97b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  if (!signatures.signatures_size()) {
98b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    LOG(ERROR) << "No signatures stored in the blob.";
99b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    return false;
100923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  }
101923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
1023f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  std::vector<brillo::Blob> tested_hashes;
103b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  // Tries every signature in the signature blob.
104b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  for (int i = 0; i < signatures.signatures_size(); i++) {
105b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    const Signatures_Signature& signature = signatures.signatures(i);
1063f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    brillo::Blob sig_data(signature.data().begin(), signature.data().end());
1073f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    brillo::Blob sig_hash_data;
108b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    if (!GetRawHashFromSignature(sig_data, public_key_path, &sig_hash_data))
109b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo      continue;
110b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo
111b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    if (hash_data == sig_hash_data) {
112b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo      LOG(INFO) << "Verified correct signature " << i + 1 << " out of "
113b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo                << signatures.signatures_size() << " signatures.";
114b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo      return true;
115b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    }
116b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    tested_hashes.push_back(sig_hash_data);
117b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  }
118b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  LOG(ERROR) << "None of the " << signatures.signatures_size()
119b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo             << " signatures is correct. Expected:";
120b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  utils::HexDumpVector(hash_data);
121b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  LOG(ERROR) << "But found decrypted hashes:";
122b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  for (const auto& sig_hash_data : tested_hashes) {
123b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo    utils::HexDumpVector(sig_hash_data);
124b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  }
125b552a68af39efa42d462a9272d3dc47eb39c6db8Alex Deymo  return false;
126923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo}
127923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
128923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
129923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymobool PayloadVerifier::GetRawHashFromSignature(
1303f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    const brillo::Blob& sig_data,
131f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo    const string& public_key_path,
1323f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    brillo::Blob* out_hash_data) {
133923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  TEST_AND_RETURN_FALSE(!public_key_path.empty());
134923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
135923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // The code below executes the equivalent of:
136923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  //
137923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // openssl rsautl -verify -pubin -inkey |public_key_path|
138923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  //   -in |sig_data| -out |out_hash_data|
139923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
140923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // Loads the public key.
141923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  FILE* fpubkey = fopen(public_key_path.c_str(), "rb");
142923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  if (!fpubkey) {
143923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo    LOG(ERROR) << "Unable to open public key file: " << public_key_path;
144923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo    return false;
145923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  }
146923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
147923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  char dummy_password[] = { ' ', 0 };  // Ensure no password is read from stdin.
14888b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  RSA* rsa = PEM_read_RSA_PUBKEY(fpubkey, nullptr, nullptr, dummy_password);
149923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  fclose(fpubkey);
15088b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  TEST_AND_RETURN_FALSE(rsa != nullptr);
151923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  unsigned int keysize = RSA_size(rsa);
152923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  if (sig_data.size() > 2 * keysize) {
153923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo    LOG(ERROR) << "Signature size is too big for public key size.";
154923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo    RSA_free(rsa);
155923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo    return false;
156923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  }
157923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
158923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  // Decrypts the signature.
1593f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob hash_data(keysize);
160f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  int decrypt_size = RSA_public_decrypt(sig_data.size(),
161f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                                        sig_data.data(),
162f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                                        hash_data.data(),
163f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                                        rsa,
164f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                                        RSA_NO_PADDING);
165923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  RSA_free(rsa);
166923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  TEST_AND_RETURN_FALSE(decrypt_size > 0 &&
167923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo                        decrypt_size <= static_cast<int>(hash_data.size()));
168923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  hash_data.resize(decrypt_size);
169923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  out_hash_data->swap(hash_data);
170923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  return true;
171923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo}
172923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
1733f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkobool PayloadVerifier::PadRSA2048SHA256Hash(brillo::Blob* hash) {
174923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  TEST_AND_RETURN_FALSE(hash->size() == 32);
175923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  hash->insert(hash->begin(),
176923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo               reinterpret_cast<const char*>(kRSA2048SHA256Padding),
177923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo               reinterpret_cast<const char*>(kRSA2048SHA256Padding +
178923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo                                             sizeof(kRSA2048SHA256Padding)));
179923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  TEST_AND_RETURN_FALSE(hash->size() == 256);
180923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo  return true;
181923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo}
182923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo
183923d8faa6b341ce5e16a760749e98cc6703ca2fdAlex Deymo}  // namespace chromeos_update_engine
184