1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 * Copyright 2017 NXP
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <assert.h>
19 #include <stddef.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <uapi/err.h>
24
25 #include <interface/hwkey/hwkey.h>
26 #include <nxp_hwcrypto_uuid_consts.h>
27 #include <openssl/aes.h>
28 #include <openssl/cipher.h>
29 #include <openssl/digest.h>
30 #include <openssl/err.h>
31 #include <openssl/hkdf.h>
32
33 #include "caam.h"
34 #include "common.h"
35 #include "hwkey_keyslots.h"
36 #include "hwkey_srv_priv.h"
37
38 #define TLOG_TAG "hwkey_caam"
39 #include <trusty_log.h>
40
41 static const uint8_t skeymod[16] __attribute__((aligned(16))) = {
42 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
43 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
44
45 static uint8_t kdfv1_key[32] __attribute__((aligned(32)));
46
47 /*
48 * Derive key V1 - HKDF based key derive.
49 */
derive_key_v1(const uuid_t * uuid,const uint8_t * ikm_data,size_t ikm_len,uint8_t * key_buf,size_t * key_len)50 uint32_t derive_key_v1(const uuid_t* uuid,
51 const uint8_t* ikm_data,
52 size_t ikm_len,
53 uint8_t* key_buf,
54 size_t* key_len) {
55 uint32_t res;
56
57 *key_len = 0;
58
59 if (!ikm_len)
60 return HWKEY_ERR_BAD_LEN;
61
62 if (!HKDF(key_buf, ikm_len, EVP_sha256(), (const uint8_t*)kdfv1_key,
63 sizeof(kdfv1_key), (const uint8_t*)uuid, sizeof(uuid_t), ikm_data,
64 ikm_len)) {
65 TLOGE("HDKF failed 0x%x\n", ERR_get_error());
66 memset(key_buf, 0, ikm_len);
67 res = HWKEY_ERR_GENERIC;
68 goto done;
69 }
70 *key_len = ikm_len;
71 res = HWKEY_NO_ERROR;
72 done:
73 return res;
74 }
75
76 /*
77 * RPMB Key support
78 */
79 #define RPMB_SS_AUTH_KEY_SIZE 32
80 #define RPMB_SS_AUTH_KEY_ID "com.android.trusty.storage_auth.rpmb"
81
82 /* Secure storage service app uuid */
83 static const uuid_t ss_uuid = SECURE_STORAGE_SERVER_APP_UUID;
84 static size_t rpmb_keyblob_len;
85 static uint8_t rpmb_keyblob[RPMBKEY_LEN];
86
87 /*
88 * Fetch RPMB Secure Storage Authentication key
89 */
get_rpmb_ss_auth_key(const struct hwkey_keyslot * slot,uint8_t * kbuf,size_t kbuf_len,size_t * klen)90 static uint32_t get_rpmb_ss_auth_key(const struct hwkey_keyslot* slot,
91 uint8_t* kbuf,
92 size_t kbuf_len,
93 size_t* klen) {
94 uint32_t res;
95 assert(kbuf_len >= RPMB_SS_AUTH_KEY_SIZE);
96
97 if (rpmb_keyblob_len != sizeof(rpmb_keyblob))
98 return HWKEY_ERR_NOT_FOUND; /* no RPMB key */
99
100 res = caam_decap_blob(skeymod, sizeof(skeymod), kbuf, rpmb_keyblob,
101 RPMB_SS_AUTH_KEY_SIZE);
102 if (res == CAAM_SUCCESS) {
103 *klen = RPMB_SS_AUTH_KEY_SIZE;
104 return HWKEY_NO_ERROR;
105 } else {
106 /* wipe target buffer */
107 TLOGE("%s: failed to unpack rpmb key\n", __func__);
108 memset(kbuf, 0, RPMB_SS_AUTH_KEY_SIZE);
109 return HWKEY_ERR_GENERIC;
110 }
111 }
112
113 /*
114 * List of keys slots that hwkey service supports
115 */
116 static const struct hwkey_keyslot _keys[] = {
117 {
118 .uuid = &ss_uuid,
119 .key_id = RPMB_SS_AUTH_KEY_ID,
120 .handler = get_rpmb_ss_auth_key,
121 },
122 };
123
unpack_kbox(void)124 static void unpack_kbox(void) {
125 uint32_t res;
126 struct keyslot_package* kbox = caam_get_keybox();
127
128 if (strncmp(kbox->magic, KEYPACK_MAGIC, 4)) {
129 TLOGE("Invalid magic\n");
130 abort();
131 }
132
133 /* Copy RPMB blob */
134 assert(!rpmb_keyblob_len); /* key should be unset */
135 if (kbox->rpmb_keyblob_len != sizeof(rpmb_keyblob)) {
136 TLOGE("Unexpected RPMB key len: %u\n", kbox->rpmb_keyblob_len);
137 } else {
138 memcpy(rpmb_keyblob, kbox->rpmb_keyblob, kbox->rpmb_keyblob_len);
139 rpmb_keyblob_len = kbox->rpmb_keyblob_len;
140 }
141
142 /* generate kdfv1 root it should never fail */
143 res = caam_gen_kdfv1_root_key(kdfv1_key, sizeof(kdfv1_key));
144 assert(res == CAAM_SUCCESS);
145
146 /* copy pubkey blob */
147
148 /* wipe kbox in sram */
149 memset(kbox, 0, sizeof(*kbox));
150 }
151
152 /*
153 * Initialize Fake HWKEY service provider
154 */
hwkey_init_srv_provider(void)155 void hwkey_init_srv_provider(void) {
156 int rc;
157
158 TLOGD("Init HWKEY service provider\n");
159
160 unpack_kbox();
161
162 /* install key handlers */
163 hwkey_install_keys(_keys, countof(_keys));
164
165 /* start service */
166 rc = hwkey_start_service();
167 if (rc != NO_ERROR) {
168 TLOGE("failed (%d) to start HWKEY service\n", rc);
169 }
170 }
171