1 //
2 // Copyright (C) 2015 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 "attestation/common/crypto_utility_impl.h"
18
19 #include <limits>
20 #include <string>
21
22 #include <arpa/inet.h>
23 #include <base/sha1.h>
24 #include <base/stl_util.h>
25 #include <crypto/scoped_openssl_types.h>
26 #include <crypto/secure_util.h>
27 #include <crypto/sha2.h>
28 #include <openssl/bio.h>
29 #include <openssl/err.h>
30 #include <openssl/evp.h>
31 #include <openssl/hmac.h>
32 #include <openssl/rand.h>
33 #include <openssl/rsa.h>
34 #include <openssl/sha.h>
35 #include <openssl/x509.h>
36
37 namespace {
38
39 const size_t kAesKeySize = 32;
40 const size_t kAesBlockSize = 16;
41
GetOpenSSLError()42 std::string GetOpenSSLError() {
43 BIO* bio = BIO_new(BIO_s_mem());
44 ERR_print_errors(bio);
45 char* data = nullptr;
46 int data_len = BIO_get_mem_data(bio, &data);
47 std::string error_string(data, data_len);
48 BIO_free(bio);
49 return error_string;
50 }
51
StringAsOpenSSLBuffer(std::string * s)52 unsigned char* StringAsOpenSSLBuffer(std::string* s) {
53 return reinterpret_cast<unsigned char*>(string_as_array(s));
54 }
55
56 } // namespace
57
58 namespace attestation {
59
CryptoUtilityImpl(TpmUtility * tpm_utility)60 CryptoUtilityImpl::CryptoUtilityImpl(TpmUtility* tpm_utility)
61 : tpm_utility_(tpm_utility) {
62 OpenSSL_add_all_algorithms();
63 ERR_load_crypto_strings();
64 }
65
~CryptoUtilityImpl()66 CryptoUtilityImpl::~CryptoUtilityImpl() {
67 EVP_cleanup();
68 ERR_free_strings();
69 }
70
GetRandom(size_t num_bytes,std::string * random_data) const71 bool CryptoUtilityImpl::GetRandom(size_t num_bytes,
72 std::string* random_data) const {
73 // OpenSSL takes a signed integer.
74 if (num_bytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
75 return false;
76 }
77 random_data->resize(num_bytes);
78 unsigned char* buffer = StringAsOpenSSLBuffer(random_data);
79 return (RAND_bytes(buffer, num_bytes) == 1);
80 }
81
CreateSealedKey(std::string * aes_key,std::string * sealed_key)82 bool CryptoUtilityImpl::CreateSealedKey(std::string* aes_key,
83 std::string* sealed_key) {
84 if (!GetRandom(kAesKeySize, aes_key)) {
85 LOG(ERROR) << __func__ << ": GetRandom failed.";
86 return false;
87 }
88 if (!tpm_utility_->SealToPCR0(*aes_key, sealed_key)) {
89 LOG(ERROR) << __func__ << ": Failed to seal cipher key.";
90 return false;
91 }
92 return true;
93 }
94
EncryptData(const std::string & data,const std::string & aes_key,const std::string & sealed_key,std::string * encrypted_data)95 bool CryptoUtilityImpl::EncryptData(const std::string& data,
96 const std::string& aes_key,
97 const std::string& sealed_key,
98 std::string* encrypted_data) {
99 std::string iv;
100 if (!GetRandom(kAesBlockSize, &iv)) {
101 LOG(ERROR) << __func__ << ": GetRandom failed.";
102 return false;
103 }
104 std::string raw_encrypted_data;
105 if (!AesEncrypt(data, aes_key, iv, &raw_encrypted_data)) {
106 LOG(ERROR) << __func__ << ": AES encryption failed.";
107 return false;
108 }
109 EncryptedData encrypted_pb;
110 encrypted_pb.set_wrapped_key(sealed_key);
111 encrypted_pb.set_iv(iv);
112 encrypted_pb.set_encrypted_data(raw_encrypted_data);
113 encrypted_pb.set_mac(HmacSha512(iv + raw_encrypted_data, aes_key));
114 if (!encrypted_pb.SerializeToString(encrypted_data)) {
115 LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
116 return false;
117 }
118 return true;
119 }
120
UnsealKey(const std::string & encrypted_data,std::string * aes_key,std::string * sealed_key)121 bool CryptoUtilityImpl::UnsealKey(const std::string& encrypted_data,
122 std::string* aes_key,
123 std::string* sealed_key) {
124 EncryptedData encrypted_pb;
125 if (!encrypted_pb.ParseFromString(encrypted_data)) {
126 LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
127 return false;
128 }
129 *sealed_key = encrypted_pb.wrapped_key();
130 if (!tpm_utility_->Unseal(*sealed_key, aes_key)) {
131 LOG(ERROR) << __func__ << ": Cannot unseal aes key.";
132 return false;
133 }
134 return true;
135 }
136
DecryptData(const std::string & encrypted_data,const std::string & aes_key,std::string * data)137 bool CryptoUtilityImpl::DecryptData(const std::string& encrypted_data,
138 const std::string& aes_key,
139 std::string* data) {
140 EncryptedData encrypted_pb;
141 if (!encrypted_pb.ParseFromString(encrypted_data)) {
142 LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
143 return false;
144 }
145 std::string mac = HmacSha512(
146 encrypted_pb.iv() + encrypted_pb.encrypted_data(),
147 aes_key);
148 if (mac.length() != encrypted_pb.mac().length()) {
149 LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
150 return false;
151 }
152 if (!crypto::SecureMemEqual(mac.data(), encrypted_pb.mac().data(),
153 mac.length())) {
154 LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
155 return false;
156 }
157 if (!AesDecrypt(encrypted_pb.encrypted_data(), aes_key, encrypted_pb.iv(),
158 data)) {
159 LOG(ERROR) << __func__ << ": AES decryption failed.";
160 return false;
161 }
162 return true;
163 }
164
GetRSASubjectPublicKeyInfo(const std::string & public_key,std::string * public_key_info)165 bool CryptoUtilityImpl::GetRSASubjectPublicKeyInfo(
166 const std::string& public_key,
167 std::string* public_key_info) {
168 auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
169 crypto::ScopedRSA rsa(d2i_RSAPublicKey(nullptr, &asn1_ptr,
170 public_key.size()));
171 if (!rsa.get()) {
172 LOG(ERROR) << __func__ << ": Failed to decode public key: "
173 << GetOpenSSLError();
174 return false;
175 }
176 unsigned char* buffer = nullptr;
177 int length = i2d_RSA_PUBKEY(rsa.get(), &buffer);
178 if (length <= 0) {
179 LOG(ERROR) << __func__ << ": Failed to encode public key: "
180 << GetOpenSSLError();
181 return false;
182 }
183 crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
184 public_key_info->assign(reinterpret_cast<char*>(buffer), length);
185 return true;
186 }
187
GetRSAPublicKey(const std::string & public_key_info,std::string * public_key)188 bool CryptoUtilityImpl::GetRSAPublicKey(const std::string& public_key_info,
189 std::string* public_key) {
190 auto asn1_ptr = reinterpret_cast<const unsigned char*>(
191 public_key_info.data());
192 crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr,
193 public_key_info.size()));
194 if (!rsa.get()) {
195 LOG(ERROR) << __func__ << ": Failed to decode public key: "
196 << GetOpenSSLError();
197 return false;
198 }
199 unsigned char* buffer = NULL;
200 int length = i2d_RSAPublicKey(rsa.get(), &buffer);
201 if (length <= 0) {
202 LOG(ERROR) << __func__ << ": Failed to encode public key: "
203 << GetOpenSSLError();
204 return false;
205 }
206 crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
207 public_key->assign(reinterpret_cast<char*>(buffer), length);
208 return true;
209 }
210
EncryptIdentityCredential(const std::string & credential,const std::string & ek_public_key_info,const std::string & aik_public_key,EncryptedIdentityCredential * encrypted)211 bool CryptoUtilityImpl::EncryptIdentityCredential(
212 const std::string& credential,
213 const std::string& ek_public_key_info,
214 const std::string& aik_public_key,
215 EncryptedIdentityCredential* encrypted) {
216 const char kAlgAES256 = 9; // This comes from TPM_ALG_AES256.
217 const char kEncModeCBC = 2; // This comes from TPM_SYM_MODE_CBC.
218 const char kAsymContentHeader[] =
219 {0, 0, 0, kAlgAES256, 0, kEncModeCBC, 0, kAesKeySize};
220 const char kSymContentHeader[12] = {};
221
222 // Generate an AES key and encrypt the credential.
223 std::string aes_key;
224 if (!GetRandom(kAesKeySize, &aes_key)) {
225 LOG(ERROR) << __func__ << ": GetRandom failed.";
226 return false;
227 }
228 std::string encrypted_credential;
229 if (!TssCompatibleEncrypt(credential, aes_key, &encrypted_credential)) {
230 LOG(ERROR) << __func__ << ": Failed to encrypt credential.";
231 return false;
232 }
233
234 // Construct a TPM_ASYM_CA_CONTENTS structure.
235 std::string asym_header(std::begin(kAsymContentHeader),
236 std::end(kAsymContentHeader));
237 std::string asym_content = asym_header + aes_key +
238 base::SHA1HashString(aik_public_key);
239
240 // Encrypt the TPM_ASYM_CA_CONTENTS with the EK public key.
241 auto asn1_ptr = reinterpret_cast<const unsigned char*>(
242 ek_public_key_info.data());
243 crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr,
244 ek_public_key_info.size()));
245 if (!rsa.get()) {
246 LOG(ERROR) << __func__ << ": Failed to decode EK public key: "
247 << GetOpenSSLError();
248 return false;
249 }
250 std::string encrypted_asym_content;
251 if (!TpmCompatibleOAEPEncrypt(asym_content, rsa.get(),
252 &encrypted_asym_content)) {
253 LOG(ERROR) << __func__ << ": Failed to encrypt with EK public key.";
254 return false;
255 }
256
257 // Construct a TPM_SYM_CA_ATTESTATION structure.
258 uint32_t length = htonl(encrypted_credential.size());
259 auto length_bytes = reinterpret_cast<const char*>(&length);
260 std::string length_blob(length_bytes, sizeof(uint32_t));
261 std::string sym_header(std::begin(kSymContentHeader),
262 std::end(kSymContentHeader));
263 std::string sym_content = length_blob + sym_header + encrypted_credential;
264
265 encrypted->set_asym_ca_contents(encrypted_asym_content);
266 encrypted->set_sym_ca_attestation(sym_content);
267 return true;
268 }
269
EncryptForUnbind(const std::string & public_key,const std::string & data,std::string * encrypted_data)270 bool CryptoUtilityImpl::EncryptForUnbind(const std::string& public_key,
271 const std::string& data,
272 std::string* encrypted_data) {
273 // Construct a TPM_BOUND_DATA structure.
274 const char kBoundDataHeader[] = {1, 1, 0, 0, 2 /* TPM_PT_BIND */};
275 std::string header(std::begin(kBoundDataHeader), std::end(kBoundDataHeader));
276 std::string bound_data = header + data;
277
278 // Encrypt using the TPM_ES_RSAESOAEP_SHA1_MGF1 scheme.
279 auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
280 crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
281 if (!rsa.get()) {
282 LOG(ERROR) << __func__ << ": Failed to decode public key: "
283 << GetOpenSSLError();
284 return false;
285 }
286 if (!TpmCompatibleOAEPEncrypt(bound_data, rsa.get(), encrypted_data)) {
287 LOG(ERROR) << __func__ << ": Failed to encrypt with public key.";
288 return false;
289 }
290 return true;
291 }
292
VerifySignature(const std::string & public_key,const std::string & data,const std::string & signature)293 bool CryptoUtilityImpl::VerifySignature(const std::string& public_key,
294 const std::string& data,
295 const std::string& signature) {
296 auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
297 crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
298 if (!rsa.get()) {
299 LOG(ERROR) << __func__ << ": Failed to decode public key: "
300 << GetOpenSSLError();
301 return false;
302 }
303 std::string digest = crypto::SHA256HashString(data);
304 auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
305 std::string mutable_signature(signature);
306 unsigned char* signature_buffer = StringAsOpenSSLBuffer(&mutable_signature);
307 return (RSA_verify(NID_sha256, digest_buffer, digest.size(),
308 signature_buffer, signature.size(), rsa.get()) == 1);
309 }
310
AesEncrypt(const std::string & data,const std::string & key,const std::string & iv,std::string * encrypted_data)311 bool CryptoUtilityImpl::AesEncrypt(const std::string& data,
312 const std::string& key,
313 const std::string& iv,
314 std::string* encrypted_data) {
315 if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
316 return false;
317 }
318 if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
319 // EVP_EncryptUpdate takes a signed int.
320 return false;
321 }
322 std::string mutable_data(data);
323 unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_data);
324 std::string mutable_key(key);
325 unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
326 std::string mutable_iv(iv);
327 unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
328 // Allocate enough space for the output (including padding).
329 encrypted_data->resize(data.size() + kAesBlockSize);
330 auto output_buffer = reinterpret_cast<unsigned char*>(
331 string_as_array(encrypted_data));
332 int output_size = 0;
333 const EVP_CIPHER* cipher = EVP_aes_256_cbc();
334 EVP_CIPHER_CTX encryption_context;
335 EVP_CIPHER_CTX_init(&encryption_context);
336 if (!EVP_EncryptInit_ex(&encryption_context, cipher, nullptr, key_buffer,
337 iv_buffer)) {
338 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
339 return false;
340 }
341 if (!EVP_EncryptUpdate(&encryption_context, output_buffer, &output_size,
342 input_buffer, data.size())) {
343 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
344 EVP_CIPHER_CTX_cleanup(&encryption_context);
345 return false;
346 }
347 size_t total_size = output_size;
348 output_buffer += output_size;
349 output_size = 0;
350 if (!EVP_EncryptFinal_ex(&encryption_context, output_buffer, &output_size)) {
351 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
352 EVP_CIPHER_CTX_cleanup(&encryption_context);
353 return false;
354 }
355 total_size += output_size;
356 encrypted_data->resize(total_size);
357 EVP_CIPHER_CTX_cleanup(&encryption_context);
358 return true;
359 }
360
AesDecrypt(const std::string & encrypted_data,const std::string & key,const std::string & iv,std::string * data)361 bool CryptoUtilityImpl::AesDecrypt(const std::string& encrypted_data,
362 const std::string& key,
363 const std::string& iv,
364 std::string* data) {
365 if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
366 return false;
367 }
368 if (encrypted_data.size() >
369 static_cast<size_t>(std::numeric_limits<int>::max())) {
370 // EVP_DecryptUpdate takes a signed int.
371 return false;
372 }
373 std::string mutable_encrypted_data(encrypted_data);
374 unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_encrypted_data);
375 std::string mutable_key(key);
376 unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
377 std::string mutable_iv(iv);
378 unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
379 // Allocate enough space for the output.
380 data->resize(encrypted_data.size());
381 unsigned char* output_buffer = StringAsOpenSSLBuffer(data);
382 int output_size = 0;
383 const EVP_CIPHER* cipher = EVP_aes_256_cbc();
384 EVP_CIPHER_CTX decryption_context;
385 EVP_CIPHER_CTX_init(&decryption_context);
386 if (!EVP_DecryptInit_ex(&decryption_context, cipher, nullptr, key_buffer,
387 iv_buffer)) {
388 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
389 return false;
390 }
391 if (!EVP_DecryptUpdate(&decryption_context, output_buffer, &output_size,
392 input_buffer, encrypted_data.size())) {
393 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
394 EVP_CIPHER_CTX_cleanup(&decryption_context);
395 return false;
396 }
397 size_t total_size = output_size;
398 output_buffer += output_size;
399 output_size = 0;
400 if (!EVP_DecryptFinal_ex(&decryption_context, output_buffer, &output_size)) {
401 LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
402 EVP_CIPHER_CTX_cleanup(&decryption_context);
403 return false;
404 }
405 total_size += output_size;
406 data->resize(total_size);
407 EVP_CIPHER_CTX_cleanup(&decryption_context);
408 return true;
409 }
410
HmacSha512(const std::string & data,const std::string & key)411 std::string CryptoUtilityImpl::HmacSha512(const std::string& data,
412 const std::string& key) {
413 unsigned char mac[SHA512_DIGEST_LENGTH];
414 std::string mutable_data(data);
415 unsigned char* data_buffer = StringAsOpenSSLBuffer(&mutable_data);
416 HMAC(EVP_sha512(), key.data(), key.size(), data_buffer, data.size(), mac,
417 nullptr);
418 return std::string(std::begin(mac), std::end(mac));
419 }
420
TssCompatibleEncrypt(const std::string & input,const std::string & key,std::string * output)421 bool CryptoUtilityImpl::TssCompatibleEncrypt(const std::string& input,
422 const std::string& key,
423 std::string* output) {
424 CHECK(output);
425 CHECK_EQ(key.size(), kAesKeySize);
426 std::string iv;
427 if (!GetRandom(kAesBlockSize, &iv)) {
428 LOG(ERROR) << __func__ << ": GetRandom failed.";
429 return false;
430 }
431 std::string encrypted;
432 if (!AesEncrypt(input, key, iv, &encrypted)) {
433 LOG(ERROR) << __func__ << ": Encryption failed.";
434 return false;
435 }
436 *output = iv + encrypted;
437 return true;
438 }
439
TpmCompatibleOAEPEncrypt(const std::string & input,RSA * key,std::string * output)440 bool CryptoUtilityImpl::TpmCompatibleOAEPEncrypt(const std::string& input,
441 RSA* key,
442 std::string* output) {
443 CHECK(output);
444 // The custom OAEP parameter as specified in TPM Main Part 1, Section 31.1.1.
445 const unsigned char oaep_param[4] = {'T', 'C', 'P', 'A'};
446 std::string padded_input;
447 padded_input.resize(RSA_size(key));
448 auto padded_buffer = reinterpret_cast<unsigned char*>(
449 string_as_array(&padded_input));
450 auto input_buffer = reinterpret_cast<const unsigned char*>(input.data());
451 int result = RSA_padding_add_PKCS1_OAEP(padded_buffer, padded_input.size(),
452 input_buffer, input.size(),
453 oaep_param, arraysize(oaep_param));
454 if (!result) {
455 LOG(ERROR) << __func__ << ": Failed to add OAEP padding: "
456 << GetOpenSSLError();
457 return false;
458 }
459 output->resize(padded_input.size());
460 auto output_buffer = reinterpret_cast<unsigned char*>(
461 string_as_array(output));
462 result = RSA_public_encrypt(padded_input.size(), padded_buffer,
463 output_buffer, key, RSA_NO_PADDING);
464 if (result == -1) {
465 LOG(ERROR) << __func__ << ": Failed to encrypt OAEP padded input: "
466 << GetOpenSSLError();
467 return false;
468 }
469 return true;
470 }
471
472 } // namespace attestation
473