Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/platform/cznic/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 3 kB image not shown  

Quelle  turris-omnia-mcu-keyctl.c   Sprache: C

 
// 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)
{
 struct omnia_mcu *mcu = dev_get_drvdata(turris_signing_key_get_dev(key));

 return mcu->board_public_key;
}

static const struct turris_signing_key_subtype omnia_signing_key_subtype = {
 .key_size  = 256,
 .data_size  = SHA256_DIGEST_SIZE,
 .sig_size  = OMNIA_MCU_CRYPTO_SIGNATURE_LEN,
 .public_key_size = OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN,
 .hash_algo  = "sha256",
 .get_public_key  = omnia_mcu_get_public_key,
 .sign   = omnia_mcu_sign,
};

static int omnia_mcu_read_public_key(struct omnia_mcu *mcu)
{
 u8 reply[1 + OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN];
 int err;

 err = omnia_cmd_read(mcu->client, OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY,
        reply, sizeof(reply));
 if (err)
  return err;

 if (reply[0] != OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN)
  return -EIO;

 memcpy(mcu->board_public_key, &reply[1],
        OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN);

 return 0;
}

int omnia_mcu_register_keyctl(struct omnia_mcu *mcu)
{
 struct device *dev = &mcu->client->dev;
 char desc[48];
 int err;

 if (!(mcu->features & OMNIA_FEAT_CRYPTO))
  return 0;

 err = omnia_mcu_read_public_key(mcu);
 if (err)
  return dev_err_probe(dev, err,
         "Cannot read board public key\n");

 err = devm_mutex_init(dev, &mcu->sign_lock);
 if (err)
  return err;

 init_completion(&mcu->msg_signed);

 err = omnia_mcu_request_irq(mcu, OMNIA_INT_MESSAGE_SIGNED,
        omnia_msg_signed_irq_handler,
        "turris-omnia-mcu-keyctl");
 if (err)
  return dev_err_probe(dev, err,
         "Cannot request MESSAGE_SIGNED IRQ\n");

 sprintf(desc, "Turris Omnia SN %016llX MCU ECDSA key",
  mcu->board_serial_number);

 err = devm_turris_signing_key_create(dev, &omnia_signing_key_subtype,
          desc);
 if (err)
  return dev_err_probe(dev, err, "Cannot create signing key\n");

 return 0;
}

Messung V0.5
C=99 H=100 G=99

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.