1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved
4 * Author: Jorge Ramirez <jorge@foundries.io>
5 */
6
7 #include <crypto/crypto.h>
8 #include <se050.h>
9 #include <se050_utils.h>
10 #include <string.h>
11 #include <util.h>
12
13 /* exp: minimal amount of transient memory required to generate an RSA key */
14 #define TRANSIENT_MEMORY_THRESHOLD 0x140
15
16 #define NBR_OID ((uint32_t)(OID_MAX - OID_MIN))
17 #define IS_WATERMARKED(x) (((x) & WATERMARKED(0)) == WATERMARKED(0))
18
delete_transient_objects(void)19 static void delete_transient_objects(void)
20 {
21 SE05x_AttestationType_t att = kSE05x_AttestationType_None;
22 SE05x_SecureObjectType_t type = kSE05x_SecObjTyp_HMAC_KEY;
23 uint8_t more = kSE05x_MoreIndicator_NA;
24 smStatus_t status = SM_NOT_OK;
25 Se05xSession_t *ctx = NULL;
26 uint8_t *list = NULL;
27 size_t len = 1024;
28 uint16_t offset = 0;
29 uint8_t mode = 0;
30 uint32_t id = 0;
31 size_t i = 0;
32
33 if (!se050_session)
34 return;
35
36 ctx = &se050_session->s_ctx;
37
38 list = calloc(1, len);
39 if (!list)
40 return;
41 do {
42 status = Se05x_API_ReadIDList(ctx, offset, 0xFF, &more,
43 list, &len);
44 if (status != SM_OK)
45 break;
46
47 offset = len;
48 for (i = 0; i < len; i += 4) {
49 id = (list[i + 0] << (3 * 8)) |
50 (list[i + 1] << (2 * 8)) |
51 (list[i + 2] << (1 * 8)) |
52 (list[i + 3] << (0 * 8));
53
54 if (id >= OID_MAX || id == 0)
55 continue;
56
57 status = Se05x_API_ReadType(ctx, id, &type, &mode, att);
58 if (status != SM_OK)
59 continue;
60
61 if (mode == kKeyObject_Mode_Transient)
62 Se05x_API_DeleteSecureObject(ctx, id);
63 }
64 } while (more == kSE05x_MoreIndicator_MORE);
65
66 free(list);
67 }
68
generate_oid(uint32_t * val)69 static sss_status_t generate_oid(uint32_t *val)
70 {
71 uint32_t oid = OID_MIN;
72 uint32_t random = 0;
73 size_t i = 0;
74
75 for (i = 0; i < NBR_OID; i++) {
76 if (crypto_rng_read(&random, sizeof(random)))
77 return kStatus_SSS_Fail;
78
79 oid = OID_MIN + (random & OID_MAX);
80 if (oid > OID_MAX)
81 continue;
82
83 if (!se050_key_exists(oid, &se050_session->s_ctx)) {
84 *val = oid;
85 return kStatus_SSS_Success;
86 }
87 }
88
89 return kStatus_SSS_Fail;
90 }
91
se050_get_oid(uint32_t * val)92 sss_status_t se050_get_oid(uint32_t *val)
93 {
94 sss_status_t status = kStatus_SSS_Success;
95 uint16_t mem_t = 0;
96
97 if (!val)
98 return kStatus_SSS_Fail;
99
100 status = se050_get_free_memory(&se050_session->s_ctx, &mem_t,
101 kSE05x_MemoryType_TRANSIENT_DESELECT);
102 if (status != kStatus_SSS_Success)
103 return kStatus_SSS_Fail;
104
105 if (mem_t < TRANSIENT_MEMORY_THRESHOLD)
106 delete_transient_objects();
107
108 return generate_oid(val);
109 }
110
se050_key(uint64_t key)111 static uint32_t se050_key(uint64_t key)
112 {
113 uint32_t oid = (uint32_t)key;
114
115 if (!IS_WATERMARKED(key))
116 return 0;
117
118 /* oid > OID_MAX could have been created by an external client */
119 if (oid < OID_MIN)
120 return 0;
121
122 return oid;
123 }
124
se050_rsa_keypair_from_nvm(struct rsa_keypair * key)125 uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key)
126 {
127 uint64_t key_id = 0;
128
129 if (!key)
130 return 0;
131
132 if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t))
133 return 0;
134
135 crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id);
136
137 return se050_key(key_id);
138 }
139
se050_ecc_keypair_from_nvm(struct ecc_keypair * key)140 uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key)
141 {
142 uint64_t key_id = 0;
143
144 if (!key)
145 return 0;
146
147 if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t))
148 return 0;
149
150 crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id);
151
152 return se050_key(key_id);
153 }
154
se050_generate_private_key(uint32_t oid)155 uint64_t se050_generate_private_key(uint32_t oid)
156 {
157 return WATERMARKED(oid);
158 }
159
se050_refcount_init_ctx(uint8_t ** cnt)160 void se050_refcount_init_ctx(uint8_t **cnt)
161 {
162 if (!*cnt) {
163 *cnt = calloc(1, sizeof(uint8_t));
164 if (*cnt)
165 **cnt = 1;
166 else
167 EMSG("can't allocate refcount");
168 } else {
169 **cnt = **cnt + 1;
170 }
171 }
172
se050_refcount_final_ctx(uint8_t * cnt)173 int se050_refcount_final_ctx(uint8_t *cnt)
174 {
175 if (!cnt)
176 return 1;
177
178 if (!*cnt) {
179 free(cnt);
180 return 1;
181 }
182
183 *cnt = *cnt - 1;
184
185 return 0;
186 }
187