Update from upstream to 2.4.0 version
[platform/core/security/tef-optee_os.git] / core / tee / tee_fs_key_manager.c
1 /*
2  * Copyright (c) 2015, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28
29 /*
30  * Acronyms:
31  *
32  * FEK - File Encryption Key
33  * SSK - Secure Storage Key
34  * TSK - Trusted app Storage Key
35  * IV  - Initial vector
36  * HUK - Hardware Unique Key
37  * RNG - Random Number Generator
38  */
39
40 #include <initcall.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <kernel/panic.h>
44 #include <kernel/tee_common_otp.h>
45 #include <kernel/tee_ta_manager.h>
46 #include <tee/tee_cryp_utl.h>
47 #include <tee/tee_cryp_provider.h>
48 #include <tee/tee_fs_key_manager.h>
49 #include <compiler.h>
50 #include <trace.h>
51 #include <util.h>
52
53 struct tee_fs_ssk {
54         bool is_init;
55         uint8_t key[TEE_FS_KM_SSK_SIZE];
56 };
57
58 static struct tee_fs_ssk tee_fs_ssk;
59 static uint8_t string_for_ssk_gen[] = "ONLY_FOR_tee_fs_ssk";
60
61
62 static TEE_Result do_hmac(uint8_t *out_key, uint32_t out_key_size,
63                           const uint8_t *in_key, uint32_t in_key_size,
64                           const uint8_t *message, uint32_t message_size)
65 {
66         TEE_Result res = TEE_ERROR_GENERIC;
67         uint8_t *ctx = NULL;
68         size_t hash_ctx_size = 0;
69
70         if (!out_key || !in_key || !message)
71                 return TEE_ERROR_BAD_PARAMETERS;
72
73         res = crypto_ops.mac.get_ctx_size(TEE_FS_KM_HMAC_ALG, &hash_ctx_size);
74         if (res != TEE_SUCCESS)
75                 return res;
76
77         ctx = malloc(hash_ctx_size);
78         if (!ctx)
79                 return TEE_ERROR_OUT_OF_MEMORY;
80
81         res = crypto_ops.mac.init(ctx, TEE_FS_KM_HMAC_ALG, in_key, in_key_size);
82         if (res != TEE_SUCCESS)
83                 goto exit;
84
85         res = crypto_ops.mac.update(ctx, TEE_FS_KM_HMAC_ALG,
86                         message, message_size);
87         if (res != TEE_SUCCESS)
88                 goto exit;
89
90         res = crypto_ops.mac.final(ctx, TEE_FS_KM_HMAC_ALG, out_key,
91                                    out_key_size);
92         if (res != TEE_SUCCESS)
93                 goto exit;
94
95         res = TEE_SUCCESS;
96
97 exit:
98         free(ctx);
99         return res;
100 }
101
102 TEE_Result tee_fs_fek_crypt(TEE_OperationMode mode, const uint8_t *in_key,
103                             size_t size, uint8_t *out_key)
104 {
105         TEE_Result res;
106         uint8_t *ctx = NULL;
107         size_t ctx_size;
108         uint8_t tsk[TEE_FS_KM_TSK_SIZE];
109         uint8_t dst_key[size];
110         struct tee_ta_session *sess;
111
112         if (!in_key || !out_key)
113                 return TEE_ERROR_BAD_PARAMETERS;
114
115         if (size != TEE_FS_KM_FEK_SIZE)
116                 return TEE_ERROR_BAD_PARAMETERS;
117
118         if (tee_fs_ssk.is_init == 0)
119                 return TEE_ERROR_GENERIC;
120
121         res = tee_ta_get_current_session(&sess);
122         if (res != TEE_SUCCESS)
123                 return res;
124
125         res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE,
126                       (uint8_t *)&sess->ctx->uuid, sizeof(TEE_UUID));
127         if (res != TEE_SUCCESS)
128                 return res;
129
130         res = crypto_ops.cipher.get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
131         if (res != TEE_SUCCESS)
132                 return res;
133
134         ctx = malloc(ctx_size);
135         if (!ctx)
136                 return TEE_ERROR_OUT_OF_MEMORY;
137
138         res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
139                                      sizeof(tsk), NULL, 0, NULL, 0);
140         if (res != TEE_SUCCESS)
141                 goto exit;
142
143         res = crypto_ops.cipher.update(ctx, TEE_FS_KM_ENC_FEK_ALG,
144                         mode, true, in_key, size, dst_key);
145         if (res != TEE_SUCCESS)
146                 goto exit;
147
148         crypto_ops.cipher.final(ctx, TEE_FS_KM_ENC_FEK_ALG);
149
150         memcpy(out_key, dst_key, sizeof(dst_key));
151
152 exit:
153         free(ctx);
154
155         return res;
156 }
157
158 static TEE_Result generate_fek(uint8_t *key, uint8_t len)
159 {
160         return crypto_ops.prng.read(key, len);
161 }
162
163 static TEE_Result tee_fs_init_key_manager(void)
164 {
165         int res = TEE_SUCCESS;
166         struct tee_hw_unique_key huk;
167         uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH];
168         uint8_t message[sizeof(chip_id) + sizeof(string_for_ssk_gen)];
169
170         /* Secure Storage Key Generation:
171          *
172          *     SSK = HMAC(HUK, message)
173          *     message := concatenate(chip_id, static string)
174          * */
175         tee_otp_get_hw_unique_key(&huk);
176         tee_otp_get_die_id(chip_id, sizeof(chip_id));
177
178         memcpy(message, chip_id, sizeof(chip_id));
179         memcpy(message + sizeof(chip_id), string_for_ssk_gen,
180                         sizeof(string_for_ssk_gen));
181
182         res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
183                         huk.data, sizeof(huk.data),
184                         message, sizeof(message));
185
186         if (res == TEE_SUCCESS)
187                 tee_fs_ssk.is_init = 1;
188
189         return res;
190 }
191
192 TEE_Result tee_fs_generate_fek(uint8_t *buf, int buf_size)
193 {
194         TEE_Result res;
195
196         if (buf_size != TEE_FS_KM_FEK_SIZE)
197                 return TEE_ERROR_BAD_PARAMETERS;
198
199         res = generate_fek(buf, TEE_FS_KM_FEK_SIZE);
200         if (res != TEE_SUCCESS)
201                 return res;
202
203         return tee_fs_fek_crypt(TEE_MODE_ENCRYPT, buf, TEE_FS_KM_FEK_SIZE, buf);
204 }
205
206 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
207                          size_t in_size)
208 {
209         TEE_Result res;
210         uint8_t *ctx = NULL;
211         size_t ctx_size;
212         uint32_t algo = TEE_ALG_SHA256;
213
214         res = crypto_ops.hash.get_ctx_size(algo, &ctx_size);
215         if (res != TEE_SUCCESS)
216                 return res;
217
218         ctx = malloc(ctx_size);
219         if (!ctx)
220                 return TEE_ERROR_OUT_OF_MEMORY;
221
222         res = crypto_ops.hash.init(ctx, algo);
223         if (res != TEE_SUCCESS)
224                 goto out;
225
226         res = crypto_ops.hash.update(ctx, algo, in, in_size);
227         if (res != TEE_SUCCESS)
228                 goto out;
229
230         res = crypto_ops.hash.final(ctx, algo, out, out_size);
231
232 out:
233         free(ctx);
234         return res;
235 }
236
237 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],
238                           const uint8_t in[TEE_AES_BLOCK_SIZE],
239                           const uint8_t *key, size_t key_size)
240 {
241         TEE_Result res;
242         uint8_t *ctx = NULL;
243         size_t ctx_size;
244         uint32_t algo = TEE_ALG_AES_ECB_NOPAD;
245
246         res = crypto_ops.cipher.get_ctx_size(algo, &ctx_size);
247         if (res != TEE_SUCCESS)
248                 return res;
249
250         ctx = malloc(ctx_size);
251         if (!ctx)
252                 return TEE_ERROR_OUT_OF_MEMORY;
253
254         res = crypto_ops.cipher.init(ctx, algo, TEE_MODE_ENCRYPT, key,
255                                      key_size, NULL, 0, NULL, 0);
256         if (res != TEE_SUCCESS)
257                 goto out;
258
259         res = crypto_ops.cipher.update(ctx, algo, TEE_MODE_ENCRYPT, true, in,
260                                        TEE_AES_BLOCK_SIZE, out);
261         if (res != TEE_SUCCESS)
262                 goto out;
263
264         crypto_ops.cipher.final(ctx, algo);
265         res = TEE_SUCCESS;
266
267 out:
268         free(ctx);
269         return res;
270 }
271
272 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],
273                         const uint8_t fek[TEE_FS_KM_FEK_SIZE],
274                         uint16_t blk_idx)
275 {
276         TEE_Result res;
277         uint8_t sha[TEE_SHA256_HASH_SIZE];
278         uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, };
279
280         res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE);
281         if (res != TEE_SUCCESS)
282                 return res;
283
284         pad_blkid[0] = (blk_idx & 0xFF);
285         pad_blkid[1] = (blk_idx & 0xFF00) >> 8;
286
287         return aes_ecb(iv, pad_blkid, sha, 16);
288 }
289
290 /*
291  * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV.
292  */
293 TEE_Result tee_fs_crypt_block(uint8_t *out, const uint8_t *in, size_t size,
294                               uint16_t blk_idx, const uint8_t *encrypted_fek,
295                               TEE_OperationMode mode)
296 {
297         TEE_Result res;
298         uint8_t fek[TEE_FS_KM_FEK_SIZE];
299         uint8_t iv[TEE_AES_BLOCK_SIZE];
300         uint8_t *ctx;
301         size_t ctx_size;
302         uint32_t algo = TEE_ALG_AES_CBC_NOPAD;
303
304         DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De",
305              blk_idx);
306
307         /* Decrypt FEK */
308         res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, encrypted_fek,
309                                TEE_FS_KM_FEK_SIZE, fek);
310         if (res != TEE_SUCCESS)
311                 return res;
312
313         /* Compute initialization vector for this block */
314         res = essiv(iv, fek, blk_idx);
315
316         /* Run AES CBC */
317         res = crypto_ops.cipher.get_ctx_size(algo, &ctx_size);
318         if (res != TEE_SUCCESS)
319                 return res;
320         ctx = malloc(ctx_size);
321         if (!ctx)
322                 return TEE_ERROR_OUT_OF_MEMORY;
323
324         res = crypto_ops.cipher.init(ctx, algo, mode, fek, sizeof(fek), NULL,
325                                      0, iv, TEE_AES_BLOCK_SIZE);
326         if (res != TEE_SUCCESS)
327                 goto exit;
328         res = crypto_ops.cipher.update(ctx, algo, mode, true, in, size, out);
329         if (res != TEE_SUCCESS)
330                 goto exit;
331
332         crypto_ops.cipher.final(ctx, algo);
333
334 exit:
335         free(ctx);
336         return res;
337 }
338
339 service_init_late(tee_fs_init_key_manager);