xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 2ea9746d84bb9c057f85acebf6b1fe87fb0e2f6b)
163f89caaSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
263f89caaSJens Wiklander /*
363f89caaSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
463f89caaSJens Wiklander  */
563f89caaSJens Wiklander 
663f89caaSJens Wiklander #include <assert.h>
7bcac2127SMarouene Boubakri #include <config.h>
863f89caaSJens Wiklander #include <inttypes.h>
97c243321SVesa Jääskeläinen #include <mbedtls/asn1write.h>
107c243321SVesa Jääskeläinen #include <mbedtls/ecp.h>
1145d40bdaSValerii Chubar #include <mbedtls/pk.h>
1263f89caaSJens Wiklander #include <pkcs11_ta.h>
1363f89caaSJens Wiklander #include <stdlib.h>
1463f89caaSJens Wiklander #include <string_ext.h>
1563f89caaSJens Wiklander #include <tee_internal_api_extensions.h>
1663f89caaSJens Wiklander #include <tee_internal_api.h>
176a760c9eSEtienne Carriere #include <trace.h>
1863f89caaSJens Wiklander #include <util.h>
1963f89caaSJens Wiklander 
2063f89caaSJens Wiklander #include "attributes.h"
2163f89caaSJens Wiklander #include "handle.h"
2263f89caaSJens Wiklander #include "pkcs11_attributes.h"
2363f89caaSJens Wiklander #include "pkcs11_helpers.h"
2463f89caaSJens Wiklander #include "pkcs11_token.h"
257c243321SVesa Jääskeläinen #include "processing.h"
2663f89caaSJens Wiklander #include "sanitize_object.h"
2763f89caaSJens Wiklander #include "serializer.h"
2863f89caaSJens Wiklander #include "token_capabilities.h"
2963f89caaSJens Wiklander 
30512cbf1dSJens Wiklander static uint32_t pkcs11_func2ckfm(enum processing_func function)
31512cbf1dSJens Wiklander {
32512cbf1dSJens Wiklander 	switch (function) {
33512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
34512cbf1dSJens Wiklander 		return PKCS11_CKFM_DIGEST;
35512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE:
36512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE;
37512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE_PAIR:
38512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE_KEY_PAIR;
39512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
40512cbf1dSJens Wiklander 		return PKCS11_CKFM_DERIVE;
41512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
42512cbf1dSJens Wiklander 		return PKCS11_CKFM_WRAP;
43512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
44512cbf1dSJens Wiklander 		return PKCS11_CKFM_UNWRAP;
45512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
46512cbf1dSJens Wiklander 		return PKCS11_CKFM_ENCRYPT;
47512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
48512cbf1dSJens Wiklander 		return PKCS11_CKFM_DECRYPT;
49512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
50512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN;
51512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
52512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY;
53512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
54512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN_RECOVER;
55512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
56512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY_RECOVER;
57512cbf1dSJens Wiklander 	default:
58512cbf1dSJens Wiklander 		return 0;
59512cbf1dSJens Wiklander 	}
60512cbf1dSJens Wiklander }
61512cbf1dSJens Wiklander 
62512cbf1dSJens Wiklander enum pkcs11_rc
63512cbf1dSJens Wiklander check_mechanism_against_processing(struct pkcs11_session *session,
64512cbf1dSJens Wiklander 				   enum pkcs11_mechanism_id mechanism_type,
65512cbf1dSJens Wiklander 				   enum processing_func function,
66512cbf1dSJens Wiklander 				   enum processing_step step)
67512cbf1dSJens Wiklander {
68512cbf1dSJens Wiklander 	bool allowed = false;
69512cbf1dSJens Wiklander 
70512cbf1dSJens Wiklander 	switch (step) {
71512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_INIT:
72512cbf1dSJens Wiklander 		switch (function) {
73512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_IMPORT:
74512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_COPY:
75512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_MODIFY:
76512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DESTROY:
77512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
78512cbf1dSJens Wiklander 		default:
79512cbf1dSJens Wiklander 			break;
80512cbf1dSJens Wiklander 		}
81512cbf1dSJens Wiklander 		/*
82512cbf1dSJens Wiklander 		 * Check that the returned PKCS11_CKFM_* flag from
83512cbf1dSJens Wiklander 		 * pkcs11_func2ckfm() is among the ones from
84512cbf1dSJens Wiklander 		 * mechanism_supported_flags().
85512cbf1dSJens Wiklander 		 */
86512cbf1dSJens Wiklander 		allowed = mechanism_supported_flags(mechanism_type) &
87512cbf1dSJens Wiklander 			  pkcs11_func2ckfm(function);
88512cbf1dSJens Wiklander 		break;
89512cbf1dSJens Wiklander 
90512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_ONESHOT:
910460a039SRuchika Gupta 		if (session->processing->always_authen &&
920460a039SRuchika Gupta 		    !session->processing->relogged)
930460a039SRuchika Gupta 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
940460a039SRuchika Gupta 
952364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_UPDATE ||
962364aa69SRuchika Gupta 		    session->processing->step == PKCS11_FUNC_STEP_FINAL) {
972364aa69SRuchika Gupta 			EMSG("Cannot perform one-shot on active processing");
980460a039SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
990460a039SRuchika Gupta 		}
1000460a039SRuchika Gupta 
1010460a039SRuchika Gupta 		allowed = true;
1020460a039SRuchika Gupta 		break;
1030460a039SRuchika Gupta 
104512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
105512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
106512cbf1dSJens Wiklander 		    !session->processing->relogged)
107512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
108512cbf1dSJens Wiklander 
1092364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT ||
1102364aa69SRuchika Gupta 		    session->processing->step == PKCS11_FUNC_STEP_FINAL) {
1112364aa69SRuchika Gupta 			EMSG("Cannot perform update on finalized processing");
1122364aa69SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
1132364aa69SRuchika Gupta 		}
1142364aa69SRuchika Gupta 
115512cbf1dSJens Wiklander 		allowed = !mechanism_is_one_shot_only(mechanism_type);
116512cbf1dSJens Wiklander 		break;
117512cbf1dSJens Wiklander 
1189e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
1199e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
1209e91a619SVesa Jääskeläinen 
1219e91a619SVesa Jääskeläinen 		if (session->processing->always_authen &&
1229e91a619SVesa Jääskeläinen 		    !session->processing->relogged)
1239e91a619SVesa Jääskeläinen 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
1249e91a619SVesa Jääskeläinen 
1259e91a619SVesa Jääskeläinen 		allowed = true;
1269e91a619SVesa Jääskeläinen 		break;
1279e91a619SVesa Jääskeläinen 
128512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_FINAL:
129512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
130512cbf1dSJens Wiklander 		    !session->processing->relogged)
131512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
132512cbf1dSJens Wiklander 
1332364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT) {
1342364aa69SRuchika Gupta 			EMSG("Cannot perform final on oneshot processing");
1352364aa69SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
1362364aa69SRuchika Gupta 		}
137512cbf1dSJens Wiklander 		return PKCS11_CKR_OK;
138512cbf1dSJens Wiklander 
139512cbf1dSJens Wiklander 	default:
140512cbf1dSJens Wiklander 		TEE_Panic(step);
141512cbf1dSJens Wiklander 		break;
142512cbf1dSJens Wiklander 	}
143512cbf1dSJens Wiklander 
144512cbf1dSJens Wiklander 	if (!allowed) {
145512cbf1dSJens Wiklander 		EMSG("Processing %#x/%s not permitted (%u/%u)",
146512cbf1dSJens Wiklander 		     (unsigned int)mechanism_type, id2str_proc(mechanism_type),
147512cbf1dSJens Wiklander 		     function, step);
148df705578SRuchika Gupta 		return PKCS11_CKR_MECHANISM_INVALID;
149512cbf1dSJens Wiklander 	}
150512cbf1dSJens Wiklander 
151512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
152512cbf1dSJens Wiklander }
153512cbf1dSJens Wiklander 
15463f89caaSJens Wiklander /*
15563f89caaSJens Wiklander  * Object default boolean attributes as per PKCS#11
15663f89caaSJens Wiklander  */
15763f89caaSJens Wiklander static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute)
15863f89caaSJens Wiklander {
15963f89caaSJens Wiklander 	static const uint8_t bool_true = 1;
16063f89caaSJens Wiklander 	static const uint8_t bool_false;
16163f89caaSJens Wiklander 
16263f89caaSJens Wiklander 	switch (attribute) {
16363f89caaSJens Wiklander 	/* As per PKCS#11 default value */
16463f89caaSJens Wiklander 	case PKCS11_CKA_MODIFIABLE:
16563f89caaSJens Wiklander 	case PKCS11_CKA_COPYABLE:
16663f89caaSJens Wiklander 	case PKCS11_CKA_DESTROYABLE:
16763f89caaSJens Wiklander 		return (uint8_t *)&bool_true;
16863f89caaSJens Wiklander 	case PKCS11_CKA_TOKEN:
16963f89caaSJens Wiklander 	case PKCS11_CKA_PRIVATE:
17039fc24faSEtienne Carriere 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
17139fc24faSEtienne Carriere 	case PKCS11_CKA_ALWAYS_AUTHENTICATE:
17263f89caaSJens Wiklander 	case PKCS11_CKA_SENSITIVE:
17363f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
17463f89caaSJens Wiklander 	/* Token specific default value */
17563f89caaSJens Wiklander 	case PKCS11_CKA_SIGN:
17663f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY:
17763f89caaSJens Wiklander 	case PKCS11_CKA_DERIVE:
17863f89caaSJens Wiklander 	case PKCS11_CKA_ENCRYPT:
17963f89caaSJens Wiklander 	case PKCS11_CKA_DECRYPT:
18063f89caaSJens Wiklander 	case PKCS11_CKA_SIGN_RECOVER:
18163f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY_RECOVER:
18263f89caaSJens Wiklander 	case PKCS11_CKA_WRAP:
18363f89caaSJens Wiklander 	case PKCS11_CKA_UNWRAP:
18463f89caaSJens Wiklander 	case PKCS11_CKA_EXTRACTABLE:
18563f89caaSJens Wiklander 	case PKCS11_CKA_TRUSTED:
18663f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
18763f89caaSJens Wiklander 	default:
18863f89caaSJens Wiklander 		DMSG("No default for boolprop attribute %#"PRIx32, attribute);
18963f89caaSJens Wiklander 		return NULL;
19063f89caaSJens Wiklander 	}
19163f89caaSJens Wiklander }
19263f89caaSJens Wiklander 
19363f89caaSJens Wiklander /*
19463f89caaSJens Wiklander  * Object expects several boolean attributes to be set to a default value
19563f89caaSJens Wiklander  * or to a validate client configuration value. This function append the input
19663f89caaSJens Wiklander  * attribute (id/size/value) in the serialized object.
19763f89caaSJens Wiklander  */
19863f89caaSJens Wiklander static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out,
19963f89caaSJens Wiklander 						    struct obj_attrs *templ,
20063f89caaSJens Wiklander 						    uint32_t attribute)
20163f89caaSJens Wiklander {
20263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
20363f89caaSJens Wiklander 	uint8_t bbool = 0;
20463f89caaSJens Wiklander 	uint32_t size = sizeof(uint8_t);
20563f89caaSJens Wiklander 	void *attr = NULL;
20663f89caaSJens Wiklander 
20763f89caaSJens Wiklander 	rc = get_attribute(templ, attribute, &bbool, &size);
20863f89caaSJens Wiklander 	if (rc) {
20963f89caaSJens Wiklander 		if (rc != PKCS11_RV_NOT_FOUND)
21063f89caaSJens Wiklander 			return rc;
21163f89caaSJens Wiklander 		attr = pkcs11_object_default_boolprop(attribute);
21263f89caaSJens Wiklander 		if (!attr)
21363f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
21463f89caaSJens Wiklander 	} else {
21563f89caaSJens Wiklander 		attr = &bbool;
21663f89caaSJens Wiklander 	}
21763f89caaSJens Wiklander 
21863f89caaSJens Wiklander 	/* Boolean attributes are 1byte in the ABI, no alignment issue */
21963f89caaSJens Wiklander 	return add_attribute(out, attribute, attr, sizeof(uint8_t));
22063f89caaSJens Wiklander }
22163f89caaSJens Wiklander 
22263f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out,
22363f89caaSJens Wiklander 					      struct obj_attrs *temp,
22463f89caaSJens Wiklander 					      uint32_t const *bp,
22563f89caaSJens Wiklander 					      size_t bp_count)
22663f89caaSJens Wiklander {
22763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
22863f89caaSJens Wiklander 	size_t n = 0;
22963f89caaSJens Wiklander 
23063f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
23163f89caaSJens Wiklander 		rc = pkcs11_import_object_boolprop(out, temp, bp[n]);
23263f89caaSJens Wiklander 		if (rc)
23363f89caaSJens Wiklander 			return rc;
23463f89caaSJens Wiklander 	}
23563f89caaSJens Wiklander 
23663f89caaSJens Wiklander 	return rc;
23763f89caaSJens Wiklander }
23863f89caaSJens Wiklander 
23963f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out,
24063f89caaSJens Wiklander 					       struct obj_attrs *temp,
24116df60c7SEtienne Carriere 					       uint32_t const *attrs,
24216df60c7SEtienne Carriere 					       size_t attrs_count)
24363f89caaSJens Wiklander {
24463f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
24563f89caaSJens Wiklander 	size_t n = 0;
24663f89caaSJens Wiklander 
24716df60c7SEtienne Carriere 	for (n = 0; n < attrs_count; n++) {
24863f89caaSJens Wiklander 		uint32_t size = 0;
24963f89caaSJens Wiklander 		void *value = NULL;
25063f89caaSJens Wiklander 
25116df60c7SEtienne Carriere 		if (get_attribute_ptr(temp, attrs[n], &value, &size))
25263f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
25363f89caaSJens Wiklander 
25416df60c7SEtienne Carriere 		rc = add_attribute(out, attrs[n], value, size);
25563f89caaSJens Wiklander 		if (rc)
25663f89caaSJens Wiklander 			return rc;
25763f89caaSJens Wiklander 	}
25863f89caaSJens Wiklander 
25963f89caaSJens Wiklander 	return rc;
26063f89caaSJens Wiklander }
26163f89caaSJens Wiklander 
26263f89caaSJens Wiklander static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value,
26363f89caaSJens Wiklander 					uint32_t *size)
26463f89caaSJens Wiklander {
26563f89caaSJens Wiklander 	/* should have been taken care of already */
26663f89caaSJens Wiklander 	assert(!pkcs11_attr_is_boolean(id));
26763f89caaSJens Wiklander 
26863f89caaSJens Wiklander 	/* All other attributes have an empty default value */
26963f89caaSJens Wiklander 	*value = NULL;
27063f89caaSJens Wiklander 	*size = 0;
27163f89caaSJens Wiklander 	return PKCS11_CKR_OK;
27263f89caaSJens Wiklander }
27363f89caaSJens Wiklander 
2744eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out,
27563f89caaSJens Wiklander 						       struct obj_attrs *temp,
27616df60c7SEtienne Carriere 						       uint32_t const *attrs,
27716df60c7SEtienne Carriere 						       size_t attrs_count,
2784eb88651SRuchika Gupta 						       bool default_to_null)
27963f89caaSJens Wiklander {
28063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
28163f89caaSJens Wiklander 	size_t n = 0;
28263f89caaSJens Wiklander 
28316df60c7SEtienne Carriere 	for (n = 0; n < attrs_count; n++) {
28463f89caaSJens Wiklander 		uint32_t size = 0;
28563f89caaSJens Wiklander 		void *value = NULL;
28663f89caaSJens Wiklander 
28716df60c7SEtienne Carriere 		rc = get_attribute_ptr(temp, attrs[n], &value, &size);
2884eb88651SRuchika Gupta 		if (rc == PKCS11_RV_NOT_FOUND) {
2894eb88651SRuchika Gupta 			if (default_to_null) {
29016df60c7SEtienne Carriere 				rc = get_default_value(attrs[n], &value, &size);
2914eb88651SRuchika Gupta 			} else {
2924eb88651SRuchika Gupta 				rc = PKCS11_CKR_OK;
2934eb88651SRuchika Gupta 				continue;
2944eb88651SRuchika Gupta 			}
2954eb88651SRuchika Gupta 		}
29663f89caaSJens Wiklander 		if (rc)
29763f89caaSJens Wiklander 			return rc;
29863f89caaSJens Wiklander 
29916df60c7SEtienne Carriere 		rc = add_attribute(out, attrs[n], value, size);
30063f89caaSJens Wiklander 		if (rc)
30163f89caaSJens Wiklander 			return rc;
30263f89caaSJens Wiklander 	}
30363f89caaSJens Wiklander 
30463f89caaSJens Wiklander 	return rc;
30563f89caaSJens Wiklander }
30663f89caaSJens Wiklander 
3074eb88651SRuchika Gupta static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out,
3084eb88651SRuchika Gupta 						 struct obj_attrs *temp,
30916df60c7SEtienne Carriere 						 uint32_t const *attrs,
31016df60c7SEtienne Carriere 						 size_t attrs_count)
3114eb88651SRuchika Gupta {
31216df60c7SEtienne Carriere 	return set_optional_attributes_with_def(out, temp, attrs, attrs_count,
31316df60c7SEtienne Carriere 						true /* defaults to empty */);
3144eb88651SRuchika Gupta }
3154eb88651SRuchika Gupta 
3164eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out,
3174eb88651SRuchika Gupta 					      struct obj_attrs *temp,
31816df60c7SEtienne Carriere 					      uint32_t const *attrs,
31916df60c7SEtienne Carriere 					      size_t attrs_count)
3204eb88651SRuchika Gupta {
32116df60c7SEtienne Carriere 	return set_optional_attributes_with_def(out, temp, attrs, attrs_count,
32216df60c7SEtienne Carriere 						false /* no default value */);
3234eb88651SRuchika Gupta }
3244eb88651SRuchika Gupta 
32563f89caaSJens Wiklander /*
32663f89caaSJens Wiklander  * Below are listed the mandated or optional expected attributes for
32763f89caaSJens Wiklander  * PKCS#11 storage objects.
32863f89caaSJens Wiklander  *
32963f89caaSJens Wiklander  * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE,
33063f89caaSJens Wiklander  * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided
33163f89caaSJens Wiklander  * in the client template.
33263f89caaSJens Wiklander  */
33363f89caaSJens Wiklander 
33463f89caaSJens Wiklander /* PKCS#11 specification for any object (session/token) of the storage */
3354eb88651SRuchika Gupta static const uint32_t any_object_boolprops[] = {
33663f89caaSJens Wiklander 	PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
33763f89caaSJens Wiklander 	PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE,
33863f89caaSJens Wiklander };
33963f89caaSJens Wiklander 
3404eb88651SRuchika Gupta static const uint32_t any_object_opt_or_null[] = {
34163f89caaSJens Wiklander 	PKCS11_CKA_LABEL,
34263f89caaSJens Wiklander };
34363f89caaSJens Wiklander 
3444eb88651SRuchika Gupta /* PKCS#11 specification for raw data object (+any_object_xxx) */
3454eb88651SRuchika Gupta const uint32_t raw_data_opt_or_null[] = {
34663f89caaSJens Wiklander 	PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE,
34763f89caaSJens Wiklander };
34863f89caaSJens Wiklander 
3494137952dSVesa Jääskeläinen /* PKCS#11 specification for certificate object (+pkcs11_any_object_xxx) */
3504137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_mandated[] = {
3514137952dSVesa Jääskeläinen 	PKCS11_CKA_CERTIFICATE_TYPE,
3524137952dSVesa Jääskeläinen };
3534137952dSVesa Jääskeläinen 
3544137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_boolprops[] = {
3554137952dSVesa Jääskeläinen 	PKCS11_CKA_TRUSTED,
3564137952dSVesa Jääskeläinen };
3574137952dSVesa Jääskeläinen 
3584137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_optional[] = {
359bcac2127SMarouene Boubakri 	PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_START_DATE,
360bcac2127SMarouene Boubakri 	PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO,
361bcac2127SMarouene Boubakri #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
362bcac2127SMarouene Boubakri 	/* Consider KCV attribute only when supported */
363bcac2127SMarouene Boubakri 	PKCS11_CKA_CHECK_VALUE,
364bcac2127SMarouene Boubakri #endif
3654137952dSVesa Jääskeläinen };
3664137952dSVesa Jääskeläinen 
3674137952dSVesa Jääskeläinen /*
3684137952dSVesa Jääskeläinen  * PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx)
3694137952dSVesa Jääskeläinen  */
3704137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_mandated[] = {
3714137952dSVesa Jääskeläinen 	PKCS11_CKA_SUBJECT,
3724137952dSVesa Jääskeläinen };
3734137952dSVesa Jääskeläinen 
3744137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_optional[] = {
3754137952dSVesa Jääskeläinen 	PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER,
3764137952dSVesa Jääskeläinen 	PKCS11_CKA_VALUE, PKCS11_CKA_URL,
3774137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
3784137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
3794137952dSVesa Jääskeläinen 	PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM,
3804137952dSVesa Jääskeläinen };
3814137952dSVesa Jääskeläinen 
3824eb88651SRuchika Gupta /* PKCS#11 specification for any key object (+any_object_xxx) */
3834eb88651SRuchika Gupta static const uint32_t any_key_boolprops[] = {
38463f89caaSJens Wiklander 	PKCS11_CKA_DERIVE,
38563f89caaSJens Wiklander };
38663f89caaSJens Wiklander 
3874eb88651SRuchika Gupta static const uint32_t any_key_opt_or_null[] = {
38863f89caaSJens Wiklander 	PKCS11_CKA_ID,
38963f89caaSJens Wiklander 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE,
3904eb88651SRuchika Gupta };
3914eb88651SRuchika Gupta 
3924eb88651SRuchika Gupta static const uint32_t any_key_optional[] = {
39363f89caaSJens Wiklander 	PKCS11_CKA_ALLOWED_MECHANISMS,
39463f89caaSJens Wiklander };
39563f89caaSJens Wiklander 
3964eb88651SRuchika Gupta /* PKCS#11 specification for any symmetric key (+any_key_xxx) */
3974eb88651SRuchika Gupta static const uint32_t symm_key_boolprops[] = {
39863f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT,
39963f89caaSJens Wiklander 	PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY,
40063f89caaSJens Wiklander 	PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP,
40163f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
40263f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED,
40363f89caaSJens Wiklander };
40463f89caaSJens Wiklander 
4054eb88651SRuchika Gupta static const uint32_t symm_key_opt_or_null[] = {
40663f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE,
4070ac5c695SRuchika Gupta 	PKCS11_CKA_DERIVE_TEMPLATE, PKCS11_CKA_VALUE,
4080ac5c695SRuchika Gupta };
4090ac5c695SRuchika Gupta 
4100ac5c695SRuchika Gupta static const uint32_t symm_key_optional[] = {
4110ac5c695SRuchika Gupta 	PKCS11_CKA_VALUE_LEN,
412bcac2127SMarouene Boubakri #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
413bcac2127SMarouene Boubakri 	/* Consider KCV attribute only when supported */
414bcac2127SMarouene Boubakri 	PKCS11_CKA_CHECK_VALUE,
415bcac2127SMarouene Boubakri #endif
41663f89caaSJens Wiklander };
41763f89caaSJens Wiklander 
4184eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
4194eb88651SRuchika Gupta static const uint32_t public_key_boolprops[] = {
42063f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER,
42163f89caaSJens Wiklander 	PKCS11_CKA_WRAP,
42263f89caaSJens Wiklander 	PKCS11_CKA_TRUSTED,
42363f89caaSJens Wiklander };
42463f89caaSJens Wiklander 
4254eb88651SRuchika Gupta static const uint32_t public_key_mandated[] = {
42663f89caaSJens Wiklander };
42763f89caaSJens Wiklander 
4284eb88651SRuchika Gupta static const uint32_t public_key_opt_or_null[] = {
429edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_WRAP_TEMPLATE,
430edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
43163f89caaSJens Wiklander };
43263f89caaSJens Wiklander 
4334eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */
4344eb88651SRuchika Gupta static const uint32_t private_key_boolprops[] = {
43563f89caaSJens Wiklander 	PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER,
43663f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP,
43763f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
43863f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE,
43963f89caaSJens Wiklander };
44063f89caaSJens Wiklander 
4414eb88651SRuchika Gupta static const uint32_t private_key_mandated[] = {
44263f89caaSJens Wiklander };
44363f89caaSJens Wiklander 
4444eb88651SRuchika Gupta static const uint32_t private_key_opt_or_null[] = {
445edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_UNWRAP_TEMPLATE,
446edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
44763f89caaSJens Wiklander };
44863f89caaSJens Wiklander 
4494eb88651SRuchika Gupta /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */
4509cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_mand[] = {
45163f89caaSJens Wiklander 	PKCS11_CKA_MODULUS_BITS,
45263f89caaSJens Wiklander };
45363f89caaSJens Wiklander 
4549cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_create_mand[] = {
45563f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
45663f89caaSJens Wiklander };
45763f89caaSJens Wiklander 
4589cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_opt_or_null[] = {
4599cf1afceSVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_EXPONENT,
4609cf1afceSVesa Jääskeläinen };
4619cf1afceSVesa Jääskeläinen 
4629cf1afceSVesa Jääskeläinen static const uint32_t rsa_priv_key_opt_or_null[] = {
46363f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
46463f89caaSJens Wiklander 	PKCS11_CKA_PRIVATE_EXPONENT,
46563f89caaSJens Wiklander 	PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2,
46663f89caaSJens Wiklander 	PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT,
46763f89caaSJens Wiklander };
46863f89caaSJens Wiklander 
4694eb88651SRuchika Gupta /* PKCS#11 specification for any EC key (+public/private_key_xxx) */
4704eb88651SRuchika Gupta static const uint32_t ec_public_key_mandated[] = {
47163f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
47263f89caaSJens Wiklander };
47363f89caaSJens Wiklander 
4744eb88651SRuchika Gupta static const uint32_t ec_public_key_opt_or_null[] = {
47563f89caaSJens Wiklander 	PKCS11_CKA_EC_POINT,
47663f89caaSJens Wiklander };
47763f89caaSJens Wiklander 
4784eb88651SRuchika Gupta static const uint32_t ec_private_key_mandated[] = {
47963f89caaSJens Wiklander };
48063f89caaSJens Wiklander 
4814eb88651SRuchika Gupta static const uint32_t ec_private_key_opt_or_null[] = {
48202b16804SVesa Jääskeläinen 	PKCS11_CKA_EC_PARAMS,
48363f89caaSJens Wiklander 	PKCS11_CKA_VALUE,
48463f89caaSJens Wiklander };
48563f89caaSJens Wiklander 
48603e07432SValerii Chubar static const uint32_t eddsa_private_key_opt_or_null[] = {
48703e07432SValerii Chubar 	PKCS11_CKA_EC_PARAMS,
48803e07432SValerii Chubar 	PKCS11_CKA_VALUE,
48903e07432SValerii Chubar 	PKCS11_CKA_EC_POINT,
49003e07432SValerii Chubar };
49103e07432SValerii Chubar 
49263f89caaSJens Wiklander static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out,
49363f89caaSJens Wiklander 						struct obj_attrs *temp)
49463f89caaSJens Wiklander {
49563f89caaSJens Wiklander 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
49663f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
49763f89caaSJens Wiklander 
49863f89caaSJens Wiklander 	rc = init_attributes_head(out);
49963f89caaSJens Wiklander 	if (rc)
50063f89caaSJens Wiklander 		return rc;
50163f89caaSJens Wiklander 
50263f89caaSJens Wiklander 	/* Object class is mandatory */
50363f89caaSJens Wiklander 	class = get_class(temp);
50463f89caaSJens Wiklander 	if (class == PKCS11_CKO_UNDEFINED_ID) {
50563f89caaSJens Wiklander 		EMSG("Class attribute not found");
50663f89caaSJens Wiklander 
50763f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
50863f89caaSJens Wiklander 	}
50963f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t));
51063f89caaSJens Wiklander 	if (rc)
51163f89caaSJens Wiklander 		return rc;
51263f89caaSJens Wiklander 
5134eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_object_boolprops,
5144eb88651SRuchika Gupta 				     ARRAY_SIZE(any_object_boolprops));
51563f89caaSJens Wiklander 	if (rc)
51663f89caaSJens Wiklander 		return rc;
51763f89caaSJens Wiklander 
5184eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, any_object_opt_or_null,
5194eb88651SRuchika Gupta 					  ARRAY_SIZE(any_object_opt_or_null));
52063f89caaSJens Wiklander }
52163f89caaSJens Wiklander 
52263f89caaSJens Wiklander static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out,
52363f89caaSJens Wiklander 					       struct obj_attrs *temp)
52463f89caaSJens Wiklander {
52563f89caaSJens Wiklander 	uint32_t type = PKCS11_CKO_UNDEFINED_ID;
52663f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
52763f89caaSJens Wiklander 
52863f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
52963f89caaSJens Wiklander 	if (rc)
53063f89caaSJens Wiklander 		return rc;
53163f89caaSJens Wiklander 
53263f89caaSJens Wiklander 	type = get_key_type(temp);
53363f89caaSJens Wiklander 	if (type == PKCS11_CKK_UNDEFINED_ID) {
53463f89caaSJens Wiklander 		EMSG("Key type attribute not found");
53563f89caaSJens Wiklander 
53663f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
53763f89caaSJens Wiklander 	}
53863f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t));
53963f89caaSJens Wiklander 	if (rc)
54063f89caaSJens Wiklander 		return rc;
54163f89caaSJens Wiklander 
5424eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_key_boolprops,
5434eb88651SRuchika Gupta 				     ARRAY_SIZE(any_key_boolprops));
54463f89caaSJens Wiklander 	if (rc)
54563f89caaSJens Wiklander 		return rc;
54663f89caaSJens Wiklander 
5474eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null,
5484eb88651SRuchika Gupta 					ARRAY_SIZE(any_key_opt_or_null));
5494eb88651SRuchika Gupta 	if (rc)
5504eb88651SRuchika Gupta 		return rc;
5514eb88651SRuchika Gupta 
5524eb88651SRuchika Gupta 	return set_optional_attributes(out, temp, any_key_optional,
5534eb88651SRuchika Gupta 				       ARRAY_SIZE(any_key_optional));
5544eb88651SRuchika Gupta 
55563f89caaSJens Wiklander }
55663f89caaSJens Wiklander 
55763f89caaSJens Wiklander static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out,
55863f89caaSJens Wiklander 						 struct obj_attrs *temp)
55963f89caaSJens Wiklander {
56063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
56163f89caaSJens Wiklander 
56263f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_SECRET_KEY);
56363f89caaSJens Wiklander 
56463f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
56563f89caaSJens Wiklander 	if (rc)
56663f89caaSJens Wiklander 		return rc;
56763f89caaSJens Wiklander 
56863f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_SECRET_KEY);
56963f89caaSJens Wiklander 
57063f89caaSJens Wiklander 	switch (get_key_type(*out)) {
57163f89caaSJens Wiklander 	case PKCS11_CKK_GENERIC_SECRET:
57263f89caaSJens Wiklander 	case PKCS11_CKK_AES:
57363f89caaSJens Wiklander 	case PKCS11_CKK_MD5_HMAC:
57463f89caaSJens Wiklander 	case PKCS11_CKK_SHA_1_HMAC:
57563f89caaSJens Wiklander 	case PKCS11_CKK_SHA256_HMAC:
57663f89caaSJens Wiklander 	case PKCS11_CKK_SHA384_HMAC:
57763f89caaSJens Wiklander 	case PKCS11_CKK_SHA512_HMAC:
57863f89caaSJens Wiklander 	case PKCS11_CKK_SHA224_HMAC:
57963f89caaSJens Wiklander 		break;
58063f89caaSJens Wiklander 	default:
58163f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
58263f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
58363f89caaSJens Wiklander 
58463f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
58563f89caaSJens Wiklander 	}
58663f89caaSJens Wiklander 
5874eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, symm_key_boolprops,
5884eb88651SRuchika Gupta 				     ARRAY_SIZE(symm_key_boolprops));
58963f89caaSJens Wiklander 	if (rc)
59063f89caaSJens Wiklander 		return rc;
59163f89caaSJens Wiklander 
5920ac5c695SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, symm_key_opt_or_null,
5934eb88651SRuchika Gupta 					ARRAY_SIZE(symm_key_opt_or_null));
5940ac5c695SRuchika Gupta 	if (rc)
5950ac5c695SRuchika Gupta 		return rc;
5960ac5c695SRuchika Gupta 
5970ac5c695SRuchika Gupta 	return set_optional_attributes(out, temp, symm_key_optional,
5980ac5c695SRuchika Gupta 				       ARRAY_SIZE(symm_key_optional));
59963f89caaSJens Wiklander }
60063f89caaSJens Wiklander 
60163f89caaSJens Wiklander static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
60263f89caaSJens Wiklander 					     struct obj_attrs *temp)
60363f89caaSJens Wiklander {
60463f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
60563f89caaSJens Wiklander 
60663f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_DATA);
60763f89caaSJens Wiklander 
60863f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
60963f89caaSJens Wiklander 	if (rc)
61063f89caaSJens Wiklander 		return rc;
61163f89caaSJens Wiklander 
61263f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_DATA);
61363f89caaSJens Wiklander 
6144eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null,
6154eb88651SRuchika Gupta 					  ARRAY_SIZE(raw_data_opt_or_null));
61663f89caaSJens Wiklander }
61763f89caaSJens Wiklander 
6184137952dSVesa Jääskeläinen static enum pkcs11_rc create_certificate_attributes(struct obj_attrs **out,
6194137952dSVesa Jääskeläinen 						    struct obj_attrs *temp)
6204137952dSVesa Jääskeläinen {
6214137952dSVesa Jääskeläinen 	uint32_t const *mandated = NULL;
6224137952dSVesa Jääskeläinen 	uint32_t const *optional = NULL;
6234137952dSVesa Jääskeläinen 	size_t mandated_count = 0;
6244137952dSVesa Jääskeläinen 	size_t optional_count = 0;
6254137952dSVesa Jääskeläinen 	void *attr_value = NULL;
6264137952dSVesa Jääskeläinen 	uint32_t attr_size = 0;
6274137952dSVesa Jääskeläinen 	uint32_t default_cert_category =
6284137952dSVesa Jääskeläinen 		PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED;
6294137952dSVesa Jääskeläinen 	uint32_t default_name_hash_alg = PKCS11_CKM_SHA_1;
6304137952dSVesa Jääskeläinen 	uint32_t cert_category = 0;
6314137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
6324137952dSVesa Jääskeläinen 
6334137952dSVesa Jääskeläinen 	assert(get_class(temp) == PKCS11_CKO_CERTIFICATE);
6344137952dSVesa Jääskeläinen 
6354137952dSVesa Jääskeläinen 	rc = create_storage_attributes(out, temp);
6364137952dSVesa Jääskeläinen 	if (rc)
6374137952dSVesa Jääskeläinen 		return rc;
6384137952dSVesa Jääskeläinen 
6394137952dSVesa Jääskeläinen 	assert(get_class(*out) == PKCS11_CKO_CERTIFICATE);
6404137952dSVesa Jääskeläinen 
6414137952dSVesa Jääskeläinen 	rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops,
6424137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_boolprops));
6434137952dSVesa Jääskeläinen 	if (rc)
6444137952dSVesa Jääskeläinen 		return rc;
6454137952dSVesa Jääskeläinen 
6464137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated,
6474137952dSVesa Jääskeläinen 				      ARRAY_SIZE(pkcs11_certificate_mandated));
6484137952dSVesa Jääskeläinen 	if (rc)
6494137952dSVesa Jääskeläinen 		return rc;
6504137952dSVesa Jääskeläinen 
6514137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, pkcs11_certificate_optional,
6524137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_optional));
6534137952dSVesa Jääskeläinen 	if (rc)
6544137952dSVesa Jääskeläinen 		return rc;
6554137952dSVesa Jääskeläinen 
6564137952dSVesa Jääskeläinen 	switch (get_certificate_type(*out)) {
6574137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
6584137952dSVesa Jääskeläinen 		mandated = pkcs11_x509_certificate_mandated;
6594137952dSVesa Jääskeläinen 		optional = pkcs11_x509_certificate_optional;
6604137952dSVesa Jääskeläinen 		mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated);
6614137952dSVesa Jääskeläinen 		optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional);
6624137952dSVesa Jääskeläinen 		break;
6634137952dSVesa Jääskeläinen 	default:
6644137952dSVesa Jääskeläinen 		EMSG("Invalid certificate type %#"PRIx32"/%s",
6654137952dSVesa Jääskeläinen 		     get_certificate_type(*out),
6664137952dSVesa Jääskeläinen 		     id2str_certificate_type(get_certificate_type(*out)));
6674137952dSVesa Jääskeläinen 
6684137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
6694137952dSVesa Jääskeläinen 	}
6704137952dSVesa Jääskeläinen 
6714137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
6724137952dSVesa Jääskeläinen 	if (rc)
6734137952dSVesa Jääskeläinen 		return rc;
6744137952dSVesa Jääskeläinen 
6754137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, optional, optional_count);
6764137952dSVesa Jääskeläinen 	if (rc)
6774137952dSVesa Jääskeläinen 		return rc;
6784137952dSVesa Jääskeläinen 
6794137952dSVesa Jääskeläinen 	attr_size = 0;
6804137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY,
6814137952dSVesa Jääskeläinen 			       &attr_value, &attr_size);
6824137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(cert_category)) {
6834137952dSVesa Jääskeläinen 		/* Sanitize certificate category */
6844137952dSVesa Jääskeläinen 		TEE_MemMove(&cert_category, attr_value, sizeof(cert_category));
6854137952dSVesa Jääskeläinen 
6864137952dSVesa Jääskeläinen 		switch (cert_category) {
6874137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED:
6884137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER:
6894137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY:
6904137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY:
6914137952dSVesa Jääskeläinen 			break;
6924137952dSVesa Jääskeläinen 		default:
6934137952dSVesa Jääskeläinen 			EMSG("Invalid certificate category %#"PRIx32,
6944137952dSVesa Jääskeläinen 			     cert_category);
6954137952dSVesa Jääskeläinen 
6964137952dSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
6974137952dSVesa Jääskeläinen 		}
6984137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
6994137952dSVesa Jääskeläinen 		/* Set default category when missing */
7004137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY,
7014137952dSVesa Jääskeläinen 				   &default_cert_category,
7024137952dSVesa Jääskeläinen 				   sizeof(default_cert_category));
7034137952dSVesa Jääskeläinen 		if (rc)
7044137952dSVesa Jääskeläinen 			return rc;
7054137952dSVesa Jääskeläinen 	} else {
7064137952dSVesa Jääskeläinen 		/* All other cases are errors */
7074137952dSVesa Jääskeläinen 		EMSG("Invalid certificate category");
7084137952dSVesa Jääskeläinen 
7094137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7104137952dSVesa Jääskeläinen 	}
7114137952dSVesa Jääskeläinen 
7124137952dSVesa Jääskeläinen 	attr_size = 0;
7134137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL,
7144137952dSVesa Jääskeläinen 			       &attr_size);
7154137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(uint32_t)) {
7164137952dSVesa Jääskeläinen 		/* We accept any algorithm what caller wanted to specify */
7174137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
7184137952dSVesa Jääskeläinen 		/* Set default hash algorithm when missing */
7194137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM,
7204137952dSVesa Jääskeläinen 				   &default_name_hash_alg,
7214137952dSVesa Jääskeläinen 				   sizeof(default_name_hash_alg));
7224137952dSVesa Jääskeläinen 		if (rc)
7234137952dSVesa Jääskeläinen 			return rc;
7244137952dSVesa Jääskeläinen 	} else {
7254137952dSVesa Jääskeläinen 		/* All other cases are errors */
7264137952dSVesa Jääskeläinen 		EMSG("Invalid name hash algorithm");
7274137952dSVesa Jääskeläinen 
7284137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7294137952dSVesa Jääskeläinen 	}
7304137952dSVesa Jääskeläinen 
7314137952dSVesa Jääskeläinen 	return rc;
7324137952dSVesa Jääskeläinen }
7334137952dSVesa Jääskeläinen 
73463f89caaSJens Wiklander static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
7359cf1afceSVesa Jääskeläinen 						struct obj_attrs *temp,
7369cf1afceSVesa Jääskeläinen 						enum processing_func function)
73763f89caaSJens Wiklander {
73863f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
7399cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
74063f89caaSJens Wiklander 	size_t mandated_count = 0;
7419cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
74263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
74363f89caaSJens Wiklander 
74463f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY);
74563f89caaSJens Wiklander 
74663f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
74763f89caaSJens Wiklander 	if (rc)
74863f89caaSJens Wiklander 		return rc;
74963f89caaSJens Wiklander 
75063f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY);
75163f89caaSJens Wiklander 
7524eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, public_key_boolprops,
7534eb88651SRuchika Gupta 				     ARRAY_SIZE(public_key_boolprops));
75463f89caaSJens Wiklander 	if (rc)
75563f89caaSJens Wiklander 		return rc;
75663f89caaSJens Wiklander 
7574eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, public_key_mandated,
7584eb88651SRuchika Gupta 				      ARRAY_SIZE(public_key_mandated));
75963f89caaSJens Wiklander 	if (rc)
76063f89caaSJens Wiklander 		return rc;
76163f89caaSJens Wiklander 
7624eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp,
7634eb88651SRuchika Gupta 					public_key_opt_or_null,
7644eb88651SRuchika Gupta 					ARRAY_SIZE(public_key_opt_or_null));
76563f89caaSJens Wiklander 	if (rc)
76663f89caaSJens Wiklander 		return rc;
76763f89caaSJens Wiklander 
76863f89caaSJens Wiklander 	switch (get_key_type(*out)) {
76963f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
7709cf1afceSVesa Jääskeläinen 		switch (function) {
7719cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
7729cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_gen_mand;
7739cf1afceSVesa Jääskeläinen 			oon = rsa_pub_key_gen_opt_or_null;
7749cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_gen_mand);
7759cf1afceSVesa Jääskeläinen 			oon_count = ARRAY_SIZE(rsa_pub_key_gen_opt_or_null);
7769cf1afceSVesa Jääskeläinen 			break;
7779cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_IMPORT:
7789cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_create_mand;
7799cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_create_mand);
7809cf1afceSVesa Jääskeläinen 			break;
7819cf1afceSVesa Jääskeläinen 		default:
7829cf1afceSVesa Jääskeläinen 			EMSG("Unsupported function %#"PRIx32"/%s", function,
7839cf1afceSVesa Jääskeläinen 			     id2str_function(function));
7849cf1afceSVesa Jääskeläinen 
7859cf1afceSVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7869cf1afceSVesa Jääskeläinen 		}
78763f89caaSJens Wiklander 		break;
78863f89caaSJens Wiklander 	case PKCS11_CKK_EC:
78903e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
7904eb88651SRuchika Gupta 		mandated = ec_public_key_mandated;
7919cf1afceSVesa Jääskeläinen 		oon = ec_public_key_opt_or_null;
7924eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_public_key_mandated);
7939cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_public_key_opt_or_null);
79463f89caaSJens Wiklander 		break;
79563f89caaSJens Wiklander 	default:
79663f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
79763f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
79863f89caaSJens Wiklander 
79963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
80063f89caaSJens Wiklander 	}
80163f89caaSJens Wiklander 
80263f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
80363f89caaSJens Wiklander 	if (rc)
80463f89caaSJens Wiklander 		return rc;
80563f89caaSJens Wiklander 
8069cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
80763f89caaSJens Wiklander }
80863f89caaSJens Wiklander 
8095071d7d1SVesa Jääskeläinen static enum pkcs11_rc
8105071d7d1SVesa Jääskeläinen create_pub_key_rsa_generated_attributes(struct obj_attrs **out,
8115071d7d1SVesa Jääskeläinen 					struct obj_attrs *temp,
8125071d7d1SVesa Jääskeläinen 					enum processing_func function)
8135071d7d1SVesa Jääskeläinen {
8145071d7d1SVesa Jääskeläinen 	uint32_t key_bits = 0;
8155071d7d1SVesa Jääskeläinen 	void *a_ptr = NULL;
8165071d7d1SVesa Jääskeläinen 	uint32_t a_size = 0;
8175071d7d1SVesa Jääskeläinen 
8185071d7d1SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
8195071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_OK;
8205071d7d1SVesa Jääskeläinen 
8215071d7d1SVesa Jääskeläinen 	/* Calculate CKA_MODULUS_BITS */
8225071d7d1SVesa Jääskeläinen 
8235071d7d1SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_MODULUS,
8245071d7d1SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
8255071d7d1SVesa Jääskeläinen 		EMSG("No CKA_MODULUS attribute found in public key");
8265071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
8275071d7d1SVesa Jääskeläinen 	}
8285071d7d1SVesa Jääskeläinen 
8295071d7d1SVesa Jääskeläinen 	key_bits = a_size * 8;
8305071d7d1SVesa Jääskeläinen 
8315071d7d1SVesa Jääskeläinen 	return add_attribute(out, PKCS11_CKA_MODULUS_BITS, &key_bits,
8325071d7d1SVesa Jääskeläinen 			     sizeof(key_bits));
8335071d7d1SVesa Jääskeläinen }
8345071d7d1SVesa Jääskeläinen 
8355071d7d1SVesa Jääskeläinen static enum pkcs11_rc
8365071d7d1SVesa Jääskeläinen create_pub_key_generated_attributes(struct obj_attrs **out,
8375071d7d1SVesa Jääskeläinen 				    struct obj_attrs *temp,
8385071d7d1SVesa Jääskeläinen 				    enum processing_func function)
8395071d7d1SVesa Jääskeläinen {
8405071d7d1SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
8415071d7d1SVesa Jääskeläinen 
8425071d7d1SVesa Jääskeläinen 	switch (get_key_type(*out)) {
8435071d7d1SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
8445071d7d1SVesa Jääskeläinen 		rc = create_pub_key_rsa_generated_attributes(out, temp,
8455071d7d1SVesa Jääskeläinen 							     function);
8465071d7d1SVesa Jääskeläinen 		break;
8475071d7d1SVesa Jääskeläinen 	default:
8485071d7d1SVesa Jääskeläinen 		/* no-op */
8495071d7d1SVesa Jääskeläinen 		break;
8505071d7d1SVesa Jääskeläinen 	}
8515071d7d1SVesa Jääskeläinen 
8525071d7d1SVesa Jääskeläinen 	return rc;
8535071d7d1SVesa Jääskeläinen }
8545071d7d1SVesa Jääskeläinen 
85563f89caaSJens Wiklander static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out,
85663f89caaSJens Wiklander 						 struct obj_attrs *temp)
85763f89caaSJens Wiklander {
85863f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
8599cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
86063f89caaSJens Wiklander 	size_t mandated_count = 0;
8619cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
86263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
86363f89caaSJens Wiklander 
86463f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY);
86563f89caaSJens Wiklander 
86663f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
86763f89caaSJens Wiklander 	if (rc)
86863f89caaSJens Wiklander 		return rc;
86963f89caaSJens Wiklander 
87063f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY);
87163f89caaSJens Wiklander 
8724eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, private_key_boolprops,
8734eb88651SRuchika Gupta 				     ARRAY_SIZE(private_key_boolprops));
87463f89caaSJens Wiklander 	if (rc)
87563f89caaSJens Wiklander 		return rc;
87663f89caaSJens Wiklander 
8774eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, private_key_mandated,
8784eb88651SRuchika Gupta 				      ARRAY_SIZE(private_key_mandated));
87963f89caaSJens Wiklander 	if (rc)
88063f89caaSJens Wiklander 		return rc;
88163f89caaSJens Wiklander 
8824eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null,
8834eb88651SRuchika Gupta 					ARRAY_SIZE(private_key_opt_or_null));
88463f89caaSJens Wiklander 	if (rc)
88563f89caaSJens Wiklander 		return rc;
88663f89caaSJens Wiklander 
88763f89caaSJens Wiklander 	switch (get_key_type(*out)) {
88863f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
8899cf1afceSVesa Jääskeläinen 		oon = rsa_priv_key_opt_or_null;
8909cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(rsa_priv_key_opt_or_null);
89163f89caaSJens Wiklander 		break;
89263f89caaSJens Wiklander 	case PKCS11_CKK_EC:
8934eb88651SRuchika Gupta 		mandated = ec_private_key_mandated;
8949cf1afceSVesa Jääskeläinen 		oon = ec_private_key_opt_or_null;
8954eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
8969cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_private_key_opt_or_null);
89763f89caaSJens Wiklander 		break;
89803e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
89903e07432SValerii Chubar 		mandated = ec_private_key_mandated;
90003e07432SValerii Chubar 		oon = eddsa_private_key_opt_or_null;
90103e07432SValerii Chubar 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
90203e07432SValerii Chubar 		oon_count = ARRAY_SIZE(eddsa_private_key_opt_or_null);
90303e07432SValerii Chubar 		break;
90463f89caaSJens Wiklander 	default:
90563f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
90663f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
90763f89caaSJens Wiklander 
90863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
90963f89caaSJens Wiklander 	}
91063f89caaSJens Wiklander 
91163f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
91263f89caaSJens Wiklander 	if (rc)
91363f89caaSJens Wiklander 		return rc;
91463f89caaSJens Wiklander 
9159cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
91663f89caaSJens Wiklander }
91763f89caaSJens Wiklander 
91832b31808SJens Wiklander static int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len)
91932b31808SJens Wiklander {
92032b31808SJens Wiklander 	TEE_GenerateRandom(output, len);
92132b31808SJens Wiklander 	return 0;
92232b31808SJens Wiklander }
92332b31808SJens Wiklander 
924196bcd93SRuchika Gupta static enum pkcs11_rc
9257c243321SVesa Jääskeläinen create_ec_priv_key_hidden_attributes(struct obj_attrs **out,
9267c243321SVesa Jääskeläinen 				     struct obj_attrs *temp,
9277c243321SVesa Jääskeläinen 				     enum processing_func function)
9287c243321SVesa Jääskeläinen {
9297c243321SVesa Jääskeläinen 	struct mbedtls_ecp_keypair key_pair = { };
9307c243321SVesa Jääskeläinen 	mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE;
93132b31808SJens Wiklander 	mbedtls_ecp_group key_pair_grp = { };
93232b31808SJens Wiklander 	mbedtls_ecp_point key_pair_Q = { };
93332b31808SJens Wiklander 	mbedtls_mpi key_pair_d = { };
9347c243321SVesa Jääskeläinen 	size_t buflen = 0;
9357c243321SVesa Jääskeläinen 	uint8_t *buf = NULL;
9367c243321SVesa Jääskeläinen 	size_t asnbuflen = 0;
9377c243321SVesa Jääskeläinen 	uint8_t *asnbuf = NULL;
9387c243321SVesa Jääskeläinen 	uint8_t *ptr = NULL;
9397c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
9407c243321SVesa Jääskeläinen 	int tee_size = 0;
9417c243321SVesa Jääskeläinen 	int tee_curve = 0;
9427c243321SVesa Jääskeläinen 	void *a_ptr = NULL;
9437c243321SVesa Jääskeläinen 	uint32_t a_size = 0;
9447c243321SVesa Jääskeläinen 	int ret = 0;
9457c243321SVesa Jääskeläinen 
9467c243321SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
9477c243321SVesa Jääskeläinen 		return PKCS11_CKR_OK;
9487c243321SVesa Jääskeläinen 
9497c243321SVesa Jääskeläinen 	/*
9507c243321SVesa Jääskeläinen 	 * TEE internal API requires that for private key operations there
9517c243321SVesa Jääskeläinen 	 * needs to be also public key available.
9527c243321SVesa Jääskeläinen 	 *
9537c243321SVesa Jääskeläinen 	 * Generate hidden EC point from private key.
9547c243321SVesa Jääskeläinen 	 */
9557c243321SVesa Jääskeläinen 
9567c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS,
9577c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9587c243321SVesa Jääskeläinen 		EMSG("No EC_PARAMS attribute found in private key");
9597c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9607c243321SVesa Jääskeläinen 	}
9617c243321SVesa Jääskeläinen 
9627c243321SVesa Jääskeläinen 	/* Just valdiate that curve is found */
9637c243321SVesa Jääskeläinen 	tee_size = ec_params2tee_keysize(a_ptr, a_size);
9647c243321SVesa Jääskeläinen 	if (!tee_size) {
9657c243321SVesa Jääskeläinen 		EMSG("Unsupported EC_PARAMS curve");
9667c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9677c243321SVesa Jääskeläinen 	}
9687c243321SVesa Jääskeläinen 
9697c243321SVesa Jääskeläinen 	tee_curve = ec_params2tee_curve(a_ptr, a_size);
9707c243321SVesa Jääskeläinen 
9717c243321SVesa Jääskeläinen 	switch (tee_curve) {
9727c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P192:
9737c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP192R1;
9747c243321SVesa Jääskeläinen 		break;
9757c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P224:
9767c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP224R1;
9777c243321SVesa Jääskeläinen 		break;
9787c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P256:
9797c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP256R1;
9807c243321SVesa Jääskeläinen 		break;
9817c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P384:
9827c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP384R1;
9837c243321SVesa Jääskeläinen 		break;
9847c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P521:
9857c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP521R1;
9867c243321SVesa Jääskeläinen 		break;
9877c243321SVesa Jääskeläinen 	default:
9887c243321SVesa Jääskeläinen 		EMSG("Failed to map EC_PARAMS to supported curve");
9897c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9907c243321SVesa Jääskeläinen 	}
9917c243321SVesa Jääskeläinen 
9927c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_VALUE,
9937c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9947c243321SVesa Jääskeläinen 		EMSG("No VALUE attribute found in private key");
9957c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9967c243321SVesa Jääskeläinen 	}
9977c243321SVesa Jääskeläinen 
9987c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_init(&key_pair);
99932b31808SJens Wiklander 	mbedtls_ecp_group_init(&key_pair_grp);
100032b31808SJens Wiklander 	mbedtls_mpi_init(&key_pair_d);
100132b31808SJens Wiklander 	mbedtls_ecp_point_init(&key_pair_Q);
10027c243321SVesa Jääskeläinen 
10037c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size);
10047c243321SVesa Jääskeläinen 	if (ret) {
10057c243321SVesa Jääskeläinen 		EMSG("Failed to parse CKA_VALUE");
10067c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
10077c243321SVesa Jääskeläinen 		goto out;
10087c243321SVesa Jääskeläinen 	}
10097c243321SVesa Jääskeläinen 
101032b31808SJens Wiklander 	ret = mbedtls_ecp_export(&key_pair, &key_pair_grp, &key_pair_d,
101132b31808SJens Wiklander 				 &key_pair_Q);
101232b31808SJens Wiklander 	if (ret) {
101332b31808SJens Wiklander 		EMSG("Failed to export key");
101432b31808SJens Wiklander 		goto out;
101532b31808SJens Wiklander 	}
101632b31808SJens Wiklander 
101732b31808SJens Wiklander 	ret = mbedtls_ecp_mul(&key_pair_grp, &key_pair_Q, &key_pair_d,
101832b31808SJens Wiklander 			      &key_pair_grp.G, mbd_rand, NULL);
10197c243321SVesa Jääskeläinen 	if (ret) {
10207c243321SVesa Jääskeläinen 		EMSG("Failed to create public key");
10217c243321SVesa Jääskeläinen 		goto out;
10227c243321SVesa Jääskeläinen 	}
10237c243321SVesa Jääskeläinen 
102432b31808SJens Wiklander 	ret = mbedtls_ecp_check_privkey(&key_pair_grp, &key_pair_d);
10257c243321SVesa Jääskeläinen 	if (ret) {
10267c243321SVesa Jääskeläinen 		EMSG("Failed to verify private key");
10277c243321SVesa Jääskeläinen 		goto out;
10287c243321SVesa Jääskeläinen 	}
10297c243321SVesa Jääskeläinen 
103032b31808SJens Wiklander 	ret = mbedtls_ecp_check_pubkey(&key_pair_grp, &key_pair_Q);
10317c243321SVesa Jääskeläinen 	if (ret) {
10327c243321SVesa Jääskeläinen 		EMSG("Failed to verify public key");
10337c243321SVesa Jääskeläinen 		goto out;
10347c243321SVesa Jääskeläinen 	}
10357c243321SVesa Jääskeläinen 
103632b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10377c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10387c243321SVesa Jääskeläinen 					     &buflen, NULL, 0);
10397c243321SVesa Jääskeläinen 	if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
10407c243321SVesa Jääskeläinen 		EMSG("Failed to determine size of binary public key");
10417c243321SVesa Jääskeläinen 		goto out;
10427c243321SVesa Jääskeläinen 	}
10437c243321SVesa Jääskeläinen 
10447c243321SVesa Jääskeläinen 	buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO);
10457c243321SVesa Jääskeläinen 	if (!buf) {
10467c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10477c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10487c243321SVesa Jääskeläinen 		goto out;
10497c243321SVesa Jääskeläinen 	}
10507c243321SVesa Jääskeläinen 
10517c243321SVesa Jääskeläinen 	asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen;
10527c243321SVesa Jääskeläinen 
10537c243321SVesa Jääskeläinen 	asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO);
10547c243321SVesa Jääskeläinen 	if (!asnbuf) {
10557c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10567c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10577c243321SVesa Jääskeläinen 		goto out;
10587c243321SVesa Jääskeläinen 	}
10597c243321SVesa Jääskeläinen 
106032b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10617c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10627c243321SVesa Jääskeläinen 					     &buflen, buf, buflen);
10637c243321SVesa Jääskeläinen 	if (ret) {
10647c243321SVesa Jääskeläinen 		EMSG("Failed to write binary public key");
10657c243321SVesa Jääskeläinen 		goto out;
10667c243321SVesa Jääskeläinen 	}
10677c243321SVesa Jääskeläinen 
10687c243321SVesa Jääskeläinen 	/* Note: ASN.1 writing works backwards */
10697c243321SVesa Jääskeläinen 	ptr = asnbuf + asnbuflen;
10707c243321SVesa Jääskeläinen 
10717c243321SVesa Jääskeläinen 	ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen);
10727c243321SVesa Jääskeläinen 	if (ret < 0) {
10737c243321SVesa Jääskeläinen 		EMSG("Failed to write asn1 public key");
10747c243321SVesa Jääskeläinen 		goto out;
10757c243321SVesa Jääskeläinen 	}
10767c243321SVesa Jääskeläinen 
10777c243321SVesa Jääskeläinen 	rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr,
10787c243321SVesa Jääskeläinen 			   (size_t)ret);
10797c243321SVesa Jääskeläinen 
10807c243321SVesa Jääskeläinen out:
10817c243321SVesa Jääskeläinen 	TEE_Free(asnbuf);
10827c243321SVesa Jääskeläinen 	TEE_Free(buf);
10837c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_free(&key_pair);
108432b31808SJens Wiklander 	mbedtls_ecp_group_free(&key_pair_grp);
108532b31808SJens Wiklander 	mbedtls_mpi_free(&key_pair_d);
108632b31808SJens Wiklander 	mbedtls_ecp_point_free(&key_pair_Q);
10877c243321SVesa Jääskeläinen 
10887c243321SVesa Jääskeläinen 	return rc;
10897c243321SVesa Jääskeläinen }
10907c243321SVesa Jääskeläinen 
10917c243321SVesa Jääskeläinen static enum pkcs11_rc
10927c243321SVesa Jääskeläinen create_priv_key_hidden_attributes(struct obj_attrs **out,
10937c243321SVesa Jääskeläinen 				  struct obj_attrs *temp,
10947c243321SVesa Jääskeläinen 				  enum processing_func function)
10957c243321SVesa Jääskeläinen {
10967c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
10977c243321SVesa Jääskeläinen 
10987c243321SVesa Jääskeläinen 	switch (get_key_type(*out)) {
10997c243321SVesa Jääskeläinen 	case PKCS11_CKK_EC:
11007c243321SVesa Jääskeläinen 		rc = create_ec_priv_key_hidden_attributes(out, temp, function);
11017c243321SVesa Jääskeläinen 		break;
11027c243321SVesa Jääskeläinen 	default:
11037c243321SVesa Jääskeläinen 		/* no-op */
11047c243321SVesa Jääskeläinen 		break;
11057c243321SVesa Jääskeläinen 	}
11067c243321SVesa Jääskeläinen 
11077c243321SVesa Jääskeläinen 	return rc;
11087c243321SVesa Jääskeläinen }
11097c243321SVesa Jääskeläinen 
11107c243321SVesa Jääskeläinen static enum pkcs11_rc
1111196bcd93SRuchika Gupta sanitize_symm_key_attributes(struct obj_attrs **temp,
1112196bcd93SRuchika Gupta 			     enum processing_func function)
1113196bcd93SRuchika Gupta {
1114196bcd93SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1115196bcd93SRuchika Gupta 	uint32_t a_size = 0;
1116196bcd93SRuchika Gupta 
1117196bcd93SRuchika Gupta 	assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY);
1118196bcd93SRuchika Gupta 
1119196bcd93SRuchika Gupta 	rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size);
1120196bcd93SRuchika Gupta 
1121196bcd93SRuchika Gupta 	switch (get_key_type(*temp)) {
1122196bcd93SRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1123196bcd93SRuchika Gupta 	case PKCS11_CKK_AES:
1124196bcd93SRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
1125196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
1126196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
1127196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
1128196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
1129196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
1130196bcd93SRuchika Gupta 		switch (function) {
1131196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_IMPORT:
1132196bcd93SRuchika Gupta 			/* CKA_VALUE is a mandatory with C_CreateObject */
1133196bcd93SRuchika Gupta 			if (rc || a_size == 0)
1134196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1135196bcd93SRuchika Gupta 
1136196bcd93SRuchika Gupta 			if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL,
1137196bcd93SRuchika Gupta 					      NULL) != PKCS11_RV_NOT_FOUND)
1138196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1139196bcd93SRuchika Gupta 
1140196bcd93SRuchika Gupta 			return add_attribute(temp, PKCS11_CKA_VALUE_LEN,
1141196bcd93SRuchika Gupta 					     &a_size, sizeof(uint32_t));
1142196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1143196bcd93SRuchika Gupta 			if (rc != PKCS11_RV_NOT_FOUND)
1144196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1145196bcd93SRuchika Gupta 			break;
1146196bcd93SRuchika Gupta 		default:
1147196bcd93SRuchika Gupta 			break;
1148196bcd93SRuchika Gupta 		}
1149196bcd93SRuchika Gupta 		break;
1150196bcd93SRuchika Gupta 	default:
1151196bcd93SRuchika Gupta 		EMSG("Invalid key type %#"PRIx32"/%s",
1152196bcd93SRuchika Gupta 		     get_key_type(*temp), id2str_key_type(get_key_type(*temp)));
1153196bcd93SRuchika Gupta 
1154196bcd93SRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1155196bcd93SRuchika Gupta 	}
1156196bcd93SRuchika Gupta 
1157196bcd93SRuchika Gupta 	return PKCS11_CKR_OK;
1158196bcd93SRuchika Gupta }
1159196bcd93SRuchika Gupta 
116063f89caaSJens Wiklander /*
116163f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
116263f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
116363f89caaSJens Wiklander  * derive...).
116463f89caaSJens Wiklander  *
116563f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
116663f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
116763f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
116863f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
116963f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
117063f89caaSJens Wiklander  *
117163f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
117263f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
117363f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
117463f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
117563f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
117663f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
117763f89caaSJens Wiklander  */
117863f89caaSJens Wiklander enum pkcs11_rc
117963f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
118063f89caaSJens Wiklander 				size_t template_size,
118148799892SRuchika Gupta 				struct obj_attrs *parent,
118263f89caaSJens Wiklander 				enum processing_func function,
11834cfce748SRuchika Gupta 				enum pkcs11_mechanism_id mecha,
118402b16804SVesa Jääskeläinen 				enum pkcs11_class_id template_class)
118563f89caaSJens Wiklander {
118663f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
118763f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
118863f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
118963f89caaSJens Wiklander 	uint8_t local = 0;
119063f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
119163f89caaSJens Wiklander 	uint8_t never_extract = 0;
1192e3f0cb56SRuchika Gupta 	uint8_t extractable = 0;
1193fa247a2aSRuchika Gupta 	uint32_t class = PKCS11_UNDEFINED_ID;
1194fa247a2aSRuchika Gupta 	uint32_t type = PKCS11_UNDEFINED_ID;
119563f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
1196e3f0cb56SRuchika Gupta 	struct obj_attrs *req_attrs = NULL;
1197e3f0cb56SRuchika Gupta 	uint32_t size = 0;
1198e3f0cb56SRuchika Gupta 	uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID;
119963f89caaSJens Wiklander 
120063f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
120163f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
120263f89caaSJens Wiklander 	switch (function) {
1203fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1204013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
120563f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
12062d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
120748799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1208e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
12092d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
121063f89caaSJens Wiklander 		break;
121163f89caaSJens Wiklander 	default:
121263f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
121363f89caaSJens Wiklander 	}
121463f89caaSJens Wiklander #endif
121563f89caaSJens Wiklander 
1216dcad3409SRuchika Gupta 	/*
1217dcad3409SRuchika Gupta 	 * For PKCS11_FUNCTION_GENERATE, find the class and type
1218dcad3409SRuchika Gupta 	 * based on the mechanism. These will be passed as hint
1219dcad3409SRuchika Gupta 	 * sanitize_client_object() and added in temp if not
1220dcad3409SRuchika Gupta 	 * already present
1221dcad3409SRuchika Gupta 	 */
1222dcad3409SRuchika Gupta 	if (function == PKCS11_FUNCTION_GENERATE) {
1223fa247a2aSRuchika Gupta 		switch (mecha) {
1224fa247a2aSRuchika Gupta 		case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1225fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1226fa247a2aSRuchika Gupta 			type = PKCS11_CKK_GENERIC_SECRET;
1227fa247a2aSRuchika Gupta 			break;
1228fa247a2aSRuchika Gupta 		case PKCS11_CKM_AES_KEY_GEN:
1229fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1230fa247a2aSRuchika Gupta 			type = PKCS11_CKK_AES;
1231fa247a2aSRuchika Gupta 			break;
1232fa247a2aSRuchika Gupta 		default:
1233dcad3409SRuchika Gupta 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1234fa247a2aSRuchika Gupta 		}
1235fa247a2aSRuchika Gupta 	}
1236fa247a2aSRuchika Gupta 
12372d25a9bcSRuchika Gupta 	/*
1238013934d8SVesa Jääskeläinen 	 * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type
1239013934d8SVesa Jääskeläinen 	 * based on the mechanism. These will be passed as hint
1240013934d8SVesa Jääskeläinen 	 * sanitize_client_object() and added in temp if not
1241013934d8SVesa Jääskeläinen 	 * already present
1242013934d8SVesa Jääskeläinen 	 */
1243013934d8SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_GENERATE_PAIR) {
1244013934d8SVesa Jääskeläinen 		switch (mecha) {
124503e07432SValerii Chubar 		case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
124603e07432SValerii Chubar 			class = template_class;
124703e07432SValerii Chubar 			type = PKCS11_CKK_EDDSA;
124803e07432SValerii Chubar 			break;
124902b16804SVesa Jääskeläinen 		case PKCS11_CKM_EC_KEY_PAIR_GEN:
125002b16804SVesa Jääskeläinen 			class = template_class;
125102b16804SVesa Jääskeläinen 			type = PKCS11_CKK_EC;
125202b16804SVesa Jääskeläinen 			break;
125386922832SVesa Jääskeläinen 		case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
125486922832SVesa Jääskeläinen 			class = template_class;
125586922832SVesa Jääskeläinen 			type = PKCS11_CKK_RSA;
125686922832SVesa Jääskeläinen 			break;
1257013934d8SVesa Jääskeläinen 		default:
1258013934d8SVesa Jääskeläinen 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1259013934d8SVesa Jääskeläinen 		}
1260013934d8SVesa Jääskeläinen 	}
1261013934d8SVesa Jääskeläinen 
1262013934d8SVesa Jääskeläinen 	/*
12632d25a9bcSRuchika Gupta 	 * Check and remove duplicates if any and create a new temporary
12642d25a9bcSRuchika Gupta 	 * template
12652d25a9bcSRuchika Gupta 	 */
1266dcad3409SRuchika Gupta 	rc = sanitize_client_object(&temp, template, template_size, class,
1267dcad3409SRuchika Gupta 				    type);
1268dcad3409SRuchika Gupta 	if (rc)
1269dcad3409SRuchika Gupta 		goto out;
1270dcad3409SRuchika Gupta 
1271dcad3409SRuchika Gupta 	/*
12722d25a9bcSRuchika Gupta 	 * For function type modify and copy return the created template
12732d25a9bcSRuchika Gupta 	 * from here. Rest of the code below is for creating objects
12742d25a9bcSRuchika Gupta 	 * or generating keys.
12752d25a9bcSRuchika Gupta 	 */
12762d25a9bcSRuchika Gupta 	switch (function) {
12772d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
12782d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
12792d25a9bcSRuchika Gupta 		*out = temp;
12802d25a9bcSRuchika Gupta 		return rc;
1281e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1282e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
1283e3f0cb56SRuchika Gupta 		if (function == PKCS11_FUNCTION_UNWRAP)
1284e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE;
1285e3f0cb56SRuchika Gupta 		else
1286e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_DERIVE_TEMPLATE;
1287e3f0cb56SRuchika Gupta 
1288e3f0cb56SRuchika Gupta 		rc = get_attribute_ptr(parent, indirect_template,
1289e3f0cb56SRuchika Gupta 				       (void *)&req_attrs, &size);
1290e3f0cb56SRuchika Gupta 		if (rc == PKCS11_CKR_OK && size != 0) {
1291e3f0cb56SRuchika Gupta 			rc = attributes_match_add_reference(&temp, req_attrs);
1292e3f0cb56SRuchika Gupta 			if (rc)
1293e3f0cb56SRuchika Gupta 				goto out;
1294e3f0cb56SRuchika Gupta 		}
1295e3f0cb56SRuchika Gupta 		break;
12962d25a9bcSRuchika Gupta 	default:
12972d25a9bcSRuchika Gupta 		break;
12982d25a9bcSRuchika Gupta 	}
12992d25a9bcSRuchika Gupta 
13002d25a9bcSRuchika Gupta 	/*
1301dcad3409SRuchika Gupta 	 * Check if class and type in temp are consistent with the mechanism
1302dcad3409SRuchika Gupta 	 */
1303fa247a2aSRuchika Gupta 	switch (mecha) {
1304fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1305fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1306fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) {
1307fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1308fa247a2aSRuchika Gupta 			goto out;
1309fa247a2aSRuchika Gupta 		}
1310fa247a2aSRuchika Gupta 		break;
1311fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1312fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1313fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_AES) {
1314fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1315fa247a2aSRuchika Gupta 			goto out;
1316fa247a2aSRuchika Gupta 		}
1317fa247a2aSRuchika Gupta 		break;
131802b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
131902b16804SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
132002b16804SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132102b16804SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_EC) {
132202b16804SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
132302b16804SVesa Jääskeläinen 			goto out;
132402b16804SVesa Jääskeläinen 		}
132502b16804SVesa Jääskeläinen 		break;
132603e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
132703e07432SValerii Chubar 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
132803e07432SValerii Chubar 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132903e07432SValerii Chubar 		    get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) {
133003e07432SValerii Chubar 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
133103e07432SValerii Chubar 			goto out;
133203e07432SValerii Chubar 		}
133303e07432SValerii Chubar 		break;
133486922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
133586922832SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
133686922832SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
133786922832SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_RSA) {
133886922832SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
133986922832SVesa Jääskeläinen 			goto out;
134086922832SVesa Jääskeläinen 		}
134186922832SVesa Jääskeläinen 		break;
1342fa247a2aSRuchika Gupta 	default:
1343fa247a2aSRuchika Gupta 		break;
1344fa247a2aSRuchika Gupta 	}
134563f89caaSJens Wiklander 
134663f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
134763f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
134863f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
134963f89caaSJens Wiklander 		goto out;
135063f89caaSJens Wiklander 	}
135163f89caaSJens Wiklander 
1352e3f0cb56SRuchika Gupta 	/*
1353e3f0cb56SRuchika Gupta 	 * TBD - Add a check to see if temp contains any attribute which
1354e3f0cb56SRuchika Gupta 	 * is not consistent with the object class or type and return error.
1355e3f0cb56SRuchika Gupta 	 * In current implementation such attributes are ignored and not
1356e3f0cb56SRuchika Gupta 	 * added to final object while PKCS#11 specification expects a
1357e3f0cb56SRuchika Gupta 	 * failure and an error code be returned.
1358e3f0cb56SRuchika Gupta 	 */
1359e3f0cb56SRuchika Gupta 
136063f89caaSJens Wiklander 	switch (get_class(temp)) {
136163f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
136263f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
136363f89caaSJens Wiklander 		break;
13644137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
13654137952dSVesa Jääskeläinen 		rc = create_certificate_attributes(&attrs, temp);
13664137952dSVesa Jääskeläinen 		break;
136763f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1368196bcd93SRuchika Gupta 		rc = sanitize_symm_key_attributes(&temp, function);
1369196bcd93SRuchika Gupta 		if (rc)
1370196bcd93SRuchika Gupta 			goto out;
137163f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
137263f89caaSJens Wiklander 		break;
137363f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
13749cf1afceSVesa Jääskeläinen 		rc = create_pub_key_attributes(&attrs, temp, function);
13755071d7d1SVesa Jääskeläinen 		if (rc)
13765071d7d1SVesa Jääskeläinen 			goto out;
13775071d7d1SVesa Jääskeläinen 		rc = create_pub_key_generated_attributes(&attrs, temp,
13785071d7d1SVesa Jääskeläinen 							 function);
137963f89caaSJens Wiklander 		break;
138063f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
138163f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
13827c243321SVesa Jääskeläinen 		if (rc)
13837c243321SVesa Jääskeläinen 			goto out;
13847c243321SVesa Jääskeläinen 		rc = create_priv_key_hidden_attributes(&attrs, temp, function);
138563f89caaSJens Wiklander 		break;
138663f89caaSJens Wiklander 	default:
138763f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
138863f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
138963f89caaSJens Wiklander 
139063f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139163f89caaSJens Wiklander 		break;
139263f89caaSJens Wiklander 	}
139363f89caaSJens Wiklander 	if (rc)
139463f89caaSJens Wiklander 		goto out;
139563f89caaSJens Wiklander 
139690c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) !=
1397002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1398002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139963f89caaSJens Wiklander 		goto out;
1400002f6b93SEtienne Carriere 	}
140163f89caaSJens Wiklander 
140290c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
1403002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1404002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
140563f89caaSJens Wiklander 		goto out;
1406002f6b93SEtienne Carriere 	}
140763f89caaSJens Wiklander 
140863f89caaSJens Wiklander 	switch (function) {
1409fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1410013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
1411fa247a2aSRuchika Gupta 		local = PKCS11_TRUE;
1412fa247a2aSRuchika Gupta 		break;
141363f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
141448799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1415e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
141663f89caaSJens Wiklander 	default:
141763f89caaSJens Wiklander 		local = PKCS11_FALSE;
141863f89caaSJens Wiklander 		break;
141963f89caaSJens Wiklander 	}
142063f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
142163f89caaSJens Wiklander 	if (rc)
142263f89caaSJens Wiklander 		goto out;
142363f89caaSJens Wiklander 
142463f89caaSJens Wiklander 	switch (get_class(attrs)) {
142563f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
142663f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
142763f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
142863f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
142963f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
143063f89caaSJens Wiklander 
1431fa247a2aSRuchika Gupta 		switch (function) {
143248799892SRuchika Gupta 		case PKCS11_FUNCTION_DERIVE:
143348799892SRuchika Gupta 			always_sensitive =
143448799892SRuchika Gupta 				get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) &&
143548799892SRuchika Gupta 				get_bool(attrs, PKCS11_CKA_SENSITIVE);
143648799892SRuchika Gupta 			never_extract =
143748799892SRuchika Gupta 			       get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) &&
143848799892SRuchika Gupta 			       !get_bool(attrs, PKCS11_CKA_EXTRACTABLE);
143948799892SRuchika Gupta 			break;
1440e3f0cb56SRuchika Gupta 		case PKCS11_FUNCTION_UNWRAP:
1441e3f0cb56SRuchika Gupta 			always_sensitive = PKCS11_FALSE;
1442e3f0cb56SRuchika Gupta 			never_extract = PKCS11_FALSE;
1443e3f0cb56SRuchika Gupta 			extractable = PKCS11_TRUE;
1444e3f0cb56SRuchika Gupta 
1445e3f0cb56SRuchika Gupta 			/*
1446e3f0cb56SRuchika Gupta 			 * Check if template passed by user has CKA_EXTRACTABLE.
1447e3f0cb56SRuchika Gupta 			 * If not, by default value of CKA_EXTRACTABLE is set as
1448e3f0cb56SRuchika Gupta 			 * TRUE.
1449e3f0cb56SRuchika Gupta 			 */
1450e3f0cb56SRuchika Gupta 			if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE,
1451e3f0cb56SRuchika Gupta 					      NULL,
1452e3f0cb56SRuchika Gupta 					      NULL) == PKCS11_RV_NOT_FOUND) {
1453e3f0cb56SRuchika Gupta 				rc = set_attribute(&attrs,
1454e3f0cb56SRuchika Gupta 						   PKCS11_CKA_EXTRACTABLE,
1455e3f0cb56SRuchika Gupta 						   &extractable,
1456e3f0cb56SRuchika Gupta 						   sizeof(extractable));
1457e3f0cb56SRuchika Gupta 				if (rc)
1458e3f0cb56SRuchika Gupta 					goto out;
1459e3f0cb56SRuchika Gupta 			}
1460e3f0cb56SRuchika Gupta 			break;
1461fa247a2aSRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1462013934d8SVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
1463fa247a2aSRuchika Gupta 			always_sensitive = get_bool(attrs,
1464fa247a2aSRuchika Gupta 						    PKCS11_CKA_SENSITIVE);
1465fa247a2aSRuchika Gupta 			never_extract = !get_bool(attrs,
1466fa247a2aSRuchika Gupta 						  PKCS11_CKA_EXTRACTABLE);
1467fa247a2aSRuchika Gupta 			break;
1468fa247a2aSRuchika Gupta 		default:
1469fa247a2aSRuchika Gupta 			break;
1470fa247a2aSRuchika Gupta 		}
1471fa247a2aSRuchika Gupta 
147263f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
147363f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
147463f89caaSJens Wiklander 		if (rc)
147563f89caaSJens Wiklander 			goto out;
147663f89caaSJens Wiklander 
147763f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
147863f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
147963f89caaSJens Wiklander 		if (rc)
148063f89caaSJens Wiklander 			goto out;
148163f89caaSJens Wiklander 
148263f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
1483fa247a2aSRuchika Gupta 		if (local)
1484fa247a2aSRuchika Gupta 			mechanism_id = mecha;
1485fa247a2aSRuchika Gupta 		else
148663f89caaSJens Wiklander 			mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
1487fa247a2aSRuchika Gupta 
148863f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
148963f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
149063f89caaSJens Wiklander 		if (rc)
149163f89caaSJens Wiklander 			goto out;
149263f89caaSJens Wiklander 		break;
149363f89caaSJens Wiklander 
149463f89caaSJens Wiklander 	default:
149563f89caaSJens Wiklander 		break;
149663f89caaSJens Wiklander 	}
149763f89caaSJens Wiklander 
149863f89caaSJens Wiklander 	*out = attrs;
149963f89caaSJens Wiklander 
150063f89caaSJens Wiklander #ifdef DEBUG
150163f89caaSJens Wiklander 	trace_attributes("object", attrs);
150263f89caaSJens Wiklander #endif
150363f89caaSJens Wiklander 
150463f89caaSJens Wiklander out:
150563f89caaSJens Wiklander 	TEE_Free(temp);
150663f89caaSJens Wiklander 	if (rc)
150763f89caaSJens Wiklander 		TEE_Free(attrs);
150863f89caaSJens Wiklander 
150963f89caaSJens Wiklander 	return rc;
151063f89caaSJens Wiklander }
151163f89caaSJens Wiklander 
151263f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
151363f89caaSJens Wiklander {
151463f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
151563f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
151663f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
151763f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
151863f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
151963f89caaSJens Wiklander 
152063f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152163f89caaSJens Wiklander 	}
152263f89caaSJens Wiklander 
152363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
152463f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
152563f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
152663f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
152763f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
152863f89caaSJens Wiklander 
152963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
153063f89caaSJens Wiklander 	}
153163f89caaSJens Wiklander 
153263f89caaSJens Wiklander 	return PKCS11_CKR_OK;
153363f89caaSJens Wiklander }
153463f89caaSJens Wiklander 
153589735787SRuchika Gupta bool object_is_private(struct obj_attrs *head)
153689735787SRuchika Gupta {
153765fb9092SVesa Jääskeläinen 	return get_bool(head, PKCS11_CKA_PRIVATE);
153889735787SRuchika Gupta }
153989735787SRuchika Gupta 
15402d25a9bcSRuchika Gupta bool object_is_token(struct obj_attrs *head)
15412d25a9bcSRuchika Gupta {
15422d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_TOKEN);
15432d25a9bcSRuchika Gupta }
15442d25a9bcSRuchika Gupta 
15452d25a9bcSRuchika Gupta bool object_is_modifiable(struct obj_attrs *head)
15462d25a9bcSRuchika Gupta {
15472d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_MODIFIABLE);
15482d25a9bcSRuchika Gupta }
15492d25a9bcSRuchika Gupta 
15502d25a9bcSRuchika Gupta bool object_is_copyable(struct obj_attrs *head)
15512d25a9bcSRuchika Gupta {
15522d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_COPYABLE);
15532d25a9bcSRuchika Gupta }
15542d25a9bcSRuchika Gupta 
155563f89caaSJens Wiklander /*
1556512cbf1dSJens Wiklander  * Check access to object against authentication to token
1557512cbf1dSJens Wiklander  */
1558512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
1559512cbf1dSJens Wiklander 						struct obj_attrs *head)
1560512cbf1dSJens Wiklander {
1561512cbf1dSJens Wiklander 	bool private = true;
1562512cbf1dSJens Wiklander 
1563512cbf1dSJens Wiklander 	switch (get_class(head)) {
1564512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
156565fb9092SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1566512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
1567512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
15684137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
156965fb9092SVesa Jääskeläinen 		private = object_is_private(head);
1570512cbf1dSJens Wiklander 		break;
1571512cbf1dSJens Wiklander 	default:
1572512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1573512cbf1dSJens Wiklander 	}
1574512cbf1dSJens Wiklander 
15755db0fef4SRuchika Gupta 	if (private && (pkcs11_session_is_public(session) ||
15765db0fef4SRuchika Gupta 			pkcs11_session_is_so(session))) {
15775db0fef4SRuchika Gupta 		DMSG("Private object access from a public or SO session");
1578512cbf1dSJens Wiklander 
157912f1ba86SRuchika Gupta 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1580512cbf1dSJens Wiklander 	}
1581512cbf1dSJens Wiklander 
1582512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1583512cbf1dSJens Wiklander }
1584512cbf1dSJens Wiklander 
1585512cbf1dSJens Wiklander /*
158663f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
158763f89caaSJens Wiklander  */
158863f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
158963f89caaSJens Wiklander 						 struct obj_attrs *head)
159063f89caaSJens Wiklander {
159163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
159263f89caaSJens Wiklander 
159363f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
159463f89caaSJens Wiklander 	if (rc)
159563f89caaSJens Wiklander 		return rc;
159663f89caaSJens Wiklander 
159763f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
159863f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
159963f89caaSJens Wiklander 		DMSG("Can't create trusted object");
160063f89caaSJens Wiklander 
160163f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
160263f89caaSJens Wiklander 	}
160363f89caaSJens Wiklander 
160463f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
160563f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
160663f89caaSJens Wiklander 		DMSG("Can't create persistent object");
160763f89caaSJens Wiklander 
160863f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
160963f89caaSJens Wiklander 	}
161063f89caaSJens Wiklander 
161163f89caaSJens Wiklander 	return PKCS11_CKR_OK;
161263f89caaSJens Wiklander }
161363f89caaSJens Wiklander 
161463f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
161563f89caaSJens Wiklander 	do {								\
161663f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
161763f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
161863f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
161963f89caaSJens Wiklander 									\
162063f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
162163f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
162263f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
162363f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
162463f89caaSJens Wiklander 	} while (0)
162563f89caaSJens Wiklander 
162663f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
162763f89caaSJens Wiklander 					   struct obj_attrs *head,
162863f89caaSJens Wiklander 					   uint32_t attribute, bool val)
162963f89caaSJens Wiklander {
163063f89caaSJens Wiklander 	uint8_t bbool = 0;
163163f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
163263f89caaSJens Wiklander 
163363f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
163463f89caaSJens Wiklander 		return true;
163563f89caaSJens Wiklander 
163663f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
163763f89caaSJens Wiklander 	return false;
163863f89caaSJens Wiklander }
163963f89caaSJens Wiklander 
164063f89caaSJens Wiklander /*
164163f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
164263f89caaSJens Wiklander  * used to create it.
164363f89caaSJens Wiklander  *
164463f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
164563f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
164663f89caaSJens Wiklander  */
164763f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
164863f89caaSJens Wiklander 						      struct obj_attrs *head)
164963f89caaSJens Wiklander {
165063f89caaSJens Wiklander 	/*
165163f89caaSJens Wiklander 	 * Processings that do not create secrets are not expected to call
165263f89caaSJens Wiklander 	 * this function which would panic.
165363f89caaSJens Wiklander 	 */
165463f89caaSJens Wiklander 	switch (proc_id) {
165563f89caaSJens Wiklander 	case PKCS11_PROCESSING_IMPORT:
1656cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1657e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_ECB:
1658e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_CBC:
165948799892SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
166048799892SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
166145d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
166263f89caaSJens Wiklander 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
166363f89caaSJens Wiklander 		break;
1664fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1665fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
166603e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
166702b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
166886922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
1669fa247a2aSRuchika Gupta 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true));
1670fa247a2aSRuchika Gupta 		break;
167163f89caaSJens Wiklander 	default:
167263f89caaSJens Wiklander 		TEE_Panic(proc_id);
167363f89caaSJens Wiklander 		break;
167463f89caaSJens Wiklander 	}
167563f89caaSJens Wiklander 
1676fa247a2aSRuchika Gupta 	switch (proc_id) {
1677fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1678fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET);
1679fa247a2aSRuchika Gupta 		break;
1680fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1681fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_AES);
1682fa247a2aSRuchika Gupta 		break;
168303e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
168403e07432SValerii Chubar 		assert(get_key_type(head) == PKCS11_CKK_EC_EDWARDS);
168503e07432SValerii Chubar 		break;
168602b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
168702b16804SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_EC);
168802b16804SVesa Jääskeläinen 		break;
168986922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
169086922832SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_RSA);
169186922832SVesa Jääskeläinen 		break;
1692fa247a2aSRuchika Gupta 	case PKCS11_PROCESSING_IMPORT:
1693cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1694fa247a2aSRuchika Gupta 	default:
1695fa247a2aSRuchika Gupta 		break;
1696fa247a2aSRuchika Gupta 	}
1697fa247a2aSRuchika Gupta 
169863f89caaSJens Wiklander 	return PKCS11_CKR_OK;
169963f89caaSJens Wiklander }
1700512cbf1dSJens Wiklander 
17012d0cd829SRuchika Gupta /* Return min and max key size supported for a key_type in bytes */
1702512cbf1dSJens Wiklander static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
1703512cbf1dSJens Wiklander 				  uint32_t *min_key_size,
1704512cbf1dSJens Wiklander 				  uint32_t *max_key_size)
1705512cbf1dSJens Wiklander {
1706512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
1707512cbf1dSJens Wiklander 
1708512cbf1dSJens Wiklander 	switch (key_type) {
1709fa247a2aSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1710fa247a2aSRuchika Gupta 		mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN;
1711fa247a2aSRuchika Gupta 		break;
1712512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
1713512cbf1dSJens Wiklander 		mechanism = PKCS11_CKM_AES_KEY_GEN;
1714512cbf1dSJens Wiklander 		break;
17151f45c9cfSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
17161f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_MD5_HMAC;
17171f45c9cfSRuchika Gupta 		break;
17181f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
17191f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA_1_HMAC;
17201f45c9cfSRuchika Gupta 		break;
17211f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
17221f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA224_HMAC;
17231f45c9cfSRuchika Gupta 		break;
1724a339a354SEtienne Carriere 	case PKCS11_CKK_SHA256_HMAC:
1725a339a354SEtienne Carriere 		mechanism = PKCS11_CKM_SHA256_HMAC;
1726a339a354SEtienne Carriere 		break;
17271f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
17281f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA384_HMAC;
17291f45c9cfSRuchika Gupta 		break;
17301f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
17311f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA512_HMAC;
17321f45c9cfSRuchika Gupta 		break;
1733db28c542SVesa Jääskeläinen 	case PKCS11_CKK_EC:
1734db28c542SVesa Jääskeläinen 		mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN;
1735db28c542SVesa Jääskeläinen 		break;
173603e07432SValerii Chubar 	case PKCS11_CKK_EDDSA:
173703e07432SValerii Chubar 		mechanism = PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN;
173803e07432SValerii Chubar 		break;
173986922832SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
174086922832SVesa Jääskeläinen 		mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN;
174186922832SVesa Jääskeläinen 		break;
1742512cbf1dSJens Wiklander 	default:
1743512cbf1dSJens Wiklander 		TEE_Panic(key_type);
1744512cbf1dSJens Wiklander 		break;
1745512cbf1dSJens Wiklander 	}
1746512cbf1dSJens Wiklander 
17472d0cd829SRuchika Gupta 	mechanism_supported_key_sizes_bytes(mechanism, min_key_size,
1748512cbf1dSJens Wiklander 					    max_key_size);
1749512cbf1dSJens Wiklander }
1750512cbf1dSJens Wiklander 
1751512cbf1dSJens Wiklander enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
1752512cbf1dSJens Wiklander 				   struct obj_attrs *key2)
1753512cbf1dSJens Wiklander {
1754512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1755512cbf1dSJens Wiklander 	struct obj_attrs *secret = NULL;
1756013934d8SVesa Jääskeläinen 	struct obj_attrs *private = NULL;
1757013934d8SVesa Jääskeläinen 	struct obj_attrs *public = NULL;
1758512cbf1dSJens Wiklander 	uint32_t max_key_size = 0;
1759512cbf1dSJens Wiklander 	uint32_t min_key_size = 0;
1760512cbf1dSJens Wiklander 	uint32_t key_length = 0;
1761512cbf1dSJens Wiklander 
1762512cbf1dSJens Wiklander 	switch (get_class(key1)) {
1763512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1764512cbf1dSJens Wiklander 		secret = key1;
1765512cbf1dSJens Wiklander 		break;
1766013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
1767013934d8SVesa Jääskeläinen 		public = key1;
1768013934d8SVesa Jääskeläinen 		break;
1769013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1770013934d8SVesa Jääskeläinen 		private = key1;
1771013934d8SVesa Jääskeläinen 		break;
1772512cbf1dSJens Wiklander 	default:
1773512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1774512cbf1dSJens Wiklander 	}
1775512cbf1dSJens Wiklander 
1776013934d8SVesa Jääskeläinen 	if (key2) {
1777013934d8SVesa Jääskeläinen 		switch (get_class(key2)) {
1778013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PUBLIC_KEY:
1779013934d8SVesa Jääskeläinen 			public = key2;
1780013934d8SVesa Jääskeläinen 			if (private == key1)
1781013934d8SVesa Jääskeläinen 				break;
1782013934d8SVesa Jääskeläinen 
1783013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1784013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PRIVATE_KEY:
1785013934d8SVesa Jääskeläinen 			private = key2;
1786013934d8SVesa Jääskeläinen 			if (public == key1)
1787013934d8SVesa Jääskeläinen 				break;
1788013934d8SVesa Jääskeläinen 
1789013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1790013934d8SVesa Jääskeläinen 		default:
1791512cbf1dSJens Wiklander 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1792013934d8SVesa Jääskeläinen 		}
1793013934d8SVesa Jääskeläinen 
1794013934d8SVesa Jääskeläinen 		if (get_key_type(private) != get_key_type(public))
1795013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1796013934d8SVesa Jääskeläinen 	}
1797512cbf1dSJens Wiklander 
1798512cbf1dSJens Wiklander 	if (secret) {
1799512cbf1dSJens Wiklander 		switch (get_key_type(secret)) {
1800512cbf1dSJens Wiklander 		case PKCS11_CKK_AES:
1801512cbf1dSJens Wiklander 		case PKCS11_CKK_GENERIC_SECRET:
1802512cbf1dSJens Wiklander 		case PKCS11_CKK_MD5_HMAC:
1803512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA_1_HMAC:
1804512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA224_HMAC:
1805512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA256_HMAC:
1806512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA384_HMAC:
1807512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA512_HMAC:
1808512cbf1dSJens Wiklander 			break;
1809512cbf1dSJens Wiklander 		default:
1810512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1811512cbf1dSJens Wiklander 		}
1812512cbf1dSJens Wiklander 
1813512cbf1dSJens Wiklander 		/* Get key size */
1814512cbf1dSJens Wiklander 		rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN,
1815512cbf1dSJens Wiklander 				       &key_length);
1816512cbf1dSJens Wiklander 		if (rc)
1817d1d44372SRuchika Gupta 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
1818512cbf1dSJens Wiklander 	}
1819013934d8SVesa Jääskeläinen 	if (public) {
1820013934d8SVesa Jääskeläinen 		switch (get_key_type(public)) {
182186922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
182286922832SVesa Jääskeläinen 			/* Get key size */
182386922832SVesa Jääskeläinen 			rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS,
182486922832SVesa Jääskeläinen 					       &key_length);
182586922832SVesa Jääskeläinen 			if (rc)
182686922832SVesa Jääskeläinen 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
182786922832SVesa Jääskeläinen 			key_length = ROUNDUP(key_length, 8) / 8;
182886922832SVesa Jääskeläinen 			break;
182902b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
183003e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
183102b16804SVesa Jääskeläinen 			break;
1832013934d8SVesa Jääskeläinen 		default:
1833013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1834013934d8SVesa Jääskeläinen 		}
1835013934d8SVesa Jääskeläinen 	}
1836013934d8SVesa Jääskeläinen 	if (private) {
1837013934d8SVesa Jääskeläinen 		switch (get_key_type(private)) {
183886922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
183902b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
184003e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
184102b16804SVesa Jääskeläinen 			break;
1842013934d8SVesa Jääskeläinen 		default:
1843013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1844013934d8SVesa Jääskeläinen 		}
1845013934d8SVesa Jääskeläinen 	}
1846512cbf1dSJens Wiklander 
184702b16804SVesa Jääskeläinen 	/*
184802b16804SVesa Jääskeläinen 	 * Check key size for symmetric keys and RSA keys
184902b16804SVesa Jääskeläinen 	 * EC is bound to domains, no need to check here.
185002b16804SVesa Jääskeläinen 	 */
185102b16804SVesa Jääskeläinen 	switch (get_key_type(key1)) {
185202b16804SVesa Jääskeläinen 	case PKCS11_CKK_EC:
185303e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
185402b16804SVesa Jääskeläinen 		return PKCS11_CKR_OK;
185502b16804SVesa Jääskeläinen 	default:
185602b16804SVesa Jääskeläinen 		break;
185702b16804SVesa Jääskeläinen 	}
185802b16804SVesa Jääskeläinen 
1859512cbf1dSJens Wiklander 	get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size);
1860512cbf1dSJens Wiklander 	if (key_length < min_key_size || key_length > max_key_size) {
1861512cbf1dSJens Wiklander 		EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]",
1862512cbf1dSJens Wiklander 		     key_length, min_key_size, max_key_size);
1863512cbf1dSJens Wiklander 
1864512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_SIZE_RANGE;
1865512cbf1dSJens Wiklander 	}
1866512cbf1dSJens Wiklander 
186749ed60abSRuchika Gupta 	if (secret && get_key_type(secret) == PKCS11_CKK_AES) {
186849ed60abSRuchika Gupta 		if (key_length != 16 && key_length != 24 && key_length != 32)
186949ed60abSRuchika Gupta 			return PKCS11_CKR_KEY_SIZE_RANGE;
187049ed60abSRuchika Gupta 	}
187149ed60abSRuchika Gupta 
1872512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1873512cbf1dSJens Wiklander }
1874512cbf1dSJens Wiklander 
1875512cbf1dSJens Wiklander /* Check processing ID against attribute ALLOWED_MECHANISMS if any */
1876512cbf1dSJens Wiklander static bool parent_key_complies_allowed_processings(uint32_t proc_id,
1877512cbf1dSJens Wiklander 						    struct obj_attrs *head)
1878512cbf1dSJens Wiklander {
1879512cbf1dSJens Wiklander 	char *attr = NULL;
1880512cbf1dSJens Wiklander 	uint32_t size = 0;
1881512cbf1dSJens Wiklander 	uint32_t proc = 0;
1882512cbf1dSJens Wiklander 	size_t count = 0;
18836a760c9eSEtienne Carriere 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1884512cbf1dSJens Wiklander 
18856a760c9eSEtienne Carriere 	rc = get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS,
18866a760c9eSEtienne Carriere 			       (void *)&attr, &size);
18876a760c9eSEtienne Carriere 	if (rc == PKCS11_RV_NOT_FOUND)
1888512cbf1dSJens Wiklander 		return true;
18896a760c9eSEtienne Carriere 	if (rc) {
18906a760c9eSEtienne Carriere 		EMSG("unexpected attributes state");
18916a760c9eSEtienne Carriere 		TEE_Panic(TEE_ERROR_BAD_STATE);
1892512cbf1dSJens Wiklander 	}
1893512cbf1dSJens Wiklander 
1894512cbf1dSJens Wiklander 	for (count = size / sizeof(uint32_t); count; count--) {
1895512cbf1dSJens Wiklander 		TEE_MemMove(&proc, attr, sizeof(uint32_t));
1896512cbf1dSJens Wiklander 		attr += sizeof(uint32_t);
1897512cbf1dSJens Wiklander 
1898512cbf1dSJens Wiklander 		if (proc == proc_id)
1899512cbf1dSJens Wiklander 			return true;
1900512cbf1dSJens Wiklander 	}
1901512cbf1dSJens Wiklander 
1902512cbf1dSJens Wiklander 	DMSG("can't find %s in allowed list", id2str_proc(proc_id));
1903512cbf1dSJens Wiklander 	return false;
1904512cbf1dSJens Wiklander }
1905512cbf1dSJens Wiklander 
1906512cbf1dSJens Wiklander static enum pkcs11_attr_id func_to_attr(enum processing_func func)
1907512cbf1dSJens Wiklander {
1908512cbf1dSJens Wiklander 	switch (func) {
1909512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
1910512cbf1dSJens Wiklander 		return PKCS11_CKA_ENCRYPT;
1911512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
1912512cbf1dSJens Wiklander 		return PKCS11_CKA_DECRYPT;
1913512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
1914512cbf1dSJens Wiklander 		return PKCS11_CKA_SIGN;
1915512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
1916512cbf1dSJens Wiklander 		return PKCS11_CKA_VERIFY;
1917512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
1918512cbf1dSJens Wiklander 		return PKCS11_CKA_WRAP;
1919512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
1920512cbf1dSJens Wiklander 		return PKCS11_CKA_UNWRAP;
1921512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
1922512cbf1dSJens Wiklander 		return PKCS11_CKA_DERIVE;
1923512cbf1dSJens Wiklander 	default:
1924512cbf1dSJens Wiklander 		return PKCS11_CKA_UNDEFINED_ID;
1925512cbf1dSJens Wiklander 	}
1926512cbf1dSJens Wiklander }
1927512cbf1dSJens Wiklander 
1928512cbf1dSJens Wiklander enum pkcs11_rc
1929512cbf1dSJens Wiklander check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
1930512cbf1dSJens Wiklander 				      enum processing_func function,
1931512cbf1dSJens Wiklander 				      struct obj_attrs *head)
1932512cbf1dSJens Wiklander {
1933512cbf1dSJens Wiklander 	enum pkcs11_class_id key_class = get_class(head);
1934512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(head);
1935512cbf1dSJens Wiklander 	enum pkcs11_attr_id attr = func_to_attr(function);
1936512cbf1dSJens Wiklander 
1937512cbf1dSJens Wiklander 	if (!get_bool(head, attr)) {
1938512cbf1dSJens Wiklander 		DMSG("%s not permitted", id2str_attr(attr));
1939512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1940512cbf1dSJens Wiklander 	}
1941512cbf1dSJens Wiklander 
1942512cbf1dSJens Wiklander 	/* Check processing complies with parent key family */
1943512cbf1dSJens Wiklander 	switch (proc_id) {
1944512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
1945512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
1946512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
1947512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
19480ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC:
19490ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC_GENERAL:
1950512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1951512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1952512cbf1dSJens Wiklander 			break;
1953512cbf1dSJens Wiklander 
1954512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1955512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1956512cbf1dSJens Wiklander 
19575f80f270SRuchika Gupta 		if (function == PKCS11_FUNCTION_WRAP)
19585f80f270SRuchika Gupta 			return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1959e3f0cb56SRuchika Gupta 		else if (function == PKCS11_FUNCTION_UNWRAP)
1960e3f0cb56SRuchika Gupta 			return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
19615f80f270SRuchika Gupta 		else
1962512cbf1dSJens Wiklander 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1963512cbf1dSJens Wiklander 
1964c3033708SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
1965c3033708SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
1966c3033708SRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY &&
1967c3033708SRuchika Gupta 		    key_type != PKCS11_CKK_AES)
1968c3033708SRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1969c3033708SRuchika Gupta 
1970c3033708SRuchika Gupta 		if (get_bool(head, PKCS11_CKA_ENCRYPT)) {
1971c3033708SRuchika Gupta 			/*
1972c3033708SRuchika Gupta 			 * Intentionally refuse to proceed despite
1973c3033708SRuchika Gupta 			 * PKCS#11 specifications v2.40 and v3.0 not expecting
1974c3033708SRuchika Gupta 			 * this behavior to avoid potential security issue
1975c3033708SRuchika Gupta 			 * where keys derived by these mechanisms can be
1976c3033708SRuchika Gupta 			 * revealed by doing data encryption using parent key.
1977c3033708SRuchika Gupta 			 */
1978c3033708SRuchika Gupta 			return PKCS11_CKR_FUNCTION_FAILED;
1979c3033708SRuchika Gupta 		}
1980c3033708SRuchika Gupta 
1981c3033708SRuchika Gupta 		break;
1982689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
1983689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
1984689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
1985689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
1986689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
1987689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
198870b6683bSVictor Chong 	case PKCS11_CKM_MD5_HMAC_GENERAL:
198970b6683bSVictor Chong 	case PKCS11_CKM_SHA_1_HMAC_GENERAL:
199070b6683bSVictor Chong 	case PKCS11_CKM_SHA224_HMAC_GENERAL:
199170b6683bSVictor Chong 	case PKCS11_CKM_SHA256_HMAC_GENERAL:
199270b6683bSVictor Chong 	case PKCS11_CKM_SHA384_HMAC_GENERAL:
199370b6683bSVictor Chong 	case PKCS11_CKM_SHA512_HMAC_GENERAL:
1994689f4e5bSRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY)
1995689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1996689f4e5bSRuchika Gupta 
1997689f4e5bSRuchika Gupta 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
1998689f4e5bSRuchika Gupta 			break;
1999689f4e5bSRuchika Gupta 
2000689f4e5bSRuchika Gupta 		switch (proc_id) {
2001689f4e5bSRuchika Gupta 		case PKCS11_CKM_MD5_HMAC:
200270b6683bSVictor Chong 		case PKCS11_CKM_MD5_HMAC_GENERAL:
2003689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_MD5_HMAC)
2004689f4e5bSRuchika Gupta 				break;
2005689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2006689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA_1_HMAC:
200770b6683bSVictor Chong 		case PKCS11_CKM_SHA_1_HMAC_GENERAL:
2008689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA_1_HMAC)
2009689f4e5bSRuchika Gupta 				break;
2010689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2011689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA224_HMAC:
201270b6683bSVictor Chong 		case PKCS11_CKM_SHA224_HMAC_GENERAL:
2013689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA224_HMAC)
2014689f4e5bSRuchika Gupta 				break;
2015689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2016689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA256_HMAC:
201770b6683bSVictor Chong 		case PKCS11_CKM_SHA256_HMAC_GENERAL:
2018689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA256_HMAC)
2019689f4e5bSRuchika Gupta 				break;
2020689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2021689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA384_HMAC:
202270b6683bSVictor Chong 		case PKCS11_CKM_SHA384_HMAC_GENERAL:
2023689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA384_HMAC)
2024689f4e5bSRuchika Gupta 				break;
2025689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2026689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA512_HMAC:
202770b6683bSVictor Chong 		case PKCS11_CKM_SHA512_HMAC_GENERAL:
2028689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA512_HMAC)
2029689f4e5bSRuchika Gupta 				break;
2030689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2031689f4e5bSRuchika Gupta 		default:
2032689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2033689f4e5bSRuchika Gupta 		}
2034689f4e5bSRuchika Gupta 		break;
2035689f4e5bSRuchika Gupta 
203603e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
203703e07432SValerii Chubar 		if (key_type != PKCS11_CKK_EC_EDWARDS) {
203803e07432SValerii Chubar 			EMSG("Invalid key %s for mechanism %s",
203903e07432SValerii Chubar 			     id2str_type(key_type, key_class),
204003e07432SValerii Chubar 			     id2str_proc(proc_id));
204103e07432SValerii Chubar 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
204203e07432SValerii Chubar 		}
204303e07432SValerii Chubar 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
204403e07432SValerii Chubar 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
204503e07432SValerii Chubar 			EMSG("Invalid key class for mechanism %s",
204603e07432SValerii Chubar 			     id2str_proc(proc_id));
204703e07432SValerii Chubar 
204803e07432SValerii Chubar 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
204903e07432SValerii Chubar 		}
205003e07432SValerii Chubar 		break;
205103e07432SValerii Chubar 
2052fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
2053fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
2054fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
2055fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
2056fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
2057fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
2058cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
2059fb279d8bSVesa Jääskeläinen 		if (key_type != PKCS11_CKK_EC) {
2060fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
2061fb279d8bSVesa Jääskeläinen 			     id2str_type(key_type, key_class),
2062fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2063fb279d8bSVesa Jääskeläinen 
2064fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
2065fb279d8bSVesa Jääskeläinen 		}
2066fb279d8bSVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
2067fb279d8bSVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
2068fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
2069fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2070fb279d8bSVesa Jääskeläinen 
2071fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2072fb279d8bSVesa Jääskeläinen 		}
2073fb279d8bSVesa Jääskeläinen 		break;
20740442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
20750442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
20760442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
20770442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
20780442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
20790442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
20800442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
208145d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
2082dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
2083d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
2084d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
2085d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
2086d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
2087d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
2088d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
20890442c956SVesa Jääskeläinen 		if (key_type != PKCS11_CKK_RSA) {
20900442c956SVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
20910442c956SVesa Jääskeläinen 			     id2str_type(key_type, key_class),
20920442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20930442c956SVesa Jääskeläinen 
20940442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
20950442c956SVesa Jääskeläinen 		}
20960442c956SVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
20970442c956SVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
20980442c956SVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
20990442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
21000442c956SVesa Jääskeläinen 
21010442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
21020442c956SVesa Jääskeläinen 		}
21030442c956SVesa Jääskeläinen 		break;
2104512cbf1dSJens Wiklander 	default:
2105512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
2106512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
2107512cbf1dSJens Wiklander 
2108512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
2109512cbf1dSJens Wiklander 	}
2110512cbf1dSJens Wiklander 
2111512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
2112512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
2113512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2114512cbf1dSJens Wiklander 	}
2115512cbf1dSJens Wiklander 
2116512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
2117512cbf1dSJens Wiklander }
2118783c1515SRuchika Gupta 
2119783c1515SRuchika Gupta bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
2120783c1515SRuchika Gupta 			     struct pkcs11_object *obj)
2121783c1515SRuchika Gupta {
2122783c1515SRuchika Gupta 	uint8_t boolval = 0;
2123783c1515SRuchika Gupta 	uint32_t boolsize = 0;
2124783c1515SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2125783c1515SRuchika Gupta 	enum pkcs11_class_id key_class = get_class(obj->attributes);
2126783c1515SRuchika Gupta 
2127981966bcSVesa Jääskeläinen 	if (attribute_is_hidden(req_attr))
2128981966bcSVesa Jääskeläinen 		return false;
2129981966bcSVesa Jääskeläinen 
2130783c1515SRuchika Gupta 	if (key_class != PKCS11_CKO_SECRET_KEY &&
2131783c1515SRuchika Gupta 	    key_class != PKCS11_CKO_PRIVATE_KEY)
2132783c1515SRuchika Gupta 		return true;
2133783c1515SRuchika Gupta 
2134783c1515SRuchika Gupta 	switch (req_attr->id) {
2135783c1515SRuchika Gupta 	case PKCS11_CKA_PRIVATE_EXPONENT:
2136783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_1:
2137783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_2:
2138783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_1:
2139783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_2:
2140783c1515SRuchika Gupta 	case PKCS11_CKA_COEFFICIENT:
2141783c1515SRuchika Gupta 	case PKCS11_CKA_VALUE:
2142783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2143783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
2144783c1515SRuchika Gupta 				   &boolval, &boolsize);
2145783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_FALSE)
2146783c1515SRuchika Gupta 			return false;
2147783c1515SRuchika Gupta 
2148783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2149783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
2150783c1515SRuchika Gupta 				   &boolval, &boolsize);
2151783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_TRUE)
2152783c1515SRuchika Gupta 			return false;
2153783c1515SRuchika Gupta 		break;
2154783c1515SRuchika Gupta 	default:
2155783c1515SRuchika Gupta 		break;
2156783c1515SRuchika Gupta 	}
2157783c1515SRuchika Gupta 
2158783c1515SRuchika Gupta 	return true;
2159783c1515SRuchika Gupta }
21602d25a9bcSRuchika Gupta 
21612d25a9bcSRuchika Gupta static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr)
21622d25a9bcSRuchika Gupta {
21632d25a9bcSRuchika Gupta 	switch (attr->id) {
21642d25a9bcSRuchika Gupta 	case PKCS11_CKA_ID:
21652d25a9bcSRuchika Gupta 	case PKCS11_CKA_START_DATE:
21662d25a9bcSRuchika Gupta 	case PKCS11_CKA_END_DATE:
21672d25a9bcSRuchika Gupta 	case PKCS11_CKA_DERIVE:
21682d25a9bcSRuchika Gupta 		return true;
21692d25a9bcSRuchika Gupta 	default:
21702d25a9bcSRuchika Gupta 		return false;
21712d25a9bcSRuchika Gupta 	}
21722d25a9bcSRuchika Gupta }
21732d25a9bcSRuchika Gupta 
21742d25a9bcSRuchika Gupta static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr,
21752d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21762d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj)
21772d25a9bcSRuchika Gupta {
21782d25a9bcSRuchika Gupta 	switch (attr->id) {
21792d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
21802d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
21812d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
21822d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
21832d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
21842d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
2185bcac2127SMarouene Boubakri 	case PKCS11_CKA_CHECK_VALUE:
21862d25a9bcSRuchika Gupta 		return true;
21872d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
21882d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
21892d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
21902d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
21912d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
21922d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
21932d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
21942d25a9bcSRuchika Gupta 	/* Change in CKA_TRUSTED can only be done by SO */
21952d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
21962d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
21972d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
21982d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
21992d25a9bcSRuchika Gupta 		return false;
22002d25a9bcSRuchika Gupta 	default:
22012d25a9bcSRuchika Gupta 		return false;
22022d25a9bcSRuchika Gupta 	}
22032d25a9bcSRuchika Gupta }
22042d25a9bcSRuchika Gupta 
22052d25a9bcSRuchika Gupta static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr,
22062d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
22072d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj __unused)
22082d25a9bcSRuchika Gupta {
22092d25a9bcSRuchika Gupta 	switch (attr->id) {
22102d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22112d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
22122d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
22132d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY_RECOVER:
22142d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
22152d25a9bcSRuchika Gupta 		return true;
22162d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
22172d25a9bcSRuchika Gupta 		/* Change in CKA_TRUSTED can only be done by SO */
22182d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
22192d25a9bcSRuchika Gupta 	default:
22202d25a9bcSRuchika Gupta 		return false;
22212d25a9bcSRuchika Gupta 	}
22222d25a9bcSRuchika Gupta }
22232d25a9bcSRuchika Gupta 
22242d25a9bcSRuchika Gupta static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr,
22252d25a9bcSRuchika Gupta 					   struct pkcs11_session *sess __unused,
22262d25a9bcSRuchika Gupta 					   struct pkcs11_object *obj)
22272d25a9bcSRuchika Gupta {
22282d25a9bcSRuchika Gupta 	switch (attr->id) {
22292d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22302d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
22312d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
22322d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN_RECOVER:
22332d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
22342d25a9bcSRuchika Gupta 	/*
22352d25a9bcSRuchika Gupta 	 * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO
22362d25a9bcSRuchika Gupta 	 * Specification mentions that if this attribute is
22372d25a9bcSRuchika Gupta 	 * supplied as part of a template for C_CreateObject, C_CopyObject or
22382d25a9bcSRuchika Gupta 	 * C_SetAttributeValue for a private key, the token MUST verify
22392d25a9bcSRuchika Gupta 	 * correspondence between the private key data and the public key data
22402d25a9bcSRuchika Gupta 	 * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be
22412d25a9bcSRuchika Gupta 	 * taken care of when this object type will be implemented
22422d25a9bcSRuchika Gupta 	 */
22432d25a9bcSRuchika Gupta 	case PKCS11_CKA_PUBLIC_KEY_INFO:
22442d25a9bcSRuchika Gupta 		return true;
22452d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
22462d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
22472d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
22482d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
22492d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
22502d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
22512d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
22522d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
22532d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
22542d25a9bcSRuchika Gupta 		return false;
22552d25a9bcSRuchika Gupta 	default:
22562d25a9bcSRuchika Gupta 		return false;
22572d25a9bcSRuchika Gupta 	}
22582d25a9bcSRuchika Gupta }
22592d25a9bcSRuchika Gupta 
22604137952dSVesa Jääskeläinen static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr,
22614137952dSVesa Jääskeläinen 					   struct pkcs11_session *session,
22624137952dSVesa Jääskeläinen 					   struct pkcs11_object *obj)
22634137952dSVesa Jääskeläinen {
22644137952dSVesa Jääskeläinen 	uint8_t boolval = 0;
22654137952dSVesa Jääskeläinen 	uint32_t boolsize = 0;
22664137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
22674137952dSVesa Jääskeläinen 
22684137952dSVesa Jääskeläinen 	/* Trusted certificates cannot be modified. */
22694137952dSVesa Jääskeläinen 	rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED,
22704137952dSVesa Jääskeläinen 			   &boolval, &boolsize);
22714137952dSVesa Jääskeläinen 	if (rc || boolval == PKCS11_TRUE)
22724137952dSVesa Jääskeläinen 		return false;
22734137952dSVesa Jääskeläinen 
22744137952dSVesa Jääskeläinen 	/* Common certificate attributes */
22754137952dSVesa Jääskeläinen 	switch (attr->id) {
22764137952dSVesa Jääskeläinen 	case PKCS11_CKA_TRUSTED:
22774137952dSVesa Jääskeläinen 		/*
22784137952dSVesa Jääskeläinen 		 * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an
22794137952dSVesa Jääskeläinen 		 * application. It MUST be set by a token initialization
22804137952dSVesa Jääskeläinen 		 * application or by the token’s SO.
22814137952dSVesa Jääskeläinen 		 */
22824137952dSVesa Jääskeläinen 		return pkcs11_session_is_so(session);
22834137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_TYPE:
22844137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_CATEGORY:
22854137952dSVesa Jääskeläinen 		return false;
22864137952dSVesa Jääskeläinen 	default:
22874137952dSVesa Jääskeläinen 		break;
22884137952dSVesa Jääskeläinen 	}
22894137952dSVesa Jääskeläinen 
22904137952dSVesa Jääskeläinen 	/* Certificate type specific attributes */
22914137952dSVesa Jääskeläinen 	switch (get_certificate_type(obj->attributes)) {
22924137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
22934137952dSVesa Jääskeläinen 		/*
22944137952dSVesa Jääskeläinen 		 * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER
22954137952dSVesa Jääskeläinen 		 * attributes may be modified after the object is created.
22964137952dSVesa Jääskeläinen 		 */
22974137952dSVesa Jääskeläinen 		switch (attr->id) {
22984137952dSVesa Jääskeläinen 		case PKCS11_CKA_ID:
22994137952dSVesa Jääskeläinen 		case PKCS11_CKA_ISSUER:
23004137952dSVesa Jääskeläinen 		case PKCS11_CKA_SERIAL_NUMBER:
23014137952dSVesa Jääskeläinen 			return true;
23024137952dSVesa Jääskeläinen 		default:
23034137952dSVesa Jääskeläinen 			break;
23044137952dSVesa Jääskeläinen 		}
23054137952dSVesa Jääskeläinen 		break;
23064137952dSVesa Jääskeläinen 	default:
23074137952dSVesa Jääskeläinen 		/* Unsupported certificate type */
23084137952dSVesa Jääskeläinen 		break;
23094137952dSVesa Jääskeläinen 	}
23104137952dSVesa Jääskeläinen 
23114137952dSVesa Jääskeläinen 	return false;
23124137952dSVesa Jääskeläinen }
23134137952dSVesa Jääskeläinen 
23142d25a9bcSRuchika Gupta static bool attribute_is_modifiable(struct pkcs11_session *session,
23152d25a9bcSRuchika Gupta 				    struct pkcs11_attribute_head *req_attr,
23162d25a9bcSRuchika Gupta 				    struct pkcs11_object *obj,
23172d25a9bcSRuchika Gupta 				    enum pkcs11_class_id class,
23182d25a9bcSRuchika Gupta 				    enum processing_func function)
23192d25a9bcSRuchika Gupta {
23202d25a9bcSRuchika Gupta 	/* Check modifiable attributes common to any object */
23212d25a9bcSRuchika Gupta 	switch (req_attr->id) {
23222d25a9bcSRuchika Gupta 	case PKCS11_CKA_LABEL:
23232d25a9bcSRuchika Gupta 		return true;
23242d25a9bcSRuchika Gupta 	case PKCS11_CKA_TOKEN:
23252d25a9bcSRuchika Gupta 	case PKCS11_CKA_MODIFIABLE:
23262d25a9bcSRuchika Gupta 	case PKCS11_CKA_DESTROYABLE:
23272d25a9bcSRuchika Gupta 	case PKCS11_CKA_PRIVATE:
23282d25a9bcSRuchika Gupta 		return function == PKCS11_FUNCTION_COPY;
23292d25a9bcSRuchika Gupta 	case PKCS11_CKA_COPYABLE:
23302d25a9bcSRuchika Gupta 		/*
23312d25a9bcSRuchika Gupta 		 * Specification mentions that if the attribute value is false
23322d25a9bcSRuchika Gupta 		 * it can't be set to true. Reading this we assume that it
23332d25a9bcSRuchika Gupta 		 * should be possible to modify this attribute even though this
23342d25a9bcSRuchika Gupta 		 * is not marked as modifiable in Table 10 if done in right
23352d25a9bcSRuchika Gupta 		 * direction i.e from TRUE -> FALSE.
23362d25a9bcSRuchika Gupta 		 */
23372d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, req_attr->id);
23382d25a9bcSRuchika Gupta 	default:
23392d25a9bcSRuchika Gupta 		break;
23402d25a9bcSRuchika Gupta 	}
23412d25a9bcSRuchika Gupta 
23422d25a9bcSRuchika Gupta 	/* Attribute checking based on class type */
23432d25a9bcSRuchika Gupta 	switch (class) {
23442d25a9bcSRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
23452d25a9bcSRuchika Gupta 	case PKCS11_CKO_PUBLIC_KEY:
23462d25a9bcSRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
23472d25a9bcSRuchika Gupta 		if (attr_is_modifiable_any_key(req_attr))
23482d25a9bcSRuchika Gupta 			return true;
23492d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_SECRET_KEY &&
23502d25a9bcSRuchika Gupta 		    attr_is_modifiable_secret_key(req_attr, session, obj))
23512d25a9bcSRuchika Gupta 			return true;
23522d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PUBLIC_KEY &&
23532d25a9bcSRuchika Gupta 		    attr_is_modifiable_public_key(req_attr, session, obj))
23542d25a9bcSRuchika Gupta 			return true;
23552d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PRIVATE_KEY &&
23562d25a9bcSRuchika Gupta 		    attr_is_modifiable_private_key(req_attr, session, obj))
23572d25a9bcSRuchika Gupta 			return true;
23582d25a9bcSRuchika Gupta 		break;
23592d25a9bcSRuchika Gupta 	case PKCS11_CKO_DATA:
23602d25a9bcSRuchika Gupta 		/* None of the data object attributes are modifiable */
23612d25a9bcSRuchika Gupta 		return false;
23624137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
23634137952dSVesa Jääskeläinen 		return attr_is_modifiable_certificate(req_attr, session, obj);
23642d25a9bcSRuchika Gupta 	default:
23652d25a9bcSRuchika Gupta 		break;
23662d25a9bcSRuchika Gupta 	}
23672d25a9bcSRuchika Gupta 
23682d25a9bcSRuchika Gupta 	return false;
23692d25a9bcSRuchika Gupta }
23702d25a9bcSRuchika Gupta 
23712d25a9bcSRuchika Gupta enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session,
23722d25a9bcSRuchika Gupta 						struct obj_attrs *head,
23732d25a9bcSRuchika Gupta 						struct pkcs11_object *obj,
23742d25a9bcSRuchika Gupta 						enum processing_func function)
23752d25a9bcSRuchika Gupta {
23762d25a9bcSRuchika Gupta 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
23772d25a9bcSRuchika Gupta 	char *cur = NULL;
23782d25a9bcSRuchika Gupta 	char *end = NULL;
23792d25a9bcSRuchika Gupta 	size_t len = 0;
23802d25a9bcSRuchika Gupta 
23812d25a9bcSRuchika Gupta 	class = get_class(obj->attributes);
23822d25a9bcSRuchika Gupta 
23832d25a9bcSRuchika Gupta 	cur = (char *)head + sizeof(struct obj_attrs);
23842d25a9bcSRuchika Gupta 	end = cur + head->attrs_size;
23852d25a9bcSRuchika Gupta 
23862d25a9bcSRuchika Gupta 	for (; cur < end; cur += len) {
23872d25a9bcSRuchika Gupta 		/* Structure aligned copy of the pkcs11_ref in the object */
23882d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head cli_ref = { };
23892d25a9bcSRuchika Gupta 
23902d25a9bcSRuchika Gupta 		TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
23912d25a9bcSRuchika Gupta 		len = sizeof(cli_ref) + cli_ref.size;
23922d25a9bcSRuchika Gupta 
2393981966bcSVesa Jääskeläinen 		/* Protect hidden attributes */
2394981966bcSVesa Jääskeläinen 		if (attribute_is_hidden(&cli_ref))
2395981966bcSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
2396981966bcSVesa Jääskeläinen 
23972d25a9bcSRuchika Gupta 		/*
23982d25a9bcSRuchika Gupta 		 * Check 1 - Check if attribute belongs to the object
23992d25a9bcSRuchika Gupta 		 * The obj->attributes has all the attributes in
24002d25a9bcSRuchika Gupta 		 * it which are allowed for an object.
24012d25a9bcSRuchika Gupta 		 */
24022d25a9bcSRuchika Gupta 		if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL,
24032d25a9bcSRuchika Gupta 				      NULL) == PKCS11_RV_NOT_FOUND)
24042d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
24052d25a9bcSRuchika Gupta 
24062d25a9bcSRuchika Gupta 		/* Check 2 - Is attribute modifiable */
24072d25a9bcSRuchika Gupta 		if (!attribute_is_modifiable(session, &cli_ref, obj, class,
24082d25a9bcSRuchika Gupta 					     function))
24092d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_READ_ONLY;
24102d25a9bcSRuchika Gupta 
24112d25a9bcSRuchika Gupta 		/*
24122d25a9bcSRuchika Gupta 		 * Checks for modification in PKCS11_CKA_TOKEN and
24132d25a9bcSRuchika Gupta 		 * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY
24142d25a9bcSRuchika Gupta 		 * only, so skip them for PKCS11_FUNCTION_MODIFY.
24152d25a9bcSRuchika Gupta 		 */
24162d25a9bcSRuchika Gupta 		if (function == PKCS11_FUNCTION_MODIFY)
24172d25a9bcSRuchika Gupta 			continue;
24182d25a9bcSRuchika Gupta 
24192d25a9bcSRuchika Gupta 		/*
24202d25a9bcSRuchika Gupta 		 * An attempt to copy an object to a token will fail for
24212d25a9bcSRuchika Gupta 		 * RO session
24222d25a9bcSRuchika Gupta 		 */
24232d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_TOKEN &&
24242d25a9bcSRuchika Gupta 		    get_bool(head, PKCS11_CKA_TOKEN)) {
24252d25a9bcSRuchika Gupta 			if (!pkcs11_session_is_read_write(session)) {
24262d25a9bcSRuchika Gupta 				DMSG("Can't copy to token in a RO session");
24272d25a9bcSRuchika Gupta 				return PKCS11_CKR_SESSION_READ_ONLY;
24282d25a9bcSRuchika Gupta 			}
24292d25a9bcSRuchika Gupta 		}
24302d25a9bcSRuchika Gupta 
24312d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_PRIVATE) {
24322d25a9bcSRuchika Gupta 			bool parent_priv =
24332d25a9bcSRuchika Gupta 				get_bool(obj->attributes, cli_ref.id);
24342d25a9bcSRuchika Gupta 			bool obj_priv = get_bool(head, cli_ref.id);
24352d25a9bcSRuchika Gupta 
24362d25a9bcSRuchika Gupta 			/*
24372d25a9bcSRuchika Gupta 			 * If PKCS11_CKA_PRIVATE is being set to TRUE from
24382d25a9bcSRuchika Gupta 			 * FALSE, user has to be logged in
24392d25a9bcSRuchika Gupta 			 */
24402d25a9bcSRuchika Gupta 			if (!parent_priv && obj_priv) {
24412d25a9bcSRuchika Gupta 				if ((pkcs11_session_is_public(session) ||
24422d25a9bcSRuchika Gupta 				     pkcs11_session_is_so(session)))
24432d25a9bcSRuchika Gupta 					return PKCS11_CKR_USER_NOT_LOGGED_IN;
24442d25a9bcSRuchika Gupta 			}
2445df017b2bSRuchika Gupta 
2446df017b2bSRuchika Gupta 			/*
2447df017b2bSRuchika Gupta 			 * Restriction added - Even for Copy, do not allow
2448df017b2bSRuchika Gupta 			 * modification of CKA_PRIVATE from TRUE to FALSE
2449df017b2bSRuchika Gupta 			 */
2450df017b2bSRuchika Gupta 			if (parent_priv && !obj_priv)
2451df017b2bSRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
24522d25a9bcSRuchika Gupta 		}
24532d25a9bcSRuchika Gupta 	}
24542d25a9bcSRuchika Gupta 
24552d25a9bcSRuchika Gupta 	return PKCS11_CKR_OK;
24562d25a9bcSRuchika Gupta }
24578c499324SRuchika Gupta 
24588c499324SRuchika Gupta static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
24598c499324SRuchika Gupta 					  size_t key_size)
24608c499324SRuchika Gupta {
24618c499324SRuchika Gupta 	uint32_t size = sizeof(uint32_t);
24628c499324SRuchika Gupta 	uint32_t key_length = 0;
24638c499324SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
24648c499324SRuchika Gupta 
24658c499324SRuchika Gupta 	/* Get key size if present in template */
24668c499324SRuchika Gupta 	rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size);
24678c499324SRuchika Gupta 	if (rc && rc != PKCS11_RV_NOT_FOUND)
24688c499324SRuchika Gupta 		return rc;
24698c499324SRuchika Gupta 
24708c499324SRuchika Gupta 	if (key_length) {
24718c499324SRuchika Gupta 		if (key_size < key_length)
24728c499324SRuchika Gupta 			return PKCS11_CKR_DATA_LEN_RANGE;
24738c499324SRuchika Gupta 	} else {
24748c499324SRuchika Gupta 		key_length = key_size;
24758c499324SRuchika Gupta 		rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length,
24768c499324SRuchika Gupta 				   sizeof(uint32_t));
24778c499324SRuchika Gupta 		if (rc)
24788c499324SRuchika Gupta 			return rc;
24798c499324SRuchika Gupta 	}
24808c499324SRuchika Gupta 
24818c499324SRuchika Gupta 	/* Now we can check the VALUE_LEN field */
24828c499324SRuchika Gupta 	rc = check_created_attrs(*head, NULL);
24838c499324SRuchika Gupta 	if (rc)
24848c499324SRuchika Gupta 		return rc;
24858c499324SRuchika Gupta 
24868c499324SRuchika Gupta 	/* Remove the default empty value attribute if found */
24878c499324SRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
24888c499324SRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
24898c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
24908c499324SRuchika Gupta 
2491bcac2127SMarouene Boubakri 	rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
2492bcac2127SMarouene Boubakri 	if (rc)
2493bcac2127SMarouene Boubakri 		return rc;
2494bcac2127SMarouene Boubakri 
2495bcac2127SMarouene Boubakri 	return set_check_value_attr(head);
24968c499324SRuchika Gupta }
24978c499324SRuchika Gupta 
249845d40bdaSValerii Chubar static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
249945d40bdaSValerii Chubar 					       void *data,
250045d40bdaSValerii Chubar 					       size_t key_size)
250145d40bdaSValerii Chubar {
250245d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
250345d40bdaSValerii Chubar 	int mbedtls_rc = 0;
250445d40bdaSValerii Chubar 	uint32_t key_bits = 0;
250545d40bdaSValerii Chubar 	uint32_t size = 0;
250645d40bdaSValerii Chubar 	uint32_t buffer_size = 0;
250745d40bdaSValerii Chubar 	void *buffer = NULL;
250845d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
250945d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
251045d40bdaSValerii Chubar 	mbedtls_mpi n = { };
251145d40bdaSValerii Chubar 	mbedtls_mpi e = { };
251245d40bdaSValerii Chubar 	mbedtls_mpi d = { };
251345d40bdaSValerii Chubar 	mbedtls_mpi p = { };
251445d40bdaSValerii Chubar 	mbedtls_mpi q = { };
251545d40bdaSValerii Chubar 
251645d40bdaSValerii Chubar 	rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits);
251745d40bdaSValerii Chubar 	if (rc && rc != PKCS11_RV_NOT_FOUND)
251845d40bdaSValerii Chubar 		return rc;
251945d40bdaSValerii Chubar 
252045d40bdaSValerii Chubar 	if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) ||
252145d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) ||
252245d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) ||
252345d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_1) ||
252445d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_2))
252545d40bdaSValerii Chubar 		return PKCS11_CKR_GENERAL_ERROR;
252645d40bdaSValerii Chubar 
252745d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
252845d40bdaSValerii Chubar 	mbedtls_mpi_init(&n);
252945d40bdaSValerii Chubar 	mbedtls_mpi_init(&e);
253045d40bdaSValerii Chubar 	mbedtls_mpi_init(&d);
253145d40bdaSValerii Chubar 	mbedtls_mpi_init(&p);
253245d40bdaSValerii Chubar 	mbedtls_mpi_init(&q);
253345d40bdaSValerii Chubar 
253432b31808SJens Wiklander 	mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size,
253532b31808SJens Wiklander 					  NULL, 0, mbd_rand, NULL);
253645d40bdaSValerii Chubar 	if (mbedtls_rc) {
253745d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
253845d40bdaSValerii Chubar 		goto out;
253945d40bdaSValerii Chubar 	}
254045d40bdaSValerii Chubar 
254145d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
254245d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
254345d40bdaSValerii Chubar 	if (mbedtls_rc) {
254445d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
254545d40bdaSValerii Chubar 		goto out;
254645d40bdaSValerii Chubar 	}
254745d40bdaSValerii Chubar 
254845d40bdaSValerii Chubar 	if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) {
254945d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
255045d40bdaSValerii Chubar 		goto out;
255145d40bdaSValerii Chubar 	}
255245d40bdaSValerii Chubar 
255345d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8);
255445d40bdaSValerii Chubar 	buffer_size = size;
255545d40bdaSValerii Chubar 	buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
255645d40bdaSValerii Chubar 	if (!buffer) {
255745d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
255845d40bdaSValerii Chubar 		goto out;
255945d40bdaSValerii Chubar 	}
256045d40bdaSValerii Chubar 
256145d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size);
256245d40bdaSValerii Chubar 	if (mbedtls_rc) {
256345d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
256445d40bdaSValerii Chubar 		goto out;
256545d40bdaSValerii Chubar 	}
256645d40bdaSValerii Chubar 
256745d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size);
256845d40bdaSValerii Chubar 	if (rc)
256945d40bdaSValerii Chubar 		goto out;
257045d40bdaSValerii Chubar 
257145d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8);
257245d40bdaSValerii Chubar 	if (buffer_size < size) {
257345d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
257445d40bdaSValerii Chubar 		goto out;
257545d40bdaSValerii Chubar 	}
257645d40bdaSValerii Chubar 
257745d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size);
257845d40bdaSValerii Chubar 	if (mbedtls_rc) {
257945d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
258045d40bdaSValerii Chubar 		goto out;
258145d40bdaSValerii Chubar 	}
258245d40bdaSValerii Chubar 
258345d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size);
258445d40bdaSValerii Chubar 	if (rc)
258545d40bdaSValerii Chubar 		goto out;
258645d40bdaSValerii Chubar 
258745d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8);
258845d40bdaSValerii Chubar 	if (buffer_size < size) {
258945d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
259045d40bdaSValerii Chubar 		goto out;
259145d40bdaSValerii Chubar 	}
259245d40bdaSValerii Chubar 
259345d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size);
259445d40bdaSValerii Chubar 	if (mbedtls_rc) {
259545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
259645d40bdaSValerii Chubar 		goto out;
259745d40bdaSValerii Chubar 	}
259845d40bdaSValerii Chubar 
259945d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size);
260045d40bdaSValerii Chubar 	if (rc)
260145d40bdaSValerii Chubar 		goto out;
260245d40bdaSValerii Chubar 
260345d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8);
260445d40bdaSValerii Chubar 	if (buffer_size < size) {
260545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
260645d40bdaSValerii Chubar 		goto out;
260745d40bdaSValerii Chubar 	}
260845d40bdaSValerii Chubar 
260945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size);
261045d40bdaSValerii Chubar 	if (mbedtls_rc) {
261145d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
261245d40bdaSValerii Chubar 		goto out;
261345d40bdaSValerii Chubar 	}
261445d40bdaSValerii Chubar 
261545d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size);
261645d40bdaSValerii Chubar 	if (rc)
261745d40bdaSValerii Chubar 		goto out;
261845d40bdaSValerii Chubar 
261945d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8);
262045d40bdaSValerii Chubar 	if (buffer_size < size) {
262145d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
262245d40bdaSValerii Chubar 		goto out;
262345d40bdaSValerii Chubar 	}
262445d40bdaSValerii Chubar 
262545d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size);
262645d40bdaSValerii Chubar 	if (mbedtls_rc) {
262745d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
262845d40bdaSValerii Chubar 		goto out;
262945d40bdaSValerii Chubar 	}
263045d40bdaSValerii Chubar 
263145d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size);
263245d40bdaSValerii Chubar 
263345d40bdaSValerii Chubar out:
263445d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
263545d40bdaSValerii Chubar 	mbedtls_mpi_free(&n);
263645d40bdaSValerii Chubar 	mbedtls_mpi_free(&e);
263745d40bdaSValerii Chubar 	mbedtls_mpi_free(&d);
263845d40bdaSValerii Chubar 	mbedtls_mpi_free(&p);
263945d40bdaSValerii Chubar 	mbedtls_mpi_free(&q);
264045d40bdaSValerii Chubar 	TEE_Free(buffer);
264145d40bdaSValerii Chubar 	return rc;
264245d40bdaSValerii Chubar }
264345d40bdaSValerii Chubar 
26448c499324SRuchika Gupta enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data,
26458c499324SRuchika Gupta 			    size_t key_size)
26468c499324SRuchika Gupta {
26478c499324SRuchika Gupta 	switch (get_class(*head)) {
26488c499324SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
26498c499324SRuchika Gupta 		return set_secret_key_data(head, data, key_size);
265045d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
265145d40bdaSValerii Chubar 		if (get_key_type(*head) == PKCS11_CKK_RSA)
265245d40bdaSValerii Chubar 			return set_private_key_data_rsa(head, data, key_size);
265345d40bdaSValerii Chubar 		break;
26548c499324SRuchika Gupta 	default:
26558c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
26568c499324SRuchika Gupta 	}
265745d40bdaSValerii Chubar 
265845d40bdaSValerii Chubar 	return PKCS11_CKR_GENERAL_ERROR;
26598c499324SRuchika Gupta }
26605e1d94ebSVesa Jääskeläinen 
2661a9aa45d8SValerii Chubar static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
2662a9aa45d8SValerii Chubar 						 void **data, uint32_t *sz)
2663a9aa45d8SValerii Chubar {
2664a9aa45d8SValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2665a9aa45d8SValerii Chubar 	void *buffer = NULL;
2666a9aa45d8SValerii Chubar 	void *value = NULL;
2667a9aa45d8SValerii Chubar 
2668a9aa45d8SValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz);
2669a9aa45d8SValerii Chubar 	if (rc)
2670a9aa45d8SValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
2671a9aa45d8SValerii Chubar 
2672a9aa45d8SValerii Chubar 	buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
2673a9aa45d8SValerii Chubar 	if (!buffer)
2674a9aa45d8SValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
2675a9aa45d8SValerii Chubar 
2676a9aa45d8SValerii Chubar 	TEE_MemMove(buffer, value, *sz);
2677a9aa45d8SValerii Chubar 	*data = buffer;
2678a9aa45d8SValerii Chubar 
2679a9aa45d8SValerii Chubar 	return PKCS11_CKR_OK;
2680a9aa45d8SValerii Chubar }
2681a9aa45d8SValerii Chubar 
268245d40bdaSValerii Chubar static enum pkcs11_rc
268345d40bdaSValerii Chubar encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
268445d40bdaSValerii Chubar {
268545d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
268645d40bdaSValerii Chubar 	int i = 0;
268745d40bdaSValerii Chubar 	int mbedtls_rc = 0;
268845d40bdaSValerii Chubar 	int start = 0;
268945d40bdaSValerii Chubar 	int der_size = 0;
269045d40bdaSValerii Chubar 	void *n = NULL;
269145d40bdaSValerii Chubar 	void *p = NULL;
269245d40bdaSValerii Chubar 	void *q = NULL;
269345d40bdaSValerii Chubar 	void *d = NULL;
269445d40bdaSValerii Chubar 	void *e = NULL;
269545d40bdaSValerii Chubar 	uint32_t n_len = 0;
269645d40bdaSValerii Chubar 	uint32_t p_len = 0;
269745d40bdaSValerii Chubar 	uint32_t q_len = 0;
269845d40bdaSValerii Chubar 	uint32_t d_len = 0;
269945d40bdaSValerii Chubar 	uint32_t e_len = 0;
270045d40bdaSValerii Chubar 	uint8_t *buffer = NULL;
270145d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
270245d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
270345d40bdaSValerii Chubar 	const mbedtls_pk_info_t *pk_info = NULL;
270445d40bdaSValerii Chubar 
270545d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
270645d40bdaSValerii Chubar 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
270745d40bdaSValerii Chubar 	if (mbedtls_pk_setup(&pk, pk_info)) {
270845d40bdaSValerii Chubar 		rc = PKCS11_CKR_GENERAL_ERROR;
270945d40bdaSValerii Chubar 		goto out;
271045d40bdaSValerii Chubar 	}
271145d40bdaSValerii Chubar 
271245d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len);
271345d40bdaSValerii Chubar 	if (rc)
271445d40bdaSValerii Chubar 		goto out;
271545d40bdaSValerii Chubar 
271645d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len);
271745d40bdaSValerii Chubar 	if (rc)
271845d40bdaSValerii Chubar 		goto out;
271945d40bdaSValerii Chubar 
272045d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len);
272145d40bdaSValerii Chubar 	if (rc)
272245d40bdaSValerii Chubar 		goto out;
272345d40bdaSValerii Chubar 
272445d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len);
272545d40bdaSValerii Chubar 	if (rc)
272645d40bdaSValerii Chubar 		goto out;
272745d40bdaSValerii Chubar 
272845d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len);
272945d40bdaSValerii Chubar 	if (rc)
273045d40bdaSValerii Chubar 		goto out;
273145d40bdaSValerii Chubar 
273245d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
273345d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
273445d40bdaSValerii Chubar 					    q, q_len, d, d_len, e, e_len);
273545d40bdaSValerii Chubar 	if (mbedtls_rc) {
273645d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
273745d40bdaSValerii Chubar 		goto out;
273845d40bdaSValerii Chubar 	}
273945d40bdaSValerii Chubar 
274045d40bdaSValerii Chubar 	if (mbedtls_rsa_complete(rsa)) {
274145d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
274245d40bdaSValerii Chubar 		goto out;
274345d40bdaSValerii Chubar 	}
274445d40bdaSValerii Chubar 
274545d40bdaSValerii Chubar 	if (mbedtls_rsa_check_privkey(rsa)) {
274645d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
274745d40bdaSValerii Chubar 		goto out;
274845d40bdaSValerii Chubar 	}
274945d40bdaSValerii Chubar 
275045d40bdaSValerii Chubar 	der_size = n_len * 8;
275145d40bdaSValerii Chubar 	buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
275245d40bdaSValerii Chubar 	if (!buffer) {
275345d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
275445d40bdaSValerii Chubar 		goto out;
275545d40bdaSValerii Chubar 	}
275645d40bdaSValerii Chubar 
275745d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size);
275845d40bdaSValerii Chubar 	if (mbedtls_rc < 0) {
275945d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
276045d40bdaSValerii Chubar 		goto out;
276145d40bdaSValerii Chubar 	}
276245d40bdaSValerii Chubar 
276345d40bdaSValerii Chubar 	start = der_size - mbedtls_rc;
276445d40bdaSValerii Chubar 	for (i = 0; i < mbedtls_rc; i++) {
276545d40bdaSValerii Chubar 		buffer[i] = buffer[i + start];
276645d40bdaSValerii Chubar 		buffer[i + start] = 0;
276745d40bdaSValerii Chubar 	}
276845d40bdaSValerii Chubar 
276945d40bdaSValerii Chubar 	*data = buffer;
277045d40bdaSValerii Chubar 	*sz = mbedtls_rc;
277145d40bdaSValerii Chubar out:
277245d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
277345d40bdaSValerii Chubar 
277445d40bdaSValerii Chubar 	if (rc)
277545d40bdaSValerii Chubar 		TEE_Free(buffer);
277645d40bdaSValerii Chubar 
277745d40bdaSValerii Chubar 	return rc;
277845d40bdaSValerii Chubar }
277945d40bdaSValerii Chubar 
2780a9aa45d8SValerii Chubar enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
27815f80f270SRuchika Gupta 				      uint32_t *sz)
27825f80f270SRuchika Gupta {
278345d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
278445d40bdaSValerii Chubar 
27855f80f270SRuchika Gupta 	switch (get_class(head)) {
27865f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
278745d40bdaSValerii Chubar 		rc = alloc_copy_attribute_value(head, data, sz);
278845d40bdaSValerii Chubar 		break;
278945d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
279045d40bdaSValerii Chubar 		if (get_key_type(head) == PKCS11_CKK_RSA)
279145d40bdaSValerii Chubar 			rc = encode_rsa_private_key_der(head, data, sz);
279245d40bdaSValerii Chubar 		break;
27935f80f270SRuchika Gupta 	default:
279445d40bdaSValerii Chubar 		break;
27955f80f270SRuchika Gupta 	}
27965f80f270SRuchika Gupta 
279745d40bdaSValerii Chubar 	return rc;
27985f80f270SRuchika Gupta }
27995f80f270SRuchika Gupta 
28005e1d94ebSVesa Jääskeläinen enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
28015e1d94ebSVesa Jääskeläinen 					struct obj_attrs **priv_head)
28025e1d94ebSVesa Jääskeläinen {
28035e1d94ebSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
28045e1d94ebSVesa Jääskeläinen 	void *id1 = NULL;
28055e1d94ebSVesa Jääskeläinen 	uint32_t id1_size = 0;
28065e1d94ebSVesa Jääskeläinen 	void *id2 = NULL;
28075e1d94ebSVesa Jääskeläinen 	uint32_t id2_size = 0;
28085e1d94ebSVesa Jääskeläinen 
28095e1d94ebSVesa Jääskeläinen 	assert(pub_head);
28105e1d94ebSVesa Jääskeläinen 	assert(priv_head);
28115e1d94ebSVesa Jääskeläinen 
28125e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size);
28135e1d94ebSVesa Jääskeläinen 	if (rc) {
28145e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28155e1d94ebSVesa Jääskeläinen 			return rc;
28165e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28175e1d94ebSVesa Jääskeläinen 	} else if (!id1_size) {
28185e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28195e1d94ebSVesa Jääskeläinen 	}
28205e1d94ebSVesa Jääskeläinen 
28215e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size);
28225e1d94ebSVesa Jääskeläinen 	if (rc) {
28235e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28245e1d94ebSVesa Jääskeläinen 			return rc;
28255e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28265e1d94ebSVesa Jääskeläinen 	} else if (!id2_size) {
28275e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28285e1d94ebSVesa Jääskeläinen 	}
28295e1d94ebSVesa Jääskeläinen 
28305e1d94ebSVesa Jääskeläinen 	/* Both have value -- let them be what caller has specified them */
28315e1d94ebSVesa Jääskeläinen 	if (id1 && id2)
28325e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28335e1d94ebSVesa Jääskeläinen 
28345e1d94ebSVesa Jääskeläinen 	/* Both are empty -- leave empty values */
28355e1d94ebSVesa Jääskeläinen 	if (!id1 && !id2)
28365e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28375e1d94ebSVesa Jääskeläinen 
28385e1d94ebSVesa Jääskeläinen 	/* Cross copy CKA_ID value */
28395e1d94ebSVesa Jääskeläinen 	if (id1)
28405e1d94ebSVesa Jääskeläinen 		return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size);
28415e1d94ebSVesa Jääskeläinen 	else
28425e1d94ebSVesa Jääskeläinen 		return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size);
28435e1d94ebSVesa Jääskeläinen }
2844bcac2127SMarouene Boubakri 
2845bcac2127SMarouene Boubakri /*
2846bcac2127SMarouene Boubakri  * The key check value is derived from the object by taking the first
2847bcac2127SMarouene Boubakri  * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute.
2848bcac2127SMarouene Boubakri  */
2849bcac2127SMarouene Boubakri static enum pkcs11_rc compute_check_value_with_sha1(void *key,
2850bcac2127SMarouene Boubakri 						    uint32_t key_size,
2851bcac2127SMarouene Boubakri 						    void *kcv)
2852bcac2127SMarouene Boubakri {
2853bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2854bcac2127SMarouene Boubakri 	TEE_Result res = TEE_ERROR_GENERIC;
2855bcac2127SMarouene Boubakri 	TEE_OperationHandle op = TEE_HANDLE_NULL;
2856bcac2127SMarouene Boubakri 	size_t buf_size = TEE_MAX_HASH_SIZE;
2857bcac2127SMarouene Boubakri 	uint8_t *buf = NULL;
2858bcac2127SMarouene Boubakri 
2859bcac2127SMarouene Boubakri 	assert(key && kcv);
2860bcac2127SMarouene Boubakri 
2861bcac2127SMarouene Boubakri 	res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0);
2862bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2863bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2864bcac2127SMarouene Boubakri 		goto out;
2865bcac2127SMarouene Boubakri 
2866bcac2127SMarouene Boubakri 	buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO);
2867bcac2127SMarouene Boubakri 	if (!buf) {
2868bcac2127SMarouene Boubakri 		rc = PKCS11_CKR_DEVICE_MEMORY;
2869bcac2127SMarouene Boubakri 		goto out;
2870bcac2127SMarouene Boubakri 	}
2871bcac2127SMarouene Boubakri 
2872bcac2127SMarouene Boubakri 	res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size);
2873bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2874bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2875bcac2127SMarouene Boubakri 		goto out;
2876bcac2127SMarouene Boubakri 
2877bcac2127SMarouene Boubakri 	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
2878bcac2127SMarouene Boubakri 
2879bcac2127SMarouene Boubakri out:
2880bcac2127SMarouene Boubakri 	TEE_Free(buf);
2881bcac2127SMarouene Boubakri 	TEE_FreeOperation(op);
2882bcac2127SMarouene Boubakri 
2883bcac2127SMarouene Boubakri 	return rc;
2884bcac2127SMarouene Boubakri }
2885bcac2127SMarouene Boubakri 
2886bcac2127SMarouene Boubakri /*
2887bcac2127SMarouene Boubakri  * The key check value that is calculated as follows:
2888bcac2127SMarouene Boubakri  * 1) Take a buffer of the cipher block size of binary zeros (0x00).
2889bcac2127SMarouene Boubakri  * 2) Encrypt this block in ECB mode.
2890bcac2127SMarouene Boubakri  * 3) Take the first three bytes of cipher text as the check value.
2891bcac2127SMarouene Boubakri  */
2892bcac2127SMarouene Boubakri static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size,
2893bcac2127SMarouene Boubakri 						   void *kcv)
2894bcac2127SMarouene Boubakri {
2895bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2896bcac2127SMarouene Boubakri 	TEE_Result res = TEE_ERROR_GENERIC;
2897bcac2127SMarouene Boubakri 	TEE_OperationHandle op = TEE_HANDLE_NULL;
2898bcac2127SMarouene Boubakri 	TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
2899bcac2127SMarouene Boubakri 	TEE_Attribute attr = { };
2900adfad2cdSEtienne Carriere 	uint8_t buf[TEE_AES_BLOCK_SIZE] = { };
2901adfad2cdSEtienne Carriere 	size_t buf_size = sizeof(buf);
2902bcac2127SMarouene Boubakri 
2903bcac2127SMarouene Boubakri 	assert(key && kcv);
2904bcac2127SMarouene Boubakri 
2905bcac2127SMarouene Boubakri 	res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD,
2906bcac2127SMarouene Boubakri 				    TEE_MODE_ENCRYPT, key_size * 8);
2907bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2908bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2909bcac2127SMarouene Boubakri 		goto out;
2910bcac2127SMarouene Boubakri 
2911bcac2127SMarouene Boubakri 	res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey);
2912bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2913bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2914bcac2127SMarouene Boubakri 		goto out;
2915bcac2127SMarouene Boubakri 
29163bc92b91SEtienne Carriere 	TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size);
2917bcac2127SMarouene Boubakri 
2918bcac2127SMarouene Boubakri 	res = TEE_PopulateTransientObject(hkey, &attr, 1);
2919bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2920bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2921bcac2127SMarouene Boubakri 		goto out;
2922bcac2127SMarouene Boubakri 
2923bcac2127SMarouene Boubakri 	res = TEE_SetOperationKey(op, hkey);
2924bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2925bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2926bcac2127SMarouene Boubakri 		goto out;
2927bcac2127SMarouene Boubakri 
2928bcac2127SMarouene Boubakri 	TEE_CipherInit(op, NULL, 0);
2929bcac2127SMarouene Boubakri 
2930bcac2127SMarouene Boubakri 	res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size);
2931bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2932bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2933bcac2127SMarouene Boubakri 		goto out;
2934bcac2127SMarouene Boubakri 
2935bcac2127SMarouene Boubakri 	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
2936bcac2127SMarouene Boubakri 
2937bcac2127SMarouene Boubakri out:
2938bcac2127SMarouene Boubakri 	TEE_FreeTransientObject(hkey);
2939bcac2127SMarouene Boubakri 	TEE_FreeOperation(op);
2940bcac2127SMarouene Boubakri 
2941bcac2127SMarouene Boubakri 	return rc;
2942bcac2127SMarouene Boubakri }
2943bcac2127SMarouene Boubakri 
2944bcac2127SMarouene Boubakri enum pkcs11_rc set_check_value_attr(struct obj_attrs **head)
2945bcac2127SMarouene Boubakri {
2946bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2947bcac2127SMarouene Boubakri 	uint32_t val_len = 0;
2948bcac2127SMarouene Boubakri 	uint32_t kcv2_len = 0;
2949bcac2127SMarouene Boubakri 	void *val = NULL;
2950bcac2127SMarouene Boubakri 	uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { };
2951bcac2127SMarouene Boubakri 	void *kcv2 = NULL;
2952bcac2127SMarouene Boubakri 
2953bcac2127SMarouene Boubakri 	assert(head && *head);
2954bcac2127SMarouene Boubakri 
2955bcac2127SMarouene Boubakri 	if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE))
2956bcac2127SMarouene Boubakri 		return PKCS11_CKR_OK;
2957bcac2127SMarouene Boubakri 
2958bcac2127SMarouene Boubakri 	switch (get_class(*head)) {
2959bcac2127SMarouene Boubakri 	case PKCS11_CKO_SECRET_KEY:
2960bcac2127SMarouene Boubakri 	case PKCS11_CKO_CERTIFICATE:
2961bcac2127SMarouene Boubakri 		break;
2962bcac2127SMarouene Boubakri 	default:
2963cfbe7874SEtienne Carriere 		/* Nothing to do */
2964cfbe7874SEtienne Carriere 		return PKCS11_CKR_OK;
2965bcac2127SMarouene Boubakri 	}
2966bcac2127SMarouene Boubakri 
2967bcac2127SMarouene Boubakri 	/* Check whether CKA_CHECK_VALUE has been provided in the template */
2968bcac2127SMarouene Boubakri 	rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len);
2969bcac2127SMarouene Boubakri 
2970bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
2971bcac2127SMarouene Boubakri 		return PKCS11_CKR_GENERAL_ERROR;
2972bcac2127SMarouene Boubakri 
2973bcac2127SMarouene Boubakri 	/*
2974bcac2127SMarouene Boubakri 	 * The generation of the KCV may be prevented by the application
2975bcac2127SMarouene Boubakri 	 * supplying the attribute in the template as a no-value (0 length)
2976bcac2127SMarouene Boubakri 	 * entry.
2977bcac2127SMarouene Boubakri 	 */
2978bcac2127SMarouene Boubakri 	if (rc == PKCS11_CKR_OK && !kcv2_len)
2979bcac2127SMarouene Boubakri 		return PKCS11_CKR_OK;
2980bcac2127SMarouene Boubakri 
2981bcac2127SMarouene Boubakri 	if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE)
2982*2ea9746dSEtienne Carriere 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
2983bcac2127SMarouene Boubakri 
2984bcac2127SMarouene Boubakri 	/* Get key CKA_VALUE */
2985bcac2127SMarouene Boubakri 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len);
2986bcac2127SMarouene Boubakri 	if (rc)
2987bcac2127SMarouene Boubakri 		return rc;
2988bcac2127SMarouene Boubakri 
2989bcac2127SMarouene Boubakri 	if (get_class(*head) == PKCS11_CKO_SECRET_KEY) {
2990bcac2127SMarouene Boubakri 		switch (get_key_type(*head)) {
2991bcac2127SMarouene Boubakri 		case PKCS11_CKK_AES:
2992bcac2127SMarouene Boubakri 			rc = compute_check_value_with_ecb(val, val_len, kcv);
2993bcac2127SMarouene Boubakri 			break;
2994bcac2127SMarouene Boubakri 		case PKCS11_CKK_GENERIC_SECRET:
2995bcac2127SMarouene Boubakri 		case PKCS11_CKK_MD5_HMAC:
2996bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA_1_HMAC:
2997bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA256_HMAC:
2998bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA384_HMAC:
2999bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA512_HMAC:
3000bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA224_HMAC:
3001bcac2127SMarouene Boubakri 			rc = compute_check_value_with_sha1(val, val_len, kcv);
3002bcac2127SMarouene Boubakri 			break;
3003bcac2127SMarouene Boubakri 		default:
3004bcac2127SMarouene Boubakri 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
3005bcac2127SMarouene Boubakri 			break;
3006bcac2127SMarouene Boubakri 		}
3007bcac2127SMarouene Boubakri 	} else {
3008bcac2127SMarouene Boubakri 		rc = compute_check_value_with_sha1(val, val_len, kcv);
3009bcac2127SMarouene Boubakri 	}
3010bcac2127SMarouene Boubakri 
3011bcac2127SMarouene Boubakri 	if (rc)
3012bcac2127SMarouene Boubakri 		return rc;
3013bcac2127SMarouene Boubakri 
3014bcac2127SMarouene Boubakri 	/*
3015bcac2127SMarouene Boubakri 	 * If the computed KCV does not match the provided one
3016bcac2127SMarouene Boubakri 	 * then return CKR_ATTRIBUTE_VALUE_INVALID
3017bcac2127SMarouene Boubakri 	 */
3018bcac2127SMarouene Boubakri 	if (kcv2_len) {
3019bcac2127SMarouene Boubakri 		/* Provided KCV value shall match the computed one */
3020bcac2127SMarouene Boubakri 		if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE))
3021bcac2127SMarouene Boubakri 			rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
3022bcac2127SMarouene Boubakri 	} else {
3023bcac2127SMarouene Boubakri 		rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv,
3024bcac2127SMarouene Boubakri 				   PKCS11_CKA_CHECK_VALUE_SIZE);
3025bcac2127SMarouene Boubakri 	}
3026bcac2127SMarouene Boubakri 
3027bcac2127SMarouene Boubakri 	return rc;
3028bcac2127SMarouene Boubakri }
3029