162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <keys/trusted_caam.h>
762306a36Sopenharmony_ci#include <keys/trusted-type.h>
862306a36Sopenharmony_ci#include <linux/build_bug.h>
962306a36Sopenharmony_ci#include <linux/key-type.h>
1062306a36Sopenharmony_ci#include <soc/fsl/caam-blob.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic struct caam_blob_priv *blobifier;
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define KEYMOD "SECURE_KEY"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN);
1762306a36Sopenharmony_cistatic_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN);
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic int trusted_caam_seal(struct trusted_key_payload *p, char *datablob)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	int ret;
2262306a36Sopenharmony_ci	struct caam_blob_info info = {
2362306a36Sopenharmony_ci		.input  = p->key,  .input_len   = p->key_len,
2462306a36Sopenharmony_ci		.output = p->blob, .output_len  = MAX_BLOB_SIZE,
2562306a36Sopenharmony_ci		.key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1,
2662306a36Sopenharmony_ci	};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	ret = caam_encap_blob(blobifier, &info);
2962306a36Sopenharmony_ci	if (ret)
3062306a36Sopenharmony_ci		return ret;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	p->blob_len = info.output_len;
3362306a36Sopenharmony_ci	return 0;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	int ret;
3962306a36Sopenharmony_ci	struct caam_blob_info info = {
4062306a36Sopenharmony_ci		.input   = p->blob,  .input_len  = p->blob_len,
4162306a36Sopenharmony_ci		.output  = p->key,   .output_len = MAX_KEY_SIZE,
4262306a36Sopenharmony_ci		.key_mod = KEYMOD,  .key_mod_len = sizeof(KEYMOD) - 1,
4362306a36Sopenharmony_ci	};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	ret = caam_decap_blob(blobifier, &info);
4662306a36Sopenharmony_ci	if (ret)
4762306a36Sopenharmony_ci		return ret;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	p->key_len = info.output_len;
5062306a36Sopenharmony_ci	return 0;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic int trusted_caam_init(void)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	int ret;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	blobifier = caam_blob_gen_init();
5862306a36Sopenharmony_ci	if (IS_ERR(blobifier))
5962306a36Sopenharmony_ci		return PTR_ERR(blobifier);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	ret = register_key_type(&key_type_trusted);
6262306a36Sopenharmony_ci	if (ret)
6362306a36Sopenharmony_ci		caam_blob_gen_exit(blobifier);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return ret;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic void trusted_caam_exit(void)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	unregister_key_type(&key_type_trusted);
7162306a36Sopenharmony_ci	caam_blob_gen_exit(blobifier);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistruct trusted_key_ops trusted_key_caam_ops = {
7562306a36Sopenharmony_ci	.migratable = 0, /* non-migratable */
7662306a36Sopenharmony_ci	.init = trusted_caam_init,
7762306a36Sopenharmony_ci	.seal = trusted_caam_seal,
7862306a36Sopenharmony_ci	.unseal = trusted_caam_unseal,
7962306a36Sopenharmony_ci	.exit = trusted_caam_exit,
8062306a36Sopenharmony_ci};
81