shamd5.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. //*****************************************************************************
  2. //
  3. // shamd5.c
  4. //
  5. // Driver for the SHA/MD5 module.
  6. //
  7. // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
  8. //
  9. //
  10. // Redistribution and use in source and binary forms, with or without
  11. // modification, are permitted provided that the following conditions
  12. // are met:
  13. //
  14. // Redistributions of source code must retain the above copyright
  15. // notice, this list of conditions and the following disclaimer.
  16. //
  17. // Redistributions in binary form must reproduce the above copyright
  18. // notice, this list of conditions and the following disclaimer in the
  19. // documentation and/or other materials provided with the
  20. // distribution.
  21. //
  22. // Neither the name of Texas Instruments Incorporated nor the names of
  23. // its contributors may be used to endorse or promote products derived
  24. // from this software without specific prior written permission.
  25. //
  26. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  30. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  31. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  32. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  33. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  34. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  35. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  36. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. //
  38. //*****************************************************************************
  39. //*****************************************************************************
  40. //
  41. //! \addtogroup SHA_Secure_Hash_Algorithm_api
  42. //! @{
  43. //
  44. //*****************************************************************************
  45. #include <stdbool.h>
  46. #include <stdint.h>
  47. #include "inc/hw_dthe.h"
  48. #include "inc/hw_ints.h"
  49. #include "inc/hw_memmap.h"
  50. #include "inc/hw_nvic.h"
  51. #include "inc/hw_shamd5.h"
  52. #include "inc/hw_types.h"
  53. #include "debug.h"
  54. #include "interrupt.h"
  55. #include "shamd5.h"
  56. #include "rom_map.h"
  57. #define SHAMD5_MODE_ALGO_MD5 0x00000000 // MD5
  58. #define SHAMD5_MODE_ALGO_SHA1 0x00000002 // SHA-1
  59. #define SHAMD5_MODE_ALGO_SHA224 0x00000004 // SHA-224
  60. #define SHAMD5_MODE_ALGO_SHA256 0x00000006 // SHA-256
  61. //*****************************************************************************
  62. //
  63. //! Enables the uDMA requests in the SHA/MD5 module.
  64. //!
  65. //! \param ui32Base is the base address of the SHA/MD5 module.
  66. //!
  67. //! This function configures the DMA options of the SHA/MD5 module.
  68. //!
  69. //! \return None
  70. //
  71. //*****************************************************************************
  72. void
  73. SHAMD5DMAEnable(uint32_t ui32Base)
  74. {
  75. //
  76. // Check the arguments.
  77. //
  78. ASSERT(ui32Base == SHAMD5_BASE);
  79. //
  80. // Write the new configuration into the register.
  81. //
  82. HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |=
  83. SHAMD5_SYSCONFIG_PADVANCED | SHAMD5_SYSCONFIG_PDMA_EN;
  84. }
  85. //*****************************************************************************
  86. //
  87. //! Disables the uDMA requests in the SHA/MD5 module.
  88. //!
  89. //! \param ui32Base is the base address of the SHA/MD5 module.
  90. //!
  91. //! This function configures the DMA options of the SHA/MD5 module.
  92. //!
  93. //! \return None
  94. //
  95. //*****************************************************************************
  96. void
  97. SHAMD5DMADisable(uint32_t ui32Base)
  98. {
  99. //
  100. // Check the arguments.
  101. //
  102. ASSERT(ui32Base == SHAMD5_BASE);
  103. //
  104. // Write the new configuration into the register.
  105. //
  106. HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &=
  107. ~(SHAMD5_SYSCONFIG_PADVANCED | SHAMD5_SYSCONFIG_PDMA_EN);
  108. }
  109. //*****************************************************************************
  110. //
  111. //! Get the interrupt status of the SHA/MD5 module.
  112. //!
  113. //! \param ui32Base is the base address of the SHA/MD5 module.
  114. //! \param bMasked is \b false if the raw interrupt status is required and
  115. //! \b true if the masked interrupt status is required.
  116. //!
  117. //! This function returns the current value of the IRQSTATUS register. The
  118. //! value will be a logical OR of the following:
  119. //!
  120. //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
  121. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
  122. //! a context switch.
  123. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
  124. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
  125. //!
  126. //! \return Interrupt status
  127. //
  128. //*****************************************************************************
  129. uint32_t
  130. SHAMD5IntStatus(uint32_t ui32Base, bool bMasked)
  131. {
  132. uint32_t ui32Temp;
  133. uint32_t ui32IrqEnable;
  134. //
  135. // Check the arguments.
  136. //
  137. ASSERT(ui32Base == SHAMD5_BASE);
  138. //
  139. // Return the value of the IRQSTATUS register.
  140. //
  141. if(bMasked)
  142. {
  143. ui32Temp = HWREG(DTHE_BASE + DTHE_O_SHA_MIS);
  144. ui32IrqEnable = HWREG(ui32Base + SHAMD5_O_IRQENABLE);
  145. return((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) &
  146. ui32IrqEnable) | (ui32Temp & 0x00000007) << 16);
  147. }
  148. else
  149. {
  150. ui32Temp = HWREG(DTHE_BASE + DTHE_O_SHA_RIS);
  151. return(HWREG(ui32Base + SHAMD5_O_IRQSTATUS) |
  152. (ui32Temp & 0x00000007) << 16);
  153. }
  154. }
  155. //*****************************************************************************
  156. //
  157. //! Enable interrupt sources in the SHA/MD5 module.
  158. //!
  159. //! \param ui32Base is the base address of the SHA/MD5 module.
  160. //! \param ui32IntFlags contains desired interrupts to enable.
  161. //!
  162. //! This function enables interrupt sources in the SHA/MD5 module.
  163. //! ui32IntFlags must be a logical OR of one or more of the following
  164. //! values:
  165. //!
  166. //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
  167. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
  168. //! a context switch.
  169. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
  170. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
  171. //!
  172. //! \return None.
  173. //
  174. //*****************************************************************************
  175. void
  176. SHAMD5IntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
  177. {
  178. //
  179. // Check the arguments.
  180. //
  181. ASSERT(ui32Base == SHAMD5_BASE);
  182. ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
  183. (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
  184. (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
  185. (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
  186. //
  187. // Enable the interrupt sources.
  188. //
  189. HWREG(DTHE_BASE + DTHE_O_SHA_IM) &= ~((ui32IntFlags & 0x00070000) >> 16);
  190. HWREG(ui32Base + SHAMD5_O_IRQENABLE) |= ui32IntFlags & 0x0000ffff;
  191. //
  192. // Enable all interrupts.
  193. //
  194. HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |= SHAMD5_SYSCONFIG_PIT_EN;
  195. }
  196. //*****************************************************************************
  197. //
  198. //! Disable interrupt sources in the SHA/MD5 module.
  199. //!
  200. //! \param ui32Base is the base address of the SHA/MD5 module.
  201. //! \param ui32IntFlags contains desired interrupts to disable.
  202. //!
  203. //! \e ui32IntFlags must be a logical OR of one or more of the following
  204. //! values:
  205. //!
  206. //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
  207. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
  208. //! a context switch.
  209. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
  210. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
  211. //!
  212. //! \return None.
  213. //
  214. //*****************************************************************************
  215. void
  216. SHAMD5IntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
  217. {
  218. //
  219. // Check the arguments.
  220. //
  221. ASSERT(ui32Base == SHAMD5_BASE);
  222. ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
  223. (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
  224. (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
  225. (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
  226. //
  227. // Clear the corresponding flags disabling the interrupt sources.
  228. //
  229. HWREG(DTHE_BASE + DTHE_O_SHA_IM) |= ((ui32IntFlags & 0x00070000) >> 16);
  230. HWREG(ui32Base + SHAMD5_O_IRQENABLE) &= ~(ui32IntFlags & 0x0000ffff);
  231. //
  232. // If there are no interrupts enabled, then disable all interrupts.
  233. //
  234. if(HWREG(ui32Base + SHAMD5_O_IRQENABLE) == 0x0)
  235. {
  236. HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &= ~SHAMD5_SYSCONFIG_PIT_EN;
  237. }
  238. }
  239. //*****************************************************************************
  240. //
  241. //! Clears interrupt sources in the SHA/MD5 module.
  242. //!
  243. //! \param ui32Base is the base address of the SHA/MD5 module.
  244. //! \param ui32IntFlags contains desired interrupts to disable.
  245. //!
  246. //! \e ui32IntFlags must be a logical OR of one or more of the following
  247. //! values:
  248. //!
  249. //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
  250. //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
  251. //! a context switch.
  252. //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
  253. //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
  254. //!
  255. //! \return None.
  256. //
  257. //*****************************************************************************
  258. void
  259. SHAMD5IntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
  260. {
  261. //
  262. // Check the arguments.
  263. //
  264. ASSERT(ui32Base == SHAMD5_BASE);
  265. ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
  266. (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
  267. (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
  268. (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
  269. //
  270. // Clear the corresponding flags disabling the interrupt sources.
  271. //
  272. HWREG(DTHE_BASE + DTHE_O_SHA_IC) = ((ui32IntFlags & 0x00070000) >> 16);
  273. }
  274. //*****************************************************************************
  275. //
  276. //! Registers an interrupt handler for the SHA/MD5 module.
  277. //!
  278. //! \param ui32Base is the base address of the SHA/MD5 module.
  279. //! \param pfnHandler is a pointer to the function to be called when the
  280. //! enabled SHA/MD5 interrupts occur.
  281. //!
  282. //! This function registers the interrupt handler in the interrupt vector
  283. //! table, and enables SHA/MD5 interrupts on the interrupt controller;
  284. //! specific SHA/MD5 interrupt sources must be enabled using
  285. //! SHAMD5IntEnable(). The interrupt handler being registered must clear
  286. //! the source of the interrupt using SHAMD5IntClear().
  287. //!
  288. //! If the application is using a static interrupt vector table stored in
  289. //! flash, then it is not necessary to register the interrupt handler this way.
  290. //! Instead, IntEnable() should be used to enable SHA/MD5 interrupts on the
  291. //! interrupt controller.
  292. //!
  293. //! \sa IntRegister() for important information about registering interrupt
  294. //! handlers.
  295. //!
  296. //! \return None.
  297. //
  298. //*****************************************************************************
  299. void
  300. SHAMD5IntRegister(uint32_t ui32Base, void(*pfnHandler)(void))
  301. {
  302. //
  303. // Check the arguments.
  304. //
  305. ASSERT(ui32Base == SHAMD5_BASE);
  306. //
  307. // Register the interrupt handler.
  308. //
  309. IntRegister(INT_SHA, pfnHandler);
  310. //
  311. // Enable the interrupt
  312. //
  313. IntEnable(INT_SHA);
  314. }
  315. //*****************************************************************************
  316. //
  317. //! Unregisters an interrupt handler for the SHA/MD5 module.
  318. //!
  319. //! \param ui32Base is the base address of the SHA/MD5 module.
  320. //!
  321. //! This function unregisters the previously registered interrupt handler and
  322. //! disables the interrupt in the interrupt controller.
  323. //!
  324. //! \sa IntRegister() for important information about registering interrupt
  325. //! handlers.
  326. //!
  327. //! \return None.
  328. //
  329. //*****************************************************************************
  330. void
  331. SHAMD5IntUnregister(uint32_t ui32Base)
  332. {
  333. //
  334. // Check the arguments.
  335. //
  336. ASSERT(ui32Base == SHAMD5_BASE);
  337. //
  338. // Disable the interrupt.
  339. //
  340. IntDisable(INT_SHA);
  341. //
  342. // Unregister the interrupt handler.
  343. //
  344. IntUnregister(INT_SHA);
  345. }
  346. //*****************************************************************************
  347. //
  348. //! Write the hash length to the SHA/MD5 module.
  349. //!
  350. //! \param ui32Base is the base address of the SHA/MD5 module.
  351. //! \param ui32Length is the hash length in bytes.
  352. //!
  353. //! This function writes the length of the hash data of the current operation
  354. //! to the SHA/MD5 module. The value must be a multiple of 64 if the close
  355. //! hash is not set in the mode register.
  356. //!
  357. //! \note When this register is written, hash processing is triggered.
  358. //!
  359. //! \return None.
  360. //
  361. //*****************************************************************************
  362. void
  363. SHAMD5DataLengthSet(uint32_t ui32Base, uint32_t ui32Length)
  364. {
  365. //
  366. // Check the arguments.
  367. //
  368. ASSERT(ui32Base == SHAMD5_BASE);
  369. //
  370. // Set the LENGTH register and start processing.
  371. //
  372. HWREG(ui32Base + SHAMD5_O_LENGTH) = ui32Length;
  373. }
  374. //*****************************************************************************
  375. //
  376. //! Writes the mode in the SHA/MD5 module.
  377. //!
  378. //! \param ui32Base is the base address of the SHA/MD5 module.
  379. //! \param ui32Mode is the mode of the SHA/MD5 module.
  380. //!
  381. //! This function writes the mode register configuring the SHA/MD5 module.
  382. //!
  383. //! The ui32Mode paramerter is a bit-wise OR of values:
  384. //!
  385. //! - \b SHAMD5_ALGO_MD5 - Regular hash with MD5
  386. //! - \b SHAMD5_ALGO_SHA1 - Regular hash with SHA-1
  387. //! - \b SHAMD5_ALGO_SHA224 - Regular hash with SHA-224
  388. //! - \b SHAMD5_ALGO_SHA256 - Regular hash with SHA-256
  389. //! - \b SHAMD5_ALGO_HMAC_MD5 - HMAC with MD5
  390. //! - \b SHAMD5_ALGO_HMAC_SHA1 - HMAC with SHA-1
  391. //! - \b SHAMD5_ALGO_HMAC_SHA224 - HMAC with SHA-224
  392. //! - \b SHAMD5_ALGO_HMAC_SHA256 - HMAC with SHA-256
  393. //!
  394. //! \return None
  395. //
  396. //*****************************************************************************
  397. void
  398. SHAMD5ConfigSet(uint32_t ui32Base, uint32_t ui32Mode)
  399. {
  400. //
  401. // Check the arguments.
  402. //
  403. ASSERT(ui32Base == SHAMD5_BASE);
  404. ASSERT((ui32Mode == SHAMD5_ALGO_MD5) ||
  405. (ui32Mode == SHAMD5_ALGO_SHA1) ||
  406. (ui32Mode == SHAMD5_ALGO_SHA224) ||
  407. (ui32Mode == SHAMD5_ALGO_SHA256) ||
  408. (ui32Mode == SHAMD5_ALGO_HMAC_MD5) ||
  409. (ui32Mode == SHAMD5_ALGO_HMAC_SHA1) ||
  410. (ui32Mode == SHAMD5_ALGO_HMAC_SHA224) ||
  411. (ui32Mode == SHAMD5_ALGO_HMAC_SHA256));
  412. //
  413. // Write the value in the MODE register.
  414. //
  415. HWREG(ui32Base + SHAMD5_O_MODE) = ui32Mode;
  416. }
  417. //*****************************************************************************
  418. //
  419. //! Perform a non-blocking write of 16 words of data to the SHA/MD5 module.
  420. //!
  421. //! \param ui32Base is the base address of the SHA/MD5 module.
  422. //! \param pui8Src is the pointer to the 16-word array of data that will be
  423. //! written.
  424. //!
  425. //! This function writes 16 words of data into the data register.
  426. //!
  427. //! \return This function returns true if the write completed successfully.
  428. //! It returns false if the module was not ready.
  429. //
  430. //*****************************************************************************
  431. bool
  432. SHAMD5DataWriteNonBlocking(uint32_t ui32Base, uint8_t *pui8Src)
  433. {
  434. uint32_t ui8Counter;
  435. //
  436. // Check the arguments.
  437. //
  438. ASSERT(ui32Base == SHAMD5_BASE);
  439. //
  440. // Check that the SHA/MD5 module is ready for data. If not, return false.
  441. //
  442. if((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0)
  443. {
  444. return(false);
  445. }
  446. //
  447. // Write the 16 words of data.
  448. //
  449. for(ui8Counter = 0; ui8Counter < 64; ui8Counter += 4)
  450. {
  451. HWREG(ui32Base + SHAMD5_O_DATA0_IN + ui8Counter) = *((uint32_t *)(pui8Src + ui8Counter));
  452. }
  453. //
  454. // Return true as a sign of successfully completing the function.
  455. //
  456. return(true);
  457. }
  458. //*****************************************************************************
  459. //
  460. //! Perform a blocking write of 64 bytes of data to the SHA/MD5 module.
  461. //!
  462. //! \param ui32Base is the base address of the SHA/MD5 module.
  463. //! \param pui8Src is the pointer to the 64-byte array of data that will be
  464. //! written.
  465. //!
  466. //! This function does not return until the module is ready to accept data and
  467. //! the data has been written.
  468. //!
  469. //! \return None.
  470. //
  471. //*****************************************************************************
  472. void
  473. SHAMD5DataWrite(uint32_t ui32Base, uint8_t *pui8Src)
  474. {
  475. uint8_t ui8Counter;
  476. //
  477. // Check the arguments.
  478. //
  479. ASSERT(ui32Base == SHAMD5_BASE);
  480. //
  481. // Wait for the module to be ready to accept data.
  482. //
  483. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0)
  484. {
  485. }
  486. //
  487. // Write the 64 bytes of data.
  488. //
  489. for(ui8Counter = 0; ui8Counter < 64; ui8Counter += 4)
  490. {
  491. HWREG(ui32Base + SHAMD5_O_DATA0_IN + ui8Counter) =
  492. *((uint32_t *) (pui8Src + ui8Counter));
  493. }
  494. }
  495. //*****************************************************************************
  496. //
  497. //! Reads the result of a hashing operation.
  498. //!
  499. //! \param ui32Base is the base address of the SHA/MD5 module.
  500. //! \param pui8Dest is the pointer to the byte array of data that will be
  501. //! written.
  502. //!
  503. //! This function does not return until the module is ready to accept data and
  504. //! the data has been written.
  505. //! -----------------------------------------
  506. //! | Algorithm | Number of Words in Result |
  507. //! -----------------------------------------
  508. //! | MD5 | 16 Bytes (128 bits) |
  509. //! | SHA-1 | 20 Bytes (160 bits) |
  510. //! | SHA-224 | 28 Bytes (224 bits) |
  511. //! | SHA-256 | 32 Bytes (256 bits) |
  512. //! -----------------------------------------
  513. //!
  514. //! \return None.
  515. //
  516. //*****************************************************************************
  517. void
  518. SHAMD5ResultRead(uint32_t ui32Base, uint8_t *pui8Dest)
  519. {
  520. uint32_t ui32Idx, ui32Count;
  521. //
  522. // Check the arguments.
  523. //
  524. ASSERT(ui32Base == SHAMD5_BASE);
  525. //
  526. // Determine the number of bytes in the result, based on the hash type.
  527. //
  528. switch(HWREG(ui32Base + SHAMD5_O_MODE) & SHAMD5_MODE_ALGO_M)
  529. {
  530. //
  531. // The MD5 hash is being used.
  532. //
  533. case SHAMD5_MODE_ALGO_MD5:
  534. {
  535. //
  536. // There are 16 bytes in the MD5 hash.
  537. //
  538. ui32Count = 16;
  539. //
  540. // Done.
  541. //
  542. break;
  543. }
  544. //
  545. // The SHA-1 hash is being used.
  546. //
  547. case SHAMD5_MODE_ALGO_SHA1:
  548. {
  549. //
  550. // There are 20 bytes in the SHA-1 hash.
  551. //
  552. ui32Count = 20;
  553. //
  554. // Done.
  555. //
  556. break;
  557. }
  558. //
  559. // The SHA-224 hash is being used.
  560. //
  561. case SHAMD5_MODE_ALGO_SHA224:
  562. {
  563. //
  564. // There are 28 bytes in the SHA-224 hash.
  565. //
  566. ui32Count = 28;
  567. //
  568. // Done.
  569. //
  570. break;
  571. }
  572. //
  573. // The SHA-256 hash is being used.
  574. //
  575. case SHAMD5_MODE_ALGO_SHA256:
  576. {
  577. //
  578. // There are 32 bytes in the SHA-256 hash.
  579. //
  580. ui32Count = 32;
  581. //
  582. // Done.
  583. //
  584. break;
  585. }
  586. //
  587. // The hash type is not recognized.
  588. //
  589. default:
  590. {
  591. //
  592. // Return without reading a result since the hardware appears to be
  593. // misconfigured.
  594. //
  595. return;
  596. }
  597. }
  598. //
  599. // Read the hash result.
  600. //
  601. for(ui32Idx = 0; ui32Idx < ui32Count; ui32Idx += 4)
  602. {
  603. *((uint32_t *)(pui8Dest+ui32Idx)) =
  604. HWREG(ui32Base + SHAMD5_O_IDIGEST_A + ui32Idx);
  605. }
  606. }
  607. //*****************************************************************************
  608. //
  609. //! Writes multiple words of data into the SHA/MD5 data registers.
  610. //!
  611. //! \param ui32Base is the base address of the SHA/MD5 module.
  612. //! \param pui8DataSrc is a pointer to an array of data to be written.
  613. //! \param ui32DataLength is the length of the data to be written in bytes.
  614. //!
  615. //! This function writes a variable number of words into the SHA/MD5 data
  616. //! registers. The function waits for each block of data to be processed
  617. //! before another is written.
  618. //!
  619. //! \note This function is used by SHAMD5HashCompute(), SHAMD5HMACWithKPP(),
  620. //! and SHAMD5HMACNoKPP() to process data.
  621. //!
  622. //! \return None.
  623. //
  624. //*****************************************************************************
  625. void
  626. SHAMD5DataWriteMultiple(uint8_t *pui8DataSrc, uint32_t ui32DataLength)
  627. {
  628. uint32_t ui32Idx, ui32Count, ui32Lastword, ui32TempData = 0;
  629. uint8_t * ui8TempData;
  630. //
  631. // Calculate the number of blocks of data.
  632. //
  633. ui32Count = ui32DataLength / 64;
  634. //
  635. // Loop through all the blocks and write them into the data registers
  636. // making sure to block additional operations until we can write the
  637. // next 16 words.
  638. //
  639. for (ui32Idx = 0; ui32Idx < ui32Count; ui32Idx++)
  640. {
  641. //
  642. // Write the block of data.
  643. //
  644. MAP_SHAMD5DataWrite(SHAMD5_BASE, pui8DataSrc);
  645. //
  646. // Increment the pointer to next block of data.
  647. //
  648. pui8DataSrc += 64;
  649. }
  650. //
  651. // Calculate the remaining bytes of data that don't make up a full block.
  652. //
  653. ui32Count = ui32DataLength % 64;
  654. //
  655. // If there are bytes that do not make up a whole block, then
  656. // write them separately.
  657. //
  658. if(ui32Count)
  659. {
  660. //
  661. // Wait until the engine has finished processing the previous block.
  662. //
  663. while ((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0);
  664. //
  665. // Loop through the remaining words.
  666. //
  667. ui32Count = ui32Count / 4;
  668. for (ui32Idx = 0; ui32Idx < ui32Count; ui32Idx ++)
  669. {
  670. //
  671. // Write the word into the data register.
  672. //
  673. HWREG(SHAMD5_BASE + SHAMD5_O_DATA0_IN + (ui32Idx * 4)) =* ( (uint32_t *) pui8DataSrc);
  674. pui8DataSrc +=4;
  675. }
  676. //
  677. // Loop through the remaining bytes
  678. //
  679. ui32Count = ui32DataLength % 4;
  680. ui8TempData = (uint8_t *) &ui32TempData;
  681. if(ui32Count)
  682. {
  683. ui32Lastword = 0;
  684. if(ui32Idx)
  685. {
  686. ui32Lastword = (ui32Idx-1) *4;
  687. }
  688. for(ui32Idx=0 ; ui32Idx<ui32Count ; ui32Idx++)
  689. {
  690. *(ui8TempData+ui32Idx) = *(pui8DataSrc+ui32Idx);
  691. }
  692. HWREG(SHAMD5_BASE + SHAMD5_O_DATA0_IN + ui32Lastword) = ui32TempData;
  693. }
  694. }
  695. }
  696. //*****************************************************************************
  697. //
  698. //! Compute a hash using the SHA/MD5 module.
  699. //!
  700. //! \param ui32Base is the base address of the SHA/MD5 module.
  701. //! \param pui8DataSrc is a pointer to an array of data that contains the
  702. //! data that will be hashed.
  703. //! \param ui32DataLength specifies the length of the data to be hashed in
  704. //! bytes.
  705. //! \param pui8HashResult is a pointer to an array that holds the result
  706. //! of the hashing operation.
  707. //!
  708. //! This function computes the hash of an array of data using the SHA/MD5
  709. //! module.
  710. //!
  711. //! The length of the hash result is dependent on the algorithm that is in use.
  712. //! The following table shows the correct array size for each algorithm:
  713. //!
  714. //! -----------------------------------------
  715. //! | Algorithm | Number of Words in Result |
  716. //! -----------------------------------------
  717. //! | MD5 | 4 Words (128 bits) |
  718. //! | SHA-1 | 5 Words (160 bits) |
  719. //! | SHA-224 | 7 Words (224 bits) |
  720. //! | SHA-256 | 8 Words (256 bits) |
  721. //! -----------------------------------------
  722. //!
  723. //! \return None
  724. //
  725. //*****************************************************************************
  726. bool
  727. SHAMD5DataProcess(uint32_t ui32Base, uint8_t *pui8DataSrc,
  728. uint32_t ui32DataLength, uint8_t *pui8HashResult)
  729. {
  730. //
  731. // Check the arguments.
  732. //
  733. ASSERT(ui32Base == SHAMD5_BASE);
  734. ASSERT((ui32DataLength % 64) == 0);
  735. //
  736. // Wait for the context to be ready before writing the mode.
  737. //
  738. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
  739. 0)
  740. {
  741. }
  742. //
  743. // Write the length.
  744. //
  745. SHAMD5DataLengthSet(ui32Base, ui32DataLength);
  746. //
  747. // Write the data.
  748. //
  749. SHAMD5DataWriteMultiple(pui8DataSrc, ui32DataLength);
  750. //
  751. // Wait for the output to be ready.
  752. //
  753. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
  754. 0)
  755. {
  756. }
  757. //
  758. // Read the result.
  759. //
  760. SHAMD5ResultRead(ui32Base, pui8HashResult);
  761. //
  762. // Return true to indicate successful completion of the function.
  763. //
  764. return(true);
  765. }
  766. //*****************************************************************************
  767. //
  768. //! Compute a HMAC with key pre-processing using the SHA/MD5 module.
  769. //!
  770. //! \param ui32Base is the base address of the SHA/MD5 module.
  771. //! \param pui8DataSrc is a pointer to an array of data that contains the
  772. //! data that is to be hashed.
  773. //! \param ui32DataLength specifies the length of the data to be hashed in
  774. //! bytes.
  775. //! \param pui8HashResult is a pointer to an array that holds the result
  776. //! of the hashing operation.
  777. //!
  778. //! This function computes a HMAC with the given data using the SHA/MD5
  779. //! module with a preprocessed key.
  780. //!
  781. //! The length of the hash result is dependent on the algorithm that is
  782. //! selected with the \e ui32Algo argument. The following table shows the
  783. //! correct array size for each algorithm:
  784. //!
  785. //! -----------------------------------------
  786. //! | Algorithm | Number of Words in Result |
  787. //! -----------------------------------------
  788. //! | MD5 | 4 Words (128 bits) |
  789. //! | SHA-1 | 5 Words (160 bits) |
  790. //! | SHA-224 | 7 Words (224 bits) |
  791. //! | SHA-256 | 8 Words (256 bits) |
  792. //! -----------------------------------------
  793. //!
  794. //! \return None
  795. //
  796. //*****************************************************************************
  797. bool
  798. SHAMD5HMACProcess(uint32_t ui32Base, uint8_t *pui8DataSrc,
  799. uint32_t ui32DataLength, uint8_t *pui8HashResult)
  800. {
  801. //
  802. // Check the arguments.
  803. //
  804. ASSERT(ui32Base == SHAMD5_BASE);
  805. //
  806. // Wait for the context to be ready before writing the mode.
  807. //
  808. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
  809. 0)
  810. {
  811. }
  812. //
  813. // Write the length.
  814. //
  815. SHAMD5DataLengthSet(ui32Base, ui32DataLength);
  816. //
  817. // Write the data in the registers.
  818. //
  819. SHAMD5DataWriteMultiple(pui8DataSrc, ui32DataLength);
  820. //
  821. // Wait for the output to be ready.
  822. //
  823. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
  824. 0)
  825. {
  826. }
  827. //
  828. // Read the result.
  829. //
  830. SHAMD5ResultRead(ui32Base, pui8HashResult);
  831. //
  832. // Return true to indicate successful completion of the function.
  833. //
  834. return(true);
  835. }
  836. //*****************************************************************************
  837. //
  838. //! Process an HMAC key using the SHA/MD5 module.
  839. //!
  840. //! \param ui32Base is the base address of the SHA/MD5 module.
  841. //! \param pui8Key is a pointer to an array that contains the key to be
  842. //! processed.
  843. //! \param pui8PPKey is the pointer to the array that contains the
  844. //! pre-processed key.
  845. //!
  846. //! This function processes an HMAC key using the SHA/MD5. The resultant
  847. //! pre-processed key can then be used with later HMAC operations to speed
  848. //! processing time.
  849. //!
  850. //! The \e pui8Key array must be 512 bits long. If the key is
  851. //! less than 512 bits, it must be padded with zeros. The
  852. //! \e pui8PPKey array must each be 512 bits long.
  853. //!
  854. //! \return None
  855. //
  856. //*****************************************************************************
  857. void
  858. SHAMD5HMACPPKeyGenerate(uint32_t ui32Base, uint8_t *pui8Key,
  859. uint8_t *pui8PPKey)
  860. {
  861. uint32_t ui32Index;
  862. //
  863. // Check the arguments.
  864. //
  865. ASSERT(ui32Base == SHAMD5_BASE);
  866. //
  867. // Wait for the context to be ready before writing the mode.
  868. //
  869. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
  870. 0)
  871. {
  872. }
  873. //
  874. // Write the HMAC key.
  875. //
  876. for(ui32Index = 0; ui32Index < 64; ui32Index += 4)
  877. {
  878. HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Index) =
  879. *((uint32_t *)(pui8Key + ui32Index));
  880. }
  881. //
  882. // Set the flag to cause the HMAC key to be pre-processed.
  883. //
  884. HWREG(ui32Base + SHAMD5_O_MODE) |= SHAMD5_MODE_HMAC_KEY_PROC;
  885. //
  886. // Set the length to zero to start the HMAC key pre-processing.
  887. //
  888. HWREG(ui32Base + SHAMD5_O_LENGTH) = 0;
  889. //
  890. // Wait for key to be processed.
  891. //
  892. while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
  893. 0)
  894. {
  895. }
  896. //
  897. // Read the pre-processed key from the SHA/MD5 module.
  898. //
  899. for(ui32Index = 0; ui32Index < 64; ui32Index += 4)
  900. {
  901. *((uint32_t *)(pui8PPKey+ui32Index)) =
  902. HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Index);
  903. }
  904. }
  905. //*****************************************************************************
  906. //
  907. //! Writes an HMAC key to the digest registers in the SHA/MD5 module.
  908. //!
  909. //! \param ui32Base is the base address of the SHA/MD5 module.
  910. //! \param pui8Src is the pointer to the 16-word array of the HMAC key.
  911. //!
  912. //! This function is used to write HMAC key to the digest registers for
  913. //! key preprocessing. The size of pui8Src must be 512 bytes. If the key is
  914. //! less than 512 bytes, then it must be padded with zeros.
  915. //!
  916. //! \note It is recommended to use the SHAMD5GetIntStatus function to check
  917. //! whether the context is ready before writing the key.
  918. //!
  919. //! \return None
  920. //
  921. //*****************************************************************************
  922. void
  923. SHAMD5HMACKeySet(uint32_t ui32Base, uint8_t *pui8Src)
  924. {
  925. uint32_t ui32Idx;
  926. //
  927. // Check the arguments.
  928. //
  929. ASSERT(ui32Base == SHAMD5_BASE);
  930. //
  931. // Write the key to the digest registers.
  932. //
  933. for(ui32Idx = 0; ui32Idx < 64; ui32Idx += 4)
  934. {
  935. HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Idx) =
  936. * ((uint32_t *)(pui8Src + ui32Idx));
  937. }
  938. //
  939. // Configure the SHA engine for HMAC operation.
  940. //
  941. HWREG(ui32Base + SHAMD5_O_MODE) |= (SHAMD5_MODE_HMAC_OUTER_HASH |
  942. SHAMD5_MODE_HMAC_KEY_PROC |
  943. SHAMD5_MODE_CLOSE_HASH);
  944. }
  945. //*****************************************************************************
  946. //
  947. //! Writes a pre-processed HMAC key to the digest registers in the SHA/MD5
  948. //! module.
  949. //!
  950. //! \param ui32Base is the base address of the SHA/MD5 module.
  951. //! \param pui8Src is the pointer to the 16-word array of the HMAC key.
  952. //!
  953. //! This function is used to write HMAC key to the digest registers for
  954. //! key preprocessing. The size of pui8Src must be 512 bytes. If the key is
  955. //! less than 512 bytes, then it must be padded with zeros.
  956. //!
  957. //! \note It is recommended to use the SHAMD5GetIntStatus function to check
  958. //! whether the context is ready before writing the key.
  959. //!
  960. //! \return None
  961. //
  962. //*****************************************************************************
  963. void
  964. SHAMD5HMACPPKeySet(uint32_t ui32Base, uint8_t *pui8Src)
  965. {
  966. uint32_t ui32Idx;
  967. //
  968. // Check the arguments.
  969. //
  970. ASSERT(ui32Base == SHAMD5_BASE);
  971. //
  972. // Write the key to the digest registers.
  973. //
  974. for(ui32Idx = 0; ui32Idx < 64; ui32Idx += 4)
  975. {
  976. HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Idx) =
  977. *((uint32_t *) (pui8Src + ui32Idx));
  978. }
  979. //
  980. // Configure the SHA engine to continue the HMAC.
  981. //
  982. HWREG(ui32Base + SHAMD5_O_MODE) |= (SHAMD5_MODE_HMAC_OUTER_HASH |
  983. SHAMD5_MODE_CLOSE_HASH);
  984. //
  985. // Write the digest count to 64 to account for the preprocessed key.
  986. //
  987. HWREG(ui32Base + SHAMD5_O_DIGEST_COUNT) = 64;
  988. }
  989. //*****************************************************************************
  990. //
  991. // Close the Doxygen group.
  992. //! @}
  993. //
  994. //*****************************************************************************