xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
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>
763f89caaSJens Wiklander #include <inttypes.h>
87c243321SVesa Jääskeläinen #include <mbedtls/asn1write.h>
97c243321SVesa Jääskeläinen #include <mbedtls/ecp.h>
1045d40bdaSValerii Chubar #include <mbedtls/pk.h>
1163f89caaSJens Wiklander #include <pkcs11_ta.h>
1263f89caaSJens Wiklander #include <stdlib.h>
1363f89caaSJens Wiklander #include <string_ext.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 
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
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  */
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  */
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 
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 
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 
26163f89caaSJens Wiklander static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value,
26263f89caaSJens Wiklander 					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 
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 
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 
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[] = {
3584137952dSVesa Jääskeläinen 	PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_CHECK_VALUE,
3594137952dSVesa Jääskeläinen 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO,
3604137952dSVesa Jääskeläinen };
3614137952dSVesa Jääskeläinen 
3624137952dSVesa Jääskeläinen /*
3634137952dSVesa Jääskeläinen  * PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx)
3644137952dSVesa Jääskeläinen  */
3654137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_mandated[] = {
3664137952dSVesa Jääskeläinen 	PKCS11_CKA_SUBJECT,
3674137952dSVesa Jääskeläinen };
3684137952dSVesa Jääskeläinen 
3694137952dSVesa Jääskeläinen static const uint32_t pkcs11_x509_certificate_optional[] = {
3704137952dSVesa Jääskeläinen 	PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER,
3714137952dSVesa Jääskeläinen 	PKCS11_CKA_VALUE, PKCS11_CKA_URL,
3724137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
3734137952dSVesa Jääskeläinen 	PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
3744137952dSVesa Jääskeläinen 	PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM,
3754137952dSVesa Jääskeläinen };
3764137952dSVesa Jääskeläinen 
3774eb88651SRuchika Gupta /* PKCS#11 specification for any key object (+any_object_xxx) */
3784eb88651SRuchika Gupta static const uint32_t any_key_boolprops[] = {
37963f89caaSJens Wiklander 	PKCS11_CKA_DERIVE,
38063f89caaSJens Wiklander };
38163f89caaSJens Wiklander 
3824eb88651SRuchika Gupta static const uint32_t any_key_opt_or_null[] = {
38363f89caaSJens Wiklander 	PKCS11_CKA_ID,
38463f89caaSJens Wiklander 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE,
3854eb88651SRuchika Gupta };
3864eb88651SRuchika Gupta 
3874eb88651SRuchika Gupta static const uint32_t any_key_optional[] = {
38863f89caaSJens Wiklander 	PKCS11_CKA_ALLOWED_MECHANISMS,
38963f89caaSJens Wiklander };
39063f89caaSJens Wiklander 
3914eb88651SRuchika Gupta /* PKCS#11 specification for any symmetric key (+any_key_xxx) */
3924eb88651SRuchika Gupta static const uint32_t symm_key_boolprops[] = {
39363f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT,
39463f89caaSJens Wiklander 	PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY,
39563f89caaSJens Wiklander 	PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP,
39663f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
39763f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED,
39863f89caaSJens Wiklander };
39963f89caaSJens Wiklander 
4004eb88651SRuchika Gupta static const uint32_t symm_key_opt_or_null[] = {
40163f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE,
4020ac5c695SRuchika Gupta 	PKCS11_CKA_DERIVE_TEMPLATE, PKCS11_CKA_VALUE,
4030ac5c695SRuchika Gupta };
4040ac5c695SRuchika Gupta 
4050ac5c695SRuchika Gupta static const uint32_t symm_key_optional[] = {
4060ac5c695SRuchika Gupta 	PKCS11_CKA_VALUE_LEN,
40763f89caaSJens Wiklander };
40863f89caaSJens Wiklander 
4094eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
4104eb88651SRuchika Gupta static const uint32_t public_key_boolprops[] = {
41163f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER,
41263f89caaSJens Wiklander 	PKCS11_CKA_WRAP,
41363f89caaSJens Wiklander 	PKCS11_CKA_TRUSTED,
41463f89caaSJens Wiklander };
41563f89caaSJens Wiklander 
4164eb88651SRuchika Gupta static const uint32_t public_key_mandated[] = {
41763f89caaSJens Wiklander };
41863f89caaSJens Wiklander 
4194eb88651SRuchika Gupta static const uint32_t public_key_opt_or_null[] = {
420edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_WRAP_TEMPLATE,
421edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
42263f89caaSJens Wiklander };
42363f89caaSJens Wiklander 
4244eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */
4254eb88651SRuchika Gupta static const uint32_t private_key_boolprops[] = {
42663f89caaSJens Wiklander 	PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER,
42763f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP,
42863f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
42963f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE,
43063f89caaSJens Wiklander };
43163f89caaSJens Wiklander 
4324eb88651SRuchika Gupta static const uint32_t private_key_mandated[] = {
43363f89caaSJens Wiklander };
43463f89caaSJens Wiklander 
4354eb88651SRuchika Gupta static const uint32_t private_key_opt_or_null[] = {
436edd95148SVesa Jääskeläinen 	PKCS11_CKA_SUBJECT, PKCS11_CKA_UNWRAP_TEMPLATE,
437edd95148SVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_KEY_INFO,
43863f89caaSJens Wiklander };
43963f89caaSJens Wiklander 
4404eb88651SRuchika Gupta /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */
4419cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_mand[] = {
44263f89caaSJens Wiklander 	PKCS11_CKA_MODULUS_BITS,
44363f89caaSJens Wiklander };
44463f89caaSJens Wiklander 
4459cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_create_mand[] = {
44663f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
44763f89caaSJens Wiklander };
44863f89caaSJens Wiklander 
4499cf1afceSVesa Jääskeläinen static const uint32_t rsa_pub_key_gen_opt_or_null[] = {
4509cf1afceSVesa Jääskeläinen 	PKCS11_CKA_PUBLIC_EXPONENT,
4519cf1afceSVesa Jääskeläinen };
4529cf1afceSVesa Jääskeläinen 
4539cf1afceSVesa Jääskeläinen static const uint32_t rsa_priv_key_opt_or_null[] = {
45463f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
45563f89caaSJens Wiklander 	PKCS11_CKA_PRIVATE_EXPONENT,
45663f89caaSJens Wiklander 	PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2,
45763f89caaSJens Wiklander 	PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT,
45863f89caaSJens Wiklander };
45963f89caaSJens Wiklander 
4604eb88651SRuchika Gupta /* PKCS#11 specification for any EC key (+public/private_key_xxx) */
4614eb88651SRuchika Gupta static const uint32_t ec_public_key_mandated[] = {
46263f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
46363f89caaSJens Wiklander };
46463f89caaSJens Wiklander 
4654eb88651SRuchika Gupta static const uint32_t ec_public_key_opt_or_null[] = {
46663f89caaSJens Wiklander 	PKCS11_CKA_EC_POINT,
46763f89caaSJens Wiklander };
46863f89caaSJens Wiklander 
4694eb88651SRuchika Gupta static const uint32_t ec_private_key_mandated[] = {
47063f89caaSJens Wiklander };
47163f89caaSJens Wiklander 
4724eb88651SRuchika Gupta static const uint32_t ec_private_key_opt_or_null[] = {
47302b16804SVesa Jääskeläinen 	PKCS11_CKA_EC_PARAMS,
47463f89caaSJens Wiklander 	PKCS11_CKA_VALUE,
47563f89caaSJens Wiklander };
47663f89caaSJens Wiklander 
47703e07432SValerii Chubar static const uint32_t eddsa_private_key_opt_or_null[] = {
47803e07432SValerii Chubar 	PKCS11_CKA_EC_PARAMS,
47903e07432SValerii Chubar 	PKCS11_CKA_VALUE,
48003e07432SValerii Chubar 	PKCS11_CKA_EC_POINT,
48103e07432SValerii Chubar };
48203e07432SValerii Chubar 
48363f89caaSJens Wiklander static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out,
48463f89caaSJens Wiklander 						struct obj_attrs *temp)
48563f89caaSJens Wiklander {
48663f89caaSJens Wiklander 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
48763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
48863f89caaSJens Wiklander 
48963f89caaSJens Wiklander 	rc = init_attributes_head(out);
49063f89caaSJens Wiklander 	if (rc)
49163f89caaSJens Wiklander 		return rc;
49263f89caaSJens Wiklander 
49363f89caaSJens Wiklander 	/* Object class is mandatory */
49463f89caaSJens Wiklander 	class = get_class(temp);
49563f89caaSJens Wiklander 	if (class == PKCS11_CKO_UNDEFINED_ID) {
49663f89caaSJens Wiklander 		EMSG("Class attribute not found");
49763f89caaSJens Wiklander 
49863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
49963f89caaSJens Wiklander 	}
50063f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t));
50163f89caaSJens Wiklander 	if (rc)
50263f89caaSJens Wiklander 		return rc;
50363f89caaSJens Wiklander 
5044eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_object_boolprops,
5054eb88651SRuchika Gupta 				     ARRAY_SIZE(any_object_boolprops));
50663f89caaSJens Wiklander 	if (rc)
50763f89caaSJens Wiklander 		return rc;
50863f89caaSJens Wiklander 
5094eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, any_object_opt_or_null,
5104eb88651SRuchika Gupta 					  ARRAY_SIZE(any_object_opt_or_null));
51163f89caaSJens Wiklander }
51263f89caaSJens Wiklander 
51363f89caaSJens Wiklander static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out,
51463f89caaSJens Wiklander 					       struct obj_attrs *temp)
51563f89caaSJens Wiklander {
51663f89caaSJens Wiklander 	uint32_t type = PKCS11_CKO_UNDEFINED_ID;
51763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
51863f89caaSJens Wiklander 
51963f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
52063f89caaSJens Wiklander 	if (rc)
52163f89caaSJens Wiklander 		return rc;
52263f89caaSJens Wiklander 
52363f89caaSJens Wiklander 	type = get_key_type(temp);
52463f89caaSJens Wiklander 	if (type == PKCS11_CKK_UNDEFINED_ID) {
52563f89caaSJens Wiklander 		EMSG("Key type attribute not found");
52663f89caaSJens Wiklander 
52763f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
52863f89caaSJens Wiklander 	}
52963f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t));
53063f89caaSJens Wiklander 	if (rc)
53163f89caaSJens Wiklander 		return rc;
53263f89caaSJens Wiklander 
5334eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_key_boolprops,
5344eb88651SRuchika Gupta 				     ARRAY_SIZE(any_key_boolprops));
53563f89caaSJens Wiklander 	if (rc)
53663f89caaSJens Wiklander 		return rc;
53763f89caaSJens Wiklander 
5384eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null,
5394eb88651SRuchika Gupta 					ARRAY_SIZE(any_key_opt_or_null));
5404eb88651SRuchika Gupta 	if (rc)
5414eb88651SRuchika Gupta 		return rc;
5424eb88651SRuchika Gupta 
5434eb88651SRuchika Gupta 	return set_optional_attributes(out, temp, any_key_optional,
5444eb88651SRuchika Gupta 				       ARRAY_SIZE(any_key_optional));
5454eb88651SRuchika Gupta 
54663f89caaSJens Wiklander }
54763f89caaSJens Wiklander 
54863f89caaSJens Wiklander static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out,
54963f89caaSJens Wiklander 						 struct obj_attrs *temp)
55063f89caaSJens Wiklander {
55163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
55263f89caaSJens Wiklander 
55363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_SECRET_KEY);
55463f89caaSJens Wiklander 
55563f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
55663f89caaSJens Wiklander 	if (rc)
55763f89caaSJens Wiklander 		return rc;
55863f89caaSJens Wiklander 
55963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_SECRET_KEY);
56063f89caaSJens Wiklander 
56163f89caaSJens Wiklander 	switch (get_key_type(*out)) {
56263f89caaSJens Wiklander 	case PKCS11_CKK_GENERIC_SECRET:
56363f89caaSJens Wiklander 	case PKCS11_CKK_AES:
56463f89caaSJens Wiklander 	case PKCS11_CKK_MD5_HMAC:
56563f89caaSJens Wiklander 	case PKCS11_CKK_SHA_1_HMAC:
56663f89caaSJens Wiklander 	case PKCS11_CKK_SHA256_HMAC:
56763f89caaSJens Wiklander 	case PKCS11_CKK_SHA384_HMAC:
56863f89caaSJens Wiklander 	case PKCS11_CKK_SHA512_HMAC:
56963f89caaSJens Wiklander 	case PKCS11_CKK_SHA224_HMAC:
57063f89caaSJens Wiklander 		break;
57163f89caaSJens Wiklander 	default:
57263f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
57363f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
57463f89caaSJens Wiklander 
57563f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
57663f89caaSJens Wiklander 	}
57763f89caaSJens Wiklander 
5784eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, symm_key_boolprops,
5794eb88651SRuchika Gupta 				     ARRAY_SIZE(symm_key_boolprops));
58063f89caaSJens Wiklander 	if (rc)
58163f89caaSJens Wiklander 		return rc;
58263f89caaSJens Wiklander 
5830ac5c695SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, symm_key_opt_or_null,
5844eb88651SRuchika Gupta 					ARRAY_SIZE(symm_key_opt_or_null));
5850ac5c695SRuchika Gupta 	if (rc)
5860ac5c695SRuchika Gupta 		return rc;
5870ac5c695SRuchika Gupta 
5880ac5c695SRuchika Gupta 	return set_optional_attributes(out, temp, symm_key_optional,
5890ac5c695SRuchika Gupta 				       ARRAY_SIZE(symm_key_optional));
59063f89caaSJens Wiklander }
59163f89caaSJens Wiklander 
59263f89caaSJens Wiklander static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
59363f89caaSJens Wiklander 					     struct obj_attrs *temp)
59463f89caaSJens Wiklander {
59563f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
59663f89caaSJens Wiklander 
59763f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_DATA);
59863f89caaSJens Wiklander 
59963f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
60063f89caaSJens Wiklander 	if (rc)
60163f89caaSJens Wiklander 		return rc;
60263f89caaSJens Wiklander 
60363f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_DATA);
60463f89caaSJens Wiklander 
6054eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null,
6064eb88651SRuchika Gupta 					  ARRAY_SIZE(raw_data_opt_or_null));
60763f89caaSJens Wiklander }
60863f89caaSJens Wiklander 
6094137952dSVesa Jääskeläinen static enum pkcs11_rc create_certificate_attributes(struct obj_attrs **out,
6104137952dSVesa Jääskeläinen 						    struct obj_attrs *temp)
6114137952dSVesa Jääskeläinen {
6124137952dSVesa Jääskeläinen 	uint32_t const *mandated = NULL;
6134137952dSVesa Jääskeläinen 	uint32_t const *optional = NULL;
6144137952dSVesa Jääskeläinen 	size_t mandated_count = 0;
6154137952dSVesa Jääskeläinen 	size_t optional_count = 0;
6164137952dSVesa Jääskeläinen 	void *attr_value = NULL;
6174137952dSVesa Jääskeläinen 	uint32_t attr_size = 0;
6184137952dSVesa Jääskeläinen 	uint32_t default_cert_category =
6194137952dSVesa Jääskeläinen 		PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED;
6204137952dSVesa Jääskeläinen 	uint32_t default_name_hash_alg = PKCS11_CKM_SHA_1;
6214137952dSVesa Jääskeläinen 	uint32_t cert_category = 0;
6224137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
6234137952dSVesa Jääskeläinen 
6244137952dSVesa Jääskeläinen 	assert(get_class(temp) == PKCS11_CKO_CERTIFICATE);
6254137952dSVesa Jääskeläinen 
6264137952dSVesa Jääskeläinen 	rc = create_storage_attributes(out, temp);
6274137952dSVesa Jääskeläinen 	if (rc)
6284137952dSVesa Jääskeläinen 		return rc;
6294137952dSVesa Jääskeläinen 
6304137952dSVesa Jääskeläinen 	assert(get_class(*out) == PKCS11_CKO_CERTIFICATE);
6314137952dSVesa Jääskeläinen 
6324137952dSVesa Jääskeläinen 	rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops,
6334137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_boolprops));
6344137952dSVesa Jääskeläinen 	if (rc)
6354137952dSVesa Jääskeläinen 		return rc;
6364137952dSVesa Jääskeläinen 
6374137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated,
6384137952dSVesa Jääskeläinen 				      ARRAY_SIZE(pkcs11_certificate_mandated));
6394137952dSVesa Jääskeläinen 	if (rc)
6404137952dSVesa Jääskeläinen 		return rc;
6414137952dSVesa Jääskeläinen 
6424137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, pkcs11_certificate_optional,
6434137952dSVesa Jääskeläinen 				     ARRAY_SIZE(pkcs11_certificate_optional));
6444137952dSVesa Jääskeläinen 	if (rc)
6454137952dSVesa Jääskeläinen 		return rc;
6464137952dSVesa Jääskeläinen 
6474137952dSVesa Jääskeläinen 	switch (get_certificate_type(*out)) {
6484137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
6494137952dSVesa Jääskeläinen 		mandated = pkcs11_x509_certificate_mandated;
6504137952dSVesa Jääskeläinen 		optional = pkcs11_x509_certificate_optional;
6514137952dSVesa Jääskeläinen 		mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated);
6524137952dSVesa Jääskeläinen 		optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional);
6534137952dSVesa Jääskeläinen 		break;
6544137952dSVesa Jääskeläinen 	default:
6554137952dSVesa Jääskeläinen 		EMSG("Invalid certificate type %#"PRIx32"/%s",
6564137952dSVesa Jääskeläinen 		     get_certificate_type(*out),
6574137952dSVesa Jääskeläinen 		     id2str_certificate_type(get_certificate_type(*out)));
6584137952dSVesa Jääskeläinen 
6594137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
6604137952dSVesa Jääskeläinen 	}
6614137952dSVesa Jääskeläinen 
6624137952dSVesa Jääskeläinen 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
6634137952dSVesa Jääskeläinen 	if (rc)
6644137952dSVesa Jääskeläinen 		return rc;
6654137952dSVesa Jääskeläinen 
6664137952dSVesa Jääskeläinen 	rc = set_optional_attributes(out, temp, optional, optional_count);
6674137952dSVesa Jääskeläinen 	if (rc)
6684137952dSVesa Jääskeläinen 		return rc;
6694137952dSVesa Jääskeläinen 
6704137952dSVesa Jääskeläinen 	attr_size = 0;
6714137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY,
6724137952dSVesa Jääskeläinen 			       &attr_value, &attr_size);
6734137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(cert_category)) {
6744137952dSVesa Jääskeläinen 		/* Sanitize certificate category */
6754137952dSVesa Jääskeläinen 		TEE_MemMove(&cert_category, attr_value, sizeof(cert_category));
6764137952dSVesa Jääskeläinen 
6774137952dSVesa Jääskeläinen 		switch (cert_category) {
6784137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED:
6794137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER:
6804137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY:
6814137952dSVesa Jääskeläinen 		case PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY:
6824137952dSVesa Jääskeläinen 			break;
6834137952dSVesa Jääskeläinen 		default:
6844137952dSVesa Jääskeläinen 			EMSG("Invalid certificate category %#"PRIx32,
6854137952dSVesa Jääskeläinen 			     cert_category);
6864137952dSVesa Jääskeläinen 
6874137952dSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
6884137952dSVesa Jääskeläinen 		}
6894137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
6904137952dSVesa Jääskeläinen 		/* Set default category when missing */
6914137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY,
6924137952dSVesa Jääskeläinen 				   &default_cert_category,
6934137952dSVesa Jääskeläinen 				   sizeof(default_cert_category));
6944137952dSVesa Jääskeläinen 		if (rc)
6954137952dSVesa Jääskeläinen 			return rc;
6964137952dSVesa Jääskeläinen 	} else {
6974137952dSVesa Jääskeläinen 		/* All other cases are errors */
6984137952dSVesa Jääskeläinen 		EMSG("Invalid certificate category");
6994137952dSVesa Jääskeläinen 
7004137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7014137952dSVesa Jääskeläinen 	}
7024137952dSVesa Jääskeläinen 
7034137952dSVesa Jääskeläinen 	attr_size = 0;
7044137952dSVesa Jääskeläinen 	rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL,
7054137952dSVesa Jääskeläinen 			       &attr_size);
7064137952dSVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && attr_size == sizeof(uint32_t)) {
7074137952dSVesa Jääskeläinen 		/* We accept any algorithm what caller wanted to specify */
7084137952dSVesa Jääskeläinen 	} else if (rc == PKCS11_RV_NOT_FOUND) {
7094137952dSVesa Jääskeläinen 		/* Set default hash algorithm when missing */
7104137952dSVesa Jääskeläinen 		rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM,
7114137952dSVesa Jääskeläinen 				   &default_name_hash_alg,
7124137952dSVesa Jääskeläinen 				   sizeof(default_name_hash_alg));
7134137952dSVesa Jääskeläinen 		if (rc)
7144137952dSVesa Jääskeläinen 			return rc;
7154137952dSVesa Jääskeläinen 	} else {
7164137952dSVesa Jääskeläinen 		/* All other cases are errors */
7174137952dSVesa Jääskeläinen 		EMSG("Invalid name hash algorithm");
7184137952dSVesa Jääskeläinen 
7194137952dSVesa Jääskeläinen 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7204137952dSVesa Jääskeläinen 	}
7214137952dSVesa Jääskeläinen 
7224137952dSVesa Jääskeläinen 	return rc;
7234137952dSVesa Jääskeläinen }
7244137952dSVesa Jääskeläinen 
72563f89caaSJens Wiklander static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
7269cf1afceSVesa Jääskeläinen 						struct obj_attrs *temp,
7279cf1afceSVesa Jääskeläinen 						enum processing_func function)
72863f89caaSJens Wiklander {
72963f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
7309cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
73163f89caaSJens Wiklander 	size_t mandated_count = 0;
7329cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
73363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
73463f89caaSJens Wiklander 
73563f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY);
73663f89caaSJens Wiklander 
73763f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
73863f89caaSJens Wiklander 	if (rc)
73963f89caaSJens Wiklander 		return rc;
74063f89caaSJens Wiklander 
74163f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY);
74263f89caaSJens Wiklander 
7434eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, public_key_boolprops,
7444eb88651SRuchika Gupta 				     ARRAY_SIZE(public_key_boolprops));
74563f89caaSJens Wiklander 	if (rc)
74663f89caaSJens Wiklander 		return rc;
74763f89caaSJens Wiklander 
7484eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, public_key_mandated,
7494eb88651SRuchika Gupta 				      ARRAY_SIZE(public_key_mandated));
75063f89caaSJens Wiklander 	if (rc)
75163f89caaSJens Wiklander 		return rc;
75263f89caaSJens Wiklander 
7534eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp,
7544eb88651SRuchika Gupta 					public_key_opt_or_null,
7554eb88651SRuchika Gupta 					ARRAY_SIZE(public_key_opt_or_null));
75663f89caaSJens Wiklander 	if (rc)
75763f89caaSJens Wiklander 		return rc;
75863f89caaSJens Wiklander 
75963f89caaSJens Wiklander 	switch (get_key_type(*out)) {
76063f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
7619cf1afceSVesa Jääskeläinen 		switch (function) {
7629cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
7639cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_gen_mand;
7649cf1afceSVesa Jääskeläinen 			oon = rsa_pub_key_gen_opt_or_null;
7659cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_gen_mand);
7669cf1afceSVesa Jääskeläinen 			oon_count = ARRAY_SIZE(rsa_pub_key_gen_opt_or_null);
7679cf1afceSVesa Jääskeläinen 			break;
7689cf1afceSVesa Jääskeläinen 		case PKCS11_FUNCTION_IMPORT:
7699cf1afceSVesa Jääskeläinen 			mandated = rsa_pub_key_create_mand;
7709cf1afceSVesa Jääskeläinen 			mandated_count = ARRAY_SIZE(rsa_pub_key_create_mand);
7719cf1afceSVesa Jääskeläinen 			break;
7729cf1afceSVesa Jääskeläinen 		default:
7739cf1afceSVesa Jääskeläinen 			EMSG("Unsupported function %#"PRIx32"/%s", function,
7749cf1afceSVesa Jääskeläinen 			     id2str_function(function));
7759cf1afceSVesa Jääskeläinen 
7769cf1afceSVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
7779cf1afceSVesa Jääskeläinen 		}
77863f89caaSJens Wiklander 		break;
77963f89caaSJens Wiklander 	case PKCS11_CKK_EC:
78003e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
7814eb88651SRuchika Gupta 		mandated = ec_public_key_mandated;
7829cf1afceSVesa Jääskeläinen 		oon = ec_public_key_opt_or_null;
7834eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_public_key_mandated);
7849cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_public_key_opt_or_null);
78563f89caaSJens Wiklander 		break;
78663f89caaSJens Wiklander 	default:
78763f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
78863f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
78963f89caaSJens Wiklander 
79063f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
79163f89caaSJens Wiklander 	}
79263f89caaSJens Wiklander 
79363f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
79463f89caaSJens Wiklander 	if (rc)
79563f89caaSJens Wiklander 		return rc;
79663f89caaSJens Wiklander 
7979cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
79863f89caaSJens Wiklander }
79963f89caaSJens Wiklander 
8005071d7d1SVesa Jääskeläinen static enum pkcs11_rc
8015071d7d1SVesa Jääskeläinen create_pub_key_rsa_generated_attributes(struct obj_attrs **out,
8025071d7d1SVesa Jääskeläinen 					struct obj_attrs *temp,
8035071d7d1SVesa Jääskeläinen 					enum processing_func function)
8045071d7d1SVesa Jääskeläinen {
8055071d7d1SVesa Jääskeläinen 	uint32_t key_bits = 0;
8065071d7d1SVesa Jääskeläinen 	void *a_ptr = NULL;
8075071d7d1SVesa Jääskeläinen 	uint32_t a_size = 0;
8085071d7d1SVesa Jääskeläinen 
8095071d7d1SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
8105071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_OK;
8115071d7d1SVesa Jääskeläinen 
8125071d7d1SVesa Jääskeläinen 	/* Calculate CKA_MODULUS_BITS */
8135071d7d1SVesa Jääskeläinen 
8145071d7d1SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_MODULUS,
8155071d7d1SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
8165071d7d1SVesa Jääskeläinen 		EMSG("No CKA_MODULUS attribute found in public key");
8175071d7d1SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
8185071d7d1SVesa Jääskeläinen 	}
8195071d7d1SVesa Jääskeläinen 
8205071d7d1SVesa Jääskeläinen 	key_bits = a_size * 8;
8215071d7d1SVesa Jääskeläinen 
8225071d7d1SVesa Jääskeläinen 	return add_attribute(out, PKCS11_CKA_MODULUS_BITS, &key_bits,
8235071d7d1SVesa Jääskeläinen 			     sizeof(key_bits));
8245071d7d1SVesa Jääskeläinen }
8255071d7d1SVesa Jääskeläinen 
8265071d7d1SVesa Jääskeläinen static enum pkcs11_rc
8275071d7d1SVesa Jääskeläinen create_pub_key_generated_attributes(struct obj_attrs **out,
8285071d7d1SVesa Jääskeläinen 				    struct obj_attrs *temp,
8295071d7d1SVesa Jääskeläinen 				    enum processing_func function)
8305071d7d1SVesa Jääskeläinen {
8315071d7d1SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
8325071d7d1SVesa Jääskeläinen 
8335071d7d1SVesa Jääskeläinen 	switch (get_key_type(*out)) {
8345071d7d1SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
8355071d7d1SVesa Jääskeläinen 		rc = create_pub_key_rsa_generated_attributes(out, temp,
8365071d7d1SVesa Jääskeläinen 							     function);
8375071d7d1SVesa Jääskeläinen 		break;
8385071d7d1SVesa Jääskeläinen 	default:
8395071d7d1SVesa Jääskeläinen 		/* no-op */
8405071d7d1SVesa Jääskeläinen 		break;
8415071d7d1SVesa Jääskeläinen 	}
8425071d7d1SVesa Jääskeläinen 
8435071d7d1SVesa Jääskeläinen 	return rc;
8445071d7d1SVesa Jääskeläinen }
8455071d7d1SVesa Jääskeläinen 
84663f89caaSJens Wiklander static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out,
84763f89caaSJens Wiklander 						 struct obj_attrs *temp)
84863f89caaSJens Wiklander {
84963f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
8509cf1afceSVesa Jääskeläinen 	uint32_t const *oon = NULL;
85163f89caaSJens Wiklander 	size_t mandated_count = 0;
8529cf1afceSVesa Jääskeläinen 	size_t oon_count = 0;
85363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
85463f89caaSJens Wiklander 
85563f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY);
85663f89caaSJens Wiklander 
85763f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
85863f89caaSJens Wiklander 	if (rc)
85963f89caaSJens Wiklander 		return rc;
86063f89caaSJens Wiklander 
86163f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY);
86263f89caaSJens Wiklander 
8634eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, private_key_boolprops,
8644eb88651SRuchika Gupta 				     ARRAY_SIZE(private_key_boolprops));
86563f89caaSJens Wiklander 	if (rc)
86663f89caaSJens Wiklander 		return rc;
86763f89caaSJens Wiklander 
8684eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, private_key_mandated,
8694eb88651SRuchika Gupta 				      ARRAY_SIZE(private_key_mandated));
87063f89caaSJens Wiklander 	if (rc)
87163f89caaSJens Wiklander 		return rc;
87263f89caaSJens Wiklander 
8734eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null,
8744eb88651SRuchika Gupta 					ARRAY_SIZE(private_key_opt_or_null));
87563f89caaSJens Wiklander 	if (rc)
87663f89caaSJens Wiklander 		return rc;
87763f89caaSJens Wiklander 
87863f89caaSJens Wiklander 	switch (get_key_type(*out)) {
87963f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
8809cf1afceSVesa Jääskeläinen 		oon = rsa_priv_key_opt_or_null;
8819cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(rsa_priv_key_opt_or_null);
88263f89caaSJens Wiklander 		break;
88363f89caaSJens Wiklander 	case PKCS11_CKK_EC:
8844eb88651SRuchika Gupta 		mandated = ec_private_key_mandated;
8859cf1afceSVesa Jääskeläinen 		oon = ec_private_key_opt_or_null;
8864eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
8879cf1afceSVesa Jääskeläinen 		oon_count = ARRAY_SIZE(ec_private_key_opt_or_null);
88863f89caaSJens Wiklander 		break;
88903e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
89003e07432SValerii Chubar 		mandated = ec_private_key_mandated;
89103e07432SValerii Chubar 		oon = eddsa_private_key_opt_or_null;
89203e07432SValerii Chubar 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
89303e07432SValerii Chubar 		oon_count = ARRAY_SIZE(eddsa_private_key_opt_or_null);
89403e07432SValerii Chubar 		break;
89563f89caaSJens Wiklander 	default:
89663f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
89763f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
89863f89caaSJens Wiklander 
89963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
90063f89caaSJens Wiklander 	}
90163f89caaSJens Wiklander 
90263f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
90363f89caaSJens Wiklander 	if (rc)
90463f89caaSJens Wiklander 		return rc;
90563f89caaSJens Wiklander 
9069cf1afceSVesa Jääskeläinen 	return set_attributes_opt_or_null(out, temp, oon, oon_count);
90763f89caaSJens Wiklander }
90863f89caaSJens Wiklander 
909*32b31808SJens Wiklander static int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len)
910*32b31808SJens Wiklander {
911*32b31808SJens Wiklander 	TEE_GenerateRandom(output, len);
912*32b31808SJens Wiklander 	return 0;
913*32b31808SJens Wiklander }
914*32b31808SJens Wiklander 
915196bcd93SRuchika Gupta static enum pkcs11_rc
9167c243321SVesa Jääskeläinen create_ec_priv_key_hidden_attributes(struct obj_attrs **out,
9177c243321SVesa Jääskeläinen 				     struct obj_attrs *temp,
9187c243321SVesa Jääskeläinen 				     enum processing_func function)
9197c243321SVesa Jääskeläinen {
9207c243321SVesa Jääskeläinen 	struct mbedtls_ecp_keypair key_pair = { };
9217c243321SVesa Jääskeläinen 	mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE;
922*32b31808SJens Wiklander 	mbedtls_ecp_group key_pair_grp = { };
923*32b31808SJens Wiklander 	mbedtls_ecp_point key_pair_Q = { };
924*32b31808SJens Wiklander 	mbedtls_mpi key_pair_d = { };
9257c243321SVesa Jääskeläinen 	size_t buflen = 0;
9267c243321SVesa Jääskeläinen 	uint8_t *buf = NULL;
9277c243321SVesa Jääskeläinen 	size_t asnbuflen = 0;
9287c243321SVesa Jääskeläinen 	uint8_t *asnbuf = NULL;
9297c243321SVesa Jääskeläinen 	uint8_t *ptr = NULL;
9307c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
9317c243321SVesa Jääskeläinen 	int tee_size = 0;
9327c243321SVesa Jääskeläinen 	int tee_curve = 0;
9337c243321SVesa Jääskeläinen 	void *a_ptr = NULL;
9347c243321SVesa Jääskeläinen 	uint32_t a_size = 0;
9357c243321SVesa Jääskeläinen 	int ret = 0;
9367c243321SVesa Jääskeläinen 
9377c243321SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
9387c243321SVesa Jääskeläinen 		return PKCS11_CKR_OK;
9397c243321SVesa Jääskeläinen 
9407c243321SVesa Jääskeläinen 	/*
9417c243321SVesa Jääskeläinen 	 * TEE internal API requires that for private key operations there
9427c243321SVesa Jääskeläinen 	 * needs to be also public key available.
9437c243321SVesa Jääskeläinen 	 *
9447c243321SVesa Jääskeläinen 	 * Generate hidden EC point from private key.
9457c243321SVesa Jääskeläinen 	 */
9467c243321SVesa Jääskeläinen 
9477c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS,
9487c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9497c243321SVesa Jääskeläinen 		EMSG("No EC_PARAMS attribute found in private key");
9507c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9517c243321SVesa Jääskeläinen 	}
9527c243321SVesa Jääskeläinen 
9537c243321SVesa Jääskeläinen 	/* Just valdiate that curve is found */
9547c243321SVesa Jääskeläinen 	tee_size = ec_params2tee_keysize(a_ptr, a_size);
9557c243321SVesa Jääskeläinen 	if (!tee_size) {
9567c243321SVesa Jääskeläinen 		EMSG("Unsupported EC_PARAMS curve");
9577c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9587c243321SVesa Jääskeläinen 	}
9597c243321SVesa Jääskeläinen 
9607c243321SVesa Jääskeläinen 	tee_curve = ec_params2tee_curve(a_ptr, a_size);
9617c243321SVesa Jääskeläinen 
9627c243321SVesa Jääskeläinen 	switch (tee_curve) {
9637c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P192:
9647c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP192R1;
9657c243321SVesa Jääskeläinen 		break;
9667c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P224:
9677c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP224R1;
9687c243321SVesa Jääskeläinen 		break;
9697c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P256:
9707c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP256R1;
9717c243321SVesa Jääskeläinen 		break;
9727c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P384:
9737c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP384R1;
9747c243321SVesa Jääskeläinen 		break;
9757c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P521:
9767c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP521R1;
9777c243321SVesa Jääskeläinen 		break;
9787c243321SVesa Jääskeläinen 	default:
9797c243321SVesa Jääskeläinen 		EMSG("Failed to map EC_PARAMS to supported curve");
9807c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
9817c243321SVesa Jääskeläinen 	}
9827c243321SVesa Jääskeläinen 
9837c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_VALUE,
9847c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
9857c243321SVesa Jääskeläinen 		EMSG("No VALUE attribute found in private key");
9867c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9877c243321SVesa Jääskeläinen 	}
9887c243321SVesa Jääskeläinen 
9897c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_init(&key_pair);
990*32b31808SJens Wiklander 	mbedtls_ecp_group_init(&key_pair_grp);
991*32b31808SJens Wiklander 	mbedtls_mpi_init(&key_pair_d);
992*32b31808SJens Wiklander 	mbedtls_ecp_point_init(&key_pair_Q);
9937c243321SVesa Jääskeläinen 
9947c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size);
9957c243321SVesa Jääskeläinen 	if (ret) {
9967c243321SVesa Jääskeläinen 		EMSG("Failed to parse CKA_VALUE");
9977c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
9987c243321SVesa Jääskeläinen 		goto out;
9997c243321SVesa Jääskeläinen 	}
10007c243321SVesa Jääskeläinen 
1001*32b31808SJens Wiklander 	ret = mbedtls_ecp_export(&key_pair, &key_pair_grp, &key_pair_d,
1002*32b31808SJens Wiklander 				 &key_pair_Q);
1003*32b31808SJens Wiklander 	if (ret) {
1004*32b31808SJens Wiklander 		EMSG("Failed to export key");
1005*32b31808SJens Wiklander 		goto out;
1006*32b31808SJens Wiklander 	}
1007*32b31808SJens Wiklander 
1008*32b31808SJens Wiklander 	ret = mbedtls_ecp_mul(&key_pair_grp, &key_pair_Q, &key_pair_d,
1009*32b31808SJens Wiklander 			      &key_pair_grp.G, mbd_rand, NULL);
10107c243321SVesa Jääskeläinen 	if (ret) {
10117c243321SVesa Jääskeläinen 		EMSG("Failed to create public key");
10127c243321SVesa Jääskeläinen 		goto out;
10137c243321SVesa Jääskeläinen 	}
10147c243321SVesa Jääskeläinen 
1015*32b31808SJens Wiklander 	ret = mbedtls_ecp_check_privkey(&key_pair_grp, &key_pair_d);
10167c243321SVesa Jääskeläinen 	if (ret) {
10177c243321SVesa Jääskeläinen 		EMSG("Failed to verify private key");
10187c243321SVesa Jääskeläinen 		goto out;
10197c243321SVesa Jääskeläinen 	}
10207c243321SVesa Jääskeläinen 
1021*32b31808SJens Wiklander 	ret = mbedtls_ecp_check_pubkey(&key_pair_grp, &key_pair_Q);
10227c243321SVesa Jääskeläinen 	if (ret) {
10237c243321SVesa Jääskeläinen 		EMSG("Failed to verify public key");
10247c243321SVesa Jääskeläinen 		goto out;
10257c243321SVesa Jääskeläinen 	}
10267c243321SVesa Jääskeläinen 
1027*32b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10287c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10297c243321SVesa Jääskeläinen 					     &buflen, NULL, 0);
10307c243321SVesa Jääskeläinen 	if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
10317c243321SVesa Jääskeläinen 		EMSG("Failed to determine size of binary public key");
10327c243321SVesa Jääskeläinen 		goto out;
10337c243321SVesa Jääskeläinen 	}
10347c243321SVesa Jääskeläinen 
10357c243321SVesa Jääskeläinen 	buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO);
10367c243321SVesa Jääskeläinen 	if (!buf) {
10377c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10387c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10397c243321SVesa Jääskeläinen 		goto out;
10407c243321SVesa Jääskeläinen 	}
10417c243321SVesa Jääskeläinen 
10427c243321SVesa Jääskeläinen 	asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen;
10437c243321SVesa Jääskeläinen 
10447c243321SVesa Jääskeläinen 	asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO);
10457c243321SVesa Jääskeläinen 	if (!asnbuf) {
10467c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
10477c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
10487c243321SVesa Jääskeläinen 		goto out;
10497c243321SVesa Jääskeläinen 	}
10507c243321SVesa Jääskeläinen 
1051*32b31808SJens Wiklander 	ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q,
10527c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
10537c243321SVesa Jääskeläinen 					     &buflen, buf, buflen);
10547c243321SVesa Jääskeläinen 	if (ret) {
10557c243321SVesa Jääskeläinen 		EMSG("Failed to write binary public key");
10567c243321SVesa Jääskeläinen 		goto out;
10577c243321SVesa Jääskeläinen 	}
10587c243321SVesa Jääskeläinen 
10597c243321SVesa Jääskeläinen 	/* Note: ASN.1 writing works backwards */
10607c243321SVesa Jääskeläinen 	ptr = asnbuf + asnbuflen;
10617c243321SVesa Jääskeläinen 
10627c243321SVesa Jääskeläinen 	ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen);
10637c243321SVesa Jääskeläinen 	if (ret < 0) {
10647c243321SVesa Jääskeläinen 		EMSG("Failed to write asn1 public key");
10657c243321SVesa Jääskeläinen 		goto out;
10667c243321SVesa Jääskeläinen 	}
10677c243321SVesa Jääskeläinen 
10687c243321SVesa Jääskeläinen 	rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr,
10697c243321SVesa Jääskeläinen 			   (size_t)ret);
10707c243321SVesa Jääskeläinen 
10717c243321SVesa Jääskeläinen out:
10727c243321SVesa Jääskeläinen 	TEE_Free(asnbuf);
10737c243321SVesa Jääskeläinen 	TEE_Free(buf);
10747c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_free(&key_pair);
1075*32b31808SJens Wiklander 	mbedtls_ecp_group_free(&key_pair_grp);
1076*32b31808SJens Wiklander 	mbedtls_mpi_free(&key_pair_d);
1077*32b31808SJens Wiklander 	mbedtls_ecp_point_free(&key_pair_Q);
10787c243321SVesa Jääskeläinen 
10797c243321SVesa Jääskeläinen 	return rc;
10807c243321SVesa Jääskeläinen }
10817c243321SVesa Jääskeläinen 
10827c243321SVesa Jääskeläinen static enum pkcs11_rc
10837c243321SVesa Jääskeläinen create_priv_key_hidden_attributes(struct obj_attrs **out,
10847c243321SVesa Jääskeläinen 				  struct obj_attrs *temp,
10857c243321SVesa Jääskeläinen 				  enum processing_func function)
10867c243321SVesa Jääskeläinen {
10877c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
10887c243321SVesa Jääskeläinen 
10897c243321SVesa Jääskeläinen 	switch (get_key_type(*out)) {
10907c243321SVesa Jääskeläinen 	case PKCS11_CKK_EC:
10917c243321SVesa Jääskeläinen 		rc = create_ec_priv_key_hidden_attributes(out, temp, function);
10927c243321SVesa Jääskeläinen 		break;
10937c243321SVesa Jääskeläinen 	default:
10947c243321SVesa Jääskeläinen 		/* no-op */
10957c243321SVesa Jääskeläinen 		break;
10967c243321SVesa Jääskeläinen 	}
10977c243321SVesa Jääskeläinen 
10987c243321SVesa Jääskeläinen 	return rc;
10997c243321SVesa Jääskeläinen }
11007c243321SVesa Jääskeläinen 
11017c243321SVesa Jääskeläinen static enum pkcs11_rc
1102196bcd93SRuchika Gupta sanitize_symm_key_attributes(struct obj_attrs **temp,
1103196bcd93SRuchika Gupta 			     enum processing_func function)
1104196bcd93SRuchika Gupta {
1105196bcd93SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1106196bcd93SRuchika Gupta 	uint32_t a_size = 0;
1107196bcd93SRuchika Gupta 
1108196bcd93SRuchika Gupta 	assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY);
1109196bcd93SRuchika Gupta 
1110196bcd93SRuchika Gupta 	rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size);
1111196bcd93SRuchika Gupta 
1112196bcd93SRuchika Gupta 	switch (get_key_type(*temp)) {
1113196bcd93SRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1114196bcd93SRuchika Gupta 	case PKCS11_CKK_AES:
1115196bcd93SRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
1116196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
1117196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
1118196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
1119196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
1120196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
1121196bcd93SRuchika Gupta 		switch (function) {
1122196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_IMPORT:
1123196bcd93SRuchika Gupta 			/* CKA_VALUE is a mandatory with C_CreateObject */
1124196bcd93SRuchika Gupta 			if (rc || a_size == 0)
1125196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1126196bcd93SRuchika Gupta 
1127196bcd93SRuchika Gupta 			if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL,
1128196bcd93SRuchika Gupta 					      NULL) != PKCS11_RV_NOT_FOUND)
1129196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1130196bcd93SRuchika Gupta 
1131196bcd93SRuchika Gupta 			return add_attribute(temp, PKCS11_CKA_VALUE_LEN,
1132196bcd93SRuchika Gupta 					     &a_size, sizeof(uint32_t));
1133196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1134196bcd93SRuchika Gupta 			if (rc != PKCS11_RV_NOT_FOUND)
1135196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1136196bcd93SRuchika Gupta 			break;
1137196bcd93SRuchika Gupta 		default:
1138196bcd93SRuchika Gupta 			break;
1139196bcd93SRuchika Gupta 		}
1140196bcd93SRuchika Gupta 		break;
1141196bcd93SRuchika Gupta 	default:
1142196bcd93SRuchika Gupta 		EMSG("Invalid key type %#"PRIx32"/%s",
1143196bcd93SRuchika Gupta 		     get_key_type(*temp), id2str_key_type(get_key_type(*temp)));
1144196bcd93SRuchika Gupta 
1145196bcd93SRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1146196bcd93SRuchika Gupta 	}
1147196bcd93SRuchika Gupta 
1148196bcd93SRuchika Gupta 	return PKCS11_CKR_OK;
1149196bcd93SRuchika Gupta }
1150196bcd93SRuchika Gupta 
115163f89caaSJens Wiklander /*
115263f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
115363f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
115463f89caaSJens Wiklander  * derive...).
115563f89caaSJens Wiklander  *
115663f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
115763f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
115863f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
115963f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
116063f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
116163f89caaSJens Wiklander  *
116263f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
116363f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
116463f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
116563f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
116663f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
116763f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
116863f89caaSJens Wiklander  */
116963f89caaSJens Wiklander enum pkcs11_rc
117063f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
117163f89caaSJens Wiklander 				size_t template_size,
117248799892SRuchika Gupta 				struct obj_attrs *parent,
117363f89caaSJens Wiklander 				enum processing_func function,
11744cfce748SRuchika Gupta 				enum pkcs11_mechanism_id mecha,
117502b16804SVesa Jääskeläinen 				enum pkcs11_class_id template_class)
117663f89caaSJens Wiklander {
117763f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
117863f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
117963f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
118063f89caaSJens Wiklander 	uint8_t local = 0;
118163f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
118263f89caaSJens Wiklander 	uint8_t never_extract = 0;
1183e3f0cb56SRuchika Gupta 	uint8_t extractable = 0;
1184fa247a2aSRuchika Gupta 	uint32_t class = PKCS11_UNDEFINED_ID;
1185fa247a2aSRuchika Gupta 	uint32_t type = PKCS11_UNDEFINED_ID;
118663f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
1187e3f0cb56SRuchika Gupta 	struct obj_attrs *req_attrs = NULL;
1188e3f0cb56SRuchika Gupta 	uint32_t size = 0;
1189e3f0cb56SRuchika Gupta 	uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID;
119063f89caaSJens Wiklander 
119163f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
119263f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
119363f89caaSJens Wiklander 	switch (function) {
1194fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1195013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
119663f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
11972d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
119848799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1199e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
12002d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
120163f89caaSJens Wiklander 		break;
120263f89caaSJens Wiklander 	default:
120363f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
120463f89caaSJens Wiklander 	}
120563f89caaSJens Wiklander #endif
120663f89caaSJens Wiklander 
1207dcad3409SRuchika Gupta 	/*
1208dcad3409SRuchika Gupta 	 * For PKCS11_FUNCTION_GENERATE, find the class and type
1209dcad3409SRuchika Gupta 	 * based on the mechanism. These will be passed as hint
1210dcad3409SRuchika Gupta 	 * sanitize_client_object() and added in temp if not
1211dcad3409SRuchika Gupta 	 * already present
1212dcad3409SRuchika Gupta 	 */
1213dcad3409SRuchika Gupta 	if (function == PKCS11_FUNCTION_GENERATE) {
1214fa247a2aSRuchika Gupta 		switch (mecha) {
1215fa247a2aSRuchika Gupta 		case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1216fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1217fa247a2aSRuchika Gupta 			type = PKCS11_CKK_GENERIC_SECRET;
1218fa247a2aSRuchika Gupta 			break;
1219fa247a2aSRuchika Gupta 		case PKCS11_CKM_AES_KEY_GEN:
1220fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1221fa247a2aSRuchika Gupta 			type = PKCS11_CKK_AES;
1222fa247a2aSRuchika Gupta 			break;
1223fa247a2aSRuchika Gupta 		default:
1224dcad3409SRuchika Gupta 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1225fa247a2aSRuchika Gupta 		}
1226fa247a2aSRuchika Gupta 	}
1227fa247a2aSRuchika Gupta 
12282d25a9bcSRuchika Gupta 	/*
1229013934d8SVesa Jääskeläinen 	 * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type
1230013934d8SVesa Jääskeläinen 	 * based on the mechanism. These will be passed as hint
1231013934d8SVesa Jääskeläinen 	 * sanitize_client_object() and added in temp if not
1232013934d8SVesa Jääskeläinen 	 * already present
1233013934d8SVesa Jääskeläinen 	 */
1234013934d8SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_GENERATE_PAIR) {
1235013934d8SVesa Jääskeläinen 		switch (mecha) {
123603e07432SValerii Chubar 		case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
123703e07432SValerii Chubar 			class = template_class;
123803e07432SValerii Chubar 			type = PKCS11_CKK_EDDSA;
123903e07432SValerii Chubar 			break;
124002b16804SVesa Jääskeläinen 		case PKCS11_CKM_EC_KEY_PAIR_GEN:
124102b16804SVesa Jääskeläinen 			class = template_class;
124202b16804SVesa Jääskeläinen 			type = PKCS11_CKK_EC;
124302b16804SVesa Jääskeläinen 			break;
124486922832SVesa Jääskeläinen 		case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
124586922832SVesa Jääskeläinen 			class = template_class;
124686922832SVesa Jääskeläinen 			type = PKCS11_CKK_RSA;
124786922832SVesa Jääskeläinen 			break;
1248013934d8SVesa Jääskeläinen 		default:
1249013934d8SVesa Jääskeläinen 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1250013934d8SVesa Jääskeläinen 		}
1251013934d8SVesa Jääskeläinen 	}
1252013934d8SVesa Jääskeläinen 
1253013934d8SVesa Jääskeläinen 	/*
12542d25a9bcSRuchika Gupta 	 * Check and remove duplicates if any and create a new temporary
12552d25a9bcSRuchika Gupta 	 * template
12562d25a9bcSRuchika Gupta 	 */
1257dcad3409SRuchika Gupta 	rc = sanitize_client_object(&temp, template, template_size, class,
1258dcad3409SRuchika Gupta 				    type);
1259dcad3409SRuchika Gupta 	if (rc)
1260dcad3409SRuchika Gupta 		goto out;
1261dcad3409SRuchika Gupta 
1262dcad3409SRuchika Gupta 	/*
12632d25a9bcSRuchika Gupta 	 * For function type modify and copy return the created template
12642d25a9bcSRuchika Gupta 	 * from here. Rest of the code below is for creating objects
12652d25a9bcSRuchika Gupta 	 * or generating keys.
12662d25a9bcSRuchika Gupta 	 */
12672d25a9bcSRuchika Gupta 	switch (function) {
12682d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
12692d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
12702d25a9bcSRuchika Gupta 		*out = temp;
12712d25a9bcSRuchika Gupta 		return rc;
1272e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1273e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
1274e3f0cb56SRuchika Gupta 		if (function == PKCS11_FUNCTION_UNWRAP)
1275e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE;
1276e3f0cb56SRuchika Gupta 		else
1277e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_DERIVE_TEMPLATE;
1278e3f0cb56SRuchika Gupta 
1279e3f0cb56SRuchika Gupta 		rc = get_attribute_ptr(parent, indirect_template,
1280e3f0cb56SRuchika Gupta 				       (void *)&req_attrs, &size);
1281e3f0cb56SRuchika Gupta 		if (rc == PKCS11_CKR_OK && size != 0) {
1282e3f0cb56SRuchika Gupta 			rc = attributes_match_add_reference(&temp, req_attrs);
1283e3f0cb56SRuchika Gupta 			if (rc)
1284e3f0cb56SRuchika Gupta 				goto out;
1285e3f0cb56SRuchika Gupta 		}
1286e3f0cb56SRuchika Gupta 		break;
12872d25a9bcSRuchika Gupta 	default:
12882d25a9bcSRuchika Gupta 		break;
12892d25a9bcSRuchika Gupta 	}
12902d25a9bcSRuchika Gupta 
12912d25a9bcSRuchika Gupta 	/*
1292dcad3409SRuchika Gupta 	 * Check if class and type in temp are consistent with the mechanism
1293dcad3409SRuchika Gupta 	 */
1294fa247a2aSRuchika Gupta 	switch (mecha) {
1295fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1296fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1297fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) {
1298fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1299fa247a2aSRuchika Gupta 			goto out;
1300fa247a2aSRuchika Gupta 		}
1301fa247a2aSRuchika Gupta 		break;
1302fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1303fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1304fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_AES) {
1305fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1306fa247a2aSRuchika Gupta 			goto out;
1307fa247a2aSRuchika Gupta 		}
1308fa247a2aSRuchika Gupta 		break;
130902b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
131002b16804SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
131102b16804SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
131202b16804SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_EC) {
131302b16804SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
131402b16804SVesa Jääskeläinen 			goto out;
131502b16804SVesa Jääskeläinen 		}
131602b16804SVesa Jääskeläinen 		break;
131703e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
131803e07432SValerii Chubar 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
131903e07432SValerii Chubar 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132003e07432SValerii Chubar 		    get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) {
132103e07432SValerii Chubar 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
132203e07432SValerii Chubar 			goto out;
132303e07432SValerii Chubar 		}
132403e07432SValerii Chubar 		break;
132586922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
132686922832SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
132786922832SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
132886922832SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_RSA) {
132986922832SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
133086922832SVesa Jääskeläinen 			goto out;
133186922832SVesa Jääskeläinen 		}
133286922832SVesa Jääskeläinen 		break;
1333fa247a2aSRuchika Gupta 	default:
1334fa247a2aSRuchika Gupta 		break;
1335fa247a2aSRuchika Gupta 	}
133663f89caaSJens Wiklander 
133763f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
133863f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
133963f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
134063f89caaSJens Wiklander 		goto out;
134163f89caaSJens Wiklander 	}
134263f89caaSJens Wiklander 
1343e3f0cb56SRuchika Gupta 	/*
1344e3f0cb56SRuchika Gupta 	 * TBD - Add a check to see if temp contains any attribute which
1345e3f0cb56SRuchika Gupta 	 * is not consistent with the object class or type and return error.
1346e3f0cb56SRuchika Gupta 	 * In current implementation such attributes are ignored and not
1347e3f0cb56SRuchika Gupta 	 * added to final object while PKCS#11 specification expects a
1348e3f0cb56SRuchika Gupta 	 * failure and an error code be returned.
1349e3f0cb56SRuchika Gupta 	 */
1350e3f0cb56SRuchika Gupta 
135163f89caaSJens Wiklander 	switch (get_class(temp)) {
135263f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
135363f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
135463f89caaSJens Wiklander 		break;
13554137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
13564137952dSVesa Jääskeläinen 		rc = create_certificate_attributes(&attrs, temp);
13574137952dSVesa Jääskeläinen 		break;
135863f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1359196bcd93SRuchika Gupta 		rc = sanitize_symm_key_attributes(&temp, function);
1360196bcd93SRuchika Gupta 		if (rc)
1361196bcd93SRuchika Gupta 			goto out;
136263f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
136363f89caaSJens Wiklander 		break;
136463f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
13659cf1afceSVesa Jääskeläinen 		rc = create_pub_key_attributes(&attrs, temp, function);
13665071d7d1SVesa Jääskeläinen 		if (rc)
13675071d7d1SVesa Jääskeläinen 			goto out;
13685071d7d1SVesa Jääskeläinen 		rc = create_pub_key_generated_attributes(&attrs, temp,
13695071d7d1SVesa Jääskeläinen 							 function);
137063f89caaSJens Wiklander 		break;
137163f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
137263f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
13737c243321SVesa Jääskeläinen 		if (rc)
13747c243321SVesa Jääskeläinen 			goto out;
13757c243321SVesa Jääskeläinen 		rc = create_priv_key_hidden_attributes(&attrs, temp, function);
137663f89caaSJens Wiklander 		break;
137763f89caaSJens Wiklander 	default:
137863f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
137963f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
138063f89caaSJens Wiklander 
138163f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
138263f89caaSJens Wiklander 		break;
138363f89caaSJens Wiklander 	}
138463f89caaSJens Wiklander 	if (rc)
138563f89caaSJens Wiklander 		goto out;
138663f89caaSJens Wiklander 
138790c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) !=
1388002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1389002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139063f89caaSJens Wiklander 		goto out;
1391002f6b93SEtienne Carriere 	}
139263f89caaSJens Wiklander 
139390c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
1394002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1395002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
139663f89caaSJens Wiklander 		goto out;
1397002f6b93SEtienne Carriere 	}
139863f89caaSJens Wiklander 
139963f89caaSJens Wiklander 	switch (function) {
1400fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1401013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
1402fa247a2aSRuchika Gupta 		local = PKCS11_TRUE;
1403fa247a2aSRuchika Gupta 		break;
140463f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
140548799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1406e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
140763f89caaSJens Wiklander 	default:
140863f89caaSJens Wiklander 		local = PKCS11_FALSE;
140963f89caaSJens Wiklander 		break;
141063f89caaSJens Wiklander 	}
141163f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
141263f89caaSJens Wiklander 	if (rc)
141363f89caaSJens Wiklander 		goto out;
141463f89caaSJens Wiklander 
141563f89caaSJens Wiklander 	switch (get_class(attrs)) {
141663f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
141763f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
141863f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
141963f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
142063f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
142163f89caaSJens Wiklander 
1422fa247a2aSRuchika Gupta 		switch (function) {
142348799892SRuchika Gupta 		case PKCS11_FUNCTION_DERIVE:
142448799892SRuchika Gupta 			always_sensitive =
142548799892SRuchika Gupta 				get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) &&
142648799892SRuchika Gupta 				get_bool(attrs, PKCS11_CKA_SENSITIVE);
142748799892SRuchika Gupta 			never_extract =
142848799892SRuchika Gupta 			       get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) &&
142948799892SRuchika Gupta 			       !get_bool(attrs, PKCS11_CKA_EXTRACTABLE);
143048799892SRuchika Gupta 			break;
1431e3f0cb56SRuchika Gupta 		case PKCS11_FUNCTION_UNWRAP:
1432e3f0cb56SRuchika Gupta 			always_sensitive = PKCS11_FALSE;
1433e3f0cb56SRuchika Gupta 			never_extract = PKCS11_FALSE;
1434e3f0cb56SRuchika Gupta 			extractable = PKCS11_TRUE;
1435e3f0cb56SRuchika Gupta 
1436e3f0cb56SRuchika Gupta 			/*
1437e3f0cb56SRuchika Gupta 			 * Check if template passed by user has CKA_EXTRACTABLE.
1438e3f0cb56SRuchika Gupta 			 * If not, by default value of CKA_EXTRACTABLE is set as
1439e3f0cb56SRuchika Gupta 			 * TRUE.
1440e3f0cb56SRuchika Gupta 			 */
1441e3f0cb56SRuchika Gupta 			if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE,
1442e3f0cb56SRuchika Gupta 					      NULL,
1443e3f0cb56SRuchika Gupta 					      NULL) == PKCS11_RV_NOT_FOUND) {
1444e3f0cb56SRuchika Gupta 				rc = set_attribute(&attrs,
1445e3f0cb56SRuchika Gupta 						   PKCS11_CKA_EXTRACTABLE,
1446e3f0cb56SRuchika Gupta 						   &extractable,
1447e3f0cb56SRuchika Gupta 						   sizeof(extractable));
1448e3f0cb56SRuchika Gupta 				if (rc)
1449e3f0cb56SRuchika Gupta 					goto out;
1450e3f0cb56SRuchika Gupta 			}
1451e3f0cb56SRuchika Gupta 			break;
1452fa247a2aSRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1453013934d8SVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
1454fa247a2aSRuchika Gupta 			always_sensitive = get_bool(attrs,
1455fa247a2aSRuchika Gupta 						    PKCS11_CKA_SENSITIVE);
1456fa247a2aSRuchika Gupta 			never_extract = !get_bool(attrs,
1457fa247a2aSRuchika Gupta 						  PKCS11_CKA_EXTRACTABLE);
1458fa247a2aSRuchika Gupta 			break;
1459fa247a2aSRuchika Gupta 		default:
1460fa247a2aSRuchika Gupta 			break;
1461fa247a2aSRuchika Gupta 		}
1462fa247a2aSRuchika Gupta 
146363f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
146463f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
146563f89caaSJens Wiklander 		if (rc)
146663f89caaSJens Wiklander 			goto out;
146763f89caaSJens Wiklander 
146863f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
146963f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
147063f89caaSJens Wiklander 		if (rc)
147163f89caaSJens Wiklander 			goto out;
147263f89caaSJens Wiklander 
147363f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
1474fa247a2aSRuchika Gupta 		if (local)
1475fa247a2aSRuchika Gupta 			mechanism_id = mecha;
1476fa247a2aSRuchika Gupta 		else
147763f89caaSJens Wiklander 			mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
1478fa247a2aSRuchika Gupta 
147963f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
148063f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
148163f89caaSJens Wiklander 		if (rc)
148263f89caaSJens Wiklander 			goto out;
148363f89caaSJens Wiklander 		break;
148463f89caaSJens Wiklander 
148563f89caaSJens Wiklander 	default:
148663f89caaSJens Wiklander 		break;
148763f89caaSJens Wiklander 	}
148863f89caaSJens Wiklander 
148963f89caaSJens Wiklander 	*out = attrs;
149063f89caaSJens Wiklander 
149163f89caaSJens Wiklander #ifdef DEBUG
149263f89caaSJens Wiklander 	trace_attributes("object", attrs);
149363f89caaSJens Wiklander #endif
149463f89caaSJens Wiklander 
149563f89caaSJens Wiklander out:
149663f89caaSJens Wiklander 	TEE_Free(temp);
149763f89caaSJens Wiklander 	if (rc)
149863f89caaSJens Wiklander 		TEE_Free(attrs);
149963f89caaSJens Wiklander 
150063f89caaSJens Wiklander 	return rc;
150163f89caaSJens Wiklander }
150263f89caaSJens Wiklander 
150363f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
150463f89caaSJens Wiklander {
150563f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
150663f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
150763f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
150863f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
150963f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
151063f89caaSJens Wiklander 
151163f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
151263f89caaSJens Wiklander 	}
151363f89caaSJens Wiklander 
151463f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
151563f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
151663f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
151763f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
151863f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
151963f89caaSJens Wiklander 
152063f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152163f89caaSJens Wiklander 	}
152263f89caaSJens Wiklander 
152363f89caaSJens Wiklander 	return PKCS11_CKR_OK;
152463f89caaSJens Wiklander }
152563f89caaSJens Wiklander 
152689735787SRuchika Gupta bool object_is_private(struct obj_attrs *head)
152789735787SRuchika Gupta {
152865fb9092SVesa Jääskeläinen 	return get_bool(head, PKCS11_CKA_PRIVATE);
152989735787SRuchika Gupta }
153089735787SRuchika Gupta 
15312d25a9bcSRuchika Gupta bool object_is_token(struct obj_attrs *head)
15322d25a9bcSRuchika Gupta {
15332d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_TOKEN);
15342d25a9bcSRuchika Gupta }
15352d25a9bcSRuchika Gupta 
15362d25a9bcSRuchika Gupta bool object_is_modifiable(struct obj_attrs *head)
15372d25a9bcSRuchika Gupta {
15382d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_MODIFIABLE);
15392d25a9bcSRuchika Gupta }
15402d25a9bcSRuchika Gupta 
15412d25a9bcSRuchika Gupta bool object_is_copyable(struct obj_attrs *head)
15422d25a9bcSRuchika Gupta {
15432d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_COPYABLE);
15442d25a9bcSRuchika Gupta }
15452d25a9bcSRuchika Gupta 
154663f89caaSJens Wiklander /*
1547512cbf1dSJens Wiklander  * Check access to object against authentication to token
1548512cbf1dSJens Wiklander  */
1549512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
1550512cbf1dSJens Wiklander 						struct obj_attrs *head)
1551512cbf1dSJens Wiklander {
1552512cbf1dSJens Wiklander 	bool private = true;
1553512cbf1dSJens Wiklander 
1554512cbf1dSJens Wiklander 	switch (get_class(head)) {
1555512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
155665fb9092SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1557512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
1558512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
15594137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
156065fb9092SVesa Jääskeläinen 		private = object_is_private(head);
1561512cbf1dSJens Wiklander 		break;
1562512cbf1dSJens Wiklander 	default:
1563512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1564512cbf1dSJens Wiklander 	}
1565512cbf1dSJens Wiklander 
15665db0fef4SRuchika Gupta 	if (private && (pkcs11_session_is_public(session) ||
15675db0fef4SRuchika Gupta 			pkcs11_session_is_so(session))) {
15685db0fef4SRuchika Gupta 		DMSG("Private object access from a public or SO session");
1569512cbf1dSJens Wiklander 
157012f1ba86SRuchika Gupta 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1571512cbf1dSJens Wiklander 	}
1572512cbf1dSJens Wiklander 
1573512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1574512cbf1dSJens Wiklander }
1575512cbf1dSJens Wiklander 
1576512cbf1dSJens Wiklander /*
157763f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
157863f89caaSJens Wiklander  */
157963f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
158063f89caaSJens Wiklander 						 struct obj_attrs *head)
158163f89caaSJens Wiklander {
158263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
158363f89caaSJens Wiklander 
158463f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
158563f89caaSJens Wiklander 	if (rc)
158663f89caaSJens Wiklander 		return rc;
158763f89caaSJens Wiklander 
158863f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
158963f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
159063f89caaSJens Wiklander 		DMSG("Can't create trusted object");
159163f89caaSJens Wiklander 
159263f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
159363f89caaSJens Wiklander 	}
159463f89caaSJens Wiklander 
159563f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
159663f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
159763f89caaSJens Wiklander 		DMSG("Can't create persistent object");
159863f89caaSJens Wiklander 
159963f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
160063f89caaSJens Wiklander 	}
160163f89caaSJens Wiklander 
160263f89caaSJens Wiklander 	return PKCS11_CKR_OK;
160363f89caaSJens Wiklander }
160463f89caaSJens Wiklander 
160563f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
160663f89caaSJens Wiklander 	do {								\
160763f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
160863f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
160963f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
161063f89caaSJens Wiklander 									\
161163f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
161263f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
161363f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
161463f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
161563f89caaSJens Wiklander 	} while (0)
161663f89caaSJens Wiklander 
161763f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
161863f89caaSJens Wiklander 					   struct obj_attrs *head,
161963f89caaSJens Wiklander 					   uint32_t attribute, bool val)
162063f89caaSJens Wiklander {
162163f89caaSJens Wiklander 	uint8_t bbool = 0;
162263f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
162363f89caaSJens Wiklander 
162463f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
162563f89caaSJens Wiklander 		return true;
162663f89caaSJens Wiklander 
162763f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
162863f89caaSJens Wiklander 	return false;
162963f89caaSJens Wiklander }
163063f89caaSJens Wiklander 
163163f89caaSJens Wiklander /*
163263f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
163363f89caaSJens Wiklander  * used to create it.
163463f89caaSJens Wiklander  *
163563f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
163663f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
163763f89caaSJens Wiklander  */
163863f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
163963f89caaSJens Wiklander 						      struct obj_attrs *head)
164063f89caaSJens Wiklander {
164163f89caaSJens Wiklander 	/*
164263f89caaSJens Wiklander 	 * Processings that do not create secrets are not expected to call
164363f89caaSJens Wiklander 	 * this function which would panic.
164463f89caaSJens Wiklander 	 */
164563f89caaSJens Wiklander 	switch (proc_id) {
164663f89caaSJens Wiklander 	case PKCS11_PROCESSING_IMPORT:
1647cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1648e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_ECB:
1649e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_CBC:
165048799892SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
165148799892SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
165245d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
165363f89caaSJens Wiklander 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
165463f89caaSJens Wiklander 		break;
1655fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1656fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
165703e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
165802b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
165986922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
1660fa247a2aSRuchika Gupta 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true));
1661fa247a2aSRuchika Gupta 		break;
166263f89caaSJens Wiklander 	default:
166363f89caaSJens Wiklander 		TEE_Panic(proc_id);
166463f89caaSJens Wiklander 		break;
166563f89caaSJens Wiklander 	}
166663f89caaSJens Wiklander 
1667fa247a2aSRuchika Gupta 	switch (proc_id) {
1668fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1669fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET);
1670fa247a2aSRuchika Gupta 		break;
1671fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1672fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_AES);
1673fa247a2aSRuchika Gupta 		break;
167403e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
167503e07432SValerii Chubar 		assert(get_key_type(head) == PKCS11_CKK_EC_EDWARDS);
167603e07432SValerii Chubar 		break;
167702b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
167802b16804SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_EC);
167902b16804SVesa Jääskeläinen 		break;
168086922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
168186922832SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_RSA);
168286922832SVesa Jääskeläinen 		break;
1683fa247a2aSRuchika Gupta 	case PKCS11_PROCESSING_IMPORT:
1684cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1685fa247a2aSRuchika Gupta 	default:
1686fa247a2aSRuchika Gupta 		break;
1687fa247a2aSRuchika Gupta 	}
1688fa247a2aSRuchika Gupta 
168963f89caaSJens Wiklander 	return PKCS11_CKR_OK;
169063f89caaSJens Wiklander }
1691512cbf1dSJens Wiklander 
16922d0cd829SRuchika Gupta /* Return min and max key size supported for a key_type in bytes */
1693512cbf1dSJens Wiklander static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
1694512cbf1dSJens Wiklander 				  uint32_t *min_key_size,
1695512cbf1dSJens Wiklander 				  uint32_t *max_key_size)
1696512cbf1dSJens Wiklander {
1697512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
1698512cbf1dSJens Wiklander 
1699512cbf1dSJens Wiklander 	switch (key_type) {
1700fa247a2aSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1701fa247a2aSRuchika Gupta 		mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN;
1702fa247a2aSRuchika Gupta 		break;
1703512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
1704512cbf1dSJens Wiklander 		mechanism = PKCS11_CKM_AES_KEY_GEN;
1705512cbf1dSJens Wiklander 		break;
17061f45c9cfSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
17071f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_MD5_HMAC;
17081f45c9cfSRuchika Gupta 		break;
17091f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
17101f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA_1_HMAC;
17111f45c9cfSRuchika Gupta 		break;
17121f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
17131f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA224_HMAC;
17141f45c9cfSRuchika Gupta 		break;
1715a339a354SEtienne Carriere 	case PKCS11_CKK_SHA256_HMAC:
1716a339a354SEtienne Carriere 		mechanism = PKCS11_CKM_SHA256_HMAC;
1717a339a354SEtienne Carriere 		break;
17181f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
17191f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA384_HMAC;
17201f45c9cfSRuchika Gupta 		break;
17211f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
17221f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA512_HMAC;
17231f45c9cfSRuchika Gupta 		break;
1724db28c542SVesa Jääskeläinen 	case PKCS11_CKK_EC:
1725db28c542SVesa Jääskeläinen 		mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN;
1726db28c542SVesa Jääskeläinen 		break;
172703e07432SValerii Chubar 	case PKCS11_CKK_EDDSA:
172803e07432SValerii Chubar 		mechanism = PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN;
172903e07432SValerii Chubar 		break;
173086922832SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
173186922832SVesa Jääskeläinen 		mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN;
173286922832SVesa Jääskeläinen 		break;
1733512cbf1dSJens Wiklander 	default:
1734512cbf1dSJens Wiklander 		TEE_Panic(key_type);
1735512cbf1dSJens Wiklander 		break;
1736512cbf1dSJens Wiklander 	}
1737512cbf1dSJens Wiklander 
17382d0cd829SRuchika Gupta 	mechanism_supported_key_sizes_bytes(mechanism, min_key_size,
1739512cbf1dSJens Wiklander 					    max_key_size);
1740512cbf1dSJens Wiklander }
1741512cbf1dSJens Wiklander 
1742512cbf1dSJens Wiklander enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
1743512cbf1dSJens Wiklander 				   struct obj_attrs *key2)
1744512cbf1dSJens Wiklander {
1745512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1746512cbf1dSJens Wiklander 	struct obj_attrs *secret = NULL;
1747013934d8SVesa Jääskeläinen 	struct obj_attrs *private = NULL;
1748013934d8SVesa Jääskeläinen 	struct obj_attrs *public = NULL;
1749512cbf1dSJens Wiklander 	uint32_t max_key_size = 0;
1750512cbf1dSJens Wiklander 	uint32_t min_key_size = 0;
1751512cbf1dSJens Wiklander 	uint32_t key_length = 0;
1752512cbf1dSJens Wiklander 
1753512cbf1dSJens Wiklander 	switch (get_class(key1)) {
1754512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1755512cbf1dSJens Wiklander 		secret = key1;
1756512cbf1dSJens Wiklander 		break;
1757013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
1758013934d8SVesa Jääskeläinen 		public = key1;
1759013934d8SVesa Jääskeläinen 		break;
1760013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1761013934d8SVesa Jääskeläinen 		private = key1;
1762013934d8SVesa Jääskeläinen 		break;
1763512cbf1dSJens Wiklander 	default:
1764512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1765512cbf1dSJens Wiklander 	}
1766512cbf1dSJens Wiklander 
1767013934d8SVesa Jääskeläinen 	if (key2) {
1768013934d8SVesa Jääskeläinen 		switch (get_class(key2)) {
1769013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PUBLIC_KEY:
1770013934d8SVesa Jääskeläinen 			public = key2;
1771013934d8SVesa Jääskeläinen 			if (private == key1)
1772013934d8SVesa Jääskeläinen 				break;
1773013934d8SVesa Jääskeläinen 
1774013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1775013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PRIVATE_KEY:
1776013934d8SVesa Jääskeläinen 			private = key2;
1777013934d8SVesa Jääskeläinen 			if (public == key1)
1778013934d8SVesa Jääskeläinen 				break;
1779013934d8SVesa Jääskeläinen 
1780013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1781013934d8SVesa Jääskeläinen 		default:
1782512cbf1dSJens Wiklander 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1783013934d8SVesa Jääskeläinen 		}
1784013934d8SVesa Jääskeläinen 
1785013934d8SVesa Jääskeläinen 		if (get_key_type(private) != get_key_type(public))
1786013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1787013934d8SVesa Jääskeläinen 	}
1788512cbf1dSJens Wiklander 
1789512cbf1dSJens Wiklander 	if (secret) {
1790512cbf1dSJens Wiklander 		switch (get_key_type(secret)) {
1791512cbf1dSJens Wiklander 		case PKCS11_CKK_AES:
1792512cbf1dSJens Wiklander 		case PKCS11_CKK_GENERIC_SECRET:
1793512cbf1dSJens Wiklander 		case PKCS11_CKK_MD5_HMAC:
1794512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA_1_HMAC:
1795512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA224_HMAC:
1796512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA256_HMAC:
1797512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA384_HMAC:
1798512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA512_HMAC:
1799512cbf1dSJens Wiklander 			break;
1800512cbf1dSJens Wiklander 		default:
1801512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1802512cbf1dSJens Wiklander 		}
1803512cbf1dSJens Wiklander 
1804512cbf1dSJens Wiklander 		/* Get key size */
1805512cbf1dSJens Wiklander 		rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN,
1806512cbf1dSJens Wiklander 				       &key_length);
1807512cbf1dSJens Wiklander 		if (rc)
1808d1d44372SRuchika Gupta 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
1809512cbf1dSJens Wiklander 	}
1810013934d8SVesa Jääskeläinen 	if (public) {
1811013934d8SVesa Jääskeläinen 		switch (get_key_type(public)) {
181286922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
181386922832SVesa Jääskeläinen 			/* Get key size */
181486922832SVesa Jääskeläinen 			rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS,
181586922832SVesa Jääskeläinen 					       &key_length);
181686922832SVesa Jääskeläinen 			if (rc)
181786922832SVesa Jääskeläinen 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
181886922832SVesa Jääskeläinen 			key_length = ROUNDUP(key_length, 8) / 8;
181986922832SVesa Jääskeläinen 			break;
182002b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
182103e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
182202b16804SVesa Jääskeläinen 			break;
1823013934d8SVesa Jääskeläinen 		default:
1824013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1825013934d8SVesa Jääskeläinen 		}
1826013934d8SVesa Jääskeläinen 	}
1827013934d8SVesa Jääskeläinen 	if (private) {
1828013934d8SVesa Jääskeläinen 		switch (get_key_type(private)) {
182986922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
183002b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
183103e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
183202b16804SVesa Jääskeläinen 			break;
1833013934d8SVesa Jääskeläinen 		default:
1834013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1835013934d8SVesa Jääskeläinen 		}
1836013934d8SVesa Jääskeläinen 	}
1837512cbf1dSJens Wiklander 
183802b16804SVesa Jääskeläinen 	/*
183902b16804SVesa Jääskeläinen 	 * Check key size for symmetric keys and RSA keys
184002b16804SVesa Jääskeläinen 	 * EC is bound to domains, no need to check here.
184102b16804SVesa Jääskeläinen 	 */
184202b16804SVesa Jääskeläinen 	switch (get_key_type(key1)) {
184302b16804SVesa Jääskeläinen 	case PKCS11_CKK_EC:
184403e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
184502b16804SVesa Jääskeläinen 		return PKCS11_CKR_OK;
184602b16804SVesa Jääskeläinen 	default:
184702b16804SVesa Jääskeläinen 		break;
184802b16804SVesa Jääskeläinen 	}
184902b16804SVesa Jääskeläinen 
1850512cbf1dSJens Wiklander 	get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size);
1851512cbf1dSJens Wiklander 	if (key_length < min_key_size || key_length > max_key_size) {
1852512cbf1dSJens Wiklander 		EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]",
1853512cbf1dSJens Wiklander 		     key_length, min_key_size, max_key_size);
1854512cbf1dSJens Wiklander 
1855512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_SIZE_RANGE;
1856512cbf1dSJens Wiklander 	}
1857512cbf1dSJens Wiklander 
185849ed60abSRuchika Gupta 	if (secret && get_key_type(secret) == PKCS11_CKK_AES) {
185949ed60abSRuchika Gupta 		if (key_length != 16 && key_length != 24 && key_length != 32)
186049ed60abSRuchika Gupta 			return PKCS11_CKR_KEY_SIZE_RANGE;
186149ed60abSRuchika Gupta 	}
186249ed60abSRuchika Gupta 
1863512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1864512cbf1dSJens Wiklander }
1865512cbf1dSJens Wiklander 
1866512cbf1dSJens Wiklander /* Check processing ID against attribute ALLOWED_MECHANISMS if any */
1867512cbf1dSJens Wiklander static bool parent_key_complies_allowed_processings(uint32_t proc_id,
1868512cbf1dSJens Wiklander 						    struct obj_attrs *head)
1869512cbf1dSJens Wiklander {
1870512cbf1dSJens Wiklander 	char *attr = NULL;
1871512cbf1dSJens Wiklander 	uint32_t size = 0;
1872512cbf1dSJens Wiklander 	uint32_t proc = 0;
1873512cbf1dSJens Wiklander 	size_t count = 0;
18746a760c9eSEtienne Carriere 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1875512cbf1dSJens Wiklander 
18766a760c9eSEtienne Carriere 	rc = get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS,
18776a760c9eSEtienne Carriere 			       (void *)&attr, &size);
18786a760c9eSEtienne Carriere 	if (rc == PKCS11_RV_NOT_FOUND)
1879512cbf1dSJens Wiklander 		return true;
18806a760c9eSEtienne Carriere 	if (rc) {
18816a760c9eSEtienne Carriere 		EMSG("unexpected attributes state");
18826a760c9eSEtienne Carriere 		TEE_Panic(TEE_ERROR_BAD_STATE);
1883512cbf1dSJens Wiklander 	}
1884512cbf1dSJens Wiklander 
1885512cbf1dSJens Wiklander 	for (count = size / sizeof(uint32_t); count; count--) {
1886512cbf1dSJens Wiklander 		TEE_MemMove(&proc, attr, sizeof(uint32_t));
1887512cbf1dSJens Wiklander 		attr += sizeof(uint32_t);
1888512cbf1dSJens Wiklander 
1889512cbf1dSJens Wiklander 		if (proc == proc_id)
1890512cbf1dSJens Wiklander 			return true;
1891512cbf1dSJens Wiklander 	}
1892512cbf1dSJens Wiklander 
1893512cbf1dSJens Wiklander 	DMSG("can't find %s in allowed list", id2str_proc(proc_id));
1894512cbf1dSJens Wiklander 	return false;
1895512cbf1dSJens Wiklander }
1896512cbf1dSJens Wiklander 
1897512cbf1dSJens Wiklander static enum pkcs11_attr_id func_to_attr(enum processing_func func)
1898512cbf1dSJens Wiklander {
1899512cbf1dSJens Wiklander 	switch (func) {
1900512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
1901512cbf1dSJens Wiklander 		return PKCS11_CKA_ENCRYPT;
1902512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
1903512cbf1dSJens Wiklander 		return PKCS11_CKA_DECRYPT;
1904512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
1905512cbf1dSJens Wiklander 		return PKCS11_CKA_SIGN;
1906512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
1907512cbf1dSJens Wiklander 		return PKCS11_CKA_VERIFY;
1908512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
1909512cbf1dSJens Wiklander 		return PKCS11_CKA_WRAP;
1910512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
1911512cbf1dSJens Wiklander 		return PKCS11_CKA_UNWRAP;
1912512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
1913512cbf1dSJens Wiklander 		return PKCS11_CKA_DERIVE;
1914512cbf1dSJens Wiklander 	default:
1915512cbf1dSJens Wiklander 		return PKCS11_CKA_UNDEFINED_ID;
1916512cbf1dSJens Wiklander 	}
1917512cbf1dSJens Wiklander }
1918512cbf1dSJens Wiklander 
1919512cbf1dSJens Wiklander enum pkcs11_rc
1920512cbf1dSJens Wiklander check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
1921512cbf1dSJens Wiklander 				      enum processing_func function,
1922512cbf1dSJens Wiklander 				      struct obj_attrs *head)
1923512cbf1dSJens Wiklander {
1924512cbf1dSJens Wiklander 	enum pkcs11_class_id key_class = get_class(head);
1925512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(head);
1926512cbf1dSJens Wiklander 	enum pkcs11_attr_id attr = func_to_attr(function);
1927512cbf1dSJens Wiklander 
1928512cbf1dSJens Wiklander 	if (!get_bool(head, attr)) {
1929512cbf1dSJens Wiklander 		DMSG("%s not permitted", id2str_attr(attr));
1930512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1931512cbf1dSJens Wiklander 	}
1932512cbf1dSJens Wiklander 
1933512cbf1dSJens Wiklander 	/* Check processing complies with parent key family */
1934512cbf1dSJens Wiklander 	switch (proc_id) {
1935512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
1936512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
1937512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
1938512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
19390ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC:
19400ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC_GENERAL:
1941512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1942512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1943512cbf1dSJens Wiklander 			break;
1944512cbf1dSJens Wiklander 
1945512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1946512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1947512cbf1dSJens Wiklander 
19485f80f270SRuchika Gupta 		if (function == PKCS11_FUNCTION_WRAP)
19495f80f270SRuchika Gupta 			return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1950e3f0cb56SRuchika Gupta 		else if (function == PKCS11_FUNCTION_UNWRAP)
1951e3f0cb56SRuchika Gupta 			return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
19525f80f270SRuchika Gupta 		else
1953512cbf1dSJens Wiklander 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1954512cbf1dSJens Wiklander 
1955c3033708SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
1956c3033708SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
1957c3033708SRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY &&
1958c3033708SRuchika Gupta 		    key_type != PKCS11_CKK_AES)
1959c3033708SRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1960c3033708SRuchika Gupta 
1961c3033708SRuchika Gupta 		if (get_bool(head, PKCS11_CKA_ENCRYPT)) {
1962c3033708SRuchika Gupta 			/*
1963c3033708SRuchika Gupta 			 * Intentionally refuse to proceed despite
1964c3033708SRuchika Gupta 			 * PKCS#11 specifications v2.40 and v3.0 not expecting
1965c3033708SRuchika Gupta 			 * this behavior to avoid potential security issue
1966c3033708SRuchika Gupta 			 * where keys derived by these mechanisms can be
1967c3033708SRuchika Gupta 			 * revealed by doing data encryption using parent key.
1968c3033708SRuchika Gupta 			 */
1969c3033708SRuchika Gupta 			return PKCS11_CKR_FUNCTION_FAILED;
1970c3033708SRuchika Gupta 		}
1971c3033708SRuchika Gupta 
1972c3033708SRuchika Gupta 		break;
1973689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
1974689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
1975689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
1976689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
1977689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
1978689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
197970b6683bSVictor Chong 	case PKCS11_CKM_MD5_HMAC_GENERAL:
198070b6683bSVictor Chong 	case PKCS11_CKM_SHA_1_HMAC_GENERAL:
198170b6683bSVictor Chong 	case PKCS11_CKM_SHA224_HMAC_GENERAL:
198270b6683bSVictor Chong 	case PKCS11_CKM_SHA256_HMAC_GENERAL:
198370b6683bSVictor Chong 	case PKCS11_CKM_SHA384_HMAC_GENERAL:
198470b6683bSVictor Chong 	case PKCS11_CKM_SHA512_HMAC_GENERAL:
1985689f4e5bSRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY)
1986689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1987689f4e5bSRuchika Gupta 
1988689f4e5bSRuchika Gupta 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
1989689f4e5bSRuchika Gupta 			break;
1990689f4e5bSRuchika Gupta 
1991689f4e5bSRuchika Gupta 		switch (proc_id) {
1992689f4e5bSRuchika Gupta 		case PKCS11_CKM_MD5_HMAC:
199370b6683bSVictor Chong 		case PKCS11_CKM_MD5_HMAC_GENERAL:
1994689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_MD5_HMAC)
1995689f4e5bSRuchika Gupta 				break;
1996689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1997689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA_1_HMAC:
199870b6683bSVictor Chong 		case PKCS11_CKM_SHA_1_HMAC_GENERAL:
1999689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA_1_HMAC)
2000689f4e5bSRuchika Gupta 				break;
2001689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2002689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA224_HMAC:
200370b6683bSVictor Chong 		case PKCS11_CKM_SHA224_HMAC_GENERAL:
2004689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA224_HMAC)
2005689f4e5bSRuchika Gupta 				break;
2006689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2007689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA256_HMAC:
200870b6683bSVictor Chong 		case PKCS11_CKM_SHA256_HMAC_GENERAL:
2009689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA256_HMAC)
2010689f4e5bSRuchika Gupta 				break;
2011689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2012689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA384_HMAC:
201370b6683bSVictor Chong 		case PKCS11_CKM_SHA384_HMAC_GENERAL:
2014689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA384_HMAC)
2015689f4e5bSRuchika Gupta 				break;
2016689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2017689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA512_HMAC:
201870b6683bSVictor Chong 		case PKCS11_CKM_SHA512_HMAC_GENERAL:
2019689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA512_HMAC)
2020689f4e5bSRuchika Gupta 				break;
2021689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2022689f4e5bSRuchika Gupta 		default:
2023689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2024689f4e5bSRuchika Gupta 		}
2025689f4e5bSRuchika Gupta 		break;
2026689f4e5bSRuchika Gupta 
202703e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
202803e07432SValerii Chubar 		if (key_type != PKCS11_CKK_EC_EDWARDS) {
202903e07432SValerii Chubar 			EMSG("Invalid key %s for mechanism %s",
203003e07432SValerii Chubar 			     id2str_type(key_type, key_class),
203103e07432SValerii Chubar 			     id2str_proc(proc_id));
203203e07432SValerii Chubar 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
203303e07432SValerii Chubar 		}
203403e07432SValerii Chubar 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
203503e07432SValerii Chubar 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
203603e07432SValerii Chubar 			EMSG("Invalid key class for mechanism %s",
203703e07432SValerii Chubar 			     id2str_proc(proc_id));
203803e07432SValerii Chubar 
203903e07432SValerii Chubar 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
204003e07432SValerii Chubar 		}
204103e07432SValerii Chubar 		break;
204203e07432SValerii Chubar 
2043fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
2044fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
2045fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
2046fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
2047fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
2048fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
2049cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
2050fb279d8bSVesa Jääskeläinen 		if (key_type != PKCS11_CKK_EC) {
2051fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
2052fb279d8bSVesa Jääskeläinen 			     id2str_type(key_type, key_class),
2053fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2054fb279d8bSVesa Jääskeläinen 
2055fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
2056fb279d8bSVesa Jääskeläinen 		}
2057fb279d8bSVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
2058fb279d8bSVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
2059fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
2060fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2061fb279d8bSVesa Jääskeläinen 
2062fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2063fb279d8bSVesa Jääskeläinen 		}
2064fb279d8bSVesa Jääskeläinen 		break;
20650442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
20660442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
20670442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
20680442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
20690442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
20700442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
20710442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
207245d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
2073dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
2074d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
2075d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
2076d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
2077d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
2078d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
2079d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
20800442c956SVesa Jääskeläinen 		if (key_type != PKCS11_CKK_RSA) {
20810442c956SVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
20820442c956SVesa Jääskeläinen 			     id2str_type(key_type, key_class),
20830442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20840442c956SVesa Jääskeläinen 
20850442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
20860442c956SVesa Jääskeläinen 		}
20870442c956SVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
20880442c956SVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
20890442c956SVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
20900442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20910442c956SVesa Jääskeläinen 
20920442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
20930442c956SVesa Jääskeläinen 		}
20940442c956SVesa Jääskeläinen 		break;
2095512cbf1dSJens Wiklander 	default:
2096512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
2097512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
2098512cbf1dSJens Wiklander 
2099512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
2100512cbf1dSJens Wiklander 	}
2101512cbf1dSJens Wiklander 
2102512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
2103512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
2104512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2105512cbf1dSJens Wiklander 	}
2106512cbf1dSJens Wiklander 
2107512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
2108512cbf1dSJens Wiklander }
2109783c1515SRuchika Gupta 
2110783c1515SRuchika Gupta bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
2111783c1515SRuchika Gupta 			     struct pkcs11_object *obj)
2112783c1515SRuchika Gupta {
2113783c1515SRuchika Gupta 	uint8_t boolval = 0;
2114783c1515SRuchika Gupta 	uint32_t boolsize = 0;
2115783c1515SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2116783c1515SRuchika Gupta 	enum pkcs11_class_id key_class = get_class(obj->attributes);
2117783c1515SRuchika Gupta 
2118981966bcSVesa Jääskeläinen 	if (attribute_is_hidden(req_attr))
2119981966bcSVesa Jääskeläinen 		return false;
2120981966bcSVesa Jääskeläinen 
2121783c1515SRuchika Gupta 	if (key_class != PKCS11_CKO_SECRET_KEY &&
2122783c1515SRuchika Gupta 	    key_class != PKCS11_CKO_PRIVATE_KEY)
2123783c1515SRuchika Gupta 		return true;
2124783c1515SRuchika Gupta 
2125783c1515SRuchika Gupta 	switch (req_attr->id) {
2126783c1515SRuchika Gupta 	case PKCS11_CKA_PRIVATE_EXPONENT:
2127783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_1:
2128783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_2:
2129783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_1:
2130783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_2:
2131783c1515SRuchika Gupta 	case PKCS11_CKA_COEFFICIENT:
2132783c1515SRuchika Gupta 	case PKCS11_CKA_VALUE:
2133783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2134783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
2135783c1515SRuchika Gupta 				   &boolval, &boolsize);
2136783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_FALSE)
2137783c1515SRuchika Gupta 			return false;
2138783c1515SRuchika Gupta 
2139783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2140783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
2141783c1515SRuchika Gupta 				   &boolval, &boolsize);
2142783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_TRUE)
2143783c1515SRuchika Gupta 			return false;
2144783c1515SRuchika Gupta 		break;
2145783c1515SRuchika Gupta 	default:
2146783c1515SRuchika Gupta 		break;
2147783c1515SRuchika Gupta 	}
2148783c1515SRuchika Gupta 
2149783c1515SRuchika Gupta 	return true;
2150783c1515SRuchika Gupta }
21512d25a9bcSRuchika Gupta 
21522d25a9bcSRuchika Gupta static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr)
21532d25a9bcSRuchika Gupta {
21542d25a9bcSRuchika Gupta 	switch (attr->id) {
21552d25a9bcSRuchika Gupta 	case PKCS11_CKA_ID:
21562d25a9bcSRuchika Gupta 	case PKCS11_CKA_START_DATE:
21572d25a9bcSRuchika Gupta 	case PKCS11_CKA_END_DATE:
21582d25a9bcSRuchika Gupta 	case PKCS11_CKA_DERIVE:
21592d25a9bcSRuchika Gupta 		return true;
21602d25a9bcSRuchika Gupta 	default:
21612d25a9bcSRuchika Gupta 		return false;
21622d25a9bcSRuchika Gupta 	}
21632d25a9bcSRuchika Gupta }
21642d25a9bcSRuchika Gupta 
21652d25a9bcSRuchika Gupta static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr,
21662d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21672d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj)
21682d25a9bcSRuchika Gupta {
21692d25a9bcSRuchika Gupta 	switch (attr->id) {
21702d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
21712d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
21722d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
21732d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
21742d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
21752d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
21762d25a9bcSRuchika Gupta 		return true;
21772d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
21782d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
21792d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
21802d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
21812d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
21822d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
21832d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
21842d25a9bcSRuchika Gupta 	/* Change in CKA_TRUSTED can only be done by SO */
21852d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
21862d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
21872d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
21882d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
21892d25a9bcSRuchika Gupta 		return false;
21902d25a9bcSRuchika Gupta 	default:
21912d25a9bcSRuchika Gupta 		return false;
21922d25a9bcSRuchika Gupta 	}
21932d25a9bcSRuchika Gupta }
21942d25a9bcSRuchika Gupta 
21952d25a9bcSRuchika Gupta static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr,
21962d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21972d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj __unused)
21982d25a9bcSRuchika Gupta {
21992d25a9bcSRuchika Gupta 	switch (attr->id) {
22002d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22012d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
22022d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
22032d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY_RECOVER:
22042d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
22052d25a9bcSRuchika Gupta 		return true;
22062d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
22072d25a9bcSRuchika Gupta 		/* Change in CKA_TRUSTED can only be done by SO */
22082d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
22092d25a9bcSRuchika Gupta 	default:
22102d25a9bcSRuchika Gupta 		return false;
22112d25a9bcSRuchika Gupta 	}
22122d25a9bcSRuchika Gupta }
22132d25a9bcSRuchika Gupta 
22142d25a9bcSRuchika Gupta static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr,
22152d25a9bcSRuchika Gupta 					   struct pkcs11_session *sess __unused,
22162d25a9bcSRuchika Gupta 					   struct pkcs11_object *obj)
22172d25a9bcSRuchika Gupta {
22182d25a9bcSRuchika Gupta 	switch (attr->id) {
22192d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
22202d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
22212d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
22222d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN_RECOVER:
22232d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
22242d25a9bcSRuchika Gupta 	/*
22252d25a9bcSRuchika Gupta 	 * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO
22262d25a9bcSRuchika Gupta 	 * Specification mentions that if this attribute is
22272d25a9bcSRuchika Gupta 	 * supplied as part of a template for C_CreateObject, C_CopyObject or
22282d25a9bcSRuchika Gupta 	 * C_SetAttributeValue for a private key, the token MUST verify
22292d25a9bcSRuchika Gupta 	 * correspondence between the private key data and the public key data
22302d25a9bcSRuchika Gupta 	 * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be
22312d25a9bcSRuchika Gupta 	 * taken care of when this object type will be implemented
22322d25a9bcSRuchika Gupta 	 */
22332d25a9bcSRuchika Gupta 	case PKCS11_CKA_PUBLIC_KEY_INFO:
22342d25a9bcSRuchika Gupta 		return true;
22352d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
22362d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
22372d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
22382d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
22392d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
22402d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
22412d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
22422d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
22432d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
22442d25a9bcSRuchika Gupta 		return false;
22452d25a9bcSRuchika Gupta 	default:
22462d25a9bcSRuchika Gupta 		return false;
22472d25a9bcSRuchika Gupta 	}
22482d25a9bcSRuchika Gupta }
22492d25a9bcSRuchika Gupta 
22504137952dSVesa Jääskeläinen static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr,
22514137952dSVesa Jääskeläinen 					   struct pkcs11_session *session,
22524137952dSVesa Jääskeläinen 					   struct pkcs11_object *obj)
22534137952dSVesa Jääskeläinen {
22544137952dSVesa Jääskeläinen 	uint8_t boolval = 0;
22554137952dSVesa Jääskeläinen 	uint32_t boolsize = 0;
22564137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
22574137952dSVesa Jääskeläinen 
22584137952dSVesa Jääskeläinen 	/* Trusted certificates cannot be modified. */
22594137952dSVesa Jääskeläinen 	rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED,
22604137952dSVesa Jääskeläinen 			   &boolval, &boolsize);
22614137952dSVesa Jääskeläinen 	if (rc || boolval == PKCS11_TRUE)
22624137952dSVesa Jääskeläinen 		return false;
22634137952dSVesa Jääskeläinen 
22644137952dSVesa Jääskeläinen 	/* Common certificate attributes */
22654137952dSVesa Jääskeläinen 	switch (attr->id) {
22664137952dSVesa Jääskeläinen 	case PKCS11_CKA_TRUSTED:
22674137952dSVesa Jääskeläinen 		/*
22684137952dSVesa Jääskeläinen 		 * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an
22694137952dSVesa Jääskeläinen 		 * application. It MUST be set by a token initialization
22704137952dSVesa Jääskeläinen 		 * application or by the token’s SO.
22714137952dSVesa Jääskeläinen 		 */
22724137952dSVesa Jääskeläinen 		return pkcs11_session_is_so(session);
22734137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_TYPE:
22744137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_CATEGORY:
22754137952dSVesa Jääskeläinen 		return false;
22764137952dSVesa Jääskeläinen 	default:
22774137952dSVesa Jääskeläinen 		break;
22784137952dSVesa Jääskeläinen 	}
22794137952dSVesa Jääskeläinen 
22804137952dSVesa Jääskeläinen 	/* Certificate type specific attributes */
22814137952dSVesa Jääskeläinen 	switch (get_certificate_type(obj->attributes)) {
22824137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
22834137952dSVesa Jääskeläinen 		/*
22844137952dSVesa Jääskeläinen 		 * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER
22854137952dSVesa Jääskeläinen 		 * attributes may be modified after the object is created.
22864137952dSVesa Jääskeläinen 		 */
22874137952dSVesa Jääskeläinen 		switch (attr->id) {
22884137952dSVesa Jääskeläinen 		case PKCS11_CKA_ID:
22894137952dSVesa Jääskeläinen 		case PKCS11_CKA_ISSUER:
22904137952dSVesa Jääskeläinen 		case PKCS11_CKA_SERIAL_NUMBER:
22914137952dSVesa Jääskeläinen 			return true;
22924137952dSVesa Jääskeläinen 		default:
22934137952dSVesa Jääskeläinen 			break;
22944137952dSVesa Jääskeläinen 		}
22954137952dSVesa Jääskeläinen 		break;
22964137952dSVesa Jääskeläinen 	default:
22974137952dSVesa Jääskeläinen 		/* Unsupported certificate type */
22984137952dSVesa Jääskeläinen 		break;
22994137952dSVesa Jääskeläinen 	}
23004137952dSVesa Jääskeläinen 
23014137952dSVesa Jääskeläinen 	return false;
23024137952dSVesa Jääskeläinen }
23034137952dSVesa Jääskeläinen 
23042d25a9bcSRuchika Gupta static bool attribute_is_modifiable(struct pkcs11_session *session,
23052d25a9bcSRuchika Gupta 				    struct pkcs11_attribute_head *req_attr,
23062d25a9bcSRuchika Gupta 				    struct pkcs11_object *obj,
23072d25a9bcSRuchika Gupta 				    enum pkcs11_class_id class,
23082d25a9bcSRuchika Gupta 				    enum processing_func function)
23092d25a9bcSRuchika Gupta {
23102d25a9bcSRuchika Gupta 	/* Check modifiable attributes common to any object */
23112d25a9bcSRuchika Gupta 	switch (req_attr->id) {
23122d25a9bcSRuchika Gupta 	case PKCS11_CKA_LABEL:
23132d25a9bcSRuchika Gupta 		return true;
23142d25a9bcSRuchika Gupta 	case PKCS11_CKA_TOKEN:
23152d25a9bcSRuchika Gupta 	case PKCS11_CKA_MODIFIABLE:
23162d25a9bcSRuchika Gupta 	case PKCS11_CKA_DESTROYABLE:
23172d25a9bcSRuchika Gupta 	case PKCS11_CKA_PRIVATE:
23182d25a9bcSRuchika Gupta 		return function == PKCS11_FUNCTION_COPY;
23192d25a9bcSRuchika Gupta 	case PKCS11_CKA_COPYABLE:
23202d25a9bcSRuchika Gupta 		/*
23212d25a9bcSRuchika Gupta 		 * Specification mentions that if the attribute value is false
23222d25a9bcSRuchika Gupta 		 * it can't be set to true. Reading this we assume that it
23232d25a9bcSRuchika Gupta 		 * should be possible to modify this attribute even though this
23242d25a9bcSRuchika Gupta 		 * is not marked as modifiable in Table 10 if done in right
23252d25a9bcSRuchika Gupta 		 * direction i.e from TRUE -> FALSE.
23262d25a9bcSRuchika Gupta 		 */
23272d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, req_attr->id);
23282d25a9bcSRuchika Gupta 	default:
23292d25a9bcSRuchika Gupta 		break;
23302d25a9bcSRuchika Gupta 	}
23312d25a9bcSRuchika Gupta 
23322d25a9bcSRuchika Gupta 	/* Attribute checking based on class type */
23332d25a9bcSRuchika Gupta 	switch (class) {
23342d25a9bcSRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
23352d25a9bcSRuchika Gupta 	case PKCS11_CKO_PUBLIC_KEY:
23362d25a9bcSRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
23372d25a9bcSRuchika Gupta 		if (attr_is_modifiable_any_key(req_attr))
23382d25a9bcSRuchika Gupta 			return true;
23392d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_SECRET_KEY &&
23402d25a9bcSRuchika Gupta 		    attr_is_modifiable_secret_key(req_attr, session, obj))
23412d25a9bcSRuchika Gupta 			return true;
23422d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PUBLIC_KEY &&
23432d25a9bcSRuchika Gupta 		    attr_is_modifiable_public_key(req_attr, session, obj))
23442d25a9bcSRuchika Gupta 			return true;
23452d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PRIVATE_KEY &&
23462d25a9bcSRuchika Gupta 		    attr_is_modifiable_private_key(req_attr, session, obj))
23472d25a9bcSRuchika Gupta 			return true;
23482d25a9bcSRuchika Gupta 		break;
23492d25a9bcSRuchika Gupta 	case PKCS11_CKO_DATA:
23502d25a9bcSRuchika Gupta 		/* None of the data object attributes are modifiable */
23512d25a9bcSRuchika Gupta 		return false;
23524137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
23534137952dSVesa Jääskeläinen 		return attr_is_modifiable_certificate(req_attr, session, obj);
23542d25a9bcSRuchika Gupta 	default:
23552d25a9bcSRuchika Gupta 		break;
23562d25a9bcSRuchika Gupta 	}
23572d25a9bcSRuchika Gupta 
23582d25a9bcSRuchika Gupta 	return false;
23592d25a9bcSRuchika Gupta }
23602d25a9bcSRuchika Gupta 
23612d25a9bcSRuchika Gupta enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session,
23622d25a9bcSRuchika Gupta 						struct obj_attrs *head,
23632d25a9bcSRuchika Gupta 						struct pkcs11_object *obj,
23642d25a9bcSRuchika Gupta 						enum processing_func function)
23652d25a9bcSRuchika Gupta {
23662d25a9bcSRuchika Gupta 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
23672d25a9bcSRuchika Gupta 	char *cur = NULL;
23682d25a9bcSRuchika Gupta 	char *end = NULL;
23692d25a9bcSRuchika Gupta 	size_t len = 0;
23702d25a9bcSRuchika Gupta 
23712d25a9bcSRuchika Gupta 	class = get_class(obj->attributes);
23722d25a9bcSRuchika Gupta 
23732d25a9bcSRuchika Gupta 	cur = (char *)head + sizeof(struct obj_attrs);
23742d25a9bcSRuchika Gupta 	end = cur + head->attrs_size;
23752d25a9bcSRuchika Gupta 
23762d25a9bcSRuchika Gupta 	for (; cur < end; cur += len) {
23772d25a9bcSRuchika Gupta 		/* Structure aligned copy of the pkcs11_ref in the object */
23782d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head cli_ref = { };
23792d25a9bcSRuchika Gupta 
23802d25a9bcSRuchika Gupta 		TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
23812d25a9bcSRuchika Gupta 		len = sizeof(cli_ref) + cli_ref.size;
23822d25a9bcSRuchika Gupta 
2383981966bcSVesa Jääskeläinen 		/* Protect hidden attributes */
2384981966bcSVesa Jääskeläinen 		if (attribute_is_hidden(&cli_ref))
2385981966bcSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
2386981966bcSVesa Jääskeläinen 
23872d25a9bcSRuchika Gupta 		/*
23882d25a9bcSRuchika Gupta 		 * Check 1 - Check if attribute belongs to the object
23892d25a9bcSRuchika Gupta 		 * The obj->attributes has all the attributes in
23902d25a9bcSRuchika Gupta 		 * it which are allowed for an object.
23912d25a9bcSRuchika Gupta 		 */
23922d25a9bcSRuchika Gupta 		if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL,
23932d25a9bcSRuchika Gupta 				      NULL) == PKCS11_RV_NOT_FOUND)
23942d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
23952d25a9bcSRuchika Gupta 
23962d25a9bcSRuchika Gupta 		/* Check 2 - Is attribute modifiable */
23972d25a9bcSRuchika Gupta 		if (!attribute_is_modifiable(session, &cli_ref, obj, class,
23982d25a9bcSRuchika Gupta 					     function))
23992d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_READ_ONLY;
24002d25a9bcSRuchika Gupta 
24012d25a9bcSRuchika Gupta 		/*
24022d25a9bcSRuchika Gupta 		 * Checks for modification in PKCS11_CKA_TOKEN and
24032d25a9bcSRuchika Gupta 		 * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY
24042d25a9bcSRuchika Gupta 		 * only, so skip them for PKCS11_FUNCTION_MODIFY.
24052d25a9bcSRuchika Gupta 		 */
24062d25a9bcSRuchika Gupta 		if (function == PKCS11_FUNCTION_MODIFY)
24072d25a9bcSRuchika Gupta 			continue;
24082d25a9bcSRuchika Gupta 
24092d25a9bcSRuchika Gupta 		/*
24102d25a9bcSRuchika Gupta 		 * An attempt to copy an object to a token will fail for
24112d25a9bcSRuchika Gupta 		 * RO session
24122d25a9bcSRuchika Gupta 		 */
24132d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_TOKEN &&
24142d25a9bcSRuchika Gupta 		    get_bool(head, PKCS11_CKA_TOKEN)) {
24152d25a9bcSRuchika Gupta 			if (!pkcs11_session_is_read_write(session)) {
24162d25a9bcSRuchika Gupta 				DMSG("Can't copy to token in a RO session");
24172d25a9bcSRuchika Gupta 				return PKCS11_CKR_SESSION_READ_ONLY;
24182d25a9bcSRuchika Gupta 			}
24192d25a9bcSRuchika Gupta 		}
24202d25a9bcSRuchika Gupta 
24212d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_PRIVATE) {
24222d25a9bcSRuchika Gupta 			bool parent_priv =
24232d25a9bcSRuchika Gupta 				get_bool(obj->attributes, cli_ref.id);
24242d25a9bcSRuchika Gupta 			bool obj_priv = get_bool(head, cli_ref.id);
24252d25a9bcSRuchika Gupta 
24262d25a9bcSRuchika Gupta 			/*
24272d25a9bcSRuchika Gupta 			 * If PKCS11_CKA_PRIVATE is being set to TRUE from
24282d25a9bcSRuchika Gupta 			 * FALSE, user has to be logged in
24292d25a9bcSRuchika Gupta 			 */
24302d25a9bcSRuchika Gupta 			if (!parent_priv && obj_priv) {
24312d25a9bcSRuchika Gupta 				if ((pkcs11_session_is_public(session) ||
24322d25a9bcSRuchika Gupta 				     pkcs11_session_is_so(session)))
24332d25a9bcSRuchika Gupta 					return PKCS11_CKR_USER_NOT_LOGGED_IN;
24342d25a9bcSRuchika Gupta 			}
2435df017b2bSRuchika Gupta 
2436df017b2bSRuchika Gupta 			/*
2437df017b2bSRuchika Gupta 			 * Restriction added - Even for Copy, do not allow
2438df017b2bSRuchika Gupta 			 * modification of CKA_PRIVATE from TRUE to FALSE
2439df017b2bSRuchika Gupta 			 */
2440df017b2bSRuchika Gupta 			if (parent_priv && !obj_priv)
2441df017b2bSRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
24422d25a9bcSRuchika Gupta 		}
24432d25a9bcSRuchika Gupta 	}
24442d25a9bcSRuchika Gupta 
24452d25a9bcSRuchika Gupta 	return PKCS11_CKR_OK;
24462d25a9bcSRuchika Gupta }
24478c499324SRuchika Gupta 
24488c499324SRuchika Gupta static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
24498c499324SRuchika Gupta 					  size_t key_size)
24508c499324SRuchika Gupta {
24518c499324SRuchika Gupta 	uint32_t size = sizeof(uint32_t);
24528c499324SRuchika Gupta 	uint32_t key_length = 0;
24538c499324SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
24548c499324SRuchika Gupta 
24558c499324SRuchika Gupta 	/* Get key size if present in template */
24568c499324SRuchika Gupta 	rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size);
24578c499324SRuchika Gupta 	if (rc && rc != PKCS11_RV_NOT_FOUND)
24588c499324SRuchika Gupta 		return rc;
24598c499324SRuchika Gupta 
24608c499324SRuchika Gupta 	if (key_length) {
24618c499324SRuchika Gupta 		if (key_size < key_length)
24628c499324SRuchika Gupta 			return PKCS11_CKR_DATA_LEN_RANGE;
24638c499324SRuchika Gupta 	} else {
24648c499324SRuchika Gupta 		key_length = key_size;
24658c499324SRuchika Gupta 		rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length,
24668c499324SRuchika Gupta 				   sizeof(uint32_t));
24678c499324SRuchika Gupta 		if (rc)
24688c499324SRuchika Gupta 			return rc;
24698c499324SRuchika Gupta 	}
24708c499324SRuchika Gupta 
24718c499324SRuchika Gupta 	/* Now we can check the VALUE_LEN field */
24728c499324SRuchika Gupta 	rc = check_created_attrs(*head, NULL);
24738c499324SRuchika Gupta 	if (rc)
24748c499324SRuchika Gupta 		return rc;
24758c499324SRuchika Gupta 
24768c499324SRuchika Gupta 	/* Remove the default empty value attribute if found */
24778c499324SRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
24788c499324SRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
24798c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
24808c499324SRuchika Gupta 
24818c499324SRuchika Gupta 	return add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
24828c499324SRuchika Gupta }
24838c499324SRuchika Gupta 
248445d40bdaSValerii Chubar static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
248545d40bdaSValerii Chubar 					       void *data,
248645d40bdaSValerii Chubar 					       size_t key_size)
248745d40bdaSValerii Chubar {
248845d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
248945d40bdaSValerii Chubar 	int mbedtls_rc = 0;
249045d40bdaSValerii Chubar 	uint32_t key_bits = 0;
249145d40bdaSValerii Chubar 	uint32_t size = 0;
249245d40bdaSValerii Chubar 	uint32_t buffer_size = 0;
249345d40bdaSValerii Chubar 	void *buffer = NULL;
249445d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
249545d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
249645d40bdaSValerii Chubar 	mbedtls_mpi n = { };
249745d40bdaSValerii Chubar 	mbedtls_mpi e = { };
249845d40bdaSValerii Chubar 	mbedtls_mpi d = { };
249945d40bdaSValerii Chubar 	mbedtls_mpi p = { };
250045d40bdaSValerii Chubar 	mbedtls_mpi q = { };
250145d40bdaSValerii Chubar 
250245d40bdaSValerii Chubar 	rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits);
250345d40bdaSValerii Chubar 	if (rc && rc != PKCS11_RV_NOT_FOUND)
250445d40bdaSValerii Chubar 		return rc;
250545d40bdaSValerii Chubar 
250645d40bdaSValerii Chubar 	if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) ||
250745d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) ||
250845d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) ||
250945d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_1) ||
251045d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_2))
251145d40bdaSValerii Chubar 		return PKCS11_CKR_GENERAL_ERROR;
251245d40bdaSValerii Chubar 
251345d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
251445d40bdaSValerii Chubar 	mbedtls_mpi_init(&n);
251545d40bdaSValerii Chubar 	mbedtls_mpi_init(&e);
251645d40bdaSValerii Chubar 	mbedtls_mpi_init(&d);
251745d40bdaSValerii Chubar 	mbedtls_mpi_init(&p);
251845d40bdaSValerii Chubar 	mbedtls_mpi_init(&q);
251945d40bdaSValerii Chubar 
2520*32b31808SJens Wiklander 	mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size,
2521*32b31808SJens Wiklander 					  NULL, 0, mbd_rand, NULL);
252245d40bdaSValerii Chubar 	if (mbedtls_rc) {
252345d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
252445d40bdaSValerii Chubar 		goto out;
252545d40bdaSValerii Chubar 	}
252645d40bdaSValerii Chubar 
252745d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
252845d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
252945d40bdaSValerii Chubar 	if (mbedtls_rc) {
253045d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
253145d40bdaSValerii Chubar 		goto out;
253245d40bdaSValerii Chubar 	}
253345d40bdaSValerii Chubar 
253445d40bdaSValerii Chubar 	if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) {
253545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
253645d40bdaSValerii Chubar 		goto out;
253745d40bdaSValerii Chubar 	}
253845d40bdaSValerii Chubar 
253945d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8);
254045d40bdaSValerii Chubar 	buffer_size = size;
254145d40bdaSValerii Chubar 	buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
254245d40bdaSValerii Chubar 	if (!buffer) {
254345d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
254445d40bdaSValerii Chubar 		goto out;
254545d40bdaSValerii Chubar 	}
254645d40bdaSValerii Chubar 
254745d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size);
254845d40bdaSValerii Chubar 	if (mbedtls_rc) {
254945d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
255045d40bdaSValerii Chubar 		goto out;
255145d40bdaSValerii Chubar 	}
255245d40bdaSValerii Chubar 
255345d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size);
255445d40bdaSValerii Chubar 	if (rc)
255545d40bdaSValerii Chubar 		goto out;
255645d40bdaSValerii Chubar 
255745d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8);
255845d40bdaSValerii Chubar 	if (buffer_size < size) {
255945d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
256045d40bdaSValerii Chubar 		goto out;
256145d40bdaSValerii Chubar 	}
256245d40bdaSValerii Chubar 
256345d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size);
256445d40bdaSValerii Chubar 	if (mbedtls_rc) {
256545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
256645d40bdaSValerii Chubar 		goto out;
256745d40bdaSValerii Chubar 	}
256845d40bdaSValerii Chubar 
256945d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size);
257045d40bdaSValerii Chubar 	if (rc)
257145d40bdaSValerii Chubar 		goto out;
257245d40bdaSValerii Chubar 
257345d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8);
257445d40bdaSValerii Chubar 	if (buffer_size < size) {
257545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
257645d40bdaSValerii Chubar 		goto out;
257745d40bdaSValerii Chubar 	}
257845d40bdaSValerii Chubar 
257945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size);
258045d40bdaSValerii Chubar 	if (mbedtls_rc) {
258145d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
258245d40bdaSValerii Chubar 		goto out;
258345d40bdaSValerii Chubar 	}
258445d40bdaSValerii Chubar 
258545d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size);
258645d40bdaSValerii Chubar 	if (rc)
258745d40bdaSValerii Chubar 		goto out;
258845d40bdaSValerii Chubar 
258945d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8);
259045d40bdaSValerii Chubar 	if (buffer_size < size) {
259145d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
259245d40bdaSValerii Chubar 		goto out;
259345d40bdaSValerii Chubar 	}
259445d40bdaSValerii Chubar 
259545d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size);
259645d40bdaSValerii Chubar 	if (mbedtls_rc) {
259745d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
259845d40bdaSValerii Chubar 		goto out;
259945d40bdaSValerii Chubar 	}
260045d40bdaSValerii Chubar 
260145d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size);
260245d40bdaSValerii Chubar 	if (rc)
260345d40bdaSValerii Chubar 		goto out;
260445d40bdaSValerii Chubar 
260545d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8);
260645d40bdaSValerii Chubar 	if (buffer_size < size) {
260745d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
260845d40bdaSValerii Chubar 		goto out;
260945d40bdaSValerii Chubar 	}
261045d40bdaSValerii Chubar 
261145d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size);
261245d40bdaSValerii Chubar 	if (mbedtls_rc) {
261345d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
261445d40bdaSValerii Chubar 		goto out;
261545d40bdaSValerii Chubar 	}
261645d40bdaSValerii Chubar 
261745d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size);
261845d40bdaSValerii Chubar 
261945d40bdaSValerii Chubar out:
262045d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
262145d40bdaSValerii Chubar 	mbedtls_mpi_free(&n);
262245d40bdaSValerii Chubar 	mbedtls_mpi_free(&e);
262345d40bdaSValerii Chubar 	mbedtls_mpi_free(&d);
262445d40bdaSValerii Chubar 	mbedtls_mpi_free(&p);
262545d40bdaSValerii Chubar 	mbedtls_mpi_free(&q);
262645d40bdaSValerii Chubar 	TEE_Free(buffer);
262745d40bdaSValerii Chubar 	return rc;
262845d40bdaSValerii Chubar }
262945d40bdaSValerii Chubar 
26308c499324SRuchika Gupta enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data,
26318c499324SRuchika Gupta 			    size_t key_size)
26328c499324SRuchika Gupta {
26338c499324SRuchika Gupta 	switch (get_class(*head)) {
26348c499324SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
26358c499324SRuchika Gupta 		return set_secret_key_data(head, data, key_size);
263645d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
263745d40bdaSValerii Chubar 		if (get_key_type(*head) == PKCS11_CKK_RSA)
263845d40bdaSValerii Chubar 			return set_private_key_data_rsa(head, data, key_size);
263945d40bdaSValerii Chubar 		break;
26408c499324SRuchika Gupta 	default:
26418c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
26428c499324SRuchika Gupta 	}
264345d40bdaSValerii Chubar 
264445d40bdaSValerii Chubar 	return PKCS11_CKR_GENERAL_ERROR;
26458c499324SRuchika Gupta }
26465e1d94ebSVesa Jääskeläinen 
2647a9aa45d8SValerii Chubar static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
2648a9aa45d8SValerii Chubar 						 void **data, uint32_t *sz)
2649a9aa45d8SValerii Chubar {
2650a9aa45d8SValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2651a9aa45d8SValerii Chubar 	void *buffer = NULL;
2652a9aa45d8SValerii Chubar 	void *value = NULL;
2653a9aa45d8SValerii Chubar 
2654a9aa45d8SValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz);
2655a9aa45d8SValerii Chubar 	if (rc)
2656a9aa45d8SValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
2657a9aa45d8SValerii Chubar 
2658a9aa45d8SValerii Chubar 	buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
2659a9aa45d8SValerii Chubar 	if (!buffer)
2660a9aa45d8SValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
2661a9aa45d8SValerii Chubar 
2662a9aa45d8SValerii Chubar 	TEE_MemMove(buffer, value, *sz);
2663a9aa45d8SValerii Chubar 	*data = buffer;
2664a9aa45d8SValerii Chubar 
2665a9aa45d8SValerii Chubar 	return PKCS11_CKR_OK;
2666a9aa45d8SValerii Chubar }
2667a9aa45d8SValerii Chubar 
266845d40bdaSValerii Chubar static enum pkcs11_rc
266945d40bdaSValerii Chubar encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
267045d40bdaSValerii Chubar {
267145d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
267245d40bdaSValerii Chubar 	int i = 0;
267345d40bdaSValerii Chubar 	int mbedtls_rc = 0;
267445d40bdaSValerii Chubar 	int start = 0;
267545d40bdaSValerii Chubar 	int der_size = 0;
267645d40bdaSValerii Chubar 	void *n = NULL;
267745d40bdaSValerii Chubar 	void *p = NULL;
267845d40bdaSValerii Chubar 	void *q = NULL;
267945d40bdaSValerii Chubar 	void *d = NULL;
268045d40bdaSValerii Chubar 	void *e = NULL;
268145d40bdaSValerii Chubar 	uint32_t n_len = 0;
268245d40bdaSValerii Chubar 	uint32_t p_len = 0;
268345d40bdaSValerii Chubar 	uint32_t q_len = 0;
268445d40bdaSValerii Chubar 	uint32_t d_len = 0;
268545d40bdaSValerii Chubar 	uint32_t e_len = 0;
268645d40bdaSValerii Chubar 	uint8_t *buffer = NULL;
268745d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
268845d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
268945d40bdaSValerii Chubar 	const mbedtls_pk_info_t *pk_info = NULL;
269045d40bdaSValerii Chubar 
269145d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
269245d40bdaSValerii Chubar 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
269345d40bdaSValerii Chubar 	if (mbedtls_pk_setup(&pk, pk_info)) {
269445d40bdaSValerii Chubar 		rc = PKCS11_CKR_GENERAL_ERROR;
269545d40bdaSValerii Chubar 		goto out;
269645d40bdaSValerii Chubar 	}
269745d40bdaSValerii Chubar 
269845d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len);
269945d40bdaSValerii Chubar 	if (rc)
270045d40bdaSValerii Chubar 		goto out;
270145d40bdaSValerii Chubar 
270245d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len);
270345d40bdaSValerii Chubar 	if (rc)
270445d40bdaSValerii Chubar 		goto out;
270545d40bdaSValerii Chubar 
270645d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len);
270745d40bdaSValerii Chubar 	if (rc)
270845d40bdaSValerii Chubar 		goto out;
270945d40bdaSValerii Chubar 
271045d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len);
271145d40bdaSValerii Chubar 	if (rc)
271245d40bdaSValerii Chubar 		goto out;
271345d40bdaSValerii Chubar 
271445d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len);
271545d40bdaSValerii Chubar 	if (rc)
271645d40bdaSValerii Chubar 		goto out;
271745d40bdaSValerii Chubar 
271845d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
271945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
272045d40bdaSValerii Chubar 					    q, q_len, d, d_len, e, e_len);
272145d40bdaSValerii Chubar 	if (mbedtls_rc) {
272245d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
272345d40bdaSValerii Chubar 		goto out;
272445d40bdaSValerii Chubar 	}
272545d40bdaSValerii Chubar 
272645d40bdaSValerii Chubar 	if (mbedtls_rsa_complete(rsa)) {
272745d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
272845d40bdaSValerii Chubar 		goto out;
272945d40bdaSValerii Chubar 	}
273045d40bdaSValerii Chubar 
273145d40bdaSValerii Chubar 	if (mbedtls_rsa_check_privkey(rsa)) {
273245d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
273345d40bdaSValerii Chubar 		goto out;
273445d40bdaSValerii Chubar 	}
273545d40bdaSValerii Chubar 
273645d40bdaSValerii Chubar 	der_size = n_len * 8;
273745d40bdaSValerii Chubar 	buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
273845d40bdaSValerii Chubar 	if (!buffer) {
273945d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
274045d40bdaSValerii Chubar 		goto out;
274145d40bdaSValerii Chubar 	}
274245d40bdaSValerii Chubar 
274345d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size);
274445d40bdaSValerii Chubar 	if (mbedtls_rc < 0) {
274545d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
274645d40bdaSValerii Chubar 		goto out;
274745d40bdaSValerii Chubar 	}
274845d40bdaSValerii Chubar 
274945d40bdaSValerii Chubar 	start = der_size - mbedtls_rc;
275045d40bdaSValerii Chubar 	for (i = 0; i < mbedtls_rc; i++) {
275145d40bdaSValerii Chubar 		buffer[i] = buffer[i + start];
275245d40bdaSValerii Chubar 		buffer[i + start] = 0;
275345d40bdaSValerii Chubar 	}
275445d40bdaSValerii Chubar 
275545d40bdaSValerii Chubar 	*data = buffer;
275645d40bdaSValerii Chubar 	*sz = mbedtls_rc;
275745d40bdaSValerii Chubar out:
275845d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
275945d40bdaSValerii Chubar 
276045d40bdaSValerii Chubar 	if (rc)
276145d40bdaSValerii Chubar 		TEE_Free(buffer);
276245d40bdaSValerii Chubar 
276345d40bdaSValerii Chubar 	return rc;
276445d40bdaSValerii Chubar }
276545d40bdaSValerii Chubar 
2766a9aa45d8SValerii Chubar enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
27675f80f270SRuchika Gupta 				      uint32_t *sz)
27685f80f270SRuchika Gupta {
276945d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
277045d40bdaSValerii Chubar 
27715f80f270SRuchika Gupta 	switch (get_class(head)) {
27725f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
277345d40bdaSValerii Chubar 		rc = alloc_copy_attribute_value(head, data, sz);
277445d40bdaSValerii Chubar 		break;
277545d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
277645d40bdaSValerii Chubar 		if (get_key_type(head) == PKCS11_CKK_RSA)
277745d40bdaSValerii Chubar 			rc = encode_rsa_private_key_der(head, data, sz);
277845d40bdaSValerii Chubar 		break;
27795f80f270SRuchika Gupta 	default:
278045d40bdaSValerii Chubar 		break;
27815f80f270SRuchika Gupta 	}
27825f80f270SRuchika Gupta 
278345d40bdaSValerii Chubar 	return rc;
27845f80f270SRuchika Gupta }
27855f80f270SRuchika Gupta 
27865e1d94ebSVesa Jääskeläinen enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
27875e1d94ebSVesa Jääskeläinen 					struct obj_attrs **priv_head)
27885e1d94ebSVesa Jääskeläinen {
27895e1d94ebSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
27905e1d94ebSVesa Jääskeläinen 	void *id1 = NULL;
27915e1d94ebSVesa Jääskeläinen 	uint32_t id1_size = 0;
27925e1d94ebSVesa Jääskeläinen 	void *id2 = NULL;
27935e1d94ebSVesa Jääskeläinen 	uint32_t id2_size = 0;
27945e1d94ebSVesa Jääskeläinen 
27955e1d94ebSVesa Jääskeläinen 	assert(pub_head);
27965e1d94ebSVesa Jääskeläinen 	assert(priv_head);
27975e1d94ebSVesa Jääskeläinen 
27985e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size);
27995e1d94ebSVesa Jääskeläinen 	if (rc) {
28005e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28015e1d94ebSVesa Jääskeläinen 			return rc;
28025e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28035e1d94ebSVesa Jääskeläinen 	} else if (!id1_size) {
28045e1d94ebSVesa Jääskeläinen 		id1 = NULL;
28055e1d94ebSVesa Jääskeläinen 	}
28065e1d94ebSVesa Jääskeläinen 
28075e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size);
28085e1d94ebSVesa Jääskeläinen 	if (rc) {
28095e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
28105e1d94ebSVesa Jääskeläinen 			return rc;
28115e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28125e1d94ebSVesa Jääskeläinen 	} else if (!id2_size) {
28135e1d94ebSVesa Jääskeläinen 		id2 = NULL;
28145e1d94ebSVesa Jääskeläinen 	}
28155e1d94ebSVesa Jääskeläinen 
28165e1d94ebSVesa Jääskeläinen 	/* Both have value -- let them be what caller has specified them */
28175e1d94ebSVesa Jääskeläinen 	if (id1 && id2)
28185e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28195e1d94ebSVesa Jääskeläinen 
28205e1d94ebSVesa Jääskeläinen 	/* Both are empty -- leave empty values */
28215e1d94ebSVesa Jääskeläinen 	if (!id1 && !id2)
28225e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28235e1d94ebSVesa Jääskeläinen 
28245e1d94ebSVesa Jääskeläinen 	/* Cross copy CKA_ID value */
28255e1d94ebSVesa Jääskeläinen 	if (id1)
28265e1d94ebSVesa Jääskeläinen 		return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size);
28275e1d94ebSVesa Jääskeläinen 	else
28285e1d94ebSVesa Jääskeläinen 		return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size);
28295e1d94ebSVesa Jääskeläinen }
2830