drivers/platform/cznic/turris-omnia-mcu-keyctl.c

Source file repositories/reference/linux-study-clean/drivers/platform/cznic/turris-omnia-mcu-keyctl.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/cznic/turris-omnia-mcu-keyctl.c
Extension
.c
Size
3909 bytes
Lines
163
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * CZ.NIC's Turris Omnia MCU ECDSA message signing via keyctl
 *
 * 2025 by Marek BehĂșn <kabel@kernel.org>
 */

#include <crypto/sha2.h>
#include <linux/cleanup.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/key.h>
#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/types.h>

#include <linux/turris-omnia-mcu-interface.h>
#include <linux/turris-signing-key.h>
#include "turris-omnia-mcu.h"

static irqreturn_t omnia_msg_signed_irq_handler(int irq, void *dev_id)
{
	u8 reply[1 + OMNIA_MCU_CRYPTO_SIGNATURE_LEN];
	struct omnia_mcu *mcu = dev_id;
	int err;

	err = omnia_cmd_read(mcu->client, OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE,
			     reply, sizeof(reply));
	if (!err && reply[0] != OMNIA_MCU_CRYPTO_SIGNATURE_LEN)
		err = -EIO;

	guard(mutex)(&mcu->sign_lock);

	if (mcu->sign_requested) {
		mcu->sign_err = err;
		if (!err)
			memcpy(mcu->signature, &reply[1],
			       OMNIA_MCU_CRYPTO_SIGNATURE_LEN);
		mcu->sign_requested = false;
		complete(&mcu->msg_signed);
	}

	return IRQ_HANDLED;
}

static int omnia_mcu_sign(const struct key *key, const void *msg,
			  void *signature)
{
	struct omnia_mcu *mcu = dev_get_drvdata(turris_signing_key_get_dev(key));
	u8 cmd[1 + SHA256_DIGEST_SIZE], reply;
	int err;

	scoped_guard(mutex, &mcu->sign_lock) {
		if (mcu->sign_requested)
			return -EBUSY;

		cmd[0] = OMNIA_CMD_CRYPTO_SIGN_MESSAGE;
		memcpy(&cmd[1], msg, SHA256_DIGEST_SIZE);

		err = omnia_cmd_write_read(mcu->client, cmd, sizeof(cmd),
					   &reply, 1);
		if (err)
			return err;

		if (!reply)
			return -EBUSY;

		mcu->sign_requested = true;
	}

	if (wait_for_completion_interruptible(&mcu->msg_signed))
		return -EINTR;

	guard(mutex)(&mcu->sign_lock);

	if (mcu->sign_err)
		return mcu->sign_err;

	memcpy(signature, mcu->signature, OMNIA_MCU_CRYPTO_SIGNATURE_LEN);

	/* forget the signature, for security */
	memzero_explicit(mcu->signature, sizeof(mcu->signature));

	return OMNIA_MCU_CRYPTO_SIGNATURE_LEN;
}

static const void *omnia_mcu_get_public_key(const struct key *key)

Annotation

Implementation Notes