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