shamd5.c 32 KB

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