pic32mz_crypto_hash.c
Go to the documentation of this file.
1 /**
2  * @file pic32mz_crypto_hash.c
3  * @brief PIC32MZ hash hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include <p32xxxx.h>
36 #include <sys/kmem.h>
37 #include "core/crypto.h"
40 #include "hash/hash_algorithms.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (PIC32MZ_CRYPTO_HASH_SUPPORT == ENABLED)
45 
46 //Buffer descriptor
47 volatile Pic32mzCryptoBufferDesc hashBufferDesc
48  __attribute__((coherent, aligned(8)));
49 
50 //Security association
51 volatile Pic32mzCryptoSecurityAssoc hashSecurityAssoc
52  __attribute__((coherent, aligned(8)));
53 
54 //Input buffer
55 uint8_t hashInput[PIC32MZ_CRYPTO_BUFFER_SIZE]
56  __attribute__((coherent, aligned(4)));
57 
58 //Output buffer
59 uint8_t hashOutput[PIC32MZ_CRYPTO_BUFFER_SIZE]
60  __attribute__((coherent, aligned(4)));
61 
62 //MD5 value for an empty message
63 const uint8_t md5EmptyDigest[] =
64 {
65  0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
66  0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E
67 };
68 
69 //SHA-1 value for an empty message
70 const uint8_t sha1EmptyDigest[] =
71 {
72  0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D,
73  0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90,
74  0xAF, 0xD8, 0x07, 0x09
75 };
76 
77 //SHA-256 value for an empty message
78 const uint8_t sha256EmptyDigest[] =
79 {
80  0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14,
81  0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
82  0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C,
83  0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
84 };
85 
86 
87 /**
88  * @brief Digest a message using the specified hash algorithm
89  * @param[in] algo Hash algorithm
90  * @param[in] data Pointer to the input message
91  * @param[in] length Length of the input message, in bytes
92  **/
93 
94 void hashProcessData(uint32_t algo, const uint8_t *data, size_t length)
95 {
96  size_t i;
97  size_t n;
98 
99  //Acquire exclusive access to the crypto engine
101 
102  //Reset the crypto engine
103  CECON |= _CECON_SWRST_MASK;
104  //Wait for the reset to complete
105  while((CECON & _CECON_SWRST_MASK) != 0)
106  {
107  }
108 
109  //Clear descriptors
110  memset((void *) &hashBufferDesc, 0, sizeof(Pic32mzCryptoBufferDesc));
111  memset((void *) &hashSecurityAssoc, 0, sizeof(Pic32mzCryptoSecurityAssoc));
112 
113  //Set up buffer descriptor
114  hashBufferDesc.SA_ADDR = KVA_TO_PA(&hashSecurityAssoc);
115  hashBufferDesc.SRCADDR = KVA_TO_PA(hashInput);
116  hashBufferDesc.NXTPTR = KVA_TO_PA(&hashBufferDesc);
117  hashBufferDesc.UPDPTR = KVA_TO_PA(hashOutput);
118  hashBufferDesc.MSG_LEN = length;
119 
120  //Set up security association
121  hashSecurityAssoc.SA_CTRL = SA_CTRL_LNC | SA_CTRL_LOADIV | SA_CTRL_FB |
122  algo;
123 
124  //Set the number of cycles that the DMA would wait before refetching the
125  //descriptor control word if the previous descriptor fetched was disabled
126  CEPOLLCON = 10;
127 
128  //Set the address from which the DMA will start fetching buffer descriptors
129  CEBDPADDR = KVA_TO_PA(&hashBufferDesc);
130 
131  //Enable DMA engine
132  CECON = _CECON_SWAPOEN_MASK | _CECON_SWAPEN_MASK | _CECON_BDPCHST_MASK |
133  _CECON_BDPPLEN_MASK | _CECON_DMAEN_MASK;
134 
135  //Digest input message
136  for(i = 0; i < length; i += n)
137  {
138  //Limit the number of data to process at a time
139  n = MIN(length - i, sizeof(hashInput));
140  //Copy input data
141  osMemcpy(hashInput, data, n);
142 
143  //Set buffer length
144  hashBufferDesc.BD_CTRL = BD_CTRL_SA_FETCH_EN | ((n + 3) & ~3UL);
145 
146  //First buffer descriptor?
147  if(i == 0)
148  {
149  //Fetch security association from the SA pointer
150  hashBufferDesc.BD_CTRL |= BD_CTRL_SA_FETCH_EN;
151  }
152 
153  //Last buffer descriptor?
154  if((i + n) == length)
155  {
156  //This BD is the last in the frame
157  hashBufferDesc.BD_CTRL |= BD_CTRL_LIFM;
158  }
159 
160  //Give the ownership of the descriptor to the hardware
161  hashBufferDesc.BD_CTRL |= BD_CTRL_DESC_EN;
162 
163  //Wait for the processing to complete
164  while((hashBufferDesc.BD_CTRL & BD_CTRL_DESC_EN) != 0)
165  {
166  }
167 
168  //Advance data pointer
169  data += n;
170  }
171 
172  //Release exclusive access to the crypto engine
174 }
175 
176 
177 #if (MD5_SUPPORT == ENABLED)
178 
179 /**
180  * @brief Digest a message using MD5
181  * @param[in] data Pointer to the message being hashed
182  * @param[in] length Length of the message
183  * @param[out] digest Pointer to the calculated digest
184  * @return Error code
185  **/
186 
187 error_t md5Compute(const void *data, size_t length, uint8_t *digest)
188 {
189  //Empty message?
190  if(length == 0)
191  {
192  //Return the MD5 digest value for an empty message
194  }
195  else
196  {
197  //Digest the message using MD5
199  //Copy the resulting digest value
200  osMemcpy(digest, hashOutput, MD5_DIGEST_SIZE);
201  }
202 
203  //Successful processing
204  return NO_ERROR;
205 }
206 
207 #endif
208 #if (SHA1_SUPPORT == ENABLED)
209 
210 /**
211  * @brief Digest a message using SHA-1
212  * @param[in] data Pointer to the message being hashed
213  * @param[in] length Length of the message
214  * @param[out] digest Pointer to the calculated digest
215  * @return Error code
216  **/
217 
218 error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
219 {
220  //Empty message?
221  if(length == 0)
222  {
223  //Return the SHA-1 digest value for an empty message
225  }
226  else
227  {
228  //Digest the message using SHA-1
230  //Copy the resulting digest value
231  osMemcpy(digest, hashOutput, SHA1_DIGEST_SIZE);
232  }
233 
234  //Successful processing
235  return NO_ERROR;
236 }
237 
238 #endif
239 #if (SHA256_SUPPORT == ENABLED)
240 
241 /**
242  * @brief Digest a message using SHA-256
243  * @param[in] data Pointer to the message being hashed
244  * @param[in] length Length of the message
245  * @param[out] digest Pointer to the calculated digest
246  * @return Error code
247  **/
248 
249 error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
250 {
251  //Empty message?
252  if(length == 0)
253  {
254  //Return the SHA-256 digest value for an empty message
256  }
257  else
258  {
259  //Digest the message using SHA-256
261  //Copy the resulting digest value
262  osMemcpy(digest, hashOutput, SHA256_DIGEST_SIZE);
263  }
264 
265  //Successful processing
266  return NO_ERROR;
267 }
268 
269 #endif
270 #endif
General definitions for cryptographic algorithms.
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t data[]
Definition: ethernet.h:222
Collection of hash algorithms.
#define MD5_DIGEST_SIZE
Definition: md5.h:45
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
OsMutex pic32mzCryptoMutex
PIC32MZ hardware cryptographic accelerator.
#define BD_CTRL_SA_FETCH_EN
#define SA_CTRL_FB
#define BD_CTRL_DESC_EN
#define BD_CTRL_LIFM
#define PIC32MZ_CRYPTO_BUFFER_SIZE
#define SA_CTRL_LNC
#define SA_CTRL_LOADIV
#define SA_CTRL_ALGO_SHA256
#define SA_CTRL_ALGO_MD5
#define SA_CTRL_ALGO_SHA1
void hashProcessData(uint32_t algo, const uint8_t *data, size_t length)
Digest a message using the specified hash algorithm.
error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-256.
const uint8_t md5EmptyDigest[]
error_t md5Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using MD5.
const uint8_t sha256EmptyDigest[]
volatile Pic32mzCryptoBufferDesc hashBufferDesc __attribute__((coherent, aligned(8)))
const uint8_t sha1EmptyDigest[]
error_t sha1Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using SHA-1.
PIC32MZ hash hardware accelerator.
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
Buffer description.
Security association.
uint8_t length
Definition: tcp.h:368