Page MenuHomeFreeBSD

D45593.id140221.diff
No OneTemporary

D45593.id140221.diff

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

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)

Event Timeline