include/crypto: Crypto abstraction header
Adds crypto API interface for interaction between applications and crypto drivers. Encryption/Decryption APIs are defined here. Jira: ZEP-328 Change-Id: I1a534ae2a69c7e1c416fa78a2822c37040b225f6 Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
This commit is contained in:
parent
867e61cbf3
commit
417c341011
2 changed files with 544 additions and 0 deletions
281
include/crypto/cipher.h
Normal file
281
include/crypto/cipher.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Crypto Cipher APIs
|
||||
*
|
||||
* This file contains the Crypto Abstraction layer APIs.
|
||||
*
|
||||
* [Experimental] Users should note that the APIs can change
|
||||
* as a part of ongoing development.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_CIPHER_H__
|
||||
#define __CRYPTO_CIPHER_H__
|
||||
|
||||
#include <device.h>
|
||||
#include <errno.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/__assert.h>
|
||||
#include "cipher_structs.h"
|
||||
|
||||
/* The API a crypto driver should implement */
|
||||
struct crypto_driver_api {
|
||||
int (*query_hw_caps)(struct device *dev);
|
||||
|
||||
/* Setup a crypto session */
|
||||
int (*begin_session)(struct device *dev, struct cipher_ctx *ctx,
|
||||
enum cipher_algo algo, enum cipher_mode mode,
|
||||
enum cipher_op op_type);
|
||||
|
||||
/* Tear down an established session */
|
||||
int (*free_session)(struct device *dev, struct cipher_ctx *ctx);
|
||||
|
||||
/* Register async crypto op completion callback with the driver*/
|
||||
int (*crypto_async_callback_set)(struct device *dev,
|
||||
crypto_completion_cb cb);
|
||||
};
|
||||
|
||||
/* Following are the calls an app could make to get cipher stuff done.
|
||||
* The first two relates to crypto "session" setup / tear down.
|
||||
* Further we have four mode specific (CTR, CCM, CBC ...) calls to perform the
|
||||
* actual crypto operation in the context of a session. Also we have an
|
||||
* API to provide the callback for async operations.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @brief Query the crypto hardware capabilities
|
||||
*
|
||||
* This API is used by the app to query the capabilities supported by the
|
||||
* crypto device. Based on this the app can specify a subset of the supported
|
||||
* options to be honored for a session during cipher_begin_session()
|
||||
*
|
||||
* @param[in] dev Pointer to the device structure for the driver instance.
|
||||
*
|
||||
* @return bitmask of supported options.
|
||||
*/
|
||||
static inline int cipher_query_hwcaps(struct device *dev)
|
||||
{
|
||||
struct crypto_driver_api *api;
|
||||
int tmp;
|
||||
|
||||
api = (struct crypto_driver_api *) dev->driver_api;
|
||||
|
||||
tmp = api->query_hw_caps(dev);
|
||||
|
||||
__ASSERT((tmp & (CAP_OPAQUE_KEY_HNDL | CAP_RAW_KEY)) != 0,
|
||||
"Driver should support atleast one key type: RAW/Opaque");
|
||||
|
||||
__ASSERT((tmp & (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS)) != 0,
|
||||
"Driver should support atleast one IO buf type: Inplace/separate");
|
||||
|
||||
__ASSERT((tmp & (CAP_SYNC_OPS | CAP_ASYNC_OPS)) != 0,
|
||||
"Driver should support atleast one op-type: sync/async");
|
||||
return tmp;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Setup a crypto session
|
||||
*
|
||||
* Initializes one time parameters, like the session key, algorithm and cipher
|
||||
* mode which may remain constant for all operations in the session. The state
|
||||
* may be cached in hardware and/or driver data state variables.
|
||||
*
|
||||
* @param[in] dev Pointer to the device structure for the driver instance.
|
||||
* @param[in] ctx Pointer to the context structure. Various one time
|
||||
* parameters like key, keylength etc are supplied via
|
||||
* this field. Take a look at the ctx structure definition
|
||||
* to know which fields are to be populated by the app
|
||||
* before making this call.
|
||||
* @param[in] algo The crypto algorithm to be used in this session. e.g AES
|
||||
* @param[in] mode The cipher mode to be used in this session. e.g CBC, CTR
|
||||
* @param[in] optype Whether we should encrypt or decrypt in this session
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_begin_session(struct device *dev,
|
||||
struct cipher_ctx *ctx,
|
||||
enum cipher_algo algo,
|
||||
enum cipher_mode mode,
|
||||
enum cipher_op optype)
|
||||
{
|
||||
struct crypto_driver_api *api;
|
||||
uint32_t flags;
|
||||
|
||||
api = (struct crypto_driver_api *) dev->driver_api;
|
||||
ctx->device = dev;
|
||||
ctx->ops.cipher_mode = mode;
|
||||
|
||||
flags = (ctx->flags & (CAP_OPAQUE_KEY_HNDL | CAP_RAW_KEY));
|
||||
__ASSERT(flags != 0, "Keytype missing: RAW Key or OPAQUE handle");
|
||||
__ASSERT(flags != (CAP_OPAQUE_KEY_HNDL | CAP_RAW_KEY),
|
||||
"conflicting options for keytype");
|
||||
|
||||
flags = (ctx->flags & (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS));
|
||||
__ASSERT(flags != 0, "IO buffer type missing");
|
||||
__ASSERT(flags != (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS),
|
||||
"conflicting options for IO buffer type");
|
||||
|
||||
flags = (ctx->flags & (CAP_SYNC_OPS | CAP_ASYNC_OPS));
|
||||
__ASSERT(flags != 0, "sync/async type missing");
|
||||
__ASSERT(flags != (CAP_SYNC_OPS | CAP_ASYNC_OPS),
|
||||
"conflicting options for sync/async");
|
||||
|
||||
return api->begin_session(dev, ctx, algo, mode, optype);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Cleanup a crypto session
|
||||
*
|
||||
* Clears the hardware and/or driver state of a previous session.
|
||||
*
|
||||
* @param[in] dev Pointer to the device structure for the driver instance.
|
||||
* @param[in] ctx Pointer to the crypto context structure, of the session
|
||||
* to be freed.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_free_session(struct device *dev,
|
||||
struct cipher_ctx *ctx)
|
||||
{
|
||||
struct crypto_driver_api *api;
|
||||
|
||||
api = (struct crypto_driver_api *) dev->driver_api;
|
||||
|
||||
return api->free_session(dev, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Registers an async crypto op completion callback with the driver
|
||||
*
|
||||
* The application can register an async crypto op completion callback handler
|
||||
* to be invoked by the driver, on completion of a prior request submitted via
|
||||
* crypto_do_op(). Based on crypto device hardware semantics, this is likely to
|
||||
* be invoked from an ISR context.
|
||||
*
|
||||
* @param[in] dev Pointer to the device structure for the driver instance.
|
||||
* @param[in] cb Pointer to application callback to be called by the driver.
|
||||
*
|
||||
* @return 0 on success, -ENOTSUP if the driver does not support async op,
|
||||
* negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_callback_set(struct device *dev,
|
||||
crypto_completion_cb cb)
|
||||
{
|
||||
struct crypto_driver_api *api;
|
||||
|
||||
api = (struct crypto_driver_api *) dev->driver_api;
|
||||
|
||||
if (api->crypto_async_callback_set) {
|
||||
return api->crypto_async_callback_set(dev, cb);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Perform Single block crypto op. This should not be overloaded to
|
||||
* operate on multiple blocks for security reasons.
|
||||
*
|
||||
* @param[in] ctx Pointer to the crypto context of this op.
|
||||
* @param[in/out] pkt Structure holding the Input/Output buffer pointers.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_block_op(struct cipher_ctx *ctx,
|
||||
struct cipher_pkt *pkt)
|
||||
{
|
||||
__ASSERT(ctx->ops.cipher_mode == CRYPTO_CIPHER_MODE_ECB, "ECB mode "
|
||||
"session invoking a different mode handler");
|
||||
|
||||
pkt->ctx = ctx;
|
||||
return ctx->ops.block_crypt_hndlr(ctx, pkt);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Perform Cipher Block Chaining (CBC) crypto operation.
|
||||
*
|
||||
* @param[in] ctx Pointer to the crypto context of this op.
|
||||
* @param[in/out] pkt Structure holding the Input/Output buffer pointers.
|
||||
* @param[in] iv Initialization Vector for the operation. Same
|
||||
* iv value should not be reused across multiple
|
||||
* operations (within a session context) for security.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_cbc_op(struct cipher_ctx *ctx,
|
||||
struct cipher_pkt *pkt, uint8_t *iv)
|
||||
{
|
||||
__ASSERT(ctx->ops.cipher_mode == CRYPTO_CIPHER_MODE_CBC, "CBC mode "
|
||||
"session invoking a different mode handler");
|
||||
|
||||
pkt->ctx = ctx;
|
||||
return ctx->ops.cbc_crypt_hndlr(ctx, pkt, iv);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Perform Counter (CTR) mode crypto operation.
|
||||
*
|
||||
* @param[in] ctx Pointer to the crypto context of this op.
|
||||
* @param[in/out] pkt Structure holding the Input/Output buffer pointers.
|
||||
* @param[in] iv Initialization Vector for the operation. We use a
|
||||
* split counter formed by appending iv and ctr.
|
||||
* Consequently ivlen = keylen - ctrlen. 'ctrlen' is
|
||||
* specified during session setup through the
|
||||
* 'ctx.mode_params.ctr_params.ctr_len' parameter. IV
|
||||
* should not be reused across multiple operations
|
||||
* (within a session context) for security. The non-iv
|
||||
* part of the split counter is transparent to the caller
|
||||
* and is fully managed by the crypto provider.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_ctr_op(struct cipher_ctx *ctx,
|
||||
struct cipher_pkt *pkt, uint8_t *iv)
|
||||
{
|
||||
__ASSERT(ctx->ops.cipher_mode == CRYPTO_CIPHER_MODE_CTR, "CTR mode "
|
||||
"session invoking a different mode handler");
|
||||
|
||||
pkt->ctx = ctx;
|
||||
return ctx->ops.ctr_crypt_hndlr(ctx, pkt, iv);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Perform Counter with CBC-MAC (CCM) mode crypto operation
|
||||
*
|
||||
* @param[in] ctx Pointer to the crypto context of this op.
|
||||
* @param[in/out] pkt Structure holding the Input/Output, Assosciated Data
|
||||
* and tag buffer pointers.
|
||||
* @param[in] nonce Nonce for the operation. Same Nonce value should not
|
||||
* be reused across multiple operations (within a
|
||||
* session context) for security.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail.
|
||||
*/
|
||||
static inline int cipher_ccm_op(struct cipher_ctx *ctx,
|
||||
struct cipher_aead_pkt *pkt, uint8_t *nonce)
|
||||
{
|
||||
__ASSERT(ctx->ops.cipher_mode == CRYPTO_CIPHER_MODE_CCM, "CCM mode "
|
||||
"session invoking a different mode handler");
|
||||
|
||||
pkt->pkt->ctx = ctx;
|
||||
return ctx->ops.ccm_crypt_hndlr(ctx, pkt, nonce);
|
||||
}
|
||||
|
||||
#endif /* __CRYPTO_CIPHER_H__ */
|
263
include/crypto/cipher_structs.h
Normal file
263
include/crypto/cipher_structs.h
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Crypto Cipher structure definitions
|
||||
*
|
||||
* This file contains the Crypto Abstraction layer structures.
|
||||
*
|
||||
* [Experimental] Users should note that the Structures can change
|
||||
* as a part of ongoing development.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_CIPHER_STRUCTS_H__
|
||||
#define __CRYPTO_CIPHER_STRUCTS_H__
|
||||
|
||||
#include <device.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
enum cipher_algo {
|
||||
CRYPTO_CIPHER_ALGO_AES = 1,
|
||||
};
|
||||
|
||||
enum cipher_op {
|
||||
CRYPTO_CIPHER_OP_DECRYPT = 0,
|
||||
CRYPTO_CIPHER_OP_ENCRYPT = 1,
|
||||
};
|
||||
|
||||
/* Possible cipher mode options. More to be
|
||||
* added as required.
|
||||
*/
|
||||
|
||||
enum cipher_mode {
|
||||
CRYPTO_CIPHER_MODE_ECB = 1,
|
||||
CRYPTO_CIPHER_MODE_CBC = 2,
|
||||
CRYPTO_CIPHER_MODE_CTR = 3,
|
||||
CRYPTO_CIPHER_MODE_CCM = 4,
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
struct cipher_aead_pkt;
|
||||
struct cipher_ctx;
|
||||
struct cipher_pkt;
|
||||
|
||||
typedef int (*block_op_t)(struct cipher_ctx *ctx, struct cipher_pkt *pkt);
|
||||
|
||||
/* Function signatures for encryption/ decryption using standard cipher modes
|
||||
* like CBC, CTR, CCM.
|
||||
*/
|
||||
typedef int (*cbc_op_t)(struct cipher_ctx *ctx, struct cipher_pkt *pkt,
|
||||
uint8_t *iv);
|
||||
|
||||
typedef int (*ctr_op_t)(struct cipher_ctx *ctx, struct cipher_pkt *pkt,
|
||||
uint8_t *ctr);
|
||||
|
||||
typedef int (*ccm_op_t)(struct cipher_ctx *ctx, struct cipher_aead_pkt *pkt,
|
||||
uint8_t *nonce);
|
||||
|
||||
struct cipher_ops {
|
||||
|
||||
enum cipher_mode cipher_mode;
|
||||
|
||||
union {
|
||||
block_op_t block_crypt_hndlr;
|
||||
cbc_op_t cbc_crypt_hndlr;
|
||||
ctr_op_t ctr_crypt_hndlr;
|
||||
ccm_op_t ccm_crypt_hndlr;
|
||||
};
|
||||
};
|
||||
|
||||
struct ccm_params {
|
||||
uint16_t tag_len;
|
||||
uint16_t nonce_len;
|
||||
};
|
||||
|
||||
struct ctr_params {
|
||||
/* CTR mode counter is a split counter composed of iv and counter
|
||||
* such that ivlen + ctr_len = keylen
|
||||
*/
|
||||
uint32_t ctr_len;
|
||||
};
|
||||
|
||||
/* Structure encoding session parameters. Refer to comments for individual
|
||||
* fields to know the contract in terms of who fills what and when w.r.t
|
||||
* begin_session() call.
|
||||
*/
|
||||
struct cipher_ctx {
|
||||
|
||||
/* Place for driver to return function pointers to be invoked per
|
||||
* cipher operation. To be populated by crypto driver on return from
|
||||
* begin_session() based on the algo/mode chosen by the app.
|
||||
*/
|
||||
struct cipher_ops ops;
|
||||
|
||||
/* To be populated by the app before calling begin_session() */
|
||||
union {
|
||||
/* Cryptographic key to be used in this session */
|
||||
uint8_t *bit_stream;
|
||||
/* For cases where key is protected and is not
|
||||
* available to caller
|
||||
*/
|
||||
void *handle;
|
||||
} key;
|
||||
|
||||
/* The device driver instance this crypto context relates to. Will be
|
||||
* populated by the begin_session() API.
|
||||
*/
|
||||
struct device *device;
|
||||
|
||||
/* If the driver supports multiple simultaneously crypto sessions, this
|
||||
* will identify the specific driver state this crypto session relates
|
||||
* to. Since dynamic memory allocation is is not possible, it is
|
||||
* suggested that at build time drivers allocate space for the
|
||||
* max simultaneous sessions they intend to support. To be populated
|
||||
* by the driver on return from begin_session()
|
||||
*/
|
||||
void *drv_sessn_state;
|
||||
|
||||
/* Place for the app to put info relevant stuff for resuming when
|
||||
* completion call back happens for async ops. Totally managed by the
|
||||
* app.
|
||||
*/
|
||||
void *app_sessn_state;
|
||||
|
||||
|
||||
/* Standard mode parameters, which remain constant for all ops
|
||||
* in a session. To be populated by the app before calling
|
||||
* begin_session()
|
||||
*/
|
||||
union {
|
||||
struct ccm_params ccm_info;
|
||||
struct ctr_params ctr_info;
|
||||
|
||||
} mode_params;
|
||||
|
||||
|
||||
/* Cryptographic keylength in bytes. To be populated by the app
|
||||
* before calling begin_session()
|
||||
*/
|
||||
uint16_t keylen;
|
||||
|
||||
|
||||
/* How certain fields are to be interpreted for this sesssion.
|
||||
* To be populated by the app before calling begin_session().
|
||||
* An app can obtain the capability flags supported by a hw/driver
|
||||
* by calling cipher_query_hwcaps(). (A bitmask of CAP_* below)
|
||||
*/
|
||||
uint16_t flags;
|
||||
};
|
||||
|
||||
/* Various cipher_ctx.flags options. Not all drivers support all flags.
|
||||
* An app can query the supported hw / driver
|
||||
* capabilities via provided API (cipher_query_hwcaps()), and choose a
|
||||
* supported config during the session setup.
|
||||
*/
|
||||
#define CAP_OPAQUE_KEY_HNDL BIT(0)
|
||||
#define CAP_RAW_KEY BIT(1)
|
||||
|
||||
/* TBD to define */
|
||||
#define CAP_KEY_LOADING_API BIT(2)
|
||||
|
||||
/* Whether the output is placed in separate buffer or not */
|
||||
#define CAP_INPLACE_OPS BIT(3)
|
||||
#define CAP_SEPARATE_IO_BUFS BIT(4)
|
||||
|
||||
/* These denotes if the output (completion of a cipher_xxx_op) is conveyed
|
||||
* by the op function returning, or it is conveyed by an async notification
|
||||
*/
|
||||
#define CAP_SYNC_OPS BIT(5)
|
||||
#define CAP_ASYNC_OPS BIT(6)
|
||||
|
||||
/* Whether the hardware/driver supports autononce feature */
|
||||
#define CAP_AUTONONCE BIT(7)
|
||||
|
||||
|
||||
/* More flags to be added as necessary */
|
||||
|
||||
/* Structure encoding IO parameters of one cryptographic
|
||||
* operation like encrypt/decrypt. The fields which has not been explicitly
|
||||
* called out has to be filled up by the app before making the cipher_xxx_op()
|
||||
* call
|
||||
*/
|
||||
struct cipher_pkt {
|
||||
|
||||
/* Start address of Input buffer */
|
||||
uint8_t *in_buf;
|
||||
|
||||
/* Bytes to be operated upon */
|
||||
int in_len;
|
||||
|
||||
/* Start of the Output buffer, to be allocated by
|
||||
* the application. Can be NULL for in place ops. To be populated
|
||||
* with contents by the driver on return from op / async_callback
|
||||
*/
|
||||
uint8_t *out_buf;
|
||||
|
||||
/* Size of the out_buf area allocated by the application. Drivers should
|
||||
* not write past the size of output buffer
|
||||
*/
|
||||
int out_buf_max;
|
||||
|
||||
/* To be populated by driver on return from cipher_xxx_op() and
|
||||
* holds the size of the actual result
|
||||
*/
|
||||
int out_len;
|
||||
|
||||
/* This this field contains additional crypto specific error code,
|
||||
* in the event of a failure. The cipher_xxx_op()/ async_callback
|
||||
* returns a first level success / failure status. To be populated
|
||||
* by the driver on return from op / async_callback.
|
||||
*/
|
||||
uint8_t status;
|
||||
|
||||
/* Context this packet relates to. This can be useful to get the
|
||||
* session details esp for async ops. Will be populated by the
|
||||
* cipher_xxx_op() API based on the ctx parameter
|
||||
*/
|
||||
struct cipher_ctx *ctx;
|
||||
};
|
||||
|
||||
/* Structure encoding IO parameters in AEAD (Authenticated Encryption
|
||||
* with Associated Data) scenario like in CCM. App has to furnish valid
|
||||
* contents prior to making cipher_ccm_op() call.
|
||||
*/
|
||||
struct cipher_aead_pkt {
|
||||
/* IO buffers for Encryption. This has to be supplied by the app */
|
||||
struct cipher_pkt *pkt;
|
||||
|
||||
/* Start address for Associated data. This has to be supplied by app */
|
||||
uint8_t *ad;
|
||||
|
||||
/* Size of Associated data. This has to be supplied by the app */
|
||||
uint32_t ad_len;
|
||||
|
||||
/* Start address for the Auth hash. For an Encryption op this will
|
||||
* be populated by the driver when it returns from cipher_ccm_op call.
|
||||
* For a decryption op this has to be supplied by the app.
|
||||
*/
|
||||
uint8_t *tag;
|
||||
};
|
||||
|
||||
/* Prototype for the application function to be invoked by the crypto driver
|
||||
* on completion of an async request. The app may get the session context
|
||||
* via the pkt->ctx field. For ccm ops the encopassing AEAD packet maybe
|
||||
* accessed via container_of(). The type of a packet can be determined via
|
||||
* pkt->ctx.ops.mode
|
||||
*/
|
||||
typedef void (*crypto_completion_cb)(struct cipher_pkt *completed, int status);
|
||||
|
||||
#endif /* __CRYPTO_CIPHER_STRUCTS_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue