xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 4eb886511f3ac0a9ebf53369992d102b75f58966)
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>
863f89caaSJens Wiklander #include <pkcs11_ta.h>
963f89caaSJens Wiklander #include <stdlib.h>
1063f89caaSJens Wiklander #include <string_ext.h>
1163f89caaSJens Wiklander #include <tee_internal_api_extensions.h>
1263f89caaSJens Wiklander #include <tee_internal_api.h>
1363f89caaSJens Wiklander #include <util.h>
1463f89caaSJens Wiklander 
1563f89caaSJens Wiklander #include "attributes.h"
1663f89caaSJens Wiklander #include "handle.h"
1763f89caaSJens Wiklander #include "pkcs11_attributes.h"
1863f89caaSJens Wiklander #include "pkcs11_helpers.h"
1963f89caaSJens Wiklander #include "pkcs11_token.h"
2063f89caaSJens Wiklander #include "sanitize_object.h"
2163f89caaSJens Wiklander #include "serializer.h"
2263f89caaSJens Wiklander #include "token_capabilities.h"
2363f89caaSJens Wiklander 
2463f89caaSJens Wiklander /* Byte size of CKA_ID attribute when generated locally */
2563f89caaSJens Wiklander #define PKCS11_CKA_DEFAULT_SIZE		16
2663f89caaSJens Wiklander 
27512cbf1dSJens Wiklander static uint32_t pkcs11_func2ckfm(enum processing_func function)
28512cbf1dSJens Wiklander {
29512cbf1dSJens Wiklander 	switch (function) {
30512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
31512cbf1dSJens Wiklander 		return PKCS11_CKFM_DIGEST;
32512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE:
33512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE;
34512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_GENERATE_PAIR:
35512cbf1dSJens Wiklander 		return PKCS11_CKFM_GENERATE_KEY_PAIR;
36512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
37512cbf1dSJens Wiklander 		return PKCS11_CKFM_DERIVE;
38512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
39512cbf1dSJens Wiklander 		return PKCS11_CKFM_WRAP;
40512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
41512cbf1dSJens Wiklander 		return PKCS11_CKFM_UNWRAP;
42512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
43512cbf1dSJens Wiklander 		return PKCS11_CKFM_ENCRYPT;
44512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
45512cbf1dSJens Wiklander 		return PKCS11_CKFM_DECRYPT;
46512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
47512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN;
48512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
49512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY;
50512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
51512cbf1dSJens Wiklander 		return PKCS11_CKFM_SIGN_RECOVER;
52512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
53512cbf1dSJens Wiklander 		return PKCS11_CKFM_VERIFY_RECOVER;
54512cbf1dSJens Wiklander 	default:
55512cbf1dSJens Wiklander 		return 0;
56512cbf1dSJens Wiklander 	}
57512cbf1dSJens Wiklander }
58512cbf1dSJens Wiklander 
59512cbf1dSJens Wiklander enum pkcs11_rc
60512cbf1dSJens Wiklander check_mechanism_against_processing(struct pkcs11_session *session,
61512cbf1dSJens Wiklander 				   enum pkcs11_mechanism_id mechanism_type,
62512cbf1dSJens Wiklander 				   enum processing_func function,
63512cbf1dSJens Wiklander 				   enum processing_step step)
64512cbf1dSJens Wiklander {
65512cbf1dSJens Wiklander 	bool allowed = false;
66512cbf1dSJens Wiklander 
67512cbf1dSJens Wiklander 	switch (step) {
68512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_INIT:
69512cbf1dSJens Wiklander 		switch (function) {
70512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_IMPORT:
71512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_COPY:
72512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_MODIFY:
73512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DESTROY:
74512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
75512cbf1dSJens Wiklander 		default:
76512cbf1dSJens Wiklander 			break;
77512cbf1dSJens Wiklander 		}
78512cbf1dSJens Wiklander 		/*
79512cbf1dSJens Wiklander 		 * Check that the returned PKCS11_CKFM_* flag from
80512cbf1dSJens Wiklander 		 * pkcs11_func2ckfm() is among the ones from
81512cbf1dSJens Wiklander 		 * mechanism_supported_flags().
82512cbf1dSJens Wiklander 		 */
83512cbf1dSJens Wiklander 		allowed = mechanism_supported_flags(mechanism_type) &
84512cbf1dSJens Wiklander 			  pkcs11_func2ckfm(function);
85512cbf1dSJens Wiklander 		break;
86512cbf1dSJens Wiklander 
87512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_ONESHOT:
88512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
89512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
90512cbf1dSJens Wiklander 		    !session->processing->relogged)
91512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
92512cbf1dSJens Wiklander 
93512cbf1dSJens Wiklander 		if (!session->processing->updated)
94512cbf1dSJens Wiklander 			allowed = true;
95512cbf1dSJens Wiklander 		else
96512cbf1dSJens Wiklander 			allowed = !mechanism_is_one_shot_only(mechanism_type);
97512cbf1dSJens Wiklander 		break;
98512cbf1dSJens Wiklander 
99512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_FINAL:
100512cbf1dSJens Wiklander 		if (session->processing->always_authen &&
101512cbf1dSJens Wiklander 		    !session->processing->relogged)
102512cbf1dSJens Wiklander 			return PKCS11_CKR_USER_NOT_LOGGED_IN;
103512cbf1dSJens Wiklander 
104512cbf1dSJens Wiklander 		return PKCS11_CKR_OK;
105512cbf1dSJens Wiklander 
106512cbf1dSJens Wiklander 	default:
107512cbf1dSJens Wiklander 		TEE_Panic(step);
108512cbf1dSJens Wiklander 		break;
109512cbf1dSJens Wiklander 	}
110512cbf1dSJens Wiklander 
111512cbf1dSJens Wiklander 	if (!allowed) {
112512cbf1dSJens Wiklander 		EMSG("Processing %#x/%s not permitted (%u/%u)",
113512cbf1dSJens Wiklander 		     (unsigned int)mechanism_type, id2str_proc(mechanism_type),
114512cbf1dSJens Wiklander 		     function, step);
115512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
116512cbf1dSJens Wiklander 	}
117512cbf1dSJens Wiklander 
118512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
119512cbf1dSJens Wiklander }
120512cbf1dSJens Wiklander 
12163f89caaSJens Wiklander /*
12263f89caaSJens Wiklander  * Object default boolean attributes as per PKCS#11
12363f89caaSJens Wiklander  */
12463f89caaSJens Wiklander static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute)
12563f89caaSJens Wiklander {
12663f89caaSJens Wiklander 	static const uint8_t bool_true = 1;
12763f89caaSJens Wiklander 	static const uint8_t bool_false;
12863f89caaSJens Wiklander 
12963f89caaSJens Wiklander 	switch (attribute) {
13063f89caaSJens Wiklander 	/* As per PKCS#11 default value */
13163f89caaSJens Wiklander 	case PKCS11_CKA_MODIFIABLE:
13263f89caaSJens Wiklander 	case PKCS11_CKA_COPYABLE:
13363f89caaSJens Wiklander 	case PKCS11_CKA_DESTROYABLE:
13463f89caaSJens Wiklander 		return (uint8_t *)&bool_true;
13563f89caaSJens Wiklander 	case PKCS11_CKA_TOKEN:
13663f89caaSJens Wiklander 	case PKCS11_CKA_PRIVATE:
13763f89caaSJens Wiklander 	/* symkey false, privkey: token specific */
13863f89caaSJens Wiklander 	case PKCS11_CKA_SENSITIVE:
13963f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
14063f89caaSJens Wiklander 	/* Token specific default value */
14163f89caaSJens Wiklander 	case PKCS11_CKA_SIGN:
14263f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY:
14363f89caaSJens Wiklander 		return (uint8_t *)&bool_true;
14463f89caaSJens Wiklander 	case PKCS11_CKA_DERIVE:
14563f89caaSJens Wiklander 	case PKCS11_CKA_ENCRYPT:
14663f89caaSJens Wiklander 	case PKCS11_CKA_DECRYPT:
14763f89caaSJens Wiklander 	case PKCS11_CKA_SIGN_RECOVER:
14863f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY_RECOVER:
14963f89caaSJens Wiklander 	case PKCS11_CKA_WRAP:
15063f89caaSJens Wiklander 	case PKCS11_CKA_UNWRAP:
15163f89caaSJens Wiklander 	case PKCS11_CKA_EXTRACTABLE:
15263f89caaSJens Wiklander 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
15363f89caaSJens Wiklander 	case PKCS11_CKA_ALWAYS_AUTHENTICATE:
15463f89caaSJens Wiklander 	case PKCS11_CKA_TRUSTED:
15563f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
15663f89caaSJens Wiklander 	default:
15763f89caaSJens Wiklander 		DMSG("No default for boolprop attribute %#"PRIx32, attribute);
15863f89caaSJens Wiklander 		return NULL;
15963f89caaSJens Wiklander 	}
16063f89caaSJens Wiklander }
16163f89caaSJens Wiklander 
16263f89caaSJens Wiklander /*
16363f89caaSJens Wiklander  * Object expects several boolean attributes to be set to a default value
16463f89caaSJens Wiklander  * or to a validate client configuration value. This function append the input
16563f89caaSJens Wiklander  * attribute (id/size/value) in the serialized object.
16663f89caaSJens Wiklander  */
16763f89caaSJens Wiklander static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out,
16863f89caaSJens Wiklander 						    struct obj_attrs *templ,
16963f89caaSJens Wiklander 						    uint32_t attribute)
17063f89caaSJens Wiklander {
17163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
17263f89caaSJens Wiklander 	uint8_t bbool = 0;
17363f89caaSJens Wiklander 	uint32_t size = sizeof(uint8_t);
17463f89caaSJens Wiklander 	void *attr = NULL;
17563f89caaSJens Wiklander 
17663f89caaSJens Wiklander 	rc = get_attribute(templ, attribute, &bbool, &size);
17763f89caaSJens Wiklander 	if (rc) {
17863f89caaSJens Wiklander 		if (rc != PKCS11_RV_NOT_FOUND)
17963f89caaSJens Wiklander 			return rc;
18063f89caaSJens Wiklander 		attr = pkcs11_object_default_boolprop(attribute);
18163f89caaSJens Wiklander 		if (!attr)
18263f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
18363f89caaSJens Wiklander 	} else {
18463f89caaSJens Wiklander 		attr = &bbool;
18563f89caaSJens Wiklander 	}
18663f89caaSJens Wiklander 
18763f89caaSJens Wiklander 	/* Boolean attributes are 1byte in the ABI, no alignment issue */
18863f89caaSJens Wiklander 	return add_attribute(out, attribute, attr, sizeof(uint8_t));
18963f89caaSJens Wiklander }
19063f89caaSJens Wiklander 
19163f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out,
19263f89caaSJens Wiklander 					      struct obj_attrs *temp,
19363f89caaSJens Wiklander 					      uint32_t const *bp,
19463f89caaSJens Wiklander 					      size_t bp_count)
19563f89caaSJens Wiklander {
19663f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
19763f89caaSJens Wiklander 	size_t n = 0;
19863f89caaSJens Wiklander 
19963f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
20063f89caaSJens Wiklander 		rc = pkcs11_import_object_boolprop(out, temp, bp[n]);
20163f89caaSJens Wiklander 		if (rc)
20263f89caaSJens Wiklander 			return rc;
20363f89caaSJens Wiklander 	}
20463f89caaSJens Wiklander 
20563f89caaSJens Wiklander 	return rc;
20663f89caaSJens Wiklander }
20763f89caaSJens Wiklander 
20863f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out,
20963f89caaSJens Wiklander 					       struct obj_attrs *temp,
21063f89caaSJens Wiklander 					       uint32_t const *bp,
21163f89caaSJens Wiklander 					       size_t bp_count)
21263f89caaSJens Wiklander {
21363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
21463f89caaSJens Wiklander 	size_t n = 0;
21563f89caaSJens Wiklander 
21663f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
21763f89caaSJens Wiklander 		uint32_t size = 0;
21863f89caaSJens Wiklander 		void *value = NULL;
21963f89caaSJens Wiklander 
22063f89caaSJens Wiklander 		if (get_attribute_ptr(temp, bp[n], &value, &size))
22163f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
22263f89caaSJens Wiklander 
22363f89caaSJens Wiklander 		rc = add_attribute(out, bp[n], value, size);
22463f89caaSJens Wiklander 		if (rc)
22563f89caaSJens Wiklander 			return rc;
22663f89caaSJens Wiklander 	}
22763f89caaSJens Wiklander 
22863f89caaSJens Wiklander 	return rc;
22963f89caaSJens Wiklander }
23063f89caaSJens Wiklander 
23163f89caaSJens Wiklander static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value,
23263f89caaSJens Wiklander 					uint32_t *size)
23363f89caaSJens Wiklander {
23463f89caaSJens Wiklander 	/* should have been taken care of already */
23563f89caaSJens Wiklander 	assert(!pkcs11_attr_is_boolean(id));
23663f89caaSJens Wiklander 
23763f89caaSJens Wiklander 	if (id == PKCS11_CKA_PUBLIC_KEY_INFO) {
23863f89caaSJens Wiklander 		EMSG("Cannot provide default PUBLIC_KEY_INFO");
23963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
24063f89caaSJens Wiklander 	}
24163f89caaSJens Wiklander 
24263f89caaSJens Wiklander 	/* All other attributes have an empty default value */
24363f89caaSJens Wiklander 	*value = NULL;
24463f89caaSJens Wiklander 	*size = 0;
24563f89caaSJens Wiklander 	return PKCS11_CKR_OK;
24663f89caaSJens Wiklander }
24763f89caaSJens Wiklander 
248*4eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out,
24963f89caaSJens Wiklander 						       struct obj_attrs *temp,
25063f89caaSJens Wiklander 						       uint32_t const *bp,
251*4eb88651SRuchika Gupta 						       size_t bp_count,
252*4eb88651SRuchika Gupta 						       bool default_to_null)
25363f89caaSJens Wiklander {
25463f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
25563f89caaSJens Wiklander 	size_t n = 0;
25663f89caaSJens Wiklander 
25763f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
25863f89caaSJens Wiklander 		uint32_t size = 0;
25963f89caaSJens Wiklander 		void *value = NULL;
26063f89caaSJens Wiklander 
26163f89caaSJens Wiklander 		rc = get_attribute_ptr(temp, bp[n], &value, &size);
262*4eb88651SRuchika Gupta 		if (rc == PKCS11_RV_NOT_FOUND) {
263*4eb88651SRuchika Gupta 			if (default_to_null) {
26463f89caaSJens Wiklander 				rc = get_default_value(bp[n], &value, &size);
265*4eb88651SRuchika Gupta 			} else {
266*4eb88651SRuchika Gupta 				rc = PKCS11_CKR_OK;
267*4eb88651SRuchika Gupta 				continue;
268*4eb88651SRuchika Gupta 			}
269*4eb88651SRuchika Gupta 		}
27063f89caaSJens Wiklander 		if (rc)
27163f89caaSJens Wiklander 			return rc;
27263f89caaSJens Wiklander 
27363f89caaSJens Wiklander 		rc = add_attribute(out, bp[n], value, size);
27463f89caaSJens Wiklander 		if (rc)
27563f89caaSJens Wiklander 			return rc;
27663f89caaSJens Wiklander 	}
27763f89caaSJens Wiklander 
27863f89caaSJens Wiklander 	return rc;
27963f89caaSJens Wiklander }
28063f89caaSJens Wiklander 
281*4eb88651SRuchika Gupta static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out,
282*4eb88651SRuchika Gupta 						 struct obj_attrs *temp,
283*4eb88651SRuchika Gupta 						 uint32_t const *bp,
284*4eb88651SRuchika Gupta 						 size_t bp_count)
285*4eb88651SRuchika Gupta {
286*4eb88651SRuchika Gupta 	return set_optional_attributes_with_def(out, temp, bp, bp_count, true);
287*4eb88651SRuchika Gupta }
288*4eb88651SRuchika Gupta 
289*4eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out,
290*4eb88651SRuchika Gupta 					      struct obj_attrs *temp,
291*4eb88651SRuchika Gupta 					      uint32_t const *bp,
292*4eb88651SRuchika Gupta 					      size_t bp_count)
293*4eb88651SRuchika Gupta {
294*4eb88651SRuchika Gupta 	return set_optional_attributes_with_def(out, temp, bp, bp_count, false);
295*4eb88651SRuchika Gupta }
296*4eb88651SRuchika Gupta 
29763f89caaSJens Wiklander /*
29863f89caaSJens Wiklander  * Below are listed the mandated or optional expected attributes for
29963f89caaSJens Wiklander  * PKCS#11 storage objects.
30063f89caaSJens Wiklander  *
30163f89caaSJens Wiklander  * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE,
30263f89caaSJens Wiklander  * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided
30363f89caaSJens Wiklander  * in the client template.
30463f89caaSJens Wiklander  */
30563f89caaSJens Wiklander 
30663f89caaSJens Wiklander /* PKCS#11 specification for any object (session/token) of the storage */
307*4eb88651SRuchika Gupta static const uint32_t any_object_boolprops[] = {
30863f89caaSJens Wiklander 	PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
30963f89caaSJens Wiklander 	PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE,
31063f89caaSJens Wiklander };
31163f89caaSJens Wiklander 
312*4eb88651SRuchika Gupta static const uint32_t any_object_opt_or_null[] = {
31363f89caaSJens Wiklander 	PKCS11_CKA_LABEL,
31463f89caaSJens Wiklander };
31563f89caaSJens Wiklander 
316*4eb88651SRuchika Gupta /* PKCS#11 specification for raw data object (+any_object_xxx) */
317*4eb88651SRuchika Gupta const uint32_t raw_data_opt_or_null[] = {
31863f89caaSJens Wiklander 	PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE,
31963f89caaSJens Wiklander };
32063f89caaSJens Wiklander 
321*4eb88651SRuchika Gupta /* PKCS#11 specification for any key object (+any_object_xxx) */
322*4eb88651SRuchika Gupta static const uint32_t any_key_boolprops[] = {
32363f89caaSJens Wiklander 	PKCS11_CKA_DERIVE,
32463f89caaSJens Wiklander };
32563f89caaSJens Wiklander 
326*4eb88651SRuchika Gupta static const uint32_t any_key_opt_or_null[] = {
32763f89caaSJens Wiklander 	PKCS11_CKA_ID,
32863f89caaSJens Wiklander 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE,
329*4eb88651SRuchika Gupta };
330*4eb88651SRuchika Gupta 
331*4eb88651SRuchika Gupta static const uint32_t any_key_optional[] = {
33263f89caaSJens Wiklander 	PKCS11_CKA_ALLOWED_MECHANISMS,
33363f89caaSJens Wiklander };
33463f89caaSJens Wiklander 
335*4eb88651SRuchika Gupta /* PKCS#11 specification for any symmetric key (+any_key_xxx) */
336*4eb88651SRuchika Gupta static const uint32_t symm_key_boolprops[] = {
33763f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT,
33863f89caaSJens Wiklander 	PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY,
33963f89caaSJens Wiklander 	PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP,
34063f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
34163f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED,
34263f89caaSJens Wiklander };
34363f89caaSJens Wiklander 
344*4eb88651SRuchika Gupta static const uint32_t symm_key_opt_or_null[] = {
34563f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE,
34663f89caaSJens Wiklander 	PKCS11_CKA_DERIVE_TEMPLATE,
34763f89caaSJens Wiklander 	PKCS11_CKA_VALUE, PKCS11_CKA_VALUE_LEN,
34863f89caaSJens Wiklander };
34963f89caaSJens Wiklander 
350*4eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
351*4eb88651SRuchika Gupta static const uint32_t public_key_boolprops[] = {
35263f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER,
35363f89caaSJens Wiklander 	PKCS11_CKA_WRAP,
35463f89caaSJens Wiklander 	PKCS11_CKA_TRUSTED,
35563f89caaSJens Wiklander };
35663f89caaSJens Wiklander 
357*4eb88651SRuchika Gupta static const uint32_t public_key_mandated[] = {
35863f89caaSJens Wiklander 	PKCS11_CKA_SUBJECT
35963f89caaSJens Wiklander };
36063f89caaSJens Wiklander 
361*4eb88651SRuchika Gupta static const uint32_t public_key_opt_or_null[] = {
36263f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO,
36363f89caaSJens Wiklander };
36463f89caaSJens Wiklander 
365*4eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */
366*4eb88651SRuchika Gupta static const uint32_t private_key_boolprops[] = {
36763f89caaSJens Wiklander 	PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER,
36863f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP,
36963f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
37063f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE,
37163f89caaSJens Wiklander };
37263f89caaSJens Wiklander 
373*4eb88651SRuchika Gupta static const uint32_t private_key_mandated[] = {
37463f89caaSJens Wiklander 	PKCS11_CKA_SUBJECT
37563f89caaSJens Wiklander };
37663f89caaSJens Wiklander 
377*4eb88651SRuchika Gupta static const uint32_t private_key_opt_or_null[] = {
37863f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO,
37963f89caaSJens Wiklander };
38063f89caaSJens Wiklander 
381*4eb88651SRuchika Gupta /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */
382*4eb88651SRuchika Gupta static const uint32_t rsa_public_key_mandated[] = {
38363f89caaSJens Wiklander 	PKCS11_CKA_MODULUS_BITS,
38463f89caaSJens Wiklander };
38563f89caaSJens Wiklander 
386*4eb88651SRuchika Gupta static const uint32_t rsa_public_key_opt_or_null[] = {
38763f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
38863f89caaSJens Wiklander };
38963f89caaSJens Wiklander 
390*4eb88651SRuchika Gupta static const uint32_t rsa_private_key_opt_or_null[] = {
39163f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
39263f89caaSJens Wiklander 	PKCS11_CKA_PRIVATE_EXPONENT,
39363f89caaSJens Wiklander 	PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2,
39463f89caaSJens Wiklander 	PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT,
39563f89caaSJens Wiklander };
39663f89caaSJens Wiklander 
397*4eb88651SRuchika Gupta /* PKCS#11 specification for any EC key (+public/private_key_xxx) */
398*4eb88651SRuchika Gupta static const uint32_t ec_public_key_mandated[] = {
39963f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
40063f89caaSJens Wiklander };
40163f89caaSJens Wiklander 
402*4eb88651SRuchika Gupta static const uint32_t ec_public_key_opt_or_null[] = {
40363f89caaSJens Wiklander 	PKCS11_CKA_EC_POINT,
40463f89caaSJens Wiklander };
40563f89caaSJens Wiklander 
406*4eb88651SRuchika Gupta static const uint32_t ec_private_key_mandated[] = {
40763f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
40863f89caaSJens Wiklander };
40963f89caaSJens Wiklander 
410*4eb88651SRuchika Gupta static const uint32_t ec_private_key_opt_or_null[] = {
41163f89caaSJens Wiklander 	PKCS11_CKA_VALUE,
41263f89caaSJens Wiklander };
41363f89caaSJens Wiklander 
41463f89caaSJens Wiklander static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out,
41563f89caaSJens Wiklander 						struct obj_attrs *temp)
41663f89caaSJens Wiklander {
41763f89caaSJens Wiklander 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
41863f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
41963f89caaSJens Wiklander 
42063f89caaSJens Wiklander 	rc = init_attributes_head(out);
42163f89caaSJens Wiklander 	if (rc)
42263f89caaSJens Wiklander 		return rc;
42363f89caaSJens Wiklander 
42463f89caaSJens Wiklander 	/* Object class is mandatory */
42563f89caaSJens Wiklander 	class = get_class(temp);
42663f89caaSJens Wiklander 	if (class == PKCS11_CKO_UNDEFINED_ID) {
42763f89caaSJens Wiklander 		EMSG("Class attribute not found");
42863f89caaSJens Wiklander 
42963f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
43063f89caaSJens Wiklander 	}
43163f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t));
43263f89caaSJens Wiklander 	if (rc)
43363f89caaSJens Wiklander 		return rc;
43463f89caaSJens Wiklander 
435*4eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_object_boolprops,
436*4eb88651SRuchika Gupta 				     ARRAY_SIZE(any_object_boolprops));
43763f89caaSJens Wiklander 	if (rc)
43863f89caaSJens Wiklander 		return rc;
43963f89caaSJens Wiklander 
440*4eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, any_object_opt_or_null,
441*4eb88651SRuchika Gupta 					  ARRAY_SIZE(any_object_opt_or_null));
44263f89caaSJens Wiklander }
44363f89caaSJens Wiklander 
44463f89caaSJens Wiklander static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out,
44563f89caaSJens Wiklander 					       struct obj_attrs *temp)
44663f89caaSJens Wiklander {
44763f89caaSJens Wiklander 	uint32_t type = PKCS11_CKO_UNDEFINED_ID;
44863f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
44963f89caaSJens Wiklander 
45063f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
45163f89caaSJens Wiklander 	if (rc)
45263f89caaSJens Wiklander 		return rc;
45363f89caaSJens Wiklander 
45463f89caaSJens Wiklander 	type = get_key_type(temp);
45563f89caaSJens Wiklander 	if (type == PKCS11_CKK_UNDEFINED_ID) {
45663f89caaSJens Wiklander 		EMSG("Key type attribute not found");
45763f89caaSJens Wiklander 
45863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
45963f89caaSJens Wiklander 	}
46063f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t));
46163f89caaSJens Wiklander 	if (rc)
46263f89caaSJens Wiklander 		return rc;
46363f89caaSJens Wiklander 
464*4eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_key_boolprops,
465*4eb88651SRuchika Gupta 				     ARRAY_SIZE(any_key_boolprops));
46663f89caaSJens Wiklander 	if (rc)
46763f89caaSJens Wiklander 		return rc;
46863f89caaSJens Wiklander 
469*4eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null,
470*4eb88651SRuchika Gupta 					ARRAY_SIZE(any_key_opt_or_null));
471*4eb88651SRuchika Gupta 	if (rc)
472*4eb88651SRuchika Gupta 		return rc;
473*4eb88651SRuchika Gupta 
474*4eb88651SRuchika Gupta 	return set_optional_attributes(out, temp, any_key_optional,
475*4eb88651SRuchika Gupta 				       ARRAY_SIZE(any_key_optional));
476*4eb88651SRuchika Gupta 
47763f89caaSJens Wiklander }
47863f89caaSJens Wiklander 
47963f89caaSJens Wiklander static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out,
48063f89caaSJens Wiklander 						 struct obj_attrs *temp)
48163f89caaSJens Wiklander {
48263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
48363f89caaSJens Wiklander 
48463f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_SECRET_KEY);
48563f89caaSJens Wiklander 
48663f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
48763f89caaSJens Wiklander 	if (rc)
48863f89caaSJens Wiklander 		return rc;
48963f89caaSJens Wiklander 
49063f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_SECRET_KEY);
49163f89caaSJens Wiklander 
49263f89caaSJens Wiklander 	switch (get_key_type(*out)) {
49363f89caaSJens Wiklander 	case PKCS11_CKK_GENERIC_SECRET:
49463f89caaSJens Wiklander 	case PKCS11_CKK_AES:
49563f89caaSJens Wiklander 	case PKCS11_CKK_MD5_HMAC:
49663f89caaSJens Wiklander 	case PKCS11_CKK_SHA_1_HMAC:
49763f89caaSJens Wiklander 	case PKCS11_CKK_SHA256_HMAC:
49863f89caaSJens Wiklander 	case PKCS11_CKK_SHA384_HMAC:
49963f89caaSJens Wiklander 	case PKCS11_CKK_SHA512_HMAC:
50063f89caaSJens Wiklander 	case PKCS11_CKK_SHA224_HMAC:
50163f89caaSJens Wiklander 		break;
50263f89caaSJens Wiklander 	default:
50363f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
50463f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
50563f89caaSJens Wiklander 
50663f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
50763f89caaSJens Wiklander 	}
50863f89caaSJens Wiklander 
509*4eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, symm_key_boolprops,
510*4eb88651SRuchika Gupta 				     ARRAY_SIZE(symm_key_boolprops));
51163f89caaSJens Wiklander 	if (rc)
51263f89caaSJens Wiklander 		return rc;
51363f89caaSJens Wiklander 
514*4eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, symm_key_opt_or_null,
515*4eb88651SRuchika Gupta 					  ARRAY_SIZE(symm_key_opt_or_null));
51663f89caaSJens Wiklander }
51763f89caaSJens Wiklander 
51863f89caaSJens Wiklander static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
51963f89caaSJens Wiklander 					     struct obj_attrs *temp)
52063f89caaSJens Wiklander {
52163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
52263f89caaSJens Wiklander 
52363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_DATA);
52463f89caaSJens Wiklander 
52563f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
52663f89caaSJens Wiklander 	if (rc)
52763f89caaSJens Wiklander 		return rc;
52863f89caaSJens Wiklander 
52963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_DATA);
53063f89caaSJens Wiklander 
531*4eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null,
532*4eb88651SRuchika Gupta 					  ARRAY_SIZE(raw_data_opt_or_null));
53363f89caaSJens Wiklander }
53463f89caaSJens Wiklander 
53563f89caaSJens Wiklander static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
53663f89caaSJens Wiklander 						struct obj_attrs *temp)
53763f89caaSJens Wiklander {
53863f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
539*4eb88651SRuchika Gupta 	uint32_t const *opt_or_null = NULL;
54063f89caaSJens Wiklander 	size_t mandated_count = 0;
541*4eb88651SRuchika Gupta 	size_t opt_or_null_count = 0;
54263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
54363f89caaSJens Wiklander 
54463f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY);
54563f89caaSJens Wiklander 
54663f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
54763f89caaSJens Wiklander 	if (rc)
54863f89caaSJens Wiklander 		return rc;
54963f89caaSJens Wiklander 
55063f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY);
55163f89caaSJens Wiklander 
552*4eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, public_key_boolprops,
553*4eb88651SRuchika Gupta 				     ARRAY_SIZE(public_key_boolprops));
55463f89caaSJens Wiklander 	if (rc)
55563f89caaSJens Wiklander 		return rc;
55663f89caaSJens Wiklander 
557*4eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, public_key_mandated,
558*4eb88651SRuchika Gupta 				      ARRAY_SIZE(public_key_mandated));
55963f89caaSJens Wiklander 	if (rc)
56063f89caaSJens Wiklander 		return rc;
56163f89caaSJens Wiklander 
562*4eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp,
563*4eb88651SRuchika Gupta 					public_key_opt_or_null,
564*4eb88651SRuchika Gupta 					ARRAY_SIZE(public_key_opt_or_null));
56563f89caaSJens Wiklander 	if (rc)
56663f89caaSJens Wiklander 		return rc;
56763f89caaSJens Wiklander 
56863f89caaSJens Wiklander 	switch (get_key_type(*out)) {
56963f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
570*4eb88651SRuchika Gupta 		mandated = rsa_public_key_mandated;
571*4eb88651SRuchika Gupta 		opt_or_null = rsa_public_key_opt_or_null;
572*4eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(rsa_public_key_mandated);
573*4eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(rsa_public_key_opt_or_null);
57463f89caaSJens Wiklander 		break;
57563f89caaSJens Wiklander 	case PKCS11_CKK_EC:
576*4eb88651SRuchika Gupta 		mandated = ec_public_key_mandated;
577*4eb88651SRuchika Gupta 		opt_or_null = ec_public_key_opt_or_null;
578*4eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_public_key_mandated);
579*4eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(ec_public_key_opt_or_null);
58063f89caaSJens Wiklander 		break;
58163f89caaSJens Wiklander 	default:
58263f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
58363f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
58463f89caaSJens Wiklander 
58563f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
58663f89caaSJens Wiklander 	}
58763f89caaSJens Wiklander 
58863f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
58963f89caaSJens Wiklander 	if (rc)
59063f89caaSJens Wiklander 		return rc;
59163f89caaSJens Wiklander 
592*4eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, opt_or_null,
593*4eb88651SRuchika Gupta 					  opt_or_null_count);
59463f89caaSJens Wiklander }
59563f89caaSJens Wiklander 
59663f89caaSJens Wiklander static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out,
59763f89caaSJens Wiklander 						 struct obj_attrs *temp)
59863f89caaSJens Wiklander {
59963f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
600*4eb88651SRuchika Gupta 	uint32_t const *opt_or_null = NULL;
60163f89caaSJens Wiklander 	size_t mandated_count = 0;
602*4eb88651SRuchika Gupta 	size_t opt_or_null_count = 0;
60363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
60463f89caaSJens Wiklander 
60563f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY);
60663f89caaSJens Wiklander 
60763f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
60863f89caaSJens Wiklander 	if (rc)
60963f89caaSJens Wiklander 		return rc;
61063f89caaSJens Wiklander 
61163f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY);
61263f89caaSJens Wiklander 
613*4eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, private_key_boolprops,
614*4eb88651SRuchika Gupta 				     ARRAY_SIZE(private_key_boolprops));
61563f89caaSJens Wiklander 	if (rc)
61663f89caaSJens Wiklander 		return rc;
61763f89caaSJens Wiklander 
618*4eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, private_key_mandated,
619*4eb88651SRuchika Gupta 				      ARRAY_SIZE(private_key_mandated));
62063f89caaSJens Wiklander 	if (rc)
62163f89caaSJens Wiklander 		return rc;
62263f89caaSJens Wiklander 
623*4eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null,
624*4eb88651SRuchika Gupta 					ARRAY_SIZE(private_key_opt_or_null));
62563f89caaSJens Wiklander 	if (rc)
62663f89caaSJens Wiklander 		return rc;
62763f89caaSJens Wiklander 
62863f89caaSJens Wiklander 	switch (get_key_type(*out)) {
62963f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
630*4eb88651SRuchika Gupta 		opt_or_null = rsa_private_key_opt_or_null;
631*4eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(rsa_private_key_opt_or_null);
63263f89caaSJens Wiklander 		break;
63363f89caaSJens Wiklander 	case PKCS11_CKK_EC:
634*4eb88651SRuchika Gupta 		mandated = ec_private_key_mandated;
635*4eb88651SRuchika Gupta 		opt_or_null = ec_private_key_opt_or_null;
636*4eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
637*4eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(ec_private_key_opt_or_null);
63863f89caaSJens Wiklander 		break;
63963f89caaSJens Wiklander 	default:
64063f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
64163f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
64263f89caaSJens Wiklander 
64363f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
64463f89caaSJens Wiklander 	}
64563f89caaSJens Wiklander 
64663f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
64763f89caaSJens Wiklander 	if (rc)
64863f89caaSJens Wiklander 		return rc;
64963f89caaSJens Wiklander 
650*4eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, opt_or_null,
651*4eb88651SRuchika Gupta 					  opt_or_null_count);
65263f89caaSJens Wiklander }
65363f89caaSJens Wiklander 
65463f89caaSJens Wiklander /*
65563f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
65663f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
65763f89caaSJens Wiklander  * derive...).
65863f89caaSJens Wiklander  *
65963f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
66063f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
66163f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
66263f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
66363f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
66463f89caaSJens Wiklander  *
66563f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
66663f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
66763f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
66863f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
66963f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
67063f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
67163f89caaSJens Wiklander  */
67263f89caaSJens Wiklander enum pkcs11_rc
67363f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
67463f89caaSJens Wiklander 				size_t template_size,
67563f89caaSJens Wiklander 				struct obj_attrs *parent __unused,
67663f89caaSJens Wiklander 				enum processing_func function,
67763f89caaSJens Wiklander 				enum pkcs11_mechanism_id mecha __unused)
67863f89caaSJens Wiklander {
67963f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
68063f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
68163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
68263f89caaSJens Wiklander 	uint8_t local = 0;
68363f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
68463f89caaSJens Wiklander 	uint8_t never_extract = 0;
68563f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
68663f89caaSJens Wiklander 
68763f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
68863f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
68963f89caaSJens Wiklander 	switch (function) {
69063f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
69163f89caaSJens Wiklander 		break;
69263f89caaSJens Wiklander 	default:
69363f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
69463f89caaSJens Wiklander 	}
69563f89caaSJens Wiklander #endif
69663f89caaSJens Wiklander 
69763f89caaSJens Wiklander 	rc = sanitize_client_object(&temp, template, template_size);
69863f89caaSJens Wiklander 	if (rc)
69963f89caaSJens Wiklander 		goto out;
70063f89caaSJens Wiklander 
70163f89caaSJens Wiklander 	/* If class/type not defined, match from mechanism */
70263f89caaSJens Wiklander 	if (get_class(temp) == PKCS11_UNDEFINED_ID &&
70363f89caaSJens Wiklander 	    get_key_type(temp) == PKCS11_UNDEFINED_ID) {
70463f89caaSJens Wiklander 		EMSG("Unable to define class/type from mechanism");
70563f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCOMPLETE;
70663f89caaSJens Wiklander 		goto out;
70763f89caaSJens Wiklander 	}
70863f89caaSJens Wiklander 
70963f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
71063f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
71163f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
71263f89caaSJens Wiklander 		goto out;
71363f89caaSJens Wiklander 	}
71463f89caaSJens Wiklander 
71563f89caaSJens Wiklander 	switch (get_class(temp)) {
71663f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
71763f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
71863f89caaSJens Wiklander 		break;
71963f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
72063f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
72163f89caaSJens Wiklander 		break;
72263f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
72363f89caaSJens Wiklander 		rc = create_pub_key_attributes(&attrs, temp);
72463f89caaSJens Wiklander 		break;
72563f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
72663f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
72763f89caaSJens Wiklander 		break;
72863f89caaSJens Wiklander 	default:
72963f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
73063f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
73163f89caaSJens Wiklander 
73263f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
73363f89caaSJens Wiklander 		break;
73463f89caaSJens Wiklander 	}
73563f89caaSJens Wiklander 	if (rc)
73663f89caaSJens Wiklander 		goto out;
73763f89caaSJens Wiklander 
73863f89caaSJens Wiklander 	if (get_attribute(attrs, PKCS11_CKA_LOCAL, NULL, NULL) !=
73963f89caaSJens Wiklander 	    PKCS11_RV_NOT_FOUND)
74063f89caaSJens Wiklander 		goto out;
74163f89caaSJens Wiklander 
74263f89caaSJens Wiklander 	if (get_attribute(attrs, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
74363f89caaSJens Wiklander 	    PKCS11_RV_NOT_FOUND)
74463f89caaSJens Wiklander 		goto out;
74563f89caaSJens Wiklander 
74663f89caaSJens Wiklander 	switch (function) {
74763f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
74863f89caaSJens Wiklander 	default:
74963f89caaSJens Wiklander 		local = PKCS11_FALSE;
75063f89caaSJens Wiklander 		break;
75163f89caaSJens Wiklander 	}
75263f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
75363f89caaSJens Wiklander 	if (rc)
75463f89caaSJens Wiklander 		goto out;
75563f89caaSJens Wiklander 
75663f89caaSJens Wiklander 	switch (get_class(attrs)) {
75763f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
75863f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
75963f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
76063f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
76163f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
76263f89caaSJens Wiklander 
76363f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
76463f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
76563f89caaSJens Wiklander 		if (rc)
76663f89caaSJens Wiklander 			goto out;
76763f89caaSJens Wiklander 
76863f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
76963f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
77063f89caaSJens Wiklander 		if (rc)
77163f89caaSJens Wiklander 			goto out;
77263f89caaSJens Wiklander 
77363f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
77463f89caaSJens Wiklander 		mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
77563f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
77663f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
77763f89caaSJens Wiklander 		if (rc)
77863f89caaSJens Wiklander 			goto out;
77963f89caaSJens Wiklander 		break;
78063f89caaSJens Wiklander 
78163f89caaSJens Wiklander 	default:
78263f89caaSJens Wiklander 		break;
78363f89caaSJens Wiklander 	}
78463f89caaSJens Wiklander 
78563f89caaSJens Wiklander 	*out = attrs;
78663f89caaSJens Wiklander 
78763f89caaSJens Wiklander #ifdef DEBUG
78863f89caaSJens Wiklander 	trace_attributes("object", attrs);
78963f89caaSJens Wiklander #endif
79063f89caaSJens Wiklander 
79163f89caaSJens Wiklander out:
79263f89caaSJens Wiklander 	TEE_Free(temp);
79363f89caaSJens Wiklander 	if (rc)
79463f89caaSJens Wiklander 		TEE_Free(attrs);
79563f89caaSJens Wiklander 
79663f89caaSJens Wiklander 	return rc;
79763f89caaSJens Wiklander }
79863f89caaSJens Wiklander 
79963f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
80063f89caaSJens Wiklander {
80163f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
80263f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
80363f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
80463f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
80563f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
80663f89caaSJens Wiklander 
80763f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
80863f89caaSJens Wiklander 	}
80963f89caaSJens Wiklander 
81063f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
81163f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
81263f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
81363f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
81463f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
81563f89caaSJens Wiklander 
81663f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
81763f89caaSJens Wiklander 	}
81863f89caaSJens Wiklander 
81963f89caaSJens Wiklander 	return PKCS11_CKR_OK;
82063f89caaSJens Wiklander }
82163f89caaSJens Wiklander 
82263f89caaSJens Wiklander /*
823512cbf1dSJens Wiklander  * Check access to object against authentication to token
824512cbf1dSJens Wiklander  */
825512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
826512cbf1dSJens Wiklander 						struct obj_attrs *head)
827512cbf1dSJens Wiklander {
828512cbf1dSJens Wiklander 	bool private = true;
829512cbf1dSJens Wiklander 
830512cbf1dSJens Wiklander 	switch (get_class(head)) {
831512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
832512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
833512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
834512cbf1dSJens Wiklander 		private = get_bool(head, PKCS11_CKA_PRIVATE);
835512cbf1dSJens Wiklander 		break;
836512cbf1dSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
837512cbf1dSJens Wiklander 		break;
838512cbf1dSJens Wiklander 	default:
839512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
840512cbf1dSJens Wiklander 	}
841512cbf1dSJens Wiklander 
842512cbf1dSJens Wiklander 	if (private && pkcs11_session_is_public(session)) {
843512cbf1dSJens Wiklander 		DMSG("Private object access from a public session");
844512cbf1dSJens Wiklander 
845512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
846512cbf1dSJens Wiklander 	}
847512cbf1dSJens Wiklander 
848512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
849512cbf1dSJens Wiklander }
850512cbf1dSJens Wiklander 
851512cbf1dSJens Wiklander /*
85263f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
85363f89caaSJens Wiklander  */
85463f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
85563f89caaSJens Wiklander 						 struct obj_attrs *head)
85663f89caaSJens Wiklander {
85763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
85863f89caaSJens Wiklander 
85963f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
86063f89caaSJens Wiklander 	if (rc)
86163f89caaSJens Wiklander 		return rc;
86263f89caaSJens Wiklander 
86363f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
86463f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
86563f89caaSJens Wiklander 		DMSG("Can't create trusted object");
86663f89caaSJens Wiklander 
86763f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
86863f89caaSJens Wiklander 	}
86963f89caaSJens Wiklander 
87063f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
87163f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
87263f89caaSJens Wiklander 		DMSG("Can't create persistent object");
87363f89caaSJens Wiklander 
87463f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
87563f89caaSJens Wiklander 	}
87663f89caaSJens Wiklander 
87763f89caaSJens Wiklander 	/*
87863f89caaSJens Wiklander 	 * TODO: START_DATE and END_DATE: complies with current time?
87963f89caaSJens Wiklander 	 */
88063f89caaSJens Wiklander 	return PKCS11_CKR_OK;
88163f89caaSJens Wiklander }
88263f89caaSJens Wiklander 
88363f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
88463f89caaSJens Wiklander 	do {								\
88563f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
88663f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
88763f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
88863f89caaSJens Wiklander 									\
88963f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
89063f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
89163f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
89263f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
89363f89caaSJens Wiklander 	} while (0)
89463f89caaSJens Wiklander 
89563f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
89663f89caaSJens Wiklander 					   struct obj_attrs *head,
89763f89caaSJens Wiklander 					   uint32_t attribute, bool val)
89863f89caaSJens Wiklander {
89963f89caaSJens Wiklander 	uint8_t bbool = 0;
90063f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
90163f89caaSJens Wiklander 
90263f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
90363f89caaSJens Wiklander 		return true;
90463f89caaSJens Wiklander 
90563f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
90663f89caaSJens Wiklander 	return false;
90763f89caaSJens Wiklander }
90863f89caaSJens Wiklander 
90963f89caaSJens Wiklander /*
91063f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
91163f89caaSJens Wiklander  * used to create it.
91263f89caaSJens Wiklander  *
91363f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
91463f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
91563f89caaSJens Wiklander  */
91663f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
91763f89caaSJens Wiklander 						      struct obj_attrs *head)
91863f89caaSJens Wiklander {
91963f89caaSJens Wiklander 	/*
92063f89caaSJens Wiklander 	 * Processings that do not create secrets are not expected to call
92163f89caaSJens Wiklander 	 * this function which would panic.
92263f89caaSJens Wiklander 	 */
92363f89caaSJens Wiklander 	switch (proc_id) {
92463f89caaSJens Wiklander 	case PKCS11_PROCESSING_IMPORT:
92563f89caaSJens Wiklander 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
92663f89caaSJens Wiklander 		break;
92763f89caaSJens Wiklander 	default:
92863f89caaSJens Wiklander 		TEE_Panic(proc_id);
92963f89caaSJens Wiklander 		break;
93063f89caaSJens Wiklander 	}
93163f89caaSJens Wiklander 
93263f89caaSJens Wiklander 	return PKCS11_CKR_OK;
93363f89caaSJens Wiklander }
934512cbf1dSJens Wiklander 
935512cbf1dSJens Wiklander static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
936512cbf1dSJens Wiklander 				  uint32_t *min_key_size,
937512cbf1dSJens Wiklander 				  uint32_t *max_key_size)
938512cbf1dSJens Wiklander {
939512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
940512cbf1dSJens Wiklander 
941512cbf1dSJens Wiklander 	switch (key_type) {
942512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
943512cbf1dSJens Wiklander 		mechanism = PKCS11_CKM_AES_KEY_GEN;
944512cbf1dSJens Wiklander 		break;
945512cbf1dSJens Wiklander 	default:
946512cbf1dSJens Wiklander 		TEE_Panic(key_type);
947512cbf1dSJens Wiklander 		break;
948512cbf1dSJens Wiklander 	}
949512cbf1dSJens Wiklander 
950512cbf1dSJens Wiklander 	mechanism_supported_key_sizes(mechanism, min_key_size,
951512cbf1dSJens Wiklander 				      max_key_size);
952512cbf1dSJens Wiklander }
953512cbf1dSJens Wiklander 
954512cbf1dSJens Wiklander enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
955512cbf1dSJens Wiklander 				   struct obj_attrs *key2)
956512cbf1dSJens Wiklander {
957512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
958512cbf1dSJens Wiklander 	struct obj_attrs *secret = NULL;
959512cbf1dSJens Wiklander 	uint32_t max_key_size = 0;
960512cbf1dSJens Wiklander 	uint32_t min_key_size = 0;
961512cbf1dSJens Wiklander 	uint32_t key_length = 0;
962512cbf1dSJens Wiklander 
963512cbf1dSJens Wiklander 	switch (get_class(key1)) {
964512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
965512cbf1dSJens Wiklander 		secret = key1;
966512cbf1dSJens Wiklander 		break;
967512cbf1dSJens Wiklander 	default:
968512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
969512cbf1dSJens Wiklander 	}
970512cbf1dSJens Wiklander 
971512cbf1dSJens Wiklander 	if (key2)
972512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
973512cbf1dSJens Wiklander 
974512cbf1dSJens Wiklander 	if (secret) {
975512cbf1dSJens Wiklander 		switch (get_key_type(secret)) {
976512cbf1dSJens Wiklander 		case PKCS11_CKK_AES:
977512cbf1dSJens Wiklander 		case PKCS11_CKK_GENERIC_SECRET:
978512cbf1dSJens Wiklander 		case PKCS11_CKK_MD5_HMAC:
979512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA_1_HMAC:
980512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA224_HMAC:
981512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA256_HMAC:
982512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA384_HMAC:
983512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA512_HMAC:
984512cbf1dSJens Wiklander 			break;
985512cbf1dSJens Wiklander 		default:
986512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
987512cbf1dSJens Wiklander 		}
988512cbf1dSJens Wiklander 
989512cbf1dSJens Wiklander 		/* Get key size */
990512cbf1dSJens Wiklander 		rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN,
991512cbf1dSJens Wiklander 				       &key_length);
992512cbf1dSJens Wiklander 		if (rc)
993512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
994512cbf1dSJens Wiklander 	}
995512cbf1dSJens Wiklander 
996512cbf1dSJens Wiklander 	get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size);
997512cbf1dSJens Wiklander 	if (key_length < min_key_size || key_length > max_key_size) {
998512cbf1dSJens Wiklander 		EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]",
999512cbf1dSJens Wiklander 		     key_length, min_key_size, max_key_size);
1000512cbf1dSJens Wiklander 
1001512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_SIZE_RANGE;
1002512cbf1dSJens Wiklander 	}
1003512cbf1dSJens Wiklander 
1004512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1005512cbf1dSJens Wiklander }
1006512cbf1dSJens Wiklander 
1007512cbf1dSJens Wiklander /* Check processing ID against attribute ALLOWED_MECHANISMS if any */
1008512cbf1dSJens Wiklander static bool parent_key_complies_allowed_processings(uint32_t proc_id,
1009512cbf1dSJens Wiklander 						    struct obj_attrs *head)
1010512cbf1dSJens Wiklander {
1011512cbf1dSJens Wiklander 	char *attr = NULL;
1012512cbf1dSJens Wiklander 	uint32_t size = 0;
1013512cbf1dSJens Wiklander 	uint32_t proc = 0;
1014512cbf1dSJens Wiklander 	size_t count = 0;
1015512cbf1dSJens Wiklander 
1016512cbf1dSJens Wiklander 	/* Check only if restricted allowed mechanisms list is defined */
1017512cbf1dSJens Wiklander 	if (get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS,
1018512cbf1dSJens Wiklander 			      (void *)&attr, &size) != PKCS11_CKR_OK) {
1019512cbf1dSJens Wiklander 		return true;
1020512cbf1dSJens Wiklander 	}
1021512cbf1dSJens Wiklander 
1022512cbf1dSJens Wiklander 	for (count = size / sizeof(uint32_t); count; count--) {
1023512cbf1dSJens Wiklander 		TEE_MemMove(&proc, attr, sizeof(uint32_t));
1024512cbf1dSJens Wiklander 		attr += sizeof(uint32_t);
1025512cbf1dSJens Wiklander 
1026512cbf1dSJens Wiklander 		if (proc == proc_id)
1027512cbf1dSJens Wiklander 			return true;
1028512cbf1dSJens Wiklander 	}
1029512cbf1dSJens Wiklander 
1030512cbf1dSJens Wiklander 	DMSG("can't find %s in allowed list", id2str_proc(proc_id));
1031512cbf1dSJens Wiklander 	return false;
1032512cbf1dSJens Wiklander }
1033512cbf1dSJens Wiklander 
1034512cbf1dSJens Wiklander static enum pkcs11_attr_id func_to_attr(enum processing_func func)
1035512cbf1dSJens Wiklander {
1036512cbf1dSJens Wiklander 	switch (func) {
1037512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
1038512cbf1dSJens Wiklander 		return PKCS11_CKA_ENCRYPT;
1039512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
1040512cbf1dSJens Wiklander 		return PKCS11_CKA_DECRYPT;
1041512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
1042512cbf1dSJens Wiklander 		return PKCS11_CKA_SIGN;
1043512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
1044512cbf1dSJens Wiklander 		return PKCS11_CKA_VERIFY;
1045512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
1046512cbf1dSJens Wiklander 		return PKCS11_CKA_WRAP;
1047512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
1048512cbf1dSJens Wiklander 		return PKCS11_CKA_UNWRAP;
1049512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
1050512cbf1dSJens Wiklander 		return PKCS11_CKA_DERIVE;
1051512cbf1dSJens Wiklander 	default:
1052512cbf1dSJens Wiklander 		return PKCS11_CKA_UNDEFINED_ID;
1053512cbf1dSJens Wiklander 	}
1054512cbf1dSJens Wiklander }
1055512cbf1dSJens Wiklander 
1056512cbf1dSJens Wiklander enum pkcs11_rc
1057512cbf1dSJens Wiklander check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
1058512cbf1dSJens Wiklander 				      enum processing_func function,
1059512cbf1dSJens Wiklander 				      struct obj_attrs *head)
1060512cbf1dSJens Wiklander {
1061512cbf1dSJens Wiklander 	enum pkcs11_class_id key_class = get_class(head);
1062512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(head);
1063512cbf1dSJens Wiklander 	enum pkcs11_attr_id attr = func_to_attr(function);
1064512cbf1dSJens Wiklander 
1065512cbf1dSJens Wiklander 	if (!get_bool(head, attr)) {
1066512cbf1dSJens Wiklander 		DMSG("%s not permitted", id2str_attr(attr));
1067512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1068512cbf1dSJens Wiklander 	}
1069512cbf1dSJens Wiklander 
1070512cbf1dSJens Wiklander 	/* Check processing complies with parent key family */
1071512cbf1dSJens Wiklander 	switch (proc_id) {
1072512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
1073512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
1074512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
1075512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
1076512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
1077512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1078512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1079512cbf1dSJens Wiklander 			break;
1080512cbf1dSJens Wiklander 
1081512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1082512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1083512cbf1dSJens Wiklander 
1084512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1085512cbf1dSJens Wiklander 
1086512cbf1dSJens Wiklander 	default:
1087512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
1088512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
1089512cbf1dSJens Wiklander 
1090512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
1091512cbf1dSJens Wiklander 	}
1092512cbf1dSJens Wiklander 
1093512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
1094512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
1095512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1096512cbf1dSJens Wiklander 	}
1097512cbf1dSJens Wiklander 
1098512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1099512cbf1dSJens Wiklander }
1100