xref: /optee_os/ta/pkcs11/src/token_capabilities.c (revision 512cbf1d30ddce3513abf2b08d4063d5c8415a40)
18849c126SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
28849c126SEtienne Carriere /*
38849c126SEtienne Carriere  * Copyright (c) 2017-2020, Linaro Limited
48849c126SEtienne Carriere  */
58849c126SEtienne Carriere 
68849c126SEtienne Carriere #include <assert.h>
78849c126SEtienne Carriere #include <pkcs11_ta.h>
88849c126SEtienne Carriere #include <string.h>
98849c126SEtienne Carriere #include <util.h>
108849c126SEtienne Carriere #include <tee_api.h>
118849c126SEtienne Carriere #include <tee_internal_api_extensions.h>
128849c126SEtienne Carriere 
138849c126SEtienne Carriere #include "pkcs11_helpers.h"
148849c126SEtienne Carriere #include "token_capabilities.h"
158849c126SEtienne Carriere 
168849c126SEtienne Carriere #define ALLOWED_PKCS11_CKFM	\
178849c126SEtienne Carriere 	(PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT |		\
188849c126SEtienne Carriere 	 PKCS11_CKFM_DERIVE | PKCS11_CKFM_DIGEST |		\
198849c126SEtienne Carriere 	 PKCS11_CKFM_SIGN | PKCS11_CKFM_SIGN_RECOVER |		\
208849c126SEtienne Carriere 	 PKCS11_CKFM_VERIFY | PKCS11_CKFM_VERIFY_RECOVER |	\
218849c126SEtienne Carriere 	 PKCS11_CKFM_GENERATE |	PKCS11_CKFM_GENERATE_KEY_PAIR |	\
228849c126SEtienne Carriere 	 PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP)
238849c126SEtienne Carriere 
248849c126SEtienne Carriere /*
258849c126SEtienne Carriere  * Definition of supported processings for a PKCS#11 mechanisms
268849c126SEtienne Carriere  * @id: Mechanism ID
278849c126SEtienne Carriere  * @flags: Valid PKCS11_CKFM_* for a mechanism as per PKCS#11
288849c126SEtienne Carriere  * @one_shot: true of mechanism can be used for a one-short processing
298849c126SEtienne Carriere  * @string: Helper string of the mechanism ID for debug purpose
308849c126SEtienne Carriere  */
318849c126SEtienne Carriere struct pkcs11_mechachism_modes {
328849c126SEtienne Carriere 	uint32_t id;
338849c126SEtienne Carriere 	uint32_t flags;
348849c126SEtienne Carriere 	bool one_shot;
358849c126SEtienne Carriere #if CFG_TEE_TA_LOG_LEVEL > 0
368849c126SEtienne Carriere 	const char *string;
378849c126SEtienne Carriere #endif
388849c126SEtienne Carriere };
398849c126SEtienne Carriere 
408849c126SEtienne Carriere #if CFG_TEE_TA_LOG_LEVEL > 0
418849c126SEtienne Carriere #define MECHANISM(_label, _flags, _single_part)	\
428849c126SEtienne Carriere 	{					\
438849c126SEtienne Carriere 		.id = _label,			\
448849c126SEtienne Carriere 		.one_shot = (_single_part),	\
458849c126SEtienne Carriere 		.flags = (_flags),		\
468849c126SEtienne Carriere 		.string = #_label,		\
478849c126SEtienne Carriere 	}
488849c126SEtienne Carriere #else
498849c126SEtienne Carriere #define MECHANISM(_label, _flags, _single_part)	\
508849c126SEtienne Carriere 	{					\
518849c126SEtienne Carriere 		.id = _label,			\
528849c126SEtienne Carriere 		.one_shot = (_single_part),	\
538849c126SEtienne Carriere 		.flags = (_flags),		\
548849c126SEtienne Carriere 	}
558849c126SEtienne Carriere #endif
568849c126SEtienne Carriere 
578849c126SEtienne Carriere #define SINGLE_PART_ONLY	true
588849c126SEtienne Carriere #define ANY_PART		false
598849c126SEtienne Carriere 
60*512cbf1dSJens Wiklander #define CKFM_CIPHER		(PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT)
61*512cbf1dSJens Wiklander #define CKFM_WRAP_UNWRAP	(PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP)
62*512cbf1dSJens Wiklander #define CKFM_CIPHER_WRAP	(CKFM_CIPHER | CKFM_WRAP_UNWRAP)
63*512cbf1dSJens Wiklander #define CKFM_CIPHER_WRAP_DERIVE	(CKFM_CIPHER_WRAP | PKCS11_CKFM_DERIVE)
64*512cbf1dSJens Wiklander #define CKFM_AUTH_NO_RECOVER	(PKCS11_CKFM_SIGN | PKCS11_CKFM_VERIFY)
65*512cbf1dSJens Wiklander #define CKFM_AUTH_WITH_RECOVER	(PKCS11_CKFM_SIGN_RECOVER | \
66*512cbf1dSJens Wiklander 				 PKCS11_CKFM_VERIFY_RECOVER)
67*512cbf1dSJens Wiklander 
688849c126SEtienne Carriere /* PKCS#11 specificies permitted operation for each mechanism  */
698849c126SEtienne Carriere static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
70*512cbf1dSJens Wiklander 	/* AES */
71*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP, ANY_PART),
72*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP, ANY_PART),
73*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_CBC_PAD, CKFM_CIPHER_WRAP, ANY_PART),
74*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER_WRAP, ANY_PART),
75*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER_WRAP, ANY_PART),
76*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE,
778849c126SEtienne Carriere 		  ANY_PART),
78*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE,
79*512cbf1dSJens Wiklander 		  ANY_PART),
80*512cbf1dSJens Wiklander 	MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART),
818849c126SEtienne Carriere };
828849c126SEtienne Carriere 
838849c126SEtienne Carriere #if CFG_TEE_TA_LOG_LEVEL > 0
848849c126SEtienne Carriere const char *mechanism_string_id(enum pkcs11_mechanism_id id)
858849c126SEtienne Carriere {
868849c126SEtienne Carriere 	const size_t offset = sizeof("PKCS11_CKM_") - 1;
878849c126SEtienne Carriere 	size_t n = 0;
888849c126SEtienne Carriere 
898849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++)
908849c126SEtienne Carriere 		if (pkcs11_modes[n].id == id)
918849c126SEtienne Carriere 			return pkcs11_modes[n].string + offset;
928849c126SEtienne Carriere 
938849c126SEtienne Carriere 	return "Unknown ID";
948849c126SEtienne Carriere }
958849c126SEtienne Carriere #endif /*CFG_TEE_TA_LOG_LEVEL*/
968849c126SEtienne Carriere 
978849c126SEtienne Carriere /*
988849c126SEtienne Carriere  * Return true if @id is a valid mechanism ID
998849c126SEtienne Carriere  */
1008849c126SEtienne Carriere bool mechanism_is_valid(enum pkcs11_mechanism_id id)
1018849c126SEtienne Carriere {
1028849c126SEtienne Carriere 	size_t n = 0;
1038849c126SEtienne Carriere 
1048849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++)
1058849c126SEtienne Carriere 		if (id == pkcs11_modes[n].id)
1068849c126SEtienne Carriere 			return true;
1078849c126SEtienne Carriere 
1088849c126SEtienne Carriere 	return false;
1098849c126SEtienne Carriere }
1108849c126SEtienne Carriere 
1118849c126SEtienne Carriere /*
1128849c126SEtienne Carriere  * Return true if mechanism ID is valid and flags matches PKCS#11 compliancy
1138849c126SEtienne Carriere  */
1148849c126SEtienne Carriere bool __maybe_unused mechanism_flags_complies_pkcs11(uint32_t mechanism_type,
1158849c126SEtienne Carriere 						    uint32_t flags)
1168849c126SEtienne Carriere {
1178849c126SEtienne Carriere 	size_t n = 0;
1188849c126SEtienne Carriere 
1198849c126SEtienne Carriere 	assert((flags & ~ALLOWED_PKCS11_CKFM) == 0);
1208849c126SEtienne Carriere 
1218849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) {
1228849c126SEtienne Carriere 		if (pkcs11_modes[n].id == mechanism_type) {
1238849c126SEtienne Carriere 			if (flags & ~pkcs11_modes[n].flags)
1248849c126SEtienne Carriere 				EMSG("%s flags: 0x%"PRIx32" vs 0x%"PRIx32,
1258849c126SEtienne Carriere 				     id2str_mechanism(mechanism_type),
1268849c126SEtienne Carriere 				     flags, pkcs11_modes[n].flags);
1278849c126SEtienne Carriere 
1288849c126SEtienne Carriere 			return (flags & ~pkcs11_modes[n].flags) == 0;
1298849c126SEtienne Carriere 		}
1308849c126SEtienne Carriere 	}
1318849c126SEtienne Carriere 
1328849c126SEtienne Carriere 	/* Mechanism ID unexpectedly not found */
1338849c126SEtienne Carriere 	return false;
1348849c126SEtienne Carriere }
1358849c126SEtienne Carriere 
136*512cbf1dSJens Wiklander bool mechanism_is_one_shot_only(uint32_t mechanism_type)
137*512cbf1dSJens Wiklander {
138*512cbf1dSJens Wiklander 	size_t n = 0;
139*512cbf1dSJens Wiklander 
140*512cbf1dSJens Wiklander 	for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++)
141*512cbf1dSJens Wiklander 		if (pkcs11_modes[n].id == mechanism_type)
142*512cbf1dSJens Wiklander 			return pkcs11_modes[n].one_shot;
143*512cbf1dSJens Wiklander 
144*512cbf1dSJens Wiklander 	/* Mechanism ID unexpectedly not found */
145*512cbf1dSJens Wiklander 	TEE_Panic(PKCS11_RV_NOT_FOUND);
146*512cbf1dSJens Wiklander 	/* Dummy return to keep compiler happy */
147*512cbf1dSJens Wiklander 	return false;
148*512cbf1dSJens Wiklander }
149*512cbf1dSJens Wiklander 
150*512cbf1dSJens Wiklander /*
151*512cbf1dSJens Wiklander  * Field single_part_only is unused from array token_mechanism[], hence
152*512cbf1dSJens Wiklander  * simply use ANY_PART for all mechanism there.
153*512cbf1dSJens Wiklander  */
154*512cbf1dSJens Wiklander #define TA_MECHANISM(_label, _flags)	MECHANISM((_label), (_flags), ANY_PART)
155*512cbf1dSJens Wiklander 
1568849c126SEtienne Carriere /*
1578849c126SEtienne Carriere  * Arrays that centralizes the IDs and processing flags for mechanisms
1588849c126SEtienne Carriere  * supported by each embedded token. Currently none.
1598849c126SEtienne Carriere  */
1608849c126SEtienne Carriere const struct pkcs11_mechachism_modes token_mechanism[] = {
161*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER),
162*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER),
163*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_CBC_PAD, CKFM_CIPHER),
164*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER),
165*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER),
166*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
167*512cbf1dSJens Wiklander 	TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
1688849c126SEtienne Carriere };
1698849c126SEtienne Carriere 
1708849c126SEtienne Carriere /*
1718849c126SEtienne Carriere  * tee_malloc_mechanism_array - Allocate and fill array of supported mechanisms
1728849c126SEtienne Carriere  * @count: [in] [out] Pointer to number of mechanism IDs in client resource
1738849c126SEtienne Carriere  * Return allocated array of the supported mechanism IDs
1748849c126SEtienne Carriere  *
1758849c126SEtienne Carriere  * Allocates array with 32bit cells mechanism IDs for the supported ones only
1768849c126SEtienne Carriere  * if *@count covers number mechanism IDs exposed.
1778849c126SEtienne Carriere  */
1788849c126SEtienne Carriere uint32_t *tee_malloc_mechanism_list(size_t *out_count)
1798849c126SEtienne Carriere {
1808849c126SEtienne Carriere 	size_t n = 0;
1818849c126SEtienne Carriere 	size_t count = 0;
1828849c126SEtienne Carriere 	uint32_t *array = NULL;
1838849c126SEtienne Carriere 
1848849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(token_mechanism); n++)
1858849c126SEtienne Carriere 		if (token_mechanism[n].flags)
1868849c126SEtienne Carriere 			count++;
1878849c126SEtienne Carriere 
1888849c126SEtienne Carriere 	if (*out_count >= count)
1898849c126SEtienne Carriere 		array = TEE_Malloc(count * sizeof(*array),
1908849c126SEtienne Carriere 				   TEE_USER_MEM_HINT_NO_FILL_ZERO);
1918849c126SEtienne Carriere 
1928849c126SEtienne Carriere 	*out_count = count;
1938849c126SEtienne Carriere 
1948849c126SEtienne Carriere 	if (!array)
1958849c126SEtienne Carriere 		return NULL;
1968849c126SEtienne Carriere 
1978849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) {
1988849c126SEtienne Carriere 		if (token_mechanism[n].flags) {
1998849c126SEtienne Carriere 			count--;
2008849c126SEtienne Carriere 			array[count] = token_mechanism[n].id;
2018849c126SEtienne Carriere 		}
2028849c126SEtienne Carriere 	}
2038849c126SEtienne Carriere 	assert(!count);
2048849c126SEtienne Carriere 
2058849c126SEtienne Carriere 	return array;
2068849c126SEtienne Carriere }
2078849c126SEtienne Carriere 
2088849c126SEtienne Carriere uint32_t mechanism_supported_flags(enum pkcs11_mechanism_id id)
2098849c126SEtienne Carriere {
2108849c126SEtienne Carriere 	size_t n = 0;
2118849c126SEtienne Carriere 
2128849c126SEtienne Carriere 	for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) {
2138849c126SEtienne Carriere 		if (id == token_mechanism[n].id) {
2148849c126SEtienne Carriere 			uint32_t flags = token_mechanism[n].flags;
2158849c126SEtienne Carriere 
2168849c126SEtienne Carriere 			assert(mechanism_flags_complies_pkcs11(id, flags));
2178849c126SEtienne Carriere 			return flags;
2188849c126SEtienne Carriere 		}
2198849c126SEtienne Carriere 	}
2208849c126SEtienne Carriere 
2218849c126SEtienne Carriere 	return 0;
2228849c126SEtienne Carriere }
223*512cbf1dSJens Wiklander 
224*512cbf1dSJens Wiklander void mechanism_supported_key_sizes(uint32_t proc_id, uint32_t *min_key_size,
225*512cbf1dSJens Wiklander 				   uint32_t *max_key_size)
226*512cbf1dSJens Wiklander {
227*512cbf1dSJens Wiklander 	switch (proc_id) {
228*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_KEY_GEN:
229*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
230*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
231*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
232*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
233*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
234*512cbf1dSJens Wiklander 		*min_key_size = 16;
235*512cbf1dSJens Wiklander 		*max_key_size = 32;
236*512cbf1dSJens Wiklander 		break;
237*512cbf1dSJens Wiklander 	default:
238*512cbf1dSJens Wiklander 		*min_key_size = 0;
239*512cbf1dSJens Wiklander 		*max_key_size = 0;
240*512cbf1dSJens Wiklander 		break;
241*512cbf1dSJens Wiklander 	}
242*512cbf1dSJens Wiklander }
243