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 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 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 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