stm32l4xx_hal_hash.c 129 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540
  1. /**
  2. ******************************************************************************
  3. * @file stm32l4xx_hal_hash.c
  4. * @author MCD Application Team
  5. * @brief HASH HAL module driver.
  6. * This file provides firmware functions to manage the following
  7. * functionalities of the HASH peripheral:
  8. * + Initialization and de-initialization methods
  9. * + HASH or HMAC processing in polling mode
  10. * + HASH or HMAC processing in interrupt mode
  11. * + HASH or HMAC processing in DMA mode
  12. * + Peripheral State methods
  13. * + HASH or HMAC processing suspension/resumption
  14. *
  15. ******************************************************************************
  16. * @attention
  17. *
  18. * Copyright (c) 2017 STMicroelectronics.
  19. * All rights reserved.
  20. *
  21. * This software is licensed under terms that can be found in the LICENSE file
  22. * in the root directory of this software component.
  23. * If no LICENSE file comes with this software, it is provided AS-IS.
  24. *
  25. ******************************************************************************
  26. @verbatim
  27. ===============================================================================
  28. ##### How to use this driver #####
  29. ===============================================================================
  30. [..]
  31. The HASH HAL driver can be used as follows:
  32. (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
  33. (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
  34. (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
  35. (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
  36. (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
  37. (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
  38. (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA())
  39. (+++) Enable the DMAx interface clock using
  40. __DMAx_CLK_ENABLE()
  41. (+++) Configure and enable one DMA channel to manage data transfer from
  42. memory to peripheral (input channel). Managing data transfer from
  43. peripheral to memory can be performed only using CPU.
  44. (+++) Associate the initialized DMA handle to the HASH DMA handle
  45. using __HAL_LINKDMA()
  46. (+++) Configure the priority and enable the NVIC for the transfer complete
  47. interrupt on the DMA channel: use
  48. HAL_NVIC_SetPriority() and
  49. HAL_NVIC_EnableIRQ()
  50. (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
  51. (##) resorts to HAL_HASH_MspInit() for low-level initialization,
  52. (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
  53. (#)Three processing schemes are available:
  54. (##) Polling mode: processing APIs are blocking functions
  55. i.e. they process the data and wait till the digest computation is finished,
  56. e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
  57. (##) Interrupt mode: processing APIs are not blocking functions
  58. i.e. they process the data under interrupt,
  59. e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
  60. (##) DMA mode: processing APIs are not blocking functions and the CPU is
  61. not used for data transfer i.e. the data transfer is ensured by DMA,
  62. e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
  63. for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
  64. is then required to retrieve the digest.
  65. (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
  66. initialized and processes the buffer fed in input. When the input data have all been
  67. fed to the Peripheral, the digest computation can start.
  68. (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
  69. (##) In polling mode, only multi-buffer HASH processing is possible.
  70. API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
  71. User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
  72. well the computed digest.
  73. (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
  74. except for the last one.
  75. User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
  76. well the computed digest.
  77. (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
  78. (+++) HASH processing: once initialization is done, MDMAT bit must be set
  79. through __HAL_HASH_SET_MDMAT() macro.
  80. From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API.
  81. Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
  82. macro then wrap-up the HASH processing in feeding the last input buffer through the
  83. same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
  84. API HAL_HASH_xxx_Finish().
  85. (+++) HMAC processing (requires to resort to extended functions):
  86. after initialization, the key and the first input buffer are entered
  87. in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
  88. starts step 2.
  89. The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this
  90. point, the HMAC processing is still carrying out step 2.
  91. Then, step 2 for the last input buffer and step 3 are carried out by a single call
  92. to HAL_HMACEx_xxx_Step2_3_DMA().
  93. The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
  94. (#)Context swapping.
  95. (##) Two APIs are available to suspend HASH or HMAC processing:
  96. (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
  97. (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
  98. (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
  99. to save in memory the Peripheral context. This context can be restored afterwards
  100. to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
  101. (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
  102. time, processing can be restarted with the same API call (same API, same handle,
  103. same parameters) as done before the suspension. Relevant parameters to restart at
  104. the proper location are internally saved in the HASH handle.
  105. (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
  106. *** Remarks on message length ***
  107. ===================================
  108. [..]
  109. (#) HAL in interruption mode (interruptions driven)
  110. (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
  111. This is why, for driver implementation simplicity s sake, user is requested to enter a message the
  112. length of which is a multiple of 4 bytes.
  113. (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
  114. to specify which bits to discard at the end of the complete message to process only the message bits
  115. and not extra bits.
  116. (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
  117. in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes
  118. necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
  119. It is advised to the user to
  120. (+++) achieve the first formatting operation by software then enter the data
  121. (+++) while the Peripheral is processing the first input set, carry out the second formatting
  122. operation by software, to be ready when DINIS occurs.
  123. (+++) repeat step 2 until the whole message is processed.
  124. [..]
  125. (#) HAL in DMA mode
  126. (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
  127. The same field described above in HASH_STR is used to specify which bits to discard at the end of the
  128. DMA transfer to process only the message bits and not extra bits. Due to hardware implementation,
  129. this is possible only at the end of the complete message. When several DMA transfers are needed to
  130. enter the message, this is not applicable at the end of the intermediary transfers.
  131. (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive
  132. chunks of data by software while the DMA transfer and processing is on-going for the first parts of
  133. the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the
  134. software formatting operation is more complex than in the IT mode.
  135. *** Callback registration ***
  136. ===================================
  137. [..]
  138. (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
  139. allows the user to configure dynamically the driver callbacks.
  140. Use function HAL_HASH_RegisterCallback() to register a user callback.
  141. (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks:
  142. (+) InCpltCallback : callback for input completion.
  143. (+) DgstCpltCallback : callback for digest computation completion.
  144. (+) ErrorCallback : callback for error.
  145. (+) MspInitCallback : HASH MspInit.
  146. (+) MspDeInitCallback : HASH MspDeInit.
  147. This function takes as parameters the HAL peripheral handle, the Callback ID
  148. and a pointer to the user callback function.
  149. (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default
  150. weak (surcharged) function.
  151. HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
  152. and the Callback ID.
  153. This function allows to reset following callbacks:
  154. (+) InCpltCallback : callback for input completion.
  155. (+) DgstCpltCallback : callback for digest computation completion.
  156. (+) ErrorCallback : callback for error.
  157. (+) MspInitCallback : HASH MspInit.
  158. (+) MspDeInitCallback : HASH MspDeInit.
  159. (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
  160. all callbacks are reset to the corresponding legacy weak (surcharged) functions:
  161. examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback()
  162. Exception done for MspInit and MspDeInit callbacks that are respectively
  163. reset to the legacy weak (surcharged) functions in the HAL_HASH_Init
  164. and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
  165. If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit
  166. keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
  167. Callbacks can be registered/unregistered in READY state only.
  168. Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
  169. in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
  170. during the Init/DeInit.
  171. In that case first register the MspInit/MspDeInit user callbacks
  172. using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit
  173. or HAL_HASH_Init function.
  174. When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
  175. not defined, the callback registering feature is not available
  176. and weak (surcharged) callbacks are used.
  177. @endverbatim
  178. ******************************************************************************
  179. */
  180. /* Includes ------------------------------------------------------------------*/
  181. #include "stm32l4xx_hal.h"
  182. /** @addtogroup STM32L4xx_HAL_Driver
  183. * @{
  184. */
  185. #if defined (HASH)
  186. /** @defgroup HASH HASH
  187. * @brief HASH HAL module driver.
  188. * @{
  189. */
  190. #ifdef HAL_HASH_MODULE_ENABLED
  191. /* Private typedef -----------------------------------------------------------*/
  192. /* Private define ------------------------------------------------------------*/
  193. /** @defgroup HASH_Private_Constants HASH Private Constants
  194. * @{
  195. */
  196. /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
  197. * @{
  198. */
  199. #define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
  200. #define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */
  201. /**
  202. * @}
  203. */
  204. /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
  205. * @{
  206. */
  207. #define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */
  208. /**
  209. * @}
  210. */
  211. /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
  212. * @{
  213. */
  214. #define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */
  215. /**
  216. * @}
  217. */
  218. /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
  219. * @{
  220. */
  221. #define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */
  222. /**
  223. * @}
  224. */
  225. /**
  226. * @}
  227. */
  228. /* Private macro -------------------------------------------------------------*/
  229. /* Private variables ---------------------------------------------------------*/
  230. /* Private function prototypes -----------------------------------------------*/
  231. /** @defgroup HASH_Private_Functions HASH Private Functions
  232. * @{
  233. */
  234. static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
  235. static void HASH_DMAError(DMA_HandleTypeDef *hdma);
  236. static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
  237. static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
  238. uint32_t Timeout);
  239. static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
  240. static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
  241. static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
  242. static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
  243. /**
  244. * @}
  245. */
  246. /** @defgroup HASH_Exported_Functions HASH Exported Functions
  247. * @{
  248. */
  249. /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
  250. * @brief Initialization, configuration and call-back functions.
  251. *
  252. @verbatim
  253. ===============================================================================
  254. ##### Initialization and de-initialization functions #####
  255. ===============================================================================
  256. [..] This section provides functions allowing to:
  257. (+) Initialize the HASH according to the specified parameters
  258. in the HASH_InitTypeDef and create the associated handle
  259. (+) DeInitialize the HASH peripheral
  260. (+) Initialize the HASH MCU Specific Package (MSP)
  261. (+) DeInitialize the HASH MSP
  262. [..] This section provides as well call back functions definitions for user
  263. code to manage:
  264. (+) Input data transfer to Peripheral completion
  265. (+) Calculated digest retrieval completion
  266. (+) Error management
  267. @endverbatim
  268. * @{
  269. */
  270. /**
  271. * @brief Initialize the HASH according to the specified parameters in the
  272. HASH_HandleTypeDef and create the associated handle.
  273. * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(),
  274. * other configuration bits are set by HASH or HMAC processing APIs.
  275. * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
  276. * multi-buffer HASH processing, user needs to resort to
  277. * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
  278. * relevant APIs manage themselves the MDMAT bit.
  279. * @param hhash HASH handle
  280. * @retval HAL status
  281. */
  282. HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
  283. {
  284. /* Check the hash handle allocation */
  285. if (hhash == NULL)
  286. {
  287. return HAL_ERROR;
  288. }
  289. /* Check the parameters */
  290. assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
  291. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  292. if (hhash->State == HAL_HASH_STATE_RESET)
  293. {
  294. /* Allocate lock resource and initialize it */
  295. hhash->Lock = HAL_UNLOCKED;
  296. /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
  297. hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
  298. hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
  299. completion callback */
  300. hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
  301. if (hhash->MspInitCallback == NULL)
  302. {
  303. hhash->MspInitCallback = HAL_HASH_MspInit;
  304. }
  305. /* Init the low level hardware */
  306. hhash->MspInitCallback(hhash);
  307. }
  308. #else
  309. if (hhash->State == HAL_HASH_STATE_RESET)
  310. {
  311. /* Allocate lock resource and initialize it */
  312. hhash->Lock = HAL_UNLOCKED;
  313. /* Init the low level hardware */
  314. HAL_HASH_MspInit(hhash);
  315. }
  316. #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
  317. /* Change the HASH state */
  318. hhash->State = HAL_HASH_STATE_BUSY;
  319. /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
  320. hhash->HashInCount = 0;
  321. hhash->HashBuffSize = 0;
  322. hhash->HashITCounter = 0;
  323. hhash->NbWordsAlreadyPushed = 0;
  324. /* Reset digest calculation bridle (MDMAT bit control) */
  325. hhash->DigestCalculationDisable = RESET;
  326. /* Set phase to READY */
  327. hhash->Phase = HAL_HASH_PHASE_READY;
  328. /* Reset suspension request flag */
  329. hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
  330. /* Set the data type bit */
  331. MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
  332. /* Reset MDMAT bit */
  333. __HAL_HASH_RESET_MDMAT();
  334. /* Reset HASH handle status */
  335. hhash->Status = HAL_OK;
  336. /* Set the HASH state to Ready */
  337. hhash->State = HAL_HASH_STATE_READY;
  338. /* Initialise the error code */
  339. hhash->ErrorCode = HAL_HASH_ERROR_NONE;
  340. /* Return function status */
  341. return HAL_OK;
  342. }
  343. /**
  344. * @brief DeInitialize the HASH peripheral.
  345. * @param hhash HASH handle.
  346. * @retval HAL status
  347. */
  348. HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
  349. {
  350. /* Check the HASH handle allocation */
  351. if (hhash == NULL)
  352. {
  353. return HAL_ERROR;
  354. }
  355. /* Change the HASH state */
  356. hhash->State = HAL_HASH_STATE_BUSY;
  357. /* Set the default HASH phase */
  358. hhash->Phase = HAL_HASH_PHASE_READY;
  359. /* Reset HashInCount, HashITCounter and HashBuffSize */
  360. hhash->HashInCount = 0;
  361. hhash->HashBuffSize = 0;
  362. hhash->HashITCounter = 0;
  363. /* Reset digest calculation bridle (MDMAT bit control) */
  364. hhash->DigestCalculationDisable = RESET;
  365. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  366. if (hhash->MspDeInitCallback == NULL)
  367. {
  368. hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
  369. }
  370. /* DeInit the low level hardware */
  371. hhash->MspDeInitCallback(hhash);
  372. #else
  373. /* DeInit the low level hardware: CLOCK, NVIC */
  374. HAL_HASH_MspDeInit(hhash);
  375. #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
  376. /* Reset HASH handle status */
  377. hhash->Status = HAL_OK;
  378. /* Set the HASH state to Ready */
  379. hhash->State = HAL_HASH_STATE_RESET;
  380. /* Initialise the error code */
  381. hhash->ErrorCode = HAL_HASH_ERROR_NONE;
  382. /* Reset multi buffers accumulation flag */
  383. hhash->Accumulation = 0U;
  384. /* Return function status */
  385. return HAL_OK;
  386. }
  387. /**
  388. * @brief Initialize the HASH MSP.
  389. * @param hhash HASH handle.
  390. * @retval None
  391. */
  392. __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
  393. {
  394. /* Prevent unused argument(s) compilation warning */
  395. UNUSED(hhash);
  396. /* NOTE : This function should not be modified; when the callback is needed,
  397. HAL_HASH_MspInit() can be implemented in the user file.
  398. */
  399. }
  400. /**
  401. * @brief DeInitialize the HASH MSP.
  402. * @param hhash HASH handle.
  403. * @retval None
  404. */
  405. __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
  406. {
  407. /* Prevent unused argument(s) compilation warning */
  408. UNUSED(hhash);
  409. /* NOTE : This function should not be modified; when the callback is needed,
  410. HAL_HASH_MspDeInit() can be implemented in the user file.
  411. */
  412. }
  413. /**
  414. * @brief Input data transfer complete call back.
  415. * @note HAL_HASH_InCpltCallback() is called when the complete input message
  416. * has been fed to the Peripheral. This API is invoked only when input data are
  417. * entered under interruption or through DMA.
  418. * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
  419. * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
  420. * to the Peripheral.
  421. * @param hhash HASH handle.
  422. * @retval None
  423. */
  424. __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
  425. {
  426. /* Prevent unused argument(s) compilation warning */
  427. UNUSED(hhash);
  428. /* NOTE : This function should not be modified; when the callback is needed,
  429. HAL_HASH_InCpltCallback() can be implemented in the user file.
  430. */
  431. }
  432. /**
  433. * @brief Digest computation complete call back.
  434. * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not
  435. * relevant with DMA.
  436. * @param hhash HASH handle.
  437. * @retval None
  438. */
  439. __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
  440. {
  441. /* Prevent unused argument(s) compilation warning */
  442. UNUSED(hhash);
  443. /* NOTE : This function should not be modified; when the callback is needed,
  444. HAL_HASH_DgstCpltCallback() can be implemented in the user file.
  445. */
  446. }
  447. /**
  448. * @brief Error callback.
  449. * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
  450. * to retrieve the error type.
  451. * @param hhash HASH handle.
  452. * @retval None
  453. */
  454. __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
  455. {
  456. /* Prevent unused argument(s) compilation warning */
  457. UNUSED(hhash);
  458. /* NOTE : This function should not be modified; when the callback is needed,
  459. HAL_HASH_ErrorCallback() can be implemented in the user file.
  460. */
  461. }
  462. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  463. /**
  464. * @brief Register a User HASH Callback
  465. * To be used instead of the weak (surcharged) predefined callback
  466. * @param hhash HASH handle
  467. * @param CallbackID ID of the callback to be registered
  468. * This parameter can be one of the following values:
  469. * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
  470. * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
  471. * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
  472. * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
  473. * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
  474. * @param pCallback pointer to the Callback function
  475. * @retval status
  476. */
  477. HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID,
  478. pHASH_CallbackTypeDef pCallback)
  479. {
  480. HAL_StatusTypeDef status = HAL_OK;
  481. if (pCallback == NULL)
  482. {
  483. /* Update the error code */
  484. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  485. return HAL_ERROR;
  486. }
  487. /* Process locked */
  488. __HAL_LOCK(hhash);
  489. if (HAL_HASH_STATE_READY == hhash->State)
  490. {
  491. switch (CallbackID)
  492. {
  493. case HAL_HASH_INPUTCPLT_CB_ID :
  494. hhash->InCpltCallback = pCallback;
  495. break;
  496. case HAL_HASH_DGSTCPLT_CB_ID :
  497. hhash->DgstCpltCallback = pCallback;
  498. break;
  499. case HAL_HASH_ERROR_CB_ID :
  500. hhash->ErrorCallback = pCallback;
  501. break;
  502. case HAL_HASH_MSPINIT_CB_ID :
  503. hhash->MspInitCallback = pCallback;
  504. break;
  505. case HAL_HASH_MSPDEINIT_CB_ID :
  506. hhash->MspDeInitCallback = pCallback;
  507. break;
  508. default :
  509. /* Update the error code */
  510. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  511. /* update return status */
  512. status = HAL_ERROR;
  513. break;
  514. }
  515. }
  516. else if (HAL_HASH_STATE_RESET == hhash->State)
  517. {
  518. switch (CallbackID)
  519. {
  520. case HAL_HASH_MSPINIT_CB_ID :
  521. hhash->MspInitCallback = pCallback;
  522. break;
  523. case HAL_HASH_MSPDEINIT_CB_ID :
  524. hhash->MspDeInitCallback = pCallback;
  525. break;
  526. default :
  527. /* Update the error code */
  528. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  529. /* update return status */
  530. status = HAL_ERROR;
  531. break;
  532. }
  533. }
  534. else
  535. {
  536. /* Update the error code */
  537. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  538. /* update return status */
  539. status = HAL_ERROR;
  540. }
  541. /* Release Lock */
  542. __HAL_UNLOCK(hhash);
  543. return status;
  544. }
  545. /**
  546. * @brief Unregister a HASH Callback
  547. * HASH Callback is redirected to the weak (surcharged) predefined callback
  548. * @param hhash HASH handle
  549. * @param CallbackID ID of the callback to be unregistered
  550. * This parameter can be one of the following values:
  551. * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
  552. * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
  553. * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
  554. * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
  555. * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
  556. * @retval status
  557. */
  558. HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
  559. {
  560. HAL_StatusTypeDef status = HAL_OK;
  561. /* Process locked */
  562. __HAL_LOCK(hhash);
  563. if (HAL_HASH_STATE_READY == hhash->State)
  564. {
  565. switch (CallbackID)
  566. {
  567. case HAL_HASH_INPUTCPLT_CB_ID :
  568. hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
  569. break;
  570. case HAL_HASH_DGSTCPLT_CB_ID :
  571. hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
  572. completion callback */
  573. break;
  574. case HAL_HASH_ERROR_CB_ID :
  575. hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
  576. break;
  577. case HAL_HASH_MSPINIT_CB_ID :
  578. hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
  579. break;
  580. case HAL_HASH_MSPDEINIT_CB_ID :
  581. hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
  582. break;
  583. default :
  584. /* Update the error code */
  585. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  586. /* update return status */
  587. status = HAL_ERROR;
  588. break;
  589. }
  590. }
  591. else if (HAL_HASH_STATE_RESET == hhash->State)
  592. {
  593. switch (CallbackID)
  594. {
  595. case HAL_HASH_MSPINIT_CB_ID :
  596. hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
  597. break;
  598. case HAL_HASH_MSPDEINIT_CB_ID :
  599. hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
  600. break;
  601. default :
  602. /* Update the error code */
  603. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  604. /* update return status */
  605. status = HAL_ERROR;
  606. break;
  607. }
  608. }
  609. else
  610. {
  611. /* Update the error code */
  612. hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
  613. /* update return status */
  614. status = HAL_ERROR;
  615. }
  616. /* Release Lock */
  617. __HAL_UNLOCK(hhash);
  618. return status;
  619. }
  620. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  621. /**
  622. * @}
  623. */
  624. /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
  625. * @brief HASH processing functions using polling mode.
  626. *
  627. @verbatim
  628. ===============================================================================
  629. ##### Polling mode HASH processing functions #####
  630. ===============================================================================
  631. [..] This section provides functions allowing to calculate in polling mode
  632. the hash value using one of the following algorithms:
  633. (+) MD5
  634. (++) HAL_HASH_MD5_Start()
  635. (++) HAL_HASH_MD5_Accmlt()
  636. (++) HAL_HASH_MD5_Accmlt_End()
  637. (+) SHA1
  638. (++) HAL_HASH_SHA1_Start()
  639. (++) HAL_HASH_SHA1_Accmlt()
  640. (++) HAL_HASH_SHA1_Accmlt_End()
  641. [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
  642. [..] In case of multi-buffer HASH processing (a single digest is computed while
  643. several buffers are fed to the Peripheral), the user can resort to successive calls
  644. to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
  645. to HAL_HASH_xxx_Accumulate_End().
  646. @endverbatim
  647. * @{
  648. */
  649. /**
  650. * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
  651. * read the computed digest.
  652. * @note Digest is available in pOutBuffer.
  653. * @param hhash HASH handle.
  654. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  655. * @param Size length of the input buffer in bytes.
  656. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  657. * @param Timeout Timeout value
  658. * @retval HAL status
  659. */
  660. HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  661. uint32_t Timeout)
  662. {
  663. return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
  664. }
  665. /**
  666. * @brief If not already done, initialize the HASH peripheral in MD5 mode then
  667. * processes pInBuffer.
  668. * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
  669. * several input buffers back-to-back to the Peripheral that will yield a single
  670. * HASH signature once all buffers have been entered. Wrap-up of input
  671. * buffers feeding and retrieval of digest is done by a call to
  672. * HAL_HASH_MD5_Accmlt_End().
  673. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  674. * the Peripheral has already been initialized.
  675. * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
  676. * to read it, feeding at the same time the last input buffer to the Peripheral.
  677. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  678. * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
  679. * to manage the ending buffer with a length in bytes not a multiple of 4.
  680. * @param hhash HASH handle.
  681. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  682. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  683. * @retval HAL status
  684. */
  685. HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  686. {
  687. return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
  688. }
  689. /**
  690. * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
  691. * @note Digest is available in pOutBuffer.
  692. * @param hhash HASH handle.
  693. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  694. * @param Size length of the input buffer in bytes.
  695. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  696. * @param Timeout Timeout value
  697. * @retval HAL status
  698. */
  699. HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  700. uint8_t *pOutBuffer, uint32_t Timeout)
  701. {
  702. return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
  703. }
  704. /**
  705. * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
  706. * read the computed digest.
  707. * @note Digest is available in pOutBuffer.
  708. * @param hhash HASH handle.
  709. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  710. * @param Size length of the input buffer in bytes.
  711. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  712. * @param Timeout Timeout value
  713. * @retval HAL status
  714. */
  715. HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  716. uint32_t Timeout)
  717. {
  718. return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
  719. }
  720. /**
  721. * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
  722. * processes pInBuffer.
  723. * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
  724. * several input buffers back-to-back to the Peripheral that will yield a single
  725. * HASH signature once all buffers have been entered. Wrap-up of input
  726. * buffers feeding and retrieval of digest is done by a call to
  727. * HAL_HASH_SHA1_Accmlt_End().
  728. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  729. * the Peripheral has already been initialized.
  730. * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
  731. * to read it, feeding at the same time the last input buffer to the Peripheral.
  732. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  733. * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
  734. * to manage the ending buffer with a length in bytes not a multiple of 4.
  735. * @param hhash HASH handle.
  736. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  737. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  738. * @retval HAL status
  739. */
  740. HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  741. {
  742. return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
  743. }
  744. /**
  745. * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
  746. * @note Digest is available in pOutBuffer.
  747. * @param hhash HASH handle.
  748. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  749. * @param Size length of the input buffer in bytes.
  750. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  751. * @param Timeout Timeout value
  752. * @retval HAL status
  753. */
  754. HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  755. uint8_t *pOutBuffer, uint32_t Timeout)
  756. {
  757. return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
  758. }
  759. /**
  760. * @}
  761. */
  762. /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
  763. * @brief HASH processing functions using interrupt mode.
  764. *
  765. @verbatim
  766. ===============================================================================
  767. ##### Interruption mode HASH processing functions #####
  768. ===============================================================================
  769. [..] This section provides functions allowing to calculate in interrupt mode
  770. the hash value using one of the following algorithms:
  771. (+) MD5
  772. (++) HAL_HASH_MD5_Start_IT()
  773. (++) HAL_HASH_MD5_Accmlt_IT()
  774. (++) HAL_HASH_MD5_Accmlt_End_IT()
  775. (+) SHA1
  776. (++) HAL_HASH_SHA1_Start_IT()
  777. (++) HAL_HASH_SHA1_Accmlt_IT()
  778. (++) HAL_HASH_SHA1_Accmlt_End_IT()
  779. [..] API HAL_HASH_IRQHandler() manages each HASH interruption.
  780. [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
  781. HMAC processing mode.
  782. @endverbatim
  783. * @{
  784. */
  785. /**
  786. * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
  787. * read the computed digest in interruption mode.
  788. * @note Digest is available in pOutBuffer.
  789. * @param hhash HASH handle.
  790. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  791. * @param Size length of the input buffer in bytes.
  792. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  793. * @retval HAL status
  794. */
  795. HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  796. uint8_t *pOutBuffer)
  797. {
  798. return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
  799. }
  800. /**
  801. * @brief If not already done, initialize the HASH peripheral in MD5 mode then
  802. * processes pInBuffer in interruption mode.
  803. * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
  804. * several input buffers back-to-back to the Peripheral that will yield a single
  805. * HASH signature once all buffers have been entered. Wrap-up of input
  806. * buffers feeding and retrieval of digest is done by a call to
  807. * HAL_HASH_MD5_Accmlt_End_IT().
  808. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  809. * the Peripheral has already been initialized.
  810. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  811. * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
  812. * to manage the ending buffer with a length in bytes not a multiple of 4.
  813. * @param hhash HASH handle.
  814. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  815. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  816. * @retval HAL status
  817. */
  818. HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  819. {
  820. return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
  821. }
  822. /**
  823. * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
  824. * @note Digest is available in pOutBuffer.
  825. * @param hhash HASH handle.
  826. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  827. * @param Size length of the input buffer in bytes.
  828. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  829. * @retval HAL status
  830. */
  831. HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  832. uint8_t *pOutBuffer)
  833. {
  834. return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
  835. }
  836. /**
  837. * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
  838. * read the computed digest in interruption mode.
  839. * @note Digest is available in pOutBuffer.
  840. * @param hhash HASH handle.
  841. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  842. * @param Size length of the input buffer in bytes.
  843. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  844. * @retval HAL status
  845. */
  846. HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  847. uint8_t *pOutBuffer)
  848. {
  849. return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
  850. }
  851. /**
  852. * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
  853. * processes pInBuffer in interruption mode.
  854. * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
  855. * several input buffers back-to-back to the Peripheral that will yield a single
  856. * HASH signature once all buffers have been entered. Wrap-up of input
  857. * buffers feeding and retrieval of digest is done by a call to
  858. * HAL_HASH_SHA1_Accmlt_End_IT().
  859. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  860. * the Peripheral has already been initialized.
  861. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  862. * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
  863. * to manage the ending buffer with a length in bytes not a multiple of 4.
  864. * @param hhash HASH handle.
  865. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  866. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  867. * @retval HAL status
  868. */
  869. HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  870. {
  871. return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
  872. }
  873. /**
  874. * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
  875. * @note Digest is available in pOutBuffer.
  876. * @param hhash HASH handle.
  877. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  878. * @param Size length of the input buffer in bytes.
  879. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  880. * @retval HAL status
  881. */
  882. HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  883. uint8_t *pOutBuffer)
  884. {
  885. return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
  886. }
  887. /**
  888. * @brief Handle HASH interrupt request.
  889. * @param hhash HASH handle.
  890. * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
  891. * @note In case of error reported during the HASH interruption processing,
  892. * HAL_HASH_ErrorCallback() API is called so that user code can
  893. * manage the error. The error type is available in hhash->Status field.
  894. * @retval None
  895. */
  896. void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
  897. {
  898. hhash->Status = HASH_IT(hhash);
  899. if (hhash->Status != HAL_OK)
  900. {
  901. hhash->ErrorCode |= HAL_HASH_ERROR_IT;
  902. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  903. hhash->ErrorCallback(hhash);
  904. #else
  905. HAL_HASH_ErrorCallback(hhash);
  906. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  907. /* After error handling by code user, reset HASH handle HAL status */
  908. hhash->Status = HAL_OK;
  909. }
  910. }
  911. /**
  912. * @}
  913. */
  914. /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
  915. * @brief HASH processing functions using DMA mode.
  916. *
  917. @verbatim
  918. ===============================================================================
  919. ##### DMA mode HASH processing functions #####
  920. ===============================================================================
  921. [..] This section provides functions allowing to calculate in DMA mode
  922. the hash value using one of the following algorithms:
  923. (+) MD5
  924. (++) HAL_HASH_MD5_Start_DMA()
  925. (++) HAL_HASH_MD5_Finish()
  926. (+) SHA1
  927. (++) HAL_HASH_SHA1_Start_DMA()
  928. (++) HAL_HASH_SHA1_Finish()
  929. [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort
  930. to HAL_HASH_xxx_Start_DMA() then read the resulting digest with
  931. HAL_HASH_xxx_Finish().
  932. [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before
  933. the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
  934. reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
  935. retrieved thanks to HAL_HASH_xxx_Finish().
  936. @endverbatim
  937. * @{
  938. */
  939. /**
  940. * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
  941. * to feed the input buffer to the Peripheral.
  942. * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
  943. * be called to retrieve the computed digest.
  944. * @param hhash HASH handle.
  945. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  946. * @param Size length of the input buffer in bytes.
  947. * @retval HAL status
  948. */
  949. HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  950. {
  951. return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
  952. }
  953. /**
  954. * @brief Return the computed digest in MD5 mode.
  955. * @note The API waits for DCIS to be set then reads the computed digest.
  956. * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
  957. * HMAC MD5 mode.
  958. * @param hhash HASH handle.
  959. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  960. * @param Timeout Timeout value.
  961. * @retval HAL status
  962. */
  963. HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
  964. {
  965. return HASH_Finish(hhash, pOutBuffer, Timeout);
  966. }
  967. /**
  968. * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
  969. * to feed the input buffer to the Peripheral.
  970. * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
  971. * be called to retrieve the computed digest.
  972. * @param hhash HASH handle.
  973. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  974. * @param Size length of the input buffer in bytes.
  975. * @retval HAL status
  976. */
  977. HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  978. {
  979. return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
  980. }
  981. /**
  982. * @brief Return the computed digest in SHA1 mode.
  983. * @note The API waits for DCIS to be set then reads the computed digest.
  984. * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
  985. * HMAC SHA1 mode.
  986. * @param hhash HASH handle.
  987. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  988. * @param Timeout Timeout value.
  989. * @retval HAL status
  990. */
  991. HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
  992. {
  993. return HASH_Finish(hhash, pOutBuffer, Timeout);
  994. }
  995. /**
  996. * @}
  997. */
  998. /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
  999. * @brief HMAC processing functions using polling mode.
  1000. *
  1001. @verbatim
  1002. ===============================================================================
  1003. ##### Polling mode HMAC processing functions #####
  1004. ===============================================================================
  1005. [..] This section provides functions allowing to calculate in polling mode
  1006. the HMAC value using one of the following algorithms:
  1007. (+) MD5
  1008. (++) HAL_HMAC_MD5_Start()
  1009. (+) SHA1
  1010. (++) HAL_HMAC_SHA1_Start()
  1011. @endverbatim
  1012. * @{
  1013. */
  1014. /**
  1015. * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
  1016. * read the computed digest.
  1017. * @note Digest is available in pOutBuffer.
  1018. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1019. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1020. * @param hhash HASH handle.
  1021. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1022. * @param Size length of the input buffer in bytes.
  1023. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  1024. * @param Timeout Timeout value.
  1025. * @retval HAL status
  1026. */
  1027. HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  1028. uint32_t Timeout)
  1029. {
  1030. return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
  1031. }
  1032. /**
  1033. * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
  1034. * read the computed digest.
  1035. * @note Digest is available in pOutBuffer.
  1036. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1037. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1038. * @param hhash HASH handle.
  1039. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1040. * @param Size length of the input buffer in bytes.
  1041. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  1042. * @param Timeout Timeout value.
  1043. * @retval HAL status
  1044. */
  1045. HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  1046. uint32_t Timeout)
  1047. {
  1048. return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
  1049. }
  1050. /**
  1051. * @}
  1052. */
  1053. /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
  1054. * @brief HMAC processing functions using interrupt mode.
  1055. *
  1056. @verbatim
  1057. ===============================================================================
  1058. ##### Interrupt mode HMAC processing functions #####
  1059. ===============================================================================
  1060. [..] This section provides functions allowing to calculate in interrupt mode
  1061. the HMAC value using one of the following algorithms:
  1062. (+) MD5
  1063. (++) HAL_HMAC_MD5_Start_IT()
  1064. (+) SHA1
  1065. (++) HAL_HMAC_SHA1_Start_IT()
  1066. @endverbatim
  1067. * @{
  1068. */
  1069. /**
  1070. * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
  1071. * read the computed digest in interrupt mode.
  1072. * @note Digest is available in pOutBuffer.
  1073. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1074. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1075. * @param hhash HASH handle.
  1076. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1077. * @param Size length of the input buffer in bytes.
  1078. * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
  1079. * @retval HAL status
  1080. */
  1081. HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  1082. uint8_t *pOutBuffer)
  1083. {
  1084. return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
  1085. }
  1086. /**
  1087. * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
  1088. * read the computed digest in interrupt mode.
  1089. * @note Digest is available in pOutBuffer.
  1090. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1091. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1092. * @param hhash HASH handle.
  1093. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1094. * @param Size length of the input buffer in bytes.
  1095. * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
  1096. * @retval HAL status
  1097. */
  1098. HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
  1099. uint8_t *pOutBuffer)
  1100. {
  1101. return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
  1102. }
  1103. /**
  1104. * @}
  1105. */
  1106. /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
  1107. * @brief HMAC processing functions using DMA modes.
  1108. *
  1109. @verbatim
  1110. ===============================================================================
  1111. ##### DMA mode HMAC processing functions #####
  1112. ===============================================================================
  1113. [..] This section provides functions allowing to calculate in DMA mode
  1114. the HMAC value using one of the following algorithms:
  1115. (+) MD5
  1116. (++) HAL_HMAC_MD5_Start_DMA()
  1117. (+) SHA1
  1118. (++) HAL_HMAC_SHA1_Start_DMA()
  1119. [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
  1120. user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest
  1121. with HAL_HASH_xxx_Finish().
  1122. @endverbatim
  1123. * @{
  1124. */
  1125. /**
  1126. * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
  1127. * DMA transfers to feed the key and the input buffer to the Peripheral.
  1128. * @note Once the DMA transfers are finished (indicated by hhash->State set back
  1129. * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
  1130. * the computed digest.
  1131. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1132. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1133. * @note If MDMAT bit is set before calling this function (multi-buffer
  1134. * HASH processing case), the input buffer size (in bytes) must be
  1135. * a multiple of 4 otherwise, the HASH digest computation is corrupted.
  1136. * For the processing of the last buffer of the thread, MDMAT bit must
  1137. * be reset and the buffer length (in bytes) doesn't have to be a
  1138. * multiple of 4.
  1139. * @param hhash HASH handle.
  1140. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1141. * @param Size length of the input buffer in bytes.
  1142. * @retval HAL status
  1143. */
  1144. HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  1145. {
  1146. return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
  1147. }
  1148. /**
  1149. * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
  1150. * DMA transfers to feed the key and the input buffer to the Peripheral.
  1151. * @note Once the DMA transfers are finished (indicated by hhash->State set back
  1152. * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
  1153. * the computed digest.
  1154. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  1155. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  1156. * @note If MDMAT bit is set before calling this function (multi-buffer
  1157. * HASH processing case), the input buffer size (in bytes) must be
  1158. * a multiple of 4 otherwise, the HASH digest computation is corrupted.
  1159. * For the processing of the last buffer of the thread, MDMAT bit must
  1160. * be reset and the buffer length (in bytes) doesn't have to be a
  1161. * multiple of 4.
  1162. * @param hhash HASH handle.
  1163. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  1164. * @param Size length of the input buffer in bytes.
  1165. * @retval HAL status
  1166. */
  1167. HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  1168. {
  1169. return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
  1170. }
  1171. /**
  1172. * @}
  1173. */
  1174. /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
  1175. * @brief Peripheral State functions.
  1176. *
  1177. @verbatim
  1178. ===============================================================================
  1179. ##### Peripheral State methods #####
  1180. ===============================================================================
  1181. [..]
  1182. This section permits to get in run-time the state and the peripheral handle
  1183. status of the peripheral:
  1184. (+) HAL_HASH_GetState()
  1185. (+) HAL_HASH_GetStatus()
  1186. [..]
  1187. Additionally, this subsection provides functions allowing to save and restore
  1188. the HASH or HMAC processing context in case of calculation suspension:
  1189. (+) HAL_HASH_ContextSaving()
  1190. (+) HAL_HASH_ContextRestoring()
  1191. [..]
  1192. This subsection provides functions allowing to suspend the HASH processing
  1193. (+) when input are fed to the Peripheral by software
  1194. (++) HAL_HASH_SwFeed_ProcessSuspend()
  1195. (+) when input are fed to the Peripheral by DMA
  1196. (++) HAL_HASH_DMAFeed_ProcessSuspend()
  1197. @endverbatim
  1198. * @{
  1199. */
  1200. /**
  1201. * @brief Return the HASH handle state.
  1202. * @note The API yields the current state of the handle (BUSY, READY,...).
  1203. * @param hhash HASH handle.
  1204. * @retval HAL HASH state
  1205. */
  1206. HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
  1207. {
  1208. return hhash->State;
  1209. }
  1210. /**
  1211. * @brief Return the HASH HAL status.
  1212. * @note The API yields the HAL status of the handle: it is the result of the
  1213. * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
  1214. * @param hhash HASH handle.
  1215. * @retval HAL status
  1216. */
  1217. HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
  1218. {
  1219. return hhash->Status;
  1220. }
  1221. /**
  1222. * @brief Save the HASH context in case of processing suspension.
  1223. * @param hhash HASH handle.
  1224. * @param pMemBuffer pointer to the memory buffer where the HASH context
  1225. * is saved.
  1226. * @note The IMR, STR, CR then all the CSR registers are saved
  1227. * in that order. Only the r/w bits are read to be restored later on.
  1228. * @note By default, all the context swap registers (there are
  1229. * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
  1230. * @note pMemBuffer points to a buffer allocated by the user. The buffer size
  1231. * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
  1232. * @retval None
  1233. */
  1234. void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
  1235. {
  1236. uint32_t mem_ptr = (uint32_t)pMemBuffer;
  1237. uint32_t csr_ptr = (uint32_t)HASH->CSR;
  1238. uint32_t i;
  1239. /* Prevent unused argument(s) compilation warning */
  1240. UNUSED(hhash);
  1241. /* Save IMR register content */
  1242. *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
  1243. mem_ptr += 4U;
  1244. /* Save STR register content */
  1245. *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
  1246. mem_ptr += 4U;
  1247. /* Save CR register content */
  1248. *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO |
  1249. HASH_CR_LKEY | HASH_CR_MDMAT);
  1250. mem_ptr += 4U;
  1251. /* By default, save all CSRs registers */
  1252. for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
  1253. {
  1254. *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
  1255. mem_ptr += 4U;
  1256. csr_ptr += 4U;
  1257. }
  1258. }
  1259. /**
  1260. * @brief Restore the HASH context in case of processing resumption.
  1261. * @param hhash HASH handle.
  1262. * @param pMemBuffer pointer to the memory buffer where the HASH context
  1263. * is stored.
  1264. * @note The IMR, STR, CR then all the CSR registers are restored
  1265. * in that order. Only the r/w bits are restored.
  1266. * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
  1267. * of those) are restored (all of them have been saved by default
  1268. * beforehand).
  1269. * @retval None
  1270. */
  1271. void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
  1272. {
  1273. uint32_t mem_ptr = (uint32_t)pMemBuffer;
  1274. uint32_t csr_ptr = (uint32_t)HASH->CSR;
  1275. uint32_t i;
  1276. /* Prevent unused argument(s) compilation warning */
  1277. UNUSED(hhash);
  1278. /* Restore IMR register content */
  1279. WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
  1280. mem_ptr += 4U;
  1281. /* Restore STR register content */
  1282. WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
  1283. mem_ptr += 4U;
  1284. /* Restore CR register content */
  1285. WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
  1286. mem_ptr += 4U;
  1287. /* Reset the HASH processor before restoring the Context
  1288. Swap Registers (CSR) */
  1289. __HAL_HASH_INIT();
  1290. /* By default, restore all CSR registers */
  1291. for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
  1292. {
  1293. WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
  1294. mem_ptr += 4U;
  1295. csr_ptr += 4U;
  1296. }
  1297. }
  1298. /**
  1299. * @brief Initiate HASH processing suspension when in polling or interruption mode.
  1300. * @param hhash HASH handle.
  1301. * @note Set the handle field SuspendRequest to the appropriate value so that
  1302. * the on-going HASH processing is suspended as soon as the required
  1303. * conditions are met. Note that the actual suspension is carried out
  1304. * by the functions HASH_WriteData() in polling mode and HASH_IT() in
  1305. * interruption mode.
  1306. * @retval None
  1307. */
  1308. void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
  1309. {
  1310. /* Set Handle Suspend Request field */
  1311. hhash->SuspendRequest = HAL_HASH_SUSPEND;
  1312. }
  1313. /**
  1314. * @brief Suspend the HASH processing when in DMA mode.
  1315. * @param hhash HASH handle.
  1316. * @note When suspension attempt occurs at the very end of a DMA transfer and
  1317. * all the data have already been entered in the Peripheral, hhash->State is
  1318. * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
  1319. * recommended to wrap-up the processing in reading the digest as usual.
  1320. * @retval HAL status
  1321. */
  1322. HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
  1323. {
  1324. uint32_t tmp_remaining_DMATransferSize_inWords;
  1325. uint32_t tmp_initial_DMATransferSize_inWords;
  1326. uint32_t tmp_words_already_pushed;
  1327. if (hhash->State == HAL_HASH_STATE_READY)
  1328. {
  1329. return HAL_ERROR;
  1330. }
  1331. else
  1332. {
  1333. /* Make sure there is enough time to suspend the processing */
  1334. tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
  1335. if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
  1336. {
  1337. /* No suspension attempted since almost to the end of the transferred data. */
  1338. /* Best option for user code is to wrap up low priority message hashing */
  1339. return HAL_ERROR;
  1340. }
  1341. /* Wait for BUSY flag to be reset */
  1342. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
  1343. {
  1344. return HAL_TIMEOUT;
  1345. }
  1346. if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
  1347. {
  1348. return HAL_ERROR;
  1349. }
  1350. /* Wait for BUSY flag to be set */
  1351. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
  1352. {
  1353. return HAL_TIMEOUT;
  1354. }
  1355. /* Disable DMA channel */
  1356. /* Note that the Abort function will
  1357. - Clear the transfer error flags
  1358. - Unlock
  1359. - Set the State
  1360. */
  1361. if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
  1362. {
  1363. return HAL_ERROR;
  1364. }
  1365. /* Clear DMAE bit */
  1366. CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
  1367. /* Wait for BUSY flag to be reset */
  1368. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
  1369. {
  1370. return HAL_TIMEOUT;
  1371. }
  1372. if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
  1373. {
  1374. return HAL_ERROR;
  1375. }
  1376. /* At this point, DMA interface is disabled and no transfer is on-going */
  1377. /* Retrieve from the DMA handle how many words remain to be written */
  1378. tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
  1379. if (tmp_remaining_DMATransferSize_inWords == 0U)
  1380. {
  1381. /* All the DMA transfer is actually done. Suspension occurred at the very end
  1382. of the transfer. Either the digest computation is about to start (HASH case)
  1383. or processing is about to move from one step to another (HMAC case).
  1384. In both cases, the processing can't be suspended at this point. It is
  1385. safer to
  1386. - retrieve the low priority block digest before starting the high
  1387. priority block processing (HASH case)
  1388. - re-attempt a new suspension (HMAC case)
  1389. */
  1390. return HAL_ERROR;
  1391. }
  1392. else
  1393. {
  1394. /* Compute how many words were supposed to be transferred by DMA */
  1395. tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
  1396. ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
  1397. /* If discrepancy between the number of words reported by DMA Peripheral and
  1398. the numbers of words entered as reported by HASH Peripheral, correct it */
  1399. /* tmp_words_already_pushed reflects the number of words that were already pushed before
  1400. the start of DMA transfer (multi-buffer processing case) */
  1401. tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
  1402. if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
  1403. tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
  1404. {
  1405. tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
  1406. }
  1407. /* Accordingly, update the input pointer that points at the next word to be
  1408. transferred to the Peripheral by DMA */
  1409. hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
  1410. /* And store in HashInCount the remaining size to transfer (in bytes) */
  1411. hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
  1412. }
  1413. /* Set State as suspended */
  1414. hhash->State = HAL_HASH_STATE_SUSPENDED;
  1415. return HAL_OK;
  1416. }
  1417. }
  1418. /**
  1419. * @brief Return the HASH handle error code.
  1420. * @param hhash pointer to a HASH_HandleTypeDef structure.
  1421. * @retval HASH Error Code
  1422. */
  1423. uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
  1424. {
  1425. /* Return HASH Error Code */
  1426. return hhash->ErrorCode;
  1427. }
  1428. /**
  1429. * @}
  1430. */
  1431. /**
  1432. * @}
  1433. */
  1434. /** @defgroup HASH_Private_Functions HASH Private Functions
  1435. * @{
  1436. */
  1437. /**
  1438. * @brief DMA HASH Input Data transfer completion callback.
  1439. * @param hdma DMA handle.
  1440. * @note In case of HMAC processing, HASH_DMAXferCplt() initiates
  1441. * the next DMA transfer for the following HMAC step.
  1442. * @retval None
  1443. */
  1444. static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
  1445. {
  1446. HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
  1447. uint32_t inputaddr;
  1448. uint32_t buffersize;
  1449. HAL_StatusTypeDef status;
  1450. if (hhash->State != HAL_HASH_STATE_SUSPENDED)
  1451. {
  1452. /* Disable the DMA transfer */
  1453. CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
  1454. if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
  1455. {
  1456. /* If no HMAC processing, input data transfer is now over */
  1457. /* Change the HASH state to ready */
  1458. hhash->State = HAL_HASH_STATE_READY;
  1459. /* Call Input data transfer complete call back */
  1460. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1461. hhash->InCpltCallback(hhash);
  1462. #else
  1463. HAL_HASH_InCpltCallback(hhash);
  1464. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1465. }
  1466. else
  1467. {
  1468. /* HMAC processing: depending on the current HMAC step and whether or
  1469. not multi-buffer processing is on-going, the next step is initiated
  1470. and MDMAT bit is set. */
  1471. if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
  1472. {
  1473. /* This is the end of HMAC processing */
  1474. /* Change the HASH state to ready */
  1475. hhash->State = HAL_HASH_STATE_READY;
  1476. /* Call Input data transfer complete call back
  1477. (note that the last DMA transfer was that of the key
  1478. for the outer HASH operation). */
  1479. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1480. hhash->InCpltCallback(hhash);
  1481. #else
  1482. HAL_HASH_InCpltCallback(hhash);
  1483. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1484. return;
  1485. }
  1486. else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
  1487. {
  1488. inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */
  1489. buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */
  1490. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
  1491. /* In case of suspension request, save the new starting parameters */
  1492. hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */
  1493. hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */
  1494. hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
  1495. /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
  1496. if (hhash->DigestCalculationDisable != RESET)
  1497. {
  1498. /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
  1499. no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
  1500. __HAL_HASH_SET_MDMAT();
  1501. }
  1502. }
  1503. else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
  1504. {
  1505. if (hhash->DigestCalculationDisable != RESET)
  1506. {
  1507. /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
  1508. (case of multi-buffer HMAC processing):
  1509. DCAL must not be set.
  1510. Phase remains in Step 2, MDMAT remains set at this point.
  1511. Change the HASH state to ready and call Input data transfer complete call back. */
  1512. hhash->State = HAL_HASH_STATE_READY;
  1513. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1514. hhash->InCpltCallback(hhash);
  1515. #else
  1516. HAL_HASH_InCpltCallback(hhash);
  1517. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1518. return ;
  1519. }
  1520. else
  1521. {
  1522. /* Digest calculation is not disabled (case of single buffer input or last buffer
  1523. of multi-buffer HMAC processing) */
  1524. inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */
  1525. buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */
  1526. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
  1527. /* In case of suspension request, save the new starting parameters */
  1528. hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */
  1529. hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */
  1530. hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
  1531. }
  1532. }
  1533. /* Configure the Number of valid bits in last word of the message */
  1534. __HAL_HASH_SET_NBVALIDBITS(buffersize);
  1535. /* Set the HASH DMA transfer completion call back */
  1536. hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
  1537. /* Enable the DMA In DMA channel */
  1538. status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
  1539. (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
  1540. (buffersize / 4U)));
  1541. /* Enable DMA requests */
  1542. SET_BIT(HASH->CR, HASH_CR_DMAE);
  1543. /* Return function status */
  1544. if (status != HAL_OK)
  1545. {
  1546. /* Update HASH state machine to error */
  1547. hhash->State = HAL_HASH_STATE_ERROR;
  1548. }
  1549. else
  1550. {
  1551. /* Change HASH state */
  1552. hhash->State = HAL_HASH_STATE_BUSY;
  1553. }
  1554. }
  1555. }
  1556. return;
  1557. }
  1558. /**
  1559. * @brief DMA HASH communication error callback.
  1560. * @param hdma DMA handle.
  1561. * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
  1562. * can contain user code to manage the error.
  1563. * @retval None
  1564. */
  1565. static void HASH_DMAError(DMA_HandleTypeDef *hdma)
  1566. {
  1567. HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
  1568. if (hhash->State != HAL_HASH_STATE_SUSPENDED)
  1569. {
  1570. hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
  1571. /* Set HASH state to ready to prevent any blocking issue in user code
  1572. present in HAL_HASH_ErrorCallback() */
  1573. hhash->State = HAL_HASH_STATE_READY;
  1574. /* Set HASH handle status to error */
  1575. hhash->Status = HAL_ERROR;
  1576. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1577. hhash->ErrorCallback(hhash);
  1578. #else
  1579. HAL_HASH_ErrorCallback(hhash);
  1580. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1581. /* After error handling by code user, reset HASH handle HAL status */
  1582. hhash->Status = HAL_OK;
  1583. }
  1584. }
  1585. /**
  1586. * @brief Feed the input buffer to the HASH Peripheral.
  1587. * @param hhash HASH handle.
  1588. * @param pInBuffer pointer to input buffer.
  1589. * @param Size the size of input buffer in bytes.
  1590. * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
  1591. * or not the HASH processing must be suspended. If this is the case, the
  1592. * processing is suspended when possible and the Peripheral feeding point reached at
  1593. * suspension time is stored in the handle for resumption later on.
  1594. * @retval HAL status
  1595. */
  1596. static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
  1597. {
  1598. uint32_t buffercounter;
  1599. __IO uint32_t inputaddr = (uint32_t) pInBuffer;
  1600. uint32_t tmp;
  1601. for (buffercounter = 0U; buffercounter < (Size / 4U); buffercounter++)
  1602. {
  1603. /* Write input data 4 bytes at a time */
  1604. HASH->DIN = *(uint32_t *)inputaddr;
  1605. inputaddr += 4U;
  1606. /* If the suspension flag has been raised and if the processing is not about
  1607. to end, suspend processing */
  1608. if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (((buffercounter * 4U) + 4U) < Size))
  1609. {
  1610. /* wait for flag BUSY not set before Wait for DINIS = 1*/
  1611. if ((buffercounter * 4U) >= 64U)
  1612. {
  1613. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
  1614. {
  1615. return HAL_TIMEOUT;
  1616. }
  1617. }
  1618. /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
  1619. in the input buffer */
  1620. if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
  1621. {
  1622. /* Reset SuspendRequest */
  1623. hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
  1624. /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
  1625. reached at suspension time is not saved in the same handle fields */
  1626. if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
  1627. {
  1628. /* Save current reading and writing locations of Input and Output buffers */
  1629. hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
  1630. /* Save the number of bytes that remain to be processed at this point */
  1631. hhash->HashInCount = Size - ((buffercounter * 4U) + 4U);
  1632. }
  1633. else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
  1634. {
  1635. /* Save current reading and writing locations of Input and Output buffers */
  1636. hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr;
  1637. /* Save the number of bytes that remain to be processed at this point */
  1638. hhash->HashKeyCount = Size - ((buffercounter * 4U) + 4U);
  1639. }
  1640. else
  1641. {
  1642. /* Unexpected phase: unlock process and report error */
  1643. hhash->State = HAL_HASH_STATE_READY;
  1644. __HAL_UNLOCK(hhash);
  1645. return HAL_ERROR;
  1646. }
  1647. /* Set the HASH state to Suspended and exit to stop entering data */
  1648. hhash->State = HAL_HASH_STATE_SUSPENDED;
  1649. return HAL_OK;
  1650. } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */
  1651. } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
  1652. } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */
  1653. /* At this point, all the data have been entered to the Peripheral: exit */
  1654. if ((Size % 4U) != 0U)
  1655. {
  1656. if (hhash->Init.DataType == HASH_DATATYPE_16B)
  1657. {
  1658. /* Write remaining input data */
  1659. if ((Size % 4U) <= 2U)
  1660. {
  1661. HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
  1662. }
  1663. if ((Size % 4U) == 3U)
  1664. {
  1665. HASH->DIN = *(uint32_t *)inputaddr;
  1666. }
  1667. }
  1668. else if ((hhash->Init.DataType == HASH_DATATYPE_8B)
  1669. || (hhash->Init.DataType == HASH_DATATYPE_1B)) /* byte swap or bit swap or */
  1670. {
  1671. /* Write remaining input data */
  1672. if ((Size % 4U) == 1U)
  1673. {
  1674. HASH->DIN = (uint32_t) * (uint8_t *)inputaddr;
  1675. }
  1676. if ((Size % 4U) == 2U)
  1677. {
  1678. HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
  1679. }
  1680. if ((Size % 4U) == 3U)
  1681. {
  1682. tmp = *(uint8_t *)inputaddr;
  1683. tmp |= (uint32_t)*(uint8_t *)(inputaddr + 1U) << 8U;
  1684. tmp |= (uint32_t)*(uint8_t *)(inputaddr + 2U) << 16U;
  1685. HASH->DIN = tmp;
  1686. }
  1687. }
  1688. else
  1689. {
  1690. HASH->DIN = *(uint32_t *)inputaddr;
  1691. }
  1692. /*hhash->HashInCount += 4U;*/
  1693. }
  1694. return HAL_OK;
  1695. }
  1696. /**
  1697. * @brief Retrieve the message digest.
  1698. * @param pMsgDigest pointer to the computed digest.
  1699. * @param Size message digest size in bytes.
  1700. * @retval None
  1701. */
  1702. static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
  1703. {
  1704. uint32_t msgdigest = (uint32_t)pMsgDigest;
  1705. switch (Size)
  1706. {
  1707. /* Read the message digest */
  1708. case 16: /* MD5 */
  1709. *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
  1710. msgdigest += 4U;
  1711. *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
  1712. msgdigest += 4U;
  1713. *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
  1714. msgdigest += 4U;
  1715. *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
  1716. break;
  1717. case 20: /* SHA1 */
  1718. *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
  1719. msgdigest += 4U;
  1720. *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
  1721. msgdigest += 4U;
  1722. *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
  1723. msgdigest += 4U;
  1724. *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
  1725. msgdigest += 4U;
  1726. *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
  1727. break;
  1728. case 28: /* SHA224 */
  1729. *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
  1730. msgdigest += 4U;
  1731. *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
  1732. msgdigest += 4U;
  1733. *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
  1734. msgdigest += 4U;
  1735. *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
  1736. msgdigest += 4U;
  1737. *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
  1738. msgdigest += 4U;
  1739. *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
  1740. msgdigest += 4U;
  1741. *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
  1742. break;
  1743. case 32: /* SHA256 */
  1744. *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
  1745. msgdigest += 4U;
  1746. *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
  1747. msgdigest += 4U;
  1748. *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
  1749. msgdigest += 4U;
  1750. *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
  1751. msgdigest += 4U;
  1752. *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
  1753. msgdigest += 4U;
  1754. *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
  1755. msgdigest += 4U;
  1756. *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
  1757. msgdigest += 4U;
  1758. *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
  1759. break;
  1760. default:
  1761. break;
  1762. }
  1763. }
  1764. /**
  1765. * @brief Handle HASH processing Timeout.
  1766. * @param hhash HASH handle.
  1767. * @param Flag specifies the HASH flag to check.
  1768. * @param Status the Flag status (SET or RESET).
  1769. * @param Timeout Timeout duration.
  1770. * @retval HAL status
  1771. */
  1772. static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
  1773. uint32_t Timeout)
  1774. {
  1775. uint32_t tickstart = HAL_GetTick();
  1776. /* Wait until flag is set */
  1777. if (Status == RESET)
  1778. {
  1779. while (__HAL_HASH_GET_FLAG(Flag) == RESET)
  1780. {
  1781. /* Check for the Timeout */
  1782. if (Timeout != HAL_MAX_DELAY)
  1783. {
  1784. if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
  1785. {
  1786. /* Set State to Ready to be able to restart later on */
  1787. hhash->State = HAL_HASH_STATE_READY;
  1788. /* Store time out issue in handle status */
  1789. hhash->Status = HAL_TIMEOUT;
  1790. /* Process Unlocked */
  1791. __HAL_UNLOCK(hhash);
  1792. return HAL_TIMEOUT;
  1793. }
  1794. }
  1795. }
  1796. }
  1797. else
  1798. {
  1799. while (__HAL_HASH_GET_FLAG(Flag) != RESET)
  1800. {
  1801. /* Check for the Timeout */
  1802. if (Timeout != HAL_MAX_DELAY)
  1803. {
  1804. if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
  1805. {
  1806. /* Set State to Ready to be able to restart later on */
  1807. hhash->State = HAL_HASH_STATE_READY;
  1808. /* Store time out issue in handle status */
  1809. hhash->Status = HAL_TIMEOUT;
  1810. /* Process Unlocked */
  1811. __HAL_UNLOCK(hhash);
  1812. return HAL_TIMEOUT;
  1813. }
  1814. }
  1815. }
  1816. }
  1817. return HAL_OK;
  1818. }
  1819. /**
  1820. * @brief HASH processing in interruption mode.
  1821. * @param hhash HASH handle.
  1822. * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether
  1823. * or not the HASH processing must be suspended. If this is the case, the
  1824. * processing is suspended when possible and the Peripheral feeding point reached at
  1825. * suspension time is stored in the handle for resumption later on.
  1826. * @retval HAL status
  1827. */
  1828. static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
  1829. {
  1830. if (hhash->State == HAL_HASH_STATE_BUSY)
  1831. {
  1832. /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
  1833. if (hhash->HashITCounter == 0U)
  1834. {
  1835. /* Disable Interrupts */
  1836. __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  1837. /* HASH state set back to Ready to prevent any issue in user code
  1838. present in HAL_HASH_ErrorCallback() */
  1839. hhash->State = HAL_HASH_STATE_READY;
  1840. return HAL_ERROR;
  1841. }
  1842. else if (hhash->HashITCounter == 1U)
  1843. {
  1844. /* This is the first call to HASH_IT, the first input data are about to be
  1845. entered in the Peripheral. A specific processing is carried out at this point to
  1846. start-up the processing. */
  1847. hhash->HashITCounter = 2U;
  1848. }
  1849. else
  1850. {
  1851. /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
  1852. the HASH processing or the end of the current step for HMAC processing. */
  1853. hhash->HashITCounter = 3U;
  1854. }
  1855. /* If digest is ready */
  1856. if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
  1857. {
  1858. /* Read the digest */
  1859. HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
  1860. /* Disable Interrupts */
  1861. __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  1862. /* Change the HASH state */
  1863. hhash->State = HAL_HASH_STATE_READY;
  1864. /* Reset HASH state machine */
  1865. hhash->Phase = HAL_HASH_PHASE_READY;
  1866. /* Call digest computation complete call back */
  1867. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1868. hhash->DgstCpltCallback(hhash);
  1869. #else
  1870. HAL_HASH_DgstCpltCallback(hhash);
  1871. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1872. return HAL_OK;
  1873. }
  1874. /* If Peripheral ready to accept new data */
  1875. if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
  1876. {
  1877. /* If the suspension flag has been raised and if the processing is not about
  1878. to end, suspend processing */
  1879. if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
  1880. {
  1881. /* Disable Interrupts */
  1882. __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  1883. /* Reset SuspendRequest */
  1884. hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
  1885. /* Change the HASH state */
  1886. hhash->State = HAL_HASH_STATE_SUSPENDED;
  1887. return HAL_OK;
  1888. }
  1889. /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
  1890. check whether the digest calculation has been triggered */
  1891. if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
  1892. {
  1893. /* Call Input data transfer complete call back
  1894. (called at the end of each step for HMAC) */
  1895. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  1896. hhash->InCpltCallback(hhash);
  1897. #else
  1898. HAL_HASH_InCpltCallback(hhash);
  1899. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  1900. if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
  1901. {
  1902. /* Wait until Peripheral is not busy anymore */
  1903. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
  1904. {
  1905. /* Disable Interrupts */
  1906. __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  1907. return HAL_TIMEOUT;
  1908. }
  1909. /* Initialization start for HMAC STEP 2 */
  1910. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
  1911. __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */
  1912. hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */
  1913. hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */
  1914. hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start
  1915. of a new phase */
  1916. __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
  1917. }
  1918. else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
  1919. {
  1920. /* Wait until Peripheral is not busy anymore */
  1921. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
  1922. {
  1923. /* Disable Interrupts */
  1924. __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  1925. return HAL_TIMEOUT;
  1926. }
  1927. /* Initialization start for HMAC STEP 3 */
  1928. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
  1929. __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */
  1930. hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */
  1931. hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */
  1932. hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start
  1933. of a new phase */
  1934. __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
  1935. }
  1936. else
  1937. {
  1938. /* Nothing to do */
  1939. }
  1940. } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
  1941. } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
  1942. /* Return function status */
  1943. return HAL_OK;
  1944. }
  1945. else
  1946. {
  1947. return HAL_BUSY;
  1948. }
  1949. }
  1950. /**
  1951. * @brief Write a block of data in HASH Peripheral in interruption mode.
  1952. * @param hhash HASH handle.
  1953. * @note HASH_Write_Block_Data() is called under interruption by HASH_IT().
  1954. * @retval HAL status
  1955. */
  1956. static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
  1957. {
  1958. uint32_t inputaddr;
  1959. uint32_t buffercounter;
  1960. uint32_t inputcounter;
  1961. uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
  1962. /* If there are more than 64 bytes remaining to be entered */
  1963. if (hhash->HashInCount > 64U)
  1964. {
  1965. inputaddr = (uint32_t)hhash->pHashInBuffPtr;
  1966. /* Write the Input block in the Data IN register
  1967. (16 32-bit words, or 64 bytes are entered) */
  1968. for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
  1969. {
  1970. HASH->DIN = *(uint32_t *)inputaddr;
  1971. inputaddr += 4U;
  1972. }
  1973. /* If this is the start of input data entering, an additional word
  1974. must be entered to start up the HASH processing */
  1975. if (hhash->HashITCounter == 2U)
  1976. {
  1977. HASH->DIN = *(uint32_t *)inputaddr;
  1978. if (hhash->HashInCount >= 68U)
  1979. {
  1980. /* There are still data waiting to be entered in the Peripheral.
  1981. Decrement buffer counter and set pointer to the proper
  1982. memory location for the next data entering round. */
  1983. hhash->HashInCount -= 68U;
  1984. hhash->pHashInBuffPtr += 68U;
  1985. }
  1986. else
  1987. {
  1988. /* All the input buffer has been fed to the HW. */
  1989. hhash->HashInCount = 0U;
  1990. }
  1991. }
  1992. else
  1993. {
  1994. /* 64 bytes have been entered and there are still some remaining:
  1995. Decrement buffer counter and set pointer to the proper
  1996. memory location for the next data entering round.*/
  1997. hhash->HashInCount -= 64U;
  1998. hhash->pHashInBuffPtr += 64U;
  1999. }
  2000. }
  2001. else
  2002. {
  2003. /* 64 or less bytes remain to be entered. This is the last
  2004. data entering round. */
  2005. /* Get the buffer address */
  2006. inputaddr = (uint32_t)hhash->pHashInBuffPtr;
  2007. /* Get the buffer counter */
  2008. inputcounter = hhash->HashInCount;
  2009. /* Disable Interrupts */
  2010. __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
  2011. /* Write the Input block in the Data IN register */
  2012. for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
  2013. {
  2014. HASH->DIN = *(uint32_t *)inputaddr;
  2015. inputaddr += 4U;
  2016. }
  2017. if (hhash->Accumulation == 1U)
  2018. {
  2019. /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
  2020. The digest computation will be started when the last buffer data are entered. */
  2021. /* Reset multi buffers accumulation flag */
  2022. hhash->Accumulation = 0U;
  2023. /* Change the HASH state */
  2024. hhash->State = HAL_HASH_STATE_READY;
  2025. /* Call Input data transfer complete call back */
  2026. #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
  2027. hhash->InCpltCallback(hhash);
  2028. #else
  2029. HAL_HASH_InCpltCallback(hhash);
  2030. #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
  2031. }
  2032. else
  2033. {
  2034. /* Start the Digest calculation */
  2035. __HAL_HASH_START_DIGEST();
  2036. /* Return indication that digest calculation has started:
  2037. this return value triggers the call to Input data transfer
  2038. complete call back as well as the proper transition from
  2039. one step to another in HMAC mode. */
  2040. ret = HASH_DIGEST_CALCULATION_STARTED;
  2041. }
  2042. /* Reset buffer counter */
  2043. hhash->HashInCount = 0;
  2044. }
  2045. /* Return whether or digest calculation has started */
  2046. return ret;
  2047. }
  2048. /**
  2049. * @brief HMAC processing in polling mode.
  2050. * @param hhash HASH handle.
  2051. * @param Timeout Timeout value.
  2052. * @retval HAL status
  2053. */
  2054. static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
  2055. {
  2056. /* Ensure first that Phase is correct */
  2057. if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
  2058. && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
  2059. {
  2060. /* Change the HASH state */
  2061. hhash->State = HAL_HASH_STATE_READY;
  2062. /* Process Unlock */
  2063. __HAL_UNLOCK(hhash);
  2064. /* Return function status */
  2065. return HAL_ERROR;
  2066. }
  2067. /* HMAC Step 1 processing */
  2068. if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
  2069. {
  2070. /************************** STEP 1 ******************************************/
  2071. /* Configure the Number of valid bits in last word of the message */
  2072. __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
  2073. /* Write input buffer in Data register */
  2074. hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
  2075. if (hhash->Status != HAL_OK)
  2076. {
  2077. return hhash->Status;
  2078. }
  2079. /* Check whether or not key entering process has been suspended */
  2080. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2081. {
  2082. /* Process Unlocked */
  2083. __HAL_UNLOCK(hhash);
  2084. /* Stop right there and return function status */
  2085. return HAL_OK;
  2086. }
  2087. /* No processing suspension at this point: set DCAL bit. */
  2088. __HAL_HASH_START_DIGEST();
  2089. /* Wait for BUSY flag to be cleared */
  2090. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
  2091. {
  2092. return HAL_TIMEOUT;
  2093. }
  2094. /* Move from Step 1 to Step 2 */
  2095. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
  2096. }
  2097. /* HMAC Step 2 processing.
  2098. After phase check, HMAC_Processing() may
  2099. - directly start up from this point in resumption case
  2100. if the same Step 2 processing was suspended previously
  2101. - or fall through from the Step 1 processing carried out hereabove */
  2102. if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
  2103. {
  2104. /************************** STEP 2 ******************************************/
  2105. /* Configure the Number of valid bits in last word of the message */
  2106. __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
  2107. /* Write input buffer in Data register */
  2108. hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
  2109. if (hhash->Status != HAL_OK)
  2110. {
  2111. return hhash->Status;
  2112. }
  2113. /* Check whether or not data entering process has been suspended */
  2114. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2115. {
  2116. /* Process Unlocked */
  2117. __HAL_UNLOCK(hhash);
  2118. /* Stop right there and return function status */
  2119. return HAL_OK;
  2120. }
  2121. /* No processing suspension at this point: set DCAL bit. */
  2122. __HAL_HASH_START_DIGEST();
  2123. /* Wait for BUSY flag to be cleared */
  2124. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
  2125. {
  2126. return HAL_TIMEOUT;
  2127. }
  2128. /* Move from Step 2 to Step 3 */
  2129. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
  2130. /* In case Step 1 phase was suspended then resumed,
  2131. set again Key input buffers and size before moving to
  2132. next step */
  2133. hhash->pHashKeyBuffPtr = hhash->Init.pKey;
  2134. hhash->HashKeyCount = hhash->Init.KeySize;
  2135. }
  2136. /* HMAC Step 3 processing.
  2137. After phase check, HMAC_Processing() may
  2138. - directly start up from this point in resumption case
  2139. if the same Step 3 processing was suspended previously
  2140. - or fall through from the Step 2 processing carried out hereabove */
  2141. if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
  2142. {
  2143. /************************** STEP 3 ******************************************/
  2144. /* Configure the Number of valid bits in last word of the message */
  2145. __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
  2146. /* Write input buffer in Data register */
  2147. hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
  2148. if (hhash->Status != HAL_OK)
  2149. {
  2150. return hhash->Status;
  2151. }
  2152. /* Check whether or not key entering process has been suspended */
  2153. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2154. {
  2155. /* Process Unlocked */
  2156. __HAL_UNLOCK(hhash);
  2157. /* Stop right there and return function status */
  2158. return HAL_OK;
  2159. }
  2160. /* No processing suspension at this point: start the Digest calculation. */
  2161. __HAL_HASH_START_DIGEST();
  2162. /* Wait for DCIS flag to be set */
  2163. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
  2164. {
  2165. return HAL_TIMEOUT;
  2166. }
  2167. /* Read the message digest */
  2168. HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
  2169. /* Reset HASH state machine */
  2170. hhash->Phase = HAL_HASH_PHASE_READY;
  2171. }
  2172. /* Change the HASH state */
  2173. hhash->State = HAL_HASH_STATE_READY;
  2174. /* Process Unlock */
  2175. __HAL_UNLOCK(hhash);
  2176. /* Return function status */
  2177. return HAL_OK;
  2178. }
  2179. /**
  2180. * @brief Initialize the HASH peripheral, next process pInBuffer then
  2181. * read the computed digest.
  2182. * @note Digest is available in pOutBuffer.
  2183. * @param hhash HASH handle.
  2184. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2185. * @param Size length of the input buffer in bytes.
  2186. * @param pOutBuffer pointer to the computed digest.
  2187. * @param Timeout Timeout value.
  2188. * @param Algorithm HASH algorithm.
  2189. * @retval HAL status
  2190. */
  2191. HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  2192. uint32_t Timeout, uint32_t Algorithm)
  2193. {
  2194. uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
  2195. uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
  2196. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2197. /* Initiate HASH processing in case of start or resumption */
  2198. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2199. {
  2200. /* Check input parameters */
  2201. if ((pInBuffer == NULL) || (pOutBuffer == NULL))
  2202. {
  2203. hhash->State = HAL_HASH_STATE_READY;
  2204. return HAL_ERROR;
  2205. }
  2206. /* Process Locked */
  2207. __HAL_LOCK(hhash);
  2208. /* Check if initialization phase has not been already performed */
  2209. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2210. {
  2211. /* Change the HASH state */
  2212. hhash->State = HAL_HASH_STATE_BUSY;
  2213. /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  2214. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
  2215. /* Configure the number of valid bits in last word of the message */
  2216. __HAL_HASH_SET_NBVALIDBITS(Size);
  2217. /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
  2218. input parameters of HASH_WriteData() */
  2219. pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
  2220. Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
  2221. /* Set the phase */
  2222. hhash->Phase = HAL_HASH_PHASE_PROCESS;
  2223. }
  2224. else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
  2225. {
  2226. /* if the Peripheral has already been initialized, two cases are possible */
  2227. /* Process resumption time ... */
  2228. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2229. {
  2230. /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
  2231. to the API input parameters but to those saved beforehand by HASH_WriteData()
  2232. when the processing was suspended */
  2233. pInBuffer_tmp = hhash->pHashInBuffPtr;
  2234. Size_tmp = hhash->HashInCount;
  2235. }
  2236. /* ... or multi-buffer HASH processing end */
  2237. else
  2238. {
  2239. /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
  2240. input parameters of HASH_WriteData() */
  2241. pInBuffer_tmp = pInBuffer;
  2242. Size_tmp = Size;
  2243. /* Configure the number of valid bits in last word of the message */
  2244. __HAL_HASH_SET_NBVALIDBITS(Size);
  2245. }
  2246. /* Change the HASH state */
  2247. hhash->State = HAL_HASH_STATE_BUSY;
  2248. }
  2249. else
  2250. {
  2251. /* Phase error */
  2252. hhash->State = HAL_HASH_STATE_READY;
  2253. /* Process Unlocked */
  2254. __HAL_UNLOCK(hhash);
  2255. /* Return function status */
  2256. return HAL_ERROR;
  2257. }
  2258. /* Write input buffer in Data register */
  2259. hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
  2260. if (hhash->Status != HAL_OK)
  2261. {
  2262. return hhash->Status;
  2263. }
  2264. /* If the process has not been suspended, carry on to digest calculation */
  2265. if (hhash->State != HAL_HASH_STATE_SUSPENDED)
  2266. {
  2267. /* Start the Digest calculation */
  2268. __HAL_HASH_START_DIGEST();
  2269. /* Wait for DCIS flag to be set */
  2270. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
  2271. {
  2272. return HAL_TIMEOUT;
  2273. }
  2274. /* Read the message digest */
  2275. HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
  2276. /* Change the HASH state */
  2277. hhash->State = HAL_HASH_STATE_READY;
  2278. /* Reset HASH state machine */
  2279. hhash->Phase = HAL_HASH_PHASE_READY;
  2280. }
  2281. /* Process Unlocked */
  2282. __HAL_UNLOCK(hhash);
  2283. /* Return function status */
  2284. return HAL_OK;
  2285. }
  2286. else
  2287. {
  2288. return HAL_BUSY;
  2289. }
  2290. }
  2291. /**
  2292. * @brief If not already done, initialize the HASH peripheral then
  2293. * processes pInBuffer.
  2294. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  2295. * the Peripheral has already been initialized.
  2296. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  2297. * HASH digest computation is corrupted.
  2298. * @param hhash HASH handle.
  2299. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2300. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  2301. * @param Algorithm HASH algorithm.
  2302. * @retval HAL status
  2303. */
  2304. HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
  2305. {
  2306. uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
  2307. uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
  2308. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2309. /* Make sure the input buffer size (in bytes) is a multiple of 4 */
  2310. if ((Size % 4U) != 0U)
  2311. {
  2312. return HAL_ERROR;
  2313. }
  2314. /* Initiate HASH processing in case of start or resumption */
  2315. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2316. {
  2317. /* Check input parameters */
  2318. if ((pInBuffer == NULL) || (Size == 0U))
  2319. {
  2320. hhash->State = HAL_HASH_STATE_READY;
  2321. return HAL_ERROR;
  2322. }
  2323. /* Process Locked */
  2324. __HAL_LOCK(hhash);
  2325. /* If resuming the HASH processing */
  2326. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2327. {
  2328. /* Change the HASH state */
  2329. hhash->State = HAL_HASH_STATE_BUSY;
  2330. /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
  2331. to the API input parameters but to those saved beforehand by HASH_WriteData()
  2332. when the processing was suspended */
  2333. pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */
  2334. Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */
  2335. }
  2336. else
  2337. {
  2338. /* Change the HASH state */
  2339. hhash->State = HAL_HASH_STATE_BUSY;
  2340. /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
  2341. input parameters of HASH_WriteData() */
  2342. pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
  2343. Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
  2344. /* Check if initialization phase has already be performed */
  2345. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2346. {
  2347. /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  2348. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
  2349. }
  2350. /* Set the phase */
  2351. hhash->Phase = HAL_HASH_PHASE_PROCESS;
  2352. }
  2353. /* Write input buffer in Data register */
  2354. hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
  2355. if (hhash->Status != HAL_OK)
  2356. {
  2357. return hhash->Status;
  2358. }
  2359. /* If the process has not been suspended, move the state to Ready */
  2360. if (hhash->State != HAL_HASH_STATE_SUSPENDED)
  2361. {
  2362. /* Change the HASH state */
  2363. hhash->State = HAL_HASH_STATE_READY;
  2364. }
  2365. /* Process Unlocked */
  2366. __HAL_UNLOCK(hhash);
  2367. /* Return function status */
  2368. return HAL_OK;
  2369. }
  2370. else
  2371. {
  2372. return HAL_BUSY;
  2373. }
  2374. }
  2375. /**
  2376. * @brief If not already done, initialize the HASH peripheral then
  2377. * processes pInBuffer in interruption mode.
  2378. * @note Field hhash->Phase of HASH handle is tested to check whether or not
  2379. * the Peripheral has already been initialized.
  2380. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
  2381. * HASH digest computation is corrupted.
  2382. * @param hhash HASH handle.
  2383. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2384. * @param Size length of the input buffer in bytes, must be a multiple of 4.
  2385. * @param Algorithm HASH algorithm.
  2386. * @retval HAL status
  2387. */
  2388. HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
  2389. {
  2390. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2391. __IO uint32_t inputaddr = (uint32_t) pInBuffer;
  2392. uint32_t SizeVar = Size;
  2393. /* Make sure the input buffer size (in bytes) is a multiple of 4 */
  2394. if ((Size % 4U) != 0U)
  2395. {
  2396. return HAL_ERROR;
  2397. }
  2398. /* Initiate HASH processing in case of start or resumption */
  2399. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2400. {
  2401. /* Check input parameters */
  2402. if ((pInBuffer == NULL) || (Size == 0U))
  2403. {
  2404. hhash->State = HAL_HASH_STATE_READY;
  2405. return HAL_ERROR;
  2406. }
  2407. /* Process Locked */
  2408. __HAL_LOCK(hhash);
  2409. /* If resuming the HASH processing */
  2410. if (hhash->State == HAL_HASH_STATE_SUSPENDED)
  2411. {
  2412. /* Change the HASH state */
  2413. hhash->State = HAL_HASH_STATE_BUSY;
  2414. }
  2415. else
  2416. {
  2417. /* Change the HASH state */
  2418. hhash->State = HAL_HASH_STATE_BUSY;
  2419. /* Check if initialization phase has already be performed */
  2420. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2421. {
  2422. /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  2423. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
  2424. hhash->HashITCounter = 1;
  2425. }
  2426. else
  2427. {
  2428. hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
  2429. }
  2430. /* Set the phase */
  2431. hhash->Phase = HAL_HASH_PHASE_PROCESS;
  2432. /* If DINIS is equal to 0 (for example if an incomplete block has been previously
  2433. fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
  2434. Therefore, first words are manually entered until DINIS raises, or until there
  2435. is not more data to enter. */
  2436. while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
  2437. {
  2438. /* Write input data 4 bytes at a time */
  2439. HASH->DIN = *(uint32_t *)inputaddr;
  2440. inputaddr += 4U;
  2441. SizeVar -= 4U;
  2442. }
  2443. /* If DINIS is still not set or if all the data have been fed, stop here */
  2444. if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
  2445. {
  2446. /* Change the HASH state */
  2447. hhash->State = HAL_HASH_STATE_READY;
  2448. /* Process Unlock */
  2449. __HAL_UNLOCK(hhash);
  2450. /* Return function status */
  2451. return HAL_OK;
  2452. }
  2453. /* otherwise, carry on in interrupt-mode */
  2454. hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
  2455. to be fed to the Peripheral */
  2456. hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at
  2457. the next interruption */
  2458. /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
  2459. the information describing where the HASH process is stopped.
  2460. These variables are used later on to resume the HASH processing at the
  2461. correct location. */
  2462. }
  2463. /* Set multi buffers accumulation flag */
  2464. hhash->Accumulation = 1U;
  2465. /* Process Unlock */
  2466. __HAL_UNLOCK(hhash);
  2467. /* Enable Data Input interrupt */
  2468. __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
  2469. /* Return function status */
  2470. return HAL_OK;
  2471. }
  2472. else
  2473. {
  2474. return HAL_BUSY;
  2475. }
  2476. }
  2477. /**
  2478. * @brief Initialize the HASH peripheral, next process pInBuffer then
  2479. * read the computed digest in interruption mode.
  2480. * @note Digest is available in pOutBuffer.
  2481. * @param hhash HASH handle.
  2482. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2483. * @param Size length of the input buffer in bytes.
  2484. * @param pOutBuffer pointer to the computed digest.
  2485. * @param Algorithm HASH algorithm.
  2486. * @retval HAL status
  2487. */
  2488. HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  2489. uint32_t Algorithm)
  2490. {
  2491. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2492. __IO uint32_t inputaddr = (uint32_t) pInBuffer;
  2493. uint32_t polling_step = 0U;
  2494. uint32_t initialization_skipped = 0U;
  2495. uint32_t SizeVar = Size;
  2496. /* If State is ready or suspended, start or resume IT-based HASH processing */
  2497. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2498. {
  2499. /* Check input parameters */
  2500. if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
  2501. {
  2502. hhash->State = HAL_HASH_STATE_READY;
  2503. return HAL_ERROR;
  2504. }
  2505. /* Process Locked */
  2506. __HAL_LOCK(hhash);
  2507. /* Change the HASH state */
  2508. hhash->State = HAL_HASH_STATE_BUSY;
  2509. /* Initialize IT counter */
  2510. hhash->HashITCounter = 1;
  2511. /* Check if initialization phase has already be performed */
  2512. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2513. {
  2514. /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  2515. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
  2516. /* Configure the number of valid bits in last word of the message */
  2517. __HAL_HASH_SET_NBVALIDBITS(SizeVar);
  2518. hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
  2519. to be fed to the Peripheral */
  2520. hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at
  2521. the next interruption */
  2522. /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
  2523. the information describing where the HASH process is stopped.
  2524. These variables are used later on to resume the HASH processing at the
  2525. correct location. */
  2526. hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
  2527. }
  2528. else
  2529. {
  2530. initialization_skipped = 1; /* info user later on in case of multi-buffer */
  2531. }
  2532. /* Set the phase */
  2533. hhash->Phase = HAL_HASH_PHASE_PROCESS;
  2534. /* If DINIS is equal to 0 (for example if an incomplete block has been previously
  2535. fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
  2536. Therefore, first words are manually entered until DINIS raises. */
  2537. while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
  2538. {
  2539. polling_step = 1U; /* note that some words are entered before enabling the interrupt */
  2540. /* Write input data 4 bytes at a time */
  2541. HASH->DIN = *(uint32_t *)inputaddr;
  2542. inputaddr += 4U;
  2543. SizeVar -= 4U;
  2544. }
  2545. if (polling_step == 1U)
  2546. {
  2547. if (SizeVar == 0U)
  2548. {
  2549. /* If all the data have been entered at this point, it only remains to
  2550. read the digest */
  2551. hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
  2552. /* Start the Digest calculation */
  2553. __HAL_HASH_START_DIGEST();
  2554. /* Process Unlock */
  2555. __HAL_UNLOCK(hhash);
  2556. /* Enable Interrupts */
  2557. __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
  2558. /* Return function status */
  2559. return HAL_OK;
  2560. }
  2561. else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
  2562. {
  2563. /* It remains data to enter and the Peripheral is ready to trigger DINIE,
  2564. carry on as usual.
  2565. Update HashInCount and pHashInBuffPtr accordingly. */
  2566. hhash->HashInCount = SizeVar;
  2567. hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
  2568. /* Update the configuration of the number of valid bits in last word of the message */
  2569. __HAL_HASH_SET_NBVALIDBITS(SizeVar);
  2570. hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
  2571. if (initialization_skipped == 1U)
  2572. {
  2573. hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
  2574. }
  2575. }
  2576. else
  2577. {
  2578. /* DINIS is not set but it remains a few data to enter (not enough for a full word).
  2579. Manually enter the last bytes before enabling DCIE. */
  2580. __HAL_HASH_SET_NBVALIDBITS(SizeVar);
  2581. HASH->DIN = *(uint32_t *)inputaddr;
  2582. /* Start the Digest calculation */
  2583. hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
  2584. __HAL_HASH_START_DIGEST();
  2585. /* Process Unlock */
  2586. __HAL_UNLOCK(hhash);
  2587. /* Enable Interrupts */
  2588. __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
  2589. /* Return function status */
  2590. return HAL_OK;
  2591. }
  2592. } /* if (polling_step == 1) */
  2593. /* Process Unlock */
  2594. __HAL_UNLOCK(hhash);
  2595. /* Enable Interrupts */
  2596. __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  2597. /* Return function status */
  2598. return HAL_OK;
  2599. }
  2600. else
  2601. {
  2602. return HAL_BUSY;
  2603. }
  2604. }
  2605. /**
  2606. * @brief Initialize the HASH peripheral then initiate a DMA transfer
  2607. * to feed the input buffer to the Peripheral.
  2608. * @note If MDMAT bit is set before calling this function (multi-buffer
  2609. * HASH processing case), the input buffer size (in bytes) must be
  2610. * a multiple of 4 otherwise, the HASH digest computation is corrupted.
  2611. * For the processing of the last buffer of the thread, MDMAT bit must
  2612. * be reset and the buffer length (in bytes) doesn't have to be a
  2613. * multiple of 4.
  2614. * @param hhash HASH handle.
  2615. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2616. * @param Size length of the input buffer in bytes.
  2617. * @param Algorithm HASH algorithm.
  2618. * @retval HAL status
  2619. */
  2620. HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
  2621. {
  2622. uint32_t inputaddr;
  2623. uint32_t inputSize;
  2624. HAL_StatusTypeDef status ;
  2625. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2626. #if defined (HASH_CR_MDMAT)
  2627. /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
  2628. (case of multi-buffer HASH processing) */
  2629. assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
  2630. #endif /* MDMA defined*/
  2631. /* If State is ready or suspended, start or resume polling-based HASH processing */
  2632. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2633. {
  2634. /* Check input parameters */
  2635. if ((pInBuffer == NULL) || (Size == 0U) ||
  2636. /* Check phase coherency. Phase must be
  2637. either READY (fresh start)
  2638. or PROCESS (multi-buffer HASH management) */
  2639. ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
  2640. {
  2641. hhash->State = HAL_HASH_STATE_READY;
  2642. return HAL_ERROR;
  2643. }
  2644. /* Process Locked */
  2645. __HAL_LOCK(hhash);
  2646. /* If not a resumption case */
  2647. if (hhash->State == HAL_HASH_STATE_READY)
  2648. {
  2649. /* Change the HASH state */
  2650. hhash->State = HAL_HASH_STATE_BUSY;
  2651. /* Check if initialization phase has already been performed.
  2652. If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
  2653. API is processing a new input data message in case of multi-buffer HASH
  2654. computation. */
  2655. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2656. {
  2657. /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  2658. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
  2659. /* Set the phase */
  2660. hhash->Phase = HAL_HASH_PHASE_PROCESS;
  2661. }
  2662. /* Configure the Number of valid bits in last word of the message */
  2663. __HAL_HASH_SET_NBVALIDBITS(Size);
  2664. inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */
  2665. inputSize = Size; /* DMA transfer size (in bytes) */
  2666. /* In case of suspension request, save the starting parameters */
  2667. hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */
  2668. hhash->HashInCount = Size; /* DMA transfer size (in bytes) */
  2669. }
  2670. /* If resumption case */
  2671. else
  2672. {
  2673. /* Change the HASH state */
  2674. hhash->State = HAL_HASH_STATE_BUSY;
  2675. /* Resumption case, inputaddr and inputSize are not set to the API input parameters
  2676. but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
  2677. processing was suspended */
  2678. inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */
  2679. inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */
  2680. }
  2681. /* Set the HASH DMA transfer complete callback */
  2682. hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
  2683. /* Set the DMA error callback */
  2684. hhash->hdmain->XferErrorCallback = HASH_DMAError;
  2685. /* Store number of words already pushed to manage proper DMA processing suspension */
  2686. hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
  2687. /* Enable the DMA In DMA channel */
  2688. status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
  2689. (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
  2690. (inputSize / 4U)));
  2691. /* Enable DMA requests */
  2692. SET_BIT(HASH->CR, HASH_CR_DMAE);
  2693. /* Process Unlock */
  2694. __HAL_UNLOCK(hhash);
  2695. /* Return function status */
  2696. if (status != HAL_OK)
  2697. {
  2698. /* Update HASH state machine to error */
  2699. hhash->State = HAL_HASH_STATE_ERROR;
  2700. }
  2701. return status;
  2702. }
  2703. else
  2704. {
  2705. return HAL_BUSY;
  2706. }
  2707. }
  2708. /**
  2709. * @brief Return the computed digest.
  2710. * @note The API waits for DCIS to be set then reads the computed digest.
  2711. * @param hhash HASH handle.
  2712. * @param pOutBuffer pointer to the computed digest.
  2713. * @param Timeout Timeout value.
  2714. * @retval HAL status
  2715. */
  2716. HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
  2717. {
  2718. if (hhash->State == HAL_HASH_STATE_READY)
  2719. {
  2720. /* Check parameter */
  2721. if (pOutBuffer == NULL)
  2722. {
  2723. return HAL_ERROR;
  2724. }
  2725. /* Process Locked */
  2726. __HAL_LOCK(hhash);
  2727. /* Change the HASH state to busy */
  2728. hhash->State = HAL_HASH_STATE_BUSY;
  2729. /* Wait for DCIS flag to be set */
  2730. if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
  2731. {
  2732. return HAL_TIMEOUT;
  2733. }
  2734. /* Read the message digest */
  2735. HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
  2736. /* Change the HASH state to ready */
  2737. hhash->State = HAL_HASH_STATE_READY;
  2738. /* Reset HASH state machine */
  2739. hhash->Phase = HAL_HASH_PHASE_READY;
  2740. /* Process UnLock */
  2741. __HAL_UNLOCK(hhash);
  2742. /* Return function status */
  2743. return HAL_OK;
  2744. }
  2745. else
  2746. {
  2747. return HAL_BUSY;
  2748. }
  2749. }
  2750. /**
  2751. * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
  2752. * read the computed digest.
  2753. * @note Digest is available in pOutBuffer.
  2754. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  2755. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  2756. * @param hhash HASH handle.
  2757. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2758. * @param Size length of the input buffer in bytes.
  2759. * @param pOutBuffer pointer to the computed digest.
  2760. * @param Timeout Timeout value.
  2761. * @param Algorithm HASH algorithm.
  2762. * @retval HAL status
  2763. */
  2764. HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  2765. uint32_t Timeout, uint32_t Algorithm)
  2766. {
  2767. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2768. /* If State is ready or suspended, start or resume polling-based HASH processing */
  2769. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2770. {
  2771. /* Check input parameters */
  2772. if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
  2773. || (pOutBuffer == NULL))
  2774. {
  2775. hhash->State = HAL_HASH_STATE_READY;
  2776. return HAL_ERROR;
  2777. }
  2778. /* Process Locked */
  2779. __HAL_LOCK(hhash);
  2780. /* Change the HASH state */
  2781. hhash->State = HAL_HASH_STATE_BUSY;
  2782. /* Check if initialization phase has already be performed */
  2783. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2784. {
  2785. /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
  2786. if (hhash->Init.KeySize > 64U)
  2787. {
  2788. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2789. Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
  2790. }
  2791. else
  2792. {
  2793. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2794. Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
  2795. }
  2796. /* Set the phase to Step 1 */
  2797. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
  2798. /* Resort to hhash internal fields to feed the Peripheral.
  2799. Parameters will be updated in case of suspension to contain the proper
  2800. information at resumption time. */
  2801. hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
  2802. hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input
  2803. parameter for Step 2 */
  2804. hhash->HashInCount = Size; /* Input data size, HMAC_Processing input
  2805. parameter for Step 2 */
  2806. hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process*/
  2807. hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step
  2808. 1 and Step 3 */
  2809. hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1
  2810. and Step 3 */
  2811. }
  2812. /* Carry out HMAC processing */
  2813. return HMAC_Processing(hhash, Timeout);
  2814. }
  2815. else
  2816. {
  2817. return HAL_BUSY;
  2818. }
  2819. }
  2820. /**
  2821. * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
  2822. * read the computed digest in interruption mode.
  2823. * @note Digest is available in pOutBuffer.
  2824. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  2825. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  2826. * @param hhash HASH handle.
  2827. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2828. * @param Size length of the input buffer in bytes.
  2829. * @param pOutBuffer pointer to the computed digest.
  2830. * @param Algorithm HASH algorithm.
  2831. * @retval HAL status
  2832. */
  2833. HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
  2834. uint32_t Algorithm)
  2835. {
  2836. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2837. /* If State is ready or suspended, start or resume IT-based HASH processing */
  2838. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2839. {
  2840. /* Check input parameters */
  2841. if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
  2842. || (pOutBuffer == NULL))
  2843. {
  2844. hhash->State = HAL_HASH_STATE_READY;
  2845. return HAL_ERROR;
  2846. }
  2847. /* Process Locked */
  2848. __HAL_LOCK(hhash);
  2849. /* Change the HASH state */
  2850. hhash->State = HAL_HASH_STATE_BUSY;
  2851. /* Initialize IT counter */
  2852. hhash->HashITCounter = 1;
  2853. /* Check if initialization phase has already be performed */
  2854. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2855. {
  2856. /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
  2857. if (hhash->Init.KeySize > 64U)
  2858. {
  2859. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2860. Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
  2861. }
  2862. else
  2863. {
  2864. MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2865. Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
  2866. }
  2867. /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
  2868. to feed the Peripheral whatever the HMAC step.
  2869. Lines below are set to start HMAC Step 1 processing where key is entered first. */
  2870. hhash->HashInCount = hhash->Init.KeySize; /* Key size */
  2871. hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */
  2872. /* Store input and output parameters in handle fields to manage steps transition
  2873. or possible HMAC suspension/resumption */
  2874. hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
  2875. hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */
  2876. hhash->HashBuffSize = Size; /* Input message size (in bytes) */
  2877. hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
  2878. /* Configure the number of valid bits in last word of the key */
  2879. __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
  2880. /* Set the phase to Step 1 */
  2881. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
  2882. }
  2883. else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
  2884. {
  2885. /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
  2886. }
  2887. else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
  2888. {
  2889. /* Restart IT-based HASH processing after Step 2 suspension */
  2890. }
  2891. else
  2892. {
  2893. /* Error report as phase incorrect */
  2894. /* Process Unlock */
  2895. __HAL_UNLOCK(hhash);
  2896. hhash->State = HAL_HASH_STATE_READY;
  2897. return HAL_ERROR;
  2898. }
  2899. /* Process Unlock */
  2900. __HAL_UNLOCK(hhash);
  2901. /* Enable Interrupts */
  2902. __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
  2903. /* Return function status */
  2904. return HAL_OK;
  2905. }
  2906. else
  2907. {
  2908. return HAL_BUSY;
  2909. }
  2910. }
  2911. /**
  2912. * @brief Initialize the HASH peripheral in HMAC mode then initiate the required
  2913. * DMA transfers to feed the key and the input buffer to the Peripheral.
  2914. * @note Same key is used for the inner and the outer hash functions; pointer to key and
  2915. * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
  2916. * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
  2917. * be a multiple of 4 otherwise, the HASH digest computation is corrupted.
  2918. * Only the length of the last buffer of the thread doesn't have to be a
  2919. * multiple of 4.
  2920. * @param hhash HASH handle.
  2921. * @param pInBuffer pointer to the input buffer (buffer to be hashed).
  2922. * @param Size length of the input buffer in bytes.
  2923. * @param Algorithm HASH algorithm.
  2924. * @retval HAL status
  2925. */
  2926. HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
  2927. {
  2928. uint32_t inputaddr;
  2929. uint32_t inputSize;
  2930. HAL_StatusTypeDef status ;
  2931. HAL_HASH_StateTypeDef State_tmp = hhash->State;
  2932. /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
  2933. is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
  2934. assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
  2935. /* If State is ready or suspended, start or resume DMA-based HASH processing */
  2936. if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  2937. {
  2938. /* Check input parameters */
  2939. if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
  2940. /* Check phase coherency. Phase must be
  2941. either READY (fresh start)
  2942. or one of HMAC PROCESS steps (multi-buffer HASH management) */
  2943. ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
  2944. {
  2945. hhash->State = HAL_HASH_STATE_READY;
  2946. return HAL_ERROR;
  2947. }
  2948. /* Process Locked */
  2949. __HAL_LOCK(hhash);
  2950. /* If not a case of resumption after suspension */
  2951. if (hhash->State == HAL_HASH_STATE_READY)
  2952. {
  2953. /* Check whether or not initialization phase has already be performed */
  2954. if (hhash->Phase == HAL_HASH_PHASE_READY)
  2955. {
  2956. /* Change the HASH state */
  2957. hhash->State = HAL_HASH_STATE_BUSY;
  2958. /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
  2959. At the same time, ensure MDMAT bit is cleared. */
  2960. if (hhash->Init.KeySize > 64U)
  2961. {
  2962. MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2963. Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
  2964. }
  2965. else
  2966. {
  2967. MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
  2968. Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
  2969. }
  2970. /* Store input aparameters in handle fields to manage steps transition
  2971. or possible HMAC suspension/resumption */
  2972. hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */
  2973. hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
  2974. hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
  2975. hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */
  2976. hhash->HashBuffSize = Size; /* input data size (in bytes) */
  2977. /* Set DMA input parameters */
  2978. inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */
  2979. inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */
  2980. /* Configure the number of valid bits in last word of the key */
  2981. __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
  2982. /* Set the phase to Step 1 */
  2983. hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
  2984. }
  2985. else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
  2986. {
  2987. /* Process a new input data message in case of multi-buffer HMAC processing
  2988. (this is not a resumption case) */
  2989. /* Change the HASH state */
  2990. hhash->State = HAL_HASH_STATE_BUSY;
  2991. /* Save input parameters to be able to manage possible suspension/resumption */
  2992. hhash->HashInCount = Size; /* Input message address */
  2993. hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */
  2994. /* Set DMA input parameters */
  2995. inputaddr = (uint32_t)pInBuffer; /* Input message address */
  2996. inputSize = Size; /* Input message size in bytes */
  2997. if (hhash->DigestCalculationDisable == RESET)
  2998. {
  2999. /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
  3000. __HAL_HASH_RESET_MDMAT();
  3001. __HAL_HASH_SET_NBVALIDBITS(inputSize);
  3002. }
  3003. }
  3004. else
  3005. {
  3006. /* Phase not aligned with handle READY state */
  3007. __HAL_UNLOCK(hhash);
  3008. /* Return function status */
  3009. return HAL_ERROR;
  3010. }
  3011. }
  3012. else
  3013. {
  3014. /* Resumption case (phase may be Step 1, 2 or 3) */
  3015. /* Change the HASH state */
  3016. hhash->State = HAL_HASH_STATE_BUSY;
  3017. /* Set DMA input parameters at resumption location;
  3018. inputaddr and inputSize are not set to the API input parameters
  3019. but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
  3020. processing was suspended. */
  3021. inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */
  3022. inputSize = hhash->HashInCount; /* Input message size in bytes */
  3023. }
  3024. /* Set the HASH DMA transfer complete callback */
  3025. hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
  3026. /* Set the DMA error callback */
  3027. hhash->hdmain->XferErrorCallback = HASH_DMAError;
  3028. /* Store number of words already pushed to manage proper DMA processing suspension */
  3029. hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
  3030. /* Enable the DMA In DMA channel */
  3031. status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
  3032. (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
  3033. : (inputSize / 4U)));
  3034. /* Enable DMA requests */
  3035. SET_BIT(HASH->CR, HASH_CR_DMAE);
  3036. /* Process Unlocked */
  3037. __HAL_UNLOCK(hhash);
  3038. /* Return function status */
  3039. if (status != HAL_OK)
  3040. {
  3041. /* Update HASH state machine to error */
  3042. hhash->State = HAL_HASH_STATE_ERROR;
  3043. }
  3044. /* Return function status */
  3045. return status;
  3046. }
  3047. else
  3048. {
  3049. return HAL_BUSY;
  3050. }
  3051. }
  3052. /**
  3053. * @}
  3054. */
  3055. #endif /* HAL_HASH_MODULE_ENABLED */
  3056. /**
  3057. * @}
  3058. */
  3059. #endif /* HASH*/
  3060. /**
  3061. * @}
  3062. */