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