1 /* 2 * Copyright 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 <assert.h> 18 19 #include <openssl/aes.h> 20 #include <openssl/sha.h> 21 22 #include <keymaster/google_keymaster_utils.h> 23 #include <keymaster/key_blob.h> 24 25 #include "ae.h" 26 27 namespace keymaster { 28 29 class KeyBlob::AeCtx { 30 public: 31 AeCtx() : ctx_(ae_allocate(NULL)) {} 32 ~AeCtx() { 33 ae_clear(ctx_); 34 ae_free(ctx_); 35 } 36 37 ae_ctx* get() { return ctx_; } 38 39 private: 40 ae_ctx* ctx_; 41 }; 42 43 const size_t KeyBlob::NONCE_LENGTH; 44 const size_t KeyBlob::TAG_LENGTH; 45 46 KeyBlob::KeyBlob(const AuthorizationSet& enforced, const AuthorizationSet& unenforced, 47 const AuthorizationSet& hidden, const keymaster_key_blob_t& key, 48 const keymaster_key_blob_t& master_key, const uint8_t nonce[NONCE_LENGTH]) 49 : error_(KM_ERROR_OK), nonce_(new uint8_t[NONCE_LENGTH]), tag_(new uint8_t[TAG_LENGTH]), 50 enforced_(enforced), unenforced_(unenforced), hidden_(hidden) { 51 if (!nonce_.get() || !tag_.get()) { 52 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED; 53 return; 54 } 55 error_ = KM_ERROR_OK; 56 57 if (enforced_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE || 58 unenforced_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE || 59 hidden_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) { 60 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED; 61 return; 62 } 63 64 if (enforced_.is_valid() != AuthorizationSet::OK || 65 unenforced_.is_valid() != AuthorizationSet::OK || 66 hidden_.is_valid() != AuthorizationSet::OK) { 67 error_ = KM_ERROR_UNKNOWN_ERROR; 68 return; 69 } 70 71 if (!ExtractKeyCharacteristics()) 72 return; 73 74 key_material_length_ = key.key_material_size; 75 key_material_.reset(new uint8_t[key_material_length_]); 76 encrypted_key_material_.reset(new uint8_t[key_material_length_]); 77 78 if (!key_material_.get() || !encrypted_key_material_.get() || !nonce_.get() || !tag_.get()) { 79 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED; 80 return; 81 } 82 83 memcpy(nonce_.get(), nonce, NONCE_LENGTH); 84 memcpy(key_material_.get(), key.key_material, key_material_length_); 85 EncryptKey(master_key); 86 } 87 88 KeyBlob::KeyBlob(const keymaster_key_blob_t& key, const AuthorizationSet& hidden, 89 const keymaster_key_blob_t& master_key) 90 : nonce_(new uint8_t[NONCE_LENGTH]), tag_(new uint8_t[TAG_LENGTH]), hidden_(hidden) { 91 if (!nonce_.get() || !tag_.get()) { 92 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED; 93 return; 94 } 95 error_ = KM_ERROR_OK; 96 97 const uint8_t* p = key.key_material; 98 if (!Deserialize(&p, key.key_material + key.key_material_size)) 99 return; 100 DecryptKey(master_key); 101 } 102 103 KeyBlob::KeyBlob(const uint8_t* key_blob, size_t blob_size) 104 : nonce_(new uint8_t[NONCE_LENGTH]), tag_(new uint8_t[TAG_LENGTH]) { 105 if (!nonce_.get() || !tag_.get()) { 106 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED; 107 return; 108 } 109 error_ = KM_ERROR_OK; 110 111 if (!Deserialize(&key_blob, key_blob + blob_size)) 112 return; 113 } 114 115 size_t KeyBlob::SerializedSize() const { 116 return NONCE_LENGTH + sizeof(uint32_t) + key_material_length() + TAG_LENGTH + 117 enforced_.SerializedSize() + unenforced_.SerializedSize(); 118 } 119 120 uint8_t* KeyBlob::Serialize(uint8_t* buf, const uint8_t* end) const { 121 const uint8_t* start = buf; 122 buf = append_to_buf(buf, end, nonce(), NONCE_LENGTH); 123 buf = append_size_and_data_to_buf(buf, end, encrypted_key_material(), key_material_length()); 124 buf = append_to_buf(buf, end, tag(), TAG_LENGTH); 125 buf = enforced_.Serialize(buf, end); 126 buf = unenforced_.Serialize(buf, end); 127 assert(buf - start == static_cast<ptrdiff_t>(SerializedSize())); 128 return buf; 129 } 130 131 bool KeyBlob::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { 132 UniquePtr<uint8_t[]> tmp_key_ptr; 133 if (!copy_from_buf(buf_ptr, end, nonce_.get(), NONCE_LENGTH) || 134 !copy_size_and_data_from_buf(buf_ptr, end, &key_material_length_, &tmp_key_ptr) || 135 !copy_from_buf(buf_ptr, end, tag_.get(), TAG_LENGTH) || 136 !enforced_.Deserialize(buf_ptr, end) || !unenforced_.Deserialize(buf_ptr, end)) { 137 error_ = KM_ERROR_INVALID_KEY_BLOB; 138 return false; 139 } 140 141 if (!ExtractKeyCharacteristics()) 142 return false; 143 144 encrypted_key_material_.reset(tmp_key_ptr.release()); 145 key_material_.reset(new uint8_t[key_material_length_]); 146 return true; 147 } 148 149 void KeyBlob::EncryptKey(const keymaster_key_blob_t& master_key) { 150 UniquePtr<AeCtx> ctx(InitializeKeyWrappingContext(master_key, &error_)); 151 if (error_ != KM_ERROR_OK) 152 return; 153 154 int ae_err = ae_encrypt(ctx->get(), nonce_.get(), key_material(), key_material_length(), 155 NULL /* additional data */, 0 /* additional data length */, 156 encrypted_key_material_.get(), tag_.get(), 1 /* final */); 157 if (ae_err < 0) { 158 error_ = KM_ERROR_UNKNOWN_ERROR; 159 return; 160 } 161 assert(ae_err == static_cast<int>(key_material_length_)); 162 error_ = KM_ERROR_OK; 163 } 164 165 void KeyBlob::DecryptKey(const keymaster_key_blob_t& master_key) { 166 UniquePtr<AeCtx> ctx(InitializeKeyWrappingContext(master_key, &error_)); 167 if (error_ != KM_ERROR_OK) 168 return; 169 170 int ae_err = 171 ae_decrypt(ctx->get(), nonce_.get(), encrypted_key_material(), key_material_length(), 172 NULL /* additional data */, 0 /* additional data length */, key_material_.get(), 173 tag_.get(), 1 /* final */); 174 if (ae_err == AE_INVALID) { 175 // Authentication failed! Decryption probably succeeded(ish), but we don't want to return 176 // any data when the authentication fails, so clear it. 177 memset_s(key_material_.get(), 0, key_material_length()); 178 error_ = KM_ERROR_INVALID_KEY_BLOB; 179 return; 180 } else if (ae_err < 0) { 181 error_ = KM_ERROR_UNKNOWN_ERROR; 182 return; 183 } 184 assert(ae_err == static_cast<int>(key_material_length())); 185 error_ = KM_ERROR_OK; 186 } 187 188 KeyBlob::AeCtx* KeyBlob::InitializeKeyWrappingContext(const keymaster_key_blob_t& master_key, 189 keymaster_error_t* error) const { 190 size_t derivation_data_length; 191 UniquePtr<const uint8_t[]> derivation_data(BuildDerivationData(&derivation_data_length)); 192 if (derivation_data.get() == NULL) { 193 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; 194 return NULL; 195 } 196 197 *error = KM_ERROR_OK; 198 UniquePtr<AeCtx> ctx(new AeCtx); 199 200 SHA256_CTX sha256_ctx; 201 UniquePtr<uint8_t[]> hash_buf(new uint8_t[SHA256_DIGEST_LENGTH]); 202 Eraser hash_eraser(hash_buf.get(), SHA256_DIGEST_LENGTH); 203 UniquePtr<uint8_t[]> derived_key(new uint8_t[AES_BLOCK_SIZE]); 204 Eraser derived_key_eraser(derived_key.get(), AES_BLOCK_SIZE); 205 206 if (ctx.get() == NULL || hash_buf.get() == NULL || derived_key.get() == NULL) { 207 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; 208 return NULL; 209 } 210 211 Eraser sha256_ctx_eraser(sha256_ctx); 212 213 // Hash derivation data. 214 SHA256_Init(&sha256_ctx); 215 SHA256_Update(&sha256_ctx, derivation_data.get(), derivation_data_length); 216 SHA256_Final(hash_buf.get(), &sha256_ctx); 217 218 // Encrypt hash with master key to build derived key. 219 AES_KEY aes_key; 220 Eraser aes_key_eraser(AES_KEY); 221 if (AES_set_encrypt_key(master_key.key_material, master_key.key_material_size * 8, &aes_key) != 222 0) { 223 *error = KM_ERROR_UNKNOWN_ERROR; 224 return NULL; 225 } 226 AES_encrypt(hash_buf.get(), derived_key.get(), &aes_key); 227 228 // Set up AES OCB context using derived key. 229 if (ae_init(ctx->get(), derived_key.get(), AES_BLOCK_SIZE, NONCE_LENGTH, TAG_LENGTH) == 230 AE_SUCCESS) 231 return ctx.release(); 232 else { 233 memset_s(ctx.get(), 0, ae_ctx_sizeof()); 234 return NULL; 235 } 236 } 237 238 const uint8_t* KeyBlob::BuildDerivationData(size_t* derivation_data_length) const { 239 *derivation_data_length = 240 hidden_.SerializedSize() + enforced_.SerializedSize() + unenforced_.SerializedSize(); 241 uint8_t* derivation_data = new uint8_t[*derivation_data_length]; 242 if (derivation_data != NULL) { 243 uint8_t* buf = derivation_data; 244 uint8_t* end = derivation_data + *derivation_data_length; 245 buf = hidden_.Serialize(buf, end); 246 buf = enforced_.Serialize(buf, end); 247 buf = unenforced_.Serialize(buf, end); 248 } 249 return derivation_data; 250 } 251 252 bool KeyBlob::ExtractKeyCharacteristics() { 253 if (!enforced_.GetTagValue(TAG_ALGORITHM, &algorithm_) && 254 !unenforced_.GetTagValue(TAG_ALGORITHM, &algorithm_)) { 255 error_ = KM_ERROR_UNSUPPORTED_ALGORITHM; 256 return false; 257 } 258 if (!enforced_.GetTagValue(TAG_KEY_SIZE, &key_size_bits_) && 259 !unenforced_.GetTagValue(TAG_KEY_SIZE, &key_size_bits_)) { 260 error_ = KM_ERROR_UNSUPPORTED_KEY_SIZE; 261 return false; 262 } 263 return true; 264 } 265 266 } // namespace keymaster 267