You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_cryptobox.c 74KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /***
  17. * @module rspamd_cryptobox
  18. * Rspamd cryptobox is a module that operates with digital signatures and
  19. * hashes.
  20. * @example
  21. * local hash = require "rspamd_cryptobox_hash"
  22. *
  23. * local h = hash.create()
  24. * h:update('hello world')
  25. * print(h:hex())
  26. */
  27. #include "lua_common.h"
  28. #include "libcryptobox/cryptobox.h"
  29. #include "libcryptobox/keypair.h"
  30. #include "libcryptobox/keypair_private.h"
  31. #include "unix-std.h"
  32. #include "contrib/libottery/ottery.h"
  33. #include "libutil/ref.h"
  34. #include <stdalign.h>
  35. #include <openssl/hmac.h>
  36. enum lua_cryptobox_hash_type {
  37. LUA_CRYPTOBOX_HASH_BLAKE2 = 0,
  38. LUA_CRYPTOBOX_HASH_SSL,
  39. LUA_CRYPTOBOX_HASH_HMAC,
  40. LUA_CRYPTOBOX_HASH_XXHASH64,
  41. LUA_CRYPTOBOX_HASH_XXHASH32,
  42. LUA_CRYPTOBOX_HASH_XXHASH3,
  43. LUA_CRYPTOBOX_HASH_MUM,
  44. LUA_CRYPTOBOX_HASH_T1HA,
  45. };
  46. struct rspamd_lua_cryptobox_hash {
  47. union {
  48. rspamd_cryptobox_hash_state_t *h;
  49. EVP_MD_CTX *c;
  50. HMAC_CTX *hmac_c;
  51. rspamd_cryptobox_fast_hash_state_t *fh;
  52. } content;
  53. unsigned char out[rspamd_cryptobox_HASHBYTES];
  54. uint8_t type;
  55. uint8_t out_len;
  56. uint8_t is_finished;
  57. ref_entry_t ref;
  58. };
  59. LUA_FUNCTION_DEF(cryptobox_pubkey, load);
  60. LUA_FUNCTION_DEF(cryptobox_pubkey, create);
  61. LUA_FUNCTION_DEF(cryptobox_pubkey, gc);
  62. LUA_FUNCTION_DEF(cryptobox_keypair, load);
  63. LUA_FUNCTION_DEF(cryptobox_keypair, create);
  64. LUA_FUNCTION_DEF(cryptobox_keypair, gc);
  65. LUA_FUNCTION_DEF(cryptobox_keypair, totable);
  66. LUA_FUNCTION_DEF(cryptobox_keypair, get_type);
  67. LUA_FUNCTION_DEF(cryptobox_keypair, get_alg);
  68. LUA_FUNCTION_DEF(cryptobox_keypair, get_pk);
  69. LUA_FUNCTION_DEF(cryptobox_signature, create);
  70. LUA_FUNCTION_DEF(cryptobox_signature, load);
  71. LUA_FUNCTION_DEF(cryptobox_signature, save);
  72. LUA_FUNCTION_DEF(cryptobox_signature, gc);
  73. LUA_FUNCTION_DEF(cryptobox_signature, hex);
  74. LUA_FUNCTION_DEF(cryptobox_signature, base32);
  75. LUA_FUNCTION_DEF(cryptobox_signature, base64);
  76. LUA_FUNCTION_DEF(cryptobox_signature, bin);
  77. LUA_FUNCTION_DEF(cryptobox_hash, create);
  78. LUA_FUNCTION_DEF(cryptobox_hash, create_specific);
  79. LUA_FUNCTION_DEF(cryptobox_hash, create_specific_keyed);
  80. LUA_FUNCTION_DEF(cryptobox_hash, create_keyed);
  81. LUA_FUNCTION_DEF(cryptobox_hash, update);
  82. LUA_FUNCTION_DEF(cryptobox_hash, reset);
  83. LUA_FUNCTION_DEF(cryptobox_hash, hex);
  84. LUA_FUNCTION_DEF(cryptobox_hash, base32);
  85. LUA_FUNCTION_DEF(cryptobox_hash, base64);
  86. LUA_FUNCTION_DEF(cryptobox_hash, bin);
  87. LUA_FUNCTION_DEF(cryptobox_hash, gc);
  88. LUA_FUNCTION_DEF(cryptobox, verify_memory);
  89. LUA_FUNCTION_DEF(cryptobox, verify_file);
  90. LUA_FUNCTION_DEF(cryptobox, sign_file);
  91. LUA_FUNCTION_DEF(cryptobox, sign_memory);
  92. LUA_FUNCTION_DEF(cryptobox, encrypt_memory);
  93. LUA_FUNCTION_DEF(cryptobox, encrypt_file);
  94. LUA_FUNCTION_DEF(cryptobox, decrypt_memory);
  95. LUA_FUNCTION_DEF(cryptobox, decrypt_file);
  96. LUA_FUNCTION_DEF(cryptobox, encrypt_cookie);
  97. LUA_FUNCTION_DEF(cryptobox, decrypt_cookie);
  98. LUA_FUNCTION_DEF(cryptobox, pbkdf);
  99. LUA_FUNCTION_DEF(cryptobox, gen_dkim_keypair);
  100. /* Secretbox API: uses libsodium secretbox and blake2b for key derivation */
  101. LUA_FUNCTION_DEF(cryptobox_secretbox, create);
  102. LUA_FUNCTION_DEF(cryptobox_secretbox, encrypt);
  103. LUA_FUNCTION_DEF(cryptobox_secretbox, decrypt);
  104. LUA_FUNCTION_DEF(cryptobox_secretbox, gc);
  105. static const struct luaL_reg cryptoboxlib_f[] = {
  106. LUA_INTERFACE_DEF(cryptobox, verify_memory),
  107. LUA_INTERFACE_DEF(cryptobox, verify_file),
  108. LUA_INTERFACE_DEF(cryptobox, sign_memory),
  109. LUA_INTERFACE_DEF(cryptobox, sign_file),
  110. LUA_INTERFACE_DEF(cryptobox, encrypt_memory),
  111. LUA_INTERFACE_DEF(cryptobox, encrypt_file),
  112. LUA_INTERFACE_DEF(cryptobox, decrypt_memory),
  113. LUA_INTERFACE_DEF(cryptobox, decrypt_file),
  114. LUA_INTERFACE_DEF(cryptobox, encrypt_cookie),
  115. LUA_INTERFACE_DEF(cryptobox, decrypt_cookie),
  116. LUA_INTERFACE_DEF(cryptobox, pbkdf),
  117. LUA_INTERFACE_DEF(cryptobox, gen_dkim_keypair),
  118. {NULL, NULL}};
  119. static const struct luaL_reg cryptoboxpubkeylib_f[] = {
  120. LUA_INTERFACE_DEF(cryptobox_pubkey, load),
  121. LUA_INTERFACE_DEF(cryptobox_pubkey, create),
  122. {NULL, NULL}};
  123. static const struct luaL_reg cryptoboxpubkeylib_m[] = {
  124. {"__tostring", rspamd_lua_class_tostring},
  125. {"__gc", lua_cryptobox_pubkey_gc},
  126. {NULL, NULL}};
  127. static const struct luaL_reg cryptoboxkeypairlib_f[] = {
  128. LUA_INTERFACE_DEF(cryptobox_keypair, load),
  129. LUA_INTERFACE_DEF(cryptobox_keypair, create),
  130. {NULL, NULL}};
  131. static const struct luaL_reg cryptoboxkeypairlib_m[] = {
  132. {"__tostring", rspamd_lua_class_tostring},
  133. {"totable", lua_cryptobox_keypair_totable},
  134. {"get_type", lua_cryptobox_keypair_get_type},
  135. {"get_alg", lua_cryptobox_keypair_get_alg},
  136. {"type", lua_cryptobox_keypair_get_type},
  137. {"alg", lua_cryptobox_keypair_get_alg},
  138. {"pk", lua_cryptobox_keypair_get_pk},
  139. {"pubkey", lua_cryptobox_keypair_get_pk},
  140. {"__gc", lua_cryptobox_keypair_gc},
  141. {NULL, NULL}};
  142. static const struct luaL_reg cryptoboxsignlib_f[] = {
  143. LUA_INTERFACE_DEF(cryptobox_signature, load),
  144. LUA_INTERFACE_DEF(cryptobox_signature, create),
  145. {NULL, NULL}};
  146. static const struct luaL_reg cryptoboxsignlib_m[] = {
  147. LUA_INTERFACE_DEF(cryptobox_signature, save),
  148. LUA_INTERFACE_DEF(cryptobox_signature, hex),
  149. LUA_INTERFACE_DEF(cryptobox_signature, base32),
  150. LUA_INTERFACE_DEF(cryptobox_signature, base64),
  151. LUA_INTERFACE_DEF(cryptobox_signature, bin),
  152. {"__tostring", rspamd_lua_class_tostring},
  153. {"__gc", lua_cryptobox_signature_gc},
  154. {NULL, NULL}};
  155. static const struct luaL_reg cryptoboxhashlib_f[] = {
  156. LUA_INTERFACE_DEF(cryptobox_hash, create),
  157. LUA_INTERFACE_DEF(cryptobox_hash, create_keyed),
  158. LUA_INTERFACE_DEF(cryptobox_hash, create_specific),
  159. LUA_INTERFACE_DEF(cryptobox_hash, create_specific_keyed),
  160. {NULL, NULL}};
  161. static const struct luaL_reg cryptoboxhashlib_m[] = {
  162. LUA_INTERFACE_DEF(cryptobox_hash, update),
  163. LUA_INTERFACE_DEF(cryptobox_hash, reset),
  164. LUA_INTERFACE_DEF(cryptobox_hash, hex),
  165. LUA_INTERFACE_DEF(cryptobox_hash, base32),
  166. LUA_INTERFACE_DEF(cryptobox_hash, base64),
  167. LUA_INTERFACE_DEF(cryptobox_hash, bin),
  168. {"__tostring", rspamd_lua_class_tostring},
  169. {"__gc", lua_cryptobox_hash_gc},
  170. {NULL, NULL}};
  171. static const struct luaL_reg cryptoboxsecretboxlib_f[] = {
  172. LUA_INTERFACE_DEF(cryptobox_secretbox, create),
  173. {NULL, NULL},
  174. };
  175. static const struct luaL_reg cryptoboxsecretboxlib_m[] = {
  176. LUA_INTERFACE_DEF(cryptobox_secretbox, encrypt),
  177. LUA_INTERFACE_DEF(cryptobox_secretbox, decrypt),
  178. {"__gc", lua_cryptobox_secretbox_gc},
  179. {NULL, NULL},
  180. };
  181. struct rspamd_lua_cryptobox_secretbox {
  182. guchar sk[crypto_secretbox_KEYBYTES];
  183. };
  184. static struct rspamd_cryptobox_pubkey *
  185. lua_check_cryptobox_pubkey(lua_State *L, int pos)
  186. {
  187. void *ud = rspamd_lua_check_udata(L, pos, rspamd_cryptobox_pubkey_classname);
  188. luaL_argcheck(L, ud != NULL, 1, "'cryptobox_pubkey' expected");
  189. return ud ? *((struct rspamd_cryptobox_pubkey **) ud) : NULL;
  190. }
  191. static struct rspamd_cryptobox_keypair *
  192. lua_check_cryptobox_keypair(lua_State *L, int pos)
  193. {
  194. void *ud = rspamd_lua_check_udata(L, pos, rspamd_cryptobox_keypair_classname);
  195. luaL_argcheck(L, ud != NULL, 1, "'cryptobox_keypair' expected");
  196. return ud ? *((struct rspamd_cryptobox_keypair **) ud) : NULL;
  197. }
  198. static rspamd_fstring_t *
  199. lua_check_cryptobox_sign(lua_State *L, int pos)
  200. {
  201. void *ud = rspamd_lua_check_udata(L, pos, rspamd_cryptobox_signature_classname);
  202. luaL_argcheck(L, ud != NULL, 1, "'cryptobox_signature' expected");
  203. return ud ? *((rspamd_fstring_t **) ud) : NULL;
  204. }
  205. struct rspamd_lua_cryptobox_hash *
  206. lua_check_cryptobox_hash(lua_State *L, int pos)
  207. {
  208. void *ud = rspamd_lua_check_udata(L, pos, rspamd_cryptobox_hash_classname);
  209. luaL_argcheck(L, ud != NULL, 1, "'cryptobox_hash' expected");
  210. return ud ? *((struct rspamd_lua_cryptobox_hash **) ud) : NULL;
  211. }
  212. static struct rspamd_lua_cryptobox_secretbox *
  213. lua_check_cryptobox_secretbox(lua_State *L, int pos)
  214. {
  215. void *ud = rspamd_lua_check_udata(L, pos, rspamd_cryptobox_secretbox_classname);
  216. luaL_argcheck(L, ud != NULL, 1, "'cryptobox_secretbox' expected");
  217. return ud ? *((struct rspamd_lua_cryptobox_secretbox **) ud) : NULL;
  218. }
  219. /***
  220. * @function rspamd_cryptobox_pubkey.load(file[, type[, alg]])
  221. * Loads public key from base32 encoded file
  222. * @param {string} file filename to load
  223. * @param {string} type optional 'sign' or 'kex' for signing and encryption
  224. * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
  225. * @return {cryptobox_pubkey} new public key
  226. */
  227. static gint
  228. lua_cryptobox_pubkey_load(lua_State *L)
  229. {
  230. LUA_TRACE_POINT;
  231. struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
  232. const gchar *filename, *arg;
  233. gint type = RSPAMD_KEYPAIR_SIGN;
  234. gint alg = RSPAMD_CRYPTOBOX_MODE_25519;
  235. guchar *map;
  236. gsize len;
  237. filename = luaL_checkstring(L, 1);
  238. if (filename != NULL) {
  239. map = rspamd_file_xmap(filename, PROT_READ, &len, TRUE);
  240. if (map == NULL) {
  241. msg_err("cannot open pubkey from file: %s, %s",
  242. filename,
  243. strerror(errno));
  244. lua_pushnil(L);
  245. }
  246. else {
  247. if (lua_type(L, 2) == LUA_TSTRING) {
  248. /* keypair type */
  249. arg = lua_tostring(L, 2);
  250. if (strcmp(arg, "sign") == 0) {
  251. type = RSPAMD_KEYPAIR_SIGN;
  252. }
  253. else if (strcmp(arg, "kex") == 0) {
  254. type = RSPAMD_KEYPAIR_KEX;
  255. }
  256. }
  257. if (lua_type(L, 3) == LUA_TSTRING) {
  258. /* algorithm */
  259. arg = lua_tostring(L, 3);
  260. if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
  261. type = RSPAMD_CRYPTOBOX_MODE_25519;
  262. }
  263. else if (strcmp(arg, "nist") == 0) {
  264. type = RSPAMD_CRYPTOBOX_MODE_NIST;
  265. }
  266. }
  267. pkey = rspamd_pubkey_from_base32(map, len, type, alg);
  268. if (pkey == NULL) {
  269. msg_err("cannot open pubkey from file: %s", filename);
  270. munmap(map, len);
  271. lua_pushnil(L);
  272. }
  273. else {
  274. munmap(map, len);
  275. ppkey = lua_newuserdata(L, sizeof(void *));
  276. rspamd_lua_setclass(L, rspamd_cryptobox_pubkey_classname, -1);
  277. *ppkey = pkey;
  278. }
  279. }
  280. }
  281. else {
  282. return luaL_error(L, "bad input arguments");
  283. }
  284. return 1;
  285. }
  286. /***
  287. * @function rspamd_cryptobox_pubkey.create(data[, type[, alg]])
  288. * Loads public key from base32 encoded string
  289. * @param {base32 string} base32 string with the key
  290. * @param {string} type optional 'sign' or 'kex' for signing and encryption
  291. * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
  292. * @return {cryptobox_pubkey} new public key
  293. */
  294. static gint
  295. lua_cryptobox_pubkey_create(lua_State *L)
  296. {
  297. LUA_TRACE_POINT;
  298. struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
  299. const gchar *buf, *arg;
  300. gsize len;
  301. gint type = RSPAMD_KEYPAIR_SIGN;
  302. gint alg = RSPAMD_CRYPTOBOX_MODE_25519;
  303. buf = luaL_checklstring(L, 1, &len);
  304. if (buf != NULL) {
  305. if (lua_type(L, 2) == LUA_TSTRING) {
  306. /* keypair type */
  307. arg = lua_tostring(L, 2);
  308. if (strcmp(arg, "sign") == 0) {
  309. type = RSPAMD_KEYPAIR_SIGN;
  310. }
  311. else if (strcmp(arg, "kex") == 0) {
  312. type = RSPAMD_KEYPAIR_KEX;
  313. }
  314. }
  315. if (lua_type(L, 3) == LUA_TSTRING) {
  316. /* algorithm */
  317. arg = lua_tostring(L, 3);
  318. if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
  319. type = RSPAMD_CRYPTOBOX_MODE_25519;
  320. }
  321. else if (strcmp(arg, "nist") == 0) {
  322. type = RSPAMD_CRYPTOBOX_MODE_NIST;
  323. }
  324. }
  325. pkey = rspamd_pubkey_from_base32(buf, len, type, alg);
  326. if (pkey == NULL) {
  327. msg_err("cannot load pubkey from string");
  328. lua_pushnil(L);
  329. }
  330. else {
  331. ppkey = lua_newuserdata(L, sizeof(void *));
  332. rspamd_lua_setclass(L, rspamd_cryptobox_pubkey_classname, -1);
  333. *ppkey = pkey;
  334. }
  335. }
  336. else {
  337. return luaL_error(L, "bad input arguments");
  338. }
  339. return 1;
  340. }
  341. static gint
  342. lua_cryptobox_pubkey_gc(lua_State *L)
  343. {
  344. LUA_TRACE_POINT;
  345. struct rspamd_cryptobox_pubkey *pkey = lua_check_cryptobox_pubkey(L, 1);
  346. if (pkey != NULL) {
  347. rspamd_pubkey_unref(pkey);
  348. }
  349. return 0;
  350. }
  351. /***
  352. * @function rspamd_cryptobox_keypair.load(file|table)
  353. * Loads public key from UCL file or directly from Lua
  354. * @param {string} file filename to load
  355. * @return {cryptobox_keypair} new keypair
  356. */
  357. static gint
  358. lua_cryptobox_keypair_load(lua_State *L)
  359. {
  360. LUA_TRACE_POINT;
  361. struct rspamd_cryptobox_keypair *kp, **pkp;
  362. const gchar *buf;
  363. gsize len;
  364. struct ucl_parser *parser;
  365. ucl_object_t *obj;
  366. if (lua_type(L, 1) == LUA_TSTRING) {
  367. buf = luaL_checklstring(L, 1, &len);
  368. if (buf != NULL) {
  369. parser = ucl_parser_new(0);
  370. if (!ucl_parser_add_chunk(parser, buf, len)) {
  371. msg_err("cannot open keypair from data: %s",
  372. ucl_parser_get_error(parser));
  373. ucl_parser_free(parser);
  374. lua_pushnil(L);
  375. }
  376. else {
  377. obj = ucl_parser_get_object(parser);
  378. kp = rspamd_keypair_from_ucl(obj);
  379. ucl_parser_free(parser);
  380. if (kp == NULL) {
  381. msg_err("cannot load keypair from data");
  382. ucl_object_unref(obj);
  383. lua_pushnil(L);
  384. }
  385. else {
  386. pkp = lua_newuserdata(L, sizeof(gpointer));
  387. *pkp = kp;
  388. rspamd_lua_setclass(L, rspamd_cryptobox_keypair_classname, -1);
  389. ucl_object_unref(obj);
  390. }
  391. }
  392. }
  393. else {
  394. luaL_error(L, "bad input arguments");
  395. }
  396. }
  397. else {
  398. /* Directly import from lua */
  399. obj = ucl_object_lua_import(L, 1);
  400. kp = rspamd_keypair_from_ucl(obj);
  401. if (kp == NULL) {
  402. msg_err("cannot load keypair from data");
  403. ucl_object_unref(obj);
  404. lua_pushnil(L);
  405. }
  406. else {
  407. pkp = lua_newuserdata(L, sizeof(gpointer));
  408. *pkp = kp;
  409. rspamd_lua_setclass(L, rspamd_cryptobox_keypair_classname, -1);
  410. ucl_object_unref(obj);
  411. }
  412. }
  413. return 1;
  414. }
  415. /***
  416. * @function rspamd_cryptobox_keypair.create([type='encryption'[, alg='curve25519']])
  417. * Generates new keypair
  418. * @param {string} type type of keypair: 'encryption' (default) or 'sign'
  419. * @param {string} alg algorithm of keypair: 'curve25519' (default) or 'nist'
  420. * @return {cryptobox_keypair} new keypair
  421. */
  422. static gint
  423. lua_cryptobox_keypair_create(lua_State *L)
  424. {
  425. LUA_TRACE_POINT;
  426. struct rspamd_cryptobox_keypair *kp, **pkp;
  427. enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
  428. enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
  429. if (lua_isstring(L, 1)) {
  430. const gchar *str = lua_tostring(L, 1);
  431. if (strcmp(str, "sign") == 0) {
  432. type = RSPAMD_KEYPAIR_SIGN;
  433. }
  434. else if (strcmp(str, "encryption") == 0) {
  435. type = RSPAMD_KEYPAIR_KEX;
  436. }
  437. else {
  438. return luaL_error(L, "invalid keypair type: %s", str);
  439. }
  440. }
  441. if (lua_isstring(L, 2)) {
  442. const gchar *str = lua_tostring(L, 2);
  443. if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
  444. alg = RSPAMD_CRYPTOBOX_MODE_NIST;
  445. }
  446. else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
  447. alg = RSPAMD_CRYPTOBOX_MODE_25519;
  448. }
  449. else {
  450. return luaL_error(L, "invalid keypair algorithm: %s", str);
  451. }
  452. }
  453. kp = rspamd_keypair_new(type, alg);
  454. pkp = lua_newuserdata(L, sizeof(gpointer));
  455. *pkp = kp;
  456. rspamd_lua_setclass(L, rspamd_cryptobox_keypair_classname, -1);
  457. return 1;
  458. }
  459. static gint
  460. lua_cryptobox_keypair_gc(lua_State *L)
  461. {
  462. LUA_TRACE_POINT;
  463. struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
  464. if (kp != NULL) {
  465. rspamd_keypair_unref(kp);
  466. }
  467. return 0;
  468. }
  469. /***
  470. * @method keypair:totable([hex=false]])
  471. * Converts keypair to table (not very safe due to memory leftovers)
  472. */
  473. static gint
  474. lua_cryptobox_keypair_totable(lua_State *L)
  475. {
  476. LUA_TRACE_POINT;
  477. struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
  478. ucl_object_t *obj;
  479. gboolean hex = FALSE;
  480. gint ret = 1;
  481. if (kp != NULL) {
  482. if (lua_isboolean(L, 2)) {
  483. hex = lua_toboolean(L, 2);
  484. }
  485. obj = rspamd_keypair_to_ucl(kp, hex ? RSPAMD_KEYPAIR_DUMP_HEX : RSPAMD_KEYPAIR_DUMP_DEFAULT);
  486. ret = ucl_object_push_lua(L, obj, true);
  487. ucl_object_unref(obj);
  488. }
  489. else {
  490. return luaL_error(L, "invalid arguments");
  491. }
  492. return ret;
  493. }
  494. /***
  495. * @method keypair:type()
  496. * Returns type of keypair as a string: 'encryption' or 'sign'
  497. * @return {string} type of keypair as a string
  498. */
  499. static gint
  500. lua_cryptobox_keypair_get_type(lua_State *L)
  501. {
  502. LUA_TRACE_POINT;
  503. struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
  504. if (kp) {
  505. if (kp->type == RSPAMD_KEYPAIR_KEX) {
  506. lua_pushstring(L, "encryption");
  507. }
  508. else {
  509. lua_pushstring(L, "sign");
  510. }
  511. }
  512. else {
  513. return luaL_error(L, "invalid arguments");
  514. }
  515. return 1;
  516. }
  517. /***
  518. * @method keypair:alg()
  519. * Returns algorithm of keypair as a string: 'encryption' or 'sign'
  520. * @return {string} type of keypair as a string
  521. */
  522. static gint
  523. lua_cryptobox_keypair_get_alg(lua_State *L)
  524. {
  525. LUA_TRACE_POINT;
  526. struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
  527. if (kp) {
  528. if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
  529. lua_pushstring(L, "curve25519");
  530. }
  531. else {
  532. lua_pushstring(L, "nist");
  533. }
  534. }
  535. else {
  536. return luaL_error(L, "invalid arguments");
  537. }
  538. return 1;
  539. }
  540. /***
  541. * @method keypair:pk()
  542. * Returns pubkey for a specific keypair
  543. * @return {rspamd_pubkey} pubkey for a keypair
  544. */
  545. static gint
  546. lua_cryptobox_keypair_get_pk(lua_State *L)
  547. {
  548. LUA_TRACE_POINT;
  549. struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
  550. struct rspamd_cryptobox_pubkey *pk, **ppk;
  551. const guchar *data;
  552. guint dlen;
  553. if (kp) {
  554. data = rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_PK, &dlen);
  555. pk = rspamd_pubkey_from_bin(data, dlen, kp->type, kp->alg);
  556. if (pk == NULL) {
  557. return luaL_error(L, "invalid keypair");
  558. }
  559. ppk = lua_newuserdata(L, sizeof(*ppk));
  560. *ppk = pk;
  561. rspamd_lua_setclass(L, rspamd_cryptobox_pubkey_classname, -1);
  562. }
  563. else {
  564. return luaL_error(L, "invalid arguments");
  565. }
  566. return 1;
  567. }
  568. /***
  569. * @function rspamd_cryptobox_signature.load(file, [alg = 'curve25519'])
  570. * Loads signature from raw file
  571. * @param {string} file filename to load
  572. * @return {cryptobox_signature} new signature
  573. */
  574. static gint
  575. lua_cryptobox_signature_load(lua_State *L)
  576. {
  577. LUA_TRACE_POINT;
  578. rspamd_fstring_t *sig, **psig;
  579. const gchar *filename;
  580. gpointer data;
  581. int fd;
  582. struct stat st;
  583. enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
  584. filename = luaL_checkstring(L, 1);
  585. if (filename != NULL) {
  586. fd = open(filename, O_RDONLY);
  587. if (fd == -1) {
  588. msg_err("cannot open signature file: %s, %s", filename,
  589. strerror(errno));
  590. lua_pushnil(L);
  591. }
  592. else {
  593. if (fstat(fd, &st) == -1 ||
  594. (data =
  595. mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
  596. msg_err("cannot mmap file %s: %s", filename, strerror(errno));
  597. lua_pushnil(L);
  598. }
  599. else {
  600. if (lua_isstring(L, 2)) {
  601. const gchar *str = lua_tostring(L, 2);
  602. if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
  603. alg = RSPAMD_CRYPTOBOX_MODE_NIST;
  604. }
  605. else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
  606. alg = RSPAMD_CRYPTOBOX_MODE_25519;
  607. }
  608. else {
  609. munmap(data, st.st_size);
  610. close(fd);
  611. return luaL_error(L, "invalid keypair algorithm: %s", str);
  612. }
  613. }
  614. if (st.st_size > 0) {
  615. sig = rspamd_fstring_new_init(data, st.st_size);
  616. psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
  617. rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
  618. *psig = sig;
  619. }
  620. else {
  621. msg_err("size of %s mismatches: %d while %d is expected",
  622. filename, (int) st.st_size,
  623. rspamd_cryptobox_signature_bytes(alg));
  624. lua_pushnil(L);
  625. }
  626. munmap(data, st.st_size);
  627. }
  628. close(fd);
  629. }
  630. }
  631. else {
  632. luaL_error(L, "bad input arguments");
  633. }
  634. return 1;
  635. }
  636. /***
  637. * @method rspamd_cryptobox_signature:save(file)
  638. * Stores signature in raw file
  639. * @param {string} file filename to use
  640. * @return {boolean} true if signature has been saved
  641. */
  642. static gint
  643. lua_cryptobox_signature_save(lua_State *L)
  644. {
  645. LUA_TRACE_POINT;
  646. rspamd_fstring_t *sig;
  647. gint fd, flags;
  648. const gchar *filename;
  649. gboolean forced = FALSE, res = TRUE;
  650. sig = lua_check_cryptobox_sign(L, 1);
  651. filename = luaL_checkstring(L, 2);
  652. if (!sig || !filename) {
  653. luaL_error(L, "bad input arguments");
  654. return 1;
  655. }
  656. if (lua_gettop(L) > 2) {
  657. forced = lua_toboolean(L, 3);
  658. }
  659. if (sig != NULL && filename != NULL) {
  660. flags = O_WRONLY | O_CREAT;
  661. if (forced) {
  662. flags |= O_TRUNC;
  663. }
  664. else {
  665. flags |= O_EXCL;
  666. }
  667. fd = open(filename, flags, 00644);
  668. if (fd == -1) {
  669. msg_err("cannot create a signature file: %s, %s",
  670. filename,
  671. strerror(errno));
  672. lua_pushboolean(L, FALSE);
  673. }
  674. else {
  675. while (write(fd, sig->str, sig->len) == -1) {
  676. if (errno == EINTR) {
  677. continue;
  678. }
  679. msg_err("cannot write to a signature file: %s, %s",
  680. filename,
  681. strerror(errno));
  682. res = FALSE;
  683. break;
  684. }
  685. lua_pushboolean(L, res);
  686. close(fd);
  687. }
  688. }
  689. else {
  690. return luaL_error(L, "invalid arguments");
  691. }
  692. return 1;
  693. }
  694. /***
  695. * @function rspamd_cryptobox_signature.create(data)
  696. * Creates signature object from raw data
  697. * @param {data} raw signature data
  698. * @return {cryptobox_signature} signature object
  699. */
  700. static gint
  701. lua_cryptobox_signature_create(lua_State *L)
  702. {
  703. LUA_TRACE_POINT;
  704. rspamd_fstring_t *sig, **psig;
  705. struct rspamd_lua_text *t;
  706. const gchar *data;
  707. gsize dlen;
  708. if (lua_isuserdata(L, 1)) {
  709. t = lua_check_text(L, 1);
  710. if (!t) {
  711. return luaL_error(L, "invalid arguments");
  712. }
  713. data = t->start;
  714. dlen = t->len;
  715. }
  716. else {
  717. data = luaL_checklstring(L, 1, &dlen);
  718. }
  719. if (data != NULL) {
  720. if (dlen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) {
  721. sig = rspamd_fstring_new_init(data, dlen);
  722. psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
  723. rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
  724. *psig = sig;
  725. }
  726. }
  727. else {
  728. return luaL_error(L, "bad input arguments");
  729. }
  730. return 1;
  731. }
  732. /***
  733. * @method cryptobox_signature:hex()
  734. * Return hex encoded signature string
  735. * @return {string} raw value of signature
  736. */
  737. static gint
  738. lua_cryptobox_signature_hex(lua_State *L)
  739. {
  740. LUA_TRACE_POINT;
  741. rspamd_fstring_t *sig = lua_check_cryptobox_sign(L, 1);
  742. gchar *encoded;
  743. if (sig) {
  744. encoded = rspamd_encode_hex(sig->str, sig->len);
  745. lua_pushstring(L, encoded);
  746. g_free(encoded);
  747. }
  748. else {
  749. return luaL_error(L, "invalid arguments");
  750. }
  751. return 1;
  752. }
  753. /***
  754. * @method cryptobox_signature:base32([b32type='default'])
  755. * Return base32 encoded signature string
  756. * @param {string} b32type base32 type (default, bleach, rfc)
  757. * @return {string} raw value of signature
  758. */
  759. static gint
  760. lua_cryptobox_signature_base32(lua_State *L)
  761. {
  762. LUA_TRACE_POINT;
  763. rspamd_fstring_t *sig = lua_check_cryptobox_sign(L, 1);
  764. gchar *encoded;
  765. enum rspamd_base32_type btype = RSPAMD_BASE32_DEFAULT;
  766. if (lua_type(L, 2) == LUA_TSTRING) {
  767. btype = rspamd_base32_decode_type_from_str(lua_tostring(L, 2));
  768. if (btype == RSPAMD_BASE32_INVALID) {
  769. return luaL_error(L, "invalid b32 type: %s", lua_tostring(L, 2));
  770. }
  771. }
  772. if (sig) {
  773. encoded = rspamd_encode_base32(sig->str, sig->len, btype);
  774. lua_pushstring(L, encoded);
  775. g_free(encoded);
  776. }
  777. else {
  778. return luaL_error(L, "invalid arguments");
  779. }
  780. return 1;
  781. }
  782. /***
  783. * @method cryptobox_signature:base64()
  784. * Return base64 encoded signature string
  785. * @return {string} raw value of signature
  786. */
  787. static gint
  788. lua_cryptobox_signature_base64(lua_State *L)
  789. {
  790. LUA_TRACE_POINT;
  791. rspamd_fstring_t *sig = lua_check_cryptobox_sign(L, 1);
  792. gsize dlen;
  793. gchar *encoded;
  794. if (sig) {
  795. encoded = rspamd_encode_base64(sig->str, sig->len, 0, &dlen);
  796. lua_pushlstring(L, encoded, dlen);
  797. g_free(encoded);
  798. }
  799. else {
  800. return luaL_error(L, "invalid arguments");
  801. }
  802. return 1;
  803. }
  804. /***
  805. * @method cryptobox_signature:bin()
  806. * Return raw signature string
  807. * @return {string} raw value of signature
  808. */
  809. static gint
  810. lua_cryptobox_signature_bin(lua_State *L)
  811. {
  812. LUA_TRACE_POINT;
  813. rspamd_fstring_t *sig = lua_check_cryptobox_sign(L, 1);
  814. if (sig) {
  815. lua_pushlstring(L, sig->str, sig->len);
  816. }
  817. else {
  818. return luaL_error(L, "invalid arguments");
  819. }
  820. return 1;
  821. }
  822. static gint
  823. lua_cryptobox_signature_gc(lua_State *L)
  824. {
  825. LUA_TRACE_POINT;
  826. rspamd_fstring_t *sig = lua_check_cryptobox_sign(L, 1);
  827. rspamd_fstring_free(sig);
  828. return 0;
  829. }
  830. static void
  831. rspamd_lua_hash_update(struct rspamd_lua_cryptobox_hash *h,
  832. const void *p, gsize len)
  833. {
  834. if (h) {
  835. switch (h->type) {
  836. case LUA_CRYPTOBOX_HASH_BLAKE2:
  837. rspamd_cryptobox_hash_update(h->content.h, p, len);
  838. break;
  839. case LUA_CRYPTOBOX_HASH_SSL:
  840. EVP_DigestUpdate(h->content.c, p, len);
  841. break;
  842. case LUA_CRYPTOBOX_HASH_HMAC:
  843. HMAC_Update(h->content.hmac_c, p, len);
  844. break;
  845. case LUA_CRYPTOBOX_HASH_XXHASH64:
  846. case LUA_CRYPTOBOX_HASH_XXHASH32:
  847. case LUA_CRYPTOBOX_HASH_XXHASH3:
  848. case LUA_CRYPTOBOX_HASH_MUM:
  849. case LUA_CRYPTOBOX_HASH_T1HA:
  850. rspamd_cryptobox_fast_hash_update(h->content.fh, p, len);
  851. break;
  852. default:
  853. g_assert_not_reached();
  854. }
  855. }
  856. }
  857. static void
  858. lua_cryptobox_hash_dtor(struct rspamd_lua_cryptobox_hash *h)
  859. {
  860. if (h->type == LUA_CRYPTOBOX_HASH_SSL) {
  861. #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  862. EVP_MD_CTX_cleanup(h->content.c);
  863. #else
  864. EVP_MD_CTX_reset(h->content.c);
  865. #endif
  866. EVP_MD_CTX_destroy(h->content.c);
  867. }
  868. else if (h->type == LUA_CRYPTOBOX_HASH_HMAC) {
  869. #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  870. (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000)
  871. HMAC_CTX_cleanup(h->content.hmac_c);
  872. g_free(h->content.hmac_c);
  873. #else
  874. HMAC_CTX_free(h->content.hmac_c);
  875. #endif
  876. }
  877. else if (h->type == LUA_CRYPTOBOX_HASH_BLAKE2) {
  878. rspamd_explicit_memzero(h->content.h, sizeof(*h->content.h));
  879. free(h->content.h); /* Allocated by posix_memalign */
  880. }
  881. else {
  882. rspamd_cryptobox_fast_hash_free(h->content.fh);
  883. }
  884. g_free(h);
  885. }
  886. static inline void
  887. rspamd_lua_hash_init_default(struct rspamd_lua_cryptobox_hash *h,
  888. const gchar *key, gsize keylen)
  889. {
  890. h->type = LUA_CRYPTOBOX_HASH_BLAKE2;
  891. if (posix_memalign((void **) &h->content.h,
  892. RSPAMD_ALIGNOF(rspamd_cryptobox_hash_state_t),
  893. sizeof(*h->content.h)) != 0) {
  894. g_assert_not_reached();
  895. }
  896. rspamd_cryptobox_hash_init(h->content.h, key, keylen);
  897. h->out_len = rspamd_cryptobox_HASHBYTES;
  898. }
  899. static void
  900. rspamd_lua_ssl_hash_create(struct rspamd_lua_cryptobox_hash *h, const EVP_MD *htype,
  901. bool insecure)
  902. {
  903. h->type = LUA_CRYPTOBOX_HASH_SSL;
  904. h->content.c = EVP_MD_CTX_create();
  905. h->out_len = EVP_MD_size(htype);
  906. if (insecure) {
  907. /* Should never ever be used for crypto/security purposes! */
  908. #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
  909. EVP_MD_CTX_set_flags(h->content.c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
  910. #endif
  911. }
  912. EVP_DigestInit_ex(h->content.c, htype, NULL);
  913. }
  914. static void
  915. rspamd_lua_ssl_hmac_create(struct rspamd_lua_cryptobox_hash *h, const EVP_MD *htype,
  916. const gchar *key, gsize keylen,
  917. bool insecure)
  918. {
  919. h->type = LUA_CRYPTOBOX_HASH_HMAC;
  920. #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  921. (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000)
  922. h->content.hmac_c = g_malloc0(sizeof(*h->content.hmac_c));
  923. #else
  924. h->content.hmac_c = HMAC_CTX_new();
  925. #endif
  926. h->out_len = EVP_MD_size(htype);
  927. #if OPENSSL_VERSION_NUMBER > 0x10100000L
  928. if (insecure) {
  929. /* Should never ever be used for crypto/security purposes! */
  930. #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
  931. HMAC_CTX_set_flags(h->content.hmac_c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
  932. #endif
  933. }
  934. #endif
  935. HMAC_Init_ex(h->content.hmac_c, key, keylen, htype, NULL);
  936. }
  937. static struct rspamd_lua_cryptobox_hash *
  938. rspamd_lua_hash_create(const gchar *type, const gchar *key, gsize keylen)
  939. {
  940. struct rspamd_lua_cryptobox_hash *h;
  941. h = g_malloc0(sizeof(*h));
  942. REF_INIT_RETAIN(h, lua_cryptobox_hash_dtor);
  943. if (type) {
  944. if (g_ascii_strcasecmp(type, "md5") == 0) {
  945. if (keylen > 0) {
  946. rspamd_lua_ssl_hmac_create(h, EVP_md5(), key, keylen, true);
  947. }
  948. else {
  949. rspamd_lua_ssl_hash_create(h, EVP_md5(), true);
  950. }
  951. }
  952. else if (g_ascii_strcasecmp(type, "sha1") == 0 ||
  953. g_ascii_strcasecmp(type, "sha") == 0) {
  954. if (keylen > 0) {
  955. rspamd_lua_ssl_hmac_create(h, EVP_sha1(), key, keylen, true);
  956. }
  957. else {
  958. rspamd_lua_ssl_hash_create(h, EVP_sha1(), true);
  959. }
  960. }
  961. else if (g_ascii_strcasecmp(type, "sha256") == 0) {
  962. if (keylen > 0) {
  963. rspamd_lua_ssl_hmac_create(h, EVP_sha256(), key, keylen, true);
  964. }
  965. else {
  966. rspamd_lua_ssl_hash_create(h, EVP_sha256(), true);
  967. }
  968. }
  969. else if (g_ascii_strcasecmp(type, "sha512") == 0) {
  970. if (keylen > 0) {
  971. rspamd_lua_ssl_hmac_create(h, EVP_sha512(), key, keylen, true);
  972. }
  973. else {
  974. rspamd_lua_ssl_hash_create(h, EVP_sha512(), true);
  975. }
  976. }
  977. else if (g_ascii_strcasecmp(type, "sha384") == 0) {
  978. if (keylen > 0) {
  979. rspamd_lua_ssl_hmac_create(h, EVP_sha384(), key, keylen, true);
  980. }
  981. else {
  982. rspamd_lua_ssl_hash_create(h, EVP_sha384(), true);
  983. }
  984. }
  985. else if (g_ascii_strcasecmp(type, "xxh64") == 0) {
  986. h->type = LUA_CRYPTOBOX_HASH_XXHASH64;
  987. h->content.fh = rspamd_cryptobox_fast_hash_new();
  988. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  989. RSPAMD_CRYPTOBOX_XXHASH64, 0);
  990. h->out_len = sizeof(uint64_t);
  991. }
  992. else if (g_ascii_strcasecmp(type, "xxh32") == 0) {
  993. h->type = LUA_CRYPTOBOX_HASH_XXHASH32;
  994. h->content.fh = rspamd_cryptobox_fast_hash_new();
  995. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  996. RSPAMD_CRYPTOBOX_XXHASH32, 0);
  997. h->out_len = sizeof(uint32_t);
  998. }
  999. else if (g_ascii_strcasecmp(type, "xxh3") == 0) {
  1000. h->type = LUA_CRYPTOBOX_HASH_XXHASH3;
  1001. h->content.fh = rspamd_cryptobox_fast_hash_new();
  1002. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1003. RSPAMD_CRYPTOBOX_XXHASH3, 0);
  1004. h->out_len = sizeof(uint64_t);
  1005. }
  1006. else if (g_ascii_strcasecmp(type, "mum") == 0) {
  1007. h->type = LUA_CRYPTOBOX_HASH_MUM;
  1008. h->content.fh = rspamd_cryptobox_fast_hash_new();
  1009. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1010. RSPAMD_CRYPTOBOX_MUMHASH, 0);
  1011. h->out_len = sizeof(uint64_t);
  1012. }
  1013. else if (g_ascii_strcasecmp(type, "t1ha") == 0) {
  1014. h->type = LUA_CRYPTOBOX_HASH_T1HA;
  1015. h->content.fh = rspamd_cryptobox_fast_hash_new();
  1016. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1017. RSPAMD_CRYPTOBOX_T1HA, 0);
  1018. h->out_len = sizeof(uint64_t);
  1019. }
  1020. else if (g_ascii_strcasecmp(type, "blake2") == 0) {
  1021. rspamd_lua_hash_init_default(h, key, keylen);
  1022. }
  1023. else {
  1024. g_free(h);
  1025. return NULL;
  1026. }
  1027. }
  1028. else {
  1029. /* Default hash type */
  1030. rspamd_lua_hash_init_default(h, key, keylen);
  1031. }
  1032. return h;
  1033. }
  1034. /***
  1035. * @function rspamd_cryptobox_hash.create([string])
  1036. * Creates new hash context
  1037. * @param {string} data optional string to hash
  1038. * @return {cryptobox_hash} hash object
  1039. */
  1040. static gint
  1041. lua_cryptobox_hash_create(lua_State *L)
  1042. {
  1043. LUA_TRACE_POINT;
  1044. struct rspamd_lua_cryptobox_hash *h, **ph;
  1045. const gchar *s = NULL;
  1046. struct rspamd_lua_text *t;
  1047. gsize len = 0;
  1048. h = rspamd_lua_hash_create(NULL, NULL, 0);
  1049. if (lua_type(L, 1) == LUA_TSTRING) {
  1050. s = lua_tolstring(L, 1, &len);
  1051. }
  1052. else if (lua_type(L, 1) == LUA_TUSERDATA) {
  1053. t = lua_check_text(L, 1);
  1054. if (!t) {
  1055. REF_RELEASE(h);
  1056. return luaL_error(L, "invalid arguments");
  1057. }
  1058. s = t->start;
  1059. len = t->len;
  1060. }
  1061. if (s) {
  1062. rspamd_lua_hash_update(h, s, len);
  1063. }
  1064. ph = lua_newuserdata(L, sizeof(void *));
  1065. *ph = h;
  1066. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1067. return 1;
  1068. }
  1069. /***
  1070. * @function rspamd_cryptobox_hash.create_specific(type, [string])
  1071. * Creates new hash context
  1072. * @param {string} type type of hash (blake2, sha256, md5, sha512, mum, xxh64, xxh32, t1ha)
  1073. * @param {string} string initial data
  1074. * @return {cryptobox_hash} hash object
  1075. */
  1076. static gint
  1077. lua_cryptobox_hash_create_specific(lua_State *L)
  1078. {
  1079. LUA_TRACE_POINT;
  1080. struct rspamd_lua_cryptobox_hash *h, **ph;
  1081. const gchar *s = NULL, *type = luaL_checkstring(L, 1);
  1082. gsize len = 0;
  1083. struct rspamd_lua_text *t;
  1084. if (!type) {
  1085. return luaL_error(L, "invalid arguments");
  1086. }
  1087. h = rspamd_lua_hash_create(type, NULL, 0);
  1088. if (h == NULL) {
  1089. return luaL_error(L, "invalid hash type: %s", type);
  1090. }
  1091. if (lua_type(L, 2) == LUA_TSTRING) {
  1092. s = lua_tolstring(L, 2, &len);
  1093. }
  1094. else if (lua_type(L, 2) == LUA_TUSERDATA) {
  1095. t = lua_check_text(L, 2);
  1096. if (!t) {
  1097. REF_RELEASE(h);
  1098. return luaL_error(L, "invalid arguments");
  1099. }
  1100. s = t->start;
  1101. len = t->len;
  1102. }
  1103. if (s) {
  1104. rspamd_lua_hash_update(h, s, len);
  1105. }
  1106. ph = lua_newuserdata(L, sizeof(void *));
  1107. *ph = h;
  1108. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1109. return 1;
  1110. }
  1111. /***
  1112. * @function rspamd_cryptobox_hash.create_keyed(key, [string])
  1113. * Creates new hash context with specified key
  1114. * @param {string} key key
  1115. * @return {cryptobox_hash} hash object
  1116. */
  1117. static gint
  1118. lua_cryptobox_hash_create_keyed(lua_State *L)
  1119. {
  1120. LUA_TRACE_POINT;
  1121. struct rspamd_lua_cryptobox_hash *h, **ph;
  1122. const gchar *key, *s = NULL;
  1123. struct rspamd_lua_text *t;
  1124. gsize len = 0;
  1125. gsize keylen;
  1126. key = luaL_checklstring(L, 1, &keylen);
  1127. if (key != NULL) {
  1128. h = rspamd_lua_hash_create(NULL, key, keylen);
  1129. if (lua_type(L, 2) == LUA_TSTRING) {
  1130. s = lua_tolstring(L, 2, &len);
  1131. }
  1132. else if (lua_type(L, 2) == LUA_TUSERDATA) {
  1133. t = lua_check_text(L, 2);
  1134. if (!t) {
  1135. REF_RELEASE(h);
  1136. return luaL_error(L, "invalid arguments");
  1137. }
  1138. s = t->start;
  1139. len = t->len;
  1140. }
  1141. if (s) {
  1142. rspamd_lua_hash_update(h, s, len);
  1143. }
  1144. ph = lua_newuserdata(L, sizeof(void *));
  1145. *ph = h;
  1146. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1147. }
  1148. else {
  1149. return luaL_error(L, "invalid arguments");
  1150. }
  1151. return 1;
  1152. }
  1153. /***
  1154. * @function rspamd_cryptobox_hash.create_specific_keyed(key, type, [string])
  1155. * Creates new hash context with specified key
  1156. * @param {string} key key
  1157. * @return {cryptobox_hash} hash object
  1158. */
  1159. static gint
  1160. lua_cryptobox_hash_create_specific_keyed(lua_State *L)
  1161. {
  1162. LUA_TRACE_POINT;
  1163. struct rspamd_lua_cryptobox_hash *h, **ph;
  1164. const gchar *key, *s = NULL, *type = luaL_checkstring(L, 2);
  1165. struct rspamd_lua_text *t;
  1166. gsize len = 0;
  1167. gsize keylen;
  1168. key = luaL_checklstring(L, 1, &keylen);
  1169. if (key != NULL && type != NULL) {
  1170. h = rspamd_lua_hash_create(type, key, keylen);
  1171. if (h == NULL) {
  1172. return luaL_error(L, "invalid hash type: %s", type);
  1173. }
  1174. if (lua_type(L, 3) == LUA_TSTRING) {
  1175. s = lua_tolstring(L, 3, &len);
  1176. }
  1177. else if (lua_type(L, 3) == LUA_TUSERDATA) {
  1178. t = lua_check_text(L, 3);
  1179. if (!t) {
  1180. REF_RELEASE(h);
  1181. return luaL_error(L, "invalid arguments");
  1182. }
  1183. s = t->start;
  1184. len = t->len;
  1185. }
  1186. if (s) {
  1187. rspamd_lua_hash_update(h, s, len);
  1188. }
  1189. ph = lua_newuserdata(L, sizeof(void *));
  1190. *ph = h;
  1191. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1192. }
  1193. else {
  1194. return luaL_error(L, "invalid arguments");
  1195. }
  1196. return 1;
  1197. }
  1198. /***
  1199. * @method cryptobox_hash:update(data)
  1200. * Updates hash with the specified data (hash should not be finalized using `hex` or `bin` methods)
  1201. * @param {string} data data to hash
  1202. */
  1203. static gint
  1204. lua_cryptobox_hash_update(lua_State *L)
  1205. {
  1206. LUA_TRACE_POINT;
  1207. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1), **ph;
  1208. const gchar *data;
  1209. struct rspamd_lua_text *t;
  1210. gsize len;
  1211. if (lua_isuserdata(L, 2)) {
  1212. t = lua_check_text(L, 2);
  1213. if (!t) {
  1214. return luaL_error(L, "invalid arguments");
  1215. }
  1216. data = t->start;
  1217. len = t->len;
  1218. }
  1219. else {
  1220. data = luaL_checklstring(L, 2, &len);
  1221. }
  1222. if (lua_isnumber(L, 3)) {
  1223. gsize nlen = lua_tonumber(L, 3);
  1224. if (nlen > len) {
  1225. return luaL_error(L, "invalid length: %d while %d is available",
  1226. (int) nlen, (int) len);
  1227. }
  1228. len = nlen;
  1229. }
  1230. if (h && data) {
  1231. if (!h->is_finished) {
  1232. rspamd_lua_hash_update(h, data, len);
  1233. }
  1234. else {
  1235. return luaL_error(L, "hash is already finalized");
  1236. }
  1237. }
  1238. else {
  1239. return luaL_error(L, "invalid arguments");
  1240. }
  1241. ph = lua_newuserdata(L, sizeof(void *));
  1242. *ph = h;
  1243. REF_RETAIN(h);
  1244. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1245. return 1;
  1246. }
  1247. /***
  1248. * @method cryptobox_hash:reset()
  1249. * Resets hash to the initial state
  1250. */
  1251. static gint
  1252. lua_cryptobox_hash_reset(lua_State *L)
  1253. {
  1254. LUA_TRACE_POINT;
  1255. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1), **ph;
  1256. if (h) {
  1257. switch (h->type) {
  1258. case LUA_CRYPTOBOX_HASH_BLAKE2:
  1259. memset(h->content.h, 0, sizeof(*h->content.h));
  1260. rspamd_cryptobox_hash_init(h->content.h, NULL, 0);
  1261. break;
  1262. case LUA_CRYPTOBOX_HASH_SSL:
  1263. EVP_DigestInit(h->content.c, EVP_MD_CTX_md(h->content.c));
  1264. break;
  1265. case LUA_CRYPTOBOX_HASH_HMAC:
  1266. #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  1267. (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000)
  1268. /* Old openssl is awesome... */
  1269. HMAC_Init_ex(h->content.hmac_c, NULL, 0, h->content.hmac_c->md, NULL);
  1270. #else
  1271. HMAC_CTX_reset(h->content.hmac_c);
  1272. #endif
  1273. break;
  1274. case LUA_CRYPTOBOX_HASH_XXHASH64:
  1275. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1276. RSPAMD_CRYPTOBOX_XXHASH64, 0);
  1277. break;
  1278. case LUA_CRYPTOBOX_HASH_XXHASH32:
  1279. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1280. RSPAMD_CRYPTOBOX_XXHASH32, 0);
  1281. break;
  1282. case LUA_CRYPTOBOX_HASH_XXHASH3:
  1283. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1284. RSPAMD_CRYPTOBOX_XXHASH3, 0);
  1285. break;
  1286. case LUA_CRYPTOBOX_HASH_MUM:
  1287. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1288. RSPAMD_CRYPTOBOX_MUMHASH, 0);
  1289. break;
  1290. case LUA_CRYPTOBOX_HASH_T1HA:
  1291. rspamd_cryptobox_fast_hash_init_specific(h->content.fh,
  1292. RSPAMD_CRYPTOBOX_T1HA, 0);
  1293. break;
  1294. default:
  1295. g_assert_not_reached();
  1296. }
  1297. h->is_finished = FALSE;
  1298. }
  1299. else {
  1300. return luaL_error(L, "invalid arguments");
  1301. }
  1302. ph = lua_newuserdata(L, sizeof(void *));
  1303. *ph = h;
  1304. REF_RETAIN(h);
  1305. rspamd_lua_setclass(L, rspamd_cryptobox_hash_classname, -1);
  1306. return 1;
  1307. }
  1308. static void
  1309. lua_cryptobox_hash_finish(struct rspamd_lua_cryptobox_hash *h)
  1310. {
  1311. uint64_t ll;
  1312. guchar out[rspamd_cryptobox_HASHBYTES];
  1313. guint ssl_outlen = sizeof(out);
  1314. switch (h->type) {
  1315. case LUA_CRYPTOBOX_HASH_BLAKE2:
  1316. rspamd_cryptobox_hash_final(h->content.h, out);
  1317. memcpy(h->out, out, sizeof(out));
  1318. break;
  1319. case LUA_CRYPTOBOX_HASH_SSL:
  1320. EVP_DigestFinal_ex(h->content.c, out, &ssl_outlen);
  1321. h->out_len = ssl_outlen;
  1322. g_assert(ssl_outlen <= sizeof(h->out));
  1323. memcpy(h->out, out, ssl_outlen);
  1324. break;
  1325. case LUA_CRYPTOBOX_HASH_HMAC:
  1326. HMAC_Final(h->content.hmac_c, out, &ssl_outlen);
  1327. h->out_len = ssl_outlen;
  1328. g_assert(ssl_outlen <= sizeof(h->out));
  1329. memcpy(h->out, out, ssl_outlen);
  1330. break;
  1331. case LUA_CRYPTOBOX_HASH_XXHASH64:
  1332. case LUA_CRYPTOBOX_HASH_XXHASH32:
  1333. case LUA_CRYPTOBOX_HASH_XXHASH3:
  1334. case LUA_CRYPTOBOX_HASH_MUM:
  1335. case LUA_CRYPTOBOX_HASH_T1HA:
  1336. ll = rspamd_cryptobox_fast_hash_final(h->content.fh);
  1337. memcpy(h->out, &ll, sizeof(ll));
  1338. break;
  1339. default:
  1340. g_assert_not_reached();
  1341. }
  1342. h->is_finished = TRUE;
  1343. }
  1344. /***
  1345. * @method cryptobox_hash:hex()
  1346. * Finalizes hash and return it as hex string
  1347. * @return {string} hex value of hash
  1348. */
  1349. static gint
  1350. lua_cryptobox_hash_hex(lua_State *L)
  1351. {
  1352. LUA_TRACE_POINT;
  1353. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1);
  1354. guchar out_hex[rspamd_cryptobox_HASHBYTES * 2 + 1], *r;
  1355. guint dlen;
  1356. if (h) {
  1357. if (!h->is_finished) {
  1358. lua_cryptobox_hash_finish(h);
  1359. }
  1360. memset(out_hex, 0, sizeof(out_hex));
  1361. r = h->out;
  1362. dlen = h->out_len;
  1363. if (lua_isnumber(L, 2)) {
  1364. guint lim = lua_tonumber(L, 2);
  1365. if (lim < dlen) {
  1366. r += dlen - lim;
  1367. dlen = lim;
  1368. }
  1369. }
  1370. rspamd_encode_hex_buf(r, dlen, out_hex, sizeof(out_hex));
  1371. lua_pushstring(L, out_hex);
  1372. }
  1373. else {
  1374. return luaL_error(L, "invalid arguments");
  1375. }
  1376. return 1;
  1377. }
  1378. /***
  1379. * @method cryptobox_hash:base32([b32type])
  1380. * Finalizes hash and return it as zbase32 (by default) string
  1381. * @param {string} b32type base32 type (default, bleach, rfc)
  1382. * @return {string} base32 value of hash
  1383. */
  1384. static gint
  1385. lua_cryptobox_hash_base32(lua_State *L)
  1386. {
  1387. LUA_TRACE_POINT;
  1388. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1);
  1389. guchar out_b32[rspamd_cryptobox_HASHBYTES * 2], *r;
  1390. guint dlen;
  1391. if (h) {
  1392. enum rspamd_base32_type btype = RSPAMD_BASE32_DEFAULT;
  1393. if (lua_type(L, 2) == LUA_TSTRING) {
  1394. btype = rspamd_base32_decode_type_from_str(lua_tostring(L, 2));
  1395. if (btype == RSPAMD_BASE32_INVALID) {
  1396. return luaL_error(L, "invalid b32 type: %s", lua_tostring(L, 2));
  1397. }
  1398. }
  1399. if (!h->is_finished) {
  1400. lua_cryptobox_hash_finish(h);
  1401. }
  1402. memset(out_b32, 0, sizeof(out_b32));
  1403. r = h->out;
  1404. dlen = h->out_len;
  1405. if (lua_isnumber(L, 2)) {
  1406. guint lim = lua_tonumber(L, 2);
  1407. if (lim < dlen) {
  1408. r += dlen - lim;
  1409. dlen = lim;
  1410. }
  1411. }
  1412. rspamd_encode_base32_buf(r, dlen, out_b32, sizeof(out_b32), btype);
  1413. lua_pushstring(L, out_b32);
  1414. }
  1415. else {
  1416. return luaL_error(L, "invalid arguments");
  1417. }
  1418. return 1;
  1419. }
  1420. /***
  1421. * @method cryptobox_hash:base64()
  1422. * Finalizes hash and return it as base64 string
  1423. * @return {string} base64 value of hash
  1424. */
  1425. static gint
  1426. lua_cryptobox_hash_base64(lua_State *L)
  1427. {
  1428. LUA_TRACE_POINT;
  1429. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1);
  1430. guchar *b64, *r;
  1431. gsize len;
  1432. guint dlen;
  1433. if (h) {
  1434. if (!h->is_finished) {
  1435. lua_cryptobox_hash_finish(h);
  1436. }
  1437. r = h->out;
  1438. dlen = h->out_len;
  1439. if (lua_isnumber(L, 2)) {
  1440. guint lim = lua_tonumber(L, 2);
  1441. if (lim < dlen) {
  1442. r += dlen - lim;
  1443. dlen = lim;
  1444. }
  1445. }
  1446. b64 = rspamd_encode_base64(r, dlen, 0, &len);
  1447. lua_pushlstring(L, b64, len);
  1448. g_free(b64);
  1449. }
  1450. else {
  1451. return luaL_error(L, "invalid arguments");
  1452. }
  1453. return 1;
  1454. }
  1455. /***
  1456. * @method cryptobox_hash:bin()
  1457. * Finalizes hash and return it as raw string
  1458. * @return {string} raw value of hash
  1459. */
  1460. static gint
  1461. lua_cryptobox_hash_bin(lua_State *L)
  1462. {
  1463. LUA_TRACE_POINT;
  1464. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1);
  1465. guchar *r;
  1466. guint dlen;
  1467. if (h) {
  1468. if (!h->is_finished) {
  1469. lua_cryptobox_hash_finish(h);
  1470. }
  1471. r = h->out;
  1472. dlen = h->out_len;
  1473. if (lua_isnumber(L, 2)) {
  1474. guint lim = lua_tonumber(L, 2);
  1475. if (lim < dlen) {
  1476. r += dlen - lim;
  1477. dlen = lim;
  1478. }
  1479. }
  1480. lua_pushlstring(L, r, dlen);
  1481. h->is_finished = TRUE;
  1482. }
  1483. else {
  1484. return luaL_error(L, "invalid arguments");
  1485. }
  1486. return 1;
  1487. }
  1488. static gint
  1489. lua_cryptobox_hash_gc(lua_State *L)
  1490. {
  1491. LUA_TRACE_POINT;
  1492. struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash(L, 1);
  1493. REF_RELEASE(h);
  1494. return 0;
  1495. }
  1496. /***
  1497. * @function rspamd_cryptobox.verify_memory(pk, sig, data, [alg = 'curve25519'])
  1498. * Check memory using specified cryptobox key and signature
  1499. * @param {pubkey} pk public key to verify
  1500. * @param {sig} signature to check
  1501. * @param {string} data data to check signature against
  1502. * @return {boolean} `true` - if string matches cryptobox signature
  1503. */
  1504. static gint
  1505. lua_cryptobox_verify_memory(lua_State *L)
  1506. {
  1507. LUA_TRACE_POINT;
  1508. struct rspamd_cryptobox_pubkey *pk;
  1509. rspamd_fstring_t *signature;
  1510. struct rspamd_lua_text *t;
  1511. const gchar *data;
  1512. enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
  1513. gsize len;
  1514. gint ret;
  1515. pk = lua_check_cryptobox_pubkey(L, 1);
  1516. signature = lua_check_cryptobox_sign(L, 2);
  1517. if (lua_isuserdata(L, 3)) {
  1518. t = lua_check_text(L, 3);
  1519. if (!t) {
  1520. return luaL_error(L, "invalid arguments");
  1521. }
  1522. data = t->start;
  1523. len = t->len;
  1524. }
  1525. else {
  1526. data = luaL_checklstring(L, 3, &len);
  1527. }
  1528. if (lua_isstring(L, 4)) {
  1529. const gchar *str = lua_tostring(L, 4);
  1530. if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
  1531. alg = RSPAMD_CRYPTOBOX_MODE_NIST;
  1532. }
  1533. else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
  1534. alg = RSPAMD_CRYPTOBOX_MODE_25519;
  1535. }
  1536. else {
  1537. return luaL_error(L, "invalid algorithm: %s", str);
  1538. }
  1539. }
  1540. if (pk != NULL && signature != NULL && data != NULL) {
  1541. ret = rspamd_cryptobox_verify(signature->str, signature->len, data, len,
  1542. rspamd_pubkey_get_pk(pk, NULL), alg);
  1543. if (ret) {
  1544. lua_pushboolean(L, 1);
  1545. }
  1546. else {
  1547. lua_pushboolean(L, 0);
  1548. }
  1549. }
  1550. else {
  1551. return luaL_error(L, "invalid arguments");
  1552. }
  1553. return 1;
  1554. }
  1555. /***
  1556. * @function rspamd_cryptobox.verify_file(pk, sig, file, [alg = 'curve25519'])
  1557. * Check file using specified cryptobox key and signature
  1558. * @param {pubkey} pk public key to verify
  1559. * @param {sig} signature to check
  1560. * @param {string} file to load data from
  1561. * @return {boolean} `true` - if string matches cryptobox signature
  1562. */
  1563. static gint
  1564. lua_cryptobox_verify_file(lua_State *L)
  1565. {
  1566. LUA_TRACE_POINT;
  1567. const gchar *fname;
  1568. struct rspamd_cryptobox_pubkey *pk;
  1569. rspamd_fstring_t *signature;
  1570. guchar *map = NULL;
  1571. enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
  1572. gsize len;
  1573. gint ret;
  1574. pk = lua_check_cryptobox_pubkey(L, 1);
  1575. signature = lua_check_cryptobox_sign(L, 2);
  1576. fname = luaL_checkstring(L, 3);
  1577. if (lua_isstring(L, 4)) {
  1578. const gchar *str = lua_tostring(L, 4);
  1579. if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
  1580. alg = RSPAMD_CRYPTOBOX_MODE_NIST;
  1581. }
  1582. else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
  1583. alg = RSPAMD_CRYPTOBOX_MODE_25519;
  1584. }
  1585. else {
  1586. return luaL_error(L, "invalid algorithm: %s", str);
  1587. }
  1588. }
  1589. map = rspamd_file_xmap(fname, PROT_READ, &len, TRUE);
  1590. if (map != NULL && pk != NULL && signature != NULL) {
  1591. ret = rspamd_cryptobox_verify(signature->str, signature->len,
  1592. map, len,
  1593. rspamd_pubkey_get_pk(pk, NULL), alg);
  1594. if (ret) {
  1595. lua_pushboolean(L, 1);
  1596. }
  1597. else {
  1598. lua_pushboolean(L, 0);
  1599. }
  1600. }
  1601. else {
  1602. if (map != NULL) {
  1603. munmap(map, len);
  1604. }
  1605. return luaL_error(L, "invalid arguments");
  1606. }
  1607. if (map != NULL) {
  1608. munmap(map, len);
  1609. }
  1610. return 1;
  1611. }
  1612. /***
  1613. * @function rspamd_cryptobox.sign_memory(kp, data)
  1614. * Sign data using specified keypair
  1615. * @param {keypair} kp keypair to sign
  1616. * @param {string} data
  1617. * @return {cryptobox_signature} signature object
  1618. */
  1619. static gint
  1620. lua_cryptobox_sign_memory(lua_State *L)
  1621. {
  1622. LUA_TRACE_POINT;
  1623. struct rspamd_cryptobox_keypair *kp;
  1624. const gchar *data;
  1625. struct rspamd_lua_text *t;
  1626. gsize len = 0;
  1627. rspamd_fstring_t *sig, **psig;
  1628. kp = lua_check_cryptobox_keypair(L, 1);
  1629. if (lua_isuserdata(L, 2)) {
  1630. t = lua_check_text(L, 2);
  1631. if (!t) {
  1632. return luaL_error(L, "invalid arguments");
  1633. }
  1634. data = t->start;
  1635. len = t->len;
  1636. }
  1637. else {
  1638. data = luaL_checklstring(L, 2, &len);
  1639. }
  1640. if (!kp || !data || kp->type == RSPAMD_KEYPAIR_KEX) {
  1641. return luaL_error(L, "invalid arguments");
  1642. }
  1643. sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
  1644. rspamd_keypair_alg(kp)));
  1645. unsigned long long siglen = sig->len;
  1646. rspamd_cryptobox_sign(sig->str, &siglen, data,
  1647. len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
  1648. sig->len = siglen;
  1649. psig = lua_newuserdata(L, sizeof(void *));
  1650. *psig = sig;
  1651. rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
  1652. return 1;
  1653. }
  1654. /***
  1655. * @function rspamd_cryptobox.sign_file(kp, file)
  1656. * Sign file using specified keypair
  1657. * @param {keypair} kp keypair to sign
  1658. * @param {string} filename
  1659. * @return {cryptobox_signature} signature object
  1660. */
  1661. static gint
  1662. lua_cryptobox_sign_file(lua_State *L)
  1663. {
  1664. LUA_TRACE_POINT;
  1665. struct rspamd_cryptobox_keypair *kp;
  1666. const gchar *filename;
  1667. gchar *data;
  1668. gsize len = 0;
  1669. rspamd_fstring_t *sig, **psig;
  1670. kp = lua_check_cryptobox_keypair(L, 1);
  1671. filename = luaL_checkstring(L, 2);
  1672. if (!kp || !filename) {
  1673. return luaL_error(L, "invalid arguments");
  1674. }
  1675. data = rspamd_file_xmap(filename, PROT_READ, &len, TRUE);
  1676. if (data == NULL) {
  1677. msg_err("cannot mmap file %s: %s", filename, strerror(errno));
  1678. lua_pushnil(L);
  1679. }
  1680. else {
  1681. sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
  1682. rspamd_keypair_alg(kp)));
  1683. unsigned long long siglen = sig->len;
  1684. rspamd_cryptobox_sign(sig->str, &siglen, data,
  1685. len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
  1686. sig->len = siglen;
  1687. psig = lua_newuserdata(L, sizeof(void *));
  1688. *psig = sig;
  1689. rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
  1690. munmap(data, len);
  1691. }
  1692. return 1;
  1693. }
  1694. /***
  1695. * @function rspamd_cryptobox.encrypt_memory(kp, data[, nist=false])
  1696. * Encrypt data using specified keypair/pubkey
  1697. * @param {keypair|string} kp keypair or pubkey in base32 to use
  1698. * @param {string|text} data
  1699. * @return {rspamd_text} encrypted text
  1700. */
  1701. static gint
  1702. lua_cryptobox_encrypt_memory(lua_State *L)
  1703. {
  1704. LUA_TRACE_POINT;
  1705. struct rspamd_cryptobox_keypair *kp = NULL;
  1706. struct rspamd_cryptobox_pubkey *pk = NULL;
  1707. const gchar *data;
  1708. guchar *out = NULL;
  1709. struct rspamd_lua_text *t, *res;
  1710. gsize len = 0, outlen = 0;
  1711. GError *err = NULL;
  1712. bool owned_pk = false;
  1713. if (lua_type(L, 1) == LUA_TUSERDATA) {
  1714. if (rspamd_lua_check_udata_maybe(L, 1, rspamd_cryptobox_keypair_classname)) {
  1715. kp = lua_check_cryptobox_keypair(L, 1);
  1716. }
  1717. else if (rspamd_lua_check_udata_maybe(L, 1, rspamd_cryptobox_pubkey_classname)) {
  1718. pk = lua_check_cryptobox_pubkey(L, 1);
  1719. }
  1720. }
  1721. else if (lua_type(L, 1) == LUA_TSTRING) {
  1722. const gchar *b32;
  1723. gsize blen;
  1724. b32 = lua_tolstring(L, 1, &blen);
  1725. pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
  1726. lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
  1727. owned_pk = true;
  1728. }
  1729. if (lua_isuserdata(L, 2)) {
  1730. t = lua_check_text(L, 2);
  1731. if (!t) {
  1732. goto err;
  1733. }
  1734. data = t->start;
  1735. len = t->len;
  1736. }
  1737. else {
  1738. data = luaL_checklstring(L, 2, &len);
  1739. }
  1740. if (!(kp || pk) || !data) {
  1741. goto err;
  1742. }
  1743. if (kp) {
  1744. if (!rspamd_keypair_encrypt(kp, data, len, &out, &outlen, &err)) {
  1745. gint ret = luaL_error(L, "cannot encrypt data: %s", err->message);
  1746. g_error_free(err);
  1747. if (owned_pk) {
  1748. rspamd_pubkey_unref(pk);
  1749. }
  1750. return ret;
  1751. }
  1752. }
  1753. else {
  1754. if (!rspamd_pubkey_encrypt(pk, data, len, &out, &outlen, &err)) {
  1755. gint ret = luaL_error(L, "cannot encrypt data: %s", err->message);
  1756. g_error_free(err);
  1757. if (owned_pk) {
  1758. rspamd_pubkey_unref(pk);
  1759. }
  1760. return ret;
  1761. }
  1762. }
  1763. res = lua_newuserdata(L, sizeof(*res));
  1764. res->flags = RSPAMD_TEXT_FLAG_OWN;
  1765. res->start = out;
  1766. res->len = outlen;
  1767. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  1768. if (owned_pk) {
  1769. rspamd_pubkey_unref(pk);
  1770. }
  1771. return 1;
  1772. err:
  1773. if (owned_pk) {
  1774. rspamd_pubkey_unref(pk);
  1775. }
  1776. return luaL_error(L, "invalid arguments");
  1777. }
  1778. /***
  1779. * @function rspamd_cryptobox.encrypt_file(kp|pk_string, filename[, nist=false])
  1780. * Encrypt data using specified keypair/pubkey
  1781. * @param {keypair|string} kp keypair or pubkey in base32 to use
  1782. * @param {string} filename
  1783. * @return {rspamd_text} encrypted text
  1784. */
  1785. static gint
  1786. lua_cryptobox_encrypt_file(lua_State *L)
  1787. {
  1788. LUA_TRACE_POINT;
  1789. struct rspamd_cryptobox_keypair *kp = NULL;
  1790. struct rspamd_cryptobox_pubkey *pk = NULL;
  1791. const gchar *filename;
  1792. gchar *data = NULL;
  1793. guchar *out = NULL;
  1794. struct rspamd_lua_text *res;
  1795. gsize len = 0, outlen = 0;
  1796. GError *err = NULL;
  1797. bool own_pk = false;
  1798. if (lua_type(L, 1) == LUA_TUSERDATA) {
  1799. if (rspamd_lua_check_udata_maybe(L, 1, rspamd_cryptobox_keypair_classname)) {
  1800. kp = lua_check_cryptobox_keypair(L, 1);
  1801. }
  1802. else if (rspamd_lua_check_udata_maybe(L, 1, rspamd_cryptobox_pubkey_classname)) {
  1803. pk = lua_check_cryptobox_pubkey(L, 1);
  1804. }
  1805. }
  1806. else if (lua_type(L, 1) == LUA_TSTRING) {
  1807. const gchar *b32;
  1808. gsize blen;
  1809. b32 = lua_tolstring(L, 1, &blen);
  1810. pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
  1811. lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
  1812. own_pk = true;
  1813. }
  1814. filename = luaL_checkstring(L, 2);
  1815. data = rspamd_file_xmap(filename, PROT_READ, &len, TRUE);
  1816. if (!(kp || pk) || !data) {
  1817. goto err;
  1818. }
  1819. if (kp) {
  1820. if (!rspamd_keypair_encrypt(kp, data, len, &out, &outlen, &err)) {
  1821. gint ret = luaL_error(L, "cannot encrypt file %s: %s", filename,
  1822. err->message);
  1823. g_error_free(err);
  1824. munmap(data, len);
  1825. if (own_pk) {
  1826. rspamd_pubkey_unref(pk);
  1827. }
  1828. return ret;
  1829. }
  1830. }
  1831. else if (pk) {
  1832. if (!rspamd_pubkey_encrypt(pk, data, len, &out, &outlen, &err)) {
  1833. gint ret = luaL_error(L, "cannot encrypt file %s: %s", filename,
  1834. err->message);
  1835. g_error_free(err);
  1836. munmap(data, len);
  1837. if (own_pk) {
  1838. rspamd_pubkey_unref(pk);
  1839. }
  1840. return ret;
  1841. }
  1842. }
  1843. res = lua_newuserdata(L, sizeof(*res));
  1844. res->flags = RSPAMD_TEXT_FLAG_OWN;
  1845. res->start = out;
  1846. res->len = outlen;
  1847. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  1848. munmap(data, len);
  1849. if (own_pk) {
  1850. rspamd_pubkey_unref(pk);
  1851. }
  1852. return 1;
  1853. err:
  1854. if (data) {
  1855. munmap(data, len);
  1856. }
  1857. if (own_pk) {
  1858. rspamd_pubkey_unref(pk);
  1859. }
  1860. return luaL_error(L, "invalid arguments");
  1861. }
  1862. /***
  1863. * @function rspamd_cryptobox.decrypt_memory(kp, data[, nist = false])
  1864. * Encrypt data using specified keypair
  1865. * @param {keypair} kp keypair to use
  1866. * @param {string} data
  1867. * @return status,{rspamd_text}|error status is boolean variable followed by either unencrypted data or an error message
  1868. */
  1869. static gint
  1870. lua_cryptobox_decrypt_memory(lua_State *L)
  1871. {
  1872. LUA_TRACE_POINT;
  1873. struct rspamd_cryptobox_keypair *kp;
  1874. const gchar *data;
  1875. guchar *out;
  1876. struct rspamd_lua_text *t, *res;
  1877. gsize len = 0, outlen;
  1878. GError *err = NULL;
  1879. kp = lua_check_cryptobox_keypair(L, 1);
  1880. if (lua_isuserdata(L, 2)) {
  1881. t = lua_check_text(L, 2);
  1882. if (!t) {
  1883. return luaL_error(L, "invalid arguments");
  1884. }
  1885. data = t->start;
  1886. len = t->len;
  1887. }
  1888. else {
  1889. data = luaL_checklstring(L, 2, &len);
  1890. }
  1891. if (!kp || !data) {
  1892. return luaL_error(L, "invalid arguments");
  1893. }
  1894. if (!rspamd_keypair_decrypt(kp, data, len, &out, &outlen, &err)) {
  1895. lua_pushboolean(L, false);
  1896. lua_pushstring(L, err->message);
  1897. g_error_free(err);
  1898. }
  1899. else {
  1900. lua_pushboolean(L, true);
  1901. res = lua_newuserdata(L, sizeof(*res));
  1902. res->flags = RSPAMD_TEXT_FLAG_OWN;
  1903. res->start = out;
  1904. res->len = outlen;
  1905. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  1906. }
  1907. return 2;
  1908. }
  1909. /***
  1910. * @function rspamd_cryptobox.decrypt_file(kp, filename)
  1911. * Encrypt data using specified keypair
  1912. * @param {keypair} kp keypair to use
  1913. * @param {string} filename
  1914. * @return status,{rspamd_text}|error status is boolean variable followed by either unencrypted data or an error message
  1915. */
  1916. static gint
  1917. lua_cryptobox_decrypt_file(lua_State *L)
  1918. {
  1919. LUA_TRACE_POINT;
  1920. struct rspamd_cryptobox_keypair *kp;
  1921. const gchar *filename;
  1922. gchar *data;
  1923. guchar *out;
  1924. struct rspamd_lua_text *res;
  1925. gsize len = 0, outlen;
  1926. GError *err = NULL;
  1927. kp = lua_check_cryptobox_keypair(L, 1);
  1928. if (!kp) {
  1929. return luaL_error(L, "invalid arguments; keypair is expected");
  1930. }
  1931. filename = luaL_checkstring(L, 2);
  1932. data = rspamd_file_xmap(filename, PROT_READ, &len, TRUE);
  1933. if (!data) {
  1934. return luaL_error(L, "invalid arguments; cannot mmap %s: %s",
  1935. filename, strerror(errno));
  1936. }
  1937. if (!rspamd_keypair_decrypt(kp, data, len, &out, &outlen, &err)) {
  1938. lua_pushboolean(L, false);
  1939. lua_pushstring(L, err->message);
  1940. g_error_free(err);
  1941. }
  1942. else {
  1943. lua_pushboolean(L, true);
  1944. res = lua_newuserdata(L, sizeof(*res));
  1945. res->flags = RSPAMD_TEXT_FLAG_OWN;
  1946. res->start = out;
  1947. res->len = outlen;
  1948. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  1949. }
  1950. munmap(data, len);
  1951. return 2;
  1952. }
  1953. #define RSPAMD_CRYPTOBOX_AES_BLOCKSIZE 16
  1954. #define RSPAMD_CRYPTOBOX_AES_KEYSIZE 16
  1955. /***
  1956. * @function rspamd_cryptobox.encrypt_cookie(secret_key, secret_cookie)
  1957. * Specialised function that performs AES-CTR encryption of the provided cookie
  1958. * ```
  1959. * e := base64(nonce||aesencrypt(nonce, secret_cookie))
  1960. * nonce := uint32_le(unix_timestamp)||random_64bit
  1961. * aesencrypt := aes_ctr(nonce, secret_key) ^ pad(secret_cookie)
  1962. * pad := secret_cookie || 0^(32-len(secret_cookie))
  1963. * ```
  1964. * @param {string} secret_key secret key as a hex string (must be 16 bytes in raw or 32 in hex)
  1965. * @param {string} secret_cookie secret cookie as a string for up to 31 character
  1966. * @return {string} e function value for this sk and cookie
  1967. */
  1968. static gint
  1969. lua_cryptobox_encrypt_cookie(lua_State *L)
  1970. {
  1971. guchar aes_block[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE], *blk;
  1972. guchar padded_cookie[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE];
  1973. guchar nonce[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE];
  1974. guchar aes_key[RSPAMD_CRYPTOBOX_AES_KEYSIZE];
  1975. guchar result[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE * 2];
  1976. uint32_t ts;
  1977. const gchar *sk, *cookie;
  1978. gsize sklen, cookie_len;
  1979. gint bklen;
  1980. sk = lua_tolstring(L, 1, &sklen);
  1981. cookie = lua_tolstring(L, 2, &cookie_len);
  1982. if (sk && cookie) {
  1983. if (sklen == 32) {
  1984. /* Hex */
  1985. rspamd_decode_hex_buf(sk, sklen, aes_key, sizeof(aes_key));
  1986. }
  1987. else if (sklen == RSPAMD_CRYPTOBOX_AES_KEYSIZE) {
  1988. /* Raw */
  1989. memcpy(aes_key, sk, sizeof(aes_key));
  1990. }
  1991. else {
  1992. return luaL_error(L, "invalid keysize %d", (gint) sklen);
  1993. }
  1994. if (cookie_len > sizeof(padded_cookie) - 1) {
  1995. return luaL_error(L, "cookie is too long %d", (gint) cookie_len);
  1996. }
  1997. /* Fill nonce */
  1998. ottery_rand_bytes(nonce, sizeof(uint64_t) + sizeof(uint32_t));
  1999. ts = (uint32_t) rspamd_get_calendar_ticks();
  2000. ts = GUINT32_TO_LE(ts);
  2001. memcpy(nonce + sizeof(uint64_t) + sizeof(uint32_t), &ts, sizeof(ts));
  2002. /* Prepare padded cookie */
  2003. memset(padded_cookie, 0, sizeof(padded_cookie));
  2004. memcpy(padded_cookie, cookie, cookie_len);
  2005. /* Perform AES CTR via AES ECB on nonce */
  2006. EVP_CIPHER_CTX *ctx;
  2007. ctx = EVP_CIPHER_CTX_new();
  2008. EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, aes_key, NULL);
  2009. EVP_CIPHER_CTX_set_padding(ctx, 0);
  2010. bklen = sizeof(aes_block);
  2011. blk = aes_block;
  2012. g_assert(EVP_EncryptUpdate(ctx, blk, &bklen, nonce, sizeof(nonce)));
  2013. blk += bklen;
  2014. g_assert(EVP_EncryptFinal_ex(ctx, blk, &bklen));
  2015. EVP_CIPHER_CTX_free(ctx);
  2016. /* Encode result */
  2017. memcpy(result, nonce, sizeof(nonce));
  2018. for (guint i = 0; i < sizeof(aes_block); i++) {
  2019. result[i + sizeof(nonce)] = padded_cookie[i] ^ aes_block[i];
  2020. }
  2021. gsize rlen;
  2022. gchar *res = rspamd_encode_base64(result, sizeof(result),
  2023. 0, &rlen);
  2024. lua_pushlstring(L, res, rlen);
  2025. g_free(res);
  2026. rspamd_explicit_memzero(aes_key, sizeof(aes_key));
  2027. rspamd_explicit_memzero(aes_block, sizeof(aes_block));
  2028. }
  2029. else {
  2030. return luaL_error(L, "invalid arguments");
  2031. }
  2032. return 1;
  2033. }
  2034. /***
  2035. * @function rspamd_cryptobox.decrypt_cookie(secret_key, encrypted_cookie)
  2036. * Specialised function that performs AES-CTR decryption of the provided cookie in form
  2037. * ```
  2038. * e := base64(nonce||aesencrypt(nonce, secret_cookie))
  2039. * nonce := int32_le(unix_timestamp)||random_96bit
  2040. * aesencrypt := aes_ctr(nonce, secret_key) ^ pad(secret_cookie)
  2041. * pad := secret_cookie || 0^(32-len(secret_cookie))
  2042. * ```
  2043. * @param {string} secret_key secret key as a hex string (must be 16 bytes in raw or 32 in hex)
  2044. * @param {string} encrypted_cookie encrypted cookie as a base64 encoded string
  2045. * @return {string+number} decrypted value of the cookie and the cookie timestamp
  2046. */
  2047. static gint
  2048. lua_cryptobox_decrypt_cookie(lua_State *L)
  2049. {
  2050. guchar *blk;
  2051. guchar nonce[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE];
  2052. guchar aes_key[RSPAMD_CRYPTOBOX_AES_KEYSIZE];
  2053. guchar *src;
  2054. uint32_t ts;
  2055. const gchar *sk, *cookie;
  2056. gsize sklen, cookie_len;
  2057. gint bklen;
  2058. sk = lua_tolstring(L, 1, &sklen);
  2059. cookie = lua_tolstring(L, 2, &cookie_len);
  2060. if (sk && cookie) {
  2061. if (sklen == 32) {
  2062. /* Hex */
  2063. rspamd_decode_hex_buf(sk, sklen, aes_key, sizeof(aes_key));
  2064. }
  2065. else if (sklen == RSPAMD_CRYPTOBOX_AES_KEYSIZE) {
  2066. /* Raw */
  2067. memcpy(aes_key, sk, sizeof(aes_key));
  2068. }
  2069. else {
  2070. return luaL_error(L, "invalid keysize %d", (gint) sklen);
  2071. }
  2072. src = g_malloc(cookie_len);
  2073. rspamd_cryptobox_base64_decode(cookie, cookie_len, src, &cookie_len);
  2074. if (cookie_len != RSPAMD_CRYPTOBOX_AES_BLOCKSIZE * 2) {
  2075. g_free(src);
  2076. lua_pushnil(L);
  2077. return 1;
  2078. }
  2079. /* Perform AES CTR via AES ECB on nonce */
  2080. EVP_CIPHER_CTX *ctx;
  2081. ctx = EVP_CIPHER_CTX_new();
  2082. /* As per CTR definition, we use encrypt for both encrypt and decrypt */
  2083. EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, aes_key, NULL);
  2084. EVP_CIPHER_CTX_set_padding(ctx, 0);
  2085. /* Copy time */
  2086. memcpy(&ts, src + sizeof(uint64_t) + sizeof(uint32_t), sizeof(ts));
  2087. ts = GUINT32_FROM_LE(ts);
  2088. bklen = sizeof(nonce);
  2089. blk = nonce;
  2090. g_assert(EVP_EncryptUpdate(ctx, blk, &bklen, src,
  2091. RSPAMD_CRYPTOBOX_AES_BLOCKSIZE));
  2092. blk += bklen;
  2093. g_assert(EVP_EncryptFinal_ex(ctx, blk, &bklen));
  2094. EVP_CIPHER_CTX_free(ctx);
  2095. /* Decode result */
  2096. for (guint i = 0; i < RSPAMD_CRYPTOBOX_AES_BLOCKSIZE; i++) {
  2097. src[i + sizeof(nonce)] ^= nonce[i];
  2098. }
  2099. if (src[RSPAMD_CRYPTOBOX_AES_BLOCKSIZE * 2 - 1] != '\0') {
  2100. /* Bad cookie */
  2101. lua_pushnil(L);
  2102. lua_pushnil(L);
  2103. }
  2104. else {
  2105. lua_pushstring(L, src + sizeof(nonce));
  2106. lua_pushnumber(L, ts);
  2107. }
  2108. rspamd_explicit_memzero(src, RSPAMD_CRYPTOBOX_AES_BLOCKSIZE * 2);
  2109. g_free(src);
  2110. rspamd_explicit_memzero(aes_key, sizeof(aes_key));
  2111. }
  2112. else {
  2113. return luaL_error(L, "invalid arguments");
  2114. }
  2115. return 2;
  2116. }
  2117. /***
  2118. * @function rspamd_cryptobox.pbkdf([password, [kdf_alg]])
  2119. * Function that encrypts password using PBKDF function.
  2120. * This function either reads password from STDIN or accepts prepared password as
  2121. * an argument
  2122. * @param {string} password optional password string
  2123. * @param {string} kdf_alg algorithm to use (catena or pbkdf2)
  2124. * @return {string} encrypted password or nil if error occurs
  2125. */
  2126. static gint
  2127. lua_cryptobox_pbkdf(lua_State *L)
  2128. {
  2129. const struct rspamd_controller_pbkdf *pbkdf = NULL;
  2130. const gchar *pbkdf_str = "catena";
  2131. gchar *password;
  2132. gsize pwlen;
  2133. if (lua_type(L, 2) == LUA_TSTRING) {
  2134. pbkdf_str = lua_tostring(L, 2);
  2135. }
  2136. for (guint i = 0; i < RSPAMD_PBKDF_ID_MAX - 1; i++) {
  2137. pbkdf = &pbkdf_list[i];
  2138. if (g_ascii_strcasecmp(pbkdf_str, pbkdf->alias) == 0) {
  2139. break;
  2140. }
  2141. if (g_ascii_strcasecmp(pbkdf_str, pbkdf->name) == 0) {
  2142. break;
  2143. }
  2144. pbkdf = NULL;
  2145. }
  2146. if (pbkdf == NULL) {
  2147. return luaL_error(L, "invalid pbkdf algorithm: %s", pbkdf_str);
  2148. }
  2149. if (lua_type(L, 1) == LUA_TSTRING) {
  2150. password = g_strdup(lua_tolstring(L, 1, &pwlen));
  2151. }
  2152. else {
  2153. pwlen = 8192;
  2154. password = g_malloc0(pwlen);
  2155. pwlen = rspamd_read_passphrase(password, pwlen, 0, NULL);
  2156. }
  2157. if (pwlen == 0) {
  2158. lua_pushnil(L);
  2159. g_free(password);
  2160. return 1;
  2161. }
  2162. guchar *salt, *key;
  2163. gchar *encoded_salt, *encoded_key;
  2164. GString *result;
  2165. salt = g_alloca(pbkdf->salt_len);
  2166. key = g_alloca(pbkdf->key_len);
  2167. ottery_rand_bytes(salt, pbkdf->salt_len);
  2168. /* Derive key */
  2169. rspamd_cryptobox_pbkdf(password, pwlen,
  2170. salt, pbkdf->salt_len, key, pbkdf->key_len, pbkdf->complexity,
  2171. pbkdf->type);
  2172. encoded_salt = rspamd_encode_base32(salt, pbkdf->salt_len, RSPAMD_BASE32_DEFAULT);
  2173. encoded_key = rspamd_encode_base32(key, pbkdf->key_len, RSPAMD_BASE32_DEFAULT);
  2174. result = g_string_new("");
  2175. rspamd_printf_gstring(result, "$%d$%s$%s", pbkdf->id, encoded_salt,
  2176. encoded_key);
  2177. g_free(encoded_salt);
  2178. g_free(encoded_key);
  2179. rspamd_explicit_memzero(password, pwlen);
  2180. g_free(password);
  2181. lua_pushlstring(L, result->str, result->len);
  2182. g_string_free(result, TRUE);
  2183. return 1;
  2184. }
  2185. /***
  2186. * @function rspamd_cryptobox.gen_dkim_keypair([alg, [nbits]])
  2187. * Generates DKIM keypair. Returns 2 base64 strings as rspamd_text: privkey and pubkey
  2188. * @param {string} alg optional algorithm (rsa default, can be ed25519)
  2189. * @param {number} nbits optional number of bits for rsa (default 1024)
  2190. * @return {rspamd_text,rspamd_text} private key and public key as base64 encoded strings
  2191. */
  2192. static gint
  2193. lua_cryptobox_gen_dkim_keypair(lua_State *L)
  2194. {
  2195. const gchar *alg_str = "rsa";
  2196. guint nbits = 1024;
  2197. struct rspamd_lua_text *priv_out, *pub_out;
  2198. if (lua_type(L, 1) == LUA_TSTRING) {
  2199. alg_str = lua_tostring(L, 1);
  2200. }
  2201. if (lua_type(L, 2) == LUA_TNUMBER) {
  2202. nbits = lua_tointeger(L, 2);
  2203. }
  2204. if (strcmp(alg_str, "rsa") == 0) {
  2205. BIGNUM *e;
  2206. RSA *r;
  2207. EVP_PKEY *pk;
  2208. e = BN_new();
  2209. r = RSA_new();
  2210. pk = EVP_PKEY_new();
  2211. if (BN_set_word(e, RSA_F4) != 1) {
  2212. BN_free(e);
  2213. RSA_free(r);
  2214. EVP_PKEY_free(pk);
  2215. return luaL_error(L, "BN_set_word failed");
  2216. }
  2217. if (RSA_generate_key_ex(r, nbits, e, NULL) != 1) {
  2218. BN_free(e);
  2219. RSA_free(r);
  2220. EVP_PKEY_free(pk);
  2221. return luaL_error(L, "RSA_generate_key_ex failed");
  2222. }
  2223. if (EVP_PKEY_set1_RSA(pk, r) != 1) {
  2224. BN_free(e);
  2225. RSA_free(r);
  2226. EVP_PKEY_free(pk);
  2227. return luaL_error(L, "EVP_PKEY_set1_RSA failed");
  2228. }
  2229. BIO *mbio;
  2230. gint rc, len;
  2231. guchar *data;
  2232. gchar *b64_data;
  2233. gsize b64_len;
  2234. mbio = BIO_new(BIO_s_mem());
  2235. /* Process private key */
  2236. rc = i2d_RSAPrivateKey_bio(mbio, r);
  2237. if (rc == 0) {
  2238. BIO_free(mbio);
  2239. BN_free(e);
  2240. RSA_free(r);
  2241. EVP_PKEY_free(pk);
  2242. return luaL_error(L, "i2d_RSAPrivateKey_bio failed");
  2243. }
  2244. len = BIO_get_mem_data(mbio, &data);
  2245. b64_data = rspamd_encode_base64(data, len, -1, &b64_len);
  2246. priv_out = lua_newuserdata(L, sizeof(*priv_out));
  2247. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2248. priv_out->start = b64_data;
  2249. priv_out->len = b64_len;
  2250. priv_out->flags = RSPAMD_TEXT_FLAG_OWN | RSPAMD_TEXT_FLAG_WIPE;
  2251. /* Process public key */
  2252. BIO_reset(mbio);
  2253. rc = i2d_RSA_PUBKEY_bio(mbio, r);
  2254. if (rc == 0) {
  2255. BIO_free(mbio);
  2256. BN_free(e);
  2257. RSA_free(r);
  2258. EVP_PKEY_free(pk);
  2259. return luaL_error(L, "i2d_RSA_PUBKEY_bio failed");
  2260. }
  2261. len = BIO_get_mem_data(mbio, &data);
  2262. b64_data = rspamd_encode_base64(data, len, -1, &b64_len);
  2263. pub_out = lua_newuserdata(L, sizeof(*pub_out));
  2264. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2265. pub_out->start = b64_data;
  2266. pub_out->len = b64_len;
  2267. pub_out->flags = RSPAMD_TEXT_FLAG_OWN;
  2268. BN_free(e);
  2269. RSA_free(r);
  2270. EVP_PKEY_free(pk);
  2271. BIO_free(mbio);
  2272. }
  2273. else if (strcmp(alg_str, "ed25519") == 0) {
  2274. rspamd_sig_pk_t pk;
  2275. rspamd_sig_sk_t sk;
  2276. gchar *b64_data;
  2277. gsize b64_len;
  2278. rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
  2279. /* Process private key */
  2280. b64_data = rspamd_encode_base64(sk,
  2281. rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
  2282. -1, &b64_len);
  2283. priv_out = lua_newuserdata(L, sizeof(*priv_out));
  2284. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2285. priv_out->start = b64_data;
  2286. priv_out->len = b64_len;
  2287. priv_out->flags = RSPAMD_TEXT_FLAG_OWN | RSPAMD_TEXT_FLAG_WIPE;
  2288. /* Process public key */
  2289. b64_data = rspamd_encode_base64(pk,
  2290. rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
  2291. -1, &b64_len);
  2292. pub_out = lua_newuserdata(L, sizeof(*pub_out));
  2293. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2294. pub_out->start = b64_data;
  2295. pub_out->len = b64_len;
  2296. pub_out->flags = RSPAMD_TEXT_FLAG_OWN;
  2297. rspamd_explicit_memzero(pk, sizeof(pk));
  2298. rspamd_explicit_memzero(sk, sizeof(sk));
  2299. }
  2300. else if (strcmp(alg_str, "ed25519-seed") == 0) {
  2301. rspamd_sig_pk_t pk;
  2302. rspamd_sig_sk_t sk;
  2303. gchar *b64_data;
  2304. gsize b64_len;
  2305. rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
  2306. /* Process private key */
  2307. b64_data = rspamd_encode_base64(sk,
  2308. 32,
  2309. -1, &b64_len);
  2310. priv_out = lua_newuserdata(L, sizeof(*priv_out));
  2311. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2312. priv_out->start = b64_data;
  2313. priv_out->len = b64_len;
  2314. priv_out->flags = RSPAMD_TEXT_FLAG_OWN | RSPAMD_TEXT_FLAG_WIPE;
  2315. /* Process public key */
  2316. b64_data = rspamd_encode_base64(pk,
  2317. rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
  2318. -1, &b64_len);
  2319. pub_out = lua_newuserdata(L, sizeof(*pub_out));
  2320. rspamd_lua_setclass(L, rspamd_text_classname, -1);
  2321. pub_out->start = b64_data;
  2322. pub_out->len = b64_len;
  2323. pub_out->flags = RSPAMD_TEXT_FLAG_OWN;
  2324. rspamd_explicit_memzero(pk, sizeof(pk));
  2325. rspamd_explicit_memzero(sk, sizeof(sk));
  2326. }
  2327. else {
  2328. return luaL_error(L, "invalid algorithm %s", alg_str);
  2329. }
  2330. return 2;
  2331. }
  2332. /*
  2333. * Secretbox API
  2334. */
  2335. /* Ensure that KDF output is suitable for crypto_secretbox_KEYBYTES */
  2336. #ifdef crypto_generichash_BYTES_MIN
  2337. G_STATIC_ASSERT(crypto_secretbox_KEYBYTES >= crypto_generichash_BYTES_MIN);
  2338. #endif
  2339. /***
  2340. * @function rspamd_cryptobox_secretbox.create(secret_string, [params])
  2341. * Generates a secretbox state by expanding secret string
  2342. * @param {string/text} secret_string secret string (should have high enough entropy)
  2343. * @param {table} params optional parameters - NYI
  2344. * @return {rspamd_cryptobox_secretbox} opaque object with the key expanded
  2345. */
  2346. static gint
  2347. lua_cryptobox_secretbox_create(lua_State *L)
  2348. {
  2349. const gchar *in;
  2350. gsize inlen;
  2351. if (lua_isstring(L, 1)) {
  2352. in = lua_tolstring(L, 1, &inlen);
  2353. }
  2354. else if (lua_isuserdata(L, 1)) {
  2355. struct rspamd_lua_text *t = lua_check_text(L, 1);
  2356. if (!t) {
  2357. return luaL_error(L, "invalid arguments; userdata is not text");
  2358. }
  2359. in = t->start;
  2360. inlen = t->len;
  2361. }
  2362. else {
  2363. return luaL_error(L, "invalid arguments; userdata or string are expected");
  2364. }
  2365. if (in == NULL || inlen == 0) {
  2366. return luaL_error(L, "invalid arguments; non empty secret expected");
  2367. }
  2368. struct rspamd_lua_cryptobox_secretbox *sbox, **psbox;
  2369. sbox = g_malloc0(sizeof(*sbox));
  2370. crypto_generichash(sbox->sk, sizeof(sbox->sk), in, inlen, NULL, 0);
  2371. psbox = lua_newuserdata(L, sizeof(*psbox));
  2372. *psbox = sbox;
  2373. rspamd_lua_setclass(L, rspamd_cryptobox_secretbox_classname, -1);
  2374. return 1;
  2375. }
  2376. static gint
  2377. lua_cryptobox_secretbox_gc(lua_State *L)
  2378. {
  2379. struct rspamd_lua_cryptobox_secretbox *sbox =
  2380. lua_check_cryptobox_secretbox(L, 1);
  2381. if (sbox != NULL) {
  2382. sodium_memzero(sbox->sk, sizeof(sbox->sk));
  2383. g_free(sbox);
  2384. }
  2385. else {
  2386. return luaL_error(L, "invalid arguments");
  2387. }
  2388. return 0;
  2389. }
  2390. /***
  2391. * @method rspamd_cryptobox_secretbox:encrypt(input, [nonce])
  2392. * Encrypts data using secretbox. MAC is prepended to the message
  2393. * @param {string/text} input input to encrypt
  2394. * @param {string/text} nonce optional nonce (must be 1 - 192 bits length)
  2395. * @param {table} params optional parameters - NYI
  2396. * @return {rspamd_text},{rspamd_text} output with mac + nonce or just output if nonce is there
  2397. */
  2398. static gint
  2399. lua_cryptobox_secretbox_encrypt(lua_State *L)
  2400. {
  2401. const gchar *in, *nonce;
  2402. gsize inlen, nlen;
  2403. struct rspamd_lua_cryptobox_secretbox *sbox =
  2404. lua_check_cryptobox_secretbox(L, 1);
  2405. struct rspamd_lua_text *out;
  2406. if (sbox == NULL) {
  2407. return luaL_error(L, "invalid arguments");
  2408. }
  2409. if (lua_isstring(L, 2)) {
  2410. in = lua_tolstring(L, 2, &inlen);
  2411. }
  2412. else if (lua_isuserdata(L, 2)) {
  2413. struct rspamd_lua_text *t = lua_check_text(L, 2);
  2414. if (!t) {
  2415. return luaL_error(L, "invalid arguments; userdata is not text");
  2416. }
  2417. in = t->start;
  2418. inlen = t->len;
  2419. }
  2420. else {
  2421. return luaL_error(L, "invalid arguments; userdata or string are expected");
  2422. }
  2423. /* Nonce part */
  2424. if (!lua_isnoneornil(L, 3)) {
  2425. if (lua_isstring(L, 3)) {
  2426. nonce = lua_tolstring(L, 3, &nlen);
  2427. }
  2428. else if (lua_isuserdata(L, 3)) {
  2429. struct rspamd_lua_text *t = lua_check_text(L, 3);
  2430. if (!t) {
  2431. return luaL_error(L, "invalid arguments; userdata is not text");
  2432. }
  2433. nonce = t->start;
  2434. nlen = t->len;
  2435. }
  2436. else {
  2437. return luaL_error(L, "invalid arguments; userdata or string are expected");
  2438. }
  2439. if (nlen < 1 || nlen > crypto_secretbox_NONCEBYTES) {
  2440. return luaL_error(L, "bad nonce");
  2441. }
  2442. guchar real_nonce[crypto_secretbox_NONCEBYTES];
  2443. memset(real_nonce, 0, sizeof(real_nonce));
  2444. memcpy(real_nonce, nonce, nlen);
  2445. out = lua_new_text(L, NULL, inlen + crypto_secretbox_MACBYTES,
  2446. TRUE);
  2447. crypto_secretbox_easy((guchar *) out->start, in, inlen,
  2448. nonce, sbox->sk);
  2449. return 1;
  2450. }
  2451. else {
  2452. /* Random nonce */
  2453. struct rspamd_lua_text *random_nonce;
  2454. out = lua_new_text(L, NULL, inlen + crypto_secretbox_MACBYTES,
  2455. TRUE);
  2456. random_nonce = lua_new_text(L, NULL, crypto_secretbox_NONCEBYTES, TRUE);
  2457. randombytes_buf((guchar *) random_nonce->start, random_nonce->len);
  2458. crypto_secretbox_easy((guchar *) out->start, in, inlen,
  2459. random_nonce->start, sbox->sk);
  2460. return 2; /* output + random nonce */
  2461. }
  2462. }
  2463. /***
  2464. * @method rspamd_cryptobox_secretbox:decrypt(input, nonce)
  2465. * Decrypts data using secretbox
  2466. * @param {string/text} nonce nonce used to encrypt
  2467. * @param {string/text} input input to decrypt
  2468. * @param {table} params optional parameters - NYI
  2469. * @return {boolean},{rspamd_text} decryption result + decrypted text
  2470. */
  2471. static gint
  2472. lua_cryptobox_secretbox_decrypt(lua_State *L)
  2473. {
  2474. const gchar *in, *nonce;
  2475. gsize inlen, nlen;
  2476. struct rspamd_lua_cryptobox_secretbox *sbox =
  2477. lua_check_cryptobox_secretbox(L, 1);
  2478. struct rspamd_lua_text *out;
  2479. if (sbox == NULL) {
  2480. return luaL_error(L, "invalid arguments");
  2481. }
  2482. /* Input argument */
  2483. if (lua_isstring(L, 2)) {
  2484. in = lua_tolstring(L, 2, &inlen);
  2485. }
  2486. else if (lua_isuserdata(L, 2)) {
  2487. struct rspamd_lua_text *t = lua_check_text(L, 2);
  2488. if (!t) {
  2489. return luaL_error(L, "invalid arguments; userdata is not text");
  2490. }
  2491. in = t->start;
  2492. inlen = t->len;
  2493. }
  2494. else {
  2495. return luaL_error(L, "invalid arguments; userdata or string are expected");
  2496. }
  2497. /* Nonce argument */
  2498. if (lua_isstring(L, 3)) {
  2499. nonce = lua_tolstring(L, 3, &nlen);
  2500. }
  2501. else if (lua_isuserdata(L, 3)) {
  2502. struct rspamd_lua_text *t = lua_check_text(L, 3);
  2503. if (!t) {
  2504. return luaL_error(L, "invalid arguments; userdata is not text");
  2505. }
  2506. nonce = t->start;
  2507. nlen = t->len;
  2508. }
  2509. else {
  2510. return luaL_error(L, "invalid arguments; userdata or string are expected");
  2511. }
  2512. if (nlen < 1 || nlen > crypto_secretbox_NONCEBYTES) {
  2513. lua_pushboolean(L, false);
  2514. lua_pushstring(L, "invalid nonce");
  2515. return 2;
  2516. }
  2517. if (inlen < crypto_secretbox_MACBYTES) {
  2518. lua_pushboolean(L, false);
  2519. lua_pushstring(L, "too short");
  2520. return 2;
  2521. }
  2522. guchar real_nonce[crypto_secretbox_NONCEBYTES];
  2523. memset(real_nonce, 0, sizeof(real_nonce));
  2524. memcpy(real_nonce, nonce, nlen);
  2525. out = lua_new_text(L, NULL, inlen - crypto_secretbox_MACBYTES,
  2526. TRUE);
  2527. gint text_pos = lua_gettop(L);
  2528. if (crypto_secretbox_open_easy((guchar *) out->start, in, inlen,
  2529. nonce, sbox->sk) == 0) {
  2530. lua_pushboolean(L, true);
  2531. lua_pushvalue(L, text_pos); /* Prevent gc by copying in stack */
  2532. }
  2533. else {
  2534. lua_pushboolean(L, false);
  2535. lua_pushstring(L, "authentication error");
  2536. }
  2537. /* This causes gc method if decryption has failed */
  2538. lua_remove(L, text_pos);
  2539. return 2;
  2540. }
  2541. static gint
  2542. lua_load_pubkey(lua_State *L)
  2543. {
  2544. lua_newtable(L);
  2545. luaL_register(L, NULL, cryptoboxpubkeylib_f);
  2546. return 1;
  2547. }
  2548. static gint
  2549. lua_load_keypair(lua_State *L)
  2550. {
  2551. lua_newtable(L);
  2552. luaL_register(L, NULL, cryptoboxkeypairlib_f);
  2553. return 1;
  2554. }
  2555. static gint
  2556. lua_load_signature(lua_State *L)
  2557. {
  2558. lua_newtable(L);
  2559. luaL_register(L, NULL, cryptoboxsignlib_f);
  2560. return 1;
  2561. }
  2562. static gint
  2563. lua_load_hash(lua_State *L)
  2564. {
  2565. lua_newtable(L);
  2566. luaL_register(L, NULL, cryptoboxhashlib_f);
  2567. return 1;
  2568. }
  2569. static gint
  2570. lua_load_cryptobox_secretbox(lua_State *L)
  2571. {
  2572. lua_newtable(L);
  2573. luaL_register(L, NULL, cryptoboxsecretboxlib_f);
  2574. return 1;
  2575. }
  2576. static gint
  2577. lua_load_cryptobox(lua_State *L)
  2578. {
  2579. lua_newtable(L);
  2580. luaL_register(L, NULL, cryptoboxlib_f);
  2581. return 1;
  2582. }
  2583. void luaopen_cryptobox(lua_State *L)
  2584. {
  2585. rspamd_lua_new_class(L, rspamd_cryptobox_pubkey_classname, cryptoboxpubkeylib_m);
  2586. lua_pop(L, 1);
  2587. rspamd_lua_add_preload(L, "rspamd_cryptobox_pubkey", lua_load_pubkey);
  2588. rspamd_lua_new_class(L, rspamd_cryptobox_keypair_classname, cryptoboxkeypairlib_m);
  2589. lua_pop(L, 1);
  2590. rspamd_lua_add_preload(L, "rspamd_cryptobox_keypair", lua_load_keypair);
  2591. rspamd_lua_new_class(L, rspamd_cryptobox_signature_classname, cryptoboxsignlib_m);
  2592. lua_pop(L, 1);
  2593. rspamd_lua_add_preload(L, "rspamd_cryptobox_signature", lua_load_signature);
  2594. rspamd_lua_new_class(L, rspamd_cryptobox_hash_classname, cryptoboxhashlib_m);
  2595. lua_pop(L, 1);
  2596. rspamd_lua_add_preload(L, "rspamd_cryptobox_hash", lua_load_hash);
  2597. rspamd_lua_new_class(L, rspamd_cryptobox_secretbox_classname,
  2598. cryptoboxsecretboxlib_m);
  2599. lua_pop(L, 1);
  2600. rspamd_lua_add_preload(L, "rspamd_cryptobox_secretbox",
  2601. lua_load_cryptobox_secretbox);
  2602. rspamd_lua_add_preload(L, "rspamd_cryptobox", lua_load_cryptobox);
  2603. lua_settop(L, 0);
  2604. }