]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
greybus: Add Component Authentication Protocol support
authorViresh Kumar <viresh.kumar@linaro.org>
Thu, 30 Jun 2016 15:54:00 +0000 (10:54 -0500)
committerAlex Elder <elder@linaro.org>
Wed, 6 Jul 2016 22:51:32 +0000 (17:51 -0500)
This patch adds Component Authentication Protocol support in greybus.
The purpose of the CAP protocol is to authenticate the Module hardware,
and it can only be used when it is present as part of the
firmware-management bundle, on a separate CPort.

Compile tested only.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Jun Li <li_jun@projectara.com>
Tested-by: Jun Li <li_jun@projectara.com>
Signed-off-by: Alex Elder <elder@linaro.org>
drivers/staging/greybus/Makefile
drivers/staging/greybus/authentication.c [new file with mode: 0644]
drivers/staging/greybus/firmware.h
drivers/staging/greybus/fw-core.c
drivers/staging/greybus/greybus_authentication.h [new file with mode: 0644]
drivers/staging/greybus/greybus_manifest.h
drivers/staging/greybus/greybus_protocols.h

index bd9967ca46c6b7e0b4203403725db2064c30a1b8..fa5aaf363c7b2a34dc7ce5fc292bd81a6fd4577c 100644 (file)
@@ -33,7 +33,7 @@ gb-audio-manager-y += audio_manager.o
 gb-audio-manager-y += audio_manager_module.o
 gb-bootrom-y := bootrom.o
 gb-camera-y := camera.o
-gb-firmware-y := fw-core.o fw-download.o fw-management.o
+gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o
 gb-spilib-y := spilib.o
 gb-sdio-y := sdio.o
 gb-uart-y := uart.o
diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c
new file mode 100644 (file)
index 0000000..e469780
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Greybus Component Authentication Protocol (CAP) Driver.
+ *
+ * Copyright 2016 Google Inc.
+ * Copyright 2016 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include "greybus.h"
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/uaccess.h>
+
+#include "greybus_authentication.h"
+#include "firmware.h"
+#include "greybus.h"
+
+#define CAP_TIMEOUT_MS         1000
+
+/*
+ * Number of minor devices this driver supports.
+ * There will be exactly one required per Interface.
+ */
+#define NUM_MINORS             U8_MAX
+
+struct gb_cap {
+       struct device           *parent;
+       struct gb_connection    *connection;
+       struct kref             kref;
+       struct list_head        node;
+       bool                    disabled; /* connection getting disabled */
+
+       struct mutex            mutex;
+       struct cdev             cdev;
+       struct device           *class_device;
+       dev_t                   dev_num;
+};
+
+static struct class *cap_class;
+static dev_t cap_dev_num;
+static DEFINE_IDA(cap_minors_map);
+static LIST_HEAD(cap_list);
+static DEFINE_MUTEX(list_mutex);
+
+static void cap_kref_release(struct kref *kref)
+{
+       struct gb_cap *cap = container_of(kref, struct gb_cap, kref);
+
+       kfree(cap);
+}
+
+/*
+ * All users of cap take a reference (from within list_mutex lock), before
+ * they get a pointer to play with. And the structure will be freed only after
+ * the last user has put the reference to it.
+ */
+static void put_cap(struct gb_cap *cap)
+{
+       kref_put(&cap->kref, cap_kref_release);
+}
+
+/* Caller must call put_cap() after using struct gb_cap */
+static struct gb_cap *get_cap(struct cdev *cdev)
+{
+       struct gb_cap *cap;
+
+       mutex_lock(&list_mutex);
+
+       list_for_each_entry(cap, &cap_list, node) {
+               if (&cap->cdev == cdev) {
+                       kref_get(&cap->kref);
+                       goto unlock;
+               }
+       }
+
+       cap = NULL;
+
+unlock:
+       mutex_unlock(&list_mutex);
+
+       return cap;
+}
+
+static int cap_get_endpoint_uid(struct gb_cap *cap, u8 *euid)
+{
+       struct gb_connection *connection = cap->connection;
+       struct gb_cap_get_endpoint_uid_response response;
+       int ret;
+
+       ret = gb_operation_sync(connection, GB_CAP_TYPE_GET_ENDPOINT_UID, NULL,
+                               0, &response, sizeof(response));
+       if (ret) {
+               dev_err(cap->parent, "failed to get endpoint uid (%d)\n", ret);
+               return ret;
+       }
+
+       memcpy(euid, response.uid, sizeof(response.uid));
+
+       return 0;
+}
+
+static int cap_get_ims_certificate(struct gb_cap *cap, u32 class, u32 id,
+                                  u8 *certificate, u32 *size, u8 *result)
+{
+       struct gb_connection *connection = cap->connection;
+       struct gb_cap_get_ims_certificate_request *request;
+       struct gb_cap_get_ims_certificate_response *response;
+       size_t max_size = gb_operation_get_payload_size_max(connection);
+       struct gb_operation *op;
+       int ret;
+
+       op = gb_operation_create_flags(connection,
+                                      GB_CAP_TYPE_GET_IMS_CERTIFICATE,
+                                      sizeof(*request), max_size,
+                                      GB_OPERATION_FLAG_SHORT_RESPONSE,
+                                      GFP_KERNEL);
+       if (!op)
+               return -ENOMEM;
+
+       request = op->request->payload;
+       request->certificate_class = cpu_to_le32(class);
+       request->certificate_id = cpu_to_le32(id);
+
+       ret = gb_operation_request_send_sync(op);
+       if (ret) {
+               dev_err(cap->parent, "failed to get certificate (%d)\n", ret);
+               goto done;
+       }
+
+       response = op->response->payload;
+       *result = response->result_code;
+       *size = op->response->payload_size - sizeof(*response);
+       memcpy(certificate, response->certificate, *size);
+
+done:
+       gb_operation_put(op);
+       return ret;
+}
+
+static int cap_authenticate(struct gb_cap *cap, u32 auth_type, u8 *uid,
+                           u8 *challenge, u8 *result, u8 *auth_response,
+                           u32 *signature_size, u8 *signature)
+{
+       struct gb_connection *connection = cap->connection;
+       struct gb_cap_authenticate_request *request;
+       struct gb_cap_authenticate_response *response;
+       size_t max_size = gb_operation_get_payload_size_max(connection);
+       struct gb_operation *op;
+       int ret;
+
+       op = gb_operation_create_flags(connection, GB_CAP_TYPE_AUTHENTICATE,
+                                      sizeof(*request), max_size,
+                                      GB_OPERATION_FLAG_SHORT_RESPONSE,
+                                      GFP_KERNEL);
+       if (!op)
+               return -ENOMEM;
+
+       request = op->request->payload;
+       request->auth_type = cpu_to_le32(auth_type);
+       memcpy(request->uid, uid, sizeof(request->uid));
+       memcpy(request->challenge, challenge, sizeof(request->challenge));
+
+       ret = gb_operation_request_send_sync(op);
+       if (ret) {
+               dev_err(cap->parent, "failed to authenticate (%d)\n", ret);
+               goto done;
+       }
+
+       response = op->response->payload;
+       *result = response->result_code;
+       *signature_size = op->response->payload_size - sizeof(*response);
+       memcpy(auth_response, response->response, sizeof(response->response));
+       memcpy(signature, response->signature, *signature_size);
+
+done:
+       gb_operation_put(op);
+       return ret;
+}
+
+/* Char device fops */
+
+static int cap_open(struct inode *inode, struct file *file)
+{
+       struct gb_cap *cap = get_cap(inode->i_cdev);
+
+       /* cap structure can't get freed until file descriptor is closed */
+       if (cap) {
+               file->private_data = cap;
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static int cap_release(struct inode *inode, struct file *file)
+{
+       struct gb_cap *cap = file->private_data;
+
+       put_cap(cap);
+       return 0;
+}
+
+static int cap_ioctl(struct gb_cap *cap, unsigned int cmd,
+                        void __user *buf)
+{
+       struct cap_ioc_get_endpoint_uid endpoint_uid;
+       struct cap_ioc_get_ims_certificate *ims_cert;
+       struct cap_ioc_authenticate *authenticate;
+       int ret;
+
+       switch (cmd) {
+       case CAP_IOC_GET_ENDPOINT_UID:
+               ret = cap_get_endpoint_uid(cap, endpoint_uid.uid);
+               if (ret)
+                       return ret;
+
+               if (copy_to_user(buf, &endpoint_uid, sizeof(endpoint_uid)))
+                       return -EFAULT;
+
+               return 0;
+       case CAP_IOC_GET_IMS_CERTIFICATE:
+               ims_cert = kzalloc(sizeof(*ims_cert), GFP_KERNEL);
+               if (!ims_cert)
+                       return -ENOMEM;
+
+               if (copy_from_user(ims_cert, buf, sizeof(*ims_cert))) {
+                       ret = -EFAULT;
+                       goto free_ims_cert;
+               }
+
+               ret = cap_get_ims_certificate(cap, ims_cert->certificate_class,
+                                             ims_cert->certificate_id,
+                                             ims_cert->certificate,
+                                             &ims_cert->cert_size,
+                                             &ims_cert->result_code);
+               if (ret)
+                       goto free_ims_cert;
+
+               if (copy_to_user(buf, ims_cert, sizeof(*ims_cert)))
+                       ret = -EFAULT;
+
+free_ims_cert:
+               kfree(ims_cert);
+               return ret;
+       case CAP_IOC_AUTHENTICATE:
+               authenticate = kzalloc(sizeof(*authenticate), GFP_KERNEL);
+               if (!authenticate)
+                       return -ENOMEM;
+
+               if (copy_from_user(authenticate, buf, sizeof(*authenticate))) {
+                       ret = -EFAULT;
+                       goto free_authenticate;
+               }
+
+               ret = cap_authenticate(cap, authenticate->auth_type,
+                                      authenticate->uid,
+                                      authenticate->challenge,
+                                      &authenticate->result_code,
+                                      authenticate->response,
+                                      &authenticate->signature_size,
+                                      authenticate->signature);
+               if (ret)
+                       goto free_authenticate;
+
+               if (copy_to_user(buf, authenticate, sizeof(*authenticate)))
+                       ret = -EFAULT;
+free_authenticate:
+               kfree(authenticate);
+               return ret;
+       default:
+               return -ENOTTY;
+       }
+}
+
+static long cap_ioctl_unlocked(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       struct gb_cap *cap = file->private_data;
+       int ret = -ENODEV;
+
+       /*
+        * Serialize ioctls.
+        *
+        * We don't want the user to do multiple authentication operations in
+        * parallel.
+        *
+        * This is also used to protect ->disabled, which is used to check if
+        * the connection is getting disconnected, so that we don't start any
+        * new operations.
+        */
+       mutex_lock(&cap->mutex);
+       if (!cap->disabled)
+               ret = cap_ioctl(cap, cmd, (void __user *)arg);
+       mutex_unlock(&cap->mutex);
+
+       return ret;
+}
+
+static const struct file_operations cap_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cap_open,
+       .release        = cap_release,
+       .unlocked_ioctl = cap_ioctl_unlocked,
+};
+
+int gb_cap_connection_init(struct gb_connection *connection)
+{
+       struct gb_cap *cap;
+       int ret, minor;
+
+       if (!connection)
+               return 0;
+
+       cap = kzalloc(sizeof(*cap), GFP_KERNEL);
+       if (!cap)
+               return -ENOMEM;
+
+       cap->parent = &connection->bundle->dev;
+       cap->connection = connection;
+       mutex_init(&cap->mutex);
+       gb_connection_set_data(connection, cap);
+       kref_init(&cap->kref);
+
+       mutex_lock(&list_mutex);
+       list_add(&cap->node, &cap_list);
+       mutex_unlock(&list_mutex);
+
+       ret = gb_connection_enable(connection);
+       if (ret)
+               goto err_list_del;
+
+       minor = ida_simple_get(&cap_minors_map, 0, NUM_MINORS, GFP_KERNEL);
+       if (minor < 0) {
+               ret = minor;
+               goto err_connection_disable;
+       }
+
+       /* Add a char device to allow userspace to interact with cap */
+       cap->dev_num = MKDEV(MAJOR(cap_dev_num), minor);
+       cdev_init(&cap->cdev, &cap_fops);
+
+       ret = cdev_add(&cap->cdev, cap->dev_num, 1);
+       if (ret)
+               goto err_remove_ida;
+
+       /* Add a soft link to the previously added char-dev within the bundle */
+       cap->class_device = device_create(cap_class, cap->parent, cap->dev_num,
+                                         NULL, "gb-authenticate-%d", minor);
+       if (IS_ERR(cap->class_device)) {
+               ret = PTR_ERR(cap->class_device);
+               goto err_del_cdev;
+       }
+
+       return 0;
+
+err_del_cdev:
+       cdev_del(&cap->cdev);
+err_remove_ida:
+       ida_simple_remove(&cap_minors_map, minor);
+err_connection_disable:
+       gb_connection_disable(connection);
+err_list_del:
+       mutex_lock(&list_mutex);
+       list_del(&cap->node);
+       mutex_unlock(&list_mutex);
+
+       put_cap(cap);
+
+       return ret;
+}
+
+void gb_cap_connection_exit(struct gb_connection *connection)
+{
+       struct gb_cap *cap;
+
+       if (!connection)
+               return;
+
+       cap = gb_connection_get_data(connection);
+
+       device_destroy(cap_class, cap->dev_num);
+       cdev_del(&cap->cdev);
+       ida_simple_remove(&cap_minors_map, MINOR(cap->dev_num));
+
+       /*
+        * Disallow any new ioctl operations on the char device and wait for
+        * existing ones to finish.
+        */
+       mutex_lock(&cap->mutex);
+       cap->disabled = true;
+       mutex_unlock(&cap->mutex);
+
+       /* All pending greybus operations should have finished by now */
+       gb_connection_disable(cap->connection);
+
+       /* Disallow new users to get access to the cap structure */
+       mutex_lock(&list_mutex);
+       list_del(&cap->node);
+       mutex_unlock(&list_mutex);
+
+       /*
+        * All current users of cap would have taken a reference to it by
+        * now, we can drop our reference and wait the last user will get
+        * cap freed.
+        */
+       put_cap(cap);
+}
+
+int cap_init(void)
+{
+       int ret;
+
+       cap_class = class_create(THIS_MODULE, "gb_authenticate");
+       if (IS_ERR(cap_class))
+               return PTR_ERR(cap_class);
+
+       ret = alloc_chrdev_region(&cap_dev_num, 0, NUM_MINORS,
+                                 "gb_authenticate");
+       if (ret)
+               goto err_remove_class;
+
+       return 0;
+
+err_remove_class:
+       class_destroy(cap_class);
+       return ret;
+}
+
+void cap_exit(void)
+{
+       unregister_chrdev_region(cap_dev_num, NUM_MINORS);
+       class_destroy(cap_class);
+       ida_destroy(&cap_minors_map);
+}
index a82d0203971b74fb94e1e02e6147d1ca7ecab7f8..fb955379cfe46e7b639fcdd8e14b0914f1cbd6a9 100644 (file)
@@ -25,4 +25,10 @@ int gb_fw_download_request_handler(struct gb_operation *op);
 int gb_fw_download_connection_init(struct gb_connection *connection);
 void gb_fw_download_connection_exit(struct gb_connection *connection);
 
+/* CAP Protocol specific functions */
+int cap_init(void);
+void cap_exit(void);
+int gb_cap_connection_init(struct gb_connection *connection);
+void gb_cap_connection_exit(struct gb_connection *connection);
+
 #endif /* __FIRMWARE_H */
index 33941efe13ea21b7965ace859a58648f50a1be95..963973242be0580be3cf88b6a05348be89c9d2d4 100644 (file)
@@ -17,6 +17,7 @@ struct gb_fw_core {
        struct gb_connection    *download_connection;
        struct gb_connection    *mgmt_connection;
        struct gb_connection    *spi_connection;
+       struct gb_connection    *cap_connection;
 };
 
 struct gb_connection *to_fw_mgmt_connection(struct device *dev)
@@ -134,6 +135,24 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
                                fw_core->spi_connection = connection;
                        }
 
+                       break;
+               case GREYBUS_PROTOCOL_AUTHENTICATION:
+                       /* Disallow multiple CAP CPorts */
+                       if (fw_core->cap_connection) {
+                               dev_err(&bundle->dev, "multiple Authentication CPorts found\n");
+                               ret = -EINVAL;
+                               goto err_destroy_connections;
+                       }
+
+                       connection = gb_connection_create(bundle, cport_id,
+                                                         NULL);
+                       if (IS_ERR(connection)) {
+                               dev_err(&bundle->dev, "failed to create Authentication connection (%ld)\n",
+                                       PTR_ERR(connection));
+                       } else {
+                               fw_core->cap_connection = connection;
+                       }
+
                        break;
                default:
                        dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n",
@@ -168,6 +187,15 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
                fw_core->spi_connection = NULL;
        }
 
+       ret = gb_cap_connection_init(fw_core->cap_connection);
+       if (ret) {
+               /* We may still be able to work with the Interface */
+               dev_err(&bundle->dev, "failed to initialize CAP connection, disable it (%d)\n",
+                       ret);
+               gb_connection_destroy(fw_core->cap_connection);
+               fw_core->cap_connection = NULL;
+       }
+
        ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection);
        if (ret) {
                /* We may still be able to work with the Interface */
@@ -181,10 +209,12 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
        return 0;
 
 err_exit_connections:
+       gb_cap_connection_exit(fw_core->cap_connection);
        gb_fw_spi_connection_exit(fw_core->spi_connection);
        gb_fw_download_connection_exit(fw_core->download_connection);
 err_destroy_connections:
        gb_connection_destroy(fw_core->mgmt_connection);
+       gb_connection_destroy(fw_core->cap_connection);
        gb_connection_destroy(fw_core->spi_connection);
        gb_connection_destroy(fw_core->download_connection);
        kfree(fw_core);
@@ -197,10 +227,12 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle)
        struct gb_fw_core *fw_core = greybus_get_drvdata(bundle);
 
        gb_fw_mgmt_connection_exit(fw_core->mgmt_connection);
+       gb_cap_connection_exit(fw_core->cap_connection);
        gb_fw_spi_connection_exit(fw_core->spi_connection);
        gb_fw_download_connection_exit(fw_core->download_connection);
 
        gb_connection_destroy(fw_core->mgmt_connection);
+       gb_connection_destroy(fw_core->cap_connection);
        gb_connection_destroy(fw_core->spi_connection);
        gb_connection_destroy(fw_core->download_connection);
 
@@ -229,19 +261,32 @@ static int fw_core_init(void)
                return ret;
        }
 
-       ret = greybus_register(&gb_fw_core_driver);
+       ret = cap_init();
        if (ret) {
-               fw_mgmt_exit();
-               return ret;
+               pr_err("Failed to initialize component authentication core (%d)\n",
+                      ret);
+               goto fw_mgmt_exit;
        }
 
+       ret = greybus_register(&gb_fw_core_driver);
+       if (ret)
+               goto cap_exit;
+
        return 0;
+
+cap_exit:
+       cap_exit();
+fw_mgmt_exit:
+       fw_mgmt_exit();
+
+       return ret;
 }
 module_init(fw_core_init);
 
 static void __exit fw_core_exit(void)
 {
        greybus_deregister(&gb_fw_core_driver);
+       cap_exit();
        fw_mgmt_exit();
 }
 module_exit(fw_core_exit);
diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h
new file mode 100644 (file)
index 0000000..4784ed9
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Greybus Component Authentication User Header
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Google Inc. All rights reserved.
+ * Copyright(c) 2016 Linaro Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Google Inc. All rights reserved.
+ * Copyright(c) 2016 Linaro Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Google Inc. or Linaro Ltd. nor the names of
+ *    its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GREYBUS_AUTHENTICATION_USER_H
+#define __GREYBUS_AUTHENTICATION_USER_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define CAP_CERTIFICATE_MAX_SIZE       1600
+#define CAP_SIGNATURE_MAX_SIZE         320
+
+/* Certificate class types */
+#define CAP_CERT_IMS_EAPC              0x00000001
+#define CAP_CERT_IMS_EASC              0x00000002
+#define CAP_CERT_IMS_EARC              0x00000003
+#define CAP_CERT_IMS_IAPC              0x00000004
+#define CAP_CERT_IMS_IASC              0x00000005
+#define CAP_CERT_IMS_IARC              0x00000006
+
+/* IMS Certificate response result codes */
+#define CAP_IMS_RESULT_CERT_FOUND      0x00
+#define CAP_IMS_RESULT_CERT_CLASS_INVAL        0x01
+#define CAP_IMS_RESULT_CERT_CORRUPT    0x02
+#define CAP_IMS_RESULT_CERT_NOT_FOUND  0x03
+
+/* Authentication types */
+#define CAP_AUTH_IMS_PRI               0x00000001
+#define CAP_AUTH_IMS_SEC               0x00000002
+#define CAP_AUTH_IMS_RSA               0x00000003
+
+/* Authenticate response result codes */
+#define CAP_AUTH_RESULT_CR_SUCCESS     0x00
+#define CAP_AUTH_RESULT_CR_BAD_TYPE    0x01
+#define CAP_AUTH_RESULT_CR_WRONG_EP    0x02
+#define CAP_AUTH_RESULT_CR_NO_KEY      0x03
+#define CAP_AUTH_RESULT_CR_SIG_FAIL    0x04
+
+
+/* IOCTL support */
+struct cap_ioc_get_endpoint_uid {
+       __u8                    uid[8];
+} __attribute__ ((__packed__));
+
+struct cap_ioc_get_ims_certificate {
+       __u32                   certificate_class;
+       __u32                   certificate_id;
+
+       __u8                    result_code;
+       __u32                   cert_size;
+       __u8                    certificate[CAP_CERTIFICATE_MAX_SIZE];
+} __attribute__ ((__packed__));
+
+struct cap_ioc_authenticate {
+       __u32                   auth_type;
+       __u8                    uid[8];
+       __u8                    challenge[32];
+
+       __u8                    result_code;
+       __u8                    response[64];
+       __u32                   signature_size;
+       __u8                    signature[CAP_SIGNATURE_MAX_SIZE];
+} __attribute__ ((__packed__));
+
+#define CAP_IOCTL_BASE                 'C'
+#define CAP_IOC_GET_ENDPOINT_UID       _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid)
+#define CAP_IOC_GET_IMS_CERTIFICATE    _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate)
+#define CAP_IOC_AUTHENTICATE           _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate)
+
+#endif /* __GREYBUS_AUTHENTICATION_USER_H */
index 2ae39ad923683fd9a8afbaba23f97eb9c3e14040..d135945cefe1cada6643e6d305d02ccbc524fa17 100644 (file)
@@ -47,6 +47,7 @@ enum greybus_protocol {
        GREYBUS_PROTOCOL_CAMERA_DATA    = 0x16,
        GREYBUS_PROTOCOL_FW_DOWNLOAD    = 0x17,
        GREYBUS_PROTOCOL_FW_MANAGEMENT  = 0x18,
+       GREYBUS_PROTOCOL_AUTHENTICATION = 0x19,
        GREYBUS_PROTOCOL_LOG            = 0x1a,
                /* ... */
        GREYBUS_PROTOCOL_RAW            = 0xfe,
index 327d01f3679adb91152b27a2ed26ed13b43eaf09..0043b912f7208f8150a7edcd9df4ba4c97652c52 100644 (file)
@@ -345,6 +345,43 @@ struct gb_fw_mgmt_backend_fw_updated_request {
 /* firmware management backend firmware updated response has no payload */
 
 
+/* Component Authentication Protocol (CAP) */
+
+/* Request Types */
+#define GB_CAP_TYPE_GET_ENDPOINT_UID   0x01
+#define GB_CAP_TYPE_GET_IMS_CERTIFICATE        0x02
+#define GB_CAP_TYPE_AUTHENTICATE       0x03
+
+/* CAP get endpoint uid request has no payload */
+struct gb_cap_get_endpoint_uid_response {
+       __u8                    uid[8];
+} __packed;
+
+/* CAP get endpoint ims certificate request/response */
+struct gb_cap_get_ims_certificate_request {
+       __le32                  certificate_class;
+       __le32                  certificate_id;
+} __packed;
+
+struct gb_cap_get_ims_certificate_response {
+       __u8                    result_code;
+       __u8                    certificate[0];
+} __packed;
+
+/* CAP authenticate request/response */
+struct gb_cap_authenticate_request {
+       __le32                  auth_type;
+       __u8                    uid[8];
+       __u8                    challenge[32];
+} __packed;
+
+struct gb_cap_authenticate_response {
+       __u8                    result_code;
+       __u8                    response[64];
+       __u8                    signature[0];
+} __packed;
+
+
 /* Bootrom Protocol */
 
 /* Version of the Greybus bootrom protocol we support */