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