Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | /* * Copyright (c) 2016 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @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 ZEPHYR_INCLUDE_CRYPTO_CIPHER_H_ #define ZEPHYR_INCLUDE_CRYPTO_CIPHER_H_ #include <device.h> #include <errno.h> #include <sys/util.h> #include <sys/__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; u32_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 != 0U, "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 != 0U, "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 != 0U, "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, u8_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, u8_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, u8_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 /* ZEPHYR_INCLUDE_CRYPTO_CIPHER_H_ */ |