xref: /optee_os/ta/pkcs11/src/persistent_token.c (revision 9dbdd8cd750206c92b34c645fff365bea4485313)
1c84ccd0aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2c84ccd0aSEtienne Carriere /*
3c84ccd0aSEtienne Carriere  * Copyright (c) 2018-2020, Linaro Limited
4c84ccd0aSEtienne Carriere  */
5c84ccd0aSEtienne Carriere 
6c84ccd0aSEtienne Carriere #include <assert.h>
7c84ccd0aSEtienne Carriere #include <pkcs11_ta.h>
8c84ccd0aSEtienne Carriere #include <string.h>
9c84ccd0aSEtienne Carriere #include <string_ext.h>
10c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h>
11c84ccd0aSEtienne Carriere #include <util.h>
12c84ccd0aSEtienne Carriere 
13c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
14c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
15c84ccd0aSEtienne Carriere 
16c84ccd0aSEtienne Carriere void close_persistent_db(struct ck_token *token __unused)
17c84ccd0aSEtienne Carriere {
18c84ccd0aSEtienne Carriere }
19c84ccd0aSEtienne Carriere 
20c84ccd0aSEtienne Carriere static void init_pin_keys(struct ck_token *token, unsigned int uid)
21c84ccd0aSEtienne Carriere {
22c84ccd0aSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
23c84ccd0aSEtienne Carriere 	unsigned int token_id = get_token_id(token);
24c84ccd0aSEtienne Carriere 	TEE_ObjectHandle key_hdl = TEE_HANDLE_NULL;
25c84ccd0aSEtienne Carriere 	char file[32] = { 0 };
26be1ce869SEtienne Carriere 	int n = 0;
27c84ccd0aSEtienne Carriere 
28c84ccd0aSEtienne Carriere 	assert(token_id < 10 && uid < 10);
29c84ccd0aSEtienne Carriere 
30be1ce869SEtienne Carriere 	n = snprintf(file, sizeof(file), "token.db.%1d-pin%1d", token_id, uid);
31be1ce869SEtienne Carriere 	if (n < 0 || (size_t)n >= sizeof(file))
32c84ccd0aSEtienne Carriere 		TEE_Panic(0);
33c84ccd0aSEtienne Carriere 
34c84ccd0aSEtienne Carriere 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
35c84ccd0aSEtienne Carriere 				       file, sizeof(file), 0, &key_hdl);
36c84ccd0aSEtienne Carriere 
37c84ccd0aSEtienne Carriere 	if (res == TEE_ERROR_ITEM_NOT_FOUND) {
38c84ccd0aSEtienne Carriere 		TEE_Attribute attr = { };
39c84ccd0aSEtienne Carriere 		TEE_ObjectHandle hdl = TEE_HANDLE_NULL;
40c84ccd0aSEtienne Carriere 		uint8_t pin_key[16] = { 0 };
41c84ccd0aSEtienne Carriere 
42c84ccd0aSEtienne Carriere 		TEE_MemFill(&attr, 0, sizeof(attr));
43c84ccd0aSEtienne Carriere 
44c84ccd0aSEtienne Carriere 		TEE_GenerateRandom(pin_key, sizeof(pin_key));
45c84ccd0aSEtienne Carriere 		TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE,
46c84ccd0aSEtienne Carriere 				     pin_key, sizeof(pin_key));
47c84ccd0aSEtienne Carriere 
48c84ccd0aSEtienne Carriere 		res = TEE_AllocateTransientObject(TEE_TYPE_AES, 128, &hdl);
49c84ccd0aSEtienne Carriere 		if (res)
50c84ccd0aSEtienne Carriere 			TEE_Panic(0);
51c84ccd0aSEtienne Carriere 
52c84ccd0aSEtienne Carriere 		res = TEE_PopulateTransientObject(hdl, &attr, 1);
53c84ccd0aSEtienne Carriere 		if (res)
54c84ccd0aSEtienne Carriere 			TEE_Panic(0);
55c84ccd0aSEtienne Carriere 
56c84ccd0aSEtienne Carriere 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
57c84ccd0aSEtienne Carriere 						 file, sizeof(file), 0, hdl,
58c84ccd0aSEtienne Carriere 						 pin_key, sizeof(pin_key),
59c84ccd0aSEtienne Carriere 						 &key_hdl);
60c84ccd0aSEtienne Carriere 		TEE_CloseObject(hdl);
61c84ccd0aSEtienne Carriere 
62c84ccd0aSEtienne Carriere 		if (res == TEE_SUCCESS)
63c84ccd0aSEtienne Carriere 			DMSG("Token %u: PIN key created", token_id);
64c84ccd0aSEtienne Carriere 	}
65c84ccd0aSEtienne Carriere 
66c84ccd0aSEtienne Carriere 	if (res)
67c84ccd0aSEtienne Carriere 		TEE_Panic(res);
68c84ccd0aSEtienne Carriere 
69c84ccd0aSEtienne Carriere 	TEE_CloseObject(key_hdl);
70c84ccd0aSEtienne Carriere }
71c84ccd0aSEtienne Carriere 
72c84ccd0aSEtienne Carriere /*
73c84ccd0aSEtienne Carriere  * Return the token instance, either initialized from reset or initialized
74c84ccd0aSEtienne Carriere  * from the token persistent state if found.
75c84ccd0aSEtienne Carriere  */
76c84ccd0aSEtienne Carriere struct ck_token *init_persistent_db(unsigned int token_id)
77c84ccd0aSEtienne Carriere {
78c84ccd0aSEtienne Carriere 	struct ck_token *token = get_token(token_id);
79c84ccd0aSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
80c84ccd0aSEtienne Carriere 	char db_file[32] = { 0 };
81c84ccd0aSEtienne Carriere 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
82c84ccd0aSEtienne Carriere 	struct token_persistent_main *db_main = NULL;
83c84ccd0aSEtienne Carriere 	int n = 0;
84c84ccd0aSEtienne Carriere 
85c84ccd0aSEtienne Carriere 	if (!token)
86c84ccd0aSEtienne Carriere 		return NULL;
87c84ccd0aSEtienne Carriere 
88*9dbdd8cdSEtienne Carriere 	init_pin_keys(token, PKCS11_CKU_SO);
89*9dbdd8cdSEtienne Carriere 	init_pin_keys(token, PKCS11_CKU_USER);
90*9dbdd8cdSEtienne Carriere 	COMPILE_TIME_ASSERT(PKCS11_CKU_SO == 0 && PKCS11_CKU_USER == 1 &&
91*9dbdd8cdSEtienne Carriere 			    PKCS11_MAX_USERS >= 2);
92c84ccd0aSEtienne Carriere 
93c84ccd0aSEtienne Carriere 	db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
94c84ccd0aSEtienne Carriere 	if (!db_main)
95c84ccd0aSEtienne Carriere 		goto error;
96c84ccd0aSEtienne Carriere 
97be1ce869SEtienne Carriere 	n = snprintf(db_file, sizeof(db_file), "token.db.%1d", token_id);
98be1ce869SEtienne Carriere 	if (n < 0 || (size_t)n >= sizeof(db_file))
99c84ccd0aSEtienne Carriere 		TEE_Panic(0);
100c84ccd0aSEtienne Carriere 
101c84ccd0aSEtienne Carriere 	res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
102c84ccd0aSEtienne Carriere 				       db_file, sizeof(db_file),
103c84ccd0aSEtienne Carriere 				       TEE_DATA_FLAG_ACCESS_READ |
104c84ccd0aSEtienne Carriere 				       TEE_DATA_FLAG_ACCESS_WRITE,
105c84ccd0aSEtienne Carriere 				       &db_hdl);
106c84ccd0aSEtienne Carriere 	if (res == TEE_SUCCESS) {
107c84ccd0aSEtienne Carriere 		uint32_t size = 0;
108c84ccd0aSEtienne Carriere 
109c84ccd0aSEtienne Carriere 		IMSG("PKCS11 token %u: load db", token_id);
110c84ccd0aSEtienne Carriere 
111c84ccd0aSEtienne Carriere 		size = sizeof(*db_main);
112c84ccd0aSEtienne Carriere 		res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
113c84ccd0aSEtienne Carriere 		if (res || size != sizeof(*db_main))
114c84ccd0aSEtienne Carriere 			TEE_Panic(0);
115c84ccd0aSEtienne Carriere 	} else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
116c84ccd0aSEtienne Carriere 		IMSG("PKCS11 token %u: init db", token_id);
117c84ccd0aSEtienne Carriere 
118c84ccd0aSEtienne Carriere 		TEE_MemFill(db_main, 0, sizeof(*db_main));
119c84ccd0aSEtienne Carriere 		TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
120c84ccd0aSEtienne Carriere 
121c84ccd0aSEtienne Carriere 		db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED |
122c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED |
123c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_RNG |
124c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS |
125c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_LOGIN_REQUIRED;
126c84ccd0aSEtienne Carriere 
127c84ccd0aSEtienne Carriere 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
128c84ccd0aSEtienne Carriere 						 db_file, sizeof(db_file),
129c84ccd0aSEtienne Carriere 						 TEE_DATA_FLAG_ACCESS_READ |
130c84ccd0aSEtienne Carriere 						 TEE_DATA_FLAG_ACCESS_WRITE,
131c84ccd0aSEtienne Carriere 						 TEE_HANDLE_NULL,
132c84ccd0aSEtienne Carriere 						 db_main, sizeof(*db_main),
133c84ccd0aSEtienne Carriere 						 &db_hdl);
134c84ccd0aSEtienne Carriere 		if (res) {
135c84ccd0aSEtienne Carriere 			EMSG("Failed to create db: %"PRIx32, res);
136c84ccd0aSEtienne Carriere 			goto error;
137c84ccd0aSEtienne Carriere 		}
138c84ccd0aSEtienne Carriere 	} else {
139c84ccd0aSEtienne Carriere 		goto error;
140c84ccd0aSEtienne Carriere 	}
141c84ccd0aSEtienne Carriere 
142c84ccd0aSEtienne Carriere 	token->db_main = db_main;
143c84ccd0aSEtienne Carriere 	TEE_CloseObject(db_hdl);
144c84ccd0aSEtienne Carriere 
145c84ccd0aSEtienne Carriere 	return token;
146c84ccd0aSEtienne Carriere 
147c84ccd0aSEtienne Carriere error:
148c84ccd0aSEtienne Carriere 	TEE_Free(db_main);
149c84ccd0aSEtienne Carriere 	if (db_hdl != TEE_HANDLE_NULL)
150c84ccd0aSEtienne Carriere 		TEE_CloseObject(db_hdl);
151c84ccd0aSEtienne Carriere 
152c84ccd0aSEtienne Carriere 	return NULL;
153c84ccd0aSEtienne Carriere }
154