19e91a619SVesa Jääskeläinen // SPDX-License-Identifier: BSD-2-Clause
29e91a619SVesa Jääskeläinen /*
39e91a619SVesa Jääskeläinen * Copyright (c) 2021, Vaisala Oyj
49e91a619SVesa Jääskeläinen */
59e91a619SVesa Jääskeläinen
69e91a619SVesa Jääskeläinen #include <assert.h>
7eb88d2deSVesa Jääskeläinen #include <config.h>
89e91a619SVesa Jääskeläinen #include <pkcs11_ta.h>
99e91a619SVesa Jääskeläinen #include <string.h>
109e91a619SVesa Jääskeläinen #include <tee_api_defines.h>
119e91a619SVesa Jääskeläinen #include <tee_internal_api.h>
129e91a619SVesa Jääskeläinen #include <tee_internal_api_extensions.h>
139e91a619SVesa Jääskeläinen #include <utee_defines.h>
149e91a619SVesa Jääskeläinen #include <util.h>
159e91a619SVesa Jääskeläinen
169e91a619SVesa Jääskeläinen #include "attributes.h"
179e91a619SVesa Jääskeläinen #include "object.h"
189e91a619SVesa Jääskeläinen #include "pkcs11_attributes.h"
199e91a619SVesa Jääskeläinen #include "pkcs11_helpers.h"
209e91a619SVesa Jääskeläinen #include "pkcs11_token.h"
219e91a619SVesa Jääskeläinen #include "processing.h"
229e91a619SVesa Jääskeläinen #include "serializer.h"
239e91a619SVesa Jääskeläinen
processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id)249e91a619SVesa Jääskeläinen bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id)
259e91a619SVesa Jääskeläinen {
269e91a619SVesa Jääskeläinen switch (mecha_id) {
279e91a619SVesa Jääskeläinen case PKCS11_CKM_MD5:
289e91a619SVesa Jääskeläinen case PKCS11_CKM_SHA_1:
299e91a619SVesa Jääskeläinen case PKCS11_CKM_SHA224:
309e91a619SVesa Jääskeläinen case PKCS11_CKM_SHA256:
319e91a619SVesa Jääskeläinen case PKCS11_CKM_SHA384:
329e91a619SVesa Jääskeläinen case PKCS11_CKM_SHA512:
339e91a619SVesa Jääskeläinen return true;
349e91a619SVesa Jääskeläinen default:
359e91a619SVesa Jääskeläinen return false;
369e91a619SVesa Jääskeläinen }
379e91a619SVesa Jääskeläinen }
389e91a619SVesa Jääskeläinen
399e91a619SVesa Jääskeläinen static enum pkcs11_rc
pkcs2tee_algorithm(uint32_t * tee_id,struct pkcs11_attribute_head * proc_params)409e91a619SVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
419e91a619SVesa Jääskeläinen {
429e91a619SVesa Jääskeläinen static const struct {
439e91a619SVesa Jääskeläinen enum pkcs11_mechanism_id mech_id;
449e91a619SVesa Jääskeläinen uint32_t tee_id;
459e91a619SVesa Jääskeläinen } pkcs2tee_algo[] = {
469e91a619SVesa Jääskeläinen { PKCS11_CKM_MD5, TEE_ALG_MD5 },
479e91a619SVesa Jääskeläinen { PKCS11_CKM_SHA_1, TEE_ALG_SHA1 },
489e91a619SVesa Jääskeläinen { PKCS11_CKM_SHA224, TEE_ALG_SHA224 },
499e91a619SVesa Jääskeläinen { PKCS11_CKM_SHA256, TEE_ALG_SHA256 },
509e91a619SVesa Jääskeläinen { PKCS11_CKM_SHA384, TEE_ALG_SHA384 },
519e91a619SVesa Jääskeläinen { PKCS11_CKM_SHA512, TEE_ALG_SHA512 },
529e91a619SVesa Jääskeläinen };
539e91a619SVesa Jääskeläinen size_t n = 0;
549e91a619SVesa Jääskeläinen
559e91a619SVesa Jääskeläinen for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
569e91a619SVesa Jääskeläinen if (proc_params->id == pkcs2tee_algo[n].mech_id) {
579e91a619SVesa Jääskeläinen *tee_id = pkcs2tee_algo[n].tee_id;
589e91a619SVesa Jääskeläinen return PKCS11_CKR_OK;
599e91a619SVesa Jääskeläinen }
609e91a619SVesa Jääskeläinen }
619e91a619SVesa Jääskeläinen
629e91a619SVesa Jääskeläinen return PKCS11_RV_NOT_IMPLEMENTED;
639e91a619SVesa Jääskeläinen }
649e91a619SVesa Jääskeläinen
659e91a619SVesa Jääskeläinen static enum pkcs11_rc
allocate_tee_operation(struct pkcs11_session * session,struct pkcs11_attribute_head * params)669e91a619SVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session,
679e91a619SVesa Jääskeläinen struct pkcs11_attribute_head *params)
689e91a619SVesa Jääskeläinen {
699e91a619SVesa Jääskeläinen uint32_t algo = 0;
709e91a619SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC;
719e91a619SVesa Jääskeläinen
729e91a619SVesa Jääskeläinen assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
739e91a619SVesa Jääskeläinen
749e91a619SVesa Jääskeläinen if (pkcs2tee_algorithm(&algo, params))
759e91a619SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED;
769e91a619SVesa Jääskeläinen
779e91a619SVesa Jääskeläinen res = TEE_AllocateOperation(&session->processing->tee_op_handle,
789e91a619SVesa Jääskeläinen algo, TEE_MODE_DIGEST, 0);
799e91a619SVesa Jääskeläinen if (res)
809e91a619SVesa Jääskeläinen EMSG("TEE_AllocateOp. failed %#"PRIx32, algo);
819e91a619SVesa Jääskeläinen
829e91a619SVesa Jääskeläinen if (res == TEE_ERROR_NOT_SUPPORTED)
839e91a619SVesa Jääskeläinen return PKCS11_CKR_MECHANISM_INVALID;
849e91a619SVesa Jääskeläinen
859e91a619SVesa Jääskeläinen return tee2pkcs_error(res);
869e91a619SVesa Jääskeläinen }
879e91a619SVesa Jääskeläinen
init_digest_operation(struct pkcs11_session * session,struct pkcs11_attribute_head * proc_params)889e91a619SVesa Jääskeläinen enum pkcs11_rc init_digest_operation(struct pkcs11_session *session,
899e91a619SVesa Jääskeläinen struct pkcs11_attribute_head *proc_params)
909e91a619SVesa Jääskeläinen {
91909efccbSEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
92909efccbSEtienne Carriere
939e91a619SVesa Jääskeläinen assert(processing_is_tee_digest(proc_params->id));
949e91a619SVesa Jääskeläinen
95909efccbSEtienne Carriere rc = allocate_tee_operation(session, proc_params);
96909efccbSEtienne Carriere if (!rc)
97909efccbSEtienne Carriere session->processing->mecha_type = proc_params->id;
98909efccbSEtienne Carriere
99909efccbSEtienne Carriere return rc;
1009e91a619SVesa Jääskeläinen }
1019e91a619SVesa Jääskeläinen
1029e91a619SVesa Jääskeläinen /*
1039e91a619SVesa Jääskeläinen * step_digest_operation - processing digest operation step
1049e91a619SVesa Jääskeläinen *
1059e91a619SVesa Jääskeläinen * @session - current session
1069e91a619SVesa Jääskeläinen * @step - step ID in the processing (oneshot, update, final)
1079e91a619SVesa Jääskeläinen * @obj - PKCS#11 object for key based operations
1089e91a619SVesa Jääskeläinen * @ptype - invocation parameter types
1099e91a619SVesa Jääskeläinen * @params - invocation parameter references
1109e91a619SVesa Jääskeläinen */
step_digest_operation(struct pkcs11_session * session,enum processing_step step,struct pkcs11_object * obj,uint32_t ptypes,TEE_Param * params)1119e91a619SVesa Jääskeläinen enum pkcs11_rc step_digest_operation(struct pkcs11_session *session,
1129e91a619SVesa Jääskeläinen enum processing_step step,
1139e91a619SVesa Jääskeläinen struct pkcs11_object *obj,
1149e91a619SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params)
1159e91a619SVesa Jääskeläinen {
1169e91a619SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1179e91a619SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC;
1189e91a619SVesa Jääskeläinen void *in_buf = NULL;
1199e91a619SVesa Jääskeläinen size_t in_size = 0;
1209e91a619SVesa Jääskeläinen void *out_buf = NULL;
121*c7f1b4f7SJens Wiklander size_t out_size = 0;
1229e91a619SVesa Jääskeläinen void *secret_value = NULL;
1239e91a619SVesa Jääskeläinen uint32_t secret_value_size = 0;
1249e91a619SVesa Jääskeläinen enum pkcs11_key_type key_type = PKCS11_CKK_UNDEFINED_ID;
1259e91a619SVesa Jääskeläinen struct active_processing *proc = session->processing;
1269e91a619SVesa Jääskeläinen
1279e91a619SVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
1289e91a619SVesa Jääskeläinen in_buf = params[1].memref.buffer;
1299e91a619SVesa Jääskeläinen in_size = params[1].memref.size;
1309e91a619SVesa Jääskeläinen if (in_size && !in_buf)
1319e91a619SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1329e91a619SVesa Jääskeläinen }
1339e91a619SVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
1349e91a619SVesa Jääskeläinen out_buf = params[2].memref.buffer;
1359e91a619SVesa Jääskeläinen out_size = params[2].memref.size;
1369e91a619SVesa Jääskeläinen if (out_size && !out_buf)
1379e91a619SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1389e91a619SVesa Jääskeläinen }
1399e91a619SVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
1409e91a619SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1419e91a619SVesa Jääskeläinen
1429e91a619SVesa Jääskeläinen switch (step) {
1439e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_ONESHOT:
1449e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE:
1459e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY:
1469e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_FINAL:
1479e91a619SVesa Jääskeläinen break;
1489e91a619SVesa Jääskeläinen default:
1499e91a619SVesa Jääskeläinen TEE_Panic(step);
1509e91a619SVesa Jääskeläinen break;
1519e91a619SVesa Jääskeläinen }
1529e91a619SVesa Jääskeläinen
1539e91a619SVesa Jääskeläinen assert(proc->tee_op_handle != TEE_HANDLE_NULL);
1549e91a619SVesa Jääskeläinen
1559e91a619SVesa Jääskeläinen assert(processing_is_tee_digest(proc->mecha_type));
1569e91a619SVesa Jääskeläinen
1579e91a619SVesa Jääskeläinen /*
1589e91a619SVesa Jääskeläinen * Feed active operation with data
1599e91a619SVesa Jääskeläinen */
1609e91a619SVesa Jääskeläinen
1619e91a619SVesa Jääskeläinen switch (step) {
1629e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY:
1639e91a619SVesa Jääskeläinen assert(obj);
1649e91a619SVesa Jääskeläinen
165eb88d2deSVesa Jääskeläinen if (!IS_ENABLED(CFG_PKCS11_TA_ALLOW_DIGEST_KEY))
166eb88d2deSVesa Jääskeläinen return PKCS11_CKR_KEY_INDIGESTIBLE;
167eb88d2deSVesa Jääskeläinen
1689e91a619SVesa Jääskeläinen if (get_class(obj->attributes) != PKCS11_CKO_SECRET_KEY)
1699e91a619SVesa Jääskeläinen return PKCS11_CKR_KEY_INDIGESTIBLE;
1709e91a619SVesa Jääskeläinen
1719e91a619SVesa Jääskeläinen key_type = get_key_type(obj->attributes);
1729e91a619SVesa Jääskeläinen
1739e91a619SVesa Jääskeläinen if (key_type != PKCS11_CKK_GENERIC_SECRET &&
1749e91a619SVesa Jääskeläinen key_type != PKCS11_CKK_AES)
1759e91a619SVesa Jääskeläinen return PKCS11_CKR_KEY_INDIGESTIBLE;
1769e91a619SVesa Jääskeläinen
1779e91a619SVesa Jääskeläinen rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_VALUE,
1789e91a619SVesa Jääskeläinen &secret_value, &secret_value_size);
1799e91a619SVesa Jääskeläinen assert(!rc && secret_value && secret_value_size);
1809e91a619SVesa Jääskeläinen
1819e91a619SVesa Jääskeläinen TEE_DigestUpdate(proc->tee_op_handle, secret_value,
1829e91a619SVesa Jääskeläinen secret_value_size);
1839e91a619SVesa Jääskeläinen return PKCS11_CKR_OK;
1849e91a619SVesa Jääskeläinen
1859e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE:
1869e91a619SVesa Jääskeläinen if (!in_buf || !in_size)
1879e91a619SVesa Jääskeläinen return PKCS11_CKR_OK;
1889e91a619SVesa Jääskeläinen
1899e91a619SVesa Jääskeläinen TEE_DigestUpdate(proc->tee_op_handle, in_buf, in_size);
1909e91a619SVesa Jääskeläinen return PKCS11_CKR_OK;
1919e91a619SVesa Jääskeläinen
1929e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_ONESHOT:
1939e91a619SVesa Jääskeläinen if (!out_buf)
1949e91a619SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1959e91a619SVesa Jääskeläinen
1969e91a619SVesa Jääskeläinen goto do_final;
1979e91a619SVesa Jääskeläinen
1989e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_FINAL:
1999e91a619SVesa Jääskeläinen if (in_buf || !out_buf)
2009e91a619SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
2019e91a619SVesa Jääskeläinen
2029e91a619SVesa Jääskeläinen goto do_final;
2039e91a619SVesa Jääskeläinen
2049e91a619SVesa Jääskeläinen default:
2059e91a619SVesa Jääskeläinen TEE_Panic(step);
2069e91a619SVesa Jääskeläinen break;
2079e91a619SVesa Jääskeläinen }
2089e91a619SVesa Jääskeläinen
2099e91a619SVesa Jääskeläinen do_final:
2109e91a619SVesa Jääskeläinen res = TEE_DigestDoFinal(proc->tee_op_handle,
2119e91a619SVesa Jääskeläinen in_buf, in_size, out_buf,
2129e91a619SVesa Jääskeläinen &out_size);
2139e91a619SVesa Jääskeläinen rc = tee2pkcs_error(res);
2149e91a619SVesa Jääskeläinen
2159e91a619SVesa Jääskeläinen if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
2169e91a619SVesa Jääskeläinen params[2].memref.size = out_size;
2179e91a619SVesa Jääskeläinen
2189e91a619SVesa Jääskeläinen return rc;
2199e91a619SVesa Jääskeläinen }
220