xref: /optee_os/ta/pkcs11/src/pkcs11_attributes.c (revision 39fc24fabd9c31a22f35f79e6924685e50641dc7)
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:
137*39fc24faSEtienne Carriere 	case PKCS11_CKA_WRAP_WITH_TRUSTED:
138*39fc24faSEtienne Carriere 	case PKCS11_CKA_ALWAYS_AUTHENTICATE:
13963f89caaSJens Wiklander 	case PKCS11_CKA_SENSITIVE:
14063f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
14163f89caaSJens Wiklander 	/* Token specific default value */
14263f89caaSJens Wiklander 	case PKCS11_CKA_SIGN:
14363f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY:
14463f89caaSJens Wiklander 		return (uint8_t *)&bool_true;
14563f89caaSJens Wiklander 	case PKCS11_CKA_DERIVE:
14663f89caaSJens Wiklander 	case PKCS11_CKA_ENCRYPT:
14763f89caaSJens Wiklander 	case PKCS11_CKA_DECRYPT:
14863f89caaSJens Wiklander 	case PKCS11_CKA_SIGN_RECOVER:
14963f89caaSJens Wiklander 	case PKCS11_CKA_VERIFY_RECOVER:
15063f89caaSJens Wiklander 	case PKCS11_CKA_WRAP:
15163f89caaSJens Wiklander 	case PKCS11_CKA_UNWRAP:
15263f89caaSJens Wiklander 	case PKCS11_CKA_EXTRACTABLE:
15363f89caaSJens Wiklander 	case PKCS11_CKA_TRUSTED:
15463f89caaSJens Wiklander 		return (uint8_t *)&bool_false;
15563f89caaSJens Wiklander 	default:
15663f89caaSJens Wiklander 		DMSG("No default for boolprop attribute %#"PRIx32, attribute);
15763f89caaSJens Wiklander 		return NULL;
15863f89caaSJens Wiklander 	}
15963f89caaSJens Wiklander }
16063f89caaSJens Wiklander 
16163f89caaSJens Wiklander /*
16263f89caaSJens Wiklander  * Object expects several boolean attributes to be set to a default value
16363f89caaSJens Wiklander  * or to a validate client configuration value. This function append the input
16463f89caaSJens Wiklander  * attribute (id/size/value) in the serialized object.
16563f89caaSJens Wiklander  */
16663f89caaSJens Wiklander static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out,
16763f89caaSJens Wiklander 						    struct obj_attrs *templ,
16863f89caaSJens Wiklander 						    uint32_t attribute)
16963f89caaSJens Wiklander {
17063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
17163f89caaSJens Wiklander 	uint8_t bbool = 0;
17263f89caaSJens Wiklander 	uint32_t size = sizeof(uint8_t);
17363f89caaSJens Wiklander 	void *attr = NULL;
17463f89caaSJens Wiklander 
17563f89caaSJens Wiklander 	rc = get_attribute(templ, attribute, &bbool, &size);
17663f89caaSJens Wiklander 	if (rc) {
17763f89caaSJens Wiklander 		if (rc != PKCS11_RV_NOT_FOUND)
17863f89caaSJens Wiklander 			return rc;
17963f89caaSJens Wiklander 		attr = pkcs11_object_default_boolprop(attribute);
18063f89caaSJens Wiklander 		if (!attr)
18163f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
18263f89caaSJens Wiklander 	} else {
18363f89caaSJens Wiklander 		attr = &bbool;
18463f89caaSJens Wiklander 	}
18563f89caaSJens Wiklander 
18663f89caaSJens Wiklander 	/* Boolean attributes are 1byte in the ABI, no alignment issue */
18763f89caaSJens Wiklander 	return add_attribute(out, attribute, attr, sizeof(uint8_t));
18863f89caaSJens Wiklander }
18963f89caaSJens Wiklander 
19063f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out,
19163f89caaSJens Wiklander 					      struct obj_attrs *temp,
19263f89caaSJens Wiklander 					      uint32_t const *bp,
19363f89caaSJens Wiklander 					      size_t bp_count)
19463f89caaSJens Wiklander {
19563f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
19663f89caaSJens Wiklander 	size_t n = 0;
19763f89caaSJens Wiklander 
19863f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
19963f89caaSJens Wiklander 		rc = pkcs11_import_object_boolprop(out, temp, bp[n]);
20063f89caaSJens Wiklander 		if (rc)
20163f89caaSJens Wiklander 			return rc;
20263f89caaSJens Wiklander 	}
20363f89caaSJens Wiklander 
20463f89caaSJens Wiklander 	return rc;
20563f89caaSJens Wiklander }
20663f89caaSJens Wiklander 
20763f89caaSJens Wiklander static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out,
20863f89caaSJens Wiklander 					       struct obj_attrs *temp,
20963f89caaSJens Wiklander 					       uint32_t const *bp,
21063f89caaSJens Wiklander 					       size_t bp_count)
21163f89caaSJens Wiklander {
21263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
21363f89caaSJens Wiklander 	size_t n = 0;
21463f89caaSJens Wiklander 
21563f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
21663f89caaSJens Wiklander 		uint32_t size = 0;
21763f89caaSJens Wiklander 		void *value = NULL;
21863f89caaSJens Wiklander 
21963f89caaSJens Wiklander 		if (get_attribute_ptr(temp, bp[n], &value, &size))
22063f89caaSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCOMPLETE;
22163f89caaSJens Wiklander 
22263f89caaSJens Wiklander 		rc = add_attribute(out, bp[n], value, size);
22363f89caaSJens Wiklander 		if (rc)
22463f89caaSJens Wiklander 			return rc;
22563f89caaSJens Wiklander 	}
22663f89caaSJens Wiklander 
22763f89caaSJens Wiklander 	return rc;
22863f89caaSJens Wiklander }
22963f89caaSJens Wiklander 
23063f89caaSJens Wiklander static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value,
23163f89caaSJens Wiklander 					uint32_t *size)
23263f89caaSJens Wiklander {
23363f89caaSJens Wiklander 	/* should have been taken care of already */
23463f89caaSJens Wiklander 	assert(!pkcs11_attr_is_boolean(id));
23563f89caaSJens Wiklander 
23663f89caaSJens Wiklander 	if (id == PKCS11_CKA_PUBLIC_KEY_INFO) {
23763f89caaSJens Wiklander 		EMSG("Cannot provide default PUBLIC_KEY_INFO");
23863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
23963f89caaSJens Wiklander 	}
24063f89caaSJens Wiklander 
24163f89caaSJens Wiklander 	/* All other attributes have an empty default value */
24263f89caaSJens Wiklander 	*value = NULL;
24363f89caaSJens Wiklander 	*size = 0;
24463f89caaSJens Wiklander 	return PKCS11_CKR_OK;
24563f89caaSJens Wiklander }
24663f89caaSJens Wiklander 
2474eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out,
24863f89caaSJens Wiklander 						       struct obj_attrs *temp,
24963f89caaSJens Wiklander 						       uint32_t const *bp,
2504eb88651SRuchika Gupta 						       size_t bp_count,
2514eb88651SRuchika Gupta 						       bool default_to_null)
25263f89caaSJens Wiklander {
25363f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
25463f89caaSJens Wiklander 	size_t n = 0;
25563f89caaSJens Wiklander 
25663f89caaSJens Wiklander 	for (n = 0; n < bp_count; n++) {
25763f89caaSJens Wiklander 		uint32_t size = 0;
25863f89caaSJens Wiklander 		void *value = NULL;
25963f89caaSJens Wiklander 
26063f89caaSJens Wiklander 		rc = get_attribute_ptr(temp, bp[n], &value, &size);
2614eb88651SRuchika Gupta 		if (rc == PKCS11_RV_NOT_FOUND) {
2624eb88651SRuchika Gupta 			if (default_to_null) {
26363f89caaSJens Wiklander 				rc = get_default_value(bp[n], &value, &size);
2644eb88651SRuchika Gupta 			} else {
2654eb88651SRuchika Gupta 				rc = PKCS11_CKR_OK;
2664eb88651SRuchika Gupta 				continue;
2674eb88651SRuchika Gupta 			}
2684eb88651SRuchika Gupta 		}
26963f89caaSJens Wiklander 		if (rc)
27063f89caaSJens Wiklander 			return rc;
27163f89caaSJens Wiklander 
27263f89caaSJens Wiklander 		rc = add_attribute(out, bp[n], value, size);
27363f89caaSJens Wiklander 		if (rc)
27463f89caaSJens Wiklander 			return rc;
27563f89caaSJens Wiklander 	}
27663f89caaSJens Wiklander 
27763f89caaSJens Wiklander 	return rc;
27863f89caaSJens Wiklander }
27963f89caaSJens Wiklander 
2804eb88651SRuchika Gupta static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out,
2814eb88651SRuchika Gupta 						 struct obj_attrs *temp,
2824eb88651SRuchika Gupta 						 uint32_t const *bp,
2834eb88651SRuchika Gupta 						 size_t bp_count)
2844eb88651SRuchika Gupta {
2854eb88651SRuchika Gupta 	return set_optional_attributes_with_def(out, temp, bp, bp_count, true);
2864eb88651SRuchika Gupta }
2874eb88651SRuchika Gupta 
2884eb88651SRuchika Gupta static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out,
2894eb88651SRuchika Gupta 					      struct obj_attrs *temp,
2904eb88651SRuchika Gupta 					      uint32_t const *bp,
2914eb88651SRuchika Gupta 					      size_t bp_count)
2924eb88651SRuchika Gupta {
2934eb88651SRuchika Gupta 	return set_optional_attributes_with_def(out, temp, bp, bp_count, false);
2944eb88651SRuchika Gupta }
2954eb88651SRuchika Gupta 
29663f89caaSJens Wiklander /*
29763f89caaSJens Wiklander  * Below are listed the mandated or optional expected attributes for
29863f89caaSJens Wiklander  * PKCS#11 storage objects.
29963f89caaSJens Wiklander  *
30063f89caaSJens Wiklander  * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE,
30163f89caaSJens Wiklander  * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided
30263f89caaSJens Wiklander  * in the client template.
30363f89caaSJens Wiklander  */
30463f89caaSJens Wiklander 
30563f89caaSJens Wiklander /* PKCS#11 specification for any object (session/token) of the storage */
3064eb88651SRuchika Gupta static const uint32_t any_object_boolprops[] = {
30763f89caaSJens Wiklander 	PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
30863f89caaSJens Wiklander 	PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE,
30963f89caaSJens Wiklander };
31063f89caaSJens Wiklander 
3114eb88651SRuchika Gupta static const uint32_t any_object_opt_or_null[] = {
31263f89caaSJens Wiklander 	PKCS11_CKA_LABEL,
31363f89caaSJens Wiklander };
31463f89caaSJens Wiklander 
3154eb88651SRuchika Gupta /* PKCS#11 specification for raw data object (+any_object_xxx) */
3164eb88651SRuchika Gupta const uint32_t raw_data_opt_or_null[] = {
31763f89caaSJens Wiklander 	PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE,
31863f89caaSJens Wiklander };
31963f89caaSJens Wiklander 
3204eb88651SRuchika Gupta /* PKCS#11 specification for any key object (+any_object_xxx) */
3214eb88651SRuchika Gupta static const uint32_t any_key_boolprops[] = {
32263f89caaSJens Wiklander 	PKCS11_CKA_DERIVE,
32363f89caaSJens Wiklander };
32463f89caaSJens Wiklander 
3254eb88651SRuchika Gupta static const uint32_t any_key_opt_or_null[] = {
32663f89caaSJens Wiklander 	PKCS11_CKA_ID,
32763f89caaSJens Wiklander 	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE,
3284eb88651SRuchika Gupta };
3294eb88651SRuchika Gupta 
3304eb88651SRuchika Gupta static const uint32_t any_key_optional[] = {
33163f89caaSJens Wiklander 	PKCS11_CKA_ALLOWED_MECHANISMS,
33263f89caaSJens Wiklander };
33363f89caaSJens Wiklander 
3344eb88651SRuchika Gupta /* PKCS#11 specification for any symmetric key (+any_key_xxx) */
3354eb88651SRuchika Gupta static const uint32_t symm_key_boolprops[] = {
33663f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT,
33763f89caaSJens Wiklander 	PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY,
33863f89caaSJens Wiklander 	PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP,
33963f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
34063f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED,
34163f89caaSJens Wiklander };
34263f89caaSJens Wiklander 
3434eb88651SRuchika Gupta static const uint32_t symm_key_opt_or_null[] = {
34463f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE,
34563f89caaSJens Wiklander 	PKCS11_CKA_DERIVE_TEMPLATE,
34663f89caaSJens Wiklander 	PKCS11_CKA_VALUE, PKCS11_CKA_VALUE_LEN,
34763f89caaSJens Wiklander };
34863f89caaSJens Wiklander 
3494eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
3504eb88651SRuchika Gupta static const uint32_t public_key_boolprops[] = {
35163f89caaSJens Wiklander 	PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER,
35263f89caaSJens Wiklander 	PKCS11_CKA_WRAP,
35363f89caaSJens Wiklander 	PKCS11_CKA_TRUSTED,
35463f89caaSJens Wiklander };
35563f89caaSJens Wiklander 
3564eb88651SRuchika Gupta static const uint32_t public_key_mandated[] = {
35763f89caaSJens Wiklander 	PKCS11_CKA_SUBJECT
35863f89caaSJens Wiklander };
35963f89caaSJens Wiklander 
3604eb88651SRuchika Gupta static const uint32_t public_key_opt_or_null[] = {
36163f89caaSJens Wiklander 	PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO,
36263f89caaSJens Wiklander };
36363f89caaSJens Wiklander 
3644eb88651SRuchika Gupta /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */
3654eb88651SRuchika Gupta static const uint32_t private_key_boolprops[] = {
36663f89caaSJens Wiklander 	PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER,
36763f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP,
36863f89caaSJens Wiklander 	PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE,
36963f89caaSJens Wiklander 	PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE,
37063f89caaSJens Wiklander };
37163f89caaSJens Wiklander 
3724eb88651SRuchika Gupta static const uint32_t private_key_mandated[] = {
37363f89caaSJens Wiklander 	PKCS11_CKA_SUBJECT
37463f89caaSJens Wiklander };
37563f89caaSJens Wiklander 
3764eb88651SRuchika Gupta static const uint32_t private_key_opt_or_null[] = {
37763f89caaSJens Wiklander 	PKCS11_CKA_UNWRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO,
37863f89caaSJens Wiklander };
37963f89caaSJens Wiklander 
3804eb88651SRuchika Gupta /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */
3814eb88651SRuchika Gupta static const uint32_t rsa_public_key_mandated[] = {
38263f89caaSJens Wiklander 	PKCS11_CKA_MODULUS_BITS,
38363f89caaSJens Wiklander };
38463f89caaSJens Wiklander 
3854eb88651SRuchika Gupta static const uint32_t rsa_public_key_opt_or_null[] = {
38663f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
38763f89caaSJens Wiklander };
38863f89caaSJens Wiklander 
3894eb88651SRuchika Gupta static const uint32_t rsa_private_key_opt_or_null[] = {
39063f89caaSJens Wiklander 	PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT,
39163f89caaSJens Wiklander 	PKCS11_CKA_PRIVATE_EXPONENT,
39263f89caaSJens Wiklander 	PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2,
39363f89caaSJens Wiklander 	PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT,
39463f89caaSJens Wiklander };
39563f89caaSJens Wiklander 
3964eb88651SRuchika Gupta /* PKCS#11 specification for any EC key (+public/private_key_xxx) */
3974eb88651SRuchika Gupta static const uint32_t ec_public_key_mandated[] = {
39863f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
39963f89caaSJens Wiklander };
40063f89caaSJens Wiklander 
4014eb88651SRuchika Gupta static const uint32_t ec_public_key_opt_or_null[] = {
40263f89caaSJens Wiklander 	PKCS11_CKA_EC_POINT,
40363f89caaSJens Wiklander };
40463f89caaSJens Wiklander 
4054eb88651SRuchika Gupta static const uint32_t ec_private_key_mandated[] = {
40663f89caaSJens Wiklander 	PKCS11_CKA_EC_PARAMS,
40763f89caaSJens Wiklander };
40863f89caaSJens Wiklander 
4094eb88651SRuchika Gupta static const uint32_t ec_private_key_opt_or_null[] = {
41063f89caaSJens Wiklander 	PKCS11_CKA_VALUE,
41163f89caaSJens Wiklander };
41263f89caaSJens Wiklander 
41363f89caaSJens Wiklander static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out,
41463f89caaSJens Wiklander 						struct obj_attrs *temp)
41563f89caaSJens Wiklander {
41663f89caaSJens Wiklander 	enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
41763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
41863f89caaSJens Wiklander 
41963f89caaSJens Wiklander 	rc = init_attributes_head(out);
42063f89caaSJens Wiklander 	if (rc)
42163f89caaSJens Wiklander 		return rc;
42263f89caaSJens Wiklander 
42363f89caaSJens Wiklander 	/* Object class is mandatory */
42463f89caaSJens Wiklander 	class = get_class(temp);
42563f89caaSJens Wiklander 	if (class == PKCS11_CKO_UNDEFINED_ID) {
42663f89caaSJens Wiklander 		EMSG("Class attribute not found");
42763f89caaSJens Wiklander 
42863f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
42963f89caaSJens Wiklander 	}
43063f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t));
43163f89caaSJens Wiklander 	if (rc)
43263f89caaSJens Wiklander 		return rc;
43363f89caaSJens Wiklander 
4344eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_object_boolprops,
4354eb88651SRuchika Gupta 				     ARRAY_SIZE(any_object_boolprops));
43663f89caaSJens Wiklander 	if (rc)
43763f89caaSJens Wiklander 		return rc;
43863f89caaSJens Wiklander 
4394eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, any_object_opt_or_null,
4404eb88651SRuchika Gupta 					  ARRAY_SIZE(any_object_opt_or_null));
44163f89caaSJens Wiklander }
44263f89caaSJens Wiklander 
44363f89caaSJens Wiklander static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out,
44463f89caaSJens Wiklander 					       struct obj_attrs *temp)
44563f89caaSJens Wiklander {
44663f89caaSJens Wiklander 	uint32_t type = PKCS11_CKO_UNDEFINED_ID;
44763f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
44863f89caaSJens Wiklander 
44963f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
45063f89caaSJens Wiklander 	if (rc)
45163f89caaSJens Wiklander 		return rc;
45263f89caaSJens Wiklander 
45363f89caaSJens Wiklander 	type = get_key_type(temp);
45463f89caaSJens Wiklander 	if (type == PKCS11_CKK_UNDEFINED_ID) {
45563f89caaSJens Wiklander 		EMSG("Key type attribute not found");
45663f89caaSJens Wiklander 
45763f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
45863f89caaSJens Wiklander 	}
45963f89caaSJens Wiklander 	rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t));
46063f89caaSJens Wiklander 	if (rc)
46163f89caaSJens Wiklander 		return rc;
46263f89caaSJens Wiklander 
4634eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, any_key_boolprops,
4644eb88651SRuchika Gupta 				     ARRAY_SIZE(any_key_boolprops));
46563f89caaSJens Wiklander 	if (rc)
46663f89caaSJens Wiklander 		return rc;
46763f89caaSJens Wiklander 
4684eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null,
4694eb88651SRuchika Gupta 					ARRAY_SIZE(any_key_opt_or_null));
4704eb88651SRuchika Gupta 	if (rc)
4714eb88651SRuchika Gupta 		return rc;
4724eb88651SRuchika Gupta 
4734eb88651SRuchika Gupta 	return set_optional_attributes(out, temp, any_key_optional,
4744eb88651SRuchika Gupta 				       ARRAY_SIZE(any_key_optional));
4754eb88651SRuchika Gupta 
47663f89caaSJens Wiklander }
47763f89caaSJens Wiklander 
47863f89caaSJens Wiklander static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out,
47963f89caaSJens Wiklander 						 struct obj_attrs *temp)
48063f89caaSJens Wiklander {
48163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
48263f89caaSJens Wiklander 
48363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_SECRET_KEY);
48463f89caaSJens Wiklander 
48563f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
48663f89caaSJens Wiklander 	if (rc)
48763f89caaSJens Wiklander 		return rc;
48863f89caaSJens Wiklander 
48963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_SECRET_KEY);
49063f89caaSJens Wiklander 
49163f89caaSJens Wiklander 	switch (get_key_type(*out)) {
49263f89caaSJens Wiklander 	case PKCS11_CKK_GENERIC_SECRET:
49363f89caaSJens Wiklander 	case PKCS11_CKK_AES:
49463f89caaSJens Wiklander 	case PKCS11_CKK_MD5_HMAC:
49563f89caaSJens Wiklander 	case PKCS11_CKK_SHA_1_HMAC:
49663f89caaSJens Wiklander 	case PKCS11_CKK_SHA256_HMAC:
49763f89caaSJens Wiklander 	case PKCS11_CKK_SHA384_HMAC:
49863f89caaSJens Wiklander 	case PKCS11_CKK_SHA512_HMAC:
49963f89caaSJens Wiklander 	case PKCS11_CKK_SHA224_HMAC:
50063f89caaSJens Wiklander 		break;
50163f89caaSJens Wiklander 	default:
50263f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
50363f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
50463f89caaSJens Wiklander 
50563f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
50663f89caaSJens Wiklander 	}
50763f89caaSJens Wiklander 
5084eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, symm_key_boolprops,
5094eb88651SRuchika Gupta 				     ARRAY_SIZE(symm_key_boolprops));
51063f89caaSJens Wiklander 	if (rc)
51163f89caaSJens Wiklander 		return rc;
51263f89caaSJens Wiklander 
5134eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, symm_key_opt_or_null,
5144eb88651SRuchika Gupta 					  ARRAY_SIZE(symm_key_opt_or_null));
51563f89caaSJens Wiklander }
51663f89caaSJens Wiklander 
51763f89caaSJens Wiklander static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
51863f89caaSJens Wiklander 					     struct obj_attrs *temp)
51963f89caaSJens Wiklander {
52063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
52163f89caaSJens Wiklander 
52263f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_DATA);
52363f89caaSJens Wiklander 
52463f89caaSJens Wiklander 	rc = create_storage_attributes(out, temp);
52563f89caaSJens Wiklander 	if (rc)
52663f89caaSJens Wiklander 		return rc;
52763f89caaSJens Wiklander 
52863f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_DATA);
52963f89caaSJens Wiklander 
5304eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null,
5314eb88651SRuchika Gupta 					  ARRAY_SIZE(raw_data_opt_or_null));
53263f89caaSJens Wiklander }
53363f89caaSJens Wiklander 
53463f89caaSJens Wiklander static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
53563f89caaSJens Wiklander 						struct obj_attrs *temp)
53663f89caaSJens Wiklander {
53763f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
5384eb88651SRuchika Gupta 	uint32_t const *opt_or_null = NULL;
53963f89caaSJens Wiklander 	size_t mandated_count = 0;
5404eb88651SRuchika Gupta 	size_t opt_or_null_count = 0;
54163f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
54263f89caaSJens Wiklander 
54363f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY);
54463f89caaSJens Wiklander 
54563f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
54663f89caaSJens Wiklander 	if (rc)
54763f89caaSJens Wiklander 		return rc;
54863f89caaSJens Wiklander 
54963f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY);
55063f89caaSJens Wiklander 
5514eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, public_key_boolprops,
5524eb88651SRuchika Gupta 				     ARRAY_SIZE(public_key_boolprops));
55363f89caaSJens Wiklander 	if (rc)
55463f89caaSJens Wiklander 		return rc;
55563f89caaSJens Wiklander 
5564eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, public_key_mandated,
5574eb88651SRuchika Gupta 				      ARRAY_SIZE(public_key_mandated));
55863f89caaSJens Wiklander 	if (rc)
55963f89caaSJens Wiklander 		return rc;
56063f89caaSJens Wiklander 
5614eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp,
5624eb88651SRuchika Gupta 					public_key_opt_or_null,
5634eb88651SRuchika Gupta 					ARRAY_SIZE(public_key_opt_or_null));
56463f89caaSJens Wiklander 	if (rc)
56563f89caaSJens Wiklander 		return rc;
56663f89caaSJens Wiklander 
56763f89caaSJens Wiklander 	switch (get_key_type(*out)) {
56863f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
5694eb88651SRuchika Gupta 		mandated = rsa_public_key_mandated;
5704eb88651SRuchika Gupta 		opt_or_null = rsa_public_key_opt_or_null;
5714eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(rsa_public_key_mandated);
5724eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(rsa_public_key_opt_or_null);
57363f89caaSJens Wiklander 		break;
57463f89caaSJens Wiklander 	case PKCS11_CKK_EC:
5754eb88651SRuchika Gupta 		mandated = ec_public_key_mandated;
5764eb88651SRuchika Gupta 		opt_or_null = ec_public_key_opt_or_null;
5774eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_public_key_mandated);
5784eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(ec_public_key_opt_or_null);
57963f89caaSJens Wiklander 		break;
58063f89caaSJens Wiklander 	default:
58163f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
58263f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
58363f89caaSJens Wiklander 
58463f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
58563f89caaSJens Wiklander 	}
58663f89caaSJens Wiklander 
58763f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
58863f89caaSJens Wiklander 	if (rc)
58963f89caaSJens Wiklander 		return rc;
59063f89caaSJens Wiklander 
5914eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, opt_or_null,
5924eb88651SRuchika Gupta 					  opt_or_null_count);
59363f89caaSJens Wiklander }
59463f89caaSJens Wiklander 
59563f89caaSJens Wiklander static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out,
59663f89caaSJens Wiklander 						 struct obj_attrs *temp)
59763f89caaSJens Wiklander {
59863f89caaSJens Wiklander 	uint32_t const *mandated = NULL;
5994eb88651SRuchika Gupta 	uint32_t const *opt_or_null = NULL;
60063f89caaSJens Wiklander 	size_t mandated_count = 0;
6014eb88651SRuchika Gupta 	size_t opt_or_null_count = 0;
60263f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
60363f89caaSJens Wiklander 
60463f89caaSJens Wiklander 	assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY);
60563f89caaSJens Wiklander 
60663f89caaSJens Wiklander 	rc = create_genkey_attributes(out, temp);
60763f89caaSJens Wiklander 	if (rc)
60863f89caaSJens Wiklander 		return rc;
60963f89caaSJens Wiklander 
61063f89caaSJens Wiklander 	assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY);
61163f89caaSJens Wiklander 
6124eb88651SRuchika Gupta 	rc = set_mandatory_boolprops(out, temp, private_key_boolprops,
6134eb88651SRuchika Gupta 				     ARRAY_SIZE(private_key_boolprops));
61463f89caaSJens Wiklander 	if (rc)
61563f89caaSJens Wiklander 		return rc;
61663f89caaSJens Wiklander 
6174eb88651SRuchika Gupta 	rc = set_mandatory_attributes(out, temp, private_key_mandated,
6184eb88651SRuchika Gupta 				      ARRAY_SIZE(private_key_mandated));
61963f89caaSJens Wiklander 	if (rc)
62063f89caaSJens Wiklander 		return rc;
62163f89caaSJens Wiklander 
6224eb88651SRuchika Gupta 	rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null,
6234eb88651SRuchika Gupta 					ARRAY_SIZE(private_key_opt_or_null));
62463f89caaSJens Wiklander 	if (rc)
62563f89caaSJens Wiklander 		return rc;
62663f89caaSJens Wiklander 
62763f89caaSJens Wiklander 	switch (get_key_type(*out)) {
62863f89caaSJens Wiklander 	case PKCS11_CKK_RSA:
6294eb88651SRuchika Gupta 		opt_or_null = rsa_private_key_opt_or_null;
6304eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(rsa_private_key_opt_or_null);
63163f89caaSJens Wiklander 		break;
63263f89caaSJens Wiklander 	case PKCS11_CKK_EC:
6334eb88651SRuchika Gupta 		mandated = ec_private_key_mandated;
6344eb88651SRuchika Gupta 		opt_or_null = ec_private_key_opt_or_null;
6354eb88651SRuchika Gupta 		mandated_count = ARRAY_SIZE(ec_private_key_mandated);
6364eb88651SRuchika Gupta 		opt_or_null_count = ARRAY_SIZE(ec_private_key_opt_or_null);
63763f89caaSJens Wiklander 		break;
63863f89caaSJens Wiklander 	default:
63963f89caaSJens Wiklander 		EMSG("Invalid key type %#"PRIx32"/%s",
64063f89caaSJens Wiklander 		     get_key_type(*out), id2str_key_type(get_key_type(*out)));
64163f89caaSJens Wiklander 
64263f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
64363f89caaSJens Wiklander 	}
64463f89caaSJens Wiklander 
64563f89caaSJens Wiklander 	rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
64663f89caaSJens Wiklander 	if (rc)
64763f89caaSJens Wiklander 		return rc;
64863f89caaSJens Wiklander 
6494eb88651SRuchika Gupta 	return set_attributes_opt_or_null(out, temp, opt_or_null,
6504eb88651SRuchika Gupta 					  opt_or_null_count);
65163f89caaSJens Wiklander }
65263f89caaSJens Wiklander 
65363f89caaSJens Wiklander /*
65463f89caaSJens Wiklander  * Create an attribute list for a new object from a template and a parent
65563f89caaSJens Wiklander  * object (optional) for an object generation function (generate, copy,
65663f89caaSJens Wiklander  * derive...).
65763f89caaSJens Wiklander  *
65863f89caaSJens Wiklander  * PKCS#11 directives on the supplied template and expected return value:
65963f89caaSJens Wiklander  * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID
66063f89caaSJens Wiklander  * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID
66163f89caaSJens Wiklander  * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY
66263f89caaSJens Wiklander  * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT
66363f89caaSJens Wiklander  *
66463f89caaSJens Wiklander  * INFO on PKCS11_CMD_COPY_OBJECT:
66563f89caaSJens Wiklander  * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
66663f89caaSJens Wiklander  * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE,
66763f89caaSJens Wiklander  *   PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE.
66863f89caaSJens Wiklander  * - SENSITIVE can change from false to true, not from true to false.
66963f89caaSJens Wiklander  * - LOCAL is the parent LOCAL
67063f89caaSJens Wiklander  */
67163f89caaSJens Wiklander enum pkcs11_rc
67263f89caaSJens Wiklander create_attributes_from_template(struct obj_attrs **out, void *template,
67363f89caaSJens Wiklander 				size_t template_size,
67463f89caaSJens Wiklander 				struct obj_attrs *parent __unused,
67563f89caaSJens Wiklander 				enum processing_func function,
67663f89caaSJens Wiklander 				enum pkcs11_mechanism_id mecha __unused)
67763f89caaSJens Wiklander {
67863f89caaSJens Wiklander 	struct obj_attrs *temp = NULL;
67963f89caaSJens Wiklander 	struct obj_attrs *attrs = NULL;
68063f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
68163f89caaSJens Wiklander 	uint8_t local = 0;
68263f89caaSJens Wiklander 	uint8_t always_sensitive = 0;
68363f89caaSJens Wiklander 	uint8_t never_extract = 0;
68463f89caaSJens Wiklander 	uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
68563f89caaSJens Wiklander 
68663f89caaSJens Wiklander #ifdef DEBUG	/* Sanity: check function argument */
68763f89caaSJens Wiklander 	trace_attributes_from_api_head("template", template, template_size);
68863f89caaSJens Wiklander 	switch (function) {
68963f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
69063f89caaSJens Wiklander 		break;
69163f89caaSJens Wiklander 	default:
69263f89caaSJens Wiklander 		TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
69363f89caaSJens Wiklander 	}
69463f89caaSJens Wiklander #endif
69563f89caaSJens Wiklander 
69663f89caaSJens Wiklander 	rc = sanitize_client_object(&temp, template, template_size);
69763f89caaSJens Wiklander 	if (rc)
69863f89caaSJens Wiklander 		goto out;
69963f89caaSJens Wiklander 
70063f89caaSJens Wiklander 	/* If class/type not defined, match from mechanism */
70163f89caaSJens Wiklander 	if (get_class(temp) == PKCS11_UNDEFINED_ID &&
70263f89caaSJens Wiklander 	    get_key_type(temp) == PKCS11_UNDEFINED_ID) {
70363f89caaSJens Wiklander 		EMSG("Unable to define class/type from mechanism");
70463f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCOMPLETE;
70563f89caaSJens Wiklander 		goto out;
70663f89caaSJens Wiklander 	}
70763f89caaSJens Wiklander 
70863f89caaSJens Wiklander 	if (!sanitize_consistent_class_and_type(temp)) {
70963f89caaSJens Wiklander 		EMSG("Inconsistent class/type");
71063f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
71163f89caaSJens Wiklander 		goto out;
71263f89caaSJens Wiklander 	}
71363f89caaSJens Wiklander 
71463f89caaSJens Wiklander 	switch (get_class(temp)) {
71563f89caaSJens Wiklander 	case PKCS11_CKO_DATA:
71663f89caaSJens Wiklander 		rc = create_data_attributes(&attrs, temp);
71763f89caaSJens Wiklander 		break;
71863f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
71963f89caaSJens Wiklander 		rc = create_symm_key_attributes(&attrs, temp);
72063f89caaSJens Wiklander 		break;
72163f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
72263f89caaSJens Wiklander 		rc = create_pub_key_attributes(&attrs, temp);
72363f89caaSJens Wiklander 		break;
72463f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
72563f89caaSJens Wiklander 		rc = create_priv_key_attributes(&attrs, temp);
72663f89caaSJens Wiklander 		break;
72763f89caaSJens Wiklander 	default:
72863f89caaSJens Wiklander 		DMSG("Invalid object class %#"PRIx32"/%s",
72963f89caaSJens Wiklander 		     get_class(temp), id2str_class(get_class(temp)));
73063f89caaSJens Wiklander 
73163f89caaSJens Wiklander 		rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
73263f89caaSJens Wiklander 		break;
73363f89caaSJens Wiklander 	}
73463f89caaSJens Wiklander 	if (rc)
73563f89caaSJens Wiklander 		goto out;
73663f89caaSJens Wiklander 
73763f89caaSJens Wiklander 	if (get_attribute(attrs, PKCS11_CKA_LOCAL, NULL, NULL) !=
73863f89caaSJens Wiklander 	    PKCS11_RV_NOT_FOUND)
73963f89caaSJens Wiklander 		goto out;
74063f89caaSJens Wiklander 
74163f89caaSJens Wiklander 	if (get_attribute(attrs, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) !=
74263f89caaSJens Wiklander 	    PKCS11_RV_NOT_FOUND)
74363f89caaSJens Wiklander 		goto out;
74463f89caaSJens Wiklander 
74563f89caaSJens Wiklander 	switch (function) {
74663f89caaSJens Wiklander 	case PKCS11_FUNCTION_IMPORT:
74763f89caaSJens Wiklander 	default:
74863f89caaSJens Wiklander 		local = PKCS11_FALSE;
74963f89caaSJens Wiklander 		break;
75063f89caaSJens Wiklander 	}
75163f89caaSJens Wiklander 	rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local));
75263f89caaSJens Wiklander 	if (rc)
75363f89caaSJens Wiklander 		goto out;
75463f89caaSJens Wiklander 
75563f89caaSJens Wiklander 	switch (get_class(attrs)) {
75663f89caaSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
75763f89caaSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
75863f89caaSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
75963f89caaSJens Wiklander 		always_sensitive = PKCS11_FALSE;
76063f89caaSJens Wiklander 		never_extract = PKCS11_FALSE;
76163f89caaSJens Wiklander 
76263f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
76363f89caaSJens Wiklander 				   &always_sensitive, sizeof(always_sensitive));
76463f89caaSJens Wiklander 		if (rc)
76563f89caaSJens Wiklander 			goto out;
76663f89caaSJens Wiklander 
76763f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE,
76863f89caaSJens Wiklander 				   &never_extract, sizeof(never_extract));
76963f89caaSJens Wiklander 		if (rc)
77063f89caaSJens Wiklander 			goto out;
77163f89caaSJens Wiklander 
77263f89caaSJens Wiklander 		/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
77363f89caaSJens Wiklander 		mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
77463f89caaSJens Wiklander 		rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
77563f89caaSJens Wiklander 				   &mechanism_id, sizeof(mechanism_id));
77663f89caaSJens Wiklander 		if (rc)
77763f89caaSJens Wiklander 			goto out;
77863f89caaSJens Wiklander 		break;
77963f89caaSJens Wiklander 
78063f89caaSJens Wiklander 	default:
78163f89caaSJens Wiklander 		break;
78263f89caaSJens Wiklander 	}
78363f89caaSJens Wiklander 
78463f89caaSJens Wiklander 	*out = attrs;
78563f89caaSJens Wiklander 
78663f89caaSJens Wiklander #ifdef DEBUG
78763f89caaSJens Wiklander 	trace_attributes("object", attrs);
78863f89caaSJens Wiklander #endif
78963f89caaSJens Wiklander 
79063f89caaSJens Wiklander out:
79163f89caaSJens Wiklander 	TEE_Free(temp);
79263f89caaSJens Wiklander 	if (rc)
79363f89caaSJens Wiklander 		TEE_Free(attrs);
79463f89caaSJens Wiklander 
79563f89caaSJens Wiklander 	return rc;
79663f89caaSJens Wiklander }
79763f89caaSJens Wiklander 
79863f89caaSJens Wiklander static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head)
79963f89caaSJens Wiklander {
80063f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) &&
80163f89caaSJens Wiklander 	    get_bool(head, PKCS11_CKA_EXTRACTABLE)) {
80263f89caaSJens Wiklander 		DMSG("Never/Extractable attributes mismatch %d/%d",
80363f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE),
80463f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_EXTRACTABLE));
80563f89caaSJens Wiklander 
80663f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
80763f89caaSJens Wiklander 	}
80863f89caaSJens Wiklander 
80963f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) &&
81063f89caaSJens Wiklander 	    !get_bool(head, PKCS11_CKA_SENSITIVE)) {
81163f89caaSJens Wiklander 		DMSG("Sensitive/always attributes mismatch %d/%d",
81263f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_SENSITIVE),
81363f89caaSJens Wiklander 		     get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE));
81463f89caaSJens Wiklander 
81563f89caaSJens Wiklander 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
81663f89caaSJens Wiklander 	}
81763f89caaSJens Wiklander 
81863f89caaSJens Wiklander 	return PKCS11_CKR_OK;
81963f89caaSJens Wiklander }
82063f89caaSJens Wiklander 
82163f89caaSJens Wiklander /*
822512cbf1dSJens Wiklander  * Check access to object against authentication to token
823512cbf1dSJens Wiklander  */
824512cbf1dSJens Wiklander enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
825512cbf1dSJens Wiklander 						struct obj_attrs *head)
826512cbf1dSJens Wiklander {
827512cbf1dSJens Wiklander 	bool private = true;
828512cbf1dSJens Wiklander 
829512cbf1dSJens Wiklander 	switch (get_class(head)) {
830512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
831512cbf1dSJens Wiklander 	case PKCS11_CKO_PUBLIC_KEY:
832512cbf1dSJens Wiklander 	case PKCS11_CKO_DATA:
833512cbf1dSJens Wiklander 		private = get_bool(head, PKCS11_CKA_PRIVATE);
834512cbf1dSJens Wiklander 		break;
835512cbf1dSJens Wiklander 	case PKCS11_CKO_PRIVATE_KEY:
836512cbf1dSJens Wiklander 		break;
837512cbf1dSJens Wiklander 	default:
838512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
839512cbf1dSJens Wiklander 	}
840512cbf1dSJens Wiklander 
841512cbf1dSJens Wiklander 	if (private && pkcs11_session_is_public(session)) {
842512cbf1dSJens Wiklander 		DMSG("Private object access from a public session");
843512cbf1dSJens Wiklander 
844512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
845512cbf1dSJens Wiklander 	}
846512cbf1dSJens Wiklander 
847512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
848512cbf1dSJens Wiklander }
849512cbf1dSJens Wiklander 
850512cbf1dSJens Wiklander /*
85163f89caaSJens Wiklander  * Check the attributes of a to-be-created object matches the token state
85263f89caaSJens Wiklander  */
85363f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session,
85463f89caaSJens Wiklander 						 struct obj_attrs *head)
85563f89caaSJens Wiklander {
85663f89caaSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
85763f89caaSJens Wiklander 
85863f89caaSJens Wiklander 	rc = check_attrs_misc_integrity(head);
85963f89caaSJens Wiklander 	if (rc)
86063f89caaSJens Wiklander 		return rc;
86163f89caaSJens Wiklander 
86263f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TRUSTED) &&
86363f89caaSJens Wiklander 	    !pkcs11_session_is_so(session)) {
86463f89caaSJens Wiklander 		DMSG("Can't create trusted object");
86563f89caaSJens Wiklander 
86663f89caaSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
86763f89caaSJens Wiklander 	}
86863f89caaSJens Wiklander 
86963f89caaSJens Wiklander 	if (get_bool(head, PKCS11_CKA_TOKEN) &&
87063f89caaSJens Wiklander 	    !pkcs11_session_is_read_write(session)) {
87163f89caaSJens Wiklander 		DMSG("Can't create persistent object");
87263f89caaSJens Wiklander 
87363f89caaSJens Wiklander 		return PKCS11_CKR_SESSION_READ_ONLY;
87463f89caaSJens Wiklander 	}
87563f89caaSJens Wiklander 
87663f89caaSJens Wiklander 	/*
87763f89caaSJens Wiklander 	 * TODO: START_DATE and END_DATE: complies with current time?
87863f89caaSJens Wiklander 	 */
87963f89caaSJens Wiklander 	return PKCS11_CKR_OK;
88063f89caaSJens Wiklander }
88163f89caaSJens Wiklander 
88263f89caaSJens Wiklander #define DMSG_BAD_BBOOL(attr, proc, head)				\
88363f89caaSJens Wiklander 	do {								\
88463f89caaSJens Wiklander 		uint32_t __maybe_unused _attr = (attr);			\
88563f89caaSJens Wiklander 		uint8_t __maybe_unused _bvalue = 0;			\
88663f89caaSJens Wiklander 		enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK;	\
88763f89caaSJens Wiklander 									\
88863f89caaSJens Wiklander 		_rc = get_attribute((head), _attr, &_bvalue, NULL);	\
88963f89caaSJens Wiklander 		DMSG("%s issue for %s: %sfound, value %"PRIu8,		\
89063f89caaSJens Wiklander 		     id2str_attr(_attr), id2str_proc((proc)),		\
89163f89caaSJens Wiklander 		     _rc ? "not " : "", _bvalue);			\
89263f89caaSJens Wiklander 	} while (0)
89363f89caaSJens Wiklander 
89463f89caaSJens Wiklander static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
89563f89caaSJens Wiklander 					   struct obj_attrs *head,
89663f89caaSJens Wiklander 					   uint32_t attribute, bool val)
89763f89caaSJens Wiklander {
89863f89caaSJens Wiklander 	uint8_t bbool = 0;
89963f89caaSJens Wiklander 	uint32_t sz = sizeof(bbool);
90063f89caaSJens Wiklander 
90163f89caaSJens Wiklander 	if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val)
90263f89caaSJens Wiklander 		return true;
90363f89caaSJens Wiklander 
90463f89caaSJens Wiklander 	DMSG_BAD_BBOOL(attribute, proc_id, head);
90563f89caaSJens Wiklander 	return false;
90663f89caaSJens Wiklander }
90763f89caaSJens Wiklander 
90863f89caaSJens Wiklander /*
90963f89caaSJens Wiklander  * Check the attributes of a new secret match the processing/mechanism
91063f89caaSJens Wiklander  * used to create it.
91163f89caaSJens Wiklander  *
91263f89caaSJens Wiklander  * @proc_id - PKCS11_CKM_xxx
91363f89caaSJens Wiklander  * @head - head of the attributes of the to-be-created object.
91463f89caaSJens Wiklander  */
91563f89caaSJens Wiklander enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
91663f89caaSJens Wiklander 						      struct obj_attrs *head)
91763f89caaSJens Wiklander {
91863f89caaSJens Wiklander 	/*
91963f89caaSJens Wiklander 	 * Processings that do not create secrets are not expected to call
92063f89caaSJens Wiklander 	 * this function which would panic.
92163f89caaSJens Wiklander 	 */
92263f89caaSJens Wiklander 	switch (proc_id) {
92363f89caaSJens Wiklander 	case PKCS11_PROCESSING_IMPORT:
92463f89caaSJens Wiklander 		assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
92563f89caaSJens Wiklander 		break;
92663f89caaSJens Wiklander 	default:
92763f89caaSJens Wiklander 		TEE_Panic(proc_id);
92863f89caaSJens Wiklander 		break;
92963f89caaSJens Wiklander 	}
93063f89caaSJens Wiklander 
93163f89caaSJens Wiklander 	return PKCS11_CKR_OK;
93263f89caaSJens Wiklander }
933512cbf1dSJens Wiklander 
934512cbf1dSJens Wiklander static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
935512cbf1dSJens Wiklander 				  uint32_t *min_key_size,
936512cbf1dSJens Wiklander 				  uint32_t *max_key_size)
937512cbf1dSJens Wiklander {
938512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
939512cbf1dSJens Wiklander 
940512cbf1dSJens Wiklander 	switch (key_type) {
941512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
942512cbf1dSJens Wiklander 		mechanism = PKCS11_CKM_AES_KEY_GEN;
943512cbf1dSJens Wiklander 		break;
944512cbf1dSJens Wiklander 	default:
945512cbf1dSJens Wiklander 		TEE_Panic(key_type);
946512cbf1dSJens Wiklander 		break;
947512cbf1dSJens Wiklander 	}
948512cbf1dSJens Wiklander 
949512cbf1dSJens Wiklander 	mechanism_supported_key_sizes(mechanism, min_key_size,
950512cbf1dSJens Wiklander 				      max_key_size);
951512cbf1dSJens Wiklander }
952512cbf1dSJens Wiklander 
953512cbf1dSJens Wiklander enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
954512cbf1dSJens Wiklander 				   struct obj_attrs *key2)
955512cbf1dSJens Wiklander {
956512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
957512cbf1dSJens Wiklander 	struct obj_attrs *secret = NULL;
958512cbf1dSJens Wiklander 	uint32_t max_key_size = 0;
959512cbf1dSJens Wiklander 	uint32_t min_key_size = 0;
960512cbf1dSJens Wiklander 	uint32_t key_length = 0;
961512cbf1dSJens Wiklander 
962512cbf1dSJens Wiklander 	switch (get_class(key1)) {
963512cbf1dSJens Wiklander 	case PKCS11_CKO_SECRET_KEY:
964512cbf1dSJens Wiklander 		secret = key1;
965512cbf1dSJens Wiklander 		break;
966512cbf1dSJens Wiklander 	default:
967512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
968512cbf1dSJens Wiklander 	}
969512cbf1dSJens Wiklander 
970512cbf1dSJens Wiklander 	if (key2)
971512cbf1dSJens Wiklander 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
972512cbf1dSJens Wiklander 
973512cbf1dSJens Wiklander 	if (secret) {
974512cbf1dSJens Wiklander 		switch (get_key_type(secret)) {
975512cbf1dSJens Wiklander 		case PKCS11_CKK_AES:
976512cbf1dSJens Wiklander 		case PKCS11_CKK_GENERIC_SECRET:
977512cbf1dSJens Wiklander 		case PKCS11_CKK_MD5_HMAC:
978512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA_1_HMAC:
979512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA224_HMAC:
980512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA256_HMAC:
981512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA384_HMAC:
982512cbf1dSJens Wiklander 		case PKCS11_CKK_SHA512_HMAC:
983512cbf1dSJens Wiklander 			break;
984512cbf1dSJens Wiklander 		default:
985512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
986512cbf1dSJens Wiklander 		}
987512cbf1dSJens Wiklander 
988512cbf1dSJens Wiklander 		/* Get key size */
989512cbf1dSJens Wiklander 		rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN,
990512cbf1dSJens Wiklander 				       &key_length);
991512cbf1dSJens Wiklander 		if (rc)
992512cbf1dSJens Wiklander 			return PKCS11_CKR_TEMPLATE_INCONSISTENT;
993512cbf1dSJens Wiklander 	}
994512cbf1dSJens Wiklander 
995512cbf1dSJens Wiklander 	get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size);
996512cbf1dSJens Wiklander 	if (key_length < min_key_size || key_length > max_key_size) {
997512cbf1dSJens Wiklander 		EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]",
998512cbf1dSJens Wiklander 		     key_length, min_key_size, max_key_size);
999512cbf1dSJens Wiklander 
1000512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_SIZE_RANGE;
1001512cbf1dSJens Wiklander 	}
1002512cbf1dSJens Wiklander 
1003512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1004512cbf1dSJens Wiklander }
1005512cbf1dSJens Wiklander 
1006512cbf1dSJens Wiklander /* Check processing ID against attribute ALLOWED_MECHANISMS if any */
1007512cbf1dSJens Wiklander static bool parent_key_complies_allowed_processings(uint32_t proc_id,
1008512cbf1dSJens Wiklander 						    struct obj_attrs *head)
1009512cbf1dSJens Wiklander {
1010512cbf1dSJens Wiklander 	char *attr = NULL;
1011512cbf1dSJens Wiklander 	uint32_t size = 0;
1012512cbf1dSJens Wiklander 	uint32_t proc = 0;
1013512cbf1dSJens Wiklander 	size_t count = 0;
1014512cbf1dSJens Wiklander 
1015512cbf1dSJens Wiklander 	/* Check only if restricted allowed mechanisms list is defined */
1016512cbf1dSJens Wiklander 	if (get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS,
1017512cbf1dSJens Wiklander 			      (void *)&attr, &size) != PKCS11_CKR_OK) {
1018512cbf1dSJens Wiklander 		return true;
1019512cbf1dSJens Wiklander 	}
1020512cbf1dSJens Wiklander 
1021512cbf1dSJens Wiklander 	for (count = size / sizeof(uint32_t); count; count--) {
1022512cbf1dSJens Wiklander 		TEE_MemMove(&proc, attr, sizeof(uint32_t));
1023512cbf1dSJens Wiklander 		attr += sizeof(uint32_t);
1024512cbf1dSJens Wiklander 
1025512cbf1dSJens Wiklander 		if (proc == proc_id)
1026512cbf1dSJens Wiklander 			return true;
1027512cbf1dSJens Wiklander 	}
1028512cbf1dSJens Wiklander 
1029512cbf1dSJens Wiklander 	DMSG("can't find %s in allowed list", id2str_proc(proc_id));
1030512cbf1dSJens Wiklander 	return false;
1031512cbf1dSJens Wiklander }
1032512cbf1dSJens Wiklander 
1033512cbf1dSJens Wiklander static enum pkcs11_attr_id func_to_attr(enum processing_func func)
1034512cbf1dSJens Wiklander {
1035512cbf1dSJens Wiklander 	switch (func) {
1036512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
1037512cbf1dSJens Wiklander 		return PKCS11_CKA_ENCRYPT;
1038512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
1039512cbf1dSJens Wiklander 		return PKCS11_CKA_DECRYPT;
1040512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
1041512cbf1dSJens Wiklander 		return PKCS11_CKA_SIGN;
1042512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
1043512cbf1dSJens Wiklander 		return PKCS11_CKA_VERIFY;
1044512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_WRAP:
1045512cbf1dSJens Wiklander 		return PKCS11_CKA_WRAP;
1046512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_UNWRAP:
1047512cbf1dSJens Wiklander 		return PKCS11_CKA_UNWRAP;
1048512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DERIVE:
1049512cbf1dSJens Wiklander 		return PKCS11_CKA_DERIVE;
1050512cbf1dSJens Wiklander 	default:
1051512cbf1dSJens Wiklander 		return PKCS11_CKA_UNDEFINED_ID;
1052512cbf1dSJens Wiklander 	}
1053512cbf1dSJens Wiklander }
1054512cbf1dSJens Wiklander 
1055512cbf1dSJens Wiklander enum pkcs11_rc
1056512cbf1dSJens Wiklander check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
1057512cbf1dSJens Wiklander 				      enum processing_func function,
1058512cbf1dSJens Wiklander 				      struct obj_attrs *head)
1059512cbf1dSJens Wiklander {
1060512cbf1dSJens Wiklander 	enum pkcs11_class_id key_class = get_class(head);
1061512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(head);
1062512cbf1dSJens Wiklander 	enum pkcs11_attr_id attr = func_to_attr(function);
1063512cbf1dSJens Wiklander 
1064512cbf1dSJens Wiklander 	if (!get_bool(head, attr)) {
1065512cbf1dSJens Wiklander 		DMSG("%s not permitted", id2str_attr(attr));
1066512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1067512cbf1dSJens Wiklander 	}
1068512cbf1dSJens Wiklander 
1069512cbf1dSJens Wiklander 	/* Check processing complies with parent key family */
1070512cbf1dSJens Wiklander 	switch (proc_id) {
1071512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
1072512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
1073512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
1074512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
1075512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
1076512cbf1dSJens Wiklander 		if (key_class == PKCS11_CKO_SECRET_KEY &&
1077512cbf1dSJens Wiklander 		    key_type == PKCS11_CKK_AES)
1078512cbf1dSJens Wiklander 			break;
1079512cbf1dSJens Wiklander 
1080512cbf1dSJens Wiklander 		DMSG("%s invalid key %s/%s", id2str_proc(proc_id),
1081512cbf1dSJens Wiklander 		     id2str_class(key_class), id2str_key_type(key_type));
1082512cbf1dSJens Wiklander 
1083512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1084512cbf1dSJens Wiklander 
1085512cbf1dSJens Wiklander 	default:
1086512cbf1dSJens Wiklander 		DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
1087512cbf1dSJens Wiklander 		     id2str_proc(proc_id));
1088512cbf1dSJens Wiklander 
1089512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
1090512cbf1dSJens Wiklander 	}
1091512cbf1dSJens Wiklander 
1092512cbf1dSJens Wiklander 	if (!parent_key_complies_allowed_processings(proc_id, head)) {
1093512cbf1dSJens Wiklander 		DMSG("Allowed mechanism failed");
1094512cbf1dSJens Wiklander 		return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
1095512cbf1dSJens Wiklander 	}
1096512cbf1dSJens Wiklander 
1097512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
1098512cbf1dSJens Wiklander }
1099