1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef _FSL_DCP_H_
10 #define _FSL_DCP_H_
11 
12 #include "fsl_common.h"
13 
14 /*******************************************************************************
15  * Definitions
16  *******************************************************************************/
17 
18 /*!
19  * @addtogroup dcp_driver
20  * @{
21  */
22 /*! @name Driver version */
23 /*@{*/
24 /*! @brief DCP driver version. Version 2.1.7.
25  *
26  * Current version: 2.1.7
27  *
28  * Change log:
29  *
30  * - Version 2.1.7
31  *  - Bug Fix
32  *   - Reduce optimization level for critical functions working with SRF.
33  *
34  * - Version 2.1.6
35  *  - Bug Fix
36  *   - MISRA C-2012 issue fix.
37  *
38  * - Version 2.1.5
39  *  - Improvements
40  *   - Add support for DCACHE.
41  *
42  * - Version 2.1.4
43  *  - Bug Fix
44  *   - Fix CRC-32 computation issue on the code's block boundary size.
45  *
46  * - Version 2.1.3
47  *  - Bug Fix
48  *   - MISRA C-2012 issue fixed: rule 10.1, 10.3, 10.4, 11.9, 14.4, 16.4 and 17.7.
49  *
50  * - Version 2.1.2
51  *   - Fix sign-compare warning in dcp_reverse_and_copy.
52  *
53  * - Version 2.1.1
54  *   - Add DCP status clearing when channel operation is complete
55  *
56  * - 2.1.0
57  *   - Add byte/word swap feature for key, input and output data
58  *
59  * - Version 2.0.0
60  *   - Initial version
61  */
62 #define FSL_DCP_DRIVER_VERSION (MAKE_VERSION(2, 1, 7))
63 /*@}*/
64 
65 /*! @brief DCP status return codes. */
66 enum _dcp_status
67 {
68     kStatus_DCP_Again = MAKE_STATUS(kStatusGroup_DCP, 0), /*!< Non-blocking function shall be called again. */
69 };
70 
71 /*! @brief DCP channel enable.
72  *
73  */
74 typedef enum _dcp_ch_enable
75 {
76     kDCP_chDisable   = 0U,  /*!< DCP channel disable */
77     kDCP_ch0Enable   = 1U,  /*!< DCP channel 0 enable */
78     kDCP_ch1Enable   = 2U,  /*!< DCP channel 1 enable */
79     kDCP_ch2Enable   = 4U,  /*!< DCP channel 2 enable */
80     kDCP_ch3Enable   = 8U,  /*!< DCP channel 3 enable */
81     kDCP_chEnableAll = 15U, /*!< DCP channel enable all */
82 } _dcp_ch_enable_t;
83 
84 /*! @brief DCP interrupt enable.
85  *
86  */
87 typedef enum _dcp_ch_int_enable
88 {
89     kDCP_chIntDisable = 0U, /*!< DCP interrupts disable */
90     kDCP_ch0IntEnable = 1U, /*!< DCP channel 0 interrupt enable */
91     kDCP_ch1IntEnable = 2U, /*!< DCP channel 1 interrupt enable */
92     kDCP_ch2IntEnable = 4U, /*!< DCP channel 2 interrupt enable */
93     kDCP_ch3IntEnable = 8U, /*!< DCP channel 3 interrupt enable */
94 } _dcp_ch_int_enable_t;
95 
96 /*! @brief DCP channel selection.
97  *
98  */
99 typedef enum _dcp_channel
100 {
101     kDCP_Channel0 = (1u << 16), /*!< DCP channel 0. */
102     kDCP_Channel1 = (1u << 17), /*!< DCP channel 1. */
103     kDCP_Channel2 = (1u << 18), /*!< DCP channel 2. */
104     kDCP_Channel3 = (1u << 19), /*!< DCP channel 3. */
105 } dcp_channel_t;
106 
107 /*! @brief DCP key slot selection.
108  *
109  */
110 typedef enum _dcp_key_slot
111 {
112     kDCP_KeySlot0     = 0U, /*!< DCP key slot 0. */
113     kDCP_KeySlot1     = 1U, /*!< DCP key slot 1. */
114     kDCP_KeySlot2     = 2U, /*!< DCP key slot 2.*/
115     kDCP_KeySlot3     = 3U, /*!< DCP key slot 3. */
116     kDCP_OtpKey       = 4U, /*!< DCP OTP key. */
117     kDCP_OtpUniqueKey = 5U, /*!< DCP unique OTP key. */
118     kDCP_PayloadKey   = 6U, /*!< DCP payload key. */
119 } dcp_key_slot_t;
120 
121 /*! @brief DCP key, input & output swap options
122  *
123  */
124 typedef enum _dcp_swap
125 {
126     kDCP_NoSwap         = 0x0U,
127     kDCP_KeyByteSwap    = 0x40000U,
128     kDCP_KeyWordSwap    = 0x80000U,
129     kDCP_InputByteSwap  = 0x100000U,
130     kDCP_InputWordSwap  = 0x200000U,
131     kDCP_OutputByteSwap = 0x400000U,
132     kDCP_OutputWordSwap = 0x800000U,
133 } dcp_swap_t;
134 
135 /*! @brief DCP's work packet. */
136 typedef struct _dcp_work_packet
137 {
138     uint32_t nextCmdAddress;
139     uint32_t control0;
140     uint32_t control1;
141     uint32_t sourceBufferAddress;
142     uint32_t destinationBufferAddress;
143     uint32_t bufferSize;
144     uint32_t payloadPointer;
145     uint32_t status;
146 } dcp_work_packet_t;
147 
148 /*! @brief Specify DCP's key resource and DCP channel. */
149 typedef struct _dcp_handle
150 {
151     dcp_channel_t channel;  /*!< Specify DCP channel. */
152     dcp_key_slot_t keySlot; /*!< For operations with key (such as AES encryption/decryption), specify DCP key slot. */
153     uint32_t swapConfig;    /*!< For configuration of key, input, output byte/word swap options */
154     uint32_t keyWord[4];
155     uint32_t iv[4];
156 } dcp_handle_t;
157 
158 /*! @brief DCP's context buffer, used by DCP for context switching between channels. */
159 typedef struct _dcp_context
160 {
161     uint32_t x[208 / sizeof(uint32_t)];
162 } dcp_context_t;
163 
164 /*! @brief DCP's configuration structure. */
165 typedef struct _dcp_config
166 {
167     bool gatherResidualWrites;      /*!< Enable the ragged writes to the unaligned buffers. */
168     bool enableContextCaching;      /*!< Enable the caching of contexts between the operations. */
169     bool enableContextSwitching;    /*!< Enable automatic context switching for the channels. */
170     uint8_t enableChannel;          /*!< DCP channel enable. */
171     uint8_t enableChannelInterrupt; /*!< Per-channel interrupt enable. */
172 } dcp_config_t;
173 
174 /*! @} */
175 
176 #ifndef DCP_USE_DCACHE
177 #define DCP_USE_DCACHE 1
178 #endif
179 /* 1 - driver supports DCACHE, 0 - drivers does not support DCACHE */
180 /* When enable (DCP_USE_DCACHE = 1) Input/output buffers and hash ctx should be in */
181 /* non-cached memory or handled properly (Clean & Invalidate DCACHE) */
182 
183 /*******************************************************************************
184  * AES Definitions
185  *******************************************************************************/
186 
187 /*!
188  * @addtogroup dcp_driver_aes
189  * @{
190  */
191 
192 /*! AES block size in bytes */
193 #define DCP_AES_BLOCK_SIZE 16
194 
195 /*!
196  *@}
197  */ /* end of dcp_driver_aes */
198 
199 /*******************************************************************************
200  * HASH Definitions
201  ******************************************************************************/
202 /*!
203  * @addtogroup dcp_driver_hash
204  * @{
205  */
206 
207 /* DCP cannot correctly compute hash for message with zero size. When enabled, driver bypases DCP and returns correct
208  * hash value. If you are sure, that the driver will never be called with zero sized message, you can disable this
209  * feature to reduce code size */
210 #define DCP_HASH_CAVP_COMPATIBLE
211 
212 /*! @brief Supported cryptographic block cipher functions for HASH creation */
213 typedef enum _dcp_hash_algo_t
214 {
215     kDCP_Sha1,   /*!< SHA_1 */
216     kDCP_Sha256, /*!< SHA_256 */
217     kDCP_Crc32,  /*!< CRC_32 */
218 } dcp_hash_algo_t;
219 
220 /*! @brief DCP HASH Context size. */
221 #define DCP_SHA_BLOCK_SIZE  128U               /*!< internal buffer block size  */
222 #define DCP_HASH_BLOCK_SIZE DCP_SHA_BLOCK_SIZE /*!< DCP hash block size  */
223 
224 /*! @brief DCP HASH Context size. */
225 #define DCP_HASH_CTX_SIZE 64
226 
227 /*! @brief Storage type used to save hash context. */
228 typedef struct _dcp_hash_ctx_t
229 {
230     uint32_t x[DCP_HASH_CTX_SIZE];
231 } dcp_hash_ctx_t;
232 
233 /*!
234  *@}
235  */ /* end of dcp_driver_hash */
236 
237 /*******************************************************************************
238  * API
239  ******************************************************************************/
240 #if defined(__cplusplus)
241 extern "C" {
242 #endif
243 
244 /*!
245  * @addtogroup dcp_driver
246  * @{
247  */
248 
249 /*!
250  * @brief   Enables clock to and enables DCP
251  *
252  * Enable DCP clock and configure DCP.
253  *
254  * @param base DCP base address
255  * @param config Pointer to configuration structure.
256  */
257 void DCP_Init(DCP_Type *base, const dcp_config_t *config);
258 
259 /*!
260  * @brief   Disable DCP clock
261  *
262  * Reset DCP and Disable DCP clock.
263  *
264  * @param base DCP base address
265  */
266 void DCP_Deinit(DCP_Type *base);
267 
268 /*!
269  * @brief Gets the default configuration structure.
270  *
271  * This function initializes the DCP configuration structure to a default value. The default
272  * values are as follows.
273  *   dcpConfig->gatherResidualWrites = true;
274  *   dcpConfig->enableContextCaching = true;
275  *   dcpConfig->enableContextSwitching = true;
276  *   dcpConfig->enableChannnel = kDCP_chEnableAll;
277  *   dcpConfig->enableChannelInterrupt = kDCP_chIntDisable;
278  *
279  * @param[out] config Pointer to configuration structure.
280  */
281 void DCP_GetDefaultConfig(dcp_config_t *config);
282 
283 /*!
284  * @brief Poll and wait on DCP channel.
285  *
286  * Polls the specified DCP channel until current it completes activity.
287  *
288  * @param   base DCP peripheral base address.
289  * @param   handle Specifies DCP channel.
290  * @return  kStatus_Success When data processing completes without error.
291  * @return  kStatus_Fail When error occurs.
292  */
293 status_t DCP_WaitForChannelComplete(DCP_Type *base, dcp_handle_t *handle);
294 
295 /*!
296  *@}
297  */ /* end of dcp_driver */
298 
299 /*******************************************************************************
300  * AES API
301  ******************************************************************************/
302 
303 /*!
304  * @addtogroup dcp_driver_aes
305  * @{
306  */
307 
308 /*!
309  * @brief Set AES key to dcp_handle_t struct and optionally to DCP.
310  *
311  * Sets the AES key for encryption/decryption with the dcp_handle_t structure.
312  * The dcp_handle_t input argument specifies keySlot.
313  * If the keySlot is kDCP_OtpKey, the function will check the OTP_KEY_READY bit and will return it's ready to use
314  * status.
315  * For other keySlot selections, the function will copy and hold the key in dcp_handle_t struct.
316  * If the keySlot is one of the four DCP SRAM-based keys (one of kDCP_KeySlot0, kDCP_KeySlot1, kDCP_KeySlot2,
317  * kDCP_KeySlot3),
318  * this function will also load the supplied key to the specified keySlot in DCP.
319  *
320  * @param   base DCP peripheral base address.
321  * @param   handle Handle used for the request.
322  * @param   key 0-mod-4 aligned pointer to AES key.
323  * @param   keySize AES key size in bytes. Shall equal 16.
324  * @return  status from set key operation
325  */
326 status_t DCP_AES_SetKey(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key, size_t keySize);
327 
328 /*!
329  * @brief Encrypts AES on one or multiple 128-bit block(s).
330  *
331  * Encrypts AES.
332  * The source plaintext and destination ciphertext can overlap in system memory.
333  *
334  * @param base DCP peripheral base address
335  * @param handle Handle used for this request.
336  * @param plaintext Input plain text to encrypt
337  * @param[out] ciphertext Output cipher text
338  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
339  * @return Status from encrypt operation
340  */
341 status_t DCP_AES_EncryptEcb(
342     DCP_Type *base, dcp_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size);
343 
344 /*!
345  * @brief Decrypts AES on one or multiple 128-bit block(s).
346  *
347  * Decrypts AES.
348  * The source ciphertext and destination plaintext can overlap in system memory.
349  *
350  * @param base DCP peripheral base address
351  * @param handle Handle used for this request.
352  * @param ciphertext Input plain text to encrypt
353  * @param[out] plaintext Output cipher text
354  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
355  * @return Status from decrypt operation
356  */
357 status_t DCP_AES_DecryptEcb(
358     DCP_Type *base, dcp_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size);
359 
360 /*!
361  * @brief Encrypts AES using CBC block mode.
362  *
363  * Encrypts AES using CBC block mode.
364  * The source plaintext and destination ciphertext can overlap in system memory.
365  *
366  * @param base DCP peripheral base address
367  * @param handle Handle used for this request.
368  * @param plaintext Input plain text to encrypt
369  * @param[out] ciphertext Output cipher text
370  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
371  * @param iv Input initial vector to combine with the first input block.
372  * @return Status from encrypt operation
373  */
374 status_t DCP_AES_EncryptCbc(DCP_Type *base,
375                             dcp_handle_t *handle,
376                             const uint8_t *plaintext,
377                             uint8_t *ciphertext,
378                             size_t size,
379                             const uint8_t iv[16]);
380 
381 /*!
382  * @brief Decrypts AES using CBC block mode.
383  *
384  * Decrypts AES using CBC block mode.
385  * The source ciphertext and destination plaintext can overlap in system memory.
386  *
387  * @param base DCP peripheral base address
388  * @param handle Handle used for this request.
389  * @param ciphertext Input cipher text to decrypt
390  * @param[out] plaintext Output plain text
391  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
392  * @param iv Input initial vector to combine with the first input block.
393  * @return Status from decrypt operation
394  */
395 status_t DCP_AES_DecryptCbc(DCP_Type *base,
396                             dcp_handle_t *handle,
397                             const uint8_t *ciphertext,
398                             uint8_t *plaintext,
399                             size_t size,
400                             const uint8_t iv[16]);
401 
402 /*!
403  *@}
404  */ /* end of dcp_driver_aes */
405 
406 /*!
407  * @addtogroup dcp_nonblocking_driver_aes
408  * @{
409  */
410 /*!
411  * @brief Encrypts AES using the ECB block mode.
412  *
413  * Puts AES ECB encrypt work packet to DCP channel.
414  *
415  * @param base DCP peripheral base address
416  * @param handle Handle used for this request.
417  * @param[out] dcpPacket Memory for the DCP work packet.
418  * @param plaintext Input plain text to encrypt.
419  * @param[out] ciphertext Output cipher text
420  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
421  * @return kStatus_Success The work packet has been scheduled at DCP channel.
422  * @return kStatus_DCP_Again The DCP channel is busy processing previous request.
423  */
424 status_t DCP_AES_EncryptEcbNonBlocking(DCP_Type *base,
425                                        dcp_handle_t *handle,
426                                        dcp_work_packet_t *dcpPacket,
427                                        const uint8_t *plaintext,
428                                        uint8_t *ciphertext,
429                                        size_t size);
430 
431 /*!
432  * @brief Decrypts AES using ECB block mode.
433  *
434  * Puts AES ECB decrypt dcpPacket to DCP input job ring.
435  *
436  * @param base DCP peripheral base address
437  * @param handle Handle used for this request.
438  * @param[out] dcpPacket Memory for the DCP work packet.
439  * @param ciphertext Input cipher text to decrypt
440  * @param[out] plaintext Output plain text
441  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
442  * @return kStatus_Success The work packet has been scheduled at DCP channel.
443  * @return kStatus_DCP_Again The DCP channel is busy processing previous request.
444  */
445 status_t DCP_AES_DecryptEcbNonBlocking(DCP_Type *base,
446                                        dcp_handle_t *handle,
447                                        dcp_work_packet_t *dcpPacket,
448                                        const uint8_t *ciphertext,
449                                        uint8_t *plaintext,
450                                        size_t size);
451 
452 /*!
453  * @brief Encrypts AES using CBC block mode.
454  *
455  * Puts AES CBC encrypt dcpPacket to DCP input job ring.
456  *
457  * @param base DCP peripheral base address
458  * @param handle Handle used for this request. Specifies jobRing.
459  * @param[out] dcpPacket Memory for the DCP work packet.
460  * @param plaintext Input plain text to encrypt
461  * @param[out] ciphertext Output cipher text
462  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
463  * @param iv Input initial vector to combine with the first input block.
464  * @return kStatus_Success The work packet has been scheduled at DCP channel.
465  * @return kStatus_DCP_Again The DCP channel is busy processing previous request.
466  */
467 status_t DCP_AES_EncryptCbcNonBlocking(DCP_Type *base,
468                                        dcp_handle_t *handle,
469                                        dcp_work_packet_t *dcpPacket,
470                                        const uint8_t *plaintext,
471                                        uint8_t *ciphertext,
472                                        size_t size,
473                                        const uint8_t *iv);
474 
475 /*!
476  * @brief Decrypts AES using CBC block mode.
477  *
478  * Puts AES CBC decrypt dcpPacket to DCP input job ring.
479  *
480  * @param base DCP peripheral base address
481  * @param handle Handle used for this request. Specifies jobRing.
482  * @param[out] dcpPacket Memory for the DCP work packet.
483  * @param ciphertext Input cipher text to decrypt
484  * @param[out] plaintext Output plain text
485  * @param size Size of input and output data in bytes. Must be multiple of 16 bytes.
486  * @param iv Input initial vector to combine with the first input block.
487  * @return kStatus_Success The work packet has been scheduled at DCP channel.
488  * @return kStatus_DCP_Again The DCP channel is busy processing previous request.
489  */
490 status_t DCP_AES_DecryptCbcNonBlocking(DCP_Type *base,
491                                        dcp_handle_t *handle,
492                                        dcp_work_packet_t *dcpPacket,
493                                        const uint8_t *ciphertext,
494                                        uint8_t *plaintext,
495                                        size_t size,
496                                        const uint8_t *iv);
497 
498 /*!
499  *@}
500  */ /* end of dcp_nonblocking_driver_aes */
501 
502 /*******************************************************************************
503  * HASH API
504  ******************************************************************************/
505 
506 /*!
507  * @addtogroup dcp_driver_hash
508  * @{
509  */
510 /*!
511  * @brief Initialize HASH context
512  *
513  * This function initializes the HASH.
514  *
515  * @param base DCP peripheral base address
516  * @param handle Specifies the DCP channel used for hashing.
517  * @param[out] ctx Output hash context
518  * @param algo Underlaying algorithm to use for hash computation.
519  * @return Status of initialization
520  */
521 status_t DCP_HASH_Init(DCP_Type *base, dcp_handle_t *handle, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo);
522 
523 /*!
524  * @brief Add data to current HASH
525  *
526  * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be
527  * hashed. The functions blocks. If it returns kStatus_Success, the running hash
528  * has been updated (DCP has processed the input data), so the memory at the input pointer
529  * can be released back to system. The DCP context buffer is updated with the running hash
530  * and with all necessary information to support possible context switch.
531  *
532  * @param base DCP peripheral base address
533  * @param[in,out] ctx HASH context
534  * @param input Input data
535  * @param inputSize Size of input data in bytes
536  * @return Status of the hash update operation
537  */
538 status_t DCP_HASH_Update(DCP_Type *base, dcp_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize);
539 
540 /*!
541  * @brief Finalize hashing
542  *
543  * Outputs the final hash (computed by DCP_HASH_Update()) and erases the context.
544  *
545  * @param base DCP peripheral base address
546  * @param[in,out] ctx Input hash context
547  * @param[out] output Output hash data
548  * @param[in,out] outputSize Optional parameter (can be passed as NULL). On function entry, it specifies the size of
549  * output[] buffer. On function return, it stores the number of updated output bytes.
550  * @return Status of the hash finish operation
551  */
552 status_t DCP_HASH_Finish(DCP_Type *base, dcp_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize);
553 
554 /*!
555  * @brief Create HASH on given data
556  *
557  * Perform the full SHA or CRC32 in one function call. The function is blocking.
558  *
559  * @param base DCP peripheral base address
560  * @param handle Handle used for the request.
561  * @param algo Underlaying algorithm to use for hash computation.
562  * @param input Input data
563  * @param inputSize Size of input data in bytes
564  * @param[out] output Output hash data
565  * @param[out] outputSize Output parameter storing the size of the output hash in bytes
566  * @return Status of the one call hash operation.
567  */
568 status_t DCP_HASH(DCP_Type *base,
569                   dcp_handle_t *handle,
570                   dcp_hash_algo_t algo,
571                   const uint8_t *input,
572                   size_t inputSize,
573                   uint8_t *output,
574                   size_t *outputSize);
575 
576 /*!
577  *@}
578  */ /* end of dcp_driver_hash */
579 
580 #if defined(__cplusplus)
581 }
582 #endif
583 
584 #endif /* _FSL_DCP_H_ */
585