xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 04e46975d8f02e25209af552aaea4acb4d70c7f9)
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 <tee_internal_api_extensions.h>
1563f89caaSJens Wiklander #include <tee_internal_api.h>
166a760c9eSEtienne Carriere #include <trace.h>
1763f89caaSJens Wiklander #include <util.h>
1863f89caaSJens Wiklander 
1963f89caaSJens Wiklander #include "attributes.h"
2063f89caaSJens Wiklander #include "handle.h"
2163f89caaSJens Wiklander #include "pkcs11_attributes.h"
2263f89caaSJens Wiklander #include "pkcs11_helpers.h"
2363f89caaSJens Wiklander #include "pkcs11_token.h"
247c243321SVesa Jääskeläinen #include "processing.h"
2563f89caaSJens Wiklander #include "sanitize_object.h"
2663f89caaSJens Wiklander #include "serializer.h"
2763f89caaSJens Wiklander #include "token_capabilities.h"
2863f89caaSJens Wiklander 
pkcs11_func2ckfm(enum processing_func function)29512cbf1dSJens Wiklander static uint32_t pkcs11_func2ckfm(enum processing_func function)
30512cbf1dSJens Wiklander {
31512cbf1dSJens Wiklander 	switch (function) {
32512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
33512cbf1dSJens Wiklander 		return PKCS11_CKFM_DIGEST;
34512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE:
35512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE;
36512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE_PAIR:
37512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE_KEY_PAIR;
38512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
39512cbf1dSJens Wiklander 		return PKCS11_CKFM_DERIVE;
40512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
41512cbf1dSJens Wiklander 		return PKCS11_CKFM_WRAP;
42512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
43512cbf1dSJens Wiklander 		return PKCS11_CKFM_UNWRAP;
44512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
45512cbf1dSJens Wiklander 		return PKCS11_CKFM_ENCRYPT;
46512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
47512cbf1dSJens Wiklander 		return PKCS11_CKFM_DECRYPT;
48512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
49512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN;
50512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
51512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY;
52512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
53512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN_RECOVER;
54512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
55512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY_RECOVER;
56512cbf1dSJens Wiklander 	default:
57512cbf1dSJens Wiklander 		return 0;
58512cbf1dSJens Wiklander 	}
59512cbf1dSJens Wiklander }
60512cbf1dSJens Wiklander 
61512cbf1dSJens Wiklander enum pkcs11_rc
check_mechanism_against_processing(struct pkcs11_session * session,enum pkcs11_mechanism_id mechanism_type,enum processing_func function,enum processing_step step)62512cbf1dSJens Wiklander check_mechanism_against_processing(struct pkcs11_session *session,
63512cbf1dSJens Wiklander 				   enum pkcs11_mechanism_id mechanism_type,
64512cbf1dSJens Wiklander 				   enum processing_func function,
65512cbf1dSJens Wiklander 				   enum processing_step step)
66512cbf1dSJens Wiklander {
67512cbf1dSJens Wiklander 	bool allowed = false;
68512cbf1dSJens Wiklander 
69512cbf1dSJens Wiklander 	switch (step) {
70512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_INIT:
71512cbf1dSJens Wiklander 		switch (function) {
72512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_IMPORT:
73512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_COPY:
74512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_MODIFY:
75512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DESTROY:
76512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
77512cbf1dSJens Wiklander 		default:
78512cbf1dSJens Wiklander 			break;
79512cbf1dSJens Wiklander 		}
80512cbf1dSJens Wiklander 		/*
81512cbf1dSJens Wiklander 		 * Check that the returned PKCS11_CKFM_* flag from
82512cbf1dSJens Wiklander 		 * pkcs11_func2ckfm() is among the ones from
83512cbf1dSJens Wiklander 		 * mechanism_supported_flags().
84512cbf1dSJens Wiklander 		 */
85512cbf1dSJens Wiklander 		allowed = mechanism_supported_flags(mechanism_type) &
86512cbf1dSJens Wiklander 			  pkcs11_func2ckfm(function);
87512cbf1dSJens Wiklander 		break;
88512cbf1dSJens Wiklander 
89512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_ONESHOT:
900460a039SRuchika Gupta 		if (session->processing->always_authen &&
910460a039SRuchika Gupta 		    !session->processing->relogged)
920460a039SRuchika Gupta 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
930460a039SRuchika Gupta 
942364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_UPDATE ||
952364aa69SRuchika Gupta 		    session->processing->step == PKCS11_FUNC_STEP_FINAL) {
962364aa69SRuchika Gupta 			EMSG("Cannot perform one-shot on active processing");
970460a039SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
980460a039SRuchika Gupta 		}
990460a039SRuchika Gupta 
1000460a039SRuchika Gupta 		allowed = true;
1010460a039SRuchika Gupta 		break;
1020460a039SRuchika Gupta 
103512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
104512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
105512cbf1dSJens Wiklander 		    !session->processing->relogged)
106512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
107512cbf1dSJens Wiklander 
1082364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT ||
1092364aa69SRuchika Gupta 		    session->processing->step == PKCS11_FUNC_STEP_FINAL) {
1102364aa69SRuchika Gupta 			EMSG("Cannot perform update on finalized processing");
1112364aa69SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
1122364aa69SRuchika Gupta 		}
1132364aa69SRuchika Gupta 
114512cbf1dSJens Wiklander 		allowed = !mechanism_is_one_shot_only(mechanism_type);
115512cbf1dSJens Wiklander 		break;
116512cbf1dSJens Wiklander 
1179e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
1189e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
1199e91a619SVesa Jääskeläinen 
1209e91a619SVesa Jääskeläinen 		if (session->processing->always_authen &&
1219e91a619SVesa Jääskeläinen 		    !session->processing->relogged)
1229e91a619SVesa Jääskeläinen 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
1239e91a619SVesa Jääskeläinen 
1249e91a619SVesa Jääskeläinen 		allowed = true;
1259e91a619SVesa Jääskeläinen 		break;
1269e91a619SVesa Jääskeläinen 
127512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_FINAL:
128512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
129512cbf1dSJens Wiklander 		    !session->processing->relogged)
130512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
131512cbf1dSJens Wiklander 
1322364aa69SRuchika Gupta 		if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT) {
1332364aa69SRuchika Gupta 			EMSG("Cannot perform final on oneshot processing");
1342364aa69SRuchika Gupta 			return PKCS11_CKR_OPERATION_ACTIVE;
1352364aa69SRuchika Gupta 		}
136512cbf1dSJens Wiklander 		return PKCS11_CKR_OK;
137512cbf1dSJens Wiklander 
138512cbf1dSJens Wiklander 	default:
139512cbf1dSJens Wiklander 		TEE_Panic(step);
140512cbf1dSJens Wiklander 		break;
141512cbf1dSJens Wiklander 	}
142512cbf1dSJens Wiklander 
143512cbf1dSJens Wiklander 	if (!allowed) {
144512cbf1dSJens Wiklander 		EMSG("Processing %#x/%s not permitted (%u/%u)",
145512cbf1dSJens Wiklander 		     (unsigned int)mechanism_type, id2str_proc(mechanism_type),
146512cbf1dSJens Wiklander 		     function, step);
147df705578SRuchika Gupta 		return PKCS11_CKR_MECHANISM_INVALID;
148512cbf1dSJens Wiklander 	}
149512cbf1dSJens Wiklander 
150512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
151512cbf1dSJens Wiklander }
152512cbf1dSJens Wiklander 
15363f89caaSJens Wiklander /*
15463f89caaSJens Wiklander  * Object default boolean attributes as per PKCS#11
15563f89caaSJens Wiklander  */
pkcs11_object_default_boolprop(uint32_t attribute)15663f89caaSJens Wiklander static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute)
15763f89caaSJens Wiklander {
15863f89caaSJens Wiklander 	static const uint8_t bool_true = 1;
15963f89caaSJens Wiklander 	static const uint8_t bool_false;
16063f89caaSJens Wiklander 
16163f89caaSJens Wiklander 	switch (attribute) {
16263f89caaSJens Wiklander 	/* As per PKCS#11 default value */
16363f89caaSJens Wiklander 	case PKCS11_CKA_MODIFIABLE:
16463f89caaSJens Wiklander 	case PKCS11_CKA_COPYABLE:
16563f89caaSJens Wiklander 	case PKCS11_CKA_DESTROYABLE:
16663f89caaSJens Wiklander 		return (uint8_t *)&bool_true;
16763f89caaSJens Wiklander 	case PKCS11_CKA_TOKEN:
16863f89caaSJens Wiklander 	case PKCS11_CKA_PRIVATE:
16939fc24faSEtienne Carriere 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
17039fc24faSEtienne Carriere 	case PKCS11_CKA_ALWAYS_AUTHENTICATE:
17163f89caaSJens Wiklander 	case PKCS11_CKA_SENSITIVE:
17263f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
17363f89caaSJens Wiklander 	/* Token specific default value */
17463f89caaSJens Wiklander 	case PKCS11_CKA_SIGN:
17563f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY:
17663f89caaSJens Wiklander 	case PKCS11_CKA_DERIVE:
17763f89caaSJens Wiklander 	case PKCS11_CKA_ENCRYPT:
17863f89caaSJens Wiklander 	case PKCS11_CKA_DECRYPT:
17963f89caaSJens Wiklander 	case PKCS11_CKA_SIGN_RECOVER:
18063f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY_RECOVER:
18163f89caaSJens Wiklander 	case PKCS11_CKA_WRAP:
18263f89caaSJens Wiklander 	case PKCS11_CKA_UNWRAP:
18363f89caaSJens Wiklander 	case PKCS11_CKA_EXTRACTABLE:
18463f89caaSJens Wiklander 	case PKCS11_CKA_TRUSTED:
18563f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
18663f89caaSJens Wiklander 	default:
18763f89caaSJens Wiklander 		DMSG("No default for boolprop attribute %#"PRIx32, attribute);
18863f89caaSJens Wiklander 		return NULL;
18963f89caaSJens Wiklander 	}
19063f89caaSJens Wiklander }
19163f89caaSJens Wiklander 
19263f89caaSJens Wiklander /*
19363f89caaSJens Wiklander  * Object expects several boolean attributes to be set to a default value
19463f89caaSJens Wiklander  * or to a validate client configuration value. This function append the input
19563f89caaSJens Wiklander  * attribute (id/size/value) in the serialized object.
19663f89caaSJens Wiklander  */
pkcs11_import_object_boolprop(struct obj_attrs ** out,struct obj_attrs * templ,uint32_t attribute)19763f89caaSJens Wiklander static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out,
19863f89caaSJens Wiklander 						    struct obj_attrs *templ,
19963f89caaSJens Wiklander 						    uint32_t attribute)
20063f89caaSJens Wiklander {
20163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
20263f89caaSJens Wiklander 	uint8_t bbool = 0;
20363f89caaSJens Wiklander 	uint32_t size = sizeof(uint8_t);
20463f89caaSJens Wiklander 	void *attr = NULL;
20563f89caaSJens Wiklander 
20663f89caaSJens Wiklander 	rc = get_attribute(templ, attribute, &bbool, &size);
20763f89caaSJens Wiklander 	if (rc) {
20863f89caaSJens Wiklander 		if (rc != PKCS11_RV_NOT_FOUND)
20963f89caaSJens Wiklander 			return rc;
21063f89caaSJens Wiklander 		attr = pkcs11_object_default_boolprop(attribute);
21163f89caaSJens Wiklander 		if (!attr)
21263f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
21363f89caaSJens Wiklander 	} else {
21463f89caaSJens Wiklander 		attr = &bbool;
21563f89caaSJens Wiklander 	}
21663f89caaSJens Wiklander 
21763f89caaSJens Wiklander 	/* Boolean attributes are 1byte in the ABI, no alignment issue */
21863f89caaSJens Wiklander 	return add_attribute(out, attribute, attr, sizeof(uint8_t));
21963f89caaSJens Wiklander }
22063f89caaSJens Wiklander 
set_mandatory_boolprops(struct obj_attrs ** out,struct obj_attrs * temp,uint32_t const * bp,size_t bp_count)22163f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out,
22263f89caaSJens Wiklander 					      struct obj_attrs *temp,
22363f89caaSJens Wiklander 					      uint32_t const *bp,
22463f89caaSJens Wiklander 					      size_t bp_count)
22563f89caaSJens Wiklander {
22663f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
22763f89caaSJens Wiklander 	size_t n = 0;
22863f89caaSJens Wiklander 
22963f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
23063f89caaSJens Wiklander 		rc = pkcs11_import_object_boolprop(out, temp, bp[n]);
23163f89caaSJens Wiklander 		if (rc)
23263f89caaSJens Wiklander 			return rc;
23363f89caaSJens Wiklander 	}
23463f89caaSJens Wiklander 
23563f89caaSJens Wiklander 	return rc;
23663f89caaSJens Wiklander }
23763f89caaSJens Wiklander 
set_mandatory_attributes(struct obj_attrs ** out,struct obj_attrs * temp,uint32_t const * attrs,size_t attrs_count)23863f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out,
23963f89caaSJens Wiklander 					       struct obj_attrs *temp,
24016df60c7SEtienne Carriere 					       uint32_t const *attrs,
24116df60c7SEtienne Carriere 					       size_t attrs_count)
24263f89caaSJens Wiklander {
24363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
24463f89caaSJens Wiklander 	size_t n = 0;
24563f89caaSJens Wiklander 
24616df60c7SEtienne Carriere 	for (n = 0; n < attrs_count; n++) {
24763f89caaSJens Wiklander 		uint32_t size = 0;
24863f89caaSJens Wiklander 		void *value = NULL;
24963f89caaSJens Wiklander 
25016df60c7SEtienne Carriere 		if (get_attribute_ptr(temp, attrs[n], &value, &size))
25163f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
25263f89caaSJens Wiklander 
25316df60c7SEtienne Carriere 		rc = add_attribute(out, attrs[n], value, size);
25463f89caaSJens Wiklander 		if (rc)
25563f89caaSJens Wiklander 			return rc;
25663f89caaSJens Wiklander 	}
25763f89caaSJens Wiklander 
25863f89caaSJens Wiklander 	return rc;
25963f89caaSJens Wiklander }
26063f89caaSJens Wiklander 
get_default_value(enum pkcs11_attr_id id __maybe_unused,void ** value,uint32_t * size)261897aaf11SEtienne Carriere static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id __maybe_unused,
262897aaf11SEtienne Carriere 					void **value, uint32_t *size)
26363f89caaSJens Wiklander {
26463f89caaSJens Wiklander 	/* should have been taken care of already */
26563f89caaSJens Wiklander 	assert(!pkcs11_attr_is_boolean(id));
26663f89caaSJens Wiklander 
26763f89caaSJens Wiklander 	/* All other attributes have an empty default value */
26863f89caaSJens Wiklander 	*value = NULL;
26963f89caaSJens Wiklander 	*size = 0;
27063f89caaSJens Wiklander 	return PKCS11_CKR_OK;
27163f89caaSJens Wiklander }
27263f89caaSJens Wiklander 
set_optional_attributes_with_def(struct obj_attrs ** out,struct obj_attrs * temp,uint32_t const * attrs,size_t attrs_count,bool default_to_null)2734eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out,
27463f89caaSJens Wiklander 						       struct obj_attrs *temp,
27516df60c7SEtienne Carriere 						       uint32_t const *attrs,
27616df60c7SEtienne Carriere 						       size_t attrs_count,
2774eb88651SRuchika Gupta 						       bool default_to_null)
27863f89caaSJens Wiklander {
27963f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
28063f89caaSJens Wiklander 	size_t n = 0;
28163f89caaSJens Wiklander 
28216df60c7SEtienne Carriere 	for (n = 0; n < attrs_count; n++) {
28363f89caaSJens Wiklander 		uint32_t size = 0;
28463f89caaSJens Wiklander 		void *value = NULL;
28563f89caaSJens Wiklander 
28616df60c7SEtienne Carriere 		rc = get_attribute_ptr(temp, attrs[n], &value, &size);
2874eb88651SRuchika Gupta 		if (rc == PKCS11_RV_NOT_FOUND) {
2884eb88651SRuchika Gupta 			if (default_to_null) {
28916df60c7SEtienne Carriere 				rc = get_default_value(attrs[n], &value, &size);
2904eb88651SRuchika Gupta 			} else {
2914eb88651SRuchika Gupta 				rc = PKCS11_CKR_OK;
2924eb88651SRuchika Gupta 				continue;
2934eb88651SRuchika Gupta 			}
2944eb88651SRuchika Gupta 		}
29563f89caaSJens Wiklander 		if (rc)
29663f89caaSJens Wiklander 			return rc;
29763f89caaSJens Wiklander 
29816df60c7SEtienne Carriere 		rc = add_attribute(out, attrs[n], value, size);
29963f89caaSJens Wiklander 		if (rc)
30063f89caaSJens Wiklander 			return rc;
30163f89caaSJens Wiklander 	}
30263f89caaSJens Wiklander 
30363f89caaSJens Wiklander 	return rc;
30463f89caaSJens Wiklander }
30563f89caaSJens Wiklander 
set_attributes_opt_or_null(struct obj_attrs ** out,struct obj_attrs * temp,uint32_t const * attrs,size_t attrs_count)3064eb88651SRuchika Gupta static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out,
3074eb88651SRuchika Gupta 						 struct obj_attrs *temp,
30816df60c7SEtienne Carriere 						 uint32_t const *attrs,
30916df60c7SEtienne Carriere 						 size_t attrs_count)
3104eb88651SRuchika Gupta {
31116df60c7SEtienne Carriere 	return set_optional_attributes_with_def(out, temp, attrs, attrs_count,
31216df60c7SEtienne Carriere 						true /* defaults to empty */);
3134eb88651SRuchika Gupta }
3144eb88651SRuchika Gupta 
set_optional_attributes(struct obj_attrs ** out,struct obj_attrs * temp,uint32_t const * attrs,size_t attrs_count)3154eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out,
3164eb88651SRuchika Gupta 					      struct obj_attrs *temp,
31716df60c7SEtienne Carriere 					      uint32_t const *attrs,
31816df60c7SEtienne Carriere 					      size_t attrs_count)
3194eb88651SRuchika Gupta {
32016df60c7SEtienne Carriere 	return set_optional_attributes_with_def(out, temp, attrs, attrs_count,
32116df60c7SEtienne Carriere 						false /* no default value */);
3224eb88651SRuchika Gupta }
3234eb88651SRuchika Gupta 
32463f89caaSJens Wiklander /*
32563f89caaSJens Wiklander  * Below are listed the mandated or optional expected attributes for
32663f89caaSJens Wiklander  * PKCS#11 storage objects.
32763f89caaSJens Wiklander  *
32863f89caaSJens Wiklander  * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE,
32963f89caaSJens Wiklander  * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided
33063f89caaSJens Wiklander  * in the client template.
33163f89caaSJens Wiklander  */
33263f89caaSJens Wiklander 
33363f89caaSJens Wiklander /* PKCS#11 specification for any object (session/token) of the storage */
3344eb88651SRuchika Gupta static const uint32_t any_object_boolprops[] = {
33563f89caaSJens Wiklander 	PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
33663f89caaSJens Wiklander 	PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE,
33763f89caaSJens Wiklander };
33863f89caaSJens Wiklander 
3394eb88651SRuchika Gupta static const uint32_t any_object_opt_or_null[] = {
34063f89caaSJens Wiklander 	PKCS11_CKA_LABEL,
34163f89caaSJens Wiklander };
34263f89caaSJens Wiklander 
3434eb88651SRuchika Gupta /* PKCS#11 specification for raw data object (+any_object_xxx) */
3444eb88651SRuchika Gupta const uint32_t raw_data_opt_or_null[] = {
34563f89caaSJens Wiklander 	PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE,
34663f89caaSJens Wiklander };
34763f89caaSJens Wiklander 
3484137952dSVesa Jääskeläinen /* PKCS#11 specification for certificate object (+pkcs11_any_object_xxx) */
3494137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_mandated[] = {
3504137952dSVesa Jääskeläinen 	PKCS11_CKA_CERTIFICATE_TYPE,
3514137952dSVesa Jääskeläinen };
3524137952dSVesa Jääskeläinen 
3534137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_boolprops[] = {
3544137952dSVesa Jääskeläinen 	PKCS11_CKA_TRUSTED,
3554137952dSVesa Jääskeläinen };
3564137952dSVesa Jääskeläinen 
3574137952dSVesa Jääskeläinen static const uint32_t pkcs11_certificate_optional[] = {
358bcac2127SMarouene Boubakri 	PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_START_DATE,
359bcac2127SMarouene Boubakri 	PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO,
360bcac2127SMarouene Boubakri #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
361bcac2127SMarouene Boubakri 	/* Consider KCV attribute only when supported */
362bcac2127SMarouene Boubakri 	PKCS11_CKA_CHECK_VALUE,
363bcac2127SMarouene Boubakri #endif
3644137952dSVesa Jääskeläinen };
3654137952dSVesa Jääskeläinen 
3664137952dSVesa Jääskeläinen /*
3674137952dSVesa Jääskeläinen  * PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx)
3684137952dSVesa Jääskeläinen  */
3694137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_mandated[] = {
3704137952dSVesa Jääskeläinen 	PKCS11_CKA_SUBJECT,
3714137952dSVesa Jääskeläinen };
3724137952dSVesa Jääskeläinen 
3734137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_optional[] = {
3744137952dSVesa Jääskeläinen 	PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER,
3754137952dSVesa Jääskeläinen 	PKCS11_CKA_VALUE, PKCS11_CKA_URL,
3764137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
3774137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
3784137952dSVesa Jääskeläinen 	PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM,
3794137952dSVesa Jääskeläinen };
3804137952dSVesa Jääskeläinen 
3814eb88651SRuchika Gupta /* PKCS#11 specification for any key object (+any_object_xxx) */
3824eb88651SRuchika Gupta static const uint32_t any_key_boolprops[] = {
38363f89caaSJens Wiklander 	PKCS11_CKA_DERIVE,
38463f89caaSJens Wiklander };
38563f89caaSJens Wiklander 
3864eb88651SRuchika Gupta static const uint32_t any_key_opt_or_null[] = {
38763f89caaSJens Wiklander 	PKCS11_CKA_ID,
38863f89caaSJens Wiklander 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE,
3894eb88651SRuchika Gupta };
3904eb88651SRuchika Gupta 
3914eb88651SRuchika Gupta static const uint32_t any_key_optional[] = {
39263f89caaSJens Wiklander 	PKCS11_CKA_ALLOWED_MECHANISMS,
39363f89caaSJens Wiklander };
39463f89caaSJens Wiklander 
3954eb88651SRuchika Gupta /* PKCS#11 specification for any symmetric key (+any_key_xxx) */
3964eb88651SRuchika Gupta static const uint32_t symm_key_boolprops[] = {
39763f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT,
39863f89caaSJens Wiklander 	PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY,
39963f89caaSJens Wiklander 	PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP,
40063f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
40163f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED,
40263f89caaSJens Wiklander };
40363f89caaSJens Wiklander 
4044eb88651SRuchika Gupta static const uint32_t symm_key_opt_or_null[] = {
40563f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE,
4060ac5c695SRuchika Gupta 	PKCS11_CKA_DERIVE_TEMPLATE, PKCS11_CKA_VALUE,
4070ac5c695SRuchika Gupta };
4080ac5c695SRuchika Gupta 
4090ac5c695SRuchika Gupta static const uint32_t symm_key_optional[] = {
4100ac5c695SRuchika Gupta 	PKCS11_CKA_VALUE_LEN,
411bcac2127SMarouene Boubakri #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
412bcac2127SMarouene Boubakri 	/* Consider KCV attribute only when supported */
413bcac2127SMarouene Boubakri 	PKCS11_CKA_CHECK_VALUE,
414bcac2127SMarouene Boubakri #endif
41563f89caaSJens Wiklander };
41663f89caaSJens Wiklander 
4174eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
4184eb88651SRuchika Gupta static const uint32_t public_key_boolprops[] = {
41963f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER,
42063f89caaSJens Wiklander 	PKCS11_CKA_WRAP,
42163f89caaSJens Wiklander 	PKCS11_CKA_TRUSTED,
42263f89caaSJens Wiklander };
42363f89caaSJens Wiklander 
4244eb88651SRuchika Gupta static const uint32_t public_key_mandated[] = {
42563f89caaSJens Wiklander };
42663f89caaSJens Wiklander 
4274eb88651SRuchika Gupta static const uint32_t public_key_opt_or_null[] = {
428edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_WRAP_TEMPLATE,
429edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
43063f89caaSJens Wiklander };
43163f89caaSJens Wiklander 
4324eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */
4334eb88651SRuchika Gupta static const uint32_t private_key_boolprops[] = {
43463f89caaSJens Wiklander 	PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER,
43563f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP,
43663f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
43763f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE,
43863f89caaSJens Wiklander };
43963f89caaSJens Wiklander 
4404eb88651SRuchika Gupta static const uint32_t private_key_mandated[] = {
44163f89caaSJens Wiklander };
44263f89caaSJens Wiklander 
4434eb88651SRuchika Gupta static const uint32_t private_key_opt_or_null[] = {
444edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_UNWRAP_TEMPLATE,
445edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
44663f89caaSJens Wiklander };
44763f89caaSJens Wiklander 
4484eb88651SRuchika Gupta /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */
4499cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_mand[] = {
45063f89caaSJens Wiklander 	PKCS11_CKA_MODULUS_BITS,
45163f89caaSJens Wiklander };
45263f89caaSJens Wiklander 
4539cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_create_mand[] = {
45463f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
45563f89caaSJens Wiklander };
45663f89caaSJens Wiklander 
4579cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_opt_or_null[] = {
4589cf1afceSVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_EXPONENT,
4599cf1afceSVesa Jääskeläinen };
4609cf1afceSVesa Jääskeläinen 
4619cf1afceSVesa Jääskeläinen static const uint32_t rsa_priv_key_opt_or_null[] = {
46263f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
46363f89caaSJens Wiklander 	PKCS11_CKA_PRIVATE_EXPONENT,
46463f89caaSJens Wiklander 	PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2,
46563f89caaSJens Wiklander 	PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT,
46663f89caaSJens Wiklander };
46763f89caaSJens Wiklander 
4684eb88651SRuchika Gupta /* PKCS#11 specification for any EC key (+public/private_key_xxx) */
4694eb88651SRuchika Gupta static const uint32_t ec_public_key_mandated[] = {
47063f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
47163f89caaSJens Wiklander };
47263f89caaSJens Wiklander 
4734eb88651SRuchika Gupta static const uint32_t ec_public_key_opt_or_null[] = {
47463f89caaSJens Wiklander 	PKCS11_CKA_EC_POINT,
47563f89caaSJens Wiklander };
47663f89caaSJens Wiklander 
4774eb88651SRuchika Gupta static const uint32_t ec_private_key_mandated[] = {
47863f89caaSJens Wiklander };
47963f89caaSJens Wiklander 
4804eb88651SRuchika Gupta static const uint32_t ec_private_key_opt_or_null[] = {
48102b16804SVesa Jääskeläinen 	PKCS11_CKA_EC_PARAMS,
48263f89caaSJens Wiklander 	PKCS11_CKA_VALUE,
48363f89caaSJens Wiklander };
48463f89caaSJens Wiklander 
48503e07432SValerii Chubar static const uint32_t eddsa_private_key_opt_or_null[] = {
48603e07432SValerii Chubar 	PKCS11_CKA_EC_PARAMS,
48703e07432SValerii Chubar 	PKCS11_CKA_VALUE,
48803e07432SValerii Chubar 	PKCS11_CKA_EC_POINT,
48903e07432SValerii Chubar };
49003e07432SValerii Chubar 
create_storage_attributes(struct obj_attrs ** out,struct obj_attrs * temp)49163f89caaSJens Wiklander static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out,
49263f89caaSJens Wiklander 						struct obj_attrs *temp)
49363f89caaSJens Wiklander {
49463f89caaSJens Wiklander 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
49563f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
49663f89caaSJens Wiklander 
49763f89caaSJens Wiklander 	rc = init_attributes_head(out);
49863f89caaSJens Wiklander 	if (rc)
49963f89caaSJens Wiklander 		return rc;
50063f89caaSJens Wiklander 
50163f89caaSJens Wiklander 	/* Object class is mandatory */
50263f89caaSJens Wiklander 	class = get_class(temp);
50363f89caaSJens Wiklander 	if (class == PKCS11_CKO_UNDEFINED_ID) {
50463f89caaSJens Wiklander 		EMSG("Class attribute not found");
50563f89caaSJens Wiklander 
50663f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
50763f89caaSJens Wiklander 	}
50863f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t));
50963f89caaSJens Wiklander 	if (rc)
51063f89caaSJens Wiklander 		return rc;
51163f89caaSJens Wiklander 
5124eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_object_boolprops,
5134eb88651SRuchika Gupta 				     ARRAY_SIZE(any_object_boolprops));
51463f89caaSJens Wiklander 	if (rc)
51563f89caaSJens Wiklander 		return rc;
51663f89caaSJens Wiklander 
5174eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, any_object_opt_or_null,
5184eb88651SRuchika Gupta 					  ARRAY_SIZE(any_object_opt_or_null));
51963f89caaSJens Wiklander }
52063f89caaSJens Wiklander 
create_genkey_attributes(struct obj_attrs ** out,struct obj_attrs * temp)52163f89caaSJens Wiklander static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out,
52263f89caaSJens Wiklander 					       struct obj_attrs *temp)
52363f89caaSJens Wiklander {
52463f89caaSJens Wiklander 	uint32_t type = PKCS11_CKO_UNDEFINED_ID;
52563f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
52663f89caaSJens Wiklander 
52763f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
52863f89caaSJens Wiklander 	if (rc)
52963f89caaSJens Wiklander 		return rc;
53063f89caaSJens Wiklander 
53163f89caaSJens Wiklander 	type = get_key_type(temp);
53263f89caaSJens Wiklander 	if (type == PKCS11_CKK_UNDEFINED_ID) {
53363f89caaSJens Wiklander 		EMSG("Key type attribute not found");
53463f89caaSJens Wiklander 
53563f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
53663f89caaSJens Wiklander 	}
53763f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t));
53863f89caaSJens Wiklander 	if (rc)
53963f89caaSJens Wiklander 		return rc;
54063f89caaSJens Wiklander 
5414eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_key_boolprops,
5424eb88651SRuchika Gupta 				     ARRAY_SIZE(any_key_boolprops));
54363f89caaSJens Wiklander 	if (rc)
54463f89caaSJens Wiklander 		return rc;
54563f89caaSJens Wiklander 
5464eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null,
5474eb88651SRuchika Gupta 					ARRAY_SIZE(any_key_opt_or_null));
5484eb88651SRuchika Gupta 	if (rc)
5494eb88651SRuchika Gupta 		return rc;
5504eb88651SRuchika Gupta 
5514eb88651SRuchika Gupta 	return set_optional_attributes(out, temp, any_key_optional,
5524eb88651SRuchika Gupta 				       ARRAY_SIZE(any_key_optional));
5534eb88651SRuchika Gupta 
55463f89caaSJens Wiklander }
55563f89caaSJens Wiklander 
create_symm_key_attributes(struct obj_attrs ** out,struct obj_attrs * temp)55663f89caaSJens Wiklander static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out,
55763f89caaSJens Wiklander 						 struct obj_attrs *temp)
55863f89caaSJens Wiklander {
55963f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
56063f89caaSJens Wiklander 
56163f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_SECRET_KEY);
56263f89caaSJens Wiklander 
56363f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
56463f89caaSJens Wiklander 	if (rc)
56563f89caaSJens Wiklander 		return rc;
56663f89caaSJens Wiklander 
56763f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_SECRET_KEY);
56863f89caaSJens Wiklander 
56963f89caaSJens Wiklander 	switch (get_key_type(*out)) {
57063f89caaSJens Wiklander 	case PKCS11_CKK_GENERIC_SECRET:
57163f89caaSJens Wiklander 	case PKCS11_CKK_AES:
57263f89caaSJens Wiklander 	case PKCS11_CKK_MD5_HMAC:
57363f89caaSJens Wiklander 	case PKCS11_CKK_SHA_1_HMAC:
57463f89caaSJens Wiklander 	case PKCS11_CKK_SHA256_HMAC:
57563f89caaSJens Wiklander 	case PKCS11_CKK_SHA384_HMAC:
57663f89caaSJens Wiklander 	case PKCS11_CKK_SHA512_HMAC:
57763f89caaSJens Wiklander 	case PKCS11_CKK_SHA224_HMAC:
57863f89caaSJens Wiklander 		break;
57963f89caaSJens Wiklander 	default:
58063f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
58163f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
58263f89caaSJens Wiklander 
58363f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
58463f89caaSJens Wiklander 	}
58563f89caaSJens Wiklander 
5864eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, symm_key_boolprops,
5874eb88651SRuchika Gupta 				     ARRAY_SIZE(symm_key_boolprops));
58863f89caaSJens Wiklander 	if (rc)
58963f89caaSJens Wiklander 		return rc;
59063f89caaSJens Wiklander 
5910ac5c695SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, symm_key_opt_or_null,
5924eb88651SRuchika Gupta 					ARRAY_SIZE(symm_key_opt_or_null));
5930ac5c695SRuchika Gupta 	if (rc)
5940ac5c695SRuchika Gupta 		return rc;
5950ac5c695SRuchika Gupta 
5960ac5c695SRuchika Gupta 	return set_optional_attributes(out, temp, symm_key_optional,
5970ac5c695SRuchika Gupta 				       ARRAY_SIZE(symm_key_optional));
59863f89caaSJens Wiklander }
59963f89caaSJens Wiklander 
create_data_attributes(struct obj_attrs ** out,struct obj_attrs * temp)60063f89caaSJens Wiklander static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
60163f89caaSJens Wiklander 					     struct obj_attrs *temp)
60263f89caaSJens Wiklander {
60363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
60463f89caaSJens Wiklander 
60563f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_DATA);
60663f89caaSJens Wiklander 
60763f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
60863f89caaSJens Wiklander 	if (rc)
60963f89caaSJens Wiklander 		return rc;
61063f89caaSJens Wiklander 
61163f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_DATA);
61263f89caaSJens Wiklander 
6134eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null,
6144eb88651SRuchika Gupta 					  ARRAY_SIZE(raw_data_opt_or_null));
61563f89caaSJens Wiklander }
61663f89caaSJens Wiklander 
create_certificate_attributes(struct obj_attrs ** out,struct obj_attrs * temp)6174137952dSVesa Jääskeläinen static enum pkcs11_rc create_certificate_attributes(struct obj_attrs **out,
6184137952dSVesa Jääskeläinen 						    struct obj_attrs *temp)
6194137952dSVesa Jääskeläinen {
6204137952dSVesa Jääskeläinen 	uint32_t const *mandated = NULL;
6214137952dSVesa Jääskeläinen 	uint32_t const *optional = NULL;
6224137952dSVesa Jääskeläinen 	size_t mandated_count = 0;
6234137952dSVesa Jääskeläinen 	size_t optional_count = 0;
6244137952dSVesa Jääskeläinen 	void *attr_value = NULL;
6254137952dSVesa Jääskeläinen 	uint32_t attr_size = 0;
6264137952dSVesa Jääskeläinen 	uint32_t default_cert_category =
6274137952dSVesa Jääskeläinen 		PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED;
6284137952dSVesa Jääskeläinen 	uint32_t default_name_hash_alg = PKCS11_CKM_SHA_1;
6294137952dSVesa Jääskeläinen 	uint32_t cert_category = 0;
6304137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
6314137952dSVesa Jääskeläinen 
6324137952dSVesa Jääskeläinen 	assert(get_class(temp) == PKCS11_CKO_CERTIFICATE);
6334137952dSVesa Jääskeläinen 
6344137952dSVesa Jääskeläinen 	rc = create_storage_attributes(out, temp);
6354137952dSVesa Jääskeläinen 	if (rc)
6364137952dSVesa Jääskeläinen 		return rc;
6374137952dSVesa Jääskeläinen 
6384137952dSVesa Jääskeläinen 	assert(get_class(*out) == PKCS11_CKO_CERTIFICATE);
6394137952dSVesa Jääskeläinen 
6404137952dSVesa Jääskeläinen 	rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops,
6414137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_boolprops));
6424137952dSVesa Jääskeläinen 	if (rc)
6434137952dSVesa Jääskeläinen 		return rc;
6444137952dSVesa Jääskeläinen 
6454137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated,
6464137952dSVesa Jääskeläinen 				      ARRAY_SIZE(pkcs11_certificate_mandated));
6474137952dSVesa Jääskeläinen 	if (rc)
6484137952dSVesa Jääskeläinen 		return rc;
6494137952dSVesa Jääskeläinen 
6504137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, pkcs11_certificate_optional,
6514137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_optional));
6524137952dSVesa Jääskeläinen 	if (rc)
6534137952dSVesa Jääskeläinen 		return rc;
6544137952dSVesa Jääskeläinen 
6554137952dSVesa Jääskeläinen 	switch (get_certificate_type(*out)) {
6564137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
6574137952dSVesa Jääskeläinen 		mandated = pkcs11_x509_certificate_mandated;
6584137952dSVesa Jääskeläinen 		optional = pkcs11_x509_certificate_optional;
6594137952dSVesa Jääskeläinen 		mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated);
6604137952dSVesa Jääskeläinen 		optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional);
6614137952dSVesa Jääskeläinen 		break;
6624137952dSVesa Jääskeläinen 	default:
6634137952dSVesa Jääskeläinen 		EMSG("Invalid certificate type %#"PRIx32"/%s",
6644137952dSVesa Jääskeläinen 		     get_certificate_type(*out),
6654137952dSVesa Jääskeläinen 		     id2str_certificate_type(get_certificate_type(*out)));
6664137952dSVesa Jääskeläinen 
6674137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
6684137952dSVesa Jääskeläinen 	}
6694137952dSVesa Jääskeläinen 
6704137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
6714137952dSVesa Jääskeläinen 	if (rc)
6724137952dSVesa Jääskeläinen 		return rc;
6734137952dSVesa Jääskeläinen 
6744137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, optional, optional_count);
6754137952dSVesa Jääskeläinen 	if (rc)
6764137952dSVesa Jääskeläinen 		return rc;
6774137952dSVesa Jääskeläinen 
6784137952dSVesa Jääskeläinen 	attr_size = 0;
6794137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY,
6804137952dSVesa Jääskeläinen 			       &attr_value, &attr_size);
6814137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(cert_category)) {
6824137952dSVesa Jääskeläinen 		/* Sanitize certificate category */
6834137952dSVesa Jääskeläinen 		TEE_MemMove(&cert_category, attr_value, sizeof(cert_category));
6844137952dSVesa Jääskeläinen 
6854137952dSVesa Jääskeläinen 		switch (cert_category) {
6864137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED:
6874137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER:
6884137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY:
6894137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY:
6904137952dSVesa Jääskeläinen 			break;
6914137952dSVesa Jääskeläinen 		default:
6924137952dSVesa Jääskeläinen 			EMSG("Invalid certificate category %#"PRIx32,
6934137952dSVesa Jääskeläinen 			     cert_category);
6944137952dSVesa Jääskeläinen 
6954137952dSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
6964137952dSVesa Jääskeläinen 		}
6974137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
6984137952dSVesa Jääskeläinen 		/* Set default category when missing */
6994137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY,
7004137952dSVesa Jääskeläinen 				   &default_cert_category,
7014137952dSVesa Jääskeläinen 				   sizeof(default_cert_category));
7024137952dSVesa Jääskeläinen 		if (rc)
7034137952dSVesa Jääskeläinen 			return rc;
7044137952dSVesa Jääskeläinen 	} else {
7054137952dSVesa Jääskeläinen 		/* All other cases are errors */
7064137952dSVesa Jääskeläinen 		EMSG("Invalid certificate category");
7074137952dSVesa Jääskeläinen 
7084137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7094137952dSVesa Jääskeläinen 	}
7104137952dSVesa Jääskeläinen 
7114137952dSVesa Jääskeläinen 	attr_size = 0;
7124137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL,
7134137952dSVesa Jääskeläinen 			       &attr_size);
7144137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(uint32_t)) {
7154137952dSVesa Jääskeläinen 		/* We accept any algorithm what caller wanted to specify */
7164137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
7174137952dSVesa Jääskeläinen 		/* Set default hash algorithm when missing */
7184137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM,
7194137952dSVesa Jääskeläinen 				   &default_name_hash_alg,
7204137952dSVesa Jääskeläinen 				   sizeof(default_name_hash_alg));
7214137952dSVesa Jääskeläinen 		if (rc)
7224137952dSVesa Jääskeläinen 			return rc;
7234137952dSVesa Jääskeläinen 	} else {
7244137952dSVesa Jääskeläinen 		/* All other cases are errors */
7254137952dSVesa Jääskeläinen 		EMSG("Invalid name hash algorithm");
7264137952dSVesa Jääskeläinen 
7274137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7284137952dSVesa Jääskeläinen 	}
7294137952dSVesa Jääskeläinen 
7304137952dSVesa Jääskeläinen 	return rc;
7314137952dSVesa Jääskeläinen }
7324137952dSVesa Jääskeläinen 
create_pub_key_attributes(struct obj_attrs ** out,struct obj_attrs * temp,enum processing_func function)73363f89caaSJens Wiklander static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
7349cf1afceSVesa Jääskeläinen 						struct obj_attrs *temp,
7359cf1afceSVesa Jääskeläinen 						enum processing_func function)
73663f89caaSJens Wiklander {
73763f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
7389cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
73963f89caaSJens Wiklander 	size_t mandated_count = 0;
7409cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
74163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
74263f89caaSJens Wiklander 
74363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY);
74463f89caaSJens Wiklander 
74563f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
74663f89caaSJens Wiklander 	if (rc)
74763f89caaSJens Wiklander 		return rc;
74863f89caaSJens Wiklander 
74963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY);
75063f89caaSJens Wiklander 
7514eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, public_key_boolprops,
7524eb88651SRuchika Gupta 				     ARRAY_SIZE(public_key_boolprops));
75363f89caaSJens Wiklander 	if (rc)
75463f89caaSJens Wiklander 		return rc;
75563f89caaSJens Wiklander 
7564eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, public_key_mandated,
7574eb88651SRuchika Gupta 				      ARRAY_SIZE(public_key_mandated));
75863f89caaSJens Wiklander 	if (rc)
75963f89caaSJens Wiklander 		return rc;
76063f89caaSJens Wiklander 
7614eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp,
7624eb88651SRuchika Gupta 					public_key_opt_or_null,
7634eb88651SRuchika Gupta 					ARRAY_SIZE(public_key_opt_or_null));
76463f89caaSJens Wiklander 	if (rc)
76563f89caaSJens Wiklander 		return rc;
76663f89caaSJens Wiklander 
76763f89caaSJens Wiklander 	switch (get_key_type(*out)) {
76863f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
7699cf1afceSVesa Jääskeläinen 		switch (function) {
7709cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
7719cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_gen_mand;
7729cf1afceSVesa Jääskeläinen 			oon = rsa_pub_key_gen_opt_or_null;
7739cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_gen_mand);
7749cf1afceSVesa Jääskeläinen 			oon_count = ARRAY_SIZE(rsa_pub_key_gen_opt_or_null);
7759cf1afceSVesa Jääskeläinen 			break;
7769cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_IMPORT:
7779cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_create_mand;
7789cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_create_mand);
7799cf1afceSVesa Jääskeläinen 			break;
7809cf1afceSVesa Jääskeläinen 		default:
7819cf1afceSVesa Jääskeläinen 			EMSG("Unsupported function %#"PRIx32"/%s", function,
7829cf1afceSVesa Jääskeläinen 			     id2str_function(function));
7839cf1afceSVesa Jääskeläinen 
7849cf1afceSVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7859cf1afceSVesa Jääskeläinen 		}
78663f89caaSJens Wiklander 		break;
78763f89caaSJens Wiklander 	case PKCS11_CKK_EC:
78803e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
7894eb88651SRuchika Gupta 		mandated = ec_public_key_mandated;
7909cf1afceSVesa Jääskeläinen 		oon = ec_public_key_opt_or_null;
7914eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_public_key_mandated);
7929cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_public_key_opt_or_null);
79363f89caaSJens Wiklander 		break;
79463f89caaSJens Wiklander 	default:
79563f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
79663f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
79763f89caaSJens Wiklander 
79863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
79963f89caaSJens Wiklander 	}
80063f89caaSJens Wiklander 
80163f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
80263f89caaSJens Wiklander 	if (rc)
80363f89caaSJens Wiklander 		return rc;
80463f89caaSJens Wiklander 
8059cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
80663f89caaSJens Wiklander }
80763f89caaSJens Wiklander 
8085071d7d1SVesa Jääskeläinen static enum pkcs11_rc
create_pub_key_rsa_generated_attributes(struct obj_attrs ** out,struct obj_attrs * temp,enum processing_func function)8095071d7d1SVesa Jääskeläinen create_pub_key_rsa_generated_attributes(struct obj_attrs **out,
8105071d7d1SVesa Jääskeläinen 					struct obj_attrs *temp,
8115071d7d1SVesa Jääskeläinen 					enum processing_func function)
8125071d7d1SVesa Jääskeläinen {
8135071d7d1SVesa Jääskeläinen 	uint32_t key_bits = 0;
8145071d7d1SVesa Jääskeläinen 	void *a_ptr = NULL;
8155071d7d1SVesa Jääskeläinen 	uint32_t a_size = 0;
8165071d7d1SVesa Jääskeläinen 
8175071d7d1SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
8185071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_OK;
8195071d7d1SVesa Jääskeläinen 
8205071d7d1SVesa Jääskeläinen 	/* Calculate CKA_MODULUS_BITS */
8215071d7d1SVesa Jääskeläinen 
8225071d7d1SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_MODULUS,
8235071d7d1SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
8245071d7d1SVesa Jääskeläinen 		EMSG("No CKA_MODULUS attribute found in public key");
8255071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
8265071d7d1SVesa Jääskeläinen 	}
8275071d7d1SVesa Jääskeläinen 
8285071d7d1SVesa Jääskeläinen 	key_bits = a_size * 8;
8295071d7d1SVesa Jääskeläinen 
8305071d7d1SVesa Jääskeläinen 	return add_attribute(out, PKCS11_CKA_MODULUS_BITS, &key_bits,
8315071d7d1SVesa Jääskeläinen 			     sizeof(key_bits));
8325071d7d1SVesa Jääskeläinen }
8335071d7d1SVesa Jääskeläinen 
8345071d7d1SVesa Jääskeläinen static enum pkcs11_rc
create_pub_key_generated_attributes(struct obj_attrs ** out,struct obj_attrs * temp,enum processing_func function)8355071d7d1SVesa Jääskeläinen create_pub_key_generated_attributes(struct obj_attrs **out,
8365071d7d1SVesa Jääskeläinen 				    struct obj_attrs *temp,
8375071d7d1SVesa Jääskeläinen 				    enum processing_func function)
8385071d7d1SVesa Jääskeläinen {
8395071d7d1SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
8405071d7d1SVesa Jääskeläinen 
8415071d7d1SVesa Jääskeläinen 	switch (get_key_type(*out)) {
8425071d7d1SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
8435071d7d1SVesa Jääskeläinen 		rc = create_pub_key_rsa_generated_attributes(out, temp,
8445071d7d1SVesa Jääskeläinen 							     function);
8455071d7d1SVesa Jääskeläinen 		break;
8465071d7d1SVesa Jääskeläinen 	default:
8475071d7d1SVesa Jääskeläinen 		/* no-op */
8485071d7d1SVesa Jääskeläinen 		break;
8495071d7d1SVesa Jääskeläinen 	}
8505071d7d1SVesa Jääskeläinen 
8515071d7d1SVesa Jääskeläinen 	return rc;
8525071d7d1SVesa Jääskeläinen }
8535071d7d1SVesa Jääskeläinen 
create_priv_key_attributes(struct obj_attrs ** out,struct obj_attrs * temp)85463f89caaSJens Wiklander static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out,
85563f89caaSJens Wiklander 						 struct obj_attrs *temp)
85663f89caaSJens Wiklander {
85763f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
8589cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
85963f89caaSJens Wiklander 	size_t mandated_count = 0;
8609cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
86163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
86263f89caaSJens Wiklander 
86363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY);
86463f89caaSJens Wiklander 
86563f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
86663f89caaSJens Wiklander 	if (rc)
86763f89caaSJens Wiklander 		return rc;
86863f89caaSJens Wiklander 
86963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY);
87063f89caaSJens Wiklander 
8714eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, private_key_boolprops,
8724eb88651SRuchika Gupta 				     ARRAY_SIZE(private_key_boolprops));
87363f89caaSJens Wiklander 	if (rc)
87463f89caaSJens Wiklander 		return rc;
87563f89caaSJens Wiklander 
8764eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, private_key_mandated,
8774eb88651SRuchika Gupta 				      ARRAY_SIZE(private_key_mandated));
87863f89caaSJens Wiklander 	if (rc)
87963f89caaSJens Wiklander 		return rc;
88063f89caaSJens Wiklander 
8814eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null,
8824eb88651SRuchika Gupta 					ARRAY_SIZE(private_key_opt_or_null));
88363f89caaSJens Wiklander 	if (rc)
88463f89caaSJens Wiklander 		return rc;
88563f89caaSJens Wiklander 
88663f89caaSJens Wiklander 	switch (get_key_type(*out)) {
88763f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
8889cf1afceSVesa Jääskeläinen 		oon = rsa_priv_key_opt_or_null;
8899cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(rsa_priv_key_opt_or_null);
89063f89caaSJens Wiklander 		break;
89163f89caaSJens Wiklander 	case PKCS11_CKK_EC:
8924eb88651SRuchika Gupta 		mandated = ec_private_key_mandated;
8939cf1afceSVesa Jääskeläinen 		oon = ec_private_key_opt_or_null;
8944eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
8959cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_private_key_opt_or_null);
89663f89caaSJens Wiklander 		break;
89703e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
89803e07432SValerii Chubar 		mandated = ec_private_key_mandated;
89903e07432SValerii Chubar 		oon = eddsa_private_key_opt_or_null;
90003e07432SValerii Chubar 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
90103e07432SValerii Chubar 		oon_count = ARRAY_SIZE(eddsa_private_key_opt_or_null);
90203e07432SValerii Chubar 		break;
90363f89caaSJens Wiklander 	default:
90463f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
90563f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
90663f89caaSJens Wiklander 
90763f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
90863f89caaSJens Wiklander 	}
90963f89caaSJens Wiklander 
91063f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
91163f89caaSJens Wiklander 	if (rc)
91263f89caaSJens Wiklander 		return rc;
91363f89caaSJens Wiklander 
9149cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
91563f89caaSJens Wiklander }
91663f89caaSJens Wiklander 
mbd_rand(void * rng_state __unused,unsigned char * output,size_t len)91732b31808SJens Wiklander static int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len)
91832b31808SJens Wiklander {
91932b31808SJens Wiklander 	TEE_GenerateRandom(output, len);
92032b31808SJens Wiklander 	return 0;
92132b31808SJens Wiklander }
92232b31808SJens Wiklander 
923196bcd93SRuchika Gupta static enum pkcs11_rc
create_ec_priv_key_hidden_attributes(struct obj_attrs ** out,struct obj_attrs * temp,enum processing_func function)9247c243321SVesa Jääskeläinen create_ec_priv_key_hidden_attributes(struct obj_attrs **out,
9257c243321SVesa Jääskeläinen 				     struct obj_attrs *temp,
9267c243321SVesa Jääskeläinen 				     enum processing_func function)
9277c243321SVesa Jääskeläinen {
9287c243321SVesa Jääskeläinen 	struct mbedtls_ecp_keypair key_pair = { };
9297c243321SVesa Jääskeläinen 	mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE;
93032b31808SJens Wiklander 	mbedtls_ecp_group key_pair_grp = { };
93132b31808SJens Wiklander 	mbedtls_ecp_point key_pair_Q = { };
93232b31808SJens Wiklander 	mbedtls_mpi key_pair_d = { };
9337c243321SVesa Jääskeläinen 	size_t buflen = 0;
9347c243321SVesa Jääskeläinen 	uint8_t *buf = NULL;
9357c243321SVesa Jääskeläinen 	size_t asnbuflen = 0;
9367c243321SVesa Jääskeläinen 	uint8_t *asnbuf = NULL;
9377c243321SVesa Jääskeläinen 	uint8_t *ptr = NULL;
9387c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
9397c243321SVesa Jääskeläinen 	int tee_size = 0;
9407c243321SVesa Jääskeläinen 	int tee_curve = 0;
9417c243321SVesa Jääskeläinen 	void *a_ptr = NULL;
9427c243321SVesa Jääskeläinen 	uint32_t a_size = 0;
9437c243321SVesa Jääskeläinen 	int ret = 0;
9447c243321SVesa Jääskeläinen 
9457c243321SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
9467c243321SVesa Jääskeläinen 		return PKCS11_CKR_OK;
9477c243321SVesa Jääskeläinen 
9487c243321SVesa Jääskeläinen 	/*
9497c243321SVesa Jääskeläinen 	 * TEE internal API requires that for private key operations there
9507c243321SVesa Jääskeläinen 	 * needs to be also public key available.
9517c243321SVesa Jääskeläinen 	 *
9527c243321SVesa Jääskeläinen 	 * Generate hidden EC point from private key.
9537c243321SVesa Jääskeläinen 	 */
9547c243321SVesa Jääskeläinen 
9557c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS,
9567c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9577c243321SVesa Jääskeläinen 		EMSG("No EC_PARAMS attribute found in private key");
9587c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9597c243321SVesa Jääskeläinen 	}
9607c243321SVesa Jääskeläinen 
9617c243321SVesa Jääskeläinen 	/* Just valdiate that curve is found */
9627c243321SVesa Jääskeläinen 	tee_size = ec_params2tee_keysize(a_ptr, a_size);
9637c243321SVesa Jääskeläinen 	if (!tee_size) {
9647c243321SVesa Jääskeläinen 		EMSG("Unsupported EC_PARAMS curve");
9657c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9667c243321SVesa Jääskeläinen 	}
9677c243321SVesa Jääskeläinen 
9687c243321SVesa Jääskeläinen 	tee_curve = ec_params2tee_curve(a_ptr, a_size);
9697c243321SVesa Jääskeläinen 
9707c243321SVesa Jääskeläinen 	switch (tee_curve) {
9717c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P192:
9727c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP192R1;
9737c243321SVesa Jääskeläinen 		break;
9747c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P224:
9757c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP224R1;
9767c243321SVesa Jääskeläinen 		break;
9777c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P256:
9787c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP256R1;
9797c243321SVesa Jääskeläinen 		break;
9807c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P384:
9817c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP384R1;
9827c243321SVesa Jääskeläinen 		break;
9837c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P521:
9847c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP521R1;
9857c243321SVesa Jääskeläinen 		break;
9867c243321SVesa Jääskeläinen 	default:
9877c243321SVesa Jääskeläinen 		EMSG("Failed to map EC_PARAMS to supported curve");
9887c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9897c243321SVesa Jääskeläinen 	}
9907c243321SVesa Jääskeläinen 
9917c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_VALUE,
9927c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9937c243321SVesa Jääskeläinen 		EMSG("No VALUE attribute found in private key");
9947c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9957c243321SVesa Jääskeläinen 	}
9967c243321SVesa Jääskeläinen 
9977c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_init(&key_pair);
99832b31808SJens Wiklander 	mbedtls_ecp_group_init(&key_pair_grp);
99932b31808SJens Wiklander 	mbedtls_mpi_init(&key_pair_d);
100032b31808SJens Wiklander 	mbedtls_ecp_point_init(&key_pair_Q);
10017c243321SVesa Jääskeläinen 
10027c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size);
10037c243321SVesa Jääskeläinen 	if (ret) {
10047c243321SVesa Jääskeläinen 		EMSG("Failed to parse CKA_VALUE");
10057c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
10067c243321SVesa Jääskeläinen 		goto out;
10077c243321SVesa Jääskeläinen 	}
10087c243321SVesa Jääskeläinen 
100932b31808SJens Wiklander 	ret = mbedtls_ecp_export(&key_pair, &key_pair_grp, &key_pair_d,
101032b31808SJens Wiklander 				 &key_pair_Q);
101132b31808SJens Wiklander 	if (ret) {
101232b31808SJens Wiklander 		EMSG("Failed to export key");
101332b31808SJens Wiklander 		goto out;
101432b31808SJens Wiklander 	}
101532b31808SJens Wiklander 
101632b31808SJens Wiklander 	ret = mbedtls_ecp_mul(&key_pair_grp, &key_pair_Q, &key_pair_d,
101732b31808SJens Wiklander 			      &key_pair_grp.G, mbd_rand, NULL);
10187c243321SVesa Jääskeläinen 	if (ret) {
10197c243321SVesa Jääskeläinen 		EMSG("Failed to create public key");
10207c243321SVesa Jääskeläinen 		goto out;
10217c243321SVesa Jääskeläinen 	}
10227c243321SVesa Jääskeläinen 
102332b31808SJens Wiklander 	ret = mbedtls_ecp_check_privkey(&key_pair_grp, &key_pair_d);
10247c243321SVesa Jääskeläinen 	if (ret) {
10257c243321SVesa Jääskeläinen 		EMSG("Failed to verify private key");
10267c243321SVesa Jääskeläinen 		goto out;
10277c243321SVesa Jääskeläinen 	}
10287c243321SVesa Jääskeläinen 
102932b31808SJens Wiklander 	ret = mbedtls_ecp_check_pubkey(&key_pair_grp, &key_pair_Q);
10307c243321SVesa Jääskeläinen 	if (ret) {
10317c243321SVesa Jääskeläinen 		EMSG("Failed to verify public key");
10327c243321SVesa Jääskeläinen 		goto out;
10337c243321SVesa Jääskeläinen 	}
10347c243321SVesa Jääskeläinen 
103532b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10367c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10377c243321SVesa Jääskeläinen 					     &buflen, NULL, 0);
10387c243321SVesa Jääskeläinen 	if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
10397c243321SVesa Jääskeläinen 		EMSG("Failed to determine size of binary public key");
10407c243321SVesa Jääskeläinen 		goto out;
10417c243321SVesa Jääskeläinen 	}
10427c243321SVesa Jääskeläinen 
10437c243321SVesa Jääskeläinen 	buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO);
10447c243321SVesa Jääskeläinen 	if (!buf) {
10457c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10467c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10477c243321SVesa Jääskeläinen 		goto out;
10487c243321SVesa Jääskeläinen 	}
10497c243321SVesa Jääskeläinen 
10507c243321SVesa Jääskeläinen 	asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen;
10517c243321SVesa Jääskeläinen 
10527c243321SVesa Jääskeläinen 	asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO);
10537c243321SVesa Jääskeläinen 	if (!asnbuf) {
10547c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10557c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10567c243321SVesa Jääskeläinen 		goto out;
10577c243321SVesa Jääskeläinen 	}
10587c243321SVesa Jääskeläinen 
105932b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10607c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10617c243321SVesa Jääskeläinen 					     &buflen, buf, buflen);
10627c243321SVesa Jääskeläinen 	if (ret) {
10637c243321SVesa Jääskeläinen 		EMSG("Failed to write binary public key");
10647c243321SVesa Jääskeläinen 		goto out;
10657c243321SVesa Jääskeläinen 	}
10667c243321SVesa Jääskeläinen 
10677c243321SVesa Jääskeläinen 	/* Note: ASN.1 writing works backwards */
10687c243321SVesa Jääskeläinen 	ptr = asnbuf + asnbuflen;
10697c243321SVesa Jääskeläinen 
10707c243321SVesa Jääskeläinen 	ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen);
10717c243321SVesa Jääskeläinen 	if (ret < 0) {
10727c243321SVesa Jääskeläinen 		EMSG("Failed to write asn1 public key");
10737c243321SVesa Jääskeläinen 		goto out;
10747c243321SVesa Jääskeläinen 	}
10757c243321SVesa Jääskeläinen 
10767c243321SVesa Jääskeläinen 	rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr,
10777c243321SVesa Jääskeläinen 			   (size_t)ret);
10787c243321SVesa Jääskeläinen 
10797c243321SVesa Jääskeläinen out:
10807c243321SVesa Jääskeläinen 	TEE_Free(asnbuf);
10817c243321SVesa Jääskeläinen 	TEE_Free(buf);
10827c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_free(&key_pair);
108332b31808SJens Wiklander 	mbedtls_ecp_group_free(&key_pair_grp);
108432b31808SJens Wiklander 	mbedtls_mpi_free(&key_pair_d);
108532b31808SJens Wiklander 	mbedtls_ecp_point_free(&key_pair_Q);
10867c243321SVesa Jääskeläinen 
10877c243321SVesa Jääskeläinen 	return rc;
10887c243321SVesa Jääskeläinen }
10897c243321SVesa Jääskeläinen 
10907c243321SVesa Jääskeläinen static enum pkcs11_rc
create_priv_key_hidden_attributes(struct obj_attrs ** out,struct obj_attrs * temp,enum processing_func function)10917c243321SVesa Jääskeläinen create_priv_key_hidden_attributes(struct obj_attrs **out,
10927c243321SVesa Jääskeläinen 				  struct obj_attrs *temp,
10937c243321SVesa Jääskeläinen 				  enum processing_func function)
10947c243321SVesa Jääskeläinen {
10957c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
10967c243321SVesa Jääskeläinen 
10977c243321SVesa Jääskeläinen 	switch (get_key_type(*out)) {
10987c243321SVesa Jääskeläinen 	case PKCS11_CKK_EC:
10997c243321SVesa Jääskeläinen 		rc = create_ec_priv_key_hidden_attributes(out, temp, function);
11007c243321SVesa Jääskeläinen 		break;
11017c243321SVesa Jääskeläinen 	default:
11027c243321SVesa Jääskeläinen 		/* no-op */
11037c243321SVesa Jääskeläinen 		break;
11047c243321SVesa Jääskeläinen 	}
11057c243321SVesa Jääskeläinen 
11067c243321SVesa Jääskeläinen 	return rc;
11077c243321SVesa Jääskeläinen }
11087c243321SVesa Jääskeläinen 
11097c243321SVesa Jääskeläinen static enum pkcs11_rc
sanitize_symm_key_attributes(struct obj_attrs ** temp,enum processing_func function)1110196bcd93SRuchika Gupta sanitize_symm_key_attributes(struct obj_attrs **temp,
1111196bcd93SRuchika Gupta 			     enum processing_func function)
1112196bcd93SRuchika Gupta {
1113196bcd93SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1114196bcd93SRuchika Gupta 	uint32_t a_size = 0;
1115196bcd93SRuchika Gupta 
1116196bcd93SRuchika Gupta 	assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY);
1117196bcd93SRuchika Gupta 
1118196bcd93SRuchika Gupta 	rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size);
1119196bcd93SRuchika Gupta 
1120196bcd93SRuchika Gupta 	switch (get_key_type(*temp)) {
1121196bcd93SRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1122196bcd93SRuchika Gupta 	case PKCS11_CKK_AES:
1123196bcd93SRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
1124196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
1125196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
1126196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
1127196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
1128196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
1129196bcd93SRuchika Gupta 		switch (function) {
1130196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_IMPORT:
1131196bcd93SRuchika Gupta 			/* CKA_VALUE is a mandatory with C_CreateObject */
1132196bcd93SRuchika Gupta 			if (rc || a_size == 0)
1133196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1134196bcd93SRuchika Gupta 
1135196bcd93SRuchika Gupta 			if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL,
1136196bcd93SRuchika Gupta 					      NULL) != PKCS11_RV_NOT_FOUND)
1137196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1138196bcd93SRuchika Gupta 
1139196bcd93SRuchika Gupta 			return add_attribute(temp, PKCS11_CKA_VALUE_LEN,
1140196bcd93SRuchika Gupta 					     &a_size, sizeof(uint32_t));
1141196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1142196bcd93SRuchika Gupta 			if (rc != PKCS11_RV_NOT_FOUND)
1143196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1144196bcd93SRuchika Gupta 			break;
1145196bcd93SRuchika Gupta 		default:
1146196bcd93SRuchika Gupta 			break;
1147196bcd93SRuchika Gupta 		}
1148196bcd93SRuchika Gupta 		break;
1149196bcd93SRuchika Gupta 	default:
1150196bcd93SRuchika Gupta 		EMSG("Invalid key type %#"PRIx32"/%s",
1151196bcd93SRuchika Gupta 		     get_key_type(*temp), id2str_key_type(get_key_type(*temp)));
1152196bcd93SRuchika Gupta 
1153196bcd93SRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1154196bcd93SRuchika Gupta 	}
1155196bcd93SRuchika Gupta 
1156196bcd93SRuchika Gupta 	return PKCS11_CKR_OK;
1157196bcd93SRuchika Gupta }
1158196bcd93SRuchika Gupta 
115963f89caaSJens Wiklander /*
116063f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
116163f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
116263f89caaSJens Wiklander  * derive...).
116363f89caaSJens Wiklander  *
116463f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
116563f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
116663f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
116763f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
116863f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
116963f89caaSJens Wiklander  *
117063f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
117163f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
117263f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
117363f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
117463f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
117563f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
117663f89caaSJens Wiklander  */
117763f89caaSJens Wiklander enum pkcs11_rc
create_attributes_from_template(struct obj_attrs ** out,void * template,size_t template_size,struct obj_attrs * parent,enum processing_func function,enum pkcs11_mechanism_id mecha,enum pkcs11_class_id template_class)117863f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
117963f89caaSJens Wiklander 				size_t template_size,
118048799892SRuchika Gupta 				struct obj_attrs *parent,
118163f89caaSJens Wiklander 				enum processing_func function,
11824cfce748SRuchika Gupta 				enum pkcs11_mechanism_id mecha,
118302b16804SVesa Jääskeläinen 				enum pkcs11_class_id template_class)
118463f89caaSJens Wiklander {
118563f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
118663f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
118763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
118863f89caaSJens Wiklander 	uint8_t local = 0;
118963f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
119063f89caaSJens Wiklander 	uint8_t never_extract = 0;
1191e3f0cb56SRuchika Gupta 	uint8_t extractable = 0;
1192fa247a2aSRuchika Gupta 	uint32_t class = PKCS11_UNDEFINED_ID;
1193fa247a2aSRuchika Gupta 	uint32_t type = PKCS11_UNDEFINED_ID;
119463f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
1195e3f0cb56SRuchika Gupta 	struct obj_attrs *req_attrs = NULL;
1196e3f0cb56SRuchika Gupta 	uint32_t size = 0;
1197e3f0cb56SRuchika Gupta 	uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID;
119863f89caaSJens Wiklander 
119963f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
120063f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
120163f89caaSJens Wiklander 	switch (function) {
1202fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1203013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
120463f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
12052d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
120648799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1207e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
12082d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
120963f89caaSJens Wiklander 		break;
121063f89caaSJens Wiklander 	default:
121163f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
121263f89caaSJens Wiklander 	}
121363f89caaSJens Wiklander #endif
121463f89caaSJens Wiklander 
1215dcad3409SRuchika Gupta 	/*
1216dcad3409SRuchika Gupta 	 * For PKCS11_FUNCTION_GENERATE, find the class and type
1217dcad3409SRuchika Gupta 	 * based on the mechanism. These will be passed as hint
1218dcad3409SRuchika Gupta 	 * sanitize_client_object() and added in temp if not
1219dcad3409SRuchika Gupta 	 * already present
1220dcad3409SRuchika Gupta 	 */
1221dcad3409SRuchika Gupta 	if (function == PKCS11_FUNCTION_GENERATE) {
1222fa247a2aSRuchika Gupta 		switch (mecha) {
1223fa247a2aSRuchika Gupta 		case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1224fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1225fa247a2aSRuchika Gupta 			type = PKCS11_CKK_GENERIC_SECRET;
1226fa247a2aSRuchika Gupta 			break;
1227fa247a2aSRuchika Gupta 		case PKCS11_CKM_AES_KEY_GEN:
1228fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1229fa247a2aSRuchika Gupta 			type = PKCS11_CKK_AES;
1230fa247a2aSRuchika Gupta 			break;
1231fa247a2aSRuchika Gupta 		default:
1232dcad3409SRuchika Gupta 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1233fa247a2aSRuchika Gupta 		}
1234fa247a2aSRuchika Gupta 	}
1235fa247a2aSRuchika Gupta 
12362d25a9bcSRuchika Gupta 	/*
1237013934d8SVesa Jääskeläinen 	 * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type
1238013934d8SVesa Jääskeläinen 	 * based on the mechanism. These will be passed as hint
1239013934d8SVesa Jääskeläinen 	 * sanitize_client_object() and added in temp if not
1240013934d8SVesa Jääskeläinen 	 * already present
1241013934d8SVesa Jääskeläinen 	 */
1242013934d8SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_GENERATE_PAIR) {
1243013934d8SVesa Jääskeläinen 		switch (mecha) {
124403e07432SValerii Chubar 		case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
124503e07432SValerii Chubar 			class = template_class;
124603e07432SValerii Chubar 			type = PKCS11_CKK_EDDSA;
124703e07432SValerii Chubar 			break;
124802b16804SVesa Jääskeläinen 		case PKCS11_CKM_EC_KEY_PAIR_GEN:
124902b16804SVesa Jääskeläinen 			class = template_class;
125002b16804SVesa Jääskeläinen 			type = PKCS11_CKK_EC;
125102b16804SVesa Jääskeläinen 			break;
125286922832SVesa Jääskeläinen 		case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
125386922832SVesa Jääskeläinen 			class = template_class;
125486922832SVesa Jääskeläinen 			type = PKCS11_CKK_RSA;
125586922832SVesa Jääskeläinen 			break;
1256013934d8SVesa Jääskeläinen 		default:
1257013934d8SVesa Jääskeläinen 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1258013934d8SVesa Jääskeläinen 		}
1259013934d8SVesa Jääskeläinen 	}
1260013934d8SVesa Jääskeläinen 
1261013934d8SVesa Jääskeläinen 	/*
12622d25a9bcSRuchika Gupta 	 * Check and remove duplicates if any and create a new temporary
12632d25a9bcSRuchika Gupta 	 * template
12642d25a9bcSRuchika Gupta 	 */
1265dcad3409SRuchika Gupta 	rc = sanitize_client_object(&temp, template, template_size, class,
1266dcad3409SRuchika Gupta 				    type);
1267dcad3409SRuchika Gupta 	if (rc)
1268dcad3409SRuchika Gupta 		goto out;
1269dcad3409SRuchika Gupta 
1270dcad3409SRuchika Gupta 	/*
12712d25a9bcSRuchika Gupta 	 * For function type modify and copy return the created template
12722d25a9bcSRuchika Gupta 	 * from here. Rest of the code below is for creating objects
12732d25a9bcSRuchika Gupta 	 * or generating keys.
12742d25a9bcSRuchika Gupta 	 */
12752d25a9bcSRuchika Gupta 	switch (function) {
12762d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
12772d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
12782d25a9bcSRuchika Gupta 		*out = temp;
12792d25a9bcSRuchika Gupta 		return rc;
1280e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1281e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
1282e3f0cb56SRuchika Gupta 		if (function == PKCS11_FUNCTION_UNWRAP)
1283e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE;
1284e3f0cb56SRuchika Gupta 		else
1285e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_DERIVE_TEMPLATE;
1286e3f0cb56SRuchika Gupta 
1287e3f0cb56SRuchika Gupta 		rc = get_attribute_ptr(parent, indirect_template,
1288e3f0cb56SRuchika Gupta 				       (void *)&req_attrs, &size);
1289e3f0cb56SRuchika Gupta 		if (rc == PKCS11_CKR_OK && size != 0) {
1290e3f0cb56SRuchika Gupta 			rc = attributes_match_add_reference(&temp, req_attrs);
1291e3f0cb56SRuchika Gupta 			if (rc)
1292e3f0cb56SRuchika Gupta 				goto out;
1293e3f0cb56SRuchika Gupta 		}
1294e3f0cb56SRuchika Gupta 		break;
12952d25a9bcSRuchika Gupta 	default:
12962d25a9bcSRuchika Gupta 		break;
12972d25a9bcSRuchika Gupta 	}
12982d25a9bcSRuchika Gupta 
12992d25a9bcSRuchika Gupta 	/*
1300dcad3409SRuchika Gupta 	 * Check if class and type in temp are consistent with the mechanism
1301dcad3409SRuchika Gupta 	 */
1302fa247a2aSRuchika Gupta 	switch (mecha) {
1303fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1304fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1305fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) {
1306fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1307fa247a2aSRuchika Gupta 			goto out;
1308fa247a2aSRuchika Gupta 		}
1309fa247a2aSRuchika Gupta 		break;
1310fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1311fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1312fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_AES) {
1313fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1314fa247a2aSRuchika Gupta 			goto out;
1315fa247a2aSRuchika Gupta 		}
1316fa247a2aSRuchika Gupta 		break;
131702b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
131802b16804SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
131902b16804SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132002b16804SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_EC) {
132102b16804SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
132202b16804SVesa Jääskeläinen 			goto out;
132302b16804SVesa Jääskeläinen 		}
132402b16804SVesa Jääskeläinen 		break;
132503e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
132603e07432SValerii Chubar 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
132703e07432SValerii Chubar 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132803e07432SValerii Chubar 		    get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) {
132903e07432SValerii Chubar 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
133003e07432SValerii Chubar 			goto out;
133103e07432SValerii Chubar 		}
133203e07432SValerii Chubar 		break;
133386922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
133486922832SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
133586922832SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
133686922832SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_RSA) {
133786922832SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
133886922832SVesa Jääskeläinen 			goto out;
133986922832SVesa Jääskeläinen 		}
134086922832SVesa Jääskeläinen 		break;
1341fa247a2aSRuchika Gupta 	default:
1342fa247a2aSRuchika Gupta 		break;
1343fa247a2aSRuchika Gupta 	}
134463f89caaSJens Wiklander 
134563f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
134663f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
134763f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
134863f89caaSJens Wiklander 		goto out;
134963f89caaSJens Wiklander 	}
135063f89caaSJens Wiklander 
1351e3f0cb56SRuchika Gupta 	/*
1352e3f0cb56SRuchika Gupta 	 * TBD - Add a check to see if temp contains any attribute which
1353e3f0cb56SRuchika Gupta 	 * is not consistent with the object class or type and return error.
1354e3f0cb56SRuchika Gupta 	 * In current implementation such attributes are ignored and not
1355e3f0cb56SRuchika Gupta 	 * added to final object while PKCS#11 specification expects a
1356e3f0cb56SRuchika Gupta 	 * failure and an error code be returned.
1357e3f0cb56SRuchika Gupta 	 */
1358e3f0cb56SRuchika Gupta 
135963f89caaSJens Wiklander 	switch (get_class(temp)) {
136063f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
136163f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
136263f89caaSJens Wiklander 		break;
13634137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
13644137952dSVesa Jääskeläinen 		rc = create_certificate_attributes(&attrs, temp);
13654137952dSVesa Jääskeläinen 		break;
136663f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1367196bcd93SRuchika Gupta 		rc = sanitize_symm_key_attributes(&temp, function);
1368196bcd93SRuchika Gupta 		if (rc)
1369196bcd93SRuchika Gupta 			goto out;
137063f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
137163f89caaSJens Wiklander 		break;
137263f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
13739cf1afceSVesa Jääskeläinen 		rc = create_pub_key_attributes(&attrs, temp, function);
13745071d7d1SVesa Jääskeläinen 		if (rc)
13755071d7d1SVesa Jääskeläinen 			goto out;
13765071d7d1SVesa Jääskeläinen 		rc = create_pub_key_generated_attributes(&attrs, temp,
13775071d7d1SVesa Jääskeläinen 							 function);
137863f89caaSJens Wiklander 		break;
137963f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
138063f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
13817c243321SVesa Jääskeläinen 		if (rc)
13827c243321SVesa Jääskeläinen 			goto out;
13837c243321SVesa Jääskeläinen 		rc = create_priv_key_hidden_attributes(&attrs, temp, function);
138463f89caaSJens Wiklander 		break;
138563f89caaSJens Wiklander 	default:
138663f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
138763f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
138863f89caaSJens Wiklander 
138963f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139063f89caaSJens Wiklander 		break;
139163f89caaSJens Wiklander 	}
139263f89caaSJens Wiklander 	if (rc)
139363f89caaSJens Wiklander 		goto out;
139463f89caaSJens Wiklander 
139590c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) !=
1396002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1397002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139863f89caaSJens Wiklander 		goto out;
1399002f6b93SEtienne Carriere 	}
140063f89caaSJens Wiklander 
140190c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
1402002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1403002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
140463f89caaSJens Wiklander 		goto out;
1405002f6b93SEtienne Carriere 	}
140663f89caaSJens Wiklander 
140763f89caaSJens Wiklander 	switch (function) {
1408fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1409013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
1410fa247a2aSRuchika Gupta 		local = PKCS11_TRUE;
1411fa247a2aSRuchika Gupta 		break;
141263f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
141348799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1414e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
141563f89caaSJens Wiklander 	default:
141663f89caaSJens Wiklander 		local = PKCS11_FALSE;
141763f89caaSJens Wiklander 		break;
141863f89caaSJens Wiklander 	}
141963f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
142063f89caaSJens Wiklander 	if (rc)
142163f89caaSJens Wiklander 		goto out;
142263f89caaSJens Wiklander 
142363f89caaSJens Wiklander 	switch (get_class(attrs)) {
142463f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
142563f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
142663f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
142763f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
142863f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
142963f89caaSJens Wiklander 
1430fa247a2aSRuchika Gupta 		switch (function) {
143148799892SRuchika Gupta 		case PKCS11_FUNCTION_DERIVE:
143248799892SRuchika Gupta 			always_sensitive =
143348799892SRuchika Gupta 				get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) &&
143448799892SRuchika Gupta 				get_bool(attrs, PKCS11_CKA_SENSITIVE);
143548799892SRuchika Gupta 			never_extract =
143648799892SRuchika Gupta 			       get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) &&
143748799892SRuchika Gupta 			       !get_bool(attrs, PKCS11_CKA_EXTRACTABLE);
143848799892SRuchika Gupta 			break;
1439e3f0cb56SRuchika Gupta 		case PKCS11_FUNCTION_UNWRAP:
1440e3f0cb56SRuchika Gupta 			always_sensitive = PKCS11_FALSE;
1441e3f0cb56SRuchika Gupta 			never_extract = PKCS11_FALSE;
1442e3f0cb56SRuchika Gupta 			extractable = PKCS11_TRUE;
1443e3f0cb56SRuchika Gupta 
1444e3f0cb56SRuchika Gupta 			/*
1445e3f0cb56SRuchika Gupta 			 * Check if template passed by user has CKA_EXTRACTABLE.
1446e3f0cb56SRuchika Gupta 			 * If not, by default value of CKA_EXTRACTABLE is set as
1447e3f0cb56SRuchika Gupta 			 * TRUE.
1448e3f0cb56SRuchika Gupta 			 */
1449e3f0cb56SRuchika Gupta 			if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE,
1450e3f0cb56SRuchika Gupta 					      NULL,
1451e3f0cb56SRuchika Gupta 					      NULL) == PKCS11_RV_NOT_FOUND) {
1452e3f0cb56SRuchika Gupta 				rc = set_attribute(&attrs,
1453e3f0cb56SRuchika Gupta 						   PKCS11_CKA_EXTRACTABLE,
1454e3f0cb56SRuchika Gupta 						   &extractable,
1455e3f0cb56SRuchika Gupta 						   sizeof(extractable));
1456e3f0cb56SRuchika Gupta 				if (rc)
1457e3f0cb56SRuchika Gupta 					goto out;
1458e3f0cb56SRuchika Gupta 			}
1459e3f0cb56SRuchika Gupta 			break;
1460fa247a2aSRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1461013934d8SVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
1462fa247a2aSRuchika Gupta 			always_sensitive = get_bool(attrs,
1463fa247a2aSRuchika Gupta 						    PKCS11_CKA_SENSITIVE);
1464fa247a2aSRuchika Gupta 			never_extract = !get_bool(attrs,
1465fa247a2aSRuchika Gupta 						  PKCS11_CKA_EXTRACTABLE);
1466fa247a2aSRuchika Gupta 			break;
1467fa247a2aSRuchika Gupta 		default:
1468fa247a2aSRuchika Gupta 			break;
1469fa247a2aSRuchika Gupta 		}
1470fa247a2aSRuchika Gupta 
147163f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
147263f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
147363f89caaSJens Wiklander 		if (rc)
147463f89caaSJens Wiklander 			goto out;
147563f89caaSJens Wiklander 
147663f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
147763f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
147863f89caaSJens Wiklander 		if (rc)
147963f89caaSJens Wiklander 			goto out;
148063f89caaSJens Wiklander 
148163f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
1482fa247a2aSRuchika Gupta 		if (local)
1483fa247a2aSRuchika Gupta 			mechanism_id = mecha;
1484fa247a2aSRuchika Gupta 		else
148563f89caaSJens Wiklander 			mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
1486fa247a2aSRuchika Gupta 
148763f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
148863f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
148963f89caaSJens Wiklander 		if (rc)
149063f89caaSJens Wiklander 			goto out;
149163f89caaSJens Wiklander 		break;
149263f89caaSJens Wiklander 
149363f89caaSJens Wiklander 	default:
149463f89caaSJens Wiklander 		break;
149563f89caaSJens Wiklander 	}
149663f89caaSJens Wiklander 
149763f89caaSJens Wiklander 	*out = attrs;
149863f89caaSJens Wiklander 
149963f89caaSJens Wiklander #ifdef DEBUG
150063f89caaSJens Wiklander 	trace_attributes("object", attrs);
150163f89caaSJens Wiklander #endif
150263f89caaSJens Wiklander 
150363f89caaSJens Wiklander out:
150463f89caaSJens Wiklander 	TEE_Free(temp);
150563f89caaSJens Wiklander 	if (rc)
150663f89caaSJens Wiklander 		TEE_Free(attrs);
150763f89caaSJens Wiklander 
150863f89caaSJens Wiklander 	return rc;
150963f89caaSJens Wiklander }
151063f89caaSJens Wiklander 
check_attrs_misc_integrity(struct obj_attrs * head)151163f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
151263f89caaSJens Wiklander {
151363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
151463f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
151563f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
151663f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
151763f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
151863f89caaSJens Wiklander 
151963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152063f89caaSJens Wiklander 	}
152163f89caaSJens Wiklander 
152263f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
152363f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
152463f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
152563f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
152663f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
152763f89caaSJens Wiklander 
152863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152963f89caaSJens Wiklander 	}
153063f89caaSJens Wiklander 
153163f89caaSJens Wiklander 	return PKCS11_CKR_OK;
153263f89caaSJens Wiklander }
153363f89caaSJens Wiklander 
object_is_private(struct obj_attrs * head)153489735787SRuchika Gupta bool object_is_private(struct obj_attrs *head)
153589735787SRuchika Gupta {
153665fb9092SVesa Jääskeläinen 	return get_bool(head, PKCS11_CKA_PRIVATE);
153789735787SRuchika Gupta }
153889735787SRuchika Gupta 
object_is_token(struct obj_attrs * head)15392d25a9bcSRuchika Gupta bool object_is_token(struct obj_attrs *head)
15402d25a9bcSRuchika Gupta {
15412d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_TOKEN);
15422d25a9bcSRuchika Gupta }
15432d25a9bcSRuchika Gupta 
object_is_modifiable(struct obj_attrs * head)15442d25a9bcSRuchika Gupta bool object_is_modifiable(struct obj_attrs *head)
15452d25a9bcSRuchika Gupta {
15462d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_MODIFIABLE);
15472d25a9bcSRuchika Gupta }
15482d25a9bcSRuchika Gupta 
object_is_copyable(struct obj_attrs * head)15492d25a9bcSRuchika Gupta bool object_is_copyable(struct obj_attrs *head)
15502d25a9bcSRuchika Gupta {
15512d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_COPYABLE);
15522d25a9bcSRuchika Gupta }
15532d25a9bcSRuchika Gupta 
155463f89caaSJens Wiklander /*
1555512cbf1dSJens Wiklander  * Check access to object against authentication to token
1556512cbf1dSJens Wiklander  */
check_access_attrs_against_token(struct pkcs11_session * session,struct obj_attrs * head)1557512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
1558512cbf1dSJens Wiklander 						struct obj_attrs *head)
1559512cbf1dSJens Wiklander {
1560512cbf1dSJens Wiklander 	bool private = true;
1561512cbf1dSJens Wiklander 
1562512cbf1dSJens Wiklander 	switch (get_class(head)) {
1563512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
156465fb9092SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1565512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
1566512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
15674137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
156865fb9092SVesa Jääskeläinen 		private = object_is_private(head);
1569512cbf1dSJens Wiklander 		break;
1570512cbf1dSJens Wiklander 	default:
1571512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1572512cbf1dSJens Wiklander 	}
1573512cbf1dSJens Wiklander 
15745db0fef4SRuchika Gupta 	if (private && (pkcs11_session_is_public(session) ||
15755db0fef4SRuchika Gupta 			pkcs11_session_is_so(session))) {
15765db0fef4SRuchika Gupta 		DMSG("Private object access from a public or SO session");
1577512cbf1dSJens Wiklander 
157812f1ba86SRuchika Gupta 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1579512cbf1dSJens Wiklander 	}
1580512cbf1dSJens Wiklander 
1581512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1582512cbf1dSJens Wiklander }
1583512cbf1dSJens Wiklander 
1584512cbf1dSJens Wiklander /*
158563f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
158663f89caaSJens Wiklander  */
check_created_attrs_against_token(struct pkcs11_session * session,struct obj_attrs * head)158763f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
158863f89caaSJens Wiklander 						 struct obj_attrs *head)
158963f89caaSJens Wiklander {
159063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
159163f89caaSJens Wiklander 
159263f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
159363f89caaSJens Wiklander 	if (rc)
159463f89caaSJens Wiklander 		return rc;
159563f89caaSJens Wiklander 
159663f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
159763f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
159863f89caaSJens Wiklander 		DMSG("Can't create trusted object");
159963f89caaSJens Wiklander 
160063f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
160163f89caaSJens Wiklander 	}
160263f89caaSJens Wiklander 
160363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
160463f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
160563f89caaSJens Wiklander 		DMSG("Can't create persistent object");
160663f89caaSJens Wiklander 
160763f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
160863f89caaSJens Wiklander 	}
160963f89caaSJens Wiklander 
161063f89caaSJens Wiklander 	return PKCS11_CKR_OK;
161163f89caaSJens Wiklander }
161263f89caaSJens Wiklander 
161363f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
161463f89caaSJens Wiklander 	do {								\
161563f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
161663f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
161763f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
161863f89caaSJens Wiklander 									\
161963f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
162063f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
162163f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
162263f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
162363f89caaSJens Wiklander 	} while (0)
162463f89caaSJens Wiklander 
check_attr_bval(uint32_t proc_id __maybe_unused,struct obj_attrs * head,uint32_t attribute,bool val)162563f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
162663f89caaSJens Wiklander 					   struct obj_attrs *head,
162763f89caaSJens Wiklander 					   uint32_t attribute, bool val)
162863f89caaSJens Wiklander {
162963f89caaSJens Wiklander 	uint8_t bbool = 0;
163063f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
163163f89caaSJens Wiklander 
163263f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
163363f89caaSJens Wiklander 		return true;
163463f89caaSJens Wiklander 
163563f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
163663f89caaSJens Wiklander 	return false;
163763f89caaSJens Wiklander }
163863f89caaSJens Wiklander 
163963f89caaSJens Wiklander /*
164063f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
164163f89caaSJens Wiklander  * used to create it.
164263f89caaSJens Wiklander  *
164363f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
164463f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
164563f89caaSJens Wiklander  */
1646897aaf11SEtienne Carriere enum pkcs11_rc
check_created_attrs_against_processing(uint32_t proc_id,struct obj_attrs * head __maybe_unused)1647897aaf11SEtienne Carriere check_created_attrs_against_processing(uint32_t proc_id,
1648897aaf11SEtienne Carriere 				       struct obj_attrs *head __maybe_unused)
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 */
get_key_min_max_sizes(enum pkcs11_key_type key_type,uint32_t * min_key_size,uint32_t * max_key_size)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 
check_created_attrs(struct obj_attrs * key1,struct obj_attrs * key2)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;
1827*04e46975SEtienne Carriere 			key_length = ROUNDUP_DIV(key_length, 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 */
parent_key_complies_allowed_processings(uint32_t proc_id,struct obj_attrs * head)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 
func_to_attr(enum processing_func func)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
check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,enum processing_func function,struct obj_attrs * head)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:
194863778faaSEtienne Carriere 	case PKCS11_CKM_AES_GCM:
19490ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC:
19500ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC_GENERAL:
1951512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1952512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1953512cbf1dSJens Wiklander 			break;
1954512cbf1dSJens Wiklander 
1955512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1956512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1957512cbf1dSJens Wiklander 
19585f80f270SRuchika Gupta 		if (function == PKCS11_FUNCTION_WRAP)
19595f80f270SRuchika Gupta 			return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1960e3f0cb56SRuchika Gupta 		else if (function == PKCS11_FUNCTION_UNWRAP)
1961e3f0cb56SRuchika Gupta 			return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
19625f80f270SRuchika Gupta 		else
1963512cbf1dSJens Wiklander 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1964512cbf1dSJens Wiklander 
1965c3033708SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
1966c3033708SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
1967c3033708SRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY &&
1968c3033708SRuchika Gupta 		    key_type != PKCS11_CKK_AES)
1969c3033708SRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1970c3033708SRuchika Gupta 
1971c3033708SRuchika Gupta 		if (get_bool(head, PKCS11_CKA_ENCRYPT)) {
1972c3033708SRuchika Gupta 			/*
1973c3033708SRuchika Gupta 			 * Intentionally refuse to proceed despite
1974c3033708SRuchika Gupta 			 * PKCS#11 specifications v2.40 and v3.0 not expecting
1975c3033708SRuchika Gupta 			 * this behavior to avoid potential security issue
1976c3033708SRuchika Gupta 			 * where keys derived by these mechanisms can be
1977c3033708SRuchika Gupta 			 * revealed by doing data encryption using parent key.
1978c3033708SRuchika Gupta 			 */
1979c3033708SRuchika Gupta 			return PKCS11_CKR_FUNCTION_FAILED;
1980c3033708SRuchika Gupta 		}
1981c3033708SRuchika Gupta 
1982c3033708SRuchika Gupta 		break;
1983689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
1984689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
1985689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
1986689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
1987689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
1988689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
198970b6683bSVictor Chong 	case PKCS11_CKM_MD5_HMAC_GENERAL:
199070b6683bSVictor Chong 	case PKCS11_CKM_SHA_1_HMAC_GENERAL:
199170b6683bSVictor Chong 	case PKCS11_CKM_SHA224_HMAC_GENERAL:
199270b6683bSVictor Chong 	case PKCS11_CKM_SHA256_HMAC_GENERAL:
199370b6683bSVictor Chong 	case PKCS11_CKM_SHA384_HMAC_GENERAL:
199470b6683bSVictor Chong 	case PKCS11_CKM_SHA512_HMAC_GENERAL:
1995689f4e5bSRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY)
1996689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1997689f4e5bSRuchika Gupta 
1998689f4e5bSRuchika Gupta 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
1999689f4e5bSRuchika Gupta 			break;
2000689f4e5bSRuchika Gupta 
2001689f4e5bSRuchika Gupta 		switch (proc_id) {
2002689f4e5bSRuchika Gupta 		case PKCS11_CKM_MD5_HMAC:
200370b6683bSVictor Chong 		case PKCS11_CKM_MD5_HMAC_GENERAL:
2004689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_MD5_HMAC)
2005689f4e5bSRuchika Gupta 				break;
2006689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2007689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA_1_HMAC:
200870b6683bSVictor Chong 		case PKCS11_CKM_SHA_1_HMAC_GENERAL:
2009689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA_1_HMAC)
2010689f4e5bSRuchika Gupta 				break;
2011689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2012689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA224_HMAC:
201370b6683bSVictor Chong 		case PKCS11_CKM_SHA224_HMAC_GENERAL:
2014689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA224_HMAC)
2015689f4e5bSRuchika Gupta 				break;
2016689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2017689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA256_HMAC:
201870b6683bSVictor Chong 		case PKCS11_CKM_SHA256_HMAC_GENERAL:
2019689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA256_HMAC)
2020689f4e5bSRuchika Gupta 				break;
2021689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2022689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA384_HMAC:
202370b6683bSVictor Chong 		case PKCS11_CKM_SHA384_HMAC_GENERAL:
2024689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA384_HMAC)
2025689f4e5bSRuchika Gupta 				break;
2026689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2027689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA512_HMAC:
202870b6683bSVictor Chong 		case PKCS11_CKM_SHA512_HMAC_GENERAL:
2029689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA512_HMAC)
2030689f4e5bSRuchika Gupta 				break;
2031689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2032689f4e5bSRuchika Gupta 		default:
2033689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2034689f4e5bSRuchika Gupta 		}
2035689f4e5bSRuchika Gupta 		break;
2036689f4e5bSRuchika Gupta 
203703e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
203803e07432SValerii Chubar 		if (key_type != PKCS11_CKK_EC_EDWARDS) {
203903e07432SValerii Chubar 			EMSG("Invalid key %s for mechanism %s",
204003e07432SValerii Chubar 			     id2str_type(key_type, key_class),
204103e07432SValerii Chubar 			     id2str_proc(proc_id));
204203e07432SValerii Chubar 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
204303e07432SValerii Chubar 		}
204403e07432SValerii Chubar 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
204503e07432SValerii Chubar 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
204603e07432SValerii Chubar 			EMSG("Invalid key class for mechanism %s",
204703e07432SValerii Chubar 			     id2str_proc(proc_id));
204803e07432SValerii Chubar 
204903e07432SValerii Chubar 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
205003e07432SValerii Chubar 		}
205103e07432SValerii Chubar 		break;
205203e07432SValerii Chubar 
2053fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
2054fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
2055fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
2056fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
2057fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
2058fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
2059cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
2060fb279d8bSVesa Jääskeläinen 		if (key_type != PKCS11_CKK_EC) {
2061fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
2062fb279d8bSVesa Jääskeläinen 			     id2str_type(key_type, key_class),
2063fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2064fb279d8bSVesa Jääskeläinen 
2065fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
2066fb279d8bSVesa Jääskeläinen 		}
2067fb279d8bSVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
2068fb279d8bSVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
2069fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
2070fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2071fb279d8bSVesa Jääskeläinen 
2072fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2073fb279d8bSVesa Jääskeläinen 		}
2074fb279d8bSVesa Jääskeläinen 		break;
20750442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
20760442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
20770442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
20780442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
20790442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
20800442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
20810442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
208245d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
2083dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
2084d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
2085e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
2086d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
2087d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
2088d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
2089d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
2090d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
20910442c956SVesa Jääskeläinen 		if (key_type != PKCS11_CKK_RSA) {
20920442c956SVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
20930442c956SVesa Jääskeläinen 			     id2str_type(key_type, key_class),
20940442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20950442c956SVesa Jääskeläinen 
20960442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
20970442c956SVesa Jääskeläinen 		}
20980442c956SVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
20990442c956SVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
21000442c956SVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
21010442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
21020442c956SVesa Jääskeläinen 
21030442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
21040442c956SVesa Jääskeläinen 		}
21050442c956SVesa Jääskeläinen 		break;
2106512cbf1dSJens Wiklander 	default:
2107512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
2108512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
2109512cbf1dSJens Wiklander 
2110512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
2111512cbf1dSJens Wiklander 	}
2112512cbf1dSJens Wiklander 
2113512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
2114512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
2115512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2116512cbf1dSJens Wiklander 	}
2117512cbf1dSJens Wiklander 
2118512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
2119512cbf1dSJens Wiklander }
2120783c1515SRuchika Gupta 
attribute_is_exportable(struct pkcs11_attribute_head * req_attr,struct pkcs11_object * obj)2121783c1515SRuchika Gupta bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
2122783c1515SRuchika Gupta 			     struct pkcs11_object *obj)
2123783c1515SRuchika Gupta {
2124783c1515SRuchika Gupta 	uint8_t boolval = 0;
2125783c1515SRuchika Gupta 	uint32_t boolsize = 0;
2126783c1515SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2127783c1515SRuchika Gupta 	enum pkcs11_class_id key_class = get_class(obj->attributes);
2128783c1515SRuchika Gupta 
2129981966bcSVesa Jääskeläinen 	if (attribute_is_hidden(req_attr))
2130981966bcSVesa Jääskeläinen 		return false;
2131981966bcSVesa Jääskeläinen 
2132783c1515SRuchika Gupta 	if (key_class != PKCS11_CKO_SECRET_KEY &&
2133783c1515SRuchika Gupta 	    key_class != PKCS11_CKO_PRIVATE_KEY)
2134783c1515SRuchika Gupta 		return true;
2135783c1515SRuchika Gupta 
2136783c1515SRuchika Gupta 	switch (req_attr->id) {
2137783c1515SRuchika Gupta 	case PKCS11_CKA_PRIVATE_EXPONENT:
2138783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_1:
2139783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_2:
2140783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_1:
2141783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_2:
2142783c1515SRuchika Gupta 	case PKCS11_CKA_COEFFICIENT:
2143783c1515SRuchika Gupta 	case PKCS11_CKA_VALUE:
2144783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2145783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
2146783c1515SRuchika Gupta 				   &boolval, &boolsize);
2147783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_FALSE)
2148783c1515SRuchika Gupta 			return false;
2149783c1515SRuchika Gupta 
2150783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2151783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
2152783c1515SRuchika Gupta 				   &boolval, &boolsize);
2153783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_TRUE)
2154783c1515SRuchika Gupta 			return false;
2155783c1515SRuchika Gupta 		break;
2156783c1515SRuchika Gupta 	default:
2157783c1515SRuchika Gupta 		break;
2158783c1515SRuchika Gupta 	}
2159783c1515SRuchika Gupta 
2160783c1515SRuchika Gupta 	return true;
2161783c1515SRuchika Gupta }
21622d25a9bcSRuchika Gupta 
attr_is_modifiable_any_key(struct pkcs11_attribute_head * attr)21632d25a9bcSRuchika Gupta static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr)
21642d25a9bcSRuchika Gupta {
21652d25a9bcSRuchika Gupta 	switch (attr->id) {
21662d25a9bcSRuchika Gupta 	case PKCS11_CKA_ID:
21672d25a9bcSRuchika Gupta 	case PKCS11_CKA_START_DATE:
21682d25a9bcSRuchika Gupta 	case PKCS11_CKA_END_DATE:
21692d25a9bcSRuchika Gupta 	case PKCS11_CKA_DERIVE:
21702d25a9bcSRuchika Gupta 		return true;
21712d25a9bcSRuchika Gupta 	default:
21722d25a9bcSRuchika Gupta 		return false;
21732d25a9bcSRuchika Gupta 	}
21742d25a9bcSRuchika Gupta }
21752d25a9bcSRuchika Gupta 
attr_is_modifiable_secret_key(struct pkcs11_attribute_head * attr,struct pkcs11_session * session,struct pkcs11_object * obj)21762d25a9bcSRuchika Gupta static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr,
21772d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21782d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj)
21792d25a9bcSRuchika Gupta {
21802d25a9bcSRuchika Gupta 	switch (attr->id) {
21812d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
21822d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
21832d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
21842d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
21852d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
21862d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
2187bcac2127SMarouene Boubakri 	case PKCS11_CKA_CHECK_VALUE:
21882d25a9bcSRuchika Gupta 		return true;
21892d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
21902d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
21912d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
21922d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
21932d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
21942d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
21952d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
21962d25a9bcSRuchika Gupta 	/* Change in CKA_TRUSTED can only be done by SO */
21972d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
21982d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
21992d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
22002d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
22012d25a9bcSRuchika Gupta 		return false;
22022d25a9bcSRuchika Gupta 	default:
22032d25a9bcSRuchika Gupta 		return false;
22042d25a9bcSRuchika Gupta 	}
22052d25a9bcSRuchika Gupta }
22062d25a9bcSRuchika Gupta 
attr_is_modifiable_public_key(struct pkcs11_attribute_head * attr,struct pkcs11_session * session,struct pkcs11_object * obj __unused)22072d25a9bcSRuchika Gupta static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr,
22082d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
22092d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj __unused)
22102d25a9bcSRuchika Gupta {
22112d25a9bcSRuchika Gupta 	switch (attr->id) {
22122d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22132d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
22142d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
22152d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY_RECOVER:
22162d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
22172d25a9bcSRuchika Gupta 		return true;
22182d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
22192d25a9bcSRuchika Gupta 		/* Change in CKA_TRUSTED can only be done by SO */
22202d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
22212d25a9bcSRuchika Gupta 	default:
22222d25a9bcSRuchika Gupta 		return false;
22232d25a9bcSRuchika Gupta 	}
22242d25a9bcSRuchika Gupta }
22252d25a9bcSRuchika Gupta 
attr_is_modifiable_private_key(struct pkcs11_attribute_head * attr,struct pkcs11_session * sess __unused,struct pkcs11_object * obj)22262d25a9bcSRuchika Gupta static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr,
22272d25a9bcSRuchika Gupta 					   struct pkcs11_session *sess __unused,
22282d25a9bcSRuchika Gupta 					   struct pkcs11_object *obj)
22292d25a9bcSRuchika Gupta {
22302d25a9bcSRuchika Gupta 	switch (attr->id) {
22312d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22322d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
22332d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
22342d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN_RECOVER:
22352d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
22362d25a9bcSRuchika Gupta 	/*
22372d25a9bcSRuchika Gupta 	 * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO
22382d25a9bcSRuchika Gupta 	 * Specification mentions that if this attribute is
22392d25a9bcSRuchika Gupta 	 * supplied as part of a template for C_CreateObject, C_CopyObject or
22402d25a9bcSRuchika Gupta 	 * C_SetAttributeValue for a private key, the token MUST verify
22412d25a9bcSRuchika Gupta 	 * correspondence between the private key data and the public key data
22422d25a9bcSRuchika Gupta 	 * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be
22432d25a9bcSRuchika Gupta 	 * taken care of when this object type will be implemented
22442d25a9bcSRuchika Gupta 	 */
22452d25a9bcSRuchika Gupta 	case PKCS11_CKA_PUBLIC_KEY_INFO:
22462d25a9bcSRuchika Gupta 		return true;
22472d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
22482d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
22492d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
22502d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
22512d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
22522d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
22532d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
22542d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
22552d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
22562d25a9bcSRuchika Gupta 		return false;
22572d25a9bcSRuchika Gupta 	default:
22582d25a9bcSRuchika Gupta 		return false;
22592d25a9bcSRuchika Gupta 	}
22602d25a9bcSRuchika Gupta }
22612d25a9bcSRuchika Gupta 
attr_is_modifiable_certificate(struct pkcs11_attribute_head * attr,struct pkcs11_session * session,struct pkcs11_object * obj)22624137952dSVesa Jääskeläinen static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr,
22634137952dSVesa Jääskeläinen 					   struct pkcs11_session *session,
22644137952dSVesa Jääskeläinen 					   struct pkcs11_object *obj)
22654137952dSVesa Jääskeläinen {
22664137952dSVesa Jääskeläinen 	uint8_t boolval = 0;
22674137952dSVesa Jääskeläinen 	uint32_t boolsize = 0;
22684137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
22694137952dSVesa Jääskeläinen 
22704137952dSVesa Jääskeläinen 	/* Trusted certificates cannot be modified. */
22714137952dSVesa Jääskeläinen 	rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED,
22724137952dSVesa Jääskeläinen 			   &boolval, &boolsize);
22734137952dSVesa Jääskeläinen 	if (rc || boolval == PKCS11_TRUE)
22744137952dSVesa Jääskeläinen 		return false;
22754137952dSVesa Jääskeläinen 
22764137952dSVesa Jääskeläinen 	/* Common certificate attributes */
22774137952dSVesa Jääskeläinen 	switch (attr->id) {
22784137952dSVesa Jääskeläinen 	case PKCS11_CKA_TRUSTED:
22794137952dSVesa Jääskeläinen 		/*
22804137952dSVesa Jääskeläinen 		 * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an
22814137952dSVesa Jääskeläinen 		 * application. It MUST be set by a token initialization
22824137952dSVesa Jääskeläinen 		 * application or by the token’s SO.
22834137952dSVesa Jääskeläinen 		 */
22844137952dSVesa Jääskeläinen 		return pkcs11_session_is_so(session);
22854137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_TYPE:
22864137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_CATEGORY:
22874137952dSVesa Jääskeläinen 		return false;
22884137952dSVesa Jääskeläinen 	default:
22894137952dSVesa Jääskeläinen 		break;
22904137952dSVesa Jääskeläinen 	}
22914137952dSVesa Jääskeläinen 
22924137952dSVesa Jääskeläinen 	/* Certificate type specific attributes */
22934137952dSVesa Jääskeläinen 	switch (get_certificate_type(obj->attributes)) {
22944137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
22954137952dSVesa Jääskeläinen 		/*
22964137952dSVesa Jääskeläinen 		 * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER
22974137952dSVesa Jääskeläinen 		 * attributes may be modified after the object is created.
22984137952dSVesa Jääskeläinen 		 */
22994137952dSVesa Jääskeläinen 		switch (attr->id) {
23004137952dSVesa Jääskeläinen 		case PKCS11_CKA_ID:
23014137952dSVesa Jääskeläinen 		case PKCS11_CKA_ISSUER:
23024137952dSVesa Jääskeläinen 		case PKCS11_CKA_SERIAL_NUMBER:
23034137952dSVesa Jääskeläinen 			return true;
23044137952dSVesa Jääskeläinen 		default:
23054137952dSVesa Jääskeläinen 			break;
23064137952dSVesa Jääskeläinen 		}
23074137952dSVesa Jääskeläinen 		break;
23084137952dSVesa Jääskeläinen 	default:
23094137952dSVesa Jääskeläinen 		/* Unsupported certificate type */
23104137952dSVesa Jääskeläinen 		break;
23114137952dSVesa Jääskeläinen 	}
23124137952dSVesa Jääskeläinen 
23134137952dSVesa Jääskeläinen 	return false;
23144137952dSVesa Jääskeläinen }
23154137952dSVesa Jääskeläinen 
attribute_is_modifiable(struct pkcs11_session * session,struct pkcs11_attribute_head * req_attr,struct pkcs11_object * obj,enum pkcs11_class_id class,enum processing_func function)23162d25a9bcSRuchika Gupta static bool attribute_is_modifiable(struct pkcs11_session *session,
23172d25a9bcSRuchika Gupta 				    struct pkcs11_attribute_head *req_attr,
23182d25a9bcSRuchika Gupta 				    struct pkcs11_object *obj,
23192d25a9bcSRuchika Gupta 				    enum pkcs11_class_id class,
23202d25a9bcSRuchika Gupta 				    enum processing_func function)
23212d25a9bcSRuchika Gupta {
23222d25a9bcSRuchika Gupta 	/* Check modifiable attributes common to any object */
23232d25a9bcSRuchika Gupta 	switch (req_attr->id) {
23242d25a9bcSRuchika Gupta 	case PKCS11_CKA_LABEL:
23252d25a9bcSRuchika Gupta 		return true;
23262d25a9bcSRuchika Gupta 	case PKCS11_CKA_TOKEN:
23272d25a9bcSRuchika Gupta 	case PKCS11_CKA_MODIFIABLE:
23282d25a9bcSRuchika Gupta 	case PKCS11_CKA_DESTROYABLE:
23292d25a9bcSRuchika Gupta 	case PKCS11_CKA_PRIVATE:
23302d25a9bcSRuchika Gupta 		return function == PKCS11_FUNCTION_COPY;
23312d25a9bcSRuchika Gupta 	case PKCS11_CKA_COPYABLE:
23322d25a9bcSRuchika Gupta 		/*
23332d25a9bcSRuchika Gupta 		 * Specification mentions that if the attribute value is false
23342d25a9bcSRuchika Gupta 		 * it can't be set to true. Reading this we assume that it
23352d25a9bcSRuchika Gupta 		 * should be possible to modify this attribute even though this
23362d25a9bcSRuchika Gupta 		 * is not marked as modifiable in Table 10 if done in right
23372d25a9bcSRuchika Gupta 		 * direction i.e from TRUE -> FALSE.
23382d25a9bcSRuchika Gupta 		 */
23392d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, req_attr->id);
23402d25a9bcSRuchika Gupta 	default:
23412d25a9bcSRuchika Gupta 		break;
23422d25a9bcSRuchika Gupta 	}
23432d25a9bcSRuchika Gupta 
23442d25a9bcSRuchika Gupta 	/* Attribute checking based on class type */
23452d25a9bcSRuchika Gupta 	switch (class) {
23462d25a9bcSRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
23472d25a9bcSRuchika Gupta 	case PKCS11_CKO_PUBLIC_KEY:
23482d25a9bcSRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
23492d25a9bcSRuchika Gupta 		if (attr_is_modifiable_any_key(req_attr))
23502d25a9bcSRuchika Gupta 			return true;
23512d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_SECRET_KEY &&
23522d25a9bcSRuchika Gupta 		    attr_is_modifiable_secret_key(req_attr, session, obj))
23532d25a9bcSRuchika Gupta 			return true;
23542d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PUBLIC_KEY &&
23552d25a9bcSRuchika Gupta 		    attr_is_modifiable_public_key(req_attr, session, obj))
23562d25a9bcSRuchika Gupta 			return true;
23572d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PRIVATE_KEY &&
23582d25a9bcSRuchika Gupta 		    attr_is_modifiable_private_key(req_attr, session, obj))
23592d25a9bcSRuchika Gupta 			return true;
23602d25a9bcSRuchika Gupta 		break;
23612d25a9bcSRuchika Gupta 	case PKCS11_CKO_DATA:
23622d25a9bcSRuchika Gupta 		/* None of the data object attributes are modifiable */
23632d25a9bcSRuchika Gupta 		return false;
23644137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
23654137952dSVesa Jääskeläinen 		return attr_is_modifiable_certificate(req_attr, session, obj);
23662d25a9bcSRuchika Gupta 	default:
23672d25a9bcSRuchika Gupta 		break;
23682d25a9bcSRuchika Gupta 	}
23692d25a9bcSRuchika Gupta 
23702d25a9bcSRuchika Gupta 	return false;
23712d25a9bcSRuchika Gupta }
23722d25a9bcSRuchika Gupta 
check_attrs_against_modification(struct pkcs11_session * session,struct obj_attrs * head,struct pkcs11_object * obj,enum processing_func function)23732d25a9bcSRuchika Gupta enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session,
23742d25a9bcSRuchika Gupta 						struct obj_attrs *head,
23752d25a9bcSRuchika Gupta 						struct pkcs11_object *obj,
23762d25a9bcSRuchika Gupta 						enum processing_func function)
23772d25a9bcSRuchika Gupta {
23782d25a9bcSRuchika Gupta 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
23792d25a9bcSRuchika Gupta 	char *cur = NULL;
23802d25a9bcSRuchika Gupta 	char *end = NULL;
23812d25a9bcSRuchika Gupta 	size_t len = 0;
23822d25a9bcSRuchika Gupta 
23832d25a9bcSRuchika Gupta 	class = get_class(obj->attributes);
23842d25a9bcSRuchika Gupta 
23852d25a9bcSRuchika Gupta 	cur = (char *)head + sizeof(struct obj_attrs);
23862d25a9bcSRuchika Gupta 	end = cur + head->attrs_size;
23872d25a9bcSRuchika Gupta 
23882d25a9bcSRuchika Gupta 	for (; cur < end; cur += len) {
23892d25a9bcSRuchika Gupta 		/* Structure aligned copy of the pkcs11_ref in the object */
23902d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head cli_ref = { };
23912d25a9bcSRuchika Gupta 
23922d25a9bcSRuchika Gupta 		TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
23932d25a9bcSRuchika Gupta 		len = sizeof(cli_ref) + cli_ref.size;
23942d25a9bcSRuchika Gupta 
2395981966bcSVesa Jääskeläinen 		/* Protect hidden attributes */
2396981966bcSVesa Jääskeläinen 		if (attribute_is_hidden(&cli_ref))
2397981966bcSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
2398981966bcSVesa Jääskeläinen 
23992d25a9bcSRuchika Gupta 		/*
24002d25a9bcSRuchika Gupta 		 * Check 1 - Check if attribute belongs to the object
24012d25a9bcSRuchika Gupta 		 * The obj->attributes has all the attributes in
24022d25a9bcSRuchika Gupta 		 * it which are allowed for an object.
24032d25a9bcSRuchika Gupta 		 */
24042d25a9bcSRuchika Gupta 		if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL,
24052d25a9bcSRuchika Gupta 				      NULL) == PKCS11_RV_NOT_FOUND)
24062d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
24072d25a9bcSRuchika Gupta 
24082d25a9bcSRuchika Gupta 		/* Check 2 - Is attribute modifiable */
24092d25a9bcSRuchika Gupta 		if (!attribute_is_modifiable(session, &cli_ref, obj, class,
24102d25a9bcSRuchika Gupta 					     function))
24112d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_READ_ONLY;
24122d25a9bcSRuchika Gupta 
24132d25a9bcSRuchika Gupta 		/*
24142d25a9bcSRuchika Gupta 		 * Checks for modification in PKCS11_CKA_TOKEN and
24152d25a9bcSRuchika Gupta 		 * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY
24162d25a9bcSRuchika Gupta 		 * only, so skip them for PKCS11_FUNCTION_MODIFY.
24172d25a9bcSRuchika Gupta 		 */
24182d25a9bcSRuchika Gupta 		if (function == PKCS11_FUNCTION_MODIFY)
24192d25a9bcSRuchika Gupta 			continue;
24202d25a9bcSRuchika Gupta 
24212d25a9bcSRuchika Gupta 		/*
24222d25a9bcSRuchika Gupta 		 * An attempt to copy an object to a token will fail for
24232d25a9bcSRuchika Gupta 		 * RO session
24242d25a9bcSRuchika Gupta 		 */
24252d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_TOKEN &&
24262d25a9bcSRuchika Gupta 		    get_bool(head, PKCS11_CKA_TOKEN)) {
24272d25a9bcSRuchika Gupta 			if (!pkcs11_session_is_read_write(session)) {
24282d25a9bcSRuchika Gupta 				DMSG("Can't copy to token in a RO session");
24292d25a9bcSRuchika Gupta 				return PKCS11_CKR_SESSION_READ_ONLY;
24302d25a9bcSRuchika Gupta 			}
24312d25a9bcSRuchika Gupta 		}
24322d25a9bcSRuchika Gupta 
24332d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_PRIVATE) {
24342d25a9bcSRuchika Gupta 			bool parent_priv =
24352d25a9bcSRuchika Gupta 				get_bool(obj->attributes, cli_ref.id);
24362d25a9bcSRuchika Gupta 			bool obj_priv = get_bool(head, cli_ref.id);
24372d25a9bcSRuchika Gupta 
24382d25a9bcSRuchika Gupta 			/*
24392d25a9bcSRuchika Gupta 			 * If PKCS11_CKA_PRIVATE is being set to TRUE from
24402d25a9bcSRuchika Gupta 			 * FALSE, user has to be logged in
24412d25a9bcSRuchika Gupta 			 */
24422d25a9bcSRuchika Gupta 			if (!parent_priv && obj_priv) {
24432d25a9bcSRuchika Gupta 				if ((pkcs11_session_is_public(session) ||
24442d25a9bcSRuchika Gupta 				     pkcs11_session_is_so(session)))
24452d25a9bcSRuchika Gupta 					return PKCS11_CKR_USER_NOT_LOGGED_IN;
24462d25a9bcSRuchika Gupta 			}
2447df017b2bSRuchika Gupta 
2448df017b2bSRuchika Gupta 			/*
2449df017b2bSRuchika Gupta 			 * Restriction added - Even for Copy, do not allow
2450df017b2bSRuchika Gupta 			 * modification of CKA_PRIVATE from TRUE to FALSE
2451df017b2bSRuchika Gupta 			 */
2452df017b2bSRuchika Gupta 			if (parent_priv && !obj_priv)
2453df017b2bSRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
24542d25a9bcSRuchika Gupta 		}
24552d25a9bcSRuchika Gupta 	}
24562d25a9bcSRuchika Gupta 
24572d25a9bcSRuchika Gupta 	return PKCS11_CKR_OK;
24582d25a9bcSRuchika Gupta }
24598c499324SRuchika Gupta 
set_secret_key_data(struct obj_attrs ** head,void * data,size_t key_size)24608c499324SRuchika Gupta static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
24618c499324SRuchika Gupta 					  size_t key_size)
24628c499324SRuchika Gupta {
24638c499324SRuchika Gupta 	uint32_t size = sizeof(uint32_t);
24648c499324SRuchika Gupta 	uint32_t key_length = 0;
24658c499324SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
24668c499324SRuchika Gupta 
24678c499324SRuchika Gupta 	/* Get key size if present in template */
24688c499324SRuchika Gupta 	rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size);
24698c499324SRuchika Gupta 	if (rc && rc != PKCS11_RV_NOT_FOUND)
24708c499324SRuchika Gupta 		return rc;
24718c499324SRuchika Gupta 
24728c499324SRuchika Gupta 	if (key_length) {
24738c499324SRuchika Gupta 		if (key_size < key_length)
24748c499324SRuchika Gupta 			return PKCS11_CKR_DATA_LEN_RANGE;
24758c499324SRuchika Gupta 	} else {
24768c499324SRuchika Gupta 		key_length = key_size;
24778c499324SRuchika Gupta 		rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length,
24788c499324SRuchika Gupta 				   sizeof(uint32_t));
24798c499324SRuchika Gupta 		if (rc)
24808c499324SRuchika Gupta 			return rc;
24818c499324SRuchika Gupta 	}
24828c499324SRuchika Gupta 
24838c499324SRuchika Gupta 	/* Now we can check the VALUE_LEN field */
24848c499324SRuchika Gupta 	rc = check_created_attrs(*head, NULL);
24858c499324SRuchika Gupta 	if (rc)
24868c499324SRuchika Gupta 		return rc;
24878c499324SRuchika Gupta 
24888c499324SRuchika Gupta 	/* Remove the default empty value attribute if found */
24898c499324SRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
24908c499324SRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
24918c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
24928c499324SRuchika Gupta 
2493bcac2127SMarouene Boubakri 	rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
2494bcac2127SMarouene Boubakri 	if (rc)
2495bcac2127SMarouene Boubakri 		return rc;
2496bcac2127SMarouene Boubakri 
2497bcac2127SMarouene Boubakri 	return set_check_value_attr(head);
24988c499324SRuchika Gupta }
24998c499324SRuchika Gupta 
set_private_key_data_rsa(struct obj_attrs ** head,void * data,size_t key_size)250045d40bdaSValerii Chubar static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
250145d40bdaSValerii Chubar 					       void *data,
250245d40bdaSValerii Chubar 					       size_t key_size)
250345d40bdaSValerii Chubar {
250445d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
250545d40bdaSValerii Chubar 	int mbedtls_rc = 0;
250645d40bdaSValerii Chubar 	uint32_t key_bits = 0;
250745d40bdaSValerii Chubar 	uint32_t size = 0;
250845d40bdaSValerii Chubar 	uint32_t buffer_size = 0;
250945d40bdaSValerii Chubar 	void *buffer = NULL;
251045d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
251145d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
251245d40bdaSValerii Chubar 	mbedtls_mpi n = { };
251345d40bdaSValerii Chubar 	mbedtls_mpi e = { };
251445d40bdaSValerii Chubar 	mbedtls_mpi d = { };
251545d40bdaSValerii Chubar 	mbedtls_mpi p = { };
251645d40bdaSValerii Chubar 	mbedtls_mpi q = { };
251745d40bdaSValerii Chubar 
251845d40bdaSValerii Chubar 	rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits);
251945d40bdaSValerii Chubar 	if (rc && rc != PKCS11_RV_NOT_FOUND)
252045d40bdaSValerii Chubar 		return rc;
252145d40bdaSValerii Chubar 
252245d40bdaSValerii Chubar 	if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) ||
252345d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) ||
252445d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) ||
252545d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_1) ||
252645d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_2))
252745d40bdaSValerii Chubar 		return PKCS11_CKR_GENERAL_ERROR;
252845d40bdaSValerii Chubar 
252945d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
253045d40bdaSValerii Chubar 	mbedtls_mpi_init(&n);
253145d40bdaSValerii Chubar 	mbedtls_mpi_init(&e);
253245d40bdaSValerii Chubar 	mbedtls_mpi_init(&d);
253345d40bdaSValerii Chubar 	mbedtls_mpi_init(&p);
253445d40bdaSValerii Chubar 	mbedtls_mpi_init(&q);
253545d40bdaSValerii Chubar 
253632b31808SJens Wiklander 	mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size,
253732b31808SJens Wiklander 					  NULL, 0, mbd_rand, NULL);
253845d40bdaSValerii Chubar 	if (mbedtls_rc) {
253945d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
254045d40bdaSValerii Chubar 		goto out;
254145d40bdaSValerii Chubar 	}
254245d40bdaSValerii Chubar 
254345d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
2544a2431e9fSClement Faure 	if (!rsa) {
2545a2431e9fSClement Faure 		rc = PKCS11_CKR_GENERAL_ERROR;
2546a2431e9fSClement Faure 		goto out;
2547a2431e9fSClement Faure 	}
2548a2431e9fSClement Faure 
254945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
255045d40bdaSValerii Chubar 	if (mbedtls_rc) {
255145d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
255245d40bdaSValerii Chubar 		goto out;
255345d40bdaSValerii Chubar 	}
255445d40bdaSValerii Chubar 
255545d40bdaSValerii Chubar 	if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) {
255645d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
255745d40bdaSValerii Chubar 		goto out;
255845d40bdaSValerii Chubar 	}
255945d40bdaSValerii Chubar 
256045d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8);
256145d40bdaSValerii Chubar 	buffer_size = size;
256245d40bdaSValerii Chubar 	buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
256345d40bdaSValerii Chubar 	if (!buffer) {
256445d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
256545d40bdaSValerii Chubar 		goto out;
256645d40bdaSValerii Chubar 	}
256745d40bdaSValerii Chubar 
256845d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size);
256945d40bdaSValerii Chubar 	if (mbedtls_rc) {
257045d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
257145d40bdaSValerii Chubar 		goto out;
257245d40bdaSValerii Chubar 	}
257345d40bdaSValerii Chubar 
257445d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size);
257545d40bdaSValerii Chubar 	if (rc)
257645d40bdaSValerii Chubar 		goto out;
257745d40bdaSValerii Chubar 
257845d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8);
257945d40bdaSValerii Chubar 	if (buffer_size < size) {
258045d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
258145d40bdaSValerii Chubar 		goto out;
258245d40bdaSValerii Chubar 	}
258345d40bdaSValerii Chubar 
258445d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size);
258545d40bdaSValerii Chubar 	if (mbedtls_rc) {
258645d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
258745d40bdaSValerii Chubar 		goto out;
258845d40bdaSValerii Chubar 	}
258945d40bdaSValerii Chubar 
259045d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size);
259145d40bdaSValerii Chubar 	if (rc)
259245d40bdaSValerii Chubar 		goto out;
259345d40bdaSValerii Chubar 
259445d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8);
259545d40bdaSValerii Chubar 	if (buffer_size < size) {
259645d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
259745d40bdaSValerii Chubar 		goto out;
259845d40bdaSValerii Chubar 	}
259945d40bdaSValerii Chubar 
260045d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size);
260145d40bdaSValerii Chubar 	if (mbedtls_rc) {
260245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
260345d40bdaSValerii Chubar 		goto out;
260445d40bdaSValerii Chubar 	}
260545d40bdaSValerii Chubar 
260645d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size);
260745d40bdaSValerii Chubar 	if (rc)
260845d40bdaSValerii Chubar 		goto out;
260945d40bdaSValerii Chubar 
261045d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8);
261145d40bdaSValerii Chubar 	if (buffer_size < size) {
261245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
261345d40bdaSValerii Chubar 		goto out;
261445d40bdaSValerii Chubar 	}
261545d40bdaSValerii Chubar 
261645d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size);
261745d40bdaSValerii Chubar 	if (mbedtls_rc) {
261845d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
261945d40bdaSValerii Chubar 		goto out;
262045d40bdaSValerii Chubar 	}
262145d40bdaSValerii Chubar 
262245d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size);
262345d40bdaSValerii Chubar 	if (rc)
262445d40bdaSValerii Chubar 		goto out;
262545d40bdaSValerii Chubar 
262645d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8);
262745d40bdaSValerii Chubar 	if (buffer_size < size) {
262845d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
262945d40bdaSValerii Chubar 		goto out;
263045d40bdaSValerii Chubar 	}
263145d40bdaSValerii Chubar 
263245d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size);
263345d40bdaSValerii Chubar 	if (mbedtls_rc) {
263445d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
263545d40bdaSValerii Chubar 		goto out;
263645d40bdaSValerii Chubar 	}
263745d40bdaSValerii Chubar 
263845d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size);
263945d40bdaSValerii Chubar 
264045d40bdaSValerii Chubar out:
264145d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
264245d40bdaSValerii Chubar 	mbedtls_mpi_free(&n);
264345d40bdaSValerii Chubar 	mbedtls_mpi_free(&e);
264445d40bdaSValerii Chubar 	mbedtls_mpi_free(&d);
264545d40bdaSValerii Chubar 	mbedtls_mpi_free(&p);
264645d40bdaSValerii Chubar 	mbedtls_mpi_free(&q);
264745d40bdaSValerii Chubar 	TEE_Free(buffer);
264845d40bdaSValerii Chubar 	return rc;
264945d40bdaSValerii Chubar }
265045d40bdaSValerii Chubar 
set_key_data(struct obj_attrs ** head,void * data,size_t key_size)26518c499324SRuchika Gupta enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data,
26528c499324SRuchika Gupta 			    size_t key_size)
26538c499324SRuchika Gupta {
26548c499324SRuchika Gupta 	switch (get_class(*head)) {
26558c499324SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
26568c499324SRuchika Gupta 		return set_secret_key_data(head, data, key_size);
265745d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
265845d40bdaSValerii Chubar 		if (get_key_type(*head) == PKCS11_CKK_RSA)
265945d40bdaSValerii Chubar 			return set_private_key_data_rsa(head, data, key_size);
266045d40bdaSValerii Chubar 		break;
26618c499324SRuchika Gupta 	default:
26628c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
26638c499324SRuchika Gupta 	}
266445d40bdaSValerii Chubar 
266545d40bdaSValerii Chubar 	return PKCS11_CKR_GENERAL_ERROR;
26668c499324SRuchika Gupta }
26675e1d94ebSVesa Jääskeläinen 
alloc_copy_attribute_value(struct obj_attrs * head,void ** data,uint32_t * sz)2668a9aa45d8SValerii Chubar static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
2669a9aa45d8SValerii Chubar 						 void **data, uint32_t *sz)
2670a9aa45d8SValerii Chubar {
2671a9aa45d8SValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2672a9aa45d8SValerii Chubar 	void *buffer = NULL;
2673a9aa45d8SValerii Chubar 	void *value = NULL;
2674a9aa45d8SValerii Chubar 
2675a9aa45d8SValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz);
2676a9aa45d8SValerii Chubar 	if (rc)
2677a9aa45d8SValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
2678a9aa45d8SValerii Chubar 
2679a9aa45d8SValerii Chubar 	buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
2680a9aa45d8SValerii Chubar 	if (!buffer)
2681a9aa45d8SValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
2682a9aa45d8SValerii Chubar 
2683a9aa45d8SValerii Chubar 	TEE_MemMove(buffer, value, *sz);
2684a9aa45d8SValerii Chubar 	*data = buffer;
2685a9aa45d8SValerii Chubar 
2686a9aa45d8SValerii Chubar 	return PKCS11_CKR_OK;
2687a9aa45d8SValerii Chubar }
2688a9aa45d8SValerii Chubar 
268945d40bdaSValerii Chubar static enum pkcs11_rc
encode_rsa_private_key_der(struct obj_attrs * head,void ** data,uint32_t * sz)269045d40bdaSValerii Chubar encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
269145d40bdaSValerii Chubar {
269245d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
269345d40bdaSValerii Chubar 	int i = 0;
269445d40bdaSValerii Chubar 	int mbedtls_rc = 0;
269545d40bdaSValerii Chubar 	int start = 0;
269645d40bdaSValerii Chubar 	int der_size = 0;
269745d40bdaSValerii Chubar 	void *n = NULL;
269845d40bdaSValerii Chubar 	void *p = NULL;
269945d40bdaSValerii Chubar 	void *q = NULL;
270045d40bdaSValerii Chubar 	void *d = NULL;
270145d40bdaSValerii Chubar 	void *e = NULL;
270245d40bdaSValerii Chubar 	uint32_t n_len = 0;
270345d40bdaSValerii Chubar 	uint32_t p_len = 0;
270445d40bdaSValerii Chubar 	uint32_t q_len = 0;
270545d40bdaSValerii Chubar 	uint32_t d_len = 0;
270645d40bdaSValerii Chubar 	uint32_t e_len = 0;
270745d40bdaSValerii Chubar 	uint8_t *buffer = NULL;
270845d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
270945d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
271045d40bdaSValerii Chubar 	const mbedtls_pk_info_t *pk_info = NULL;
271145d40bdaSValerii Chubar 
271245d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
271345d40bdaSValerii Chubar 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
271445d40bdaSValerii Chubar 	if (mbedtls_pk_setup(&pk, pk_info)) {
271545d40bdaSValerii Chubar 		rc = PKCS11_CKR_GENERAL_ERROR;
271645d40bdaSValerii Chubar 		goto out;
271745d40bdaSValerii Chubar 	}
271845d40bdaSValerii Chubar 
271945d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len);
272045d40bdaSValerii Chubar 	if (rc)
272145d40bdaSValerii Chubar 		goto out;
272245d40bdaSValerii Chubar 
272345d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len);
272445d40bdaSValerii Chubar 	if (rc)
272545d40bdaSValerii Chubar 		goto out;
272645d40bdaSValerii Chubar 
272745d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len);
272845d40bdaSValerii Chubar 	if (rc)
272945d40bdaSValerii Chubar 		goto out;
273045d40bdaSValerii Chubar 
273145d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len);
273245d40bdaSValerii Chubar 	if (rc)
273345d40bdaSValerii Chubar 		goto out;
273445d40bdaSValerii Chubar 
273545d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len);
273645d40bdaSValerii Chubar 	if (rc)
273745d40bdaSValerii Chubar 		goto out;
273845d40bdaSValerii Chubar 
273945d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
2740a2431e9fSClement Faure 	if (!rsa) {
2741a2431e9fSClement Faure 		rc = PKCS11_CKR_GENERAL_ERROR;
2742a2431e9fSClement Faure 		goto out;
2743a2431e9fSClement Faure 	}
2744a2431e9fSClement Faure 
274545d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
274645d40bdaSValerii Chubar 					    q, q_len, d, d_len, e, e_len);
274745d40bdaSValerii Chubar 	if (mbedtls_rc) {
274845d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
274945d40bdaSValerii Chubar 		goto out;
275045d40bdaSValerii Chubar 	}
275145d40bdaSValerii Chubar 
275245d40bdaSValerii Chubar 	if (mbedtls_rsa_complete(rsa)) {
275345d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
275445d40bdaSValerii Chubar 		goto out;
275545d40bdaSValerii Chubar 	}
275645d40bdaSValerii Chubar 
275745d40bdaSValerii Chubar 	if (mbedtls_rsa_check_privkey(rsa)) {
275845d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
275945d40bdaSValerii Chubar 		goto out;
276045d40bdaSValerii Chubar 	}
276145d40bdaSValerii Chubar 
276245d40bdaSValerii Chubar 	der_size = n_len * 8;
276345d40bdaSValerii Chubar 	buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
276445d40bdaSValerii Chubar 	if (!buffer) {
276545d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
276645d40bdaSValerii Chubar 		goto out;
276745d40bdaSValerii Chubar 	}
276845d40bdaSValerii Chubar 
276945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size);
277045d40bdaSValerii Chubar 	if (mbedtls_rc < 0) {
277145d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
277245d40bdaSValerii Chubar 		goto out;
277345d40bdaSValerii Chubar 	}
277445d40bdaSValerii Chubar 
277545d40bdaSValerii Chubar 	start = der_size - mbedtls_rc;
277645d40bdaSValerii Chubar 	for (i = 0; i < mbedtls_rc; i++) {
277745d40bdaSValerii Chubar 		buffer[i] = buffer[i + start];
277845d40bdaSValerii Chubar 		buffer[i + start] = 0;
277945d40bdaSValerii Chubar 	}
278045d40bdaSValerii Chubar 
278145d40bdaSValerii Chubar 	*data = buffer;
278245d40bdaSValerii Chubar 	*sz = mbedtls_rc;
278345d40bdaSValerii Chubar out:
278445d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
278545d40bdaSValerii Chubar 
278645d40bdaSValerii Chubar 	if (rc)
278745d40bdaSValerii Chubar 		TEE_Free(buffer);
278845d40bdaSValerii Chubar 
278945d40bdaSValerii Chubar 	return rc;
279045d40bdaSValerii Chubar }
279145d40bdaSValerii Chubar 
alloc_key_data_to_wrap(struct obj_attrs * head,void ** data,uint32_t * sz)2792a9aa45d8SValerii Chubar enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
27935f80f270SRuchika Gupta 				      uint32_t *sz)
27945f80f270SRuchika Gupta {
279545d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
279645d40bdaSValerii Chubar 
27975f80f270SRuchika Gupta 	switch (get_class(head)) {
27985f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
279945d40bdaSValerii Chubar 		rc = alloc_copy_attribute_value(head, data, sz);
280045d40bdaSValerii Chubar 		break;
280145d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
280245d40bdaSValerii Chubar 		if (get_key_type(head) == PKCS11_CKK_RSA)
280345d40bdaSValerii Chubar 			rc = encode_rsa_private_key_der(head, data, sz);
280445d40bdaSValerii Chubar 		break;
28055f80f270SRuchika Gupta 	default:
280645d40bdaSValerii Chubar 		break;
28075f80f270SRuchika Gupta 	}
28085f80f270SRuchika Gupta 
280945d40bdaSValerii Chubar 	return rc;
28105f80f270SRuchika Gupta }
28115f80f270SRuchika Gupta 
add_missing_attribute_id(struct obj_attrs ** pub_head,struct obj_attrs ** priv_head)28125e1d94ebSVesa Jääskeläinen enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
28135e1d94ebSVesa Jääskeläinen 					struct obj_attrs **priv_head)
28145e1d94ebSVesa Jääskeläinen {
28155e1d94ebSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
28165e1d94ebSVesa Jääskeläinen 	void *id1 = NULL;
28175e1d94ebSVesa Jääskeläinen 	uint32_t id1_size = 0;
28185e1d94ebSVesa Jääskeläinen 	void *id2 = NULL;
28195e1d94ebSVesa Jääskeläinen 	uint32_t id2_size = 0;
28205e1d94ebSVesa Jääskeläinen 
28215e1d94ebSVesa Jääskeläinen 	assert(pub_head);
28225e1d94ebSVesa Jääskeläinen 	assert(priv_head);
28235e1d94ebSVesa Jääskeläinen 
28245e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size);
28255e1d94ebSVesa Jääskeläinen 	if (rc) {
28265e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28275e1d94ebSVesa Jääskeläinen 			return rc;
28285e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28295e1d94ebSVesa Jääskeläinen 	} else if (!id1_size) {
28305e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28315e1d94ebSVesa Jääskeläinen 	}
28325e1d94ebSVesa Jääskeläinen 
28335e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size);
28345e1d94ebSVesa Jääskeläinen 	if (rc) {
28355e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28365e1d94ebSVesa Jääskeläinen 			return rc;
28375e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28385e1d94ebSVesa Jääskeläinen 	} else if (!id2_size) {
28395e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28405e1d94ebSVesa Jääskeläinen 	}
28415e1d94ebSVesa Jääskeläinen 
28425e1d94ebSVesa Jääskeläinen 	/* Both have value -- let them be what caller has specified them */
28435e1d94ebSVesa Jääskeläinen 	if (id1 && id2)
28445e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28455e1d94ebSVesa Jääskeläinen 
28465e1d94ebSVesa Jääskeläinen 	/* Both are empty -- leave empty values */
28475e1d94ebSVesa Jääskeläinen 	if (!id1 && !id2)
28485e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28495e1d94ebSVesa Jääskeläinen 
28505e1d94ebSVesa Jääskeläinen 	/* Cross copy CKA_ID value */
28515e1d94ebSVesa Jääskeläinen 	if (id1)
28525e1d94ebSVesa Jääskeläinen 		return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size);
28535e1d94ebSVesa Jääskeläinen 	else
28545e1d94ebSVesa Jääskeläinen 		return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size);
28555e1d94ebSVesa Jääskeläinen }
2856bcac2127SMarouene Boubakri 
2857bcac2127SMarouene Boubakri /*
2858bcac2127SMarouene Boubakri  * The key check value is derived from the object by taking the first
2859bcac2127SMarouene Boubakri  * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute.
2860bcac2127SMarouene Boubakri  */
compute_check_value_with_sha1(void * key,uint32_t key_size,void * kcv)2861bcac2127SMarouene Boubakri static enum pkcs11_rc compute_check_value_with_sha1(void *key,
2862bcac2127SMarouene Boubakri 						    uint32_t key_size,
2863bcac2127SMarouene Boubakri 						    void *kcv)
2864bcac2127SMarouene Boubakri {
2865bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2866bcac2127SMarouene Boubakri 	TEE_Result res = TEE_ERROR_GENERIC;
2867bcac2127SMarouene Boubakri 	TEE_OperationHandle op = TEE_HANDLE_NULL;
2868bcac2127SMarouene Boubakri 	size_t buf_size = TEE_MAX_HASH_SIZE;
2869bcac2127SMarouene Boubakri 	uint8_t *buf = NULL;
2870bcac2127SMarouene Boubakri 
2871bcac2127SMarouene Boubakri 	assert(key && kcv);
2872bcac2127SMarouene Boubakri 
2873bcac2127SMarouene Boubakri 	res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0);
2874bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2875bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2876bcac2127SMarouene Boubakri 		goto out;
2877bcac2127SMarouene Boubakri 
2878bcac2127SMarouene Boubakri 	buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO);
2879bcac2127SMarouene Boubakri 	if (!buf) {
2880bcac2127SMarouene Boubakri 		rc = PKCS11_CKR_DEVICE_MEMORY;
2881bcac2127SMarouene Boubakri 		goto out;
2882bcac2127SMarouene Boubakri 	}
2883bcac2127SMarouene Boubakri 
2884bcac2127SMarouene Boubakri 	res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size);
2885bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2886bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2887bcac2127SMarouene Boubakri 		goto out;
2888bcac2127SMarouene Boubakri 
2889bcac2127SMarouene Boubakri 	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
2890bcac2127SMarouene Boubakri 
2891bcac2127SMarouene Boubakri out:
2892bcac2127SMarouene Boubakri 	TEE_Free(buf);
2893bcac2127SMarouene Boubakri 	TEE_FreeOperation(op);
2894bcac2127SMarouene Boubakri 
2895bcac2127SMarouene Boubakri 	return rc;
2896bcac2127SMarouene Boubakri }
2897bcac2127SMarouene Boubakri 
2898bcac2127SMarouene Boubakri /*
2899bcac2127SMarouene Boubakri  * The key check value that is calculated as follows:
2900bcac2127SMarouene Boubakri  * 1) Take a buffer of the cipher block size of binary zeros (0x00).
2901bcac2127SMarouene Boubakri  * 2) Encrypt this block in ECB mode.
2902bcac2127SMarouene Boubakri  * 3) Take the first three bytes of cipher text as the check value.
2903bcac2127SMarouene Boubakri  */
compute_check_value_with_ecb(void * key,uint32_t key_size,void * kcv)2904bcac2127SMarouene Boubakri static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size,
2905bcac2127SMarouene Boubakri 						   void *kcv)
2906bcac2127SMarouene Boubakri {
2907bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2908bcac2127SMarouene Boubakri 	TEE_Result res = TEE_ERROR_GENERIC;
2909bcac2127SMarouene Boubakri 	TEE_OperationHandle op = TEE_HANDLE_NULL;
2910bcac2127SMarouene Boubakri 	TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
2911bcac2127SMarouene Boubakri 	TEE_Attribute attr = { };
2912adfad2cdSEtienne Carriere 	uint8_t buf[TEE_AES_BLOCK_SIZE] = { };
2913adfad2cdSEtienne Carriere 	size_t buf_size = sizeof(buf);
2914bcac2127SMarouene Boubakri 
2915bcac2127SMarouene Boubakri 	assert(key && kcv);
2916bcac2127SMarouene Boubakri 
2917bcac2127SMarouene Boubakri 	res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD,
2918bcac2127SMarouene Boubakri 				    TEE_MODE_ENCRYPT, key_size * 8);
2919bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2920bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2921bcac2127SMarouene Boubakri 		goto out;
2922bcac2127SMarouene Boubakri 
2923bcac2127SMarouene Boubakri 	res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey);
2924bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2925bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2926bcac2127SMarouene Boubakri 		goto out;
2927bcac2127SMarouene Boubakri 
29283bc92b91SEtienne Carriere 	TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size);
2929bcac2127SMarouene Boubakri 
2930bcac2127SMarouene Boubakri 	res = TEE_PopulateTransientObject(hkey, &attr, 1);
2931bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2932bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2933bcac2127SMarouene Boubakri 		goto out;
2934bcac2127SMarouene Boubakri 
2935bcac2127SMarouene Boubakri 	res = TEE_SetOperationKey(op, hkey);
2936bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2937bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2938bcac2127SMarouene Boubakri 		goto out;
2939bcac2127SMarouene Boubakri 
2940bcac2127SMarouene Boubakri 	TEE_CipherInit(op, NULL, 0);
2941bcac2127SMarouene Boubakri 
2942bcac2127SMarouene Boubakri 	res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size);
2943bcac2127SMarouene Boubakri 	rc = tee2pkcs_error(res);
2944bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK)
2945bcac2127SMarouene Boubakri 		goto out;
2946bcac2127SMarouene Boubakri 
2947bcac2127SMarouene Boubakri 	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
2948bcac2127SMarouene Boubakri 
2949bcac2127SMarouene Boubakri out:
2950bcac2127SMarouene Boubakri 	TEE_FreeTransientObject(hkey);
2951bcac2127SMarouene Boubakri 	TEE_FreeOperation(op);
2952bcac2127SMarouene Boubakri 
2953bcac2127SMarouene Boubakri 	return rc;
2954bcac2127SMarouene Boubakri }
2955bcac2127SMarouene Boubakri 
set_check_value_attr(struct obj_attrs ** head)2956bcac2127SMarouene Boubakri enum pkcs11_rc set_check_value_attr(struct obj_attrs **head)
2957bcac2127SMarouene Boubakri {
2958bcac2127SMarouene Boubakri 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2959bcac2127SMarouene Boubakri 	uint32_t val_len = 0;
2960bcac2127SMarouene Boubakri 	uint32_t kcv2_len = 0;
2961bcac2127SMarouene Boubakri 	void *val = NULL;
2962bcac2127SMarouene Boubakri 	uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { };
2963bcac2127SMarouene Boubakri 	void *kcv2 = NULL;
2964bcac2127SMarouene Boubakri 
2965bcac2127SMarouene Boubakri 	assert(head && *head);
2966bcac2127SMarouene Boubakri 
2967bcac2127SMarouene Boubakri 	if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE))
2968bcac2127SMarouene Boubakri 		return PKCS11_CKR_OK;
2969bcac2127SMarouene Boubakri 
2970bcac2127SMarouene Boubakri 	switch (get_class(*head)) {
2971bcac2127SMarouene Boubakri 	case PKCS11_CKO_SECRET_KEY:
2972bcac2127SMarouene Boubakri 	case PKCS11_CKO_CERTIFICATE:
2973bcac2127SMarouene Boubakri 		break;
2974bcac2127SMarouene Boubakri 	default:
2975cfbe7874SEtienne Carriere 		/* Nothing to do */
2976cfbe7874SEtienne Carriere 		return PKCS11_CKR_OK;
2977bcac2127SMarouene Boubakri 	}
2978bcac2127SMarouene Boubakri 
2979bcac2127SMarouene Boubakri 	/* Check whether CKA_CHECK_VALUE has been provided in the template */
2980bcac2127SMarouene Boubakri 	rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len);
2981bcac2127SMarouene Boubakri 
2982bcac2127SMarouene Boubakri 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
2983bcac2127SMarouene Boubakri 		return PKCS11_CKR_GENERAL_ERROR;
2984bcac2127SMarouene Boubakri 
2985bcac2127SMarouene Boubakri 	/*
2986bcac2127SMarouene Boubakri 	 * The generation of the KCV may be prevented by the application
2987bcac2127SMarouene Boubakri 	 * supplying the attribute in the template as a no-value (0 length)
2988bcac2127SMarouene Boubakri 	 * entry.
2989bcac2127SMarouene Boubakri 	 */
2990bcac2127SMarouene Boubakri 	if (rc == PKCS11_CKR_OK && !kcv2_len)
2991bcac2127SMarouene Boubakri 		return PKCS11_CKR_OK;
2992bcac2127SMarouene Boubakri 
2993bcac2127SMarouene Boubakri 	if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE)
29942ea9746dSEtienne Carriere 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
2995bcac2127SMarouene Boubakri 
2996bcac2127SMarouene Boubakri 	/* Get key CKA_VALUE */
2997bcac2127SMarouene Boubakri 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len);
2998bcac2127SMarouene Boubakri 	if (rc)
2999bcac2127SMarouene Boubakri 		return rc;
3000bcac2127SMarouene Boubakri 
3001bcac2127SMarouene Boubakri 	if (get_class(*head) == PKCS11_CKO_SECRET_KEY) {
3002bcac2127SMarouene Boubakri 		switch (get_key_type(*head)) {
3003bcac2127SMarouene Boubakri 		case PKCS11_CKK_AES:
3004bcac2127SMarouene Boubakri 			rc = compute_check_value_with_ecb(val, val_len, kcv);
3005bcac2127SMarouene Boubakri 			break;
3006bcac2127SMarouene Boubakri 		case PKCS11_CKK_GENERIC_SECRET:
3007bcac2127SMarouene Boubakri 		case PKCS11_CKK_MD5_HMAC:
3008bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA_1_HMAC:
3009bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA256_HMAC:
3010bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA384_HMAC:
3011bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA512_HMAC:
3012bcac2127SMarouene Boubakri 		case PKCS11_CKK_SHA224_HMAC:
3013bcac2127SMarouene Boubakri 			rc = compute_check_value_with_sha1(val, val_len, kcv);
3014bcac2127SMarouene Boubakri 			break;
3015bcac2127SMarouene Boubakri 		default:
3016bcac2127SMarouene Boubakri 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
3017bcac2127SMarouene Boubakri 			break;
3018bcac2127SMarouene Boubakri 		}
3019bcac2127SMarouene Boubakri 	} else {
3020bcac2127SMarouene Boubakri 		rc = compute_check_value_with_sha1(val, val_len, kcv);
3021bcac2127SMarouene Boubakri 	}
3022bcac2127SMarouene Boubakri 
3023bcac2127SMarouene Boubakri 	if (rc)
3024bcac2127SMarouene Boubakri 		return rc;
3025bcac2127SMarouene Boubakri 
3026bcac2127SMarouene Boubakri 	/*
3027bcac2127SMarouene Boubakri 	 * If the computed KCV does not match the provided one
3028bcac2127SMarouene Boubakri 	 * then return CKR_ATTRIBUTE_VALUE_INVALID
3029bcac2127SMarouene Boubakri 	 */
3030bcac2127SMarouene Boubakri 	if (kcv2_len) {
3031bcac2127SMarouene Boubakri 		/* Provided KCV value shall match the computed one */
3032bcac2127SMarouene Boubakri 		if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE))
3033bcac2127SMarouene Boubakri 			rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
3034bcac2127SMarouene Boubakri 	} else {
3035bcac2127SMarouene Boubakri 		rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv,
3036bcac2127SMarouene Boubakri 				   PKCS11_CKA_CHECK_VALUE_SIZE);
3037bcac2127SMarouene Boubakri 	}
3038bcac2127SMarouene Boubakri 
3039bcac2127SMarouene Boubakri 	return rc;
3040bcac2127SMarouene Boubakri }
3041