xref: /optee_os/ta/pkcs11/src/persistent_token.c (revision 11fa71b9ddb429088f325cfda430183003ccd1db)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <pkcs11_ta.h>
8 #include <string.h>
9 #include <string_ext.h>
10 #include <tee_internal_api_extensions.h>
11 #include <util.h>
12 
13 #include "pkcs11_token.h"
14 #include "pkcs11_helpers.h"
15 
16 #define PERSISTENT_OBJECT_ID_LEN	32
17 
18 /*
19  * Token persistent objects
20  */
21 static TEE_Result get_db_file_name(struct ck_token *token,
22 				   char *name, size_t size)
23 {
24 	int n = snprintf(name, size, "token.db.%u", get_token_id(token));
25 
26 	if (n < 0 || (size_t)n >= size)
27 		return TEE_ERROR_SECURITY;
28 	else
29 		return TEE_SUCCESS;
30 }
31 
32 static TEE_Result open_db_file(struct ck_token *token,
33 			       TEE_ObjectHandle *out_hdl)
34 {
35 	char file[PERSISTENT_OBJECT_ID_LEN] = { };
36 	TEE_Result res = TEE_ERROR_GENERIC;
37 
38 	res = get_db_file_name(token, file, sizeof(file));
39 	if (res)
40 		return res;
41 
42 	return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file),
43 					TEE_DATA_FLAG_ACCESS_READ |
44 					TEE_DATA_FLAG_ACCESS_WRITE,
45 					out_hdl);
46 }
47 
48 void update_persistent_db(struct ck_token *token)
49 {
50 	TEE_Result res = TEE_ERROR_GENERIC;
51 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
52 
53 	res = open_db_file(token, &db_hdl);
54 	if (res) {
55 		EMSG("Failed to open token persistent db: %#"PRIx32, res);
56 		TEE_Panic(0);
57 	}
58 	res = TEE_WriteObjectData(db_hdl, token->db_main,
59 				  sizeof(*token->db_main));
60 	if (res) {
61 		EMSG("Failed to write to token persistent db: %#"PRIx32, res);
62 		TEE_Panic(0);
63 	}
64 
65 	TEE_CloseObject(db_hdl);
66 }
67 
68 static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin,
69 			      size_t pin_size, uint32_t salt,
70 			      uint8_t hash[TEE_MAX_HASH_SIZE])
71 {
72 	TEE_Result res = TEE_SUCCESS;
73 	TEE_OperationHandle oh = TEE_HANDLE_NULL;
74 	uint32_t sz = TEE_MAX_HASH_SIZE;
75 
76 	res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
77 	if (res)
78 		return tee2pkcs_error(res);
79 
80 	TEE_DigestUpdate(oh, &user, sizeof(user));
81 	TEE_DigestUpdate(oh, &salt, sizeof(salt));
82 	res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz);
83 	TEE_FreeOperation(oh);
84 
85 	if (res)
86 		return PKCS11_CKR_GENERAL_ERROR;
87 
88 	memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz);
89 	return PKCS11_CKR_OK;
90 }
91 
92 enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin,
93 			size_t pin_size, uint32_t *salt,
94 			uint8_t hash[TEE_MAX_HASH_SIZE])
95 {
96 	enum pkcs11_rc rc = PKCS11_CKR_OK;
97 	uint32_t s = 0;
98 
99 	TEE_GenerateRandom(&s, sizeof(s));
100 	if (!s)
101 		s++;
102 
103 	rc = do_hash(user, pin, pin_size, s, hash);
104 	if (!rc)
105 		*salt = s;
106 	return rc;
107 }
108 
109 enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin,
110 			  size_t pin_size, uint32_t salt,
111 			  const uint8_t hash[TEE_MAX_HASH_SIZE])
112 {
113 	uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 };
114 	enum pkcs11_rc rc = PKCS11_CKR_OK;
115 
116 	rc = do_hash(user, pin, pin_size, salt, tmp_hash);
117 	if (rc)
118 		return rc;
119 
120 	if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE))
121 		rc = PKCS11_CKR_PIN_INCORRECT;
122 
123 	return rc;
124 }
125 
126 /*
127  * Release resources relate to persistent database
128  */
129 void close_persistent_db(struct ck_token *token __unused)
130 {
131 }
132 
133 /*
134  * Return the token instance, either initialized from reset or initialized
135  * from the token persistent state if found.
136  */
137 struct ck_token *init_persistent_db(unsigned int token_id)
138 {
139 	struct ck_token *token = get_token(token_id);
140 	TEE_Result res = TEE_ERROR_GENERIC;
141 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
142 	/* Copy persistent database: main db and object db */
143 	struct token_persistent_main *db_main = NULL;
144 
145 	if (!token)
146 		return NULL;
147 
148 	db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
149 	if (!db_main)
150 		goto error;
151 
152 	res = open_db_file(token, &db_hdl);
153 
154 	if (res == TEE_SUCCESS) {
155 		uint32_t size = 0;
156 
157 		IMSG("PKCS11 token %u: load db", token_id);
158 
159 		size = sizeof(*db_main);
160 		res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
161 		if (res || size != sizeof(*db_main))
162 			TEE_Panic(0);
163 	} else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
164 		char file[PERSISTENT_OBJECT_ID_LEN] = { };
165 
166 		IMSG("PKCS11 token %u: init db", token_id);
167 
168 		TEE_MemFill(db_main, 0, sizeof(*db_main));
169 		TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
170 
171 		db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED |
172 				 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED |
173 				 PKCS11_CKFT_RNG |
174 				 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS |
175 				 PKCS11_CKFT_LOGIN_REQUIRED;
176 
177 		res = get_db_file_name(token, file, sizeof(file));
178 		if (res)
179 			TEE_Panic(0);
180 
181 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
182 						 file, sizeof(file),
183 						 TEE_DATA_FLAG_ACCESS_READ |
184 						 TEE_DATA_FLAG_ACCESS_WRITE,
185 						 TEE_HANDLE_NULL,
186 						 db_main, sizeof(*db_main),
187 						 &db_hdl);
188 		if (res) {
189 			EMSG("Failed to create db: %"PRIx32, res);
190 			goto error;
191 		}
192 	} else {
193 		goto error;
194 	}
195 
196 	token->db_main = db_main;
197 	TEE_CloseObject(db_hdl);
198 
199 	return token;
200 
201 error:
202 	TEE_Free(db_main);
203 	if (db_hdl != TEE_HANDLE_NULL)
204 		TEE_CloseObject(db_hdl);
205 
206 	return NULL;
207 }
208