wolfCrypt.cs 115 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971
  1. /* wolfCrypt.cs
  2. *
  3. * Copyright (C) 2006-2024 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. using System;
  22. using System.Runtime.InteropServices;
  23. using System.Security.Cryptography;
  24. using System.Text;
  25. namespace wolfSSL.CSharp
  26. {
  27. public class wolfcrypt
  28. {
  29. private const string wolfssl_dll = "wolfssl.dll";
  30. /********************************
  31. * Init wolfSSL library
  32. */
  33. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  34. private extern static int wolfCrypt_Init();
  35. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  36. private extern static int wolfCrypt_Cleanup();
  37. /********************************
  38. * Random
  39. */
  40. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  41. private extern static IntPtr wc_rng_new(IntPtr nonce, UInt32 nonceSz, IntPtr heap);
  42. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  43. private extern static void wc_rng_free(IntPtr rng);
  44. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  45. private extern static int wc_RNG_GenerateBlock(IntPtr rng, IntPtr output, UInt32 sz);
  46. /********************************
  47. * ECC
  48. */
  49. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  50. private extern static IntPtr wc_ecc_key_new(IntPtr heap);
  51. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  52. private extern static void wc_ecc_key_free(IntPtr key);
  53. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  54. private extern static int wc_ecc_set_rng(IntPtr key, IntPtr rng);
  55. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  56. private extern static int wc_ecc_make_key_ex(IntPtr rng, int keysize, IntPtr key, int curve_id);
  57. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  58. private extern static int wc_ecc_sign_hash(IntPtr hashPtr, uint hashlen, IntPtr sigPtr, IntPtr siglen, IntPtr rng, IntPtr key);
  59. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  60. private extern static int wc_ecc_verify_hash(IntPtr sigPtr, uint siglen, IntPtr hashPtr, uint hashlen, IntPtr res, IntPtr key);
  61. /* ASN.1 DER format */
  62. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  63. private extern static int wc_EccPrivateKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz);
  64. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  65. private static extern int wc_EccPublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz);
  66. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  67. private static extern int wc_EccPrivateKeyToDer(IntPtr key, byte[] output, uint inLen);
  68. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  69. private static extern int wc_EccPublicKeyToDer(IntPtr key, byte[] output, uint inLen, int with_AlgCurve);
  70. /********************************
  71. * ECIES
  72. */
  73. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  74. private extern static IntPtr wc_ecc_ctx_new(int flags, IntPtr rng);
  75. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  76. private extern static IntPtr wc_ecc_ctx_new_ex(int flags, IntPtr rng, IntPtr heap);
  77. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  78. private extern static void wc_ecc_ctx_free(IntPtr ctx);
  79. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  80. private extern static int wc_ecc_ctx_reset(IntPtr ctx, IntPtr rng);
  81. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  82. private extern static int wc_ecc_ctx_set_algo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo);
  83. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  84. private extern static IntPtr wc_ecc_ctx_get_own_salt(IntPtr ctx);
  85. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  86. private extern static int wc_ecc_ctx_set_peer_salt(IntPtr ctx, IntPtr salt);
  87. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  88. private extern static int wc_ecc_ctx_set_own_salt(IntPtr ctx, IntPtr salt, uint sz);
  89. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  90. private extern static int wc_ecc_ctx_set_kdf_salt(IntPtr ctx, IntPtr salt, uint sz);
  91. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  92. private extern static int wc_ecc_ctx_set_info(IntPtr ctx, IntPtr info, int sz);
  93. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  94. private extern static int wc_ecc_encrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx);
  95. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  96. private extern static int wc_ecc_encrypt_ex(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx, int compressed);
  97. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  98. private extern static int wc_ecc_decrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx);
  99. /********************************
  100. * ECDHE
  101. */
  102. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  103. private extern static int wc_ecc_shared_secret(IntPtr privateKey, IntPtr publicKey, byte[] outSharedSecret, ref int outlen);
  104. /********************************
  105. * RSA
  106. */
  107. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  108. private static extern IntPtr wc_NewRsaKey(IntPtr heap, int devId, IntPtr result_code);
  109. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  110. private static extern int wc_DeleteRsaKey(IntPtr key, IntPtr key_p);
  111. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  112. private extern static int wc_InitRsaKey(IntPtr key, IntPtr heap);
  113. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  114. private extern static void wc_FreeRsaKey(IntPtr key);
  115. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  116. private extern static int wc_MakeRsaKey(IntPtr key, int keysize, Int32 exponent, IntPtr rng);
  117. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  118. private extern static int wc_RsaSSL_Sign(IntPtr hashPtr, int hashLen, IntPtr sigPtr, int sigLen, IntPtr key, IntPtr rng);
  119. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  120. private extern static int wc_RsaSSL_Verify(IntPtr sigPtr, int sigLen, IntPtr hashPtr, int hashLen, IntPtr key);
  121. /* ASN.1 DER format */
  122. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  123. private extern static int wc_RsaPublicEncrypt(IntPtr inPtr, int inLen, IntPtr outPtr, int outLen, IntPtr key);
  124. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  125. private extern static int wc_RsaPrivateDecrypt(IntPtr inPtr, int inLen, IntPtr outPtr, int outLen, IntPtr key);
  126. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  127. private extern static int wc_RsaPrivateKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz);
  128. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  129. private extern static int wc_RsaPublicKeyDecode(IntPtr keyBuf, IntPtr idx, IntPtr key, uint keyBufSz);
  130. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  131. private extern static int wc_RsaPSS_Sign(IntPtr hashPtr, int hashLen, IntPtr sigPtr, int sigLen, int hashType, IntPtr rng, IntPtr key);
  132. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  133. private extern static int wc_RsaPSS_Verify(IntPtr sigPtr, int sigLen, IntPtr hashPtr, int hashLen, int hashType, IntPtr key);
  134. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  135. private extern static int wc_RsaPSS_CheckPadding(IntPtr sigPtr, int sigLen, int hashType, IntPtr key);
  136. /********************************
  137. * ED25519
  138. */
  139. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  140. private static extern IntPtr wc_ed25519_new(IntPtr heap, int devId, IntPtr result_code);
  141. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  142. private static extern int wc_ed25519_delete(IntPtr key, IntPtr key_p);
  143. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  144. private static extern int wc_ed25519_init(IntPtr key);
  145. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  146. private static extern void wc_ed25519_free(IntPtr key);
  147. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  148. private static extern int wc_ed25519_make_key(IntPtr rng, int keysize, IntPtr key);
  149. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  150. private static extern int wc_ed25519_sign_msg(IntPtr inMsg, uint inlen, IntPtr outMsg, ref uint outlen, IntPtr key);
  151. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  152. private static extern int wc_ed25519_verify_msg(IntPtr sig, uint siglen, IntPtr msg, uint msgLen, ref int ret, IntPtr key);
  153. /* ASN.1 DER format */
  154. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  155. private static extern int wc_Ed25519PrivateKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz);
  156. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  157. private static extern int wc_Ed25519PublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz);
  158. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  159. private static extern int wc_Ed25519KeyToDer(IntPtr key, byte[] output, uint inLen);
  160. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  161. private static extern int wc_Ed25519PrivateKeyToDer(IntPtr key, byte[] output, uint inLen);
  162. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  163. private static extern int wc_Ed25519PublicKeyToDer(IntPtr key, byte[] output, uint inLen, int withAlg);
  164. /* RAW format */
  165. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  166. private static extern int wc_ed25519_make_public(IntPtr key, IntPtr pubKey, uint pubKeySz);
  167. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  168. private static extern int wc_ed25519_import_public(IntPtr inMsg, uint inLen, IntPtr key);
  169. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  170. private static extern int wc_ed25519_export_public(IntPtr key, IntPtr outMsg, ref uint outLen);
  171. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  172. private static extern int wc_ed25519_export_private(IntPtr key, IntPtr outMsg, ref uint outLen);
  173. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  174. private static extern int wc_ed25519_size(IntPtr key);
  175. /********************************
  176. * Curve25519
  177. */
  178. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  179. private static extern IntPtr wc_curve25519_new(IntPtr heap, int devId, IntPtr result_code);
  180. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  181. private static extern int wc_curve25519_delete(IntPtr key, IntPtr key_p);
  182. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  183. private extern static int wc_curve25519_init(IntPtr key);
  184. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  185. private extern static void wc_curve25519_free(IntPtr key);
  186. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  187. private extern static int wc_curve25519_make_key(IntPtr rng, int keysize, IntPtr key);
  188. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  189. private extern static int wc_curve25519_shared_secret(IntPtr privateKey, IntPtr publicKey, byte[] outSharedSecret, ref int outlen);
  190. /* ASN.1 DER format */
  191. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  192. private static extern int wc_Curve25519PrivateKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz);
  193. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  194. private static extern int wc_Curve25519PublicKeyDecode(byte[] input, ref uint inOutIdx, IntPtr key, uint inSz);
  195. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  196. private static extern int wc_Curve25519PrivateKeyToDer(IntPtr key, byte[] output, uint inLen);
  197. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  198. private static extern int wc_Curve25519PublicKeyToDer(IntPtr key, byte[] output, uint inLen, int withAlg);
  199. /* RAW format */
  200. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  201. private extern static int wc_curve25519_import_private(IntPtr privKey, int privKeySz, IntPtr key);
  202. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  203. private static extern int wc_curve25519_export_public(IntPtr key, byte[] outBuffer, ref uint outLen);
  204. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  205. private extern static int wc_curve25519_import_public(IntPtr pubKey, int pubKeySz, IntPtr key);
  206. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  207. private extern static int wc_curve25519_export_public(IntPtr key, IntPtr outPubKey, ref int outlen);
  208. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  209. private static extern int wc_curve25519_export_key_raw(IntPtr key, byte[] priv, ref uint privSz, byte[] pub, ref uint pubSz);
  210. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  211. private extern static int wc_curve25519_import_private_raw(IntPtr privKey, IntPtr pubKey, IntPtr key);
  212. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  213. private extern static int wc_curve25519_export_private_raw(IntPtr key, IntPtr outPrivKey, IntPtr outPubKey);
  214. /********************************
  215. * AES-GCM
  216. */
  217. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  218. private extern static IntPtr wc_AesNew(IntPtr heap, int devId, IntPtr result_code);
  219. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  220. private extern static int wc_AesDelete(IntPtr aes, IntPtr aes_p);
  221. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  222. private extern static int wc_AesFree(IntPtr aes);
  223. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  224. private extern static int wc_AesInit(IntPtr aes, IntPtr heap, int devId);
  225. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  226. private extern static int wc_AesGcmInit(IntPtr aes, IntPtr key, uint len, IntPtr iv, uint ivSz);
  227. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  228. private extern static int wc_AesGcmSetKey(IntPtr aes, IntPtr key, uint len);
  229. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  230. private extern static int wc_AesGcmEncrypt(IntPtr aes, IntPtr output, IntPtr input, uint sz, IntPtr iv, uint ivSz, IntPtr authTag, uint authTagSz, IntPtr authIn, uint authInSz);
  231. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  232. private extern static int wc_AesGcmDecrypt(IntPtr aes, IntPtr output, IntPtr input, uint sz, IntPtr iv, uint ivSz, IntPtr authTag, uint authTagSz, IntPtr authIn, uint authInSz);
  233. /********************************
  234. * HASH
  235. */
  236. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  237. private extern static IntPtr wc_HashNew(uint hashType, IntPtr heap, int devId, IntPtr result_code);
  238. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  239. private extern static int wc_HashDelete(IntPtr hash, IntPtr hash_p);
  240. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  241. private extern static int wc_HashInit(IntPtr hash, uint hashType);
  242. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  243. private extern static int wc_HashUpdate(IntPtr hash, uint hashType, IntPtr data, uint dataSz);
  244. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  245. private extern static int wc_HashFinal(IntPtr hash, uint hashType, IntPtr output);
  246. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  247. private extern static int wc_HashFree(IntPtr hash, uint hashType);
  248. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  249. private extern static int wc_HashGetDigestSize(uint hashType);
  250. /********************************
  251. * Logging
  252. */
  253. [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
  254. private extern static IntPtr wc_GetErrorString(int error);
  255. public delegate void loggingCb(int lvl, StringBuilder msg);
  256. private static loggingCb internal_log;
  257. /// <summary>
  258. /// Log a message to set logging function
  259. /// </summary>
  260. /// <param name="lvl">Level of log message</param>
  261. /// <param name="msg">Message to log</param>
  262. private static void log(int lvl, string msg)
  263. {
  264. /* if log is not set then print nothing */
  265. if (internal_log == null)
  266. return;
  267. StringBuilder ptr = new StringBuilder(msg);
  268. internal_log(lvl, ptr);
  269. }
  270. /********************************
  271. * Enum types from wolfSSL library
  272. */
  273. /* Logging levels */
  274. public static readonly int ERROR_LOG = 0;
  275. public static readonly int INFO_LOG = 1;
  276. public static readonly int ENTER_LOG = 2;
  277. public static readonly int LEAVE_LOG = 3;
  278. public static readonly int OTHER_LOG = 4;
  279. public static readonly int INVALID_DEVID = -2;
  280. public static readonly int ECC_MAX_SIG_SIZE = 141; /* ECC max sig size */
  281. public static readonly int ECC_KEY_SIZE = 32; /* ECC key size */
  282. public static readonly int MAX_ECIES_TEST_SZ = 200; /* ECIES max sig size */
  283. public static readonly int ED25519_SIG_SIZE = 64; /* ED25519 pub + priv */
  284. public static readonly int ED25519_KEY_SIZE = 32; /* Private key only */
  285. public static readonly int ED25519_PUB_KEY_SIZE = 32; /* Compressed public */
  286. public static readonly int AES_128_KEY_SIZE = 16; /* for 128 bit */
  287. public static readonly int AES_192_KEY_SIZE = 24; /* for 192 bit */
  288. public static readonly int AES_256_KEY_SIZE = 32; /* for 256 bit */
  289. public static readonly int AES_BLOCK_SIZE = 16;
  290. /* Error codes */
  291. public static readonly int SUCCESS = 0;
  292. public static readonly int SIG_VERIFY_E = -229; /* wolfcrypt signature verify error */
  293. public static readonly int MEMORY_E = -125; /* Out of memory error */
  294. public static readonly int EXCEPTION_E = -1;
  295. public static readonly int BUFFER_E = -131; /* RSA buffer error, output too small/large */
  296. /***********************************************************************
  297. * Class Public Functions
  298. **********************************************************************/
  299. /// <summary>
  300. /// Initialize wolfCrypt library
  301. /// </summary>
  302. /// <returns>0 on success</returns>
  303. public static int Init()
  304. {
  305. int ret;
  306. try
  307. {
  308. ret = wolfCrypt_Init();
  309. }
  310. catch (Exception e)
  311. {
  312. log(ERROR_LOG, "wolfCrypt init error " + e.ToString());
  313. ret = EXCEPTION_E;
  314. }
  315. return ret;
  316. }
  317. /// <summary>
  318. /// Clean up wolfCrypt library memory
  319. /// </summary>
  320. /// <returns>0 on success</returns>
  321. public static int Cleanup()
  322. {
  323. int ret;
  324. try
  325. {
  326. ret = wolfCrypt_Cleanup();
  327. }
  328. catch (Exception e)
  329. {
  330. log(ERROR_LOG, "wolfCrypt cleanup error " + e.ToString());
  331. ret = EXCEPTION_E;
  332. }
  333. return ret;
  334. }
  335. /***********************************************************************
  336. * Random
  337. **********************************************************************/
  338. /// <summary>
  339. /// Create new WC_RNG context
  340. /// </summary>
  341. /// <returns>Pointer to allocated WC_RNG or null</returns>
  342. public static IntPtr RandomNew()
  343. {
  344. IntPtr rng;
  345. try
  346. {
  347. /* Allocate and init new WC_RNG structure */
  348. rng = wc_rng_new(
  349. IntPtr.Zero, 0, /* Nonce (optional / used by FIPS only) */
  350. IntPtr.Zero); /* Heap hint for static memory only */
  351. }
  352. catch (Exception e)
  353. {
  354. log(ERROR_LOG, "random new exception " + e.ToString());
  355. rng = IntPtr.Zero;
  356. }
  357. return rng;
  358. }
  359. /// <summary>
  360. /// Free WC_RNG context
  361. /// </summary>
  362. /// <param name="rng">Pointer to allocated WC_RNG</param>
  363. public static void RandomFree(IntPtr rng)
  364. {
  365. if (rng != IntPtr.Zero)
  366. {
  367. /* Free WC_RNG structure */
  368. wc_rng_free(rng);
  369. }
  370. }
  371. /// <summary>
  372. /// Generate random data (use existing WC_RNG context)
  373. /// </summary>
  374. /// <param name="rng">WC_RNG created from RandomNew()</param>
  375. /// <param name="buf">buffer to populate random data</param>
  376. /// <param name="sz">size of buffer</param>
  377. /// <returns>0=success or negative for error</returns>
  378. public static int Random(IntPtr rng, byte[] buf, int sz)
  379. {
  380. int ret;
  381. IntPtr data;
  382. try
  383. {
  384. /* Allocate global buffer for wolfAPI random */
  385. data = Marshal.AllocHGlobal(sz);
  386. if (data != IntPtr.Zero)
  387. {
  388. /* Generate random block */
  389. ret = wc_RNG_GenerateBlock(rng, data, Convert.ToUInt32(sz));
  390. if (ret == 0)
  391. {
  392. /* copy returned data */
  393. Marshal.Copy(data, buf, 0, sz);
  394. }
  395. else
  396. {
  397. log(ERROR_LOG, "random generate block error " + ret + ": " + GetError(ret));
  398. }
  399. Marshal.FreeHGlobal(data);
  400. }
  401. else
  402. {
  403. ret = MEMORY_E;
  404. }
  405. }
  406. catch (Exception e)
  407. {
  408. log(ERROR_LOG, "random generate block exception " + e.ToString());
  409. ret = EXCEPTION_E;
  410. }
  411. return ret;
  412. }
  413. /// <summary>
  414. /// Generate random data (single shot)
  415. /// </summary>
  416. /// <param name="buf">buffer to populate random data</param>
  417. /// <param name="sz">size of buffer</param>
  418. /// <returns>0=success or negative for error</returns>
  419. public static int Random(byte[] buf, int sz)
  420. {
  421. int ret;
  422. IntPtr rng = RandomNew();
  423. if (rng == IntPtr.Zero)
  424. {
  425. return MEMORY_E;
  426. }
  427. ret = Random(rng, buf, sz);
  428. RandomFree(rng);
  429. return ret;
  430. }
  431. /* END Random */
  432. /***********************************************************************
  433. * ECC
  434. **********************************************************************/
  435. /// <summary>
  436. /// Generate a new ECC private / public key pair
  437. /// </summary>
  438. /// <param name="keysize">Key size in bytes (example: SECP256R1 = 32)</param>
  439. /// <returns>Allocated ECC key structure or null</returns>
  440. public static IntPtr EccMakeKey(int keysize, IntPtr rng)
  441. {
  442. int ret;
  443. IntPtr key = IntPtr.Zero;
  444. try
  445. {
  446. /* Allocate and init new WC_RNG structure */
  447. key = wc_ecc_key_new(IntPtr.Zero);
  448. if (key != IntPtr.Zero)
  449. {
  450. ret = wc_ecc_make_key_ex(rng, keysize, key, 0); /* 0=use default curve */
  451. if (ret != 0)
  452. {
  453. EccFreeKey(key);
  454. key = IntPtr.Zero;
  455. }
  456. }
  457. }
  458. catch (Exception e)
  459. {
  460. log(ERROR_LOG, "ECC make key exception " + e.ToString());
  461. EccFreeKey(key);
  462. key = IntPtr.Zero;
  463. }
  464. return key;
  465. }
  466. /// <summary>
  467. /// Sets the ECC rng structure
  468. /// </summary>
  469. /// <param name="key">Supplied key as a pointer</param>
  470. /// <param name="rng">rng context as a pointer</param>
  471. /// <returns>Returns 0 on success</returns>
  472. public static int EccSetRng(IntPtr key, IntPtr rng)
  473. {
  474. int ret = 0;
  475. try
  476. {
  477. /* Check */
  478. if (key == IntPtr.Zero)
  479. {
  480. log(ERROR_LOG, "Invalid key or rng pointer.");
  481. return MEMORY_E;
  482. }
  483. /* Set ECC rng */
  484. ret = wc_ecc_set_rng(key, rng);
  485. if (ret != 0)
  486. {
  487. log(ERROR_LOG, "ECC set rng failed returned:" + ret);
  488. }
  489. }
  490. catch (Exception e)
  491. {
  492. log(ERROR_LOG, "ECC set rng exception " + e.ToString());
  493. }
  494. return ret;
  495. }
  496. /// <summary>
  497. /// Generate a new ECC private / public key pair
  498. /// </summary>
  499. /// <param name="keyASN1">ASN.1 private key buffer (see ecc_clikey_der_256)</param>
  500. /// <returns>Allocated ECC key structure or null</returns>
  501. public static IntPtr EccImportKey(byte[] keyASN1)
  502. {
  503. int ret;
  504. IntPtr key = IntPtr.Zero;
  505. try
  506. {
  507. key = wc_ecc_key_new(IntPtr.Zero);
  508. if (key != IntPtr.Zero)
  509. {
  510. IntPtr idx = Marshal.AllocHGlobal(sizeof(uint));
  511. IntPtr keydata = Marshal.AllocHGlobal(keyASN1.Length);
  512. Marshal.WriteInt32(idx, 0);
  513. Marshal.Copy(keyASN1, 0, keydata, keyASN1.Length);
  514. ret = wc_EccPrivateKeyDecode(keydata, idx, key, Convert.ToUInt32(keyASN1.Length));
  515. if (ret != 0)
  516. {
  517. EccFreeKey(key);
  518. key = IntPtr.Zero;
  519. }
  520. Marshal.FreeHGlobal(idx); /* not used */
  521. Marshal.FreeHGlobal(keydata);
  522. }
  523. }
  524. catch (Exception e)
  525. {
  526. log(ERROR_LOG, "ECC import key exception " + e.ToString());
  527. EccFreeKey(key); /* make sure its free'd */
  528. key = IntPtr.Zero;
  529. }
  530. return key;
  531. }
  532. /// <summary>
  533. /// Sign a hash using ECC
  534. /// </summary>
  535. /// <param name="key">ECC key structure</param>
  536. /// <param name="hash">Hash to sign</param>
  537. /// <param name="signature">Buffer to receive the signature</param>
  538. /// <returns>Length of the signature on success, otherwise a negative error code</returns>
  539. public static int EccSign(IntPtr key, byte[] hash, byte[] signature)
  540. {
  541. int ret;
  542. int signedLength = 0;
  543. IntPtr hashPtr = IntPtr.Zero;
  544. IntPtr sigPtr = IntPtr.Zero;
  545. IntPtr sigLen = IntPtr.Zero;
  546. IntPtr rng = IntPtr.Zero;
  547. try
  548. {
  549. rng = RandomNew();
  550. hashPtr = Marshal.AllocHGlobal(hash.Length);
  551. sigPtr = Marshal.AllocHGlobal(signature.Length);
  552. sigLen = Marshal.AllocHGlobal(sizeof(uint));
  553. Marshal.WriteInt32(sigLen, signature.Length);
  554. Marshal.Copy(hash, 0, hashPtr, hash.Length);
  555. ret = wc_ecc_sign_hash(hashPtr, Convert.ToUInt32(hash.Length), sigPtr, sigLen, rng, key);
  556. /* Output actual signature length */
  557. if (ret == 0)
  558. {
  559. signedLength = Marshal.ReadInt32(sigLen);
  560. if (signedLength <= signature.Length)
  561. {
  562. Marshal.Copy(sigPtr, signature, 0, signedLength);
  563. }
  564. else
  565. {
  566. ret = BUFFER_E;
  567. }
  568. }
  569. }
  570. catch (Exception e)
  571. {
  572. log(ERROR_LOG, "ECC sign exception: " + e.ToString());
  573. ret = EXCEPTION_E;
  574. }
  575. finally
  576. {
  577. if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr);
  578. if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr);
  579. if (sigLen != IntPtr.Zero) Marshal.FreeHGlobal(sigLen);
  580. if (rng != IntPtr.Zero) RandomFree(rng);
  581. }
  582. return ret == 0 ? signedLength : ret;
  583. }
  584. /// <summary>
  585. /// Verify a signature using ECC
  586. /// </summary>
  587. /// <param name="key">ECC key structure</param>
  588. /// <param name="signature">Signature to verify</param>
  589. /// <param name="hash">Expected hash value</param>
  590. /// <returns>0 on success, otherwise an error code</returns>
  591. public static int EccVerify(IntPtr key, byte[] signature, byte[] hash)
  592. {
  593. int ret;
  594. IntPtr hashPtr = IntPtr.Zero;
  595. IntPtr sigPtr = IntPtr.Zero;
  596. IntPtr res = IntPtr.Zero;
  597. try
  598. {
  599. hashPtr = Marshal.AllocHGlobal(hash.Length);
  600. sigPtr = Marshal.AllocHGlobal(signature.Length);
  601. res = Marshal.AllocHGlobal(sizeof(int));
  602. Marshal.Copy(hash, 0, hashPtr, hash.Length);
  603. Marshal.Copy(signature, 0, sigPtr, signature.Length);
  604. ret = wc_ecc_verify_hash(sigPtr, Convert.ToUInt32(signature.Length), hashPtr, Convert.ToUInt32(hash.Length), res, key);
  605. if (ret == 0)
  606. {
  607. int verifyResult = Marshal.ReadInt32(res);
  608. ret = verifyResult == 1 ? 0 : EXCEPTION_E;
  609. }
  610. }
  611. catch (Exception e)
  612. {
  613. log(ERROR_LOG, "ECC verify exception " + e.ToString());
  614. ret = EXCEPTION_E;
  615. }
  616. finally
  617. {
  618. if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr);
  619. if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr);
  620. if (res != IntPtr.Zero) Marshal.FreeHGlobal(res);
  621. }
  622. return ret;
  623. }
  624. /// <summary>
  625. /// Export ECC Private Key to DER format
  626. /// </summary>
  627. /// <param name="key">ECC key structure</param>
  628. /// <returns>DER-encoded private key as byte array</returns>
  629. public static int EccExportPrivateKeyToDer(IntPtr key, out byte[] derKey)
  630. {
  631. int ret;
  632. derKey = null;
  633. try
  634. {
  635. int bufferSize = wc_EccPrivateKeyToDer(key, null, 0);
  636. if (bufferSize < 0) {
  637. log(ERROR_LOG, "ECC private key get size failed " + bufferSize.ToString());
  638. return bufferSize;
  639. }
  640. derKey = new byte[bufferSize];
  641. ret = wc_EccPrivateKeyToDer(key, derKey, (uint)bufferSize);
  642. if (ret < 0)
  643. {
  644. log(ERROR_LOG, "ECC private key to der failed " + ret.ToString());
  645. }
  646. }
  647. catch (Exception e)
  648. {
  649. log(ERROR_LOG, "ECC export private exception " + e.ToString());
  650. ret = EXCEPTION_E;
  651. }
  652. return ret;
  653. }
  654. /// <summary>
  655. /// Export ECC Public Key to DER format
  656. /// </summary>
  657. /// <param name="key">ECC key structure</param>
  658. /// <param name="includeCurve">Include algorithm curve in the output</param>
  659. /// <returns>DER-encoded public key as byte array</returns>
  660. public static int EccExportPublicKeyToDer(IntPtr key, out byte[] derKey, bool includeCurve)
  661. {
  662. int ret;
  663. derKey = null;
  664. try
  665. {
  666. int bufferSize = wc_EccPublicKeyToDer(key, null, 0, includeCurve ? 1 : 0);
  667. if (bufferSize < 0) {
  668. log(ERROR_LOG, "ECC public key get size failed " + bufferSize.ToString());
  669. return bufferSize;
  670. }
  671. derKey = new byte[bufferSize];
  672. ret = wc_EccPublicKeyToDer(key, derKey, (uint)bufferSize, includeCurve ? 1 : 0);
  673. if (ret < 0)
  674. {
  675. log(ERROR_LOG, "ECC public key to der failed " + ret.ToString());
  676. }
  677. }
  678. catch (Exception e)
  679. {
  680. log(ERROR_LOG, "ECC export public exception " + e.ToString());
  681. ret = EXCEPTION_E;
  682. }
  683. return ret;
  684. }
  685. /// <summary>
  686. /// Import ECC Public Key from DER format
  687. /// </summary>
  688. /// <param name="keyDer">DER-encoded public key</param>
  689. /// <returns>Allocated ECC key structure or null</returns>
  690. public static IntPtr EccImportPublicKeyFromDer(byte[] keyDer)
  691. {
  692. int ret;
  693. IntPtr key = IntPtr.Zero;
  694. try
  695. {
  696. key = wc_ecc_key_new(IntPtr.Zero);
  697. if (key != IntPtr.Zero)
  698. {
  699. uint idx = 0;
  700. ret = wc_EccPublicKeyDecode(keyDer, ref idx, key, (uint)keyDer.Length);
  701. if (ret != 0)
  702. {
  703. EccFreeKey(key);
  704. key = IntPtr.Zero;
  705. }
  706. }
  707. }
  708. catch (Exception e)
  709. {
  710. log(ERROR_LOG, "ECC import public key exception " + e.ToString());
  711. EccFreeKey(key);
  712. key = IntPtr.Zero;
  713. }
  714. return key;
  715. }
  716. /// <summary>
  717. /// Free an ECC key structure
  718. /// </summary>
  719. /// <param name="key">ECC key structure allocated using EccMakeKey() or EccImportKey()</param>
  720. public static void EccFreeKey(IntPtr key)
  721. {
  722. if (key != IntPtr.Zero)
  723. {
  724. wc_ecc_key_free(key);
  725. }
  726. }
  727. /* END ECC */
  728. /***********************************************************************
  729. * ECIES
  730. **********************************************************************/
  731. /// <summary>
  732. /// Create a new ECIES context with flags, RNG, and custom heap.
  733. /// </summary>
  734. /// <param name="flags">Flags for the context initialization.</param>
  735. /// <param name="rng">Random Number Generator (RNG) pointer.</param>
  736. /// <param name="heap">Custom heap pointer for memory allocations.</param>
  737. /// <returns>Pointer to the newly created ECIES context or IntPtr.Zero on failure.</returns>
  738. public static IntPtr EciesNewCtx(int flags, IntPtr rng, IntPtr heap)
  739. {
  740. IntPtr ctx = IntPtr.Zero;
  741. heap = IntPtr.Zero;
  742. try
  743. {
  744. ctx = wc_ecc_ctx_new_ex(flags, rng, heap);
  745. if (ctx == IntPtr.Zero)
  746. {
  747. log(ERROR_LOG, "ECIES context creation with custom heap failed: returned IntPtr.Zero");
  748. }
  749. }
  750. catch (Exception e)
  751. {
  752. log(ERROR_LOG, "ECIES context creation with custom heap failed: " + e.ToString());
  753. return IntPtr.Zero;
  754. }
  755. return ctx;
  756. }
  757. /// <summary>
  758. /// Reset the ECIES context with a new RNG.
  759. /// </summary>
  760. /// <param name="ctx">Pointer to the ECIES context to reset.</param>
  761. /// <param name="rng">New RNG to set.</param>
  762. /// <returns>0 on success, or a negative error code on failure.</returns>
  763. public static int EciesCtxReset(IntPtr ctx, IntPtr rng)
  764. {
  765. int ret;
  766. try
  767. {
  768. ret = wc_ecc_ctx_reset(ctx, rng);
  769. }
  770. catch (Exception e)
  771. {
  772. log(ERROR_LOG, "ECIES context reset exception: " + e.ToString());
  773. ret = EXCEPTION_E;
  774. }
  775. return ret;
  776. }
  777. /// <summary>
  778. /// Set encryption, KDF, and MAC algorithms for the ECIES context.
  779. /// </summary>
  780. /// <param name="ctx">Pointer to the ECIES context.</param>
  781. /// <param name="encAlgo">Encryption algorithm identifier.</param>
  782. /// <param name="kdfAlgo">Key Derivation Function (KDF) algorithm identifier.</param>
  783. /// <param name="macAlgo">MAC algorithm identifier.</param>
  784. /// <returns>0 on success, or a negative error code on failure.</returns>
  785. public static int EciesSetAlgo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo)
  786. {
  787. int ret;
  788. try
  789. {
  790. ret = wc_ecc_ctx_set_algo(ctx, encAlgo, kdfAlgo, macAlgo);
  791. }
  792. catch (Exception e)
  793. {
  794. log(ERROR_LOG, "ECIES set algorithm exception: " + e.ToString());
  795. ret = EXCEPTION_E;
  796. }
  797. return ret;
  798. }
  799. /// <summary>
  800. /// Get the ECIES own salt as a byte array.
  801. /// </summary>
  802. /// <param name="ctx">Pointer to the ECIES context.</param>
  803. /// <returns>Byte array representing the own salt, or null if there is an error.</returns>
  804. public static byte[] EciesGetOwnSalt(IntPtr ctx)
  805. {
  806. IntPtr saltPtr = IntPtr.Zero;
  807. byte[] salt = null;
  808. try
  809. {
  810. /* Check ctx */
  811. if (ctx == IntPtr.Zero)
  812. {
  813. log(ERROR_LOG, "Invalid ECIES context pointer.");
  814. return null;
  815. }
  816. /* Get own salt */
  817. saltPtr = wc_ecc_ctx_get_own_salt(ctx);
  818. if (saltPtr == IntPtr.Zero)
  819. {
  820. log(ERROR_LOG, "Failed to get own salt.");
  821. return null;
  822. }
  823. /* Allocate salt size and copy to byte array */
  824. salt = new byte[(int)ecKeySize.EXCHANGE_SALT_SZ];
  825. Marshal.Copy(saltPtr, salt, 0, (int)ecKeySize.EXCHANGE_SALT_SZ);
  826. }
  827. catch (Exception e)
  828. {
  829. log(ERROR_LOG, "ECIES get own salt exception: " + e.ToString());
  830. return null;
  831. }
  832. finally
  833. {
  834. /* Cleanup */
  835. if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
  836. }
  837. return salt;
  838. }
  839. /// <summary>
  840. /// Set the peer salt for the ECIES context.
  841. /// </summary>
  842. /// <param name="ctx">Pointer to the ECIES context.</param>
  843. /// <param name="salt">Peer salt as a byte array.</param>
  844. /// <returns>0 on success, or a negative error code on failure.</returns>
  845. public static int EciesSetPeerSalt(IntPtr ctx, byte[] salt)
  846. {
  847. IntPtr saltPtr = IntPtr.Zero;
  848. int ret;
  849. try
  850. {
  851. /* Allocate memory */
  852. saltPtr = Marshal.AllocHGlobal(salt.Length);
  853. Marshal.Copy(salt, 0, saltPtr, salt.Length);
  854. /* Set the peer salt */
  855. ret = wc_ecc_ctx_set_peer_salt(ctx, saltPtr);
  856. }
  857. catch (Exception e)
  858. {
  859. log(ERROR_LOG, "ECIES set peer salt exception: " + e.ToString());
  860. ret = EXCEPTION_E;
  861. }
  862. finally
  863. {
  864. /* Cleanup */
  865. if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
  866. }
  867. return ret;
  868. }
  869. /// <summary>
  870. /// Set the own salt for the ECIES context.
  871. /// </summary>
  872. /// <param name="ctx">Pointer to the ECIES context.</param>
  873. /// <param name="salt">Own salt as a byte array.</param>
  874. /// <returns>0 on success, or a negative error code on failure.</returns>
  875. public static int EciesSetOwnSalt(IntPtr ctx, byte[] salt)
  876. {
  877. IntPtr saltPtr = IntPtr.Zero;
  878. uint saltSz;
  879. int ret;
  880. try
  881. {
  882. /* Allocate memory */
  883. saltSz = (uint)salt.Length;
  884. saltPtr = Marshal.AllocHGlobal(salt.Length);
  885. Marshal.Copy(salt, 0, saltPtr, salt.Length);
  886. /* Set the own salt */
  887. ret = wc_ecc_ctx_set_own_salt(ctx, saltPtr, saltSz);
  888. }
  889. catch (Exception e)
  890. {
  891. log(ERROR_LOG, "ECIES set own salt exception: " + e.ToString());
  892. ret = EXCEPTION_E;
  893. }
  894. finally
  895. {
  896. /* Cleanup */
  897. if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
  898. }
  899. return ret;
  900. }
  901. /// <summary>
  902. /// Set the KDF salt for the ECIES context.
  903. /// </summary>
  904. /// <param name="ctx">Pointer to the ECIES context.</param>
  905. /// <param name="salt">KDF salt as a byte array.</param>
  906. /// <returns>0 on success, or a negative error code on failure.</returns>
  907. public static int EciesSetKdfSalt(IntPtr ctx, byte[] salt)
  908. {
  909. IntPtr saltPtr = IntPtr.Zero;
  910. uint saltSz;
  911. int ret;
  912. try
  913. {
  914. /* Allocate memory */
  915. saltSz = (uint)salt.Length;
  916. saltPtr = Marshal.AllocHGlobal(salt.Length);
  917. Marshal.Copy(salt, 0, saltPtr, salt.Length);
  918. /* Set the KDF salt */
  919. ret = wc_ecc_ctx_set_kdf_salt(ctx, saltPtr, saltSz);
  920. }
  921. catch (Exception e)
  922. {
  923. log(ERROR_LOG, "ECIES set KDF salt exception: " + e.ToString());
  924. ret = EXCEPTION_E;
  925. }
  926. finally
  927. {
  928. /* Cleanup */
  929. if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
  930. }
  931. return ret;
  932. }
  933. /// <summary>
  934. /// Set the info for the ECIES context.
  935. /// </summary>
  936. /// <param name="ctx">Pointer to the ECIES context.</param>
  937. /// <param name="info">Info as a byte array.</param>
  938. /// <returns>0 on success, or a negative error code on failure.</returns>
  939. public static int EciesSetInfo(IntPtr ctx, byte[] info)
  940. {
  941. IntPtr infoPtr = IntPtr.Zero;
  942. int ret;
  943. try
  944. {
  945. /* Allocate memory */
  946. infoPtr = Marshal.AllocHGlobal(info.Length);
  947. Marshal.Copy(info, 0, infoPtr, info.Length);
  948. /* Set the info */
  949. ret = wc_ecc_ctx_set_info(ctx, infoPtr, info.Length);
  950. }
  951. catch (Exception e)
  952. {
  953. log(ERROR_LOG, "ECIES set info exception: " + e.ToString());
  954. ret = EXCEPTION_E;
  955. }
  956. finally
  957. {
  958. /* Cleanup */
  959. if (infoPtr != IntPtr.Zero) Marshal.FreeHGlobal(infoPtr);
  960. }
  961. return ret;
  962. }
  963. /// <summary>
  964. /// Encrypt a message using ECIES.
  965. /// </summary>
  966. /// <param name="privKey">Private key.</param>
  967. /// <param name="pubKey">Public key.</param>
  968. /// <param name="msg">Message to encrypt.</param>
  969. /// <param name="msgSz">Message size.</param>
  970. /// <param name="outBuffer">Output buffer.</param>
  971. /// <param name="ctx">ECIES context.</param>
  972. /// <returns>0 on success, or a negative error code on failure.</returns>
  973. public static int EciesEncrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx)
  974. {
  975. int ret;
  976. int outBufferLength = 0;
  977. IntPtr msgPtr = IntPtr.Zero;
  978. IntPtr outBufferPtr = IntPtr.Zero;
  979. IntPtr outSz = IntPtr.Zero;
  980. try
  981. {
  982. /* Allocate memory */
  983. msgPtr = Marshal.AllocHGlobal(msg.Length);
  984. outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length);
  985. outSz = Marshal.AllocHGlobal(sizeof(uint));
  986. Marshal.WriteInt32(outSz, outBuffer.Length);
  987. Marshal.Copy(msg, 0, msgPtr, msg.Length);
  988. /* Encrypt */
  989. ret = wc_ecc_encrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx);
  990. if (ret < 0)
  991. {
  992. log(ERROR_LOG, "Failed to encrypt message using ECIES. Error code: " + ret);
  993. }
  994. /* Output actual output buffer length */
  995. if (ret == 0)
  996. {
  997. outBufferLength = Marshal.ReadInt32(outSz);
  998. if (outBufferLength <= outBuffer.Length)
  999. {
  1000. Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength);
  1001. }
  1002. else
  1003. {
  1004. ret = BUFFER_E;
  1005. }
  1006. }
  1007. }
  1008. catch (Exception e)
  1009. {
  1010. log(ERROR_LOG, "ECIES encryption exception: " + e.ToString());
  1011. ret = EXCEPTION_E;
  1012. }
  1013. finally
  1014. {
  1015. /* Cleanup */
  1016. if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr);
  1017. if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr);
  1018. if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz);
  1019. }
  1020. return ret == 0 ? outBufferLength : ret;
  1021. }
  1022. /// <summary>
  1023. /// Decrypt a message using ECIES.
  1024. /// </summary>
  1025. /// <param name="privKey">Private key.</param>
  1026. /// <param name="pubKey">Public key.</param>
  1027. /// <param name="msg">Encrypted message.</param>
  1028. /// <param name="msgSz">Message size.</param>
  1029. /// <param name="outBuffer">Output buffer for the decrypted message.</param>
  1030. /// <param name="ctx">ECIES context.</param>
  1031. /// <returns>0 on success, or a negative error code on failure.</returns>
  1032. public static int EciesDecrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx)
  1033. {
  1034. int ret;
  1035. int outBufferLength = 0;
  1036. IntPtr msgPtr = IntPtr.Zero;
  1037. IntPtr outBufferPtr = IntPtr.Zero;
  1038. IntPtr outSz = IntPtr.Zero;
  1039. try
  1040. {
  1041. /* Allocate memory */
  1042. msgPtr = Marshal.AllocHGlobal(msg.Length);
  1043. outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length);
  1044. outSz = Marshal.AllocHGlobal(sizeof(uint));
  1045. Marshal.WriteInt32(outSz, outBuffer.Length);
  1046. Marshal.Copy(msg, 0, msgPtr, msg.Length);
  1047. /* Decrypt */
  1048. ret = wc_ecc_decrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx);
  1049. if (ret < 0)
  1050. {
  1051. log(ERROR_LOG, "Failed to decrypt message using ECIES. Error code: " + ret);
  1052. }
  1053. /* Output actual output buffer length */
  1054. if (ret == 0)
  1055. {
  1056. outBufferLength = Marshal.ReadInt32(outSz);
  1057. if (outBufferLength <= outBuffer.Length)
  1058. {
  1059. Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength);
  1060. }
  1061. else
  1062. {
  1063. ret = BUFFER_E;
  1064. }
  1065. }
  1066. }
  1067. catch (Exception e)
  1068. {
  1069. log(ERROR_LOG, "ECIES decryption exception: " + e.ToString());
  1070. return EXCEPTION_E;
  1071. }
  1072. finally
  1073. {
  1074. /* Cleanup */
  1075. if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr);
  1076. if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr);
  1077. if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz);
  1078. }
  1079. return ret == 0 ? outBufferLength : ret;
  1080. }
  1081. /// <summary>
  1082. /// Free the ECIES context.
  1083. /// </summary>
  1084. /// <param name="ctx">Pointer to the ECIES context to free.</param>
  1085. public static void EciesFreeCtx(IntPtr ctx)
  1086. {
  1087. if (ctx != IntPtr.Zero)
  1088. {
  1089. wc_ecc_ctx_free(ctx);
  1090. }
  1091. }
  1092. /********************************
  1093. * ENUMS
  1094. */
  1095. public enum ecEncAlgo {
  1096. ecAES_128_CBC = 1, /* default */
  1097. ecAES_256_CBC = 2,
  1098. ecAES_128_CTR = 3,
  1099. ecAES_256_CTR = 4
  1100. }
  1101. public enum ecKdfAlgo {
  1102. ecHKDF_SHA256 = 1, /* default */
  1103. ecHKDF_SHA1 = 2,
  1104. ecKDF_X963_SHA1 = 3,
  1105. ecKDF_X963_SHA256 = 4,
  1106. ecKDF_SHA1 = 5,
  1107. ecKDF_SHA256 = 6
  1108. }
  1109. public enum ecMacAlgo {
  1110. ecHMAC_SHA256 = 1, /* default */
  1111. ecHMAC_SHA1 = 2
  1112. }
  1113. public enum ecKeySize {
  1114. KEY_SIZE_128 = 16,
  1115. KEY_SIZE_256 = 32,
  1116. IV_SIZE_64 = 8,
  1117. IV_SIZE_128 = 16,
  1118. ECC_MAX_IV_SIZE = 16,
  1119. EXCHANGE_SALT_SZ = 16,
  1120. EXCHANGE_INFO_SZ = 23
  1121. }
  1122. public enum ecFlags {
  1123. REQ_RESP_CLIENT = 1,
  1124. REQ_RESP_SERVER = 2
  1125. }
  1126. /* END ECIES */
  1127. /***********************************************************************
  1128. * ECDHE
  1129. **********************************************************************/
  1130. /// <summary>
  1131. /// Generate a shared secret using ECC
  1132. /// </summary>
  1133. /// <param name="privateKey">ECC private key</param>
  1134. /// <param name="publicKey">ECC public key</param>
  1135. /// <param name="secret">Buffer to receive the shared secret</param>
  1136. /// <returns>0 on success, otherwise an error code</returns>
  1137. public static int EcdheSharedSecret(IntPtr privateKey, IntPtr publicKey, byte[] secret, IntPtr rng)
  1138. {
  1139. int ret;
  1140. int secretLength = secret.Length;
  1141. try
  1142. {
  1143. /* set RNG for Public Key */
  1144. ret = EccSetRng(privateKey, rng);
  1145. if (ret != 0)
  1146. {
  1147. throw new Exception("Failed to set Public Key RNG Error code: " + ret);
  1148. }
  1149. /* set RNG for Private Key */
  1150. ret = EccSetRng(publicKey, rng);
  1151. if (ret != 0)
  1152. {
  1153. throw new Exception("Failed to set Private Key RNG. Error code: " + ret);
  1154. }
  1155. /* Generate shared secret */
  1156. if (privateKey != IntPtr.Zero || publicKey != IntPtr.Zero)
  1157. {
  1158. ret = wc_ecc_shared_secret(privateKey, publicKey, secret, ref secretLength);
  1159. if (ret != 0)
  1160. {
  1161. throw new Exception("Failed to compute ECC shared secret. Error code: " + ret);
  1162. }
  1163. }
  1164. }
  1165. catch (Exception e)
  1166. {
  1167. log(ERROR_LOG, "ECC shared secret exception " + e.ToString());
  1168. ret = EXCEPTION_E;
  1169. }
  1170. return ret;
  1171. }
  1172. /* END ECDHE */
  1173. /***********************************************************************
  1174. * RSA
  1175. **********************************************************************/
  1176. /// <summary>
  1177. /// Generate a new RSA private/public key pair
  1178. /// </summary>
  1179. /// <param name="heap">Pointer to the heap for memory allocation
  1180. /// (use IntPtr.Zero if not applicable)</param>
  1181. /// <param name="devId">Device ID (if applicable, otherwise use 0)</param>
  1182. /// <param name="keysize">Key size in bits (example: 2048)</param>
  1183. /// <param name="exponent">Exponent for RSA key generation (default is 65537)</param>
  1184. /// <returns>Allocated RSA key structure or null on failure</returns>
  1185. public static IntPtr RsaMakeKey(IntPtr heap, int devId, int keysize, Int32 exponent)
  1186. {
  1187. int ret;
  1188. IntPtr key = IntPtr.Zero;
  1189. IntPtr rng = IntPtr.Zero;
  1190. try
  1191. {
  1192. /* Allocate and init new RSA key structure */
  1193. key = wc_NewRsaKey(heap, devId, IntPtr.Zero);
  1194. if (key != IntPtr.Zero)
  1195. {
  1196. rng = RandomNew();
  1197. if (rng == IntPtr.Zero)
  1198. {
  1199. throw new Exception("Failed to create rng.");
  1200. }
  1201. ret = wc_MakeRsaKey(key, keysize, exponent, rng);
  1202. if (ret != 0)
  1203. {
  1204. RsaFreeKey(key);
  1205. key = IntPtr.Zero;
  1206. }
  1207. RandomFree(rng);
  1208. rng = IntPtr.Zero;
  1209. }
  1210. }
  1211. catch (Exception e)
  1212. {
  1213. log(ERROR_LOG, "RSA make key exception " + e.ToString());
  1214. if (rng != IntPtr.Zero) RandomFree(rng);
  1215. if (key != IntPtr.Zero) RsaFreeKey(key);
  1216. key = IntPtr.Zero;
  1217. }
  1218. return key;
  1219. }
  1220. public static IntPtr RsaMakeKey(IntPtr heap, int devId, int keysize)
  1221. {
  1222. return RsaMakeKey(heap, devId, keysize, 65537);
  1223. }
  1224. /// <summary>
  1225. /// Import an RSA private key from ASN.1 buffer
  1226. /// </summary>
  1227. /// <param name="keyASN1">ASN.1 private key buffer</param>
  1228. /// <returns>Allocated RSA key structure or null</returns>
  1229. public static IntPtr RsaImportKey(byte[] keyASN1)
  1230. {
  1231. int ret;
  1232. IntPtr key = IntPtr.Zero;
  1233. try
  1234. {
  1235. key = wc_NewRsaKey(IntPtr.Zero, INVALID_DEVID, IntPtr.Zero);
  1236. if (key != IntPtr.Zero)
  1237. {
  1238. IntPtr idx = Marshal.AllocHGlobal(sizeof(uint));
  1239. IntPtr keydata = Marshal.AllocHGlobal(keyASN1.Length);
  1240. Marshal.WriteInt32(idx, 0);
  1241. Marshal.Copy(keyASN1, 0, keydata, keyASN1.Length);
  1242. ret = wc_RsaPrivateKeyDecode(keydata, idx, key, Convert.ToUInt32(keyASN1.Length));
  1243. if (ret != 0)
  1244. {
  1245. RsaFreeKey(key);
  1246. key = IntPtr.Zero;
  1247. }
  1248. Marshal.FreeHGlobal(idx); /* not used */
  1249. Marshal.FreeHGlobal(keydata);
  1250. }
  1251. }
  1252. catch (Exception e)
  1253. {
  1254. log(ERROR_LOG, "RSA make key exception " + e.ToString());
  1255. RsaFreeKey(key); /* make sure its free'd */
  1256. key = IntPtr.Zero;
  1257. }
  1258. return key;
  1259. }
  1260. /// <summary>
  1261. /// Sign a hash using RSA and SSL-style padding
  1262. /// </summary>
  1263. /// <param name="key">RSA key structure</param>
  1264. /// <param name="hash">Hash to sign</param>
  1265. /// <param name="signature">Buffer to receive the signature</param>
  1266. /// <returns>Length of the signature on success, otherwise an error code</returns>
  1267. public static int RsaSignSSL(IntPtr key, byte[] hash, byte[] signature)
  1268. {
  1269. IntPtr hashPtr = Marshal.AllocHGlobal(hash.Length);
  1270. IntPtr sigPtr = Marshal.AllocHGlobal(signature.Length);
  1271. IntPtr rng = IntPtr.Zero;
  1272. int ret;
  1273. try
  1274. {
  1275. rng = RandomNew();
  1276. if (rng == IntPtr.Zero)
  1277. {
  1278. throw new Exception("Failed to create RNG.");
  1279. }
  1280. Marshal.Copy(hash, 0, hashPtr, hash.Length);
  1281. ret = wc_RsaSSL_Sign(hashPtr, hash.Length, sigPtr, signature.Length, key, rng);
  1282. if (ret >= 0) /* `wc_RsaSSL_Sign` returns the signature length on success */
  1283. {
  1284. Marshal.Copy(sigPtr, signature, 0, ret);
  1285. }
  1286. }
  1287. finally
  1288. {
  1289. if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr);
  1290. if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr);
  1291. if (rng != IntPtr.Zero) RandomFree(rng);
  1292. }
  1293. return ret;
  1294. }
  1295. /// <summary>
  1296. /// Verify a signature using RSA and SSL-style padding
  1297. /// </summary>
  1298. /// <param name="key">RSA key structure</param>
  1299. /// <param name="signature">Signature to verify</param>
  1300. /// <param name="hash">Expected hash value</param>
  1301. /// <returns>0 on success, otherwise an error code</returns>
  1302. public static int RsaVerifySSL(IntPtr key, byte[] signature, byte[] hash)
  1303. {
  1304. IntPtr hashPtr = IntPtr.Zero;
  1305. IntPtr sigPtr = IntPtr.Zero;
  1306. int ret;
  1307. try
  1308. {
  1309. hashPtr = Marshal.AllocHGlobal(hash.Length);
  1310. sigPtr = Marshal.AllocHGlobal(signature.Length);
  1311. Marshal.Copy(signature, 0, sigPtr, signature.Length);
  1312. ret = wc_RsaSSL_Verify(sigPtr, signature.Length, hashPtr, hash.Length, key);
  1313. if (ret == hash.Length)
  1314. {
  1315. byte[] verifiedHash = new byte[hash.Length];
  1316. Marshal.Copy(hashPtr, verifiedHash, 0, hash.Length);
  1317. if (ByteArrayVerify(verifiedHash, hash))
  1318. {
  1319. ret = 0;
  1320. }
  1321. else
  1322. {
  1323. ret = SIG_VERIFY_E;
  1324. }
  1325. }
  1326. }
  1327. catch (Exception e)
  1328. {
  1329. log(ERROR_LOG, "RSA verify exception: " + e.ToString());
  1330. ret = EXCEPTION_E;
  1331. }
  1332. finally
  1333. {
  1334. if (hashPtr != IntPtr.Zero) Marshal.FreeHGlobal(hashPtr);
  1335. if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr);
  1336. }
  1337. return ret;
  1338. }
  1339. /// <summary>
  1340. /// Encrypt data using RSA public key encryption
  1341. /// </summary>
  1342. /// <param name="key">RSA key structure</param>
  1343. /// <param name="input">Data to encrypt</param>
  1344. /// <param name="output">Buffer to receive the encrypted data</param>
  1345. /// <returns>0 on success, otherwise an error code</returns>
  1346. public static int RsaPublicEncrypt(IntPtr key, byte[] input, byte[] output)
  1347. {
  1348. IntPtr inPtr = Marshal.AllocHGlobal(input.Length);
  1349. IntPtr outPtr = Marshal.AllocHGlobal(output.Length);
  1350. Marshal.Copy(input, 0, inPtr, input.Length);
  1351. int ret = wc_RsaPublicEncrypt(inPtr, input.Length, outPtr, output.Length, key);
  1352. if (ret > 0)
  1353. {
  1354. Marshal.Copy(outPtr, output, 0, ret);
  1355. }
  1356. Marshal.FreeHGlobal(inPtr);
  1357. Marshal.FreeHGlobal(outPtr);
  1358. return ret > 0 ? 0 : ret;
  1359. }
  1360. /// <summary>
  1361. /// Decrypt data using RSA private key decryption
  1362. /// </summary>
  1363. /// <param name="key">RSA key structure</param>
  1364. /// <param name="input">Encrypted data</param>
  1365. /// <param name="output">Buffer to receive the decrypted data</param>
  1366. /// <returns>0 on success, otherwise an error code</returns>
  1367. public static int RsaPrivateDecrypt(IntPtr key, byte[] input, byte[] output)
  1368. {
  1369. IntPtr inPtr = Marshal.AllocHGlobal(input.Length);
  1370. IntPtr outPtr = Marshal.AllocHGlobal(output.Length);
  1371. Marshal.Copy(input, 0, inPtr, input.Length);
  1372. int ret = wc_RsaPrivateDecrypt(inPtr, input.Length, outPtr, output.Length, key);
  1373. if (ret > 0)
  1374. {
  1375. Marshal.Copy(outPtr, output, 0, ret);
  1376. }
  1377. Marshal.FreeHGlobal(inPtr);
  1378. Marshal.FreeHGlobal(outPtr);
  1379. return ret > 0 ? 0 : ret;
  1380. }
  1381. /// <summary>
  1382. /// Free an RSA key structure
  1383. /// </summary>
  1384. /// <param name="key">RSA key structure allocated using RsaMakeKey() or RsaImportKey()</param>
  1385. public static void RsaFreeKey(IntPtr key)
  1386. {
  1387. if (key != IntPtr.Zero)
  1388. {
  1389. wc_DeleteRsaKey(key, IntPtr.Zero);
  1390. key = IntPtr.Zero;
  1391. }
  1392. }
  1393. /* END RSA */
  1394. /***********************************************************************
  1395. * ED25519
  1396. **********************************************************************/
  1397. /// <summary>
  1398. /// Generate a new ED25519 key pair with a specified heap, device ID, and internally managed RNG.
  1399. /// </summary>
  1400. /// <param name="heap">Heap to use for memory allocations (can be IntPtr.Zero).</param>
  1401. /// <param name="devId">Device ID for hardware-based keys (can be 0 for software).</param>
  1402. /// <returns>0 on success, or an error code on failure.</returns>
  1403. public static IntPtr Ed25519MakeKey(IntPtr heap, int devId)
  1404. {
  1405. int ret = 0;
  1406. IntPtr rng = IntPtr.Zero;
  1407. IntPtr key = IntPtr.Zero;
  1408. try
  1409. {
  1410. rng = RandomNew();
  1411. if (rng == IntPtr.Zero)
  1412. {
  1413. throw new Exception("Failed to create RNG.");
  1414. }
  1415. key = wc_ed25519_new(heap, devId, IntPtr.Zero);
  1416. if (key != IntPtr.Zero)
  1417. {
  1418. ret = wc_ed25519_make_key(rng, 32, key);
  1419. }
  1420. }
  1421. catch (Exception e)
  1422. {
  1423. log(ERROR_LOG, "ED25519 make key exception: " + e.ToString());
  1424. ret = EXCEPTION_E;
  1425. }
  1426. finally
  1427. {
  1428. /* Cleanup */
  1429. if (rng != IntPtr.Zero) RandomFree(rng);
  1430. if (ret != 0)
  1431. {
  1432. wc_ed25519_delete(key, IntPtr.Zero);
  1433. key = IntPtr.Zero;
  1434. }
  1435. }
  1436. return key;
  1437. }
  1438. /// <summary>
  1439. /// Sign a message with an ED25519 private key.
  1440. /// </summary>
  1441. /// <param name="inMsg">Message to be signed</param>
  1442. /// <param name="outMsg">Buffer to receive the signature</param>
  1443. /// <param name="key">Private key used for signing</param>
  1444. /// <returns>0 on success, otherwise an error code</returns>
  1445. public static int Ed25519SignMsg(byte[] inMsg, out byte[] outMsg, IntPtr key)
  1446. {
  1447. int ret;
  1448. IntPtr inMsgPtr = Marshal.AllocHGlobal(inMsg.Length);
  1449. IntPtr outMsgPtr = Marshal.AllocHGlobal(ED25519_SIG_SIZE);
  1450. outMsg = null;
  1451. try
  1452. {
  1453. Marshal.Copy(inMsg, 0, inMsgPtr, inMsg.Length);
  1454. uint outMsgSize = (uint)ED25519_SIG_SIZE;
  1455. ret = wc_ed25519_sign_msg(inMsgPtr, (uint)inMsg.Length, outMsgPtr, ref outMsgSize, key);
  1456. if (ret == 0)
  1457. {
  1458. outMsg = new byte[outMsgSize];
  1459. Marshal.Copy(outMsgPtr, outMsg, 0, (int)outMsgSize);
  1460. }
  1461. }
  1462. finally
  1463. {
  1464. /* Cleanup */
  1465. if (inMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(inMsgPtr);
  1466. if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr);
  1467. }
  1468. return ret;
  1469. }
  1470. /// <summary>
  1471. /// Verify a signature of a message with an ED25519 public key.
  1472. /// </summary>
  1473. /// <param name="sig">Signature to verify</param>
  1474. /// <param name="msg">Message that was signed</param>
  1475. /// <param name="key">Public key used for verification</param>
  1476. /// <returns>0 if the verification succeeds, otherwise an error code</returns>
  1477. public static int Ed25519VerifyMsg(byte[] sig, byte[] msg, IntPtr key)
  1478. {
  1479. IntPtr sigPtr = IntPtr.Zero;
  1480. IntPtr msgPtr = IntPtr.Zero;
  1481. int ret = 0;
  1482. try
  1483. {
  1484. /* Allocate memory */
  1485. sigPtr = Marshal.AllocHGlobal(sig.Length);
  1486. msgPtr = Marshal.AllocHGlobal(msg.Length);
  1487. Marshal.Copy(sig, 0, sigPtr, sig.Length);
  1488. Marshal.Copy(msg, 0, msgPtr, msg.Length);
  1489. int verify = 0;
  1490. ret = wc_ed25519_verify_msg(sigPtr, (uint)sig.Length, msgPtr, (uint)msg.Length, ref verify, key);
  1491. if (ret == 0 && verify == 1)
  1492. {
  1493. ret = 0;
  1494. }
  1495. else
  1496. {
  1497. ret = SIG_VERIFY_E;
  1498. }
  1499. }
  1500. catch (Exception e)
  1501. {
  1502. log(ERROR_LOG, "ED25519 verify exception: " + e.ToString());
  1503. ret = EXCEPTION_E;
  1504. }
  1505. finally
  1506. {
  1507. /* Cleanup */
  1508. if (sigPtr != IntPtr.Zero) Marshal.FreeHGlobal(sigPtr);
  1509. if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr);
  1510. }
  1511. return ret;
  1512. }
  1513. /// <summary>
  1514. /// Decode an ED25519 private key from DER format.
  1515. /// </summary>
  1516. /// <param name="input">DER-encoded private key as byte array.</param>
  1517. /// <returns>Allocated ED25519 key structure or IntPtr.Zero on failure.</returns>
  1518. public static IntPtr Ed25519PrivateKeyDecode(byte[] input)
  1519. {
  1520. IntPtr key = IntPtr.Zero;
  1521. uint idx = 0;
  1522. int ret;
  1523. try
  1524. {
  1525. key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID, IntPtr.Zero);
  1526. if (key != IntPtr.Zero)
  1527. {
  1528. ret = wc_Ed25519PrivateKeyDecode(input, ref idx, key, (uint)input.Length);
  1529. if (ret != 0)
  1530. {
  1531. Ed25519FreeKey(key);
  1532. key = IntPtr.Zero;
  1533. }
  1534. }
  1535. }
  1536. catch (Exception e)
  1537. {
  1538. log(ERROR_LOG, "ED25519 private key decode exception: " + e.ToString());
  1539. if (key != IntPtr.Zero) Ed25519FreeKey(key);
  1540. key = IntPtr.Zero;
  1541. }
  1542. return key;
  1543. }
  1544. /// <summary>
  1545. /// Decode an ED25519 public key from DER format.
  1546. /// </summary>
  1547. /// <param name="input">DER-encoded public key as byte array.</param>
  1548. /// <returns>Allocated ED25519 key structure or IntPtr.Zero on failure.</returns>
  1549. public static IntPtr Ed25519PublicKeyDecode(byte[] input)
  1550. {
  1551. IntPtr key = IntPtr.Zero;
  1552. uint idx = 0;
  1553. int ret;
  1554. try
  1555. {
  1556. key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID, IntPtr.Zero);
  1557. if (key != IntPtr.Zero)
  1558. {
  1559. ret = wc_Ed25519PublicKeyDecode(input, ref idx, key, (uint)input.Length);
  1560. if (ret != 0)
  1561. {
  1562. Ed25519FreeKey(key);
  1563. key = IntPtr.Zero;
  1564. }
  1565. }
  1566. }
  1567. catch (Exception e)
  1568. {
  1569. log(ERROR_LOG, "ED25519 public key decode exception: " + e.ToString());
  1570. if (key != IntPtr.Zero) Ed25519FreeKey(key);
  1571. key = IntPtr.Zero;
  1572. }
  1573. return key;
  1574. }
  1575. /// <summary>
  1576. /// Export an ED25519 key to DER format.
  1577. /// </summary>
  1578. /// <param name="key">ED25519 key structure.</param>
  1579. /// <param name="privKey">DER-encoded public key as byte array.</param>
  1580. /// <returns>DER-encoded key as byte array.</returns>
  1581. public static int Ed25519ExportKeyToDer(IntPtr key, out byte[] privKey)
  1582. {
  1583. int ret;
  1584. privKey = null;
  1585. try
  1586. {
  1587. /* Get length */
  1588. int len = wc_Ed25519KeyToDer(key, null, 0);
  1589. if (len < 0)
  1590. {
  1591. log(ERROR_LOG, "Failed to determine length. Error code: " + len);
  1592. return len;
  1593. }
  1594. privKey = new byte[len];
  1595. ret = wc_Ed25519KeyToDer(key, privKey, (uint)privKey.Length);
  1596. if (ret < 0)
  1597. {
  1598. log(ERROR_LOG, "Failed to export ED25519 private key to DER format. Error code: " + ret);
  1599. return ret;
  1600. }
  1601. }
  1602. catch(Exception e)
  1603. {
  1604. log(ERROR_LOG, "ED25519 export private key to DER exception: " + e.ToString());
  1605. return EXCEPTION_E;
  1606. }
  1607. return ret;
  1608. }
  1609. /// <summary>
  1610. /// Export an ED25519 private key to DER format.
  1611. /// </summary>
  1612. /// <param name="key">ED25519 private key structure.</param>
  1613. /// <param name="derKey">DER-encoded private key as byte array.</param>
  1614. /// <returns>DER-encoded private key as byte array.</returns>
  1615. public static int Ed25519ExportPrivateKeyToDer(IntPtr key, out byte[] derKey)
  1616. {
  1617. int ret;
  1618. derKey = null;
  1619. try
  1620. {
  1621. /* Determine length */
  1622. int len = wc_Ed25519PrivateKeyToDer(key, null, 0);
  1623. if (len < 0)
  1624. {
  1625. log(ERROR_LOG, "Failed to determine length. Error code: " + len);
  1626. return len;
  1627. }
  1628. derKey = new byte[len];
  1629. ret = wc_Ed25519PrivateKeyToDer(key, derKey, (uint)derKey.Length);
  1630. if (ret < 0)
  1631. {
  1632. log(ERROR_LOG, "Failed to export ED25519 private key to DER format. Error code: " + ret);
  1633. return ret;
  1634. }
  1635. }
  1636. catch (Exception e)
  1637. {
  1638. log(ERROR_LOG, "ED25519 export private key to DER exception: " + e.ToString());
  1639. return EXCEPTION_E;
  1640. }
  1641. return ret;
  1642. }
  1643. /// <summary>
  1644. /// Export an ED25519 public key to DER format.
  1645. /// </summary>
  1646. /// <param name="key">ED25519 public key structure.</param>
  1647. /// <param name="includeAlg">Whether to include the algorithm identifier in the output.</param>
  1648. /// <param name="pubKey">DER-encoded public key as byte array.</param>
  1649. /// <returns>An error code indicating success (0) or failure (negative value).</returns>
  1650. public static int Ed25519ExportPublicKeyToDer(IntPtr key, out byte[] pubKey, bool includeAlg)
  1651. {
  1652. int ret;
  1653. pubKey = null;
  1654. try
  1655. {
  1656. /* Determine length */
  1657. int len = wc_Ed25519PublicKeyToDer(key, null, 0, 1);
  1658. if (len < 0)
  1659. {
  1660. log(ERROR_LOG, "Failed to determine length. Error code: " + len);
  1661. return len;
  1662. }
  1663. pubKey = new byte[len];
  1664. ret = wc_Ed25519PublicKeyToDer(key, pubKey, (uint)pubKey.Length, includeAlg ? 1 : 0);
  1665. if (ret < 0)
  1666. {
  1667. log(ERROR_LOG, "Failed to export ED25519 public key to DER format. Error code: " + ret);
  1668. return ret;
  1669. }
  1670. }
  1671. catch (Exception e)
  1672. {
  1673. log(ERROR_LOG, "ED25519 export public key to DER exception: " + e.ToString());
  1674. return EXCEPTION_E;
  1675. }
  1676. return ret;
  1677. }
  1678. /// <summary>
  1679. /// Free an ED25519 key.
  1680. /// </summary>
  1681. /// <param name="key">Key to be freed</param>
  1682. public static void Ed25519FreeKey(IntPtr key)
  1683. {
  1684. wc_ed25519_delete(key, IntPtr.Zero);
  1685. key = IntPtr.Zero;
  1686. }
  1687. /* END ED25519 */
  1688. /***********************************************************************
  1689. * RAW ED25519
  1690. **********************************************************************/
  1691. /// <summary>
  1692. /// Initialize an ED25519 key.
  1693. /// </summary>
  1694. /// <param name="key">Buffer to receive the initialized key</param>
  1695. /// <returns>0 on success, otherwise an error code</returns>
  1696. public static int Ed25519InitKey(out IntPtr key)
  1697. {
  1698. key = IntPtr.Zero;
  1699. try
  1700. {
  1701. key = Marshal.AllocHGlobal(ED25519_SIG_SIZE);
  1702. int ret = wc_ed25519_init(key);
  1703. if (ret != 0)
  1704. {
  1705. Marshal.FreeHGlobal(key);
  1706. key = IntPtr.Zero;
  1707. }
  1708. return ret;
  1709. }
  1710. catch
  1711. {
  1712. /* Cleanup */
  1713. Marshal.FreeHGlobal(key);
  1714. key = IntPtr.Zero;
  1715. throw;
  1716. }
  1717. }
  1718. /// <summary>
  1719. /// Import a public key into an ED25519 key structure.
  1720. /// </summary>
  1721. /// <param name="inMsg">Public key to import</param>
  1722. /// <param name="inLen">Length of the public key</param>
  1723. /// <param name="key">Buffer to receive the imported key</param>
  1724. /// <returns>0 on success, otherwise an error code</returns>
  1725. public static int Ed25519ImportPublic(byte[] inMsg, uint inLen, out IntPtr key)
  1726. {
  1727. int ret;
  1728. key = IntPtr.Zero;
  1729. IntPtr inMsgPtr = IntPtr.Zero;
  1730. try
  1731. {
  1732. /* Allocate memory */
  1733. key = Marshal.AllocHGlobal(ED25519_PUB_KEY_SIZE);
  1734. if (key == IntPtr.Zero)
  1735. {
  1736. throw new OutOfMemoryException("Failed to allocate memory for the key.");
  1737. }
  1738. inMsgPtr = Marshal.AllocHGlobal(inMsg.Length);
  1739. if (inMsgPtr == IntPtr.Zero)
  1740. {
  1741. throw new OutOfMemoryException("Failed to allocate memory for the input message.");
  1742. }
  1743. Marshal.Copy(inMsg, 0, inMsgPtr, inMsg.Length);
  1744. ret = wc_ed25519_import_public(inMsgPtr, inLen, key);
  1745. if (ret != 0)
  1746. {
  1747. return ret;
  1748. }
  1749. }
  1750. catch (Exception ex)
  1751. {
  1752. Console.WriteLine($"Exception in EdImportPublic: {ex.Message}");
  1753. return EXCEPTION_E;
  1754. }
  1755. finally
  1756. {
  1757. /* Cleanup */
  1758. if (inMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(inMsgPtr);
  1759. if (key != IntPtr.Zero) Marshal.FreeHGlobal(key);
  1760. }
  1761. return ret;
  1762. }
  1763. /// <summary>
  1764. /// Export a public key from an ED25519 key structure.
  1765. /// </summary>
  1766. /// <param name="key">ED25519 key structure</param>
  1767. /// <param name="outMsg">Buffer to receive the exported public key</param>
  1768. /// <param name="outLen">Length of the exported public key</param>
  1769. /// <returns>0 on success, otherwise an error code</returns>
  1770. public static int Ed25519ExportPublic(IntPtr key, byte[] outMsg, out uint outLen)
  1771. {
  1772. int ret;
  1773. IntPtr outMsgPtr = IntPtr.Zero;
  1774. try
  1775. {
  1776. outMsgPtr = Marshal.AllocHGlobal(outMsg.Length);
  1777. outLen = (uint)outMsg.Length;
  1778. ret = wc_ed25519_export_public(key, outMsgPtr, ref outLen);
  1779. if (ret == 0)
  1780. {
  1781. Marshal.Copy(outMsgPtr, outMsg, 0, (int)outLen);
  1782. }
  1783. else
  1784. {
  1785. outLen = 0;
  1786. }
  1787. }
  1788. finally
  1789. {
  1790. /* Cleanup */
  1791. if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr);
  1792. }
  1793. return ret;
  1794. }
  1795. /// <summary>
  1796. /// Export a private key from an ED25519 key structure.
  1797. /// </summary>
  1798. /// <param name="key">ED25519 key structure</param>
  1799. /// <param name="outMsg">Buffer to receive the exported private key</param>
  1800. /// <param name="outLen">Length of the exported private key</param>
  1801. /// <returns>0 on success, otherwise an error code</returns>
  1802. public static int Ed25519ExportPrivate(IntPtr key, byte[] outMsg, out uint outLen)
  1803. {
  1804. int ret;
  1805. IntPtr outMsgPtr = IntPtr.Zero;
  1806. try
  1807. {
  1808. outMsgPtr = Marshal.AllocHGlobal(outMsg.Length);
  1809. outLen = (uint)outMsg.Length;
  1810. ret = wc_ed25519_export_private(key, outMsgPtr, ref outLen);
  1811. if (ret == 0)
  1812. {
  1813. Marshal.Copy(outMsgPtr, outMsg, 0, (int)outLen);
  1814. }
  1815. else
  1816. {
  1817. outLen = 0;
  1818. }
  1819. }
  1820. finally
  1821. {
  1822. /* Cleanup */
  1823. if (outMsgPtr != IntPtr.Zero) Marshal.FreeHGlobal(outMsgPtr);
  1824. }
  1825. return ret;
  1826. }
  1827. /// <summary>
  1828. /// Generate a public key from a private key.
  1829. /// </summary>
  1830. /// <param name="key">The private key used to generate the public key</param>
  1831. /// <param name="pubKey">Buffer to receive the public key</param>
  1832. /// <param name="pubKeySz">Size of the public key buffer</param>
  1833. /// <returns>0 on success, otherwise an error code</returns>
  1834. public static int Ed25519MakePublic(IntPtr key, byte[] pubKey, out uint pubKeySz)
  1835. {
  1836. int ret;
  1837. IntPtr pubKeyPtr = Marshal.AllocHGlobal(pubKey.Length);
  1838. try
  1839. {
  1840. pubKeySz = (uint)pubKey.Length;
  1841. ret = wc_ed25519_make_public(key, pubKeyPtr, pubKeySz);
  1842. if (ret == 0)
  1843. {
  1844. Marshal.Copy(pubKeyPtr, pubKey, 0, (int)pubKeySz);
  1845. }
  1846. }
  1847. finally
  1848. {
  1849. /* Cleanup */
  1850. if (pubKeyPtr != IntPtr.Zero) Marshal.FreeHGlobal(pubKeyPtr);
  1851. }
  1852. return ret;
  1853. }
  1854. /// <summary>
  1855. /// Get the size of the ED25519 key.
  1856. /// </summary>
  1857. /// <param name="key">ED25519 key structure</param>
  1858. /// <returns>Size of the key, or an error code if failed</returns>
  1859. public static int Ed25519GetKeySize(IntPtr key)
  1860. {
  1861. return wc_ed25519_size(key);
  1862. }
  1863. /* END RAW ED25519 */
  1864. /***********************************************************************
  1865. * Curve25519
  1866. **********************************************************************/
  1867. /// <summary>
  1868. /// Generate a new Curve25519 key pair with a specified heap, device ID, and internally managed RNG.
  1869. /// </summary>
  1870. /// <param name="heap">Heap to use for memory allocations (can be IntPtr.Zero).</param>
  1871. /// <param name="devId">Device ID for hardware-based keys (can be 0 for software).</param>
  1872. /// <returns>0 on success, or an error code on failure.</returns>
  1873. public static IntPtr Curve25519MakeKey(IntPtr heap, int devId)
  1874. {
  1875. int ret = 0;
  1876. IntPtr rng = IntPtr.Zero;
  1877. IntPtr key = IntPtr.Zero;
  1878. try
  1879. {
  1880. rng = RandomNew();
  1881. if (rng == IntPtr.Zero)
  1882. {
  1883. throw new Exception("Failed to create RNG.");
  1884. }
  1885. key = wc_curve25519_new(heap, devId, IntPtr.Zero);
  1886. if (key != IntPtr.Zero)
  1887. {
  1888. ret = wc_curve25519_make_key(rng, 32, key);
  1889. }
  1890. }
  1891. catch (Exception e)
  1892. {
  1893. log(ERROR_LOG, "Curve25519 make key exception: " + e.ToString());
  1894. ret = EXCEPTION_E;
  1895. }
  1896. finally
  1897. {
  1898. /* Cleanup */
  1899. if (rng != IntPtr.Zero) RandomFree(rng);
  1900. if (ret != 0)
  1901. {
  1902. wc_curve25519_delete(key, IntPtr.Zero);
  1903. key = IntPtr.Zero;
  1904. }
  1905. }
  1906. return key;
  1907. }
  1908. /// <summary>
  1909. /// Decode an Curve25519 private key from DER format.
  1910. /// </summary>
  1911. /// <param name="input">DER-encoded private key as byte array.</param>
  1912. /// <returns>Allocated Curve25519 key structure or IntPtr.Zero on failure.</returns>
  1913. public static IntPtr Curve25519PrivateKeyDecode(byte[] input)
  1914. {
  1915. IntPtr key = IntPtr.Zero;
  1916. uint idx = 0;
  1917. int ret;
  1918. try
  1919. {
  1920. key = wc_ed25519_new(IntPtr.Zero, INVALID_DEVID, IntPtr.Zero);
  1921. if (key != IntPtr.Zero)
  1922. {
  1923. ret = wc_Ed25519PrivateKeyDecode(input, ref idx, key, (uint)input.Length);
  1924. if (ret != 0)
  1925. {
  1926. Curve25519FreeKey(key);
  1927. key = IntPtr.Zero;
  1928. }
  1929. }
  1930. }
  1931. catch (Exception e)
  1932. {
  1933. log(ERROR_LOG, "Curve25519 private key decode exception: " + e.ToString());
  1934. if (key != IntPtr.Zero) Curve25519FreeKey(key);
  1935. key = IntPtr.Zero;
  1936. }
  1937. return key;
  1938. }
  1939. /// <summary>
  1940. /// Decode an Curve25519 public key from DER format.
  1941. /// </summary>
  1942. /// <param name="input">DER-encoded public key as byte array.</param>
  1943. /// <returns>Allocated Curve25519 key structure or IntPtr.Zero on failure.</returns>
  1944. public static IntPtr Curve25519PublicKeyDecode(byte[] input)
  1945. {
  1946. IntPtr key = IntPtr.Zero;
  1947. uint idx = 0;
  1948. int ret;
  1949. try
  1950. {
  1951. key = wc_curve25519_new(IntPtr.Zero, INVALID_DEVID, IntPtr.Zero);
  1952. if (key != IntPtr.Zero)
  1953. {
  1954. ret = wc_Curve25519PublicKeyDecode(input, ref idx, key, (uint)input.Length);
  1955. if (ret != 0)
  1956. {
  1957. Curve25519FreeKey(key);
  1958. key = IntPtr.Zero;
  1959. }
  1960. }
  1961. }
  1962. catch (Exception e)
  1963. {
  1964. log(ERROR_LOG, "Curve25519 public key decode exception: " + e.ToString());
  1965. if (key != IntPtr.Zero) Curve25519FreeKey(key);
  1966. key = IntPtr.Zero;
  1967. }
  1968. return key;
  1969. }
  1970. /// <summary>
  1971. /// Export an Curve25519 key to DER format.
  1972. /// </summary>
  1973. /// <param name="key">Curve25519 key structure.</param>
  1974. /// <param name="derKey">DER-encoded public key as byte array.</param>
  1975. /// <returns>DER-encoded key as byte array.</returns>
  1976. public static int Curve25519ExportPrivateKeyToDer(IntPtr key, out byte[] derKey)
  1977. {
  1978. int ret;
  1979. derKey = null;
  1980. try
  1981. {
  1982. /* Determine length */
  1983. int len = wc_Curve25519PrivateKeyToDer(key, null, 0);
  1984. if (len < 0)
  1985. {
  1986. log(ERROR_LOG, "Failed to determine length. Error code: " + len);
  1987. return len;
  1988. }
  1989. derKey = new byte[len];
  1990. ret = wc_Curve25519PrivateKeyToDer(key, derKey, (uint)derKey.Length);
  1991. if (ret < 0)
  1992. {
  1993. log(ERROR_LOG, "Failed to export Curve25519 private key to DER format. Error code: " + ret);
  1994. return ret;
  1995. }
  1996. }
  1997. catch (Exception e)
  1998. {
  1999. log(ERROR_LOG, "CURVE25519 export private key to DER exception: " + e.ToString());
  2000. return EXCEPTION_E;
  2001. }
  2002. return ret;
  2003. }
  2004. /// <summary>
  2005. /// Export an Curve25519 public key to DER format.
  2006. /// </summary>
  2007. /// <param name="key">Curve25519 public key structure.</param>
  2008. /// <param name="includeAlg">Whether to include the algorithm identifier in the output.</param>
  2009. /// <param name="derKey">DER-encoded public key as byte array.</param>
  2010. /// <returns>An error code indicating success (0) or failure (negative value).</returns>
  2011. public static int Curve25519ExportPublicKeyToDer(IntPtr key, out byte[] derKey, bool includeAlg)
  2012. {
  2013. int ret;
  2014. derKey = null;
  2015. try
  2016. {
  2017. /* Determine length */
  2018. int len = wc_Curve25519PublicKeyToDer(key, null, 0, 1);
  2019. if (len < 0)
  2020. {
  2021. log(ERROR_LOG, "Failed to determine length. Error code: " + len);
  2022. return len;
  2023. }
  2024. derKey = new byte[len];
  2025. ret = wc_Curve25519PublicKeyToDer(key, derKey, (uint)derKey.Length, includeAlg ? 1 : 0);
  2026. if (ret < 0)
  2027. {
  2028. log(ERROR_LOG, "Failed to export Curve25519 public key to DER format. Error code: " + ret);
  2029. }
  2030. }
  2031. catch (Exception e)
  2032. {
  2033. log(ERROR_LOG, "Curve25519 export public key to DER exception: " + e.ToString());
  2034. ret = EXCEPTION_E;
  2035. }
  2036. return ret;
  2037. }
  2038. /// <summary>
  2039. /// Free an Curve25519 key.
  2040. /// </summary>
  2041. /// <param name="key">Key to be freed</param>
  2042. public static void Curve25519FreeKey(IntPtr key)
  2043. {
  2044. wc_curve25519_delete(key, IntPtr.Zero);
  2045. key = IntPtr.Zero;
  2046. }
  2047. /* END Curve25519 */
  2048. /***********************************************************************
  2049. * RAW Curve25519
  2050. **********************************************************************/
  2051. /// <summary>
  2052. /// Generate a shared secret using Curve25519
  2053. /// </summary>
  2054. /// <param name="privateKey">Curve25519 private key</param>
  2055. /// <param name="publicKey">Curve25519 public key</param>
  2056. /// <param name="secret">Buffer to receive the shared secret</param>
  2057. /// <returns>0 on success, otherwise an error code</returns>
  2058. public static int Curve25519SharedSecret(IntPtr privateKey, IntPtr publicKey, byte[] secret)
  2059. {
  2060. int ret;
  2061. int secretLength = secret.Length;
  2062. try
  2063. {
  2064. ret = wc_curve25519_shared_secret(privateKey, publicKey, secret, ref secretLength);
  2065. if (ret != 0)
  2066. {
  2067. throw new Exception("Failed to compute Curve25519 shared secret. Error code: " + ret);
  2068. }
  2069. }
  2070. catch (Exception e)
  2071. {
  2072. log(ERROR_LOG, "Curve25519 shared secret exception " + e.ToString());
  2073. ret = EXCEPTION_E;
  2074. }
  2075. return ret;
  2076. }
  2077. /// <summary>
  2078. /// Import a Curve25519 private key from a byte array
  2079. /// </summary>
  2080. /// <param name="privateKey">Private key byte array</param>
  2081. /// <returns>Allocated Curve25519 key structure or null</returns>
  2082. public static IntPtr Curve25519ImportPrivateKey(byte[] privateKey)
  2083. {
  2084. IntPtr key = IntPtr.Zero;
  2085. try
  2086. {
  2087. key = Marshal.AllocHGlobal(privateKey.Length);
  2088. Marshal.Copy(privateKey, 0, key, privateKey.Length);
  2089. int ret = wc_curve25519_import_private(key, privateKey.Length, key);
  2090. if (ret != 0)
  2091. {
  2092. Marshal.FreeHGlobal(key);
  2093. key = IntPtr.Zero;
  2094. }
  2095. }
  2096. catch (Exception e)
  2097. {
  2098. log(ERROR_LOG, "Curve25519 import private key exception " + e.ToString());
  2099. if (key != IntPtr.Zero) Marshal.FreeHGlobal(key);
  2100. key = IntPtr.Zero;
  2101. }
  2102. return key;
  2103. }
  2104. /// <summary>
  2105. /// Import a Curve25519 public key from a byte array
  2106. /// </summary>
  2107. /// <param name="publicKey">Public key byte array</param>
  2108. /// <returns>Allocated Curve25519 key structure or null</returns>
  2109. public static IntPtr Curve25519ImportPublicKey(byte[] publicKey)
  2110. {
  2111. IntPtr key = IntPtr.Zero;
  2112. try
  2113. {
  2114. key = Marshal.AllocHGlobal(publicKey.Length);
  2115. Marshal.Copy(publicKey, 0, key, publicKey.Length);
  2116. int ret = wc_curve25519_import_public(key, publicKey.Length, key);
  2117. if (ret != 0)
  2118. {
  2119. Marshal.FreeHGlobal(key);
  2120. key = IntPtr.Zero;
  2121. }
  2122. }
  2123. catch (Exception e)
  2124. {
  2125. log(ERROR_LOG, "Curve25519 import public key exception " + e.ToString());
  2126. if (key != IntPtr.Zero) Marshal.FreeHGlobal(key);
  2127. key = IntPtr.Zero;
  2128. }
  2129. return key;
  2130. }
  2131. /// <summary>
  2132. /// Export a Curve25519 private key to a byte array
  2133. /// </summary>
  2134. /// <param name="key">Curve25519 key structure</param>
  2135. /// <returns>Private key as byte array</returns>
  2136. public static byte[] Curve25519ExportPrivateKey(IntPtr key)
  2137. {
  2138. byte[] privateKey = new byte[ED25519_KEY_SIZE];
  2139. uint privSize = (uint)privateKey.Length;
  2140. int ret = wc_curve25519_export_public(key, privateKey, ref privSize);
  2141. if (ret != 0)
  2142. {
  2143. throw new Exception("Failed to export Curve25519 private key. Error code: " + ret);
  2144. }
  2145. return privateKey;
  2146. }
  2147. /// <summary>
  2148. /// Export a Curve25519 public key to a byte array
  2149. /// </summary>
  2150. /// <param name="key">Curve25519 key structure</param>
  2151. /// <returns>Public key as byte array</returns>
  2152. public static byte[] Curve25519ExportPublicKey(IntPtr key)
  2153. {
  2154. byte[] publicKey = new byte[ED25519_PUB_KEY_SIZE];
  2155. uint pubSize = (uint)publicKey.Length;
  2156. int ret = wc_curve25519_export_public(key, publicKey, ref pubSize);
  2157. if (ret != 0)
  2158. {
  2159. throw new Exception("Failed to export Curve25519 public key. Error code: " + ret);
  2160. }
  2161. return publicKey;
  2162. }
  2163. /// <summary>
  2164. /// Export both private and public keys from a Curve25519 key structure
  2165. /// </summary>
  2166. /// <param name="key">Curve25519 key structure</param>
  2167. /// <returns>A tuple containing the private key and public key as byte arrays</returns>
  2168. public static (byte[] privateKey, byte[] publicKey) Curve25519ExportKeyRaw(IntPtr key)
  2169. {
  2170. byte[] privateKey = new byte[ED25519_KEY_SIZE];
  2171. byte[] publicKey = new byte[ED25519_PUB_KEY_SIZE];
  2172. uint privSize = (uint)privateKey.Length;
  2173. uint pubSize = (uint)publicKey.Length;
  2174. int ret = wc_curve25519_export_key_raw(key, privateKey, ref privSize, publicKey, ref pubSize);
  2175. if (ret != 0)
  2176. {
  2177. throw new Exception("Failed to export Curve25519 keys. Error code: " + ret);
  2178. }
  2179. return (privateKey, publicKey);
  2180. }
  2181. /* END RAW Curve25519 */
  2182. /***********************************************************************
  2183. * AES-GCM
  2184. **********************************************************************/
  2185. /// <summary>
  2186. /// Creates a new AES context.
  2187. /// </summary>
  2188. /// <param name="heap">Pointer to a memory heap, or IntPtr.Zero to use the default heap.</param>
  2189. /// <param name="devId">The device ID to associate with this AES context.</param>
  2190. /// <returns>A pointer to the newly created AES context, or IntPtr.Zero on failure.</returns>
  2191. public static IntPtr AesNew(IntPtr heap, int devId)
  2192. {
  2193. IntPtr aesPtr = IntPtr.Zero;
  2194. try
  2195. {
  2196. aesPtr = wc_AesNew(heap, devId, IntPtr.Zero);
  2197. if (aesPtr == IntPtr.Zero)
  2198. {
  2199. throw new Exception("Failed to create AES context.");
  2200. }
  2201. }
  2202. catch (Exception e)
  2203. {
  2204. Console.WriteLine($"AES context creation failed: {e.Message}");
  2205. }
  2206. return aesPtr;
  2207. }
  2208. /// <summary>
  2209. /// Initialize and set the AES key for AES-GCM operations.
  2210. /// </summary>
  2211. /// <param name="aes">AES-GCM context pointer.</param>
  2212. /// <param name="key">The AES key (either 128, 192, or 256 bits).</param>
  2213. /// <returns>0 on success, otherwise an error code.</returns>
  2214. public static int AesGcmSetKey(IntPtr aes, byte[] key)
  2215. {
  2216. IntPtr keyPtr = IntPtr.Zero;
  2217. int ret;
  2218. try
  2219. {
  2220. /* Allocate memory */
  2221. keyPtr = Marshal.AllocHGlobal(key.Length);
  2222. Marshal.Copy(key, 0, keyPtr, key.Length);
  2223. ret = wc_AesGcmSetKey(aes, keyPtr, (uint)key.Length);
  2224. if (ret != 0)
  2225. {
  2226. throw new Exception($"AES-GCM initialization failed with error code {ret}");
  2227. }
  2228. }
  2229. finally
  2230. {
  2231. /* Cleanup */
  2232. if (keyPtr != IntPtr.Zero) Marshal.FreeHGlobal(keyPtr);
  2233. }
  2234. return ret;
  2235. }
  2236. /// <summary>
  2237. /// Wrapper method to initialize the AES-GCM context with a given key and IV.
  2238. /// </summary>
  2239. /// <param name="aes">Pointer to the AES-GCM context that needs to be initialized.</param>
  2240. /// <param name="key">Byte array containing the AES key.</param>
  2241. /// <param name="iv">Byte array containing the initialization vector (IV).</param>
  2242. public static int AesGcmInit(IntPtr aes, byte[] key, byte[] iv)
  2243. {
  2244. IntPtr keyPtr = IntPtr.Zero;
  2245. IntPtr ivPtr = IntPtr.Zero;
  2246. int ret;
  2247. try
  2248. {
  2249. /* Allocate memory for key and IV */
  2250. keyPtr = Marshal.AllocHGlobal(key.Length);
  2251. Marshal.Copy(key, 0, keyPtr, key.Length);
  2252. ivPtr = Marshal.AllocHGlobal(iv.Length);
  2253. Marshal.Copy(iv, 0, ivPtr, iv.Length);
  2254. ret = wc_AesGcmInit(aes, keyPtr, (uint)key.Length, ivPtr, (uint)iv.Length);
  2255. if (ret != 0)
  2256. {
  2257. throw new Exception($"AES-GCM initialization failed with error code {ret}");
  2258. }
  2259. }
  2260. finally
  2261. {
  2262. /* Cleanup */
  2263. if (keyPtr != IntPtr.Zero) Marshal.FreeHGlobal(keyPtr);
  2264. if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr);
  2265. }
  2266. return ret;
  2267. }
  2268. /// <summary>
  2269. /// Encrypt data using AES-GCM
  2270. /// </summary>
  2271. /// <param name="aes">AES-GCM context pointer.</param>
  2272. /// <param name="iv">Initialization Vector (IV)</param>
  2273. /// <param name="plaintext">Data to encrypt</param>
  2274. /// <param name="ciphertext">Buffer to receive the encrypted data</param>
  2275. /// <param name="authTag">Buffer to receive the authentication tag</param>
  2276. /// <returns>0 on success, otherwise an error code</returns>
  2277. public static int AesGcmEncrypt(IntPtr aes, byte[] iv, byte[] plaintext,
  2278. byte[] ciphertext, byte[] authTag, byte[] addAuth = null)
  2279. {
  2280. int ret;
  2281. IntPtr ivPtr = IntPtr.Zero;
  2282. IntPtr ciphertextPtr = IntPtr.Zero;
  2283. IntPtr plaintextPtr = IntPtr.Zero;
  2284. IntPtr authTagPtr = IntPtr.Zero;
  2285. IntPtr addAuthPtr = IntPtr.Zero;
  2286. uint addAuthSz = 0;
  2287. try
  2288. {
  2289. /* Allocate memory */
  2290. ivPtr = Marshal.AllocHGlobal(iv.Length);
  2291. ciphertextPtr = Marshal.AllocHGlobal(ciphertext.Length);
  2292. plaintextPtr = Marshal.AllocHGlobal(plaintext.Length);
  2293. authTagPtr = Marshal.AllocHGlobal(authTag.Length);
  2294. if (addAuth != null) {
  2295. addAuthSz = (uint)addAuth.Length;
  2296. addAuthPtr = Marshal.AllocHGlobal(addAuth.Length);
  2297. Marshal.Copy(addAuth, 0, addAuthPtr, addAuth.Length);
  2298. }
  2299. Marshal.Copy(iv, 0, ivPtr, iv.Length);
  2300. Marshal.Copy(plaintext, 0, plaintextPtr, plaintext.Length);
  2301. /* Encrypt data */
  2302. ret = wc_AesGcmEncrypt(aes, ciphertextPtr, plaintextPtr, (uint)plaintext.Length,
  2303. ivPtr, (uint)iv.Length, authTagPtr, (uint)authTag.Length, addAuthPtr, addAuthSz);
  2304. if (ret < 0)
  2305. {
  2306. log(ERROR_LOG, "Failed to Encrypt data using AES-GCM. Error code: " + ret);
  2307. }
  2308. else {
  2309. Marshal.Copy(ciphertextPtr, ciphertext, 0, ciphertext.Length);
  2310. Marshal.Copy(authTagPtr, authTag, 0, authTag.Length);
  2311. ret = 0;
  2312. }
  2313. }
  2314. catch (Exception e)
  2315. {
  2316. log(ERROR_LOG, "AES-GCM Encryption failed: " + e.ToString());
  2317. ret = EXCEPTION_E;
  2318. }
  2319. finally
  2320. {
  2321. /* Cleanup */
  2322. if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr);
  2323. if (ciphertextPtr != IntPtr.Zero) Marshal.FreeHGlobal(ciphertextPtr);
  2324. if (plaintextPtr != IntPtr.Zero) Marshal.FreeHGlobal(plaintextPtr);
  2325. if (authTagPtr != IntPtr.Zero) Marshal.FreeHGlobal(authTagPtr);
  2326. if (addAuthPtr != IntPtr.Zero) Marshal.FreeHGlobal(addAuthPtr);
  2327. }
  2328. return ret;
  2329. }
  2330. /// <summary>
  2331. /// Decrypt data using AES-GCM
  2332. /// </summary>
  2333. /// <param name="aes">AES-GCM context pointer.</param>
  2334. /// <param name="iv">Initialization Vector (IV)</param>
  2335. /// <param name="ciphertext">Data to decrypt</param>
  2336. /// <param name="plaintext">Buffer to receive the decrypted data</param>
  2337. /// <param name="authTag">Authentication tag for verification</param>
  2338. /// <returns>0 on success, otherwise an error code</returns>
  2339. public static int AesGcmDecrypt(IntPtr aes, byte[] iv, byte[] ciphertext,
  2340. byte[] plaintext, byte[] authTag, byte[] addAuth = null)
  2341. {
  2342. int ret;
  2343. IntPtr ivPtr = IntPtr.Zero;
  2344. IntPtr ciphertextPtr = IntPtr.Zero;
  2345. IntPtr plaintextPtr = IntPtr.Zero;
  2346. IntPtr authTagPtr = IntPtr.Zero;
  2347. IntPtr addAuthPtr = IntPtr.Zero;
  2348. uint addAuthSz = 0;
  2349. try
  2350. {
  2351. /* Allocate memory */
  2352. ivPtr = Marshal.AllocHGlobal(iv.Length);
  2353. ciphertextPtr = Marshal.AllocHGlobal(ciphertext.Length);
  2354. plaintextPtr = Marshal.AllocHGlobal(plaintext.Length);
  2355. authTagPtr = Marshal.AllocHGlobal(authTag.Length);
  2356. if (addAuth != null) {
  2357. addAuthSz = (uint)addAuth.Length;
  2358. addAuthPtr = Marshal.AllocHGlobal(addAuth.Length);
  2359. Marshal.Copy(addAuth, 0, addAuthPtr, addAuth.Length);
  2360. }
  2361. Marshal.Copy(iv, 0, ivPtr, iv.Length);
  2362. Marshal.Copy(ciphertext, 0, ciphertextPtr, ciphertext.Length);
  2363. Marshal.Copy(authTag, 0, authTagPtr, authTag.Length);
  2364. /* Decrypt data */
  2365. ret = wc_AesGcmDecrypt(aes, plaintextPtr, ciphertextPtr, (uint)ciphertext.Length,
  2366. ivPtr, (uint)iv.Length, authTagPtr, (uint)authTag.Length, addAuthPtr, addAuthSz);
  2367. if (ret < 0)
  2368. {
  2369. log(ERROR_LOG, "Failed to Decrypt data using AES-GCM. Error code: " + ret);
  2370. }
  2371. else {
  2372. Marshal.Copy(plaintextPtr, plaintext, 0, plaintext.Length);
  2373. ret = 0;
  2374. }
  2375. }
  2376. catch (Exception e)
  2377. {
  2378. log(ERROR_LOG, "AES-GCM Decryption failed: " + e.ToString());
  2379. ret = EXCEPTION_E;
  2380. }
  2381. finally
  2382. {
  2383. /* Cleanup */
  2384. if (ivPtr != IntPtr.Zero) Marshal.FreeHGlobal(ivPtr);
  2385. if (ciphertextPtr != IntPtr.Zero) Marshal.FreeHGlobal(ciphertextPtr);
  2386. if (plaintextPtr != IntPtr.Zero) Marshal.FreeHGlobal(plaintextPtr);
  2387. if (authTagPtr != IntPtr.Zero) Marshal.FreeHGlobal(authTagPtr);
  2388. if (addAuthPtr != IntPtr.Zero) Marshal.FreeHGlobal(addAuthPtr);
  2389. }
  2390. return ret;
  2391. }
  2392. /// <summary>
  2393. /// Free AES-GCM context
  2394. /// </summary>
  2395. /// <param name="aes">AES-GCM context</param>
  2396. public static void AesGcmFree(IntPtr aes)
  2397. {
  2398. if (aes != IntPtr.Zero)
  2399. {
  2400. wc_AesDelete(aes, IntPtr.Zero);
  2401. aes = IntPtr.Zero;
  2402. }
  2403. }
  2404. /* END AES-GCM */
  2405. /***********************************************************************
  2406. * HASH
  2407. **********************************************************************/
  2408. /// <summary>
  2409. /// Allocate and set up a new hash context with proper error handling
  2410. /// </summary>
  2411. /// <param name="hashType">The type of hash (SHA-256, SHA-384, etc.)</param>
  2412. /// <param name="heap">Pointer to the heap for memory allocation (use IntPtr.Zero if not applicable)</param>
  2413. /// <param name="devId">Device ID (if applicable, otherwise use INVALID_DEVID)</param>
  2414. /// <returns>Allocated hash context pointer or IntPtr.Zero on failure</returns>
  2415. public static IntPtr HashNew(uint hashType, IntPtr heap, int devId)
  2416. {
  2417. IntPtr hash = IntPtr.Zero;
  2418. try
  2419. {
  2420. /* Allocate new hash */
  2421. hash = wc_HashNew(hashType, heap, devId, IntPtr.Zero);
  2422. if (hash == IntPtr.Zero)
  2423. {
  2424. throw new Exception("Failed to allocate new hash context.");
  2425. }
  2426. }
  2427. catch (Exception e)
  2428. {
  2429. log(ERROR_LOG, "HashNew Exception: " + e.ToString());
  2430. }
  2431. return hash;
  2432. }
  2433. /// <summary>
  2434. /// Initialize the hash context for a specific hash type with proper error handling
  2435. /// </summary>
  2436. /// <param name="hash">Hash context pointer</param>
  2437. /// <param name="hashType">The type of hash (SHA-256, SHA-384, etc.)</param>
  2438. /// <returns>0 on success, otherwise an error code</returns>
  2439. public static int InitHash(IntPtr hash, uint hashType)
  2440. {
  2441. int ret = 0;
  2442. try
  2443. {
  2444. /* Check hash */
  2445. if (hash == IntPtr.Zero)
  2446. throw new Exception("Hash context is null.");
  2447. ret = wc_HashInit(hash, hashType);
  2448. if (ret != 0)
  2449. {
  2450. throw new Exception($"Failed to initialize hash context. Error code: {ret}");
  2451. }
  2452. }
  2453. catch (Exception e)
  2454. {
  2455. /* Cleanup */
  2456. log(ERROR_LOG, "InitHash Exception: " + e.ToString());
  2457. if (hash != IntPtr.Zero) {
  2458. wc_HashDelete(hash, IntPtr.Zero);
  2459. hash = IntPtr.Zero;
  2460. }
  2461. }
  2462. return ret;
  2463. }
  2464. /// <summary>
  2465. /// Update the hash with data
  2466. /// </summary>
  2467. /// <param name="hash">Hash context pointer</param>
  2468. /// <param name="hashType">The type of hash</param>
  2469. /// <param name="data">Byte array of the data to hash</param>
  2470. /// <returns>0 on success, otherwise an error code</returns>
  2471. public static int HashUpdate(IntPtr hash, uint hashType, byte[] data)
  2472. {
  2473. int ret = 0;
  2474. IntPtr dataPtr = IntPtr.Zero;
  2475. try
  2476. {
  2477. /* Check parameters */
  2478. if (hash == IntPtr.Zero)
  2479. throw new Exception("Hash context is null.");
  2480. if (data == null || data.Length == 0)
  2481. throw new Exception("Invalid data array.");
  2482. /* Allocate memory */
  2483. dataPtr = Marshal.AllocHGlobal(data.Length);
  2484. Marshal.Copy(data, 0, dataPtr, data.Length);
  2485. /* Update hash */
  2486. ret = wc_HashUpdate(hash, hashType, dataPtr, (uint)data.Length);
  2487. if (ret != 0)
  2488. {
  2489. throw new Exception($"Failed to update hash. Error code: {ret}");
  2490. }
  2491. }
  2492. catch (Exception e)
  2493. {
  2494. log(ERROR_LOG, "HashUpdate Exception: " + e.ToString());
  2495. }
  2496. finally
  2497. {
  2498. /* Cleanup */
  2499. if (dataPtr != IntPtr.Zero) Marshal.FreeHGlobal(dataPtr);
  2500. }
  2501. return ret;
  2502. }
  2503. /// <summary>
  2504. /// Finalize the hash and output the result
  2505. /// </summary>
  2506. /// <param name="hash">Hash context pointer</param>
  2507. /// <param name="hashType">The type of hash</param>
  2508. /// <param name="output">Byte array where the hash output will be stored</param>
  2509. /// <returns>0 on success, otherwise an error code</returns>
  2510. public static int HashFinal(IntPtr hash, uint hashType, out byte[] output)
  2511. {
  2512. int ret = 0;
  2513. IntPtr outputPtr = IntPtr.Zero;
  2514. try
  2515. {
  2516. /* Get hash size and initialize */
  2517. int hashSize = wc_HashGetDigestSize(hashType);
  2518. output = new byte[hashSize];
  2519. /* Check hash */
  2520. if (hash == IntPtr.Zero)
  2521. throw new Exception("Hash context is null.");
  2522. if (hashSize <= 0)
  2523. throw new Exception("Invalid hash size.");
  2524. /* Allocate memory */
  2525. outputPtr = Marshal.AllocHGlobal(hashSize);
  2526. ret = wc_HashFinal(hash, hashType, outputPtr);
  2527. if (ret != 0)
  2528. {
  2529. throw new Exception($"Failed to finalize hash. Error code: {ret}");
  2530. }
  2531. Marshal.Copy(outputPtr, output, 0, hashSize);
  2532. }
  2533. catch (Exception e)
  2534. {
  2535. log(ERROR_LOG, "HashFinal Exception: " + e.ToString());
  2536. output = null;
  2537. }
  2538. finally
  2539. {
  2540. /* Cleanup */
  2541. if (outputPtr != IntPtr.Zero) Marshal.FreeHGlobal(outputPtr);
  2542. }
  2543. return ret;
  2544. }
  2545. /// <summary>
  2546. /// Free the allocated hash context with proper error handling
  2547. /// </summary>
  2548. /// <param name="hash">Hash context pointer to be freed</param>
  2549. /// <param name="hashType">The type of hash</param>
  2550. /// <returns>0 on success, otherwise an error code</returns>
  2551. public static int HashFree(IntPtr hash, uint hashType)
  2552. {
  2553. int ret = 0;
  2554. try
  2555. {
  2556. /* Check hash */
  2557. if (hash == IntPtr.Zero)
  2558. throw new Exception("Hash context is null, cannot free.");
  2559. /* Free hash */
  2560. ret = wc_HashDelete(hash, IntPtr.Zero);
  2561. hash = IntPtr.Zero;
  2562. if (ret != 0)
  2563. {
  2564. throw new Exception($"Failed to free hash context. Error code: {ret}");
  2565. }
  2566. }
  2567. catch (Exception e)
  2568. {
  2569. log(ERROR_LOG, "HashFree Exception: " + e.ToString());
  2570. }
  2571. return ret;
  2572. }
  2573. /// <summary>
  2574. /// Hash type enum values
  2575. /// </summary>
  2576. public enum hashType
  2577. {
  2578. WC_HASH_TYPE_NONE = 0,
  2579. WC_HASH_TYPE_MD2 = 1,
  2580. WC_HASH_TYPE_MD4 = 2,
  2581. WC_HASH_TYPE_MD5 = 3,
  2582. WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */
  2583. WC_HASH_TYPE_SHA224 = 5,
  2584. WC_HASH_TYPE_SHA256 = 6,
  2585. WC_HASH_TYPE_SHA384 = 7,
  2586. WC_HASH_TYPE_SHA512 = 8,
  2587. WC_HASH_TYPE_MD5_SHA = 9,
  2588. WC_HASH_TYPE_SHA3_224 = 10,
  2589. WC_HASH_TYPE_SHA3_256 = 11,
  2590. WC_HASH_TYPE_SHA3_384 = 12,
  2591. WC_HASH_TYPE_SHA3_512 = 13,
  2592. WC_HASH_TYPE_BLAKE2B = 14,
  2593. WC_HASH_TYPE_BLAKE2S = 15,
  2594. }
  2595. /* END HASH */
  2596. /***********************************************************************
  2597. * Logging / Other
  2598. **********************************************************************/
  2599. /// <summary>
  2600. /// Set the function to use for logging
  2601. /// </summary>
  2602. /// <param name="input">Function that conforms as to loggingCb</param>
  2603. /// <returns>0 on success</returns>
  2604. public static int SetLogging(loggingCb input)
  2605. {
  2606. internal_log = input;
  2607. return SUCCESS;
  2608. }
  2609. /// <summary>
  2610. /// Get error string for wolfCrypt error codes
  2611. /// </summary>
  2612. /// <param name="error">Negative error number from wolfCrypt API</param>
  2613. /// <returns>Error string</returns>
  2614. public static string GetError(int error)
  2615. {
  2616. try
  2617. {
  2618. IntPtr errStr = wc_GetErrorString(error);
  2619. return Marshal.PtrToStringAnsi(errStr);
  2620. }
  2621. catch (Exception e)
  2622. {
  2623. log(ERROR_LOG, "Get error exception " + e.ToString());
  2624. return string.Empty;
  2625. }
  2626. }
  2627. /// <summary>
  2628. /// Compares two byte arrays.
  2629. /// </summary>
  2630. /// <param name="array1">The first byte array to compare.</param>
  2631. /// <param name="array2">The second byte array to compare.</param>
  2632. /// <returns>True if both arrays are equal; otherwise, false.</returns>
  2633. public static bool ByteArrayVerify(byte[] array1, byte[] array2)
  2634. {
  2635. if (ReferenceEquals(array1, array2)) return true;
  2636. if (array1 == null || array2 == null) return false;
  2637. if (array1.Length != array2.Length) return false;
  2638. for (int i = 0; i < array1.Length; i++)
  2639. {
  2640. if (array1[i] != array2[i]) return false;
  2641. }
  2642. return true;
  2643. }
  2644. }
  2645. }