xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 7c24332175d8a3a60264f9de2929fd16591a0e0e)
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>
8*7c243321SVesa Jääskeläinen #include <mbedtls/asn1write.h>
9*7c243321SVesa 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"
24*7c243321SVesa 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 
909196bcd93SRuchika Gupta static enum pkcs11_rc
910*7c243321SVesa Jääskeläinen create_ec_priv_key_hidden_attributes(struct obj_attrs **out,
911*7c243321SVesa Jääskeläinen 				     struct obj_attrs *temp,
912*7c243321SVesa Jääskeläinen 				     enum processing_func function)
913*7c243321SVesa Jääskeläinen {
914*7c243321SVesa Jääskeläinen 	struct mbedtls_ecp_keypair key_pair = { };
915*7c243321SVesa Jääskeläinen 	mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE;
916*7c243321SVesa Jääskeläinen 	size_t buflen = 0;
917*7c243321SVesa Jääskeläinen 	uint8_t *buf = NULL;
918*7c243321SVesa Jääskeläinen 	size_t asnbuflen = 0;
919*7c243321SVesa Jääskeläinen 	uint8_t *asnbuf = NULL;
920*7c243321SVesa Jääskeläinen 	uint8_t *ptr = NULL;
921*7c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
922*7c243321SVesa Jääskeläinen 	int tee_size = 0;
923*7c243321SVesa Jääskeläinen 	int tee_curve = 0;
924*7c243321SVesa Jääskeläinen 	void *a_ptr = NULL;
925*7c243321SVesa Jääskeläinen 	uint32_t a_size = 0;
926*7c243321SVesa Jääskeläinen 	int ret = 0;
927*7c243321SVesa Jääskeläinen 
928*7c243321SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_IMPORT)
929*7c243321SVesa Jääskeläinen 		return PKCS11_CKR_OK;
930*7c243321SVesa Jääskeläinen 
931*7c243321SVesa Jääskeläinen 	/*
932*7c243321SVesa Jääskeläinen 	 * TEE internal API requires that for private key operations there
933*7c243321SVesa Jääskeläinen 	 * needs to be also public key available.
934*7c243321SVesa Jääskeläinen 	 *
935*7c243321SVesa Jääskeläinen 	 * Generate hidden EC point from private key.
936*7c243321SVesa Jääskeläinen 	 */
937*7c243321SVesa Jääskeläinen 
938*7c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS,
939*7c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
940*7c243321SVesa Jääskeläinen 		EMSG("No EC_PARAMS attribute found in private key");
941*7c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
942*7c243321SVesa Jääskeläinen 	}
943*7c243321SVesa Jääskeläinen 
944*7c243321SVesa Jääskeläinen 	/* Just valdiate that curve is found */
945*7c243321SVesa Jääskeläinen 	tee_size = ec_params2tee_keysize(a_ptr, a_size);
946*7c243321SVesa Jääskeläinen 	if (!tee_size) {
947*7c243321SVesa Jääskeläinen 		EMSG("Unsupported EC_PARAMS curve");
948*7c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
949*7c243321SVesa Jääskeläinen 	}
950*7c243321SVesa Jääskeläinen 
951*7c243321SVesa Jääskeläinen 	tee_curve = ec_params2tee_curve(a_ptr, a_size);
952*7c243321SVesa Jääskeläinen 
953*7c243321SVesa Jääskeläinen 	switch (tee_curve) {
954*7c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P192:
955*7c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP192R1;
956*7c243321SVesa Jääskeläinen 		break;
957*7c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P224:
958*7c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP224R1;
959*7c243321SVesa Jääskeläinen 		break;
960*7c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P256:
961*7c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP256R1;
962*7c243321SVesa Jääskeläinen 		break;
963*7c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P384:
964*7c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP384R1;
965*7c243321SVesa Jääskeläinen 		break;
966*7c243321SVesa Jääskeläinen 	case TEE_ECC_CURVE_NIST_P521:
967*7c243321SVesa Jääskeläinen 		ec_curve = MBEDTLS_ECP_DP_SECP521R1;
968*7c243321SVesa Jääskeläinen 		break;
969*7c243321SVesa Jääskeläinen 	default:
970*7c243321SVesa Jääskeläinen 		EMSG("Failed to map EC_PARAMS to supported curve");
971*7c243321SVesa Jääskeläinen 		return PKCS11_CKR_CURVE_NOT_SUPPORTED;
972*7c243321SVesa Jääskeläinen 	}
973*7c243321SVesa Jääskeläinen 
974*7c243321SVesa Jääskeläinen 	if (get_attribute_ptr(temp, PKCS11_CKA_VALUE,
975*7c243321SVesa Jääskeläinen 			      &a_ptr, &a_size) || !a_ptr) {
976*7c243321SVesa Jääskeläinen 		EMSG("No VALUE attribute found in private key");
977*7c243321SVesa Jääskeläinen 		return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
978*7c243321SVesa Jääskeläinen 	}
979*7c243321SVesa Jääskeläinen 
980*7c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_init(&key_pair);
981*7c243321SVesa Jääskeläinen 
982*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size);
983*7c243321SVesa Jääskeläinen 	if (ret) {
984*7c243321SVesa Jääskeläinen 		EMSG("Failed to parse CKA_VALUE");
985*7c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
986*7c243321SVesa Jääskeläinen 		goto out;
987*7c243321SVesa Jääskeläinen 	}
988*7c243321SVesa Jääskeläinen 
989*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_mul(&key_pair.grp, &key_pair.Q, &key_pair.d,
990*7c243321SVesa Jääskeläinen 			      &key_pair.grp.G, NULL, NULL);
991*7c243321SVesa Jääskeläinen 	if (ret) {
992*7c243321SVesa Jääskeläinen 		EMSG("Failed to create public key");
993*7c243321SVesa Jääskeläinen 		goto out;
994*7c243321SVesa Jääskeläinen 	}
995*7c243321SVesa Jääskeläinen 
996*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_check_privkey(&key_pair.grp, &key_pair.d);
997*7c243321SVesa Jääskeläinen 	if (ret) {
998*7c243321SVesa Jääskeläinen 		EMSG("Failed to verify private key");
999*7c243321SVesa Jääskeläinen 		goto out;
1000*7c243321SVesa Jääskeläinen 	}
1001*7c243321SVesa Jääskeläinen 
1002*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_check_pubkey(&key_pair.grp, &key_pair.Q);
1003*7c243321SVesa Jääskeläinen 	if (ret) {
1004*7c243321SVesa Jääskeläinen 		EMSG("Failed to verify public key");
1005*7c243321SVesa Jääskeläinen 		goto out;
1006*7c243321SVesa Jääskeläinen 	}
1007*7c243321SVesa Jääskeläinen 
1008*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_point_write_binary(&key_pair.grp, &key_pair.Q,
1009*7c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
1010*7c243321SVesa Jääskeläinen 					     &buflen, NULL, 0);
1011*7c243321SVesa Jääskeläinen 	if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
1012*7c243321SVesa Jääskeläinen 		EMSG("Failed to determine size of binary public key");
1013*7c243321SVesa Jääskeläinen 		goto out;
1014*7c243321SVesa Jääskeläinen 	}
1015*7c243321SVesa Jääskeläinen 
1016*7c243321SVesa Jääskeläinen 	buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO);
1017*7c243321SVesa Jääskeläinen 	if (!buf) {
1018*7c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
1019*7c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
1020*7c243321SVesa Jääskeläinen 		goto out;
1021*7c243321SVesa Jääskeläinen 	}
1022*7c243321SVesa Jääskeläinen 
1023*7c243321SVesa Jääskeläinen 	asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen;
1024*7c243321SVesa Jääskeläinen 
1025*7c243321SVesa Jääskeläinen 	asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO);
1026*7c243321SVesa Jääskeläinen 	if (!asnbuf) {
1027*7c243321SVesa Jääskeläinen 		EMSG("Failed to allocate memory for public key");
1028*7c243321SVesa Jääskeläinen 		rc = PKCS11_CKR_DEVICE_MEMORY;
1029*7c243321SVesa Jääskeläinen 		goto out;
1030*7c243321SVesa Jääskeläinen 	}
1031*7c243321SVesa Jääskeläinen 
1032*7c243321SVesa Jääskeläinen 	ret = mbedtls_ecp_point_write_binary(&key_pair.grp, &key_pair.Q,
1033*7c243321SVesa Jääskeläinen 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
1034*7c243321SVesa Jääskeläinen 					     &buflen, buf, buflen);
1035*7c243321SVesa Jääskeläinen 	if (ret) {
1036*7c243321SVesa Jääskeläinen 		EMSG("Failed to write binary public key");
1037*7c243321SVesa Jääskeläinen 		goto out;
1038*7c243321SVesa Jääskeläinen 	}
1039*7c243321SVesa Jääskeläinen 
1040*7c243321SVesa Jääskeläinen 	/* Note: ASN.1 writing works backwards */
1041*7c243321SVesa Jääskeläinen 	ptr = asnbuf + asnbuflen;
1042*7c243321SVesa Jääskeläinen 
1043*7c243321SVesa Jääskeläinen 	ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen);
1044*7c243321SVesa Jääskeläinen 	if (ret < 0) {
1045*7c243321SVesa Jääskeläinen 		EMSG("Failed to write asn1 public key");
1046*7c243321SVesa Jääskeläinen 		goto out;
1047*7c243321SVesa Jääskeläinen 	}
1048*7c243321SVesa Jääskeläinen 
1049*7c243321SVesa Jääskeläinen 	rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr,
1050*7c243321SVesa Jääskeläinen 			   (size_t)ret);
1051*7c243321SVesa Jääskeläinen 
1052*7c243321SVesa Jääskeläinen out:
1053*7c243321SVesa Jääskeläinen 	TEE_Free(asnbuf);
1054*7c243321SVesa Jääskeläinen 	TEE_Free(buf);
1055*7c243321SVesa Jääskeläinen 	mbedtls_ecp_keypair_free(&key_pair);
1056*7c243321SVesa Jääskeläinen 
1057*7c243321SVesa Jääskeläinen 	return rc;
1058*7c243321SVesa Jääskeläinen }
1059*7c243321SVesa Jääskeläinen 
1060*7c243321SVesa Jääskeläinen static enum pkcs11_rc
1061*7c243321SVesa Jääskeläinen create_priv_key_hidden_attributes(struct obj_attrs **out,
1062*7c243321SVesa Jääskeläinen 				  struct obj_attrs *temp,
1063*7c243321SVesa Jääskeläinen 				  enum processing_func function)
1064*7c243321SVesa Jääskeläinen {
1065*7c243321SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1066*7c243321SVesa Jääskeläinen 
1067*7c243321SVesa Jääskeläinen 	switch (get_key_type(*out)) {
1068*7c243321SVesa Jääskeläinen 	case PKCS11_CKK_EC:
1069*7c243321SVesa Jääskeläinen 		rc = create_ec_priv_key_hidden_attributes(out, temp, function);
1070*7c243321SVesa Jääskeläinen 		break;
1071*7c243321SVesa Jääskeläinen 	default:
1072*7c243321SVesa Jääskeläinen 		/* no-op */
1073*7c243321SVesa Jääskeläinen 		break;
1074*7c243321SVesa Jääskeläinen 	}
1075*7c243321SVesa Jääskeläinen 
1076*7c243321SVesa Jääskeläinen 	return rc;
1077*7c243321SVesa Jääskeläinen }
1078*7c243321SVesa Jääskeläinen 
1079*7c243321SVesa Jääskeläinen static enum pkcs11_rc
1080196bcd93SRuchika Gupta sanitize_symm_key_attributes(struct obj_attrs **temp,
1081196bcd93SRuchika Gupta 			     enum processing_func function)
1082196bcd93SRuchika Gupta {
1083196bcd93SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1084196bcd93SRuchika Gupta 	uint32_t a_size = 0;
1085196bcd93SRuchika Gupta 
1086196bcd93SRuchika Gupta 	assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY);
1087196bcd93SRuchika Gupta 
1088196bcd93SRuchika Gupta 	rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size);
1089196bcd93SRuchika Gupta 
1090196bcd93SRuchika Gupta 	switch (get_key_type(*temp)) {
1091196bcd93SRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1092196bcd93SRuchika Gupta 	case PKCS11_CKK_AES:
1093196bcd93SRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
1094196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
1095196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
1096196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
1097196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
1098196bcd93SRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
1099196bcd93SRuchika Gupta 		switch (function) {
1100196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_IMPORT:
1101196bcd93SRuchika Gupta 			/* CKA_VALUE is a mandatory with C_CreateObject */
1102196bcd93SRuchika Gupta 			if (rc || a_size == 0)
1103196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1104196bcd93SRuchika Gupta 
1105196bcd93SRuchika Gupta 			if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL,
1106196bcd93SRuchika Gupta 					      NULL) != PKCS11_RV_NOT_FOUND)
1107196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1108196bcd93SRuchika Gupta 
1109196bcd93SRuchika Gupta 			return add_attribute(temp, PKCS11_CKA_VALUE_LEN,
1110196bcd93SRuchika Gupta 					     &a_size, sizeof(uint32_t));
1111196bcd93SRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1112196bcd93SRuchika Gupta 			if (rc != PKCS11_RV_NOT_FOUND)
1113196bcd93SRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1114196bcd93SRuchika Gupta 			break;
1115196bcd93SRuchika Gupta 		default:
1116196bcd93SRuchika Gupta 			break;
1117196bcd93SRuchika Gupta 		}
1118196bcd93SRuchika Gupta 		break;
1119196bcd93SRuchika Gupta 	default:
1120196bcd93SRuchika Gupta 		EMSG("Invalid key type %#"PRIx32"/%s",
1121196bcd93SRuchika Gupta 		     get_key_type(*temp), id2str_key_type(get_key_type(*temp)));
1122196bcd93SRuchika Gupta 
1123196bcd93SRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1124196bcd93SRuchika Gupta 	}
1125196bcd93SRuchika Gupta 
1126196bcd93SRuchika Gupta 	return PKCS11_CKR_OK;
1127196bcd93SRuchika Gupta }
1128196bcd93SRuchika Gupta 
112963f89caaSJens Wiklander /*
113063f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
113163f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
113263f89caaSJens Wiklander  * derive...).
113363f89caaSJens Wiklander  *
113463f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
113563f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
113663f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
113763f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
113863f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
113963f89caaSJens Wiklander  *
114063f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
114163f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
114263f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
114363f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
114463f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
114563f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
114663f89caaSJens Wiklander  */
114763f89caaSJens Wiklander enum pkcs11_rc
114863f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
114963f89caaSJens Wiklander 				size_t template_size,
115048799892SRuchika Gupta 				struct obj_attrs *parent,
115163f89caaSJens Wiklander 				enum processing_func function,
11524cfce748SRuchika Gupta 				enum pkcs11_mechanism_id mecha,
115302b16804SVesa Jääskeläinen 				enum pkcs11_class_id template_class)
115463f89caaSJens Wiklander {
115563f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
115663f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
115763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
115863f89caaSJens Wiklander 	uint8_t local = 0;
115963f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
116063f89caaSJens Wiklander 	uint8_t never_extract = 0;
1161e3f0cb56SRuchika Gupta 	uint8_t extractable = 0;
1162fa247a2aSRuchika Gupta 	uint32_t class = PKCS11_UNDEFINED_ID;
1163fa247a2aSRuchika Gupta 	uint32_t type = PKCS11_UNDEFINED_ID;
116463f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
1165e3f0cb56SRuchika Gupta 	struct obj_attrs *req_attrs = NULL;
1166e3f0cb56SRuchika Gupta 	uint32_t size = 0;
1167e3f0cb56SRuchika Gupta 	uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID;
116863f89caaSJens Wiklander 
116963f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
117063f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
117163f89caaSJens Wiklander 	switch (function) {
1172fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1173013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
117463f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
11752d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
117648799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1177e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
11782d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
117963f89caaSJens Wiklander 		break;
118063f89caaSJens Wiklander 	default:
118163f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
118263f89caaSJens Wiklander 	}
118363f89caaSJens Wiklander #endif
118463f89caaSJens Wiklander 
1185dcad3409SRuchika Gupta 	/*
1186dcad3409SRuchika Gupta 	 * For PKCS11_FUNCTION_GENERATE, find the class and type
1187dcad3409SRuchika Gupta 	 * based on the mechanism. These will be passed as hint
1188dcad3409SRuchika Gupta 	 * sanitize_client_object() and added in temp if not
1189dcad3409SRuchika Gupta 	 * already present
1190dcad3409SRuchika Gupta 	 */
1191dcad3409SRuchika Gupta 	if (function == PKCS11_FUNCTION_GENERATE) {
1192fa247a2aSRuchika Gupta 		switch (mecha) {
1193fa247a2aSRuchika Gupta 		case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1194fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1195fa247a2aSRuchika Gupta 			type = PKCS11_CKK_GENERIC_SECRET;
1196fa247a2aSRuchika Gupta 			break;
1197fa247a2aSRuchika Gupta 		case PKCS11_CKM_AES_KEY_GEN:
1198fa247a2aSRuchika Gupta 			class = PKCS11_CKO_SECRET_KEY;
1199fa247a2aSRuchika Gupta 			type = PKCS11_CKK_AES;
1200fa247a2aSRuchika Gupta 			break;
1201fa247a2aSRuchika Gupta 		default:
1202dcad3409SRuchika Gupta 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1203fa247a2aSRuchika Gupta 		}
1204fa247a2aSRuchika Gupta 	}
1205fa247a2aSRuchika Gupta 
12062d25a9bcSRuchika Gupta 	/*
1207013934d8SVesa Jääskeläinen 	 * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type
1208013934d8SVesa Jääskeläinen 	 * based on the mechanism. These will be passed as hint
1209013934d8SVesa Jääskeläinen 	 * sanitize_client_object() and added in temp if not
1210013934d8SVesa Jääskeläinen 	 * already present
1211013934d8SVesa Jääskeläinen 	 */
1212013934d8SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_GENERATE_PAIR) {
1213013934d8SVesa Jääskeläinen 		switch (mecha) {
121403e07432SValerii Chubar 		case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
121503e07432SValerii Chubar 			class = template_class;
121603e07432SValerii Chubar 			type = PKCS11_CKK_EDDSA;
121703e07432SValerii Chubar 			break;
121802b16804SVesa Jääskeläinen 		case PKCS11_CKM_EC_KEY_PAIR_GEN:
121902b16804SVesa Jääskeläinen 			class = template_class;
122002b16804SVesa Jääskeläinen 			type = PKCS11_CKK_EC;
122102b16804SVesa Jääskeläinen 			break;
122286922832SVesa Jääskeläinen 		case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
122386922832SVesa Jääskeläinen 			class = template_class;
122486922832SVesa Jääskeläinen 			type = PKCS11_CKK_RSA;
122586922832SVesa Jääskeläinen 			break;
1226013934d8SVesa Jääskeläinen 		default:
1227013934d8SVesa Jääskeläinen 			TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
1228013934d8SVesa Jääskeläinen 		}
1229013934d8SVesa Jääskeläinen 	}
1230013934d8SVesa Jääskeläinen 
1231013934d8SVesa Jääskeläinen 	/*
12322d25a9bcSRuchika Gupta 	 * Check and remove duplicates if any and create a new temporary
12332d25a9bcSRuchika Gupta 	 * template
12342d25a9bcSRuchika Gupta 	 */
1235dcad3409SRuchika Gupta 	rc = sanitize_client_object(&temp, template, template_size, class,
1236dcad3409SRuchika Gupta 				    type);
1237dcad3409SRuchika Gupta 	if (rc)
1238dcad3409SRuchika Gupta 		goto out;
1239dcad3409SRuchika Gupta 
1240dcad3409SRuchika Gupta 	/*
12412d25a9bcSRuchika Gupta 	 * For function type modify and copy return the created template
12422d25a9bcSRuchika Gupta 	 * from here. Rest of the code below is for creating objects
12432d25a9bcSRuchika Gupta 	 * or generating keys.
12442d25a9bcSRuchika Gupta 	 */
12452d25a9bcSRuchika Gupta 	switch (function) {
12462d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_MODIFY:
12472d25a9bcSRuchika Gupta 	case PKCS11_FUNCTION_COPY:
12482d25a9bcSRuchika Gupta 		*out = temp;
12492d25a9bcSRuchika Gupta 		return rc;
1250e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1251e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
1252e3f0cb56SRuchika Gupta 		if (function == PKCS11_FUNCTION_UNWRAP)
1253e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE;
1254e3f0cb56SRuchika Gupta 		else
1255e3f0cb56SRuchika Gupta 			indirect_template = PKCS11_CKA_DERIVE_TEMPLATE;
1256e3f0cb56SRuchika Gupta 
1257e3f0cb56SRuchika Gupta 		rc = get_attribute_ptr(parent, indirect_template,
1258e3f0cb56SRuchika Gupta 				       (void *)&req_attrs, &size);
1259e3f0cb56SRuchika Gupta 		if (rc == PKCS11_CKR_OK && size != 0) {
1260e3f0cb56SRuchika Gupta 			rc = attributes_match_add_reference(&temp, req_attrs);
1261e3f0cb56SRuchika Gupta 			if (rc)
1262e3f0cb56SRuchika Gupta 				goto out;
1263e3f0cb56SRuchika Gupta 		}
1264e3f0cb56SRuchika Gupta 		break;
12652d25a9bcSRuchika Gupta 	default:
12662d25a9bcSRuchika Gupta 		break;
12672d25a9bcSRuchika Gupta 	}
12682d25a9bcSRuchika Gupta 
12692d25a9bcSRuchika Gupta 	/*
1270dcad3409SRuchika Gupta 	 * Check if class and type in temp are consistent with the mechanism
1271dcad3409SRuchika Gupta 	 */
1272fa247a2aSRuchika Gupta 	switch (mecha) {
1273fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1274fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1275fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) {
1276fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1277fa247a2aSRuchika Gupta 			goto out;
1278fa247a2aSRuchika Gupta 		}
1279fa247a2aSRuchika Gupta 		break;
1280fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1281fa247a2aSRuchika Gupta 		if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
1282fa247a2aSRuchika Gupta 		    get_key_type(temp) != PKCS11_CKK_AES) {
1283fa247a2aSRuchika Gupta 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
1284fa247a2aSRuchika Gupta 			goto out;
1285fa247a2aSRuchika Gupta 		}
1286fa247a2aSRuchika Gupta 		break;
128702b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
128802b16804SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
128902b16804SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
129002b16804SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_EC) {
129102b16804SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
129202b16804SVesa Jääskeläinen 			goto out;
129302b16804SVesa Jääskeläinen 		}
129402b16804SVesa Jääskeläinen 		break;
129503e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
129603e07432SValerii Chubar 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
129703e07432SValerii Chubar 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
129803e07432SValerii Chubar 		    get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) {
129903e07432SValerii Chubar 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
130003e07432SValerii Chubar 			goto out;
130103e07432SValerii Chubar 		}
130203e07432SValerii Chubar 		break;
130386922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
130486922832SVesa Jääskeläinen 		if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
130586922832SVesa Jääskeläinen 		     get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
130686922832SVesa Jääskeläinen 		    get_key_type(temp) != PKCS11_CKK_RSA) {
130786922832SVesa Jääskeläinen 			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
130886922832SVesa Jääskeläinen 			goto out;
130986922832SVesa Jääskeläinen 		}
131086922832SVesa Jääskeläinen 		break;
1311fa247a2aSRuchika Gupta 	default:
1312fa247a2aSRuchika Gupta 		break;
1313fa247a2aSRuchika Gupta 	}
131463f89caaSJens Wiklander 
131563f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
131663f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
131763f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
131863f89caaSJens Wiklander 		goto out;
131963f89caaSJens Wiklander 	}
132063f89caaSJens Wiklander 
1321e3f0cb56SRuchika Gupta 	/*
1322e3f0cb56SRuchika Gupta 	 * TBD - Add a check to see if temp contains any attribute which
1323e3f0cb56SRuchika Gupta 	 * is not consistent with the object class or type and return error.
1324e3f0cb56SRuchika Gupta 	 * In current implementation such attributes are ignored and not
1325e3f0cb56SRuchika Gupta 	 * added to final object while PKCS#11 specification expects a
1326e3f0cb56SRuchika Gupta 	 * failure and an error code be returned.
1327e3f0cb56SRuchika Gupta 	 */
1328e3f0cb56SRuchika Gupta 
132963f89caaSJens Wiklander 	switch (get_class(temp)) {
133063f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
133163f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
133263f89caaSJens Wiklander 		break;
13334137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
13344137952dSVesa Jääskeläinen 		rc = create_certificate_attributes(&attrs, temp);
13354137952dSVesa Jääskeläinen 		break;
133663f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1337196bcd93SRuchika Gupta 		rc = sanitize_symm_key_attributes(&temp, function);
1338196bcd93SRuchika Gupta 		if (rc)
1339196bcd93SRuchika Gupta 			goto out;
134063f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
134163f89caaSJens Wiklander 		break;
134263f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
13439cf1afceSVesa Jääskeläinen 		rc = create_pub_key_attributes(&attrs, temp, function);
13445071d7d1SVesa Jääskeläinen 		if (rc)
13455071d7d1SVesa Jääskeläinen 			goto out;
13465071d7d1SVesa Jääskeläinen 		rc = create_pub_key_generated_attributes(&attrs, temp,
13475071d7d1SVesa Jääskeläinen 							 function);
134863f89caaSJens Wiklander 		break;
134963f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
135063f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
1351*7c243321SVesa Jääskeläinen 		if (rc)
1352*7c243321SVesa Jääskeläinen 			goto out;
1353*7c243321SVesa Jääskeläinen 		rc = create_priv_key_hidden_attributes(&attrs, temp, function);
135463f89caaSJens Wiklander 		break;
135563f89caaSJens Wiklander 	default:
135663f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
135763f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
135863f89caaSJens Wiklander 
135963f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
136063f89caaSJens Wiklander 		break;
136163f89caaSJens Wiklander 	}
136263f89caaSJens Wiklander 	if (rc)
136363f89caaSJens Wiklander 		goto out;
136463f89caaSJens Wiklander 
136590c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) !=
1366002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1367002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
136863f89caaSJens Wiklander 		goto out;
1369002f6b93SEtienne Carriere 	}
137063f89caaSJens Wiklander 
137190c47fe2SRuchika Gupta 	if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
1372002f6b93SEtienne Carriere 	    PKCS11_RV_NOT_FOUND) {
1373002f6b93SEtienne Carriere 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
137463f89caaSJens Wiklander 		goto out;
1375002f6b93SEtienne Carriere 	}
137663f89caaSJens Wiklander 
137763f89caaSJens Wiklander 	switch (function) {
1378fa247a2aSRuchika Gupta 	case PKCS11_FUNCTION_GENERATE:
1379013934d8SVesa Jääskeläinen 	case PKCS11_FUNCTION_GENERATE_PAIR:
1380fa247a2aSRuchika Gupta 		local = PKCS11_TRUE;
1381fa247a2aSRuchika Gupta 		break;
138263f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
138348799892SRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
1384e3f0cb56SRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
138563f89caaSJens Wiklander 	default:
138663f89caaSJens Wiklander 		local = PKCS11_FALSE;
138763f89caaSJens Wiklander 		break;
138863f89caaSJens Wiklander 	}
138963f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
139063f89caaSJens Wiklander 	if (rc)
139163f89caaSJens Wiklander 		goto out;
139263f89caaSJens Wiklander 
139363f89caaSJens Wiklander 	switch (get_class(attrs)) {
139463f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
139563f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
139663f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
139763f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
139863f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
139963f89caaSJens Wiklander 
1400fa247a2aSRuchika Gupta 		switch (function) {
140148799892SRuchika Gupta 		case PKCS11_FUNCTION_DERIVE:
140248799892SRuchika Gupta 			always_sensitive =
140348799892SRuchika Gupta 				get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) &&
140448799892SRuchika Gupta 				get_bool(attrs, PKCS11_CKA_SENSITIVE);
140548799892SRuchika Gupta 			never_extract =
140648799892SRuchika Gupta 			       get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) &&
140748799892SRuchika Gupta 			       !get_bool(attrs, PKCS11_CKA_EXTRACTABLE);
140848799892SRuchika Gupta 			break;
1409e3f0cb56SRuchika Gupta 		case PKCS11_FUNCTION_UNWRAP:
1410e3f0cb56SRuchika Gupta 			always_sensitive = PKCS11_FALSE;
1411e3f0cb56SRuchika Gupta 			never_extract = PKCS11_FALSE;
1412e3f0cb56SRuchika Gupta 			extractable = PKCS11_TRUE;
1413e3f0cb56SRuchika Gupta 
1414e3f0cb56SRuchika Gupta 			/*
1415e3f0cb56SRuchika Gupta 			 * Check if template passed by user has CKA_EXTRACTABLE.
1416e3f0cb56SRuchika Gupta 			 * If not, by default value of CKA_EXTRACTABLE is set as
1417e3f0cb56SRuchika Gupta 			 * TRUE.
1418e3f0cb56SRuchika Gupta 			 */
1419e3f0cb56SRuchika Gupta 			if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE,
1420e3f0cb56SRuchika Gupta 					      NULL,
1421e3f0cb56SRuchika Gupta 					      NULL) == PKCS11_RV_NOT_FOUND) {
1422e3f0cb56SRuchika Gupta 				rc = set_attribute(&attrs,
1423e3f0cb56SRuchika Gupta 						   PKCS11_CKA_EXTRACTABLE,
1424e3f0cb56SRuchika Gupta 						   &extractable,
1425e3f0cb56SRuchika Gupta 						   sizeof(extractable));
1426e3f0cb56SRuchika Gupta 				if (rc)
1427e3f0cb56SRuchika Gupta 					goto out;
1428e3f0cb56SRuchika Gupta 			}
1429e3f0cb56SRuchika Gupta 			break;
1430fa247a2aSRuchika Gupta 		case PKCS11_FUNCTION_GENERATE:
1431013934d8SVesa Jääskeläinen 		case PKCS11_FUNCTION_GENERATE_PAIR:
1432fa247a2aSRuchika Gupta 			always_sensitive = get_bool(attrs,
1433fa247a2aSRuchika Gupta 						    PKCS11_CKA_SENSITIVE);
1434fa247a2aSRuchika Gupta 			never_extract = !get_bool(attrs,
1435fa247a2aSRuchika Gupta 						  PKCS11_CKA_EXTRACTABLE);
1436fa247a2aSRuchika Gupta 			break;
1437fa247a2aSRuchika Gupta 		default:
1438fa247a2aSRuchika Gupta 			break;
1439fa247a2aSRuchika Gupta 		}
1440fa247a2aSRuchika Gupta 
144163f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
144263f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
144363f89caaSJens Wiklander 		if (rc)
144463f89caaSJens Wiklander 			goto out;
144563f89caaSJens Wiklander 
144663f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
144763f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
144863f89caaSJens Wiklander 		if (rc)
144963f89caaSJens Wiklander 			goto out;
145063f89caaSJens Wiklander 
145163f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
1452fa247a2aSRuchika Gupta 		if (local)
1453fa247a2aSRuchika Gupta 			mechanism_id = mecha;
1454fa247a2aSRuchika Gupta 		else
145563f89caaSJens Wiklander 			mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
1456fa247a2aSRuchika Gupta 
145763f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
145863f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
145963f89caaSJens Wiklander 		if (rc)
146063f89caaSJens Wiklander 			goto out;
146163f89caaSJens Wiklander 		break;
146263f89caaSJens Wiklander 
146363f89caaSJens Wiklander 	default:
146463f89caaSJens Wiklander 		break;
146563f89caaSJens Wiklander 	}
146663f89caaSJens Wiklander 
146763f89caaSJens Wiklander 	*out = attrs;
146863f89caaSJens Wiklander 
146963f89caaSJens Wiklander #ifdef DEBUG
147063f89caaSJens Wiklander 	trace_attributes("object", attrs);
147163f89caaSJens Wiklander #endif
147263f89caaSJens Wiklander 
147363f89caaSJens Wiklander out:
147463f89caaSJens Wiklander 	TEE_Free(temp);
147563f89caaSJens Wiklander 	if (rc)
147663f89caaSJens Wiklander 		TEE_Free(attrs);
147763f89caaSJens Wiklander 
147863f89caaSJens Wiklander 	return rc;
147963f89caaSJens Wiklander }
148063f89caaSJens Wiklander 
148163f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
148263f89caaSJens Wiklander {
148363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
148463f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
148563f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
148663f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
148763f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
148863f89caaSJens Wiklander 
148963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
149063f89caaSJens Wiklander 	}
149163f89caaSJens Wiklander 
149263f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
149363f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
149463f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
149563f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
149663f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
149763f89caaSJens Wiklander 
149863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
149963f89caaSJens Wiklander 	}
150063f89caaSJens Wiklander 
150163f89caaSJens Wiklander 	return PKCS11_CKR_OK;
150263f89caaSJens Wiklander }
150363f89caaSJens Wiklander 
150489735787SRuchika Gupta bool object_is_private(struct obj_attrs *head)
150589735787SRuchika Gupta {
150665fb9092SVesa Jääskeläinen 	return get_bool(head, PKCS11_CKA_PRIVATE);
150789735787SRuchika Gupta }
150889735787SRuchika Gupta 
15092d25a9bcSRuchika Gupta bool object_is_token(struct obj_attrs *head)
15102d25a9bcSRuchika Gupta {
15112d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_TOKEN);
15122d25a9bcSRuchika Gupta }
15132d25a9bcSRuchika Gupta 
15142d25a9bcSRuchika Gupta bool object_is_modifiable(struct obj_attrs *head)
15152d25a9bcSRuchika Gupta {
15162d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_MODIFIABLE);
15172d25a9bcSRuchika Gupta }
15182d25a9bcSRuchika Gupta 
15192d25a9bcSRuchika Gupta bool object_is_copyable(struct obj_attrs *head)
15202d25a9bcSRuchika Gupta {
15212d25a9bcSRuchika Gupta 	return get_bool(head, PKCS11_CKA_COPYABLE);
15222d25a9bcSRuchika Gupta }
15232d25a9bcSRuchika Gupta 
152463f89caaSJens Wiklander /*
1525512cbf1dSJens Wiklander  * Check access to object against authentication to token
1526512cbf1dSJens Wiklander  */
1527512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
1528512cbf1dSJens Wiklander 						struct obj_attrs *head)
1529512cbf1dSJens Wiklander {
1530512cbf1dSJens Wiklander 	bool private = true;
1531512cbf1dSJens Wiklander 
1532512cbf1dSJens Wiklander 	switch (get_class(head)) {
1533512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
153465fb9092SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1535512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
1536512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
15374137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
153865fb9092SVesa Jääskeläinen 		private = object_is_private(head);
1539512cbf1dSJens Wiklander 		break;
1540512cbf1dSJens Wiklander 	default:
1541512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1542512cbf1dSJens Wiklander 	}
1543512cbf1dSJens Wiklander 
15445db0fef4SRuchika Gupta 	if (private && (pkcs11_session_is_public(session) ||
15455db0fef4SRuchika Gupta 			pkcs11_session_is_so(session))) {
15465db0fef4SRuchika Gupta 		DMSG("Private object access from a public or SO session");
1547512cbf1dSJens Wiklander 
154812f1ba86SRuchika Gupta 		return PKCS11_CKR_USER_NOT_LOGGED_IN;
1549512cbf1dSJens Wiklander 	}
1550512cbf1dSJens Wiklander 
1551512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1552512cbf1dSJens Wiklander }
1553512cbf1dSJens Wiklander 
1554512cbf1dSJens Wiklander /*
155563f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
155663f89caaSJens Wiklander  */
155763f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
155863f89caaSJens Wiklander 						 struct obj_attrs *head)
155963f89caaSJens Wiklander {
156063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
156163f89caaSJens Wiklander 
156263f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
156363f89caaSJens Wiklander 	if (rc)
156463f89caaSJens Wiklander 		return rc;
156563f89caaSJens Wiklander 
156663f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
156763f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
156863f89caaSJens Wiklander 		DMSG("Can't create trusted object");
156963f89caaSJens Wiklander 
157063f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
157163f89caaSJens Wiklander 	}
157263f89caaSJens Wiklander 
157363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
157463f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
157563f89caaSJens Wiklander 		DMSG("Can't create persistent object");
157663f89caaSJens Wiklander 
157763f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
157863f89caaSJens Wiklander 	}
157963f89caaSJens Wiklander 
158063f89caaSJens Wiklander 	return PKCS11_CKR_OK;
158163f89caaSJens Wiklander }
158263f89caaSJens Wiklander 
158363f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
158463f89caaSJens Wiklander 	do {								\
158563f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
158663f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
158763f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
158863f89caaSJens Wiklander 									\
158963f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
159063f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
159163f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
159263f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
159363f89caaSJens Wiklander 	} while (0)
159463f89caaSJens Wiklander 
159563f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
159663f89caaSJens Wiklander 					   struct obj_attrs *head,
159763f89caaSJens Wiklander 					   uint32_t attribute, bool val)
159863f89caaSJens Wiklander {
159963f89caaSJens Wiklander 	uint8_t bbool = 0;
160063f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
160163f89caaSJens Wiklander 
160263f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
160363f89caaSJens Wiklander 		return true;
160463f89caaSJens Wiklander 
160563f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
160663f89caaSJens Wiklander 	return false;
160763f89caaSJens Wiklander }
160863f89caaSJens Wiklander 
160963f89caaSJens Wiklander /*
161063f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
161163f89caaSJens Wiklander  * used to create it.
161263f89caaSJens Wiklander  *
161363f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
161463f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
161563f89caaSJens Wiklander  */
161663f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
161763f89caaSJens Wiklander 						      struct obj_attrs *head)
161863f89caaSJens Wiklander {
161963f89caaSJens Wiklander 	/*
162063f89caaSJens Wiklander 	 * Processings that do not create secrets are not expected to call
162163f89caaSJens Wiklander 	 * this function which would panic.
162263f89caaSJens Wiklander 	 */
162363f89caaSJens Wiklander 	switch (proc_id) {
162463f89caaSJens Wiklander 	case PKCS11_PROCESSING_IMPORT:
1625cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1626e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_ECB:
1627e3f0cb56SRuchika Gupta 	case PKCS11_CKM_AES_CBC:
162848799892SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
162948799892SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
163045d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
163163f89caaSJens Wiklander 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
163263f89caaSJens Wiklander 		break;
1633fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1634fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
163503e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
163602b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
163786922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
1638fa247a2aSRuchika Gupta 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true));
1639fa247a2aSRuchika Gupta 		break;
164063f89caaSJens Wiklander 	default:
164163f89caaSJens Wiklander 		TEE_Panic(proc_id);
164263f89caaSJens Wiklander 		break;
164363f89caaSJens Wiklander 	}
164463f89caaSJens Wiklander 
1645fa247a2aSRuchika Gupta 	switch (proc_id) {
1646fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
1647fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET);
1648fa247a2aSRuchika Gupta 		break;
1649fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
1650fa247a2aSRuchika Gupta 		assert(get_key_type(head) == PKCS11_CKK_AES);
1651fa247a2aSRuchika Gupta 		break;
165203e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
165303e07432SValerii Chubar 		assert(get_key_type(head) == PKCS11_CKK_EC_EDWARDS);
165403e07432SValerii Chubar 		break;
165502b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
165602b16804SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_EC);
165702b16804SVesa Jääskeläinen 		break;
165886922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
165986922832SVesa Jääskeläinen 		assert(get_key_type(head) == PKCS11_CKK_RSA);
166086922832SVesa Jääskeläinen 		break;
1661fa247a2aSRuchika Gupta 	case PKCS11_PROCESSING_IMPORT:
1662cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1663fa247a2aSRuchika Gupta 	default:
1664fa247a2aSRuchika Gupta 		break;
1665fa247a2aSRuchika Gupta 	}
1666fa247a2aSRuchika Gupta 
166763f89caaSJens Wiklander 	return PKCS11_CKR_OK;
166863f89caaSJens Wiklander }
1669512cbf1dSJens Wiklander 
16702d0cd829SRuchika Gupta /* Return min and max key size supported for a key_type in bytes */
1671512cbf1dSJens Wiklander static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
1672512cbf1dSJens Wiklander 				  uint32_t *min_key_size,
1673512cbf1dSJens Wiklander 				  uint32_t *max_key_size)
1674512cbf1dSJens Wiklander {
1675512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
1676512cbf1dSJens Wiklander 
1677512cbf1dSJens Wiklander 	switch (key_type) {
1678fa247a2aSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
1679fa247a2aSRuchika Gupta 		mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN;
1680fa247a2aSRuchika Gupta 		break;
1681512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
1682512cbf1dSJens Wiklander 		mechanism = PKCS11_CKM_AES_KEY_GEN;
1683512cbf1dSJens Wiklander 		break;
16841f45c9cfSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
16851f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_MD5_HMAC;
16861f45c9cfSRuchika Gupta 		break;
16871f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
16881f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA_1_HMAC;
16891f45c9cfSRuchika Gupta 		break;
16901f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
16911f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA224_HMAC;
16921f45c9cfSRuchika Gupta 		break;
1693a339a354SEtienne Carriere 	case PKCS11_CKK_SHA256_HMAC:
1694a339a354SEtienne Carriere 		mechanism = PKCS11_CKM_SHA256_HMAC;
1695a339a354SEtienne Carriere 		break;
16961f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
16971f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA384_HMAC;
16981f45c9cfSRuchika Gupta 		break;
16991f45c9cfSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
17001f45c9cfSRuchika Gupta 		mechanism = PKCS11_CKM_SHA512_HMAC;
17011f45c9cfSRuchika Gupta 		break;
1702db28c542SVesa Jääskeläinen 	case PKCS11_CKK_EC:
1703db28c542SVesa Jääskeläinen 		mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN;
1704db28c542SVesa Jääskeläinen 		break;
170503e07432SValerii Chubar 	case PKCS11_CKK_EDDSA:
170603e07432SValerii Chubar 		mechanism = PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN;
170703e07432SValerii Chubar 		break;
170886922832SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
170986922832SVesa Jääskeläinen 		mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN;
171086922832SVesa Jääskeläinen 		break;
1711512cbf1dSJens Wiklander 	default:
1712512cbf1dSJens Wiklander 		TEE_Panic(key_type);
1713512cbf1dSJens Wiklander 		break;
1714512cbf1dSJens Wiklander 	}
1715512cbf1dSJens Wiklander 
17162d0cd829SRuchika Gupta 	mechanism_supported_key_sizes_bytes(mechanism, min_key_size,
1717512cbf1dSJens Wiklander 					    max_key_size);
1718512cbf1dSJens Wiklander }
1719512cbf1dSJens Wiklander 
1720512cbf1dSJens Wiklander enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
1721512cbf1dSJens Wiklander 				   struct obj_attrs *key2)
1722512cbf1dSJens Wiklander {
1723512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1724512cbf1dSJens Wiklander 	struct obj_attrs *secret = NULL;
1725013934d8SVesa Jääskeläinen 	struct obj_attrs *private = NULL;
1726013934d8SVesa Jääskeläinen 	struct obj_attrs *public = NULL;
1727512cbf1dSJens Wiklander 	uint32_t max_key_size = 0;
1728512cbf1dSJens Wiklander 	uint32_t min_key_size = 0;
1729512cbf1dSJens Wiklander 	uint32_t key_length = 0;
1730512cbf1dSJens Wiklander 
1731512cbf1dSJens Wiklander 	switch (get_class(key1)) {
1732512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
1733512cbf1dSJens Wiklander 		secret = key1;
1734512cbf1dSJens Wiklander 		break;
1735013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
1736013934d8SVesa Jääskeläinen 		public = key1;
1737013934d8SVesa Jääskeläinen 		break;
1738013934d8SVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
1739013934d8SVesa Jääskeläinen 		private = key1;
1740013934d8SVesa Jääskeläinen 		break;
1741512cbf1dSJens Wiklander 	default:
1742512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1743512cbf1dSJens Wiklander 	}
1744512cbf1dSJens Wiklander 
1745013934d8SVesa Jääskeläinen 	if (key2) {
1746013934d8SVesa Jääskeläinen 		switch (get_class(key2)) {
1747013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PUBLIC_KEY:
1748013934d8SVesa Jääskeläinen 			public = key2;
1749013934d8SVesa Jääskeläinen 			if (private == key1)
1750013934d8SVesa Jääskeläinen 				break;
1751013934d8SVesa Jääskeläinen 
1752013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1753013934d8SVesa Jääskeläinen 		case PKCS11_CKO_PRIVATE_KEY:
1754013934d8SVesa Jääskeläinen 			private = key2;
1755013934d8SVesa Jääskeläinen 			if (public == key1)
1756013934d8SVesa Jääskeläinen 				break;
1757013934d8SVesa Jääskeläinen 
1758013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1759013934d8SVesa Jääskeläinen 		default:
1760512cbf1dSJens Wiklander 			return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
1761013934d8SVesa Jääskeläinen 		}
1762013934d8SVesa Jääskeläinen 
1763013934d8SVesa Jääskeläinen 		if (get_key_type(private) != get_key_type(public))
1764013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1765013934d8SVesa Jääskeläinen 	}
1766512cbf1dSJens Wiklander 
1767512cbf1dSJens Wiklander 	if (secret) {
1768512cbf1dSJens Wiklander 		switch (get_key_type(secret)) {
1769512cbf1dSJens Wiklander 		case PKCS11_CKK_AES:
1770512cbf1dSJens Wiklander 		case PKCS11_CKK_GENERIC_SECRET:
1771512cbf1dSJens Wiklander 		case PKCS11_CKK_MD5_HMAC:
1772512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA_1_HMAC:
1773512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA224_HMAC:
1774512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA256_HMAC:
1775512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA384_HMAC:
1776512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA512_HMAC:
1777512cbf1dSJens Wiklander 			break;
1778512cbf1dSJens Wiklander 		default:
1779512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1780512cbf1dSJens Wiklander 		}
1781512cbf1dSJens Wiklander 
1782512cbf1dSJens Wiklander 		/* Get key size */
1783512cbf1dSJens Wiklander 		rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN,
1784512cbf1dSJens Wiklander 				       &key_length);
1785512cbf1dSJens Wiklander 		if (rc)
1786d1d44372SRuchika Gupta 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
1787512cbf1dSJens Wiklander 	}
1788013934d8SVesa Jääskeläinen 	if (public) {
1789013934d8SVesa Jääskeläinen 		switch (get_key_type(public)) {
179086922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
179186922832SVesa Jääskeläinen 			/* Get key size */
179286922832SVesa Jääskeläinen 			rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS,
179386922832SVesa Jääskeläinen 					       &key_length);
179486922832SVesa Jääskeläinen 			if (rc)
179586922832SVesa Jääskeläinen 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
179686922832SVesa Jääskeläinen 			key_length = ROUNDUP(key_length, 8) / 8;
179786922832SVesa Jääskeläinen 			break;
179802b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
179903e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
180002b16804SVesa Jääskeläinen 			break;
1801013934d8SVesa Jääskeläinen 		default:
1802013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1803013934d8SVesa Jääskeläinen 		}
1804013934d8SVesa Jääskeläinen 	}
1805013934d8SVesa Jääskeläinen 	if (private) {
1806013934d8SVesa Jääskeläinen 		switch (get_key_type(private)) {
180786922832SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
180802b16804SVesa Jääskeläinen 		case PKCS11_CKK_EC:
180903e07432SValerii Chubar 		case PKCS11_CKK_EC_EDWARDS:
181002b16804SVesa Jääskeläinen 			break;
1811013934d8SVesa Jääskeläinen 		default:
1812013934d8SVesa Jääskeläinen 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
1813013934d8SVesa Jääskeläinen 		}
1814013934d8SVesa Jääskeläinen 	}
1815512cbf1dSJens Wiklander 
181602b16804SVesa Jääskeläinen 	/*
181702b16804SVesa Jääskeläinen 	 * Check key size for symmetric keys and RSA keys
181802b16804SVesa Jääskeläinen 	 * EC is bound to domains, no need to check here.
181902b16804SVesa Jääskeläinen 	 */
182002b16804SVesa Jääskeläinen 	switch (get_key_type(key1)) {
182102b16804SVesa Jääskeläinen 	case PKCS11_CKK_EC:
182203e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
182302b16804SVesa Jääskeläinen 		return PKCS11_CKR_OK;
182402b16804SVesa Jääskeläinen 	default:
182502b16804SVesa Jääskeläinen 		break;
182602b16804SVesa Jääskeläinen 	}
182702b16804SVesa Jääskeläinen 
1828512cbf1dSJens Wiklander 	get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size);
1829512cbf1dSJens Wiklander 	if (key_length < min_key_size || key_length > max_key_size) {
1830512cbf1dSJens Wiklander 		EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]",
1831512cbf1dSJens Wiklander 		     key_length, min_key_size, max_key_size);
1832512cbf1dSJens Wiklander 
1833512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_SIZE_RANGE;
1834512cbf1dSJens Wiklander 	}
1835512cbf1dSJens Wiklander 
183649ed60abSRuchika Gupta 	if (secret && get_key_type(secret) == PKCS11_CKK_AES) {
183749ed60abSRuchika Gupta 		if (key_length != 16 && key_length != 24 && key_length != 32)
183849ed60abSRuchika Gupta 			return PKCS11_CKR_KEY_SIZE_RANGE;
183949ed60abSRuchika Gupta 	}
184049ed60abSRuchika Gupta 
1841512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1842512cbf1dSJens Wiklander }
1843512cbf1dSJens Wiklander 
1844512cbf1dSJens Wiklander /* Check processing ID against attribute ALLOWED_MECHANISMS if any */
1845512cbf1dSJens Wiklander static bool parent_key_complies_allowed_processings(uint32_t proc_id,
1846512cbf1dSJens Wiklander 						    struct obj_attrs *head)
1847512cbf1dSJens Wiklander {
1848512cbf1dSJens Wiklander 	char *attr = NULL;
1849512cbf1dSJens Wiklander 	uint32_t size = 0;
1850512cbf1dSJens Wiklander 	uint32_t proc = 0;
1851512cbf1dSJens Wiklander 	size_t count = 0;
18526a760c9eSEtienne Carriere 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1853512cbf1dSJens Wiklander 
18546a760c9eSEtienne Carriere 	rc = get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS,
18556a760c9eSEtienne Carriere 			       (void *)&attr, &size);
18566a760c9eSEtienne Carriere 	if (rc == PKCS11_RV_NOT_FOUND)
1857512cbf1dSJens Wiklander 		return true;
18586a760c9eSEtienne Carriere 	if (rc) {
18596a760c9eSEtienne Carriere 		EMSG("unexpected attributes state");
18606a760c9eSEtienne Carriere 		TEE_Panic(TEE_ERROR_BAD_STATE);
1861512cbf1dSJens Wiklander 	}
1862512cbf1dSJens Wiklander 
1863512cbf1dSJens Wiklander 	for (count = size / sizeof(uint32_t); count; count--) {
1864512cbf1dSJens Wiklander 		TEE_MemMove(&proc, attr, sizeof(uint32_t));
1865512cbf1dSJens Wiklander 		attr += sizeof(uint32_t);
1866512cbf1dSJens Wiklander 
1867512cbf1dSJens Wiklander 		if (proc == proc_id)
1868512cbf1dSJens Wiklander 			return true;
1869512cbf1dSJens Wiklander 	}
1870512cbf1dSJens Wiklander 
1871512cbf1dSJens Wiklander 	DMSG("can't find %s in allowed list", id2str_proc(proc_id));
1872512cbf1dSJens Wiklander 	return false;
1873512cbf1dSJens Wiklander }
1874512cbf1dSJens Wiklander 
1875512cbf1dSJens Wiklander static enum pkcs11_attr_id func_to_attr(enum processing_func func)
1876512cbf1dSJens Wiklander {
1877512cbf1dSJens Wiklander 	switch (func) {
1878512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
1879512cbf1dSJens Wiklander 		return PKCS11_CKA_ENCRYPT;
1880512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
1881512cbf1dSJens Wiklander 		return PKCS11_CKA_DECRYPT;
1882512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
1883512cbf1dSJens Wiklander 		return PKCS11_CKA_SIGN;
1884512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
1885512cbf1dSJens Wiklander 		return PKCS11_CKA_VERIFY;
1886512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
1887512cbf1dSJens Wiklander 		return PKCS11_CKA_WRAP;
1888512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
1889512cbf1dSJens Wiklander 		return PKCS11_CKA_UNWRAP;
1890512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
1891512cbf1dSJens Wiklander 		return PKCS11_CKA_DERIVE;
1892512cbf1dSJens Wiklander 	default:
1893512cbf1dSJens Wiklander 		return PKCS11_CKA_UNDEFINED_ID;
1894512cbf1dSJens Wiklander 	}
1895512cbf1dSJens Wiklander }
1896512cbf1dSJens Wiklander 
1897512cbf1dSJens Wiklander enum pkcs11_rc
1898512cbf1dSJens Wiklander check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
1899512cbf1dSJens Wiklander 				      enum processing_func function,
1900512cbf1dSJens Wiklander 				      struct obj_attrs *head)
1901512cbf1dSJens Wiklander {
1902512cbf1dSJens Wiklander 	enum pkcs11_class_id key_class = get_class(head);
1903512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(head);
1904512cbf1dSJens Wiklander 	enum pkcs11_attr_id attr = func_to_attr(function);
1905512cbf1dSJens Wiklander 
1906512cbf1dSJens Wiklander 	if (!get_bool(head, attr)) {
1907512cbf1dSJens Wiklander 		DMSG("%s not permitted", id2str_attr(attr));
1908512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1909512cbf1dSJens Wiklander 	}
1910512cbf1dSJens Wiklander 
1911512cbf1dSJens Wiklander 	/* Check processing complies with parent key family */
1912512cbf1dSJens Wiklander 	switch (proc_id) {
1913512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
1914512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
1915512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
1916512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
19170ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC:
19180ef6b144SVictor Chong 	case PKCS11_CKM_AES_CMAC_GENERAL:
1919512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1920512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1921512cbf1dSJens Wiklander 			break;
1922512cbf1dSJens Wiklander 
1923512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1924512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1925512cbf1dSJens Wiklander 
19265f80f270SRuchika Gupta 		if (function == PKCS11_FUNCTION_WRAP)
19275f80f270SRuchika Gupta 			return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1928e3f0cb56SRuchika Gupta 		else if (function == PKCS11_FUNCTION_UNWRAP)
1929e3f0cb56SRuchika Gupta 			return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
19305f80f270SRuchika Gupta 		else
1931512cbf1dSJens Wiklander 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1932512cbf1dSJens Wiklander 
1933c3033708SRuchika Gupta 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
1934c3033708SRuchika Gupta 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
1935c3033708SRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY &&
1936c3033708SRuchika Gupta 		    key_type != PKCS11_CKK_AES)
1937c3033708SRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1938c3033708SRuchika Gupta 
1939c3033708SRuchika Gupta 		if (get_bool(head, PKCS11_CKA_ENCRYPT)) {
1940c3033708SRuchika Gupta 			/*
1941c3033708SRuchika Gupta 			 * Intentionally refuse to proceed despite
1942c3033708SRuchika Gupta 			 * PKCS#11 specifications v2.40 and v3.0 not expecting
1943c3033708SRuchika Gupta 			 * this behavior to avoid potential security issue
1944c3033708SRuchika Gupta 			 * where keys derived by these mechanisms can be
1945c3033708SRuchika Gupta 			 * revealed by doing data encryption using parent key.
1946c3033708SRuchika Gupta 			 */
1947c3033708SRuchika Gupta 			return PKCS11_CKR_FUNCTION_FAILED;
1948c3033708SRuchika Gupta 		}
1949c3033708SRuchika Gupta 
1950c3033708SRuchika Gupta 		break;
1951689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
1952689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
1953689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
1954689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
1955689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
1956689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
195770b6683bSVictor Chong 	case PKCS11_CKM_MD5_HMAC_GENERAL:
195870b6683bSVictor Chong 	case PKCS11_CKM_SHA_1_HMAC_GENERAL:
195970b6683bSVictor Chong 	case PKCS11_CKM_SHA224_HMAC_GENERAL:
196070b6683bSVictor Chong 	case PKCS11_CKM_SHA256_HMAC_GENERAL:
196170b6683bSVictor Chong 	case PKCS11_CKM_SHA384_HMAC_GENERAL:
196270b6683bSVictor Chong 	case PKCS11_CKM_SHA512_HMAC_GENERAL:
1963689f4e5bSRuchika Gupta 		if (key_class != PKCS11_CKO_SECRET_KEY)
1964689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1965689f4e5bSRuchika Gupta 
1966689f4e5bSRuchika Gupta 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
1967689f4e5bSRuchika Gupta 			break;
1968689f4e5bSRuchika Gupta 
1969689f4e5bSRuchika Gupta 		switch (proc_id) {
1970689f4e5bSRuchika Gupta 		case PKCS11_CKM_MD5_HMAC:
197170b6683bSVictor Chong 		case PKCS11_CKM_MD5_HMAC_GENERAL:
1972689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_MD5_HMAC)
1973689f4e5bSRuchika Gupta 				break;
1974689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1975689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA_1_HMAC:
197670b6683bSVictor Chong 		case PKCS11_CKM_SHA_1_HMAC_GENERAL:
1977689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA_1_HMAC)
1978689f4e5bSRuchika Gupta 				break;
1979689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1980689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA224_HMAC:
198170b6683bSVictor Chong 		case PKCS11_CKM_SHA224_HMAC_GENERAL:
1982689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA224_HMAC)
1983689f4e5bSRuchika Gupta 				break;
1984689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1985689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA256_HMAC:
198670b6683bSVictor Chong 		case PKCS11_CKM_SHA256_HMAC_GENERAL:
1987689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA256_HMAC)
1988689f4e5bSRuchika Gupta 				break;
1989689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1990689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA384_HMAC:
199170b6683bSVictor Chong 		case PKCS11_CKM_SHA384_HMAC_GENERAL:
1992689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA384_HMAC)
1993689f4e5bSRuchika Gupta 				break;
1994689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1995689f4e5bSRuchika Gupta 		case PKCS11_CKM_SHA512_HMAC:
199670b6683bSVictor Chong 		case PKCS11_CKM_SHA512_HMAC_GENERAL:
1997689f4e5bSRuchika Gupta 			if (key_type == PKCS11_CKK_SHA512_HMAC)
1998689f4e5bSRuchika Gupta 				break;
1999689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2000689f4e5bSRuchika Gupta 		default:
2001689f4e5bSRuchika Gupta 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2002689f4e5bSRuchika Gupta 		}
2003689f4e5bSRuchika Gupta 		break;
2004689f4e5bSRuchika Gupta 
200503e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
200603e07432SValerii Chubar 		if (key_type != PKCS11_CKK_EC_EDWARDS) {
200703e07432SValerii Chubar 			EMSG("Invalid key %s for mechanism %s",
200803e07432SValerii Chubar 			     id2str_type(key_type, key_class),
200903e07432SValerii Chubar 			     id2str_proc(proc_id));
201003e07432SValerii Chubar 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
201103e07432SValerii Chubar 		}
201203e07432SValerii Chubar 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
201303e07432SValerii Chubar 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
201403e07432SValerii Chubar 			EMSG("Invalid key class for mechanism %s",
201503e07432SValerii Chubar 			     id2str_proc(proc_id));
201603e07432SValerii Chubar 
201703e07432SValerii Chubar 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
201803e07432SValerii Chubar 		}
201903e07432SValerii Chubar 		break;
202003e07432SValerii Chubar 
2021fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
2022fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
2023fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
2024fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
2025fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
2026fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
2027cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
2028fb279d8bSVesa Jääskeläinen 		if (key_type != PKCS11_CKK_EC) {
2029fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
2030fb279d8bSVesa Jääskeläinen 			     id2str_type(key_type, key_class),
2031fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2032fb279d8bSVesa Jääskeläinen 
2033fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
2034fb279d8bSVesa Jääskeläinen 		}
2035fb279d8bSVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
2036fb279d8bSVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
2037fb279d8bSVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
2038fb279d8bSVesa Jääskeläinen 			     id2str_proc(proc_id));
2039fb279d8bSVesa Jääskeläinen 
2040fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2041fb279d8bSVesa Jääskeläinen 		}
2042fb279d8bSVesa Jääskeläinen 		break;
20430442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
20440442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
20450442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
20460442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
20470442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
20480442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
20490442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
205045d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
2051dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
2052d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
2053d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
2054d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
2055d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
2056d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
2057d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
20580442c956SVesa Jääskeläinen 		if (key_type != PKCS11_CKK_RSA) {
20590442c956SVesa Jääskeläinen 			EMSG("Invalid key %s for mechanism %s",
20600442c956SVesa Jääskeläinen 			     id2str_type(key_type, key_class),
20610442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20620442c956SVesa Jääskeläinen 
20630442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
20640442c956SVesa Jääskeläinen 		}
20650442c956SVesa Jääskeläinen 		if (key_class != PKCS11_CKO_PUBLIC_KEY &&
20660442c956SVesa Jääskeläinen 		    key_class != PKCS11_CKO_PRIVATE_KEY) {
20670442c956SVesa Jääskeläinen 			EMSG("Invalid key class for mechanism %s",
20680442c956SVesa Jääskeläinen 			     id2str_proc(proc_id));
20690442c956SVesa Jääskeläinen 
20700442c956SVesa Jääskeläinen 			return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
20710442c956SVesa Jääskeläinen 		}
20720442c956SVesa Jääskeläinen 		break;
2073512cbf1dSJens Wiklander 	default:
2074512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
2075512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
2076512cbf1dSJens Wiklander 
2077512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
2078512cbf1dSJens Wiklander 	}
2079512cbf1dSJens Wiklander 
2080512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
2081512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
2082512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
2083512cbf1dSJens Wiklander 	}
2084512cbf1dSJens Wiklander 
2085512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
2086512cbf1dSJens Wiklander }
2087783c1515SRuchika Gupta 
2088783c1515SRuchika Gupta bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
2089783c1515SRuchika Gupta 			     struct pkcs11_object *obj)
2090783c1515SRuchika Gupta {
2091783c1515SRuchika Gupta 	uint8_t boolval = 0;
2092783c1515SRuchika Gupta 	uint32_t boolsize = 0;
2093783c1515SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2094783c1515SRuchika Gupta 	enum pkcs11_class_id key_class = get_class(obj->attributes);
2095783c1515SRuchika Gupta 
2096981966bcSVesa Jääskeläinen 	if (attribute_is_hidden(req_attr))
2097981966bcSVesa Jääskeläinen 		return false;
2098981966bcSVesa Jääskeläinen 
2099783c1515SRuchika Gupta 	if (key_class != PKCS11_CKO_SECRET_KEY &&
2100783c1515SRuchika Gupta 	    key_class != PKCS11_CKO_PRIVATE_KEY)
2101783c1515SRuchika Gupta 		return true;
2102783c1515SRuchika Gupta 
2103783c1515SRuchika Gupta 	switch (req_attr->id) {
2104783c1515SRuchika Gupta 	case PKCS11_CKA_PRIVATE_EXPONENT:
2105783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_1:
2106783c1515SRuchika Gupta 	case PKCS11_CKA_PRIME_2:
2107783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_1:
2108783c1515SRuchika Gupta 	case PKCS11_CKA_EXPONENT_2:
2109783c1515SRuchika Gupta 	case PKCS11_CKA_COEFFICIENT:
2110783c1515SRuchika Gupta 	case PKCS11_CKA_VALUE:
2111783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2112783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
2113783c1515SRuchika Gupta 				   &boolval, &boolsize);
2114783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_FALSE)
2115783c1515SRuchika Gupta 			return false;
2116783c1515SRuchika Gupta 
2117783c1515SRuchika Gupta 		boolsize = sizeof(boolval);
2118783c1515SRuchika Gupta 		rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
2119783c1515SRuchika Gupta 				   &boolval, &boolsize);
2120783c1515SRuchika Gupta 		if (rc || boolval == PKCS11_TRUE)
2121783c1515SRuchika Gupta 			return false;
2122783c1515SRuchika Gupta 		break;
2123783c1515SRuchika Gupta 	default:
2124783c1515SRuchika Gupta 		break;
2125783c1515SRuchika Gupta 	}
2126783c1515SRuchika Gupta 
2127783c1515SRuchika Gupta 	return true;
2128783c1515SRuchika Gupta }
21292d25a9bcSRuchika Gupta 
21302d25a9bcSRuchika Gupta static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr)
21312d25a9bcSRuchika Gupta {
21322d25a9bcSRuchika Gupta 	switch (attr->id) {
21332d25a9bcSRuchika Gupta 	case PKCS11_CKA_ID:
21342d25a9bcSRuchika Gupta 	case PKCS11_CKA_START_DATE:
21352d25a9bcSRuchika Gupta 	case PKCS11_CKA_END_DATE:
21362d25a9bcSRuchika Gupta 	case PKCS11_CKA_DERIVE:
21372d25a9bcSRuchika Gupta 		return true;
21382d25a9bcSRuchika Gupta 	default:
21392d25a9bcSRuchika Gupta 		return false;
21402d25a9bcSRuchika Gupta 	}
21412d25a9bcSRuchika Gupta }
21422d25a9bcSRuchika Gupta 
21432d25a9bcSRuchika Gupta static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr,
21442d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21452d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj)
21462d25a9bcSRuchika Gupta {
21472d25a9bcSRuchika Gupta 	switch (attr->id) {
21482d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
21492d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
21502d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
21512d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
21522d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
21532d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
21542d25a9bcSRuchika Gupta 		return true;
21552d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
21562d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
21572d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
21582d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
21592d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
21602d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
21612d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
21622d25a9bcSRuchika Gupta 	/* Change in CKA_TRUSTED can only be done by SO */
21632d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
21642d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
21652d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
21662d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
21672d25a9bcSRuchika Gupta 		return false;
21682d25a9bcSRuchika Gupta 	default:
21692d25a9bcSRuchika Gupta 		return false;
21702d25a9bcSRuchika Gupta 	}
21712d25a9bcSRuchika Gupta }
21722d25a9bcSRuchika Gupta 
21732d25a9bcSRuchika Gupta static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr,
21742d25a9bcSRuchika Gupta 					  struct pkcs11_session *session,
21752d25a9bcSRuchika Gupta 					  struct pkcs11_object *obj __unused)
21762d25a9bcSRuchika Gupta {
21772d25a9bcSRuchika Gupta 	switch (attr->id) {
21782d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
21792d25a9bcSRuchika Gupta 	case PKCS11_CKA_ENCRYPT:
21802d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY:
21812d25a9bcSRuchika Gupta 	case PKCS11_CKA_VERIFY_RECOVER:
21822d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP:
21832d25a9bcSRuchika Gupta 		return true;
21842d25a9bcSRuchika Gupta 	case PKCS11_CKA_TRUSTED:
21852d25a9bcSRuchika Gupta 		/* Change in CKA_TRUSTED can only be done by SO */
21862d25a9bcSRuchika Gupta 		return pkcs11_session_is_so(session);
21872d25a9bcSRuchika Gupta 	default:
21882d25a9bcSRuchika Gupta 		return false;
21892d25a9bcSRuchika Gupta 	}
21902d25a9bcSRuchika Gupta }
21912d25a9bcSRuchika Gupta 
21922d25a9bcSRuchika Gupta static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr,
21932d25a9bcSRuchika Gupta 					   struct pkcs11_session *sess __unused,
21942d25a9bcSRuchika Gupta 					   struct pkcs11_object *obj)
21952d25a9bcSRuchika Gupta {
21962d25a9bcSRuchika Gupta 	switch (attr->id) {
21972d25a9bcSRuchika Gupta 	case PKCS11_CKA_SUBJECT:
21982d25a9bcSRuchika Gupta 	case PKCS11_CKA_DECRYPT:
21992d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN:
22002d25a9bcSRuchika Gupta 	case PKCS11_CKA_SIGN_RECOVER:
22012d25a9bcSRuchika Gupta 	case PKCS11_CKA_UNWRAP:
22022d25a9bcSRuchika Gupta 	/*
22032d25a9bcSRuchika Gupta 	 * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO
22042d25a9bcSRuchika Gupta 	 * Specification mentions that if this attribute is
22052d25a9bcSRuchika Gupta 	 * supplied as part of a template for C_CreateObject, C_CopyObject or
22062d25a9bcSRuchika Gupta 	 * C_SetAttributeValue for a private key, the token MUST verify
22072d25a9bcSRuchika Gupta 	 * correspondence between the private key data and the public key data
22082d25a9bcSRuchika Gupta 	 * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be
22092d25a9bcSRuchika Gupta 	 * taken care of when this object type will be implemented
22102d25a9bcSRuchika Gupta 	 */
22112d25a9bcSRuchika Gupta 	case PKCS11_CKA_PUBLIC_KEY_INFO:
22122d25a9bcSRuchika Gupta 		return true;
22132d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
22142d25a9bcSRuchika Gupta 	case PKCS11_CKA_EXTRACTABLE:
22152d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, attr->id);
22162d25a9bcSRuchika Gupta 	/* Can't be modified once set to CK_TRUE - 11 in Table 10 */
22172d25a9bcSRuchika Gupta 	case PKCS11_CKA_SENSITIVE:
22182d25a9bcSRuchika Gupta 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
22192d25a9bcSRuchika Gupta 		return !get_bool(obj->attributes, attr->id);
22202d25a9bcSRuchika Gupta 	case PKCS11_CKA_NEVER_EXTRACTABLE:
22212d25a9bcSRuchika Gupta 	case PKCS11_CKA_ALWAYS_SENSITIVE:
22222d25a9bcSRuchika Gupta 		return false;
22232d25a9bcSRuchika Gupta 	default:
22242d25a9bcSRuchika Gupta 		return false;
22252d25a9bcSRuchika Gupta 	}
22262d25a9bcSRuchika Gupta }
22272d25a9bcSRuchika Gupta 
22284137952dSVesa Jääskeläinen static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr,
22294137952dSVesa Jääskeläinen 					   struct pkcs11_session *session,
22304137952dSVesa Jääskeläinen 					   struct pkcs11_object *obj)
22314137952dSVesa Jääskeläinen {
22324137952dSVesa Jääskeläinen 	uint8_t boolval = 0;
22334137952dSVesa Jääskeläinen 	uint32_t boolsize = 0;
22344137952dSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
22354137952dSVesa Jääskeläinen 
22364137952dSVesa Jääskeläinen 	/* Trusted certificates cannot be modified. */
22374137952dSVesa Jääskeläinen 	rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED,
22384137952dSVesa Jääskeläinen 			   &boolval, &boolsize);
22394137952dSVesa Jääskeläinen 	if (rc || boolval == PKCS11_TRUE)
22404137952dSVesa Jääskeläinen 		return false;
22414137952dSVesa Jääskeläinen 
22424137952dSVesa Jääskeläinen 	/* Common certificate attributes */
22434137952dSVesa Jääskeläinen 	switch (attr->id) {
22444137952dSVesa Jääskeläinen 	case PKCS11_CKA_TRUSTED:
22454137952dSVesa Jääskeläinen 		/*
22464137952dSVesa Jääskeläinen 		 * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an
22474137952dSVesa Jääskeläinen 		 * application. It MUST be set by a token initialization
22484137952dSVesa Jääskeläinen 		 * application or by the token’s SO.
22494137952dSVesa Jääskeläinen 		 */
22504137952dSVesa Jääskeläinen 		return pkcs11_session_is_so(session);
22514137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_TYPE:
22524137952dSVesa Jääskeläinen 	case PKCS11_CKA_CERTIFICATE_CATEGORY:
22534137952dSVesa Jääskeläinen 		return false;
22544137952dSVesa Jääskeläinen 	default:
22554137952dSVesa Jääskeläinen 		break;
22564137952dSVesa Jääskeläinen 	}
22574137952dSVesa Jääskeläinen 
22584137952dSVesa Jääskeläinen 	/* Certificate type specific attributes */
22594137952dSVesa Jääskeläinen 	switch (get_certificate_type(obj->attributes)) {
22604137952dSVesa Jääskeläinen 	case PKCS11_CKC_X_509:
22614137952dSVesa Jääskeläinen 		/*
22624137952dSVesa Jääskeläinen 		 * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER
22634137952dSVesa Jääskeläinen 		 * attributes may be modified after the object is created.
22644137952dSVesa Jääskeläinen 		 */
22654137952dSVesa Jääskeläinen 		switch (attr->id) {
22664137952dSVesa Jääskeläinen 		case PKCS11_CKA_ID:
22674137952dSVesa Jääskeläinen 		case PKCS11_CKA_ISSUER:
22684137952dSVesa Jääskeläinen 		case PKCS11_CKA_SERIAL_NUMBER:
22694137952dSVesa Jääskeläinen 			return true;
22704137952dSVesa Jääskeläinen 		default:
22714137952dSVesa Jääskeläinen 			break;
22724137952dSVesa Jääskeläinen 		}
22734137952dSVesa Jääskeläinen 		break;
22744137952dSVesa Jääskeläinen 	default:
22754137952dSVesa Jääskeläinen 		/* Unsupported certificate type */
22764137952dSVesa Jääskeläinen 		break;
22774137952dSVesa Jääskeläinen 	}
22784137952dSVesa Jääskeläinen 
22794137952dSVesa Jääskeläinen 	return false;
22804137952dSVesa Jääskeläinen }
22814137952dSVesa Jääskeläinen 
22822d25a9bcSRuchika Gupta static bool attribute_is_modifiable(struct pkcs11_session *session,
22832d25a9bcSRuchika Gupta 				    struct pkcs11_attribute_head *req_attr,
22842d25a9bcSRuchika Gupta 				    struct pkcs11_object *obj,
22852d25a9bcSRuchika Gupta 				    enum pkcs11_class_id class,
22862d25a9bcSRuchika Gupta 				    enum processing_func function)
22872d25a9bcSRuchika Gupta {
22882d25a9bcSRuchika Gupta 	/* Check modifiable attributes common to any object */
22892d25a9bcSRuchika Gupta 	switch (req_attr->id) {
22902d25a9bcSRuchika Gupta 	case PKCS11_CKA_LABEL:
22912d25a9bcSRuchika Gupta 		return true;
22922d25a9bcSRuchika Gupta 	case PKCS11_CKA_TOKEN:
22932d25a9bcSRuchika Gupta 	case PKCS11_CKA_MODIFIABLE:
22942d25a9bcSRuchika Gupta 	case PKCS11_CKA_DESTROYABLE:
22952d25a9bcSRuchika Gupta 	case PKCS11_CKA_PRIVATE:
22962d25a9bcSRuchika Gupta 		return function == PKCS11_FUNCTION_COPY;
22972d25a9bcSRuchika Gupta 	case PKCS11_CKA_COPYABLE:
22982d25a9bcSRuchika Gupta 		/*
22992d25a9bcSRuchika Gupta 		 * Specification mentions that if the attribute value is false
23002d25a9bcSRuchika Gupta 		 * it can't be set to true. Reading this we assume that it
23012d25a9bcSRuchika Gupta 		 * should be possible to modify this attribute even though this
23022d25a9bcSRuchika Gupta 		 * is not marked as modifiable in Table 10 if done in right
23032d25a9bcSRuchika Gupta 		 * direction i.e from TRUE -> FALSE.
23042d25a9bcSRuchika Gupta 		 */
23052d25a9bcSRuchika Gupta 		return get_bool(obj->attributes, req_attr->id);
23062d25a9bcSRuchika Gupta 	default:
23072d25a9bcSRuchika Gupta 		break;
23082d25a9bcSRuchika Gupta 	}
23092d25a9bcSRuchika Gupta 
23102d25a9bcSRuchika Gupta 	/* Attribute checking based on class type */
23112d25a9bcSRuchika Gupta 	switch (class) {
23122d25a9bcSRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
23132d25a9bcSRuchika Gupta 	case PKCS11_CKO_PUBLIC_KEY:
23142d25a9bcSRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
23152d25a9bcSRuchika Gupta 		if (attr_is_modifiable_any_key(req_attr))
23162d25a9bcSRuchika Gupta 			return true;
23172d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_SECRET_KEY &&
23182d25a9bcSRuchika Gupta 		    attr_is_modifiable_secret_key(req_attr, session, obj))
23192d25a9bcSRuchika Gupta 			return true;
23202d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PUBLIC_KEY &&
23212d25a9bcSRuchika Gupta 		    attr_is_modifiable_public_key(req_attr, session, obj))
23222d25a9bcSRuchika Gupta 			return true;
23232d25a9bcSRuchika Gupta 		if (class == PKCS11_CKO_PRIVATE_KEY &&
23242d25a9bcSRuchika Gupta 		    attr_is_modifiable_private_key(req_attr, session, obj))
23252d25a9bcSRuchika Gupta 			return true;
23262d25a9bcSRuchika Gupta 		break;
23272d25a9bcSRuchika Gupta 	case PKCS11_CKO_DATA:
23282d25a9bcSRuchika Gupta 		/* None of the data object attributes are modifiable */
23292d25a9bcSRuchika Gupta 		return false;
23304137952dSVesa Jääskeläinen 	case PKCS11_CKO_CERTIFICATE:
23314137952dSVesa Jääskeläinen 		return attr_is_modifiable_certificate(req_attr, session, obj);
23322d25a9bcSRuchika Gupta 	default:
23332d25a9bcSRuchika Gupta 		break;
23342d25a9bcSRuchika Gupta 	}
23352d25a9bcSRuchika Gupta 
23362d25a9bcSRuchika Gupta 	return false;
23372d25a9bcSRuchika Gupta }
23382d25a9bcSRuchika Gupta 
23392d25a9bcSRuchika Gupta enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session,
23402d25a9bcSRuchika Gupta 						struct obj_attrs *head,
23412d25a9bcSRuchika Gupta 						struct pkcs11_object *obj,
23422d25a9bcSRuchika Gupta 						enum processing_func function)
23432d25a9bcSRuchika Gupta {
23442d25a9bcSRuchika Gupta 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
23452d25a9bcSRuchika Gupta 	char *cur = NULL;
23462d25a9bcSRuchika Gupta 	char *end = NULL;
23472d25a9bcSRuchika Gupta 	size_t len = 0;
23482d25a9bcSRuchika Gupta 
23492d25a9bcSRuchika Gupta 	class = get_class(obj->attributes);
23502d25a9bcSRuchika Gupta 
23512d25a9bcSRuchika Gupta 	cur = (char *)head + sizeof(struct obj_attrs);
23522d25a9bcSRuchika Gupta 	end = cur + head->attrs_size;
23532d25a9bcSRuchika Gupta 
23542d25a9bcSRuchika Gupta 	for (; cur < end; cur += len) {
23552d25a9bcSRuchika Gupta 		/* Structure aligned copy of the pkcs11_ref in the object */
23562d25a9bcSRuchika Gupta 		struct pkcs11_attribute_head cli_ref = { };
23572d25a9bcSRuchika Gupta 
23582d25a9bcSRuchika Gupta 		TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
23592d25a9bcSRuchika Gupta 		len = sizeof(cli_ref) + cli_ref.size;
23602d25a9bcSRuchika Gupta 
2361981966bcSVesa Jääskeläinen 		/* Protect hidden attributes */
2362981966bcSVesa Jääskeläinen 		if (attribute_is_hidden(&cli_ref))
2363981966bcSVesa Jääskeläinen 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
2364981966bcSVesa Jääskeläinen 
23652d25a9bcSRuchika Gupta 		/*
23662d25a9bcSRuchika Gupta 		 * Check 1 - Check if attribute belongs to the object
23672d25a9bcSRuchika Gupta 		 * The obj->attributes has all the attributes in
23682d25a9bcSRuchika Gupta 		 * it which are allowed for an object.
23692d25a9bcSRuchika Gupta 		 */
23702d25a9bcSRuchika Gupta 		if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL,
23712d25a9bcSRuchika Gupta 				      NULL) == PKCS11_RV_NOT_FOUND)
23722d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
23732d25a9bcSRuchika Gupta 
23742d25a9bcSRuchika Gupta 		/* Check 2 - Is attribute modifiable */
23752d25a9bcSRuchika Gupta 		if (!attribute_is_modifiable(session, &cli_ref, obj, class,
23762d25a9bcSRuchika Gupta 					     function))
23772d25a9bcSRuchika Gupta 			return PKCS11_CKR_ATTRIBUTE_READ_ONLY;
23782d25a9bcSRuchika Gupta 
23792d25a9bcSRuchika Gupta 		/*
23802d25a9bcSRuchika Gupta 		 * Checks for modification in PKCS11_CKA_TOKEN and
23812d25a9bcSRuchika Gupta 		 * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY
23822d25a9bcSRuchika Gupta 		 * only, so skip them for PKCS11_FUNCTION_MODIFY.
23832d25a9bcSRuchika Gupta 		 */
23842d25a9bcSRuchika Gupta 		if (function == PKCS11_FUNCTION_MODIFY)
23852d25a9bcSRuchika Gupta 			continue;
23862d25a9bcSRuchika Gupta 
23872d25a9bcSRuchika Gupta 		/*
23882d25a9bcSRuchika Gupta 		 * An attempt to copy an object to a token will fail for
23892d25a9bcSRuchika Gupta 		 * RO session
23902d25a9bcSRuchika Gupta 		 */
23912d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_TOKEN &&
23922d25a9bcSRuchika Gupta 		    get_bool(head, PKCS11_CKA_TOKEN)) {
23932d25a9bcSRuchika Gupta 			if (!pkcs11_session_is_read_write(session)) {
23942d25a9bcSRuchika Gupta 				DMSG("Can't copy to token in a RO session");
23952d25a9bcSRuchika Gupta 				return PKCS11_CKR_SESSION_READ_ONLY;
23962d25a9bcSRuchika Gupta 			}
23972d25a9bcSRuchika Gupta 		}
23982d25a9bcSRuchika Gupta 
23992d25a9bcSRuchika Gupta 		if (cli_ref.id == PKCS11_CKA_PRIVATE) {
24002d25a9bcSRuchika Gupta 			bool parent_priv =
24012d25a9bcSRuchika Gupta 				get_bool(obj->attributes, cli_ref.id);
24022d25a9bcSRuchika Gupta 			bool obj_priv = get_bool(head, cli_ref.id);
24032d25a9bcSRuchika Gupta 
24042d25a9bcSRuchika Gupta 			/*
24052d25a9bcSRuchika Gupta 			 * If PKCS11_CKA_PRIVATE is being set to TRUE from
24062d25a9bcSRuchika Gupta 			 * FALSE, user has to be logged in
24072d25a9bcSRuchika Gupta 			 */
24082d25a9bcSRuchika Gupta 			if (!parent_priv && obj_priv) {
24092d25a9bcSRuchika Gupta 				if ((pkcs11_session_is_public(session) ||
24102d25a9bcSRuchika Gupta 				     pkcs11_session_is_so(session)))
24112d25a9bcSRuchika Gupta 					return PKCS11_CKR_USER_NOT_LOGGED_IN;
24122d25a9bcSRuchika Gupta 			}
2413df017b2bSRuchika Gupta 
2414df017b2bSRuchika Gupta 			/*
2415df017b2bSRuchika Gupta 			 * Restriction added - Even for Copy, do not allow
2416df017b2bSRuchika Gupta 			 * modification of CKA_PRIVATE from TRUE to FALSE
2417df017b2bSRuchika Gupta 			 */
2418df017b2bSRuchika Gupta 			if (parent_priv && !obj_priv)
2419df017b2bSRuchika Gupta 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
24202d25a9bcSRuchika Gupta 		}
24212d25a9bcSRuchika Gupta 	}
24222d25a9bcSRuchika Gupta 
24232d25a9bcSRuchika Gupta 	return PKCS11_CKR_OK;
24242d25a9bcSRuchika Gupta }
24258c499324SRuchika Gupta 
24268c499324SRuchika Gupta static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
24278c499324SRuchika Gupta 					  size_t key_size)
24288c499324SRuchika Gupta {
24298c499324SRuchika Gupta 	uint32_t size = sizeof(uint32_t);
24308c499324SRuchika Gupta 	uint32_t key_length = 0;
24318c499324SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
24328c499324SRuchika Gupta 
24338c499324SRuchika Gupta 	/* Get key size if present in template */
24348c499324SRuchika Gupta 	rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size);
24358c499324SRuchika Gupta 	if (rc && rc != PKCS11_RV_NOT_FOUND)
24368c499324SRuchika Gupta 		return rc;
24378c499324SRuchika Gupta 
24388c499324SRuchika Gupta 	if (key_length) {
24398c499324SRuchika Gupta 		if (key_size < key_length)
24408c499324SRuchika Gupta 			return PKCS11_CKR_DATA_LEN_RANGE;
24418c499324SRuchika Gupta 	} else {
24428c499324SRuchika Gupta 		key_length = key_size;
24438c499324SRuchika Gupta 		rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length,
24448c499324SRuchika Gupta 				   sizeof(uint32_t));
24458c499324SRuchika Gupta 		if (rc)
24468c499324SRuchika Gupta 			return rc;
24478c499324SRuchika Gupta 	}
24488c499324SRuchika Gupta 
24498c499324SRuchika Gupta 	/* Now we can check the VALUE_LEN field */
24508c499324SRuchika Gupta 	rc = check_created_attrs(*head, NULL);
24518c499324SRuchika Gupta 	if (rc)
24528c499324SRuchika Gupta 		return rc;
24538c499324SRuchika Gupta 
24548c499324SRuchika Gupta 	/* Remove the default empty value attribute if found */
24558c499324SRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
24568c499324SRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
24578c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
24588c499324SRuchika Gupta 
24598c499324SRuchika Gupta 	return add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
24608c499324SRuchika Gupta }
24618c499324SRuchika Gupta 
246245d40bdaSValerii Chubar static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
246345d40bdaSValerii Chubar 					       void *data,
246445d40bdaSValerii Chubar 					       size_t key_size)
246545d40bdaSValerii Chubar {
246645d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
246745d40bdaSValerii Chubar 	int mbedtls_rc = 0;
246845d40bdaSValerii Chubar 	uint32_t key_bits = 0;
246945d40bdaSValerii Chubar 	uint32_t size = 0;
247045d40bdaSValerii Chubar 	uint32_t buffer_size = 0;
247145d40bdaSValerii Chubar 	void *buffer = NULL;
247245d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
247345d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
247445d40bdaSValerii Chubar 	mbedtls_mpi n = { };
247545d40bdaSValerii Chubar 	mbedtls_mpi e = { };
247645d40bdaSValerii Chubar 	mbedtls_mpi d = { };
247745d40bdaSValerii Chubar 	mbedtls_mpi p = { };
247845d40bdaSValerii Chubar 	mbedtls_mpi q = { };
247945d40bdaSValerii Chubar 
248045d40bdaSValerii Chubar 	rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits);
248145d40bdaSValerii Chubar 	if (rc && rc != PKCS11_RV_NOT_FOUND)
248245d40bdaSValerii Chubar 		return rc;
248345d40bdaSValerii Chubar 
248445d40bdaSValerii Chubar 	if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) ||
248545d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) ||
248645d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) ||
248745d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_1) ||
248845d40bdaSValerii Chubar 	    remove_empty_attribute(head, PKCS11_CKA_PRIME_2))
248945d40bdaSValerii Chubar 		return PKCS11_CKR_GENERAL_ERROR;
249045d40bdaSValerii Chubar 
249145d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
249245d40bdaSValerii Chubar 	mbedtls_mpi_init(&n);
249345d40bdaSValerii Chubar 	mbedtls_mpi_init(&e);
249445d40bdaSValerii Chubar 	mbedtls_mpi_init(&d);
249545d40bdaSValerii Chubar 	mbedtls_mpi_init(&p);
249645d40bdaSValerii Chubar 	mbedtls_mpi_init(&q);
249745d40bdaSValerii Chubar 
249845d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size, NULL, 0);
249945d40bdaSValerii Chubar 	if (mbedtls_rc) {
250045d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
250145d40bdaSValerii Chubar 		goto out;
250245d40bdaSValerii Chubar 	}
250345d40bdaSValerii Chubar 
250445d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
250545d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
250645d40bdaSValerii Chubar 	if (mbedtls_rc) {
250745d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
250845d40bdaSValerii Chubar 		goto out;
250945d40bdaSValerii Chubar 	}
251045d40bdaSValerii Chubar 
251145d40bdaSValerii Chubar 	if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) {
251245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
251345d40bdaSValerii Chubar 		goto out;
251445d40bdaSValerii Chubar 	}
251545d40bdaSValerii Chubar 
251645d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8);
251745d40bdaSValerii Chubar 	buffer_size = size;
251845d40bdaSValerii Chubar 	buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
251945d40bdaSValerii Chubar 	if (!buffer) {
252045d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
252145d40bdaSValerii Chubar 		goto out;
252245d40bdaSValerii Chubar 	}
252345d40bdaSValerii Chubar 
252445d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size);
252545d40bdaSValerii Chubar 	if (mbedtls_rc) {
252645d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
252745d40bdaSValerii Chubar 		goto out;
252845d40bdaSValerii Chubar 	}
252945d40bdaSValerii Chubar 
253045d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size);
253145d40bdaSValerii Chubar 	if (rc)
253245d40bdaSValerii Chubar 		goto out;
253345d40bdaSValerii Chubar 
253445d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8);
253545d40bdaSValerii Chubar 	if (buffer_size < size) {
253645d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
253745d40bdaSValerii Chubar 		goto out;
253845d40bdaSValerii Chubar 	}
253945d40bdaSValerii Chubar 
254045d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size);
254145d40bdaSValerii Chubar 	if (mbedtls_rc) {
254245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
254345d40bdaSValerii Chubar 		goto out;
254445d40bdaSValerii Chubar 	}
254545d40bdaSValerii Chubar 
254645d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size);
254745d40bdaSValerii Chubar 	if (rc)
254845d40bdaSValerii Chubar 		goto out;
254945d40bdaSValerii Chubar 
255045d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8);
255145d40bdaSValerii Chubar 	if (buffer_size < size) {
255245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
255345d40bdaSValerii Chubar 		goto out;
255445d40bdaSValerii Chubar 	}
255545d40bdaSValerii Chubar 
255645d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size);
255745d40bdaSValerii Chubar 	if (mbedtls_rc) {
255845d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
255945d40bdaSValerii Chubar 		goto out;
256045d40bdaSValerii Chubar 	}
256145d40bdaSValerii Chubar 
256245d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size);
256345d40bdaSValerii Chubar 	if (rc)
256445d40bdaSValerii Chubar 		goto out;
256545d40bdaSValerii Chubar 
256645d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8);
256745d40bdaSValerii Chubar 	if (buffer_size < size) {
256845d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
256945d40bdaSValerii Chubar 		goto out;
257045d40bdaSValerii Chubar 	}
257145d40bdaSValerii Chubar 
257245d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size);
257345d40bdaSValerii Chubar 	if (mbedtls_rc) {
257445d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
257545d40bdaSValerii Chubar 		goto out;
257645d40bdaSValerii Chubar 	}
257745d40bdaSValerii Chubar 
257845d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size);
257945d40bdaSValerii Chubar 	if (rc)
258045d40bdaSValerii Chubar 		goto out;
258145d40bdaSValerii Chubar 
258245d40bdaSValerii Chubar 	size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8);
258345d40bdaSValerii Chubar 	if (buffer_size < size) {
258445d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
258545d40bdaSValerii Chubar 		goto out;
258645d40bdaSValerii Chubar 	}
258745d40bdaSValerii Chubar 
258845d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size);
258945d40bdaSValerii Chubar 	if (mbedtls_rc) {
259045d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
259145d40bdaSValerii Chubar 		goto out;
259245d40bdaSValerii Chubar 	}
259345d40bdaSValerii Chubar 
259445d40bdaSValerii Chubar 	rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size);
259545d40bdaSValerii Chubar 
259645d40bdaSValerii Chubar out:
259745d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
259845d40bdaSValerii Chubar 	mbedtls_mpi_free(&n);
259945d40bdaSValerii Chubar 	mbedtls_mpi_free(&e);
260045d40bdaSValerii Chubar 	mbedtls_mpi_free(&d);
260145d40bdaSValerii Chubar 	mbedtls_mpi_free(&p);
260245d40bdaSValerii Chubar 	mbedtls_mpi_free(&q);
260345d40bdaSValerii Chubar 	TEE_Free(buffer);
260445d40bdaSValerii Chubar 	return rc;
260545d40bdaSValerii Chubar }
260645d40bdaSValerii Chubar 
26078c499324SRuchika Gupta enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data,
26088c499324SRuchika Gupta 			    size_t key_size)
26098c499324SRuchika Gupta {
26108c499324SRuchika Gupta 	switch (get_class(*head)) {
26118c499324SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
26128c499324SRuchika Gupta 		return set_secret_key_data(head, data, key_size);
261345d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
261445d40bdaSValerii Chubar 		if (get_key_type(*head) == PKCS11_CKK_RSA)
261545d40bdaSValerii Chubar 			return set_private_key_data_rsa(head, data, key_size);
261645d40bdaSValerii Chubar 		break;
26178c499324SRuchika Gupta 	default:
26188c499324SRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
26198c499324SRuchika Gupta 	}
262045d40bdaSValerii Chubar 
262145d40bdaSValerii Chubar 	return PKCS11_CKR_GENERAL_ERROR;
26228c499324SRuchika Gupta }
26235e1d94ebSVesa Jääskeläinen 
2624a9aa45d8SValerii Chubar static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
2625a9aa45d8SValerii Chubar 						 void **data, uint32_t *sz)
2626a9aa45d8SValerii Chubar {
2627a9aa45d8SValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
2628a9aa45d8SValerii Chubar 	void *buffer = NULL;
2629a9aa45d8SValerii Chubar 	void *value = NULL;
2630a9aa45d8SValerii Chubar 
2631a9aa45d8SValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz);
2632a9aa45d8SValerii Chubar 	if (rc)
2633a9aa45d8SValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
2634a9aa45d8SValerii Chubar 
2635a9aa45d8SValerii Chubar 	buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
2636a9aa45d8SValerii Chubar 	if (!buffer)
2637a9aa45d8SValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
2638a9aa45d8SValerii Chubar 
2639a9aa45d8SValerii Chubar 	TEE_MemMove(buffer, value, *sz);
2640a9aa45d8SValerii Chubar 	*data = buffer;
2641a9aa45d8SValerii Chubar 
2642a9aa45d8SValerii Chubar 	return PKCS11_CKR_OK;
2643a9aa45d8SValerii Chubar }
2644a9aa45d8SValerii Chubar 
264545d40bdaSValerii Chubar static enum pkcs11_rc
264645d40bdaSValerii Chubar encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
264745d40bdaSValerii Chubar {
264845d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
264945d40bdaSValerii Chubar 	int i = 0;
265045d40bdaSValerii Chubar 	int mbedtls_rc = 0;
265145d40bdaSValerii Chubar 	int start = 0;
265245d40bdaSValerii Chubar 	int der_size = 0;
265345d40bdaSValerii Chubar 	void *n = NULL;
265445d40bdaSValerii Chubar 	void *p = NULL;
265545d40bdaSValerii Chubar 	void *q = NULL;
265645d40bdaSValerii Chubar 	void *d = NULL;
265745d40bdaSValerii Chubar 	void *e = NULL;
265845d40bdaSValerii Chubar 	uint32_t n_len = 0;
265945d40bdaSValerii Chubar 	uint32_t p_len = 0;
266045d40bdaSValerii Chubar 	uint32_t q_len = 0;
266145d40bdaSValerii Chubar 	uint32_t d_len = 0;
266245d40bdaSValerii Chubar 	uint32_t e_len = 0;
266345d40bdaSValerii Chubar 	uint8_t *buffer = NULL;
266445d40bdaSValerii Chubar 	mbedtls_pk_context pk = { };
266545d40bdaSValerii Chubar 	mbedtls_rsa_context *rsa = NULL;
266645d40bdaSValerii Chubar 	const mbedtls_pk_info_t *pk_info = NULL;
266745d40bdaSValerii Chubar 
266845d40bdaSValerii Chubar 	mbedtls_pk_init(&pk);
266945d40bdaSValerii Chubar 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
267045d40bdaSValerii Chubar 	if (mbedtls_pk_setup(&pk, pk_info)) {
267145d40bdaSValerii Chubar 		rc = PKCS11_CKR_GENERAL_ERROR;
267245d40bdaSValerii Chubar 		goto out;
267345d40bdaSValerii Chubar 	}
267445d40bdaSValerii Chubar 
267545d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len);
267645d40bdaSValerii Chubar 	if (rc)
267745d40bdaSValerii Chubar 		goto out;
267845d40bdaSValerii Chubar 
267945d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len);
268045d40bdaSValerii Chubar 	if (rc)
268145d40bdaSValerii Chubar 		goto out;
268245d40bdaSValerii Chubar 
268345d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len);
268445d40bdaSValerii Chubar 	if (rc)
268545d40bdaSValerii Chubar 		goto out;
268645d40bdaSValerii Chubar 
268745d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len);
268845d40bdaSValerii Chubar 	if (rc)
268945d40bdaSValerii Chubar 		goto out;
269045d40bdaSValerii Chubar 
269145d40bdaSValerii Chubar 	rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len);
269245d40bdaSValerii Chubar 	if (rc)
269345d40bdaSValerii Chubar 		goto out;
269445d40bdaSValerii Chubar 
269545d40bdaSValerii Chubar 	rsa = mbedtls_pk_rsa(pk);
269645d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
269745d40bdaSValerii Chubar 					    q, q_len, d, d_len, e, e_len);
269845d40bdaSValerii Chubar 	if (mbedtls_rc) {
269945d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
270045d40bdaSValerii Chubar 		goto out;
270145d40bdaSValerii Chubar 	}
270245d40bdaSValerii Chubar 
270345d40bdaSValerii Chubar 	if (mbedtls_rsa_complete(rsa)) {
270445d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
270545d40bdaSValerii Chubar 		goto out;
270645d40bdaSValerii Chubar 	}
270745d40bdaSValerii Chubar 
270845d40bdaSValerii Chubar 	if (mbedtls_rsa_check_privkey(rsa)) {
270945d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
271045d40bdaSValerii Chubar 		goto out;
271145d40bdaSValerii Chubar 	}
271245d40bdaSValerii Chubar 
271345d40bdaSValerii Chubar 	der_size = n_len * 8;
271445d40bdaSValerii Chubar 	buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
271545d40bdaSValerii Chubar 	if (!buffer) {
271645d40bdaSValerii Chubar 		rc = PKCS11_CKR_DEVICE_MEMORY;
271745d40bdaSValerii Chubar 		goto out;
271845d40bdaSValerii Chubar 	}
271945d40bdaSValerii Chubar 
272045d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size);
272145d40bdaSValerii Chubar 	if (mbedtls_rc < 0) {
272245d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
272345d40bdaSValerii Chubar 		goto out;
272445d40bdaSValerii Chubar 	}
272545d40bdaSValerii Chubar 
272645d40bdaSValerii Chubar 	start = der_size - mbedtls_rc;
272745d40bdaSValerii Chubar 	for (i = 0; i < mbedtls_rc; i++) {
272845d40bdaSValerii Chubar 		buffer[i] = buffer[i + start];
272945d40bdaSValerii Chubar 		buffer[i + start] = 0;
273045d40bdaSValerii Chubar 	}
273145d40bdaSValerii Chubar 
273245d40bdaSValerii Chubar 	*data = buffer;
273345d40bdaSValerii Chubar 	*sz = mbedtls_rc;
273445d40bdaSValerii Chubar out:
273545d40bdaSValerii Chubar 	mbedtls_pk_free(&pk);
273645d40bdaSValerii Chubar 
273745d40bdaSValerii Chubar 	if (rc)
273845d40bdaSValerii Chubar 		TEE_Free(buffer);
273945d40bdaSValerii Chubar 
274045d40bdaSValerii Chubar 	return rc;
274145d40bdaSValerii Chubar }
274245d40bdaSValerii Chubar 
2743a9aa45d8SValerii Chubar enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
27445f80f270SRuchika Gupta 				      uint32_t *sz)
27455f80f270SRuchika Gupta {
274645d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
274745d40bdaSValerii Chubar 
27485f80f270SRuchika Gupta 	switch (get_class(head)) {
27495f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
275045d40bdaSValerii Chubar 		rc = alloc_copy_attribute_value(head, data, sz);
275145d40bdaSValerii Chubar 		break;
275245d40bdaSValerii Chubar 	case PKCS11_CKO_PRIVATE_KEY:
275345d40bdaSValerii Chubar 		if (get_key_type(head) == PKCS11_CKK_RSA)
275445d40bdaSValerii Chubar 			rc = encode_rsa_private_key_der(head, data, sz);
275545d40bdaSValerii Chubar 		break;
27565f80f270SRuchika Gupta 	default:
275745d40bdaSValerii Chubar 		break;
27585f80f270SRuchika Gupta 	}
27595f80f270SRuchika Gupta 
276045d40bdaSValerii Chubar 	return rc;
27615f80f270SRuchika Gupta }
27625f80f270SRuchika Gupta 
27635e1d94ebSVesa Jääskeläinen enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
27645e1d94ebSVesa Jääskeläinen 					struct obj_attrs **priv_head)
27655e1d94ebSVesa Jääskeläinen {
27665e1d94ebSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
27675e1d94ebSVesa Jääskeläinen 	void *id1 = NULL;
27685e1d94ebSVesa Jääskeläinen 	uint32_t id1_size = 0;
27695e1d94ebSVesa Jääskeläinen 	void *id2 = NULL;
27705e1d94ebSVesa Jääskeläinen 	uint32_t id2_size = 0;
27715e1d94ebSVesa Jääskeläinen 
27725e1d94ebSVesa Jääskeläinen 	assert(pub_head);
27735e1d94ebSVesa Jääskeläinen 	assert(priv_head);
27745e1d94ebSVesa Jääskeläinen 
27755e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size);
27765e1d94ebSVesa Jääskeläinen 	if (rc) {
27775e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
27785e1d94ebSVesa Jääskeläinen 			return rc;
27795e1d94ebSVesa Jääskeläinen 		id1 = NULL;
27805e1d94ebSVesa Jääskeläinen 	} else if (!id1_size) {
27815e1d94ebSVesa Jääskeläinen 		id1 = NULL;
27825e1d94ebSVesa Jääskeläinen 	}
27835e1d94ebSVesa Jääskeläinen 
27845e1d94ebSVesa Jääskeläinen 	rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size);
27855e1d94ebSVesa Jääskeläinen 	if (rc) {
27865e1d94ebSVesa Jääskeläinen 		if (rc != PKCS11_RV_NOT_FOUND)
27875e1d94ebSVesa Jääskeläinen 			return rc;
27885e1d94ebSVesa Jääskeläinen 		id2 = NULL;
27895e1d94ebSVesa Jääskeläinen 	} else if (!id2_size) {
27905e1d94ebSVesa Jääskeläinen 		id2 = NULL;
27915e1d94ebSVesa Jääskeläinen 	}
27925e1d94ebSVesa Jääskeläinen 
27935e1d94ebSVesa Jääskeläinen 	/* Both have value -- let them be what caller has specified them */
27945e1d94ebSVesa Jääskeläinen 	if (id1 && id2)
27955e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
27965e1d94ebSVesa Jääskeläinen 
27975e1d94ebSVesa Jääskeläinen 	/* Both are empty -- leave empty values */
27985e1d94ebSVesa Jääskeläinen 	if (!id1 && !id2)
27995e1d94ebSVesa Jääskeläinen 		return PKCS11_CKR_OK;
28005e1d94ebSVesa Jääskeläinen 
28015e1d94ebSVesa Jääskeläinen 	/* Cross copy CKA_ID value */
28025e1d94ebSVesa Jääskeläinen 	if (id1)
28035e1d94ebSVesa Jääskeläinen 		return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size);
28045e1d94ebSVesa Jääskeläinen 	else
28055e1d94ebSVesa Jääskeläinen 		return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size);
28065e1d94ebSVesa Jääskeläinen }
2807