1/* 2 * Copyright 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 "ocb_utils.h" 18 19#include <assert.h> 20 21#include <new> 22 23#include <openssl/aes.h> 24#include <openssl/sha.h> 25 26#include <hardware/keymaster_defs.h> 27#include <keymaster/authorization_set.h> 28#include <keymaster/android_keymaster_utils.h> 29 30#include "openssl_err.h" 31 32namespace keymaster { 33 34class AeCtx { 35 public: 36 AeCtx() : ctx_(ae_allocate(NULL)) {} 37 ~AeCtx() { 38 ae_clear(ctx_); 39 ae_free(ctx_); 40 } 41 42 ae_ctx* get() { return ctx_; } 43 44 private: 45 ae_ctx* ctx_; 46}; 47 48static keymaster_error_t BuildDerivationData(const AuthorizationSet& hw_enforced, 49 const AuthorizationSet& sw_enforced, 50 const AuthorizationSet& hidden, 51 UniquePtr<uint8_t[]>* derivation_data, 52 size_t* derivation_data_length) { 53 *derivation_data_length = 54 hidden.SerializedSize() + hw_enforced.SerializedSize() + sw_enforced.SerializedSize(); 55 derivation_data->reset(new (std::nothrow) uint8_t[*derivation_data_length]); 56 if (!derivation_data->get()) 57 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 58 59 uint8_t* buf = derivation_data->get(); 60 uint8_t* end = derivation_data->get() + *derivation_data_length; 61 buf = hidden.Serialize(buf, end); 62 buf = hw_enforced.Serialize(buf, end); 63 buf = sw_enforced.Serialize(buf, end); 64 65 return KM_ERROR_OK; 66} 67 68static keymaster_error_t InitializeKeyWrappingContext(const AuthorizationSet& hw_enforced, 69 const AuthorizationSet& sw_enforced, 70 const AuthorizationSet& hidden, 71 const KeymasterKeyBlob& master_key, 72 AeCtx* ctx) { 73 size_t derivation_data_length; 74 UniquePtr<uint8_t[]> derivation_data; 75 keymaster_error_t error = BuildDerivationData(hw_enforced, sw_enforced, hidden, 76 &derivation_data, &derivation_data_length); 77 if (error != KM_ERROR_OK) 78 return error; 79 80 SHA256_CTX sha256_ctx; 81 UniquePtr<uint8_t[]> hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH]); 82 if (!hash_buf.get()) 83 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 84 Eraser hash_eraser(hash_buf.get(), SHA256_DIGEST_LENGTH); 85 UniquePtr<uint8_t[]> derived_key(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]); 86 if (!derived_key.get()) 87 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 88 Eraser derived_key_eraser(derived_key.get(), AES_BLOCK_SIZE); 89 90 if (!ctx->get() || !hash_buf.get() || !derived_key.get()) 91 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 92 93 // Hash derivation data. 94 Eraser sha256_ctx_eraser(sha256_ctx); 95 SHA256_Init(&sha256_ctx); 96 SHA256_Update(&sha256_ctx, derivation_data.get(), derivation_data_length); 97 SHA256_Final(hash_buf.get(), &sha256_ctx); 98 99 // Encrypt hash with master key to build derived key. 100 AES_KEY aes_key; 101 Eraser aes_key_eraser(AES_KEY); 102 if (0 != 103 AES_set_encrypt_key(master_key.key_material, master_key.key_material_size * 8, &aes_key)) 104 return TranslateLastOpenSslError(); 105 106 AES_encrypt(hash_buf.get(), derived_key.get(), &aes_key); 107 108 // Set up AES OCB context using derived key. 109 if (ae_init(ctx->get(), derived_key.get(), AES_BLOCK_SIZE /* key length */, OCB_NONCE_LENGTH, 110 OCB_TAG_LENGTH) != AE_SUCCESS) { 111 memset_s(ctx->get(), 0, ae_ctx_sizeof()); 112 return KM_ERROR_UNKNOWN_ERROR; 113 } 114 115 return KM_ERROR_OK; 116} 117 118keymaster_error_t OcbEncryptKey(const AuthorizationSet& hw_enforced, 119 const AuthorizationSet& sw_enforced, const AuthorizationSet& hidden, 120 const KeymasterKeyBlob& master_key, 121 const KeymasterKeyBlob& plaintext, const Buffer& nonce, 122 KeymasterKeyBlob* ciphertext, Buffer* tag) { 123 assert(ciphertext && tag); 124 125 if (nonce.available_read() != OCB_NONCE_LENGTH) 126 return KM_ERROR_INVALID_ARGUMENT; 127 128 AeCtx ctx; 129 if (!ctx.get()) 130 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 131 132 keymaster_error_t error = 133 InitializeKeyWrappingContext(hw_enforced, sw_enforced, hidden, master_key, &ctx); 134 if (error != KM_ERROR_OK) 135 return error; 136 137 if (!ciphertext->Reset(plaintext.key_material_size)) 138 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 139 140 int ae_err = ae_encrypt(ctx.get(), nonce.peek_read(), plaintext.key_material, 141 plaintext.key_material_size, NULL /* additional data */, 142 0 /* additional data length */, ciphertext->writable_data(), 143 tag->peek_write(), 1 /* final */); 144 if (ae_err < 0) { 145 LOG_E("Error %d while encrypting key", ae_err); 146 return KM_ERROR_UNKNOWN_ERROR; 147 } 148 if (!tag->advance_write(OCB_TAG_LENGTH)) 149 return KM_ERROR_UNKNOWN_ERROR; 150 assert(ae_err == static_cast<int>(plaintext.key_material_size)); 151 return KM_ERROR_OK; 152} 153 154keymaster_error_t OcbDecryptKey(const AuthorizationSet& hw_enforced, 155 const AuthorizationSet& sw_enforced, const AuthorizationSet& hidden, 156 const KeymasterKeyBlob& master_key, 157 const KeymasterKeyBlob& ciphertext, const Buffer& nonce, 158 const Buffer& tag, KeymasterKeyBlob* plaintext) { 159 assert(plaintext); 160 161 if (nonce.available_read() != OCB_NONCE_LENGTH || tag.available_read() != OCB_TAG_LENGTH) 162 return KM_ERROR_INVALID_ARGUMENT; 163 164 AeCtx ctx; 165 if (!ctx.get()) 166 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 167 168 keymaster_error_t error = 169 InitializeKeyWrappingContext(hw_enforced, sw_enforced, hidden, master_key, &ctx); 170 if (error != KM_ERROR_OK) 171 return error; 172 173 if (!plaintext->Reset(ciphertext.key_material_size)) 174 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 175 176 int ae_err = ae_decrypt(ctx.get(), nonce.peek_read(), ciphertext.key_material, 177 ciphertext.key_material_size, NULL /* additional data */, 178 0 /* additional data length */, plaintext->writable_data(), 179 tag.peek_read(), 1 /* final */); 180 if (ae_err == AE_INVALID) { 181 // Authentication failed! Decryption probably succeeded(ish), but we don't want to return 182 // any data when the authentication fails, so clear it. 183 plaintext->Clear(); 184 LOG_E("Failed to validate authentication tag during key decryption", 0); 185 return KM_ERROR_INVALID_KEY_BLOB; 186 } else if (ae_err < 0) { 187 LOG_E("Failed to decrypt key, error: %d", ae_err); 188 return KM_ERROR_UNKNOWN_ERROR; 189 } 190 assert(ae_err == static_cast<int>(ciphertext.key_material_size)); 191 return KM_ERROR_OK; 192} 193 194} // namespace keymaster 195