blob: bc1603039e66cc61dcb0764ed1010141925d97a1 [file] [log] [blame]
Shawn Willden72014ad2014-09-17 13:04:10 -06001/*
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
24#include "ae.h"
25#include "unencrypted_key_blob.h"
26
27namespace keymaster {
28
29class UnencryptedKeyBlob::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
43UnencryptedKeyBlob::UnencryptedKeyBlob(const AuthorizationSet& enforced,
44 const AuthorizationSet& unenforced,
45 const AuthorizationSet& hidden,
46 const uint8_t* unencrypted_key,
47 size_t unencrypted_key_length, const uint8_t* master_key,
48 size_t master_key_length, const uint8_t nonce[NONCE_LENGTH])
49 : KeyBlob(enforced, unenforced), hidden_(hidden) {
50 // Check that KeyBlob ctor succeeded.
51 if (error_ != KM_ERROR_OK)
52 return;
53
54 if (hidden_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) {
55 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
56 return;
57 }
58
59 if (hidden_.is_valid() != AuthorizationSet::OK) {
60 error_ = KM_ERROR_UNKNOWN_ERROR;
61 return;
62 }
63
64 unencrypted_key_material_.reset(new uint8_t[unencrypted_key_length]);
65 if (!unencrypted_key_material_.get()) {
66 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
67 return;
68 }
69
70 unencrypted_key_material_length_ = unencrypted_key_length;
71 memcpy(unencrypted_key_material_.get(), unencrypted_key, unencrypted_key_length);
72 EncryptKey(master_key, master_key_length, nonce);
73}
74
75UnencryptedKeyBlob::UnencryptedKeyBlob(const keymaster_key_blob_t& key,
76 const AuthorizationSet& hidden, const uint8_t* master_key,
77 size_t master_key_length)
78 : KeyBlob(key), hidden_(hidden) {
79 // Check that KeyBlob ctor succeeded.
80 if (error_ != KM_ERROR_OK)
81 return;
82 DecryptKey(master_key, master_key_length);
83}
84
85void UnencryptedKeyBlob::EncryptKey(const uint8_t* master_key, size_t master_key_length,
86 const uint8_t* nonce) {
87 UniquePtr<AeCtx> ctx(InitializeKeyWrappingContext(master_key, master_key_length));
88 if (error_ != KM_ERROR_OK)
89 return;
90
91 UniquePtr<uint8_t[]> encrypted_key_material(new uint8_t[unencrypted_key_material_length()]);
92 UniquePtr<uint8_t[]> tag(new uint8_t[TAG_LENGTH]);
93 UniquePtr<uint8_t[]> nonce_copy(new uint8_t[NONCE_LENGTH]);
94 if (!encrypted_key_material.get() || !tag.get() || !nonce_copy.get()) {
95 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
96 return;
97 }
98 memcpy(nonce_copy.get(), nonce, NONCE_LENGTH);
99
100 int ae_err =
101 ae_encrypt(ctx->get(), nonce, unencrypted_key_material(), unencrypted_key_material_length(),
102 NULL /* additional data */, 0 /* additional data length */,
103 encrypted_key_material.get(), tag.get(), 1 /* final */);
104 if (ae_err < 0) {
105 error_ = KM_ERROR_UNKNOWN_ERROR;
106 return;
107 }
108 assert(ae_err == static_cast<int>(unencrypted_key_material_length()));
109
110 SetEncryptedKey(encrypted_key_material.release(), unencrypted_key_material_length(),
111 nonce_copy.release(), tag.release());
112}
113
114void UnencryptedKeyBlob::DecryptKey(const uint8_t* master_key, size_t master_key_length) {
115 UniquePtr<AeCtx> ctx(InitializeKeyWrappingContext(master_key, master_key_length));
116 if (error_ != KM_ERROR_OK)
117 return;
118
119 unencrypted_key_material_length_ = key_material_length();
120 unencrypted_key_material_.reset(new uint8_t[unencrypted_key_material_length_]);
121 int ae_err = ae_decrypt(ctx->get(), nonce(), encrypted_key_material(), key_material_length(),
122 NULL /* additional data */, 0 /* additional data length */,
123 unencrypted_key_material_.get(), tag(), 1 /* final */);
124 if (ae_err == AE_INVALID) {
125 // Authentication failed! Decryption probably succeeded(ish), but we don't want to return
126 // any data when the authentication fails, so clear it.
127 memset_s(unencrypted_key_material_.get(), 0, unencrypted_key_material_length());
128 error_ = KM_ERROR_INVALID_KEY_BLOB;
129 return;
130 } else if (ae_err < 0) {
131 error_ = KM_ERROR_UNKNOWN_ERROR;
132 return;
133 }
134 assert(ae_err == static_cast<int>(unencrypted_key_material_length()));
135 error_ = KM_ERROR_OK;
136}
137
138UnencryptedKeyBlob::AeCtx*
139UnencryptedKeyBlob::InitializeKeyWrappingContext(const uint8_t* master_key,
140 size_t master_key_length) {
141 size_t derivation_data_length;
142 UniquePtr<const uint8_t[]> derivation_data(BuildDerivationData(&derivation_data_length));
143 if (derivation_data.get() == NULL) {
144 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
145 return NULL;
146 }
147
148 UniquePtr<AeCtx> ctx(new AeCtx);
149
150 SHA256_CTX sha256_ctx;
151 UniquePtr<uint8_t[]> hash_buf(new uint8_t[SHA256_DIGEST_LENGTH]);
152 Eraser hash_eraser(hash_buf.get(), SHA256_DIGEST_LENGTH);
153 UniquePtr<uint8_t[]> derived_key(new uint8_t[AES_BLOCK_SIZE]);
154 Eraser derived_key_eraser(derived_key.get(), AES_BLOCK_SIZE);
155
156 if (ctx.get() == NULL || hash_buf.get() == NULL || derived_key.get() == NULL) {
157 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
158 return NULL;
159 }
160
161 Eraser sha256_ctx_eraser(sha256_ctx);
162
163 // Hash derivation data.
164 SHA256_Init(&sha256_ctx);
165 SHA256_Update(&sha256_ctx, derivation_data.get(), derivation_data_length);
166 SHA256_Final(hash_buf.get(), &sha256_ctx);
167
168 // Encrypt hash with master key to build derived key.
169 AES_KEY aes_key;
170 Eraser aes_key_eraser(AES_KEY);
171 if (AES_set_encrypt_key(master_key, master_key_length * 8, &aes_key) != 0) {
172 error_ = KM_ERROR_UNKNOWN_ERROR;
173 return NULL;
174 }
175 AES_encrypt(hash_buf.get(), derived_key.get(), &aes_key);
176
177 // Set up AES OCB context using derived key.
178 if (ae_init(ctx->get(), derived_key.get(), AES_BLOCK_SIZE, NONCE_LENGTH, TAG_LENGTH) ==
179 AE_SUCCESS)
180 return ctx.release();
181 else {
182 memset_s(ctx.get(), 0, ae_ctx_sizeof());
183 return NULL;
184 }
185}
186
187const uint8_t* UnencryptedKeyBlob::BuildDerivationData(size_t* derivation_data_length) const {
188 *derivation_data_length =
189 hidden_.SerializedSize() + enforced().SerializedSize() + unenforced().SerializedSize();
190 uint8_t* derivation_data = new uint8_t[*derivation_data_length];
191 if (derivation_data != NULL) {
192 uint8_t* buf = derivation_data;
193 uint8_t* end = derivation_data + *derivation_data_length;
194 buf = hidden_.Serialize(buf, end);
195 buf = enforced().Serialize(buf, end);
196 buf = unenforced().Serialize(buf, end);
197 }
198 return derivation_data;
199}
200
201} // namespace keymaster