xref: /optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c (revision 5abb46e24b1bb52f8c3c46b10a07b83c50a40b0c)
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 
81 		/*
82 		 * The less significant byte different than zero prevents bignum
83 		 * conversions from discarding it
84 		 */
85 		if (oid > OID_MAX || !(oid & 0xFF))
86 			continue;
87 
88 		if (!se050_key_exists(oid, &se050_session->s_ctx)) {
89 			*val = oid;
90 			return kStatus_SSS_Success;
91 		}
92 	}
93 
94 	return kStatus_SSS_Fail;
95 }
96 
se050_get_oid(uint32_t * val)97 sss_status_t se050_get_oid(uint32_t *val)
98 {
99 	sss_status_t status = kStatus_SSS_Success;
100 	uint16_t mem_t = 0;
101 
102 	if (!val)
103 		return kStatus_SSS_Fail;
104 
105 	status = se050_get_free_memory(&se050_session->s_ctx, &mem_t,
106 				       kSE05x_MemoryType_TRANSIENT_DESELECT);
107 	if (status != kStatus_SSS_Success)
108 		return kStatus_SSS_Fail;
109 
110 	if (mem_t < TRANSIENT_MEMORY_THRESHOLD)
111 		delete_transient_objects();
112 
113 	return generate_oid(val);
114 }
115 
se050_key(uint64_t key)116 static uint32_t se050_key(uint64_t key)
117 {
118 	uint32_t oid = (uint32_t)key;
119 
120 	if (!IS_WATERMARKED(key))
121 		return 0;
122 
123 	/* oid > OID_MAX could have been created by an external client */
124 	if (oid < OID_MIN)
125 		return 0;
126 
127 	return oid;
128 }
129 
se050_rsa_keypair_from_nvm(struct rsa_keypair * key)130 uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key)
131 {
132 	uint64_t key_id = 0;
133 
134 	if (!key)
135 		return 0;
136 
137 	if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t))
138 		return 0;
139 
140 	crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id);
141 
142 	return se050_key(key_id);
143 }
144 
se050_ecc_keypair_from_nvm(struct ecc_keypair * key)145 uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key)
146 {
147 	uint64_t key_id = 0;
148 
149 	if (!key)
150 		return 0;
151 
152 	if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t))
153 		return 0;
154 
155 	crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id);
156 
157 	return se050_key(key_id);
158 }
159 
se050_generate_private_key(uint32_t oid)160 uint64_t se050_generate_private_key(uint32_t oid)
161 {
162 	return WATERMARKED(oid);
163 }
164 
se050_refcount_init_ctx(uint8_t ** cnt)165 void se050_refcount_init_ctx(uint8_t **cnt)
166 {
167 	if (!*cnt) {
168 		*cnt = calloc(1, sizeof(uint8_t));
169 		if (*cnt)
170 			**cnt = 1;
171 		else
172 			EMSG("can't allocate refcount");
173 	} else {
174 		**cnt = **cnt + 1;
175 	}
176 }
177 
se050_refcount_final_ctx(uint8_t * cnt)178 int se050_refcount_final_ctx(uint8_t *cnt)
179 {
180 	if (!cnt)
181 		return 1;
182 
183 	if (!*cnt) {
184 		free(cnt);
185 		return 1;
186 	}
187 
188 	*cnt = *cnt - 1;
189 
190 	return 0;
191 }
192