Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F141944341
D45593.id140221.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D45593.id140221.diff
View Options
diff --git a/sys/arm64/qoriq/caam/caam_crypto.c b/sys/arm64/qoriq/caam/caam_crypto.c
--- a/sys/arm64/qoriq/caam/caam_crypto.c
+++ b/sys/arm64/qoriq/caam/caam_crypto.c
@@ -20,6 +20,8 @@
#include <machine/bus.h>
#include <machine/vfp.h>
+#include <dev/hwencap/hwencap_ioctl.h>
+
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform.h>
@@ -63,8 +65,20 @@
device_t jr_dev;
};
+struct caam_blob_operation {
+ struct job_descriptor jobdesc;
+ bool encapsulate;
+
+ caam_jr_dma_map_t key_mod;
+ caam_jr_dma_map_t in;
+ caam_jr_dma_map_t out;
+};
+
MALLOC_DEFINE(M_CAAM, "caam", "caam cryptography buffers");
+/* For use with character device interface */
+static device_t g_caam_dev;
+
static void
dma_data_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
@@ -369,10 +383,367 @@
return (0);
}
+static d_open_t caam_hwencap_cdev_open;
+static d_close_t caam_hwencap_cdev_close;
+static d_ioctl_t caam_hwencap_cdev_ioctl;
+
+static struct cdevsw caam_hwencap_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = caam_hwencap_cdev_open,
+ .d_close = caam_hwencap_cdev_close,
+ .d_ioctl = caam_hwencap_cdev_ioctl,
+ .d_name = "caam_hwencap_cdev",
+};
+
+static int
+caam_hwencap_cdev_open(struct cdev *dev __unused, int oflags __unused,
+ int devtype __unused, struct thread *td __unused)
+{
+ /* Nothing to do */
+ return (0);
+}
+
+static int
+caam_hwencap_cdev_close(struct cdev *dev __unused, int fflag __unused,
+ int devtype __unused, struct thread *td __unused)
+{
+ /* Nothing to do */
+ return (0);
+}
+
+static void
+caam_blob_op_build_desc(struct caam_blob_operation *op, bool little_endian)
+{
+ uint32_t *desc = op->jobdesc.desc;
+
+ caam_jobdesc_init(desc);
+ caam_jobdesc_add_word(desc, DESC_HEADER(0));
+
+ caam_jobdesc_add_word(desc, CMD_CLASS(CLASS_2) | op->key_mod.buflen);
+ caam_jobdesc_add_ptr(desc, op->key_mod.bus_addr, little_endian);
+
+ caam_jobdesc_add_word(desc, SEQ_IN_PTR_EXT);
+ caam_jobdesc_add_ptr(desc, op->in.bus_addr, little_endian);
+ caam_jobdesc_add_word(desc, op->in.buflen);
+
+ caam_jobdesc_add_word(desc, SEQ_OUT_PTR_EXT);
+ caam_jobdesc_add_ptr(desc, op->out.bus_addr, little_endian);
+ caam_jobdesc_add_word(desc, op->out.buflen);
+
+ if (op->encapsulate)
+ caam_jobdesc_add_word(desc, BLOB_ENCAPS | PROT_BLOB_TYPE_RED);
+ else
+ caam_jobdesc_add_word(desc, BLOB_DECAPS | PROT_BLOB_TYPE_RED);
+}
+
+static int
+caam_crypto_red_blob_op(device_t dev, bool encapsulate, void *in,
+ uint32_t in_sz, void *out, uint32_t out_sz)
+{
+ int rv;
+ device_t jr_dev;
+ struct caam_softc *sc;
+ struct caam_blob_operation *op;
+ uint8_t key_blob_modifier[BLOB_KEY_MODIFIER_SIZE] = "CAAM_RED_BLOB";
+
+ if (in_sz > BLOB_MAX_BUFFER_LEN || out_sz > BLOB_MAX_BUFFER_LEN) {
+ CAAM_LOG_DEV_WARN(dev, "Buffer len too large for a register\n");
+ rv = EINVAL;
+ goto exit;
+ }
+
+ op = malloc_aligned(sizeof(*op), PAGE_SIZE, M_CAAM_CRYPTO, M_NOWAIT);
+ if (op == NULL) {
+ CAAM_LOG_DEV_WARN(dev,
+ "Failed to allocate blob operation structure\n");
+ rv = ENOMEM;
+ goto exit;
+ }
+ op->encapsulate = encapsulate;
+ op->jobdesc.arg = NULL;
+ op->jobdesc.callback = NULL;
+
+ sc = device_get_softc(dev);
+ jr_dev = jr_pool_acquire(&sc->jr_pool);
+ if (jr_dev == 0) {
+ CAAM_LOG_DEV_WARN(dev, "Failed to acquire JR\n");
+ rv = EAGAIN;
+ goto op_cleanup;
+ }
+
+ /* Map and sync the key modifier */
+ rv = caam_jr_dma_map(jr_dev, &op->key_mod, key_blob_modifier,
+ sizeof(key_blob_modifier), BUS_DMA_COHERENT, BUS_DMA_WAITOK,
+ JR_MAP_SYNC);
+ if (rv != 0) {
+ CAAM_LOG_DEV_WARN(jr_dev,
+ "Failed to create key modifier map\n");
+ goto release_jr;
+ }
+
+ /* Map and sync the in buffer */
+ rv = caam_jr_dma_map(jr_dev, &op->in, in, in_sz, BUS_DMA_COHERENT,
+ BUS_DMA_WAITOK, JR_MAP_SYNC);
+ if (rv != 0) {
+ CAAM_LOG_DEV_WARN(jr_dev, "Failed to create in data map\n");
+ goto mod_map_cleanup;
+ }
+
+ /* Map the out buffer */
+ rv = caam_jr_dma_map(jr_dev, &op->out, out, out_sz, BUS_DMA_COHERENT,
+ BUS_DMA_WAITOK, JR_MAP_NOSYNC);
+ if (rv != 0) {
+ CAAM_LOG_DEV_WARN(jr_dev, "Failed to create out data map\n");
+ goto in_map_cleanup;
+ }
+
+ caam_blob_op_build_desc(op, sc->little_endian);
+
+ rv = caam_run_descriptor_jr_blocking(dev, &op->jobdesc, jr_dev);
+ if (rv != 0) {
+ CAAM_LOG_DEV_WARN(dev, "Failed to run descriptor rv=(%d)\n",
+ rv);
+ goto out_map_cleanup;
+ }
+
+ caam_jr_dma_sync_from_dma(jr_dev, &op->out);
+
+out_map_cleanup:
+ caam_jr_dma_unmap(jr_dev, &op->out, JR_MAP_NOSYNC);
+in_map_cleanup:
+ caam_jr_dma_unmap(jr_dev, &op->in, JR_MAP_NOSYNC);
+mod_map_cleanup:
+ caam_jr_dma_unmap(jr_dev, &op->key_mod, JR_MAP_NOSYNC);
+release_jr:
+ jr_pool_release(&sc->jr_pool, jr_dev);
+op_cleanup:
+ free(op, M_CAAM_CRYPTO);
+exit:
+ return (rv);
+}
+
+/*
+ * @brief Encapsulate data within a red blob.
+ *
+ * @param [in] dev caam device handle
+ * @param [in] in contiguous data buffer
+ * @param [in] in_sz data buffer length
+ * @param [out] out contiguous blob buffer
+ * @param [out] out_sz blob buffer length
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on internal error
+ */
+static int
+caam_crypto_red_blob_encap(device_t dev, void *in, uint32_t in_sz, void *out,
+ uint32_t out_sz)
+{
+ return caam_crypto_red_blob_op(dev, true, in, in_sz, out, out_sz);
+}
+
+/*
+ * @brief Decapsulate a red blob.
+ *
+ * @param [in] dev caam device handle
+ * @param [in] in contiguous blob buffer
+ * @param [in] in_sz blob buffer length
+ * @param [out] out contiguous data buffer
+ * @param [out] out_sz data buffer length
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on internal error
+ */
+static int
+caam_crypto_red_blob_decap(device_t dev, void *in, uint32_t in_sz, void *out,
+ uint32_t out_sz)
+{
+ return caam_crypto_red_blob_op(dev, false, in, in_sz, out, out_sz);
+}
+
+static int
+caam_crypto_encap(struct hwencap_encap_arg *arg)
+{
+ int rv;
+ uint8_t *plain, *blob;
+
+ if (arg->in_buf_sz < 1) {
+ CAAM_LOG_ERROR("Empty input buffer\n");
+ rv = EINVAL;
+ goto exit;
+ }
+
+ if (arg->out_buf_sz < arg->in_buf_sz + CAAM_CRYPTO_BLOB_OVERHEAD) {
+ CAAM_LOG_ERROR("out_buf_sz must be at least in_buf_sz + (%d)\n",
+ CAAM_CRYPTO_BLOB_OVERHEAD);
+ rv = EINVAL;
+ goto exit;
+ }
+
+ plain = contigmalloc(arg->in_buf_sz, M_CAAM_CRYPTO, M_NOWAIT | M_ZERO,
+ 0, ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (plain == NULL) {
+ rv = ENOMEM;
+ CAAM_LOG_ERROR("Failed to allocate contig plain\n");
+ goto exit;
+ }
+
+ blob = contigmalloc(arg->out_buf_sz, M_CAAM_CRYPTO, M_NOWAIT | M_ZERO,
+ 0, ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (blob == NULL) {
+ rv = ENOMEM;
+ CAAM_LOG_ERROR("Failed to allocate contig blob\n");
+ goto free_in;
+ }
+
+ rv = copyin((void *)arg->in_buf, plain, arg->in_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Copyin operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+ rv = caam_crypto_red_blob_encap(g_caam_dev, plain, arg->in_buf_sz, blob,
+ arg->out_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Blob operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+ rv = copyout(blob, (void *)arg->out_buf, arg->out_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Copyout operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+
+free_out:
+ contigfree(blob, arg->out_buf_sz, M_CAAM_CRYPTO);
+free_in:
+ contigfree(plain, arg->in_buf_sz, M_CAAM_CRYPTO);
+exit:
+
+ return (rv);
+}
+
+static int
+caam_crypto_decap(struct hwencap_encap_arg *arg)
+{
+ int rv;
+ uint8_t *blob, *plain;
+
+ if (arg->in_buf_sz <= CAAM_CRYPTO_BLOB_OVERHEAD) {
+ CAAM_LOG_ERROR("Malformed blob\n");
+ rv = EINVAL;
+ goto exit;
+ }
+
+ if (arg->out_buf_sz < arg->in_buf_sz - CAAM_CRYPTO_BLOB_OVERHEAD) {
+ CAAM_LOG_ERROR("out_buf_sz must be at least in_buf_sz - (%d)\n",
+ CAAM_CRYPTO_BLOB_OVERHEAD);
+ rv = EINVAL;
+ goto exit;
+ }
+
+ blob = contigmalloc(arg->in_buf_sz, M_CAAM_CRYPTO, M_NOWAIT | M_ZERO, 0,
+ ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (blob == NULL) {
+ rv = ENOMEM;
+ CAAM_LOG_ERROR("Failed to allocate contig in_buf\n");
+ goto exit;
+ }
+
+ plain = contigmalloc(arg->out_buf_sz, M_CAAM_CRYPTO, M_NOWAIT | M_ZERO,
+ 0, ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (plain == NULL) {
+ rv = ENOMEM;
+ CAAM_LOG_ERROR("Failed to allocate contig out_buf\n");
+ goto free_in;
+ }
+
+ rv = copyin((void *)arg->in_buf, blob, arg->in_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Copyin operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+ rv = caam_crypto_red_blob_decap(g_caam_dev, blob, arg->in_buf_sz, plain,
+ arg->out_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Blob operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+ rv = copyout(plain, (void *)arg->out_buf, arg->out_buf_sz);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Copyout operation failed rv=(%d)\n", rv);
+ goto free_out;
+ }
+
+free_out:
+ contigfree(plain, arg->out_buf_sz, M_CAAM_CRYPTO);
+free_in:
+ contigfree(blob, arg->in_buf_sz, M_CAAM_CRYPTO);
+exit:
+
+ return (rv);
+}
+
+static enum hwencap_mode
+caam_crypto_encap_mode(device_t caam_dev)
+{
+ uint32_t sec_status, mode;
+
+ sec_status = caam_reg_read(caam_dev, SEC_REG_SSTA_OFFSET);
+ mode = (sec_status & SSTA_MOO_MASK) >> SSTA_MOO_SHIFT;
+
+ switch (mode) {
+ case SSTA_MOO_SECURE:
+ case SSTA_MOO_TRUSTED:
+ return HWENCAP_MODE_HW_UNIQUE;
+ default:
+ return HWENCAP_MODE_HW_SHARED;
+ }
+}
+
+static int
+caam_hwencap_cdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
+ struct thread *td)
+{
+ struct hwencap_blob_sz_arg *blob_arg;
+ struct hwencap_encap_arg *arg;
+ enum hwencap_mode *mode_arg;
+ int error = 0;
+
+ switch (cmd) {
+ case HWENCAP_ENCAP:
+ arg = (struct hwencap_encap_arg *)addr;
+ error = caam_crypto_encap(arg);
+ break;
+ case HWENCAP_DECAP:
+ arg = (struct hwencap_encap_arg *)addr;
+ error = caam_crypto_decap(arg);
+ break;
+ case HWENCAP_ENCAP_BLOB_SZ:
+ blob_arg = (struct hwencap_blob_sz_arg *)addr;
+ blob_arg->out_sz = blob_arg->in_sz + CAAM_CRYPTO_BLOB_OVERHEAD;
+ break;
+ case HWENCAP_DECAP_PT_SZ:
+ blob_arg = (struct hwencap_blob_sz_arg *)addr;
+ if (blob_arg->in_sz <= CAAM_CRYPTO_BLOB_OVERHEAD)
+ return (EINVAL);
+ blob_arg->out_sz = blob_arg->in_sz - CAAM_CRYPTO_BLOB_OVERHEAD;
+ break;
+ case HWENCAP_MODE:
+ mode_arg = (enum hwencap_mode *)addr;
+ *mode_arg = caam_crypto_encap_mode(g_caam_dev);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+
+ return (error);
+}
+
int
caam_crypto_attach(device_t dev)
{
struct caam_softc *sc;
+ struct make_dev_args args;
int error = 0;
sc = device_get_softc(dev);
@@ -385,6 +756,28 @@
return (ENXIO);
}
+ if (g_caam_dev == NULL) {
+ g_caam_dev = dev;
+
+ make_dev_args_init(&args);
+ args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
+ args.mda_devsw = &caam_hwencap_cdevsw;
+ args.mda_cr = 0;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_WHEEL;
+ args.mda_mode = 0600;
+
+ CAAM_LOG_DEV_WARN(dev,
+ "Succesfully initialized caam hwencap backend\n");
+
+ error = make_dev_s(&args, &sc->crypto_cdev, "caam_hwencap");
+ if (error != 0) {
+ CAAM_LOG_DEV_WARN(dev,
+ "Failed to register caam hwencap device");
+ crypto_unregister_all(sc->crypto_id);
+ }
+ }
+
return (error);
}
@@ -395,4 +788,9 @@
sc = device_get_softc(dev);
crypto_unregister_all(sc->crypto_id);
+
+ if (g_caam_dev == dev) {
+ destroy_dev(sc->crypto_cdev);
+ g_caam_dev = NULL;
+ }
}
diff --git a/sys/arm64/qoriq/caam/caam_internal.h b/sys/arm64/qoriq/caam/caam_internal.h
--- a/sys/arm64/qoriq/caam/caam_internal.h
+++ b/sys/arm64/qoriq/caam/caam_internal.h
@@ -33,6 +33,7 @@
struct jr_pool jr_pool;
int32_t crypto_id;
+ struct cdev *crypto_cdev;
};
#endif /* CAAM_INTERNAL_H */
diff --git a/sys/dev/hwencap/hwencap_ioctl.h b/sys/dev/hwencap/hwencap_ioctl.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/hwencap/hwencap_ioctl.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 Alstom Group
+ * Copyright 2024 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HWENCAP_IOCTL_H
+#define HWENCAP_IOCTL_H
+
+#include <sys/ioccom.h>
+#include <sys/types.h>
+
+struct hwencap_encap_arg {
+ size_t in_buf_sz;
+ uintptr_t in_buf;
+ size_t out_buf_sz;
+ uintptr_t out_buf;
+};
+
+struct hwencap_blob_sz_arg {
+ size_t in_sz;
+ size_t out_sz;
+};
+
+enum hwencap_mode {
+ HWENCAP_MODE_HW_UNIQUE = 0, /* Blob bound to a specific device */
+ HWENCAP_MODE_HW_SHARED = 1, /* Blob portable between similar devices */
+ HWENCAP_MODE_SOFT = 2 /* Blob not HW bound */
+};
+
+#define HWENCAP_ENCAP _IOWR('a', 1, struct hwencap_encap_arg)
+#define HWENCAP_DECAP _IOWR('a', 2, struct hwencap_encap_arg)
+#define HWENCAP_ENCAP_BLOB_SZ _IOWR('a', 3, struct hwencap_blob_sz_arg)
+#define HWENCAP_DECAP_PT_SZ _IOWR('a', 4, struct hwencap_blob_sz_arg)
+#define HWENCAP_MODE _IOR('a', 5, int)
+
+#endif /* HWENCAP_IOCTL_H */
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -31,6 +31,7 @@
getfmac \
getpmac \
gstat \
+ hwencap \
i2c \
ifmcstat \
iostat \
diff --git a/usr.sbin/hwencap/Makefile b/usr.sbin/hwencap/Makefile
new file mode 100644
--- /dev/null
+++ b/usr.sbin/hwencap/Makefile
@@ -0,0 +1,8 @@
+
+PROG= hwencap
+MAN= hwencap.8
+SRCS= hwencap.c
+
+CFLAGS+= -I${SRCTOP}/sys
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/hwencap/hwencap.8 b/usr.sbin/hwencap/hwencap.8
new file mode 100644
--- /dev/null
+++ b/usr.sbin/hwencap/hwencap.8
@@ -0,0 +1,69 @@
+.Dd May 31, 2024
+.Dt HWENCAP 8
+.Os
+.Sh NAME
+.Nm hwencap
+.Nd hardware encapsulation tool
+.Sh SYNOPSIS
+.Nm
+.Fl -device Ns | Ns Fl f Ar device
+.Fl -encapsulate Ns | Ns Fl e
+.Op Fl -output Ns | Ns Fl o Ar output
+.Op Ar file
+.Nm
+.Fl -device Ns | Ns Fl f Ar device
+.Fl -decapsulate Ns | Ns Fl d
+.Op Fl -output Ns | Ns Fl o Ar output
+.Op Ar file
+.Nm
+.Fl -device Ns | Ns Fl f Ar device
+.Fl -getmode Ns | Ns Fl m
+.Sh DESCRIPTION
+.Nm
+uses a hardware device to encapsulate or decapsulate data.
+The device should use it's own key for encapsulation and
+the resulting output should only be able to be decoded on
+a device it was created.
+The data is by default read from standard input, but can be
+read from
+.Ar file.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl -device Ar device , Fl f Ar device
+Device file which implements the hwencap interface.
+This option is always needed.
+.It Fl -encapsulate , Fl e
+Encapsulate the input.
+.It Fl -decapsulate , Fl d
+Decapsulate the input.
+.It Fl -output Ar output , Fl o Ar output
+Output file. By default standard output is used.
+.It Fl -getmode , Fl m
+Get the mode of operation of hardware device.
+Some devices may not use unique key for encapsulation.
+This option allows checking if the key is unique and
+if the encapsulation occurs in hardware or software.
+.Sh EXAMPLES
+.Bl -tag -width 0n
+.It Sy Example 1\&: Encapsulate a key
+.Pp
+The following command encapsulates some key and
+stores it in output.key file.
+.Bd -literal -offset 2n
+.Li # Ic hwencap -f /dev/caam_hwencap -e -o output.key ./mykey
+.Ed
+.It Sy Example 2\&: Get mode of operation
+.Pp
+The following command reads the mode of operation of /dev/caam_hwencap
+.Bd -literal -offset 2n
+.Li # Ic hwencap -f /dev/caam_hwencap -m
+.Ed
+.El
+.Sh AUTHORS
+The
+.Nm
+tool was written by Sii Poland and sponsored by Alstom Group.
+.Pp
+This manual page was written by
+.An Dawid Gorecki Aq Mt dgorecki@sii.pl
diff --git a/usr.sbin/hwencap/hwencap.c b/usr.sbin/hwencap/hwencap.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/hwencap/hwencap.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2024 Alstom Group
+ * Copyright 2024 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/ioccom.h>
+
+#include <dev/hwencap/hwencap_ioctl.h>
+
+#define INITIAL_READ_SIZE 4096
+#define REALLOC_FACTOR 2
+
+enum blob_operation {
+ op_encap,
+ op_decap,
+ op_getmode,
+};
+
+enum optval {
+ opt_end = -1,
+ /* to not collide with shortops */
+ opt_dummy = CHAR_MAX,
+ opt_help,
+ opt_device,
+ opt_encap,
+ opt_decap,
+ opt_getmode,
+ opt_output,
+};
+
+static const struct option longopts[] = {
+ {"help", no_argument, 0, opt_help},
+ {"device", required_argument, 0, opt_device},
+ {"encapsulate", no_argument, 0, opt_encap},
+ {"decapsulate", no_argument, 0, opt_decap},
+ {"getmode", no_argument, 0, opt_getmode},
+ {"output", required_argument, 0, opt_output},
+ { }
+};
+
+static size_t
+read_input(FILE *f, void **buf_addr)
+{
+ size_t buf_len, new_buf_len, data_len, read_len;
+ uint8_t *buf, *new_buf;
+
+ /* Allocate initial buffer - will be realloced later if needed */
+ buf_len = INITIAL_READ_SIZE;
+ buf = malloc(buf_len);
+ if (buf == NULL)
+ err(EX_SOFTWARE, "Cannot allocate input memory");
+ data_len = 0;
+
+ while ((read_len = fread(&buf[data_len], 1, buf_len - data_len, f)) > 0) {
+ data_len += read_len;
+
+ if (buf_len - data_len == 0) {
+ /*
+ * Reallocate memory - realloc cannot be used, as
+ * we are dealing with something that needs to be
+ * cleared with explicit_bzero
+ */
+ new_buf_len = buf_len * REALLOC_FACTOR;
+ new_buf = malloc(new_buf_len);
+ if (new_buf == NULL) {
+ explicit_bzero(buf, data_len);
+ err(EX_SOFTWARE, "Cannot reallocate memory");
+ }
+
+ memcpy(new_buf, buf, data_len);
+ explicit_bzero(buf, data_len);
+ free(buf);
+
+ buf_len = new_buf_len;
+ buf = new_buf;
+ }
+ }
+
+ *buf_addr = buf;
+ return (data_len);
+}
+
+static void
+blob_operation(int dev_fd, const char *in_path, const char *out_path,
+ enum blob_operation op)
+{
+ struct hwencap_blob_sz_arg sz_arg = { 0 };
+ struct hwencap_encap_arg arg = { 0 };
+ FILE *inf, *outf;
+ size_t in_len;
+ void *in_buf;
+ int rv;
+ size_t written;
+
+ if (strcmp(in_path, "-") == 0)
+ inf = stdin;
+ else
+ inf = fopen(in_path, "r");
+ if (inf == NULL)
+ err(EX_IOERR, "Could not open input file %s", in_path);
+
+ in_len = read_input(inf, &in_buf);
+ if (inf != stdin)
+ fclose(inf);
+ arg.in_buf_sz = in_len;
+ arg.in_buf = (uintptr_t)in_buf;
+
+ sz_arg.in_sz = in_len;
+ rv = ioctl(dev_fd, (op == op_encap) ? HWENCAP_ENCAP_BLOB_SZ :
+ HWENCAP_DECAP_PT_SZ, &sz_arg);
+ if (rv != 0) {
+ explicit_bzero((void *)arg.in_buf, arg.in_buf_sz);
+ errx(EX_IOERR, "ioctl error");
+ }
+ arg.out_buf_sz = sz_arg.out_sz;
+
+ arg.out_buf = (uintptr_t)malloc(arg.out_buf_sz);
+ if ((void *)arg.out_buf == NULL) {
+ explicit_bzero((void *)arg.in_buf, arg.in_buf_sz);
+ errx(EX_IOERR, "Failed to allocate output buffer");
+ }
+
+ rv = ioctl(dev_fd, (op == op_encap) ? HWENCAP_ENCAP :
+ HWENCAP_DECAP, &arg);
+ if (rv != 0) {
+ explicit_bzero((void *)arg.in_buf, arg.in_buf_sz);
+ errx(EX_IOERR, "Failed to %s data", (op == op_encap) ?
+ "encapsulate" : "decapsulate");
+ }
+
+ explicit_bzero((void *)arg.in_buf, arg.in_buf_sz);
+ free((void *)arg.in_buf);
+
+ if (strcmp(out_path, "-") == 0)
+ outf = stdout;
+ else
+ outf = fopen(out_path, "w");
+ if (outf == NULL)
+ err(EX_IOERR, "Could not open output file %s", out_path);
+
+ written = fwrite((void *)arg.out_buf, 1, arg.out_buf_sz, outf);
+ if (written < arg.out_buf_sz) {
+ fprintf(stderr, "Failed to write entire output buffer\n");
+ }
+
+ explicit_bzero((void *)arg.out_buf, arg.out_buf_sz);
+ free((void *)arg.out_buf);
+
+ close(dev_fd);
+ if (outf != stdout)
+ fclose(outf);
+}
+
+static void
+getmode_operation(int dev_fd)
+{
+ int rv;
+ enum hwencap_mode mode;
+
+ rv = ioctl(dev_fd, HWENCAP_MODE, &mode);
+ if (rv != 0)
+ errx(EX_IOERR, "Failed to get encapsulation mode");
+
+ switch (mode) {
+ case HWENCAP_MODE_HW_UNIQUE:
+ printf("Mode: Hardware encapsulation, Device unique\n");
+ break;
+ case HWENCAP_MODE_HW_SHARED:
+ printf("Mode: Hardware encapsulation, Device shared\n");
+ break;
+ case HWENCAP_MODE_SOFT:
+ printf("Mode: Software encapsulation\n");
+ break;
+ default:
+ printf("Mode: Unknown (%d)\n", mode);
+ break;
+ }
+}
+
+static void
+perform_operation(const char *device, const char *in_path, const char *out_path,
+ enum blob_operation op)
+{
+ int dev_fd;
+
+ dev_fd = open(device, O_RDONLY);
+ if (dev_fd < 0)
+ errx(EX_IOERR, "Could not open device file %s", device);
+
+ switch (op) {
+ case op_encap:
+ case op_decap:
+ blob_operation(dev_fd, in_path, out_path, op);
+ break;
+ case op_getmode:
+ getmode_operation(dev_fd);
+ break;
+ default:
+ close(dev_fd);
+ errx(EX_USAGE, "Unsupported operation %d", op);
+ }
+
+ close(dev_fd);
+}
+
+static void
+usage(char *name)
+{
+ printf("Data encapsulation.\n\n");
+
+ printf("usage: %s [options] [input_file]\n", name);
+ printf("\tinput_file input file path, stdin if not specified\n");
+ printf("\t-f | --device path to a device implementing hwencap\n");
+ printf("\t-m | --getmode show encapsulation mode used by device\n");
+ printf("\t-e | --encapsulate encapsulate input data\n");
+ printf("\t-d | --decapsulate decapsulate input data\n");
+ printf("\t-o | --output output file path, stdout if not specified\n");
+ printf("\t-h | --help\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *dev_path = NULL, *infile = NULL, *outfile = NULL;
+ enum blob_operation op;
+ int eflag = 0, dflag = 0, mflag = 0;
+ int opt;
+
+ if (argc < 2) {
+ usage(argv[0]);
+ return (0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hdemf:o:", longopts, NULL)) != opt_end) {
+ switch (opt) {
+ case 'h':
+ case opt_help:
+ usage(argv[0]);
+ return (0);
+ case 'd':
+ case opt_decap:
+ dflag = 1;
+ break;
+ case 'e':
+ case opt_encap:
+ eflag = 1;
+ break;
+ case 'm':
+ case opt_getmode:
+ mflag = 1;
+ break;
+ case 'f':
+ case opt_device:
+ dev_path = optarg;
+ break;
+ case 'o':
+ case opt_output:
+ outfile = optarg;
+ break;
+ default:
+ printf("Not implemented!\n");
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!eflag && !dflag && !mflag)
+ errx(EX_USAGE, "No supported mode option given");
+ if (eflag && dflag)
+ errx(EX_USAGE, "Cannot set both encapsulate and decapsulate");
+ if (mflag && (eflag || dflag))
+ errx(EX_USAGE, "Cannot set both getmode and en/decapsulate");
+ if (dev_path == NULL)
+ errx(EX_USAGE, "Device path needs to be specified");
+ if (argc > 1)
+ errx(EX_USAGE, "Only one input file supported\n");
+
+ /* Default to stdout */
+ if (outfile == NULL)
+ outfile = "-";
+ if (argc == 1)
+ infile = argv[0];
+ else
+ infile = "-";
+
+ if (eflag)
+ op = op_encap;
+ if (dflag)
+ op = op_decap;
+ if (mflag)
+ op = op_getmode;
+
+ perform_operation(dev_path, infile, outfile, op);
+
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 14, 10:17 PM (20 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27640100
Default Alt Text
D45593.id140221.diff (22 KB)
Attached To
Mode
D45593: caam: Add hwencap support in caam_crypto driver
Attached
Detach File
Event Timeline
Log In to Comment