libsodium.c 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Frank Denis <jedisct1@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/info.h"
  22. #include "php_libsodium.h"
  23. #include "zend_exceptions.h"
  24. #include <sodium.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #define PHP_SODIUM_ZSTR_TRUNCATE(zs, len) do { ZSTR_LEN(zs) = (len); } while(0)
  28. static zend_class_entry *sodium_exception_ce;
  29. #if (defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || \
  30. defined(_M_AMD64) || defined(_M_IX86))
  31. # define HAVE_AESGCM 1
  32. #endif
  33. static zend_always_inline zend_string *zend_string_checked_alloc(size_t len, int persistent)
  34. {
  35. zend_string *zs;
  36. if (ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)) < len) {
  37. zend_error_noreturn(E_ERROR, "Memory allocation too large (%zu bytes)", len);
  38. }
  39. zs = zend_string_alloc(len, persistent);
  40. ZSTR_VAL(zs)[len] = 0;
  41. return zs;
  42. }
  43. #include "libsodium_arginfo.h"
  44. #ifndef crypto_aead_chacha20poly1305_IETF_KEYBYTES
  45. # define crypto_aead_chacha20poly1305_IETF_KEYBYTES crypto_aead_chacha20poly1305_KEYBYTES
  46. #endif
  47. #ifndef crypto_aead_chacha20poly1305_IETF_NSECBYTES
  48. # define crypto_aead_chacha20poly1305_IETF_NSECBYTES crypto_aead_chacha20poly1305_NSECBYTES
  49. #endif
  50. #ifndef crypto_aead_chacha20poly1305_IETF_ABYTES
  51. # define crypto_aead_chacha20poly1305_IETF_ABYTES crypto_aead_chacha20poly1305_ABYTES
  52. #endif
  53. #if defined(crypto_secretstream_xchacha20poly1305_ABYTES) && SODIUM_LIBRARY_VERSION_MAJOR < 10
  54. # undef crypto_secretstream_xchacha20poly1305_ABYTES
  55. #endif
  56. #ifndef crypto_pwhash_OPSLIMIT_MIN
  57. # define crypto_pwhash_OPSLIMIT_MIN crypto_pwhash_OPSLIMIT_INTERACTIVE
  58. #endif
  59. #ifndef crypto_pwhash_MEMLIMIT_MIN
  60. # define crypto_pwhash_MEMLIMIT_MIN crypto_pwhash_MEMLIMIT_INTERACTIVE
  61. #endif
  62. #ifndef crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN
  63. # define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
  64. #endif
  65. #ifndef crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN
  66. # define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
  67. #endif
  68. /* Load after the "standard" module in order to give it
  69. * priority in registering argon2i/argon2id password hashers.
  70. */
  71. static const zend_module_dep sodium_deps[] = {
  72. ZEND_MOD_REQUIRED("standard")
  73. ZEND_MOD_END
  74. };
  75. zend_module_entry sodium_module_entry = {
  76. STANDARD_MODULE_HEADER_EX,
  77. NULL,
  78. sodium_deps,
  79. "sodium",
  80. ext_functions,
  81. PHP_MINIT(sodium),
  82. PHP_MSHUTDOWN(sodium),
  83. NULL,
  84. NULL,
  85. PHP_MINFO(sodium),
  86. PHP_SODIUM_VERSION,
  87. STANDARD_MODULE_PROPERTIES
  88. };
  89. /* }}} */
  90. #ifdef COMPILE_DL_SODIUM
  91. ZEND_GET_MODULE(sodium)
  92. #endif
  93. /* Remove argument information from backtrace to prevent information leaks */
  94. static void sodium_remove_param_values_from_backtrace(zend_object *obj) {
  95. zval rv;
  96. zval *trace = zend_read_property(zend_get_exception_base(obj), obj, "trace", sizeof("trace")-1, 0, &rv);
  97. if (trace && Z_TYPE_P(trace) == IS_ARRAY) {
  98. zval *frame;
  99. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(trace), frame) {
  100. if (Z_TYPE_P(frame) == IS_ARRAY) {
  101. zval *args = zend_hash_str_find(Z_ARRVAL_P(frame), "args", sizeof("args")-1);
  102. if (args) {
  103. zval_ptr_dtor(args);
  104. ZVAL_EMPTY_ARRAY(args);
  105. }
  106. }
  107. } ZEND_HASH_FOREACH_END();
  108. }
  109. }
  110. static zend_object *sodium_exception_create_object(zend_class_entry *ce) {
  111. zend_object *obj = zend_ce_exception->create_object(ce);
  112. sodium_remove_param_values_from_backtrace(obj);
  113. return obj;
  114. }
  115. static void sodium_separate_string(zval *zv) {
  116. ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
  117. if (!Z_REFCOUNTED_P(zv) || Z_REFCOUNT_P(zv) > 1) {
  118. zend_string *copy = zend_string_init(Z_STRVAL_P(zv), Z_STRLEN_P(zv), 0);
  119. Z_TRY_DELREF_P(zv);
  120. ZVAL_STR(zv, copy);
  121. }
  122. }
  123. PHP_MINIT_FUNCTION(sodium)
  124. {
  125. if (sodium_init() < 0) {
  126. zend_error(E_ERROR, "sodium_init()");
  127. }
  128. sodium_exception_ce = register_class_SodiumException(zend_ce_exception);
  129. sodium_exception_ce->create_object = sodium_exception_create_object;
  130. REGISTER_STRING_CONSTANT("SODIUM_LIBRARY_VERSION",
  131. (char *) (void *) sodium_version_string(), CONST_CS | CONST_PERSISTENT);
  132. REGISTER_LONG_CONSTANT("SODIUM_LIBRARY_MAJOR_VERSION",
  133. sodium_library_version_major(), CONST_CS | CONST_PERSISTENT);
  134. REGISTER_LONG_CONSTANT("SODIUM_LIBRARY_MINOR_VERSION",
  135. sodium_library_version_minor(), CONST_CS | CONST_PERSISTENT);
  136. #ifdef HAVE_AESGCM
  137. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES",
  138. crypto_aead_aes256gcm_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  139. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES",
  140. crypto_aead_aes256gcm_NSECBYTES, CONST_CS | CONST_PERSISTENT);
  141. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES",
  142. crypto_aead_aes256gcm_NPUBBYTES, CONST_CS | CONST_PERSISTENT);
  143. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES",
  144. crypto_aead_aes256gcm_ABYTES, CONST_CS | CONST_PERSISTENT);
  145. #endif
  146. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES",
  147. crypto_aead_chacha20poly1305_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  148. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES",
  149. crypto_aead_chacha20poly1305_NSECBYTES, CONST_CS | CONST_PERSISTENT);
  150. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES",
  151. crypto_aead_chacha20poly1305_NPUBBYTES, CONST_CS | CONST_PERSISTENT);
  152. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES",
  153. crypto_aead_chacha20poly1305_ABYTES, CONST_CS | CONST_PERSISTENT);
  154. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES",
  155. crypto_aead_chacha20poly1305_IETF_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  156. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES",
  157. crypto_aead_chacha20poly1305_IETF_NSECBYTES, CONST_CS | CONST_PERSISTENT);
  158. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES",
  159. crypto_aead_chacha20poly1305_IETF_NPUBBYTES, CONST_CS | CONST_PERSISTENT);
  160. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES",
  161. crypto_aead_chacha20poly1305_IETF_ABYTES, CONST_CS | CONST_PERSISTENT);
  162. #ifdef crypto_aead_xchacha20poly1305_IETF_NPUBBYTES
  163. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES",
  164. crypto_aead_xchacha20poly1305_IETF_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  165. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES",
  166. crypto_aead_xchacha20poly1305_IETF_NSECBYTES, CONST_CS | CONST_PERSISTENT);
  167. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES",
  168. crypto_aead_xchacha20poly1305_IETF_NPUBBYTES, CONST_CS | CONST_PERSISTENT);
  169. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES",
  170. crypto_aead_xchacha20poly1305_IETF_ABYTES, CONST_CS | CONST_PERSISTENT);
  171. #endif
  172. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AUTH_BYTES",
  173. crypto_auth_BYTES, CONST_CS | CONST_PERSISTENT);
  174. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_AUTH_KEYBYTES",
  175. crypto_auth_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  176. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_SEALBYTES",
  177. crypto_box_SEALBYTES, CONST_CS | CONST_PERSISTENT);
  178. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_SECRETKEYBYTES",
  179. crypto_box_SECRETKEYBYTES, CONST_CS | CONST_PERSISTENT);
  180. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_PUBLICKEYBYTES",
  181. crypto_box_PUBLICKEYBYTES, CONST_CS | CONST_PERSISTENT);
  182. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_KEYPAIRBYTES",
  183. crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES,
  184. CONST_CS | CONST_PERSISTENT);
  185. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_MACBYTES",
  186. crypto_box_MACBYTES, CONST_CS | CONST_PERSISTENT);
  187. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_NONCEBYTES",
  188. crypto_box_NONCEBYTES, CONST_CS | CONST_PERSISTENT);
  189. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_BOX_SEEDBYTES",
  190. crypto_box_SEEDBYTES, CONST_CS | CONST_PERSISTENT);
  191. #ifndef crypto_kdf_BYTES_MIN
  192. # define crypto_kdf_BYTES_MIN 16
  193. # define crypto_kdf_BYTES_MAX 64
  194. # define crypto_kdf_CONTEXTBYTES 8
  195. # define crypto_kdf_KEYBYTES 32
  196. #endif
  197. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KDF_BYTES_MIN",
  198. crypto_kdf_BYTES_MIN, CONST_CS | CONST_PERSISTENT);
  199. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KDF_BYTES_MAX",
  200. crypto_kdf_BYTES_MAX, CONST_CS | CONST_PERSISTENT);
  201. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KDF_CONTEXTBYTES",
  202. crypto_kdf_CONTEXTBYTES, CONST_CS | CONST_PERSISTENT);
  203. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KDF_KEYBYTES",
  204. crypto_kdf_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  205. #ifndef crypto_kx_SEEDBYTES
  206. # define crypto_kx_SEEDBYTES 32
  207. # define crypto_kx_SESSIONKEYBYTES 32
  208. # define crypto_kx_PUBLICKEYBYTES 32
  209. # define crypto_kx_SECRETKEYBYTES 32
  210. #endif
  211. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SEEDBYTES",
  212. crypto_kx_SEEDBYTES, CONST_CS | CONST_PERSISTENT);
  213. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SESSIONKEYBYTES",
  214. crypto_kx_SESSIONKEYBYTES, CONST_CS | CONST_PERSISTENT);
  215. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_PUBLICKEYBYTES",
  216. crypto_kx_PUBLICKEYBYTES, CONST_CS | CONST_PERSISTENT);
  217. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_SECRETKEYBYTES",
  218. crypto_kx_SECRETKEYBYTES, CONST_CS | CONST_PERSISTENT);
  219. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_KEYPAIRBYTES",
  220. crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES,
  221. CONST_CS | CONST_PERSISTENT);
  222. #ifdef crypto_secretstream_xchacha20poly1305_ABYTES
  223. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES",
  224. crypto_secretstream_xchacha20poly1305_ABYTES,
  225. CONST_CS | CONST_PERSISTENT);
  226. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES",
  227. crypto_secretstream_xchacha20poly1305_HEADERBYTES,
  228. CONST_CS | CONST_PERSISTENT);
  229. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES",
  230. crypto_secretstream_xchacha20poly1305_KEYBYTES,
  231. CONST_CS | CONST_PERSISTENT);
  232. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX",
  233. crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX,
  234. CONST_CS | CONST_PERSISTENT);
  235. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE",
  236. crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
  237. CONST_CS | CONST_PERSISTENT);
  238. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH",
  239. crypto_secretstream_xchacha20poly1305_TAG_PUSH,
  240. CONST_CS | CONST_PERSISTENT);
  241. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY",
  242. crypto_secretstream_xchacha20poly1305_TAG_REKEY,
  243. CONST_CS | CONST_PERSISTENT);
  244. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL",
  245. crypto_secretstream_xchacha20poly1305_TAG_FINAL,
  246. CONST_CS | CONST_PERSISTENT);
  247. #endif
  248. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES",
  249. crypto_generichash_BYTES, CONST_CS | CONST_PERSISTENT);
  250. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES_MIN",
  251. crypto_generichash_BYTES_MIN, CONST_CS | CONST_PERSISTENT);
  252. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES_MAX",
  253. crypto_generichash_BYTES_MAX, CONST_CS | CONST_PERSISTENT);
  254. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_KEYBYTES",
  255. crypto_generichash_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  256. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN",
  257. crypto_generichash_KEYBYTES_MIN, CONST_CS | CONST_PERSISTENT);
  258. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX",
  259. crypto_generichash_KEYBYTES_MAX, CONST_CS | CONST_PERSISTENT);
  260. #ifdef crypto_pwhash_SALTBYTES
  261. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13",
  262. crypto_pwhash_ALG_ARGON2I13, CONST_CS | CONST_PERSISTENT);
  263. # ifdef crypto_pwhash_ALG_ARGON2ID13
  264. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13",
  265. crypto_pwhash_ALG_ARGON2ID13, CONST_CS | CONST_PERSISTENT);
  266. # endif
  267. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_ALG_DEFAULT",
  268. crypto_pwhash_ALG_DEFAULT, CONST_CS | CONST_PERSISTENT);
  269. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SALTBYTES",
  270. crypto_pwhash_SALTBYTES, CONST_CS | CONST_PERSISTENT);
  271. REGISTER_STRING_CONSTANT("SODIUM_CRYPTO_PWHASH_STRPREFIX",
  272. crypto_pwhash_STRPREFIX, CONST_CS | CONST_PERSISTENT);
  273. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE",
  274. crypto_pwhash_opslimit_interactive(), CONST_CS | CONST_PERSISTENT);
  275. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE",
  276. crypto_pwhash_memlimit_interactive(), CONST_CS | CONST_PERSISTENT);
  277. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE",
  278. crypto_pwhash_opslimit_moderate(), CONST_CS | CONST_PERSISTENT);
  279. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE",
  280. crypto_pwhash_memlimit_moderate(), CONST_CS | CONST_PERSISTENT);
  281. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE",
  282. crypto_pwhash_opslimit_sensitive(), CONST_CS | CONST_PERSISTENT);
  283. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE",
  284. crypto_pwhash_memlimit_sensitive(), CONST_CS | CONST_PERSISTENT);
  285. #endif
  286. #ifdef crypto_pwhash_scryptsalsa208sha256_SALTBYTES
  287. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES",
  288. crypto_pwhash_scryptsalsa208sha256_SALTBYTES, CONST_CS | CONST_PERSISTENT);
  289. REGISTER_STRING_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX",
  290. crypto_pwhash_scryptsalsa208sha256_STRPREFIX, CONST_CS | CONST_PERSISTENT);
  291. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE",
  292. crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(), CONST_CS | CONST_PERSISTENT);
  293. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE",
  294. crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(), CONST_CS | CONST_PERSISTENT);
  295. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE",
  296. crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(), CONST_CS | CONST_PERSISTENT);
  297. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE",
  298. crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(), CONST_CS | CONST_PERSISTENT);
  299. #endif
  300. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SCALARMULT_BYTES",
  301. crypto_scalarmult_BYTES, CONST_CS | CONST_PERSISTENT);
  302. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SCALARMULT_SCALARBYTES",
  303. crypto_scalarmult_SCALARBYTES, CONST_CS | CONST_PERSISTENT);
  304. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SHORTHASH_BYTES",
  305. crypto_shorthash_BYTES, CONST_CS | CONST_PERSISTENT);
  306. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SHORTHASH_KEYBYTES",
  307. crypto_shorthash_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  308. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETBOX_KEYBYTES",
  309. crypto_secretbox_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  310. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETBOX_MACBYTES",
  311. crypto_secretbox_MACBYTES, CONST_CS | CONST_PERSISTENT);
  312. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETBOX_NONCEBYTES",
  313. crypto_secretbox_NONCEBYTES, CONST_CS | CONST_PERSISTENT);
  314. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SIGN_BYTES",
  315. crypto_sign_BYTES, CONST_CS | CONST_PERSISTENT);
  316. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SIGN_SEEDBYTES",
  317. crypto_sign_SEEDBYTES, CONST_CS | CONST_PERSISTENT);
  318. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES",
  319. crypto_sign_PUBLICKEYBYTES, CONST_CS | CONST_PERSISTENT);
  320. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SIGN_SECRETKEYBYTES",
  321. crypto_sign_SECRETKEYBYTES, CONST_CS | CONST_PERSISTENT);
  322. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SIGN_KEYPAIRBYTES",
  323. crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES,
  324. CONST_CS | CONST_PERSISTENT);
  325. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_STREAM_NONCEBYTES",
  326. crypto_stream_NONCEBYTES, CONST_CS | CONST_PERSISTENT);
  327. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_STREAM_KEYBYTES",
  328. crypto_stream_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  329. #ifdef crypto_stream_xchacha20_KEYBYTES
  330. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES",
  331. crypto_stream_xchacha20_NONCEBYTES, CONST_CS | CONST_PERSISTENT);
  332. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES",
  333. crypto_stream_xchacha20_KEYBYTES, CONST_CS | CONST_PERSISTENT);
  334. #endif
  335. #ifdef sodium_base64_VARIANT_ORIGINAL
  336. REGISTER_LONG_CONSTANT("SODIUM_BASE64_VARIANT_ORIGINAL",
  337. sodium_base64_VARIANT_ORIGINAL, CONST_CS | CONST_PERSISTENT);
  338. REGISTER_LONG_CONSTANT("SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING",
  339. sodium_base64_VARIANT_ORIGINAL_NO_PADDING, CONST_CS | CONST_PERSISTENT);
  340. REGISTER_LONG_CONSTANT("SODIUM_BASE64_VARIANT_URLSAFE",
  341. sodium_base64_VARIANT_URLSAFE, CONST_CS | CONST_PERSISTENT);
  342. REGISTER_LONG_CONSTANT("SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING",
  343. sodium_base64_VARIANT_URLSAFE_NO_PADDING, CONST_CS | CONST_PERSISTENT);
  344. #endif
  345. #ifdef crypto_core_ristretto255_HASHBYTES
  346. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_BYTES",
  347. crypto_scalarmult_ristretto255_BYTES, CONST_CS | CONST_PERSISTENT);
  348. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES",
  349. crypto_scalarmult_ristretto255_SCALARBYTES, CONST_CS | CONST_PERSISTENT);
  350. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES",
  351. crypto_core_ristretto255_BYTES, CONST_CS | CONST_PERSISTENT);
  352. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES",
  353. crypto_core_ristretto255_HASHBYTES, CONST_CS | CONST_PERSISTENT);
  354. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES",
  355. crypto_core_ristretto255_SCALARBYTES, CONST_CS | CONST_PERSISTENT);
  356. REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES",
  357. crypto_core_ristretto255_NONREDUCEDSCALARBYTES, CONST_CS | CONST_PERSISTENT);
  358. #endif
  359. #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
  360. if (FAILURE == PHP_MINIT(sodium_password_hash)(INIT_FUNC_ARGS_PASSTHRU)) {
  361. return FAILURE;
  362. }
  363. #endif
  364. return SUCCESS;
  365. }
  366. PHP_MSHUTDOWN_FUNCTION(sodium)
  367. {
  368. randombytes_close();
  369. return SUCCESS;
  370. }
  371. PHP_MINFO_FUNCTION(sodium)
  372. {
  373. php_info_print_table_start();
  374. php_info_print_table_header(2, "sodium support", "enabled");
  375. php_info_print_table_row(2, "libsodium headers version", SODIUM_VERSION_STRING);
  376. php_info_print_table_row(2, "libsodium library version", sodium_version_string());
  377. php_info_print_table_end();
  378. }
  379. PHP_FUNCTION(sodium_memzero)
  380. {
  381. zval *buf_zv;
  382. if (zend_parse_parameters(ZEND_NUM_ARGS(),
  383. "z", &buf_zv) == FAILURE) {
  384. sodium_remove_param_values_from_backtrace(EG(exception));
  385. RETURN_THROWS();
  386. }
  387. ZVAL_DEREF(buf_zv);
  388. if (Z_TYPE_P(buf_zv) != IS_STRING) {
  389. zend_throw_exception(sodium_exception_ce, "a PHP string is required", 0);
  390. RETURN_THROWS();
  391. }
  392. if (Z_REFCOUNTED_P(buf_zv) && Z_REFCOUNT_P(buf_zv) == 1) {
  393. char *buf = Z_STRVAL(*buf_zv);
  394. size_t buf_len = Z_STRLEN(*buf_zv);
  395. if (buf_len > 0) {
  396. sodium_memzero(buf, (size_t) buf_len);
  397. }
  398. }
  399. convert_to_null(buf_zv);
  400. }
  401. PHP_FUNCTION(sodium_increment)
  402. {
  403. zval *val_zv;
  404. unsigned char *val;
  405. size_t val_len;
  406. if (zend_parse_parameters(ZEND_NUM_ARGS(),
  407. "z", &val_zv) == FAILURE) {
  408. sodium_remove_param_values_from_backtrace(EG(exception));
  409. RETURN_THROWS();
  410. }
  411. ZVAL_DEREF(val_zv);
  412. if (Z_TYPE_P(val_zv) != IS_STRING) {
  413. zend_throw_exception(sodium_exception_ce, "a PHP string is required", 0);
  414. RETURN_THROWS();
  415. }
  416. sodium_separate_string(val_zv);
  417. val = (unsigned char *) Z_STRVAL(*val_zv);
  418. val_len = Z_STRLEN(*val_zv);
  419. sodium_increment(val, val_len);
  420. }
  421. PHP_FUNCTION(sodium_add)
  422. {
  423. zval *val_zv;
  424. unsigned char *val;
  425. unsigned char *addv;
  426. size_t val_len;
  427. size_t addv_len;
  428. if (zend_parse_parameters(ZEND_NUM_ARGS(),
  429. "zs", &val_zv, &addv, &addv_len) == FAILURE) {
  430. sodium_remove_param_values_from_backtrace(EG(exception));
  431. RETURN_THROWS();
  432. }
  433. ZVAL_DEREF(val_zv);
  434. if (Z_TYPE_P(val_zv) != IS_STRING) {
  435. zend_throw_exception(sodium_exception_ce, "PHP strings are required", 0);
  436. RETURN_THROWS();
  437. }
  438. sodium_separate_string(val_zv);
  439. val = (unsigned char *) Z_STRVAL(*val_zv);
  440. val_len = Z_STRLEN(*val_zv);
  441. if (val_len != addv_len) {
  442. zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
  443. RETURN_THROWS();
  444. }
  445. sodium_add(val, addv, val_len);
  446. }
  447. PHP_FUNCTION(sodium_memcmp)
  448. {
  449. char *buf1;
  450. char *buf2;
  451. size_t len1;
  452. size_t len2;
  453. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  454. &buf1, &len1,
  455. &buf2, &len2) == FAILURE) {
  456. sodium_remove_param_values_from_backtrace(EG(exception));
  457. RETURN_THROWS();
  458. }
  459. if (len1 != len2) {
  460. zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
  461. RETURN_THROWS();
  462. }
  463. RETURN_LONG(sodium_memcmp(buf1, buf2, len1));
  464. }
  465. PHP_FUNCTION(sodium_crypto_shorthash)
  466. {
  467. zend_string *hash;
  468. unsigned char *key;
  469. unsigned char *msg;
  470. size_t key_len;
  471. size_t msg_len;
  472. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  473. &msg, &msg_len,
  474. &key, &key_len) == FAILURE) {
  475. sodium_remove_param_values_from_backtrace(EG(exception));
  476. RETURN_THROWS();
  477. }
  478. if (key_len != crypto_shorthash_KEYBYTES) {
  479. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SHORTHASH_KEYBYTES bytes long");
  480. RETURN_THROWS();
  481. }
  482. hash = zend_string_alloc(crypto_shorthash_BYTES, 0);
  483. if (crypto_shorthash((unsigned char *) ZSTR_VAL(hash), msg,
  484. (unsigned long long) msg_len, key) != 0) {
  485. zend_string_efree(hash);
  486. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  487. RETURN_THROWS();
  488. }
  489. ZSTR_VAL(hash)[crypto_shorthash_BYTES] = 0;
  490. RETURN_NEW_STR(hash);
  491. }
  492. PHP_FUNCTION(sodium_crypto_secretbox)
  493. {
  494. zend_string *ciphertext;
  495. unsigned char *key;
  496. unsigned char *msg;
  497. unsigned char *nonce;
  498. size_t key_len;
  499. size_t msg_len;
  500. size_t nonce_len;
  501. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  502. &msg, &msg_len,
  503. &nonce, &nonce_len,
  504. &key, &key_len) == FAILURE) {
  505. sodium_remove_param_values_from_backtrace(EG(exception));
  506. RETURN_THROWS();
  507. }
  508. if (nonce_len != crypto_secretbox_NONCEBYTES) {
  509. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETBOX_NONCEBYTES bytes long");
  510. RETURN_THROWS();
  511. }
  512. if (key_len != crypto_secretbox_KEYBYTES) {
  513. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long");
  514. RETURN_THROWS();
  515. }
  516. if (SIZE_MAX - msg_len <= crypto_secretbox_MACBYTES) {
  517. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  518. RETURN_THROWS();
  519. }
  520. ciphertext = zend_string_alloc((size_t) msg_len + crypto_secretbox_MACBYTES, 0);
  521. if (crypto_secretbox_easy((unsigned char *) ZSTR_VAL(ciphertext),
  522. msg, (unsigned long long) msg_len,
  523. nonce, key) != 0) {
  524. zend_string_efree(ciphertext);
  525. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  526. RETURN_THROWS();
  527. }
  528. ZSTR_VAL(ciphertext)[msg_len + crypto_secretbox_MACBYTES] = 0;
  529. RETURN_NEW_STR(ciphertext);
  530. }
  531. PHP_FUNCTION(sodium_crypto_secretbox_open)
  532. {
  533. zend_string *msg;
  534. unsigned char *key;
  535. unsigned char *ciphertext;
  536. unsigned char *nonce;
  537. size_t key_len;
  538. size_t ciphertext_len;
  539. size_t nonce_len;
  540. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  541. &ciphertext, &ciphertext_len,
  542. &nonce, &nonce_len,
  543. &key, &key_len) == FAILURE) {
  544. sodium_remove_param_values_from_backtrace(EG(exception));
  545. RETURN_THROWS();
  546. }
  547. if (nonce_len != crypto_secretbox_NONCEBYTES) {
  548. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETBOX_NONCEBYTES bytes long");
  549. RETURN_THROWS();
  550. }
  551. if (key_len != crypto_secretbox_KEYBYTES) {
  552. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long");
  553. RETURN_THROWS();
  554. }
  555. if (ciphertext_len < crypto_secretbox_MACBYTES) {
  556. RETURN_FALSE;
  557. }
  558. msg = zend_string_alloc
  559. ((size_t) ciphertext_len - crypto_secretbox_MACBYTES, 0);
  560. if (crypto_secretbox_open_easy((unsigned char *) ZSTR_VAL(msg), ciphertext,
  561. (unsigned long long) ciphertext_len,
  562. nonce, key) != 0) {
  563. zend_string_efree(msg);
  564. RETURN_FALSE;
  565. } else {
  566. ZSTR_VAL(msg)[ciphertext_len - crypto_secretbox_MACBYTES] = 0;
  567. RETURN_NEW_STR(msg);
  568. }
  569. }
  570. PHP_FUNCTION(sodium_crypto_generichash)
  571. {
  572. zend_string *hash;
  573. unsigned char *key = NULL;
  574. unsigned char *msg;
  575. zend_long hash_len = crypto_generichash_BYTES;
  576. size_t key_len = 0;
  577. size_t msg_len;
  578. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl",
  579. &msg, &msg_len,
  580. &key, &key_len,
  581. &hash_len) == FAILURE) {
  582. sodium_remove_param_values_from_backtrace(EG(exception));
  583. RETURN_THROWS();
  584. }
  585. if (hash_len < crypto_generichash_BYTES_MIN ||
  586. hash_len > crypto_generichash_BYTES_MAX) {
  587. zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
  588. RETURN_THROWS();
  589. }
  590. if (key_len != 0 &&
  591. (key_len < crypto_generichash_KEYBYTES_MIN ||
  592. key_len > crypto_generichash_KEYBYTES_MAX)) {
  593. zend_throw_exception(sodium_exception_ce, "unsupported key length", 0);
  594. RETURN_THROWS();
  595. }
  596. hash = zend_string_alloc(hash_len, 0);
  597. if (crypto_generichash((unsigned char *) ZSTR_VAL(hash), (size_t) hash_len,
  598. msg, (unsigned long long) msg_len,
  599. key, (size_t) key_len) != 0) {
  600. zend_string_efree(hash);
  601. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  602. RETURN_THROWS();
  603. }
  604. ZSTR_VAL(hash)[hash_len] = 0;
  605. RETURN_NEW_STR(hash);
  606. }
  607. PHP_FUNCTION(sodium_crypto_generichash_init)
  608. {
  609. crypto_generichash_state state_tmp;
  610. zend_string *state;
  611. unsigned char *key = NULL;
  612. size_t state_len = sizeof (crypto_generichash_state);
  613. zend_long hash_len = crypto_generichash_BYTES;
  614. size_t key_len = 0;
  615. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sl",
  616. &key, &key_len,
  617. &hash_len) == FAILURE) {
  618. sodium_remove_param_values_from_backtrace(EG(exception));
  619. RETURN_THROWS();
  620. }
  621. if (hash_len < crypto_generichash_BYTES_MIN ||
  622. hash_len > crypto_generichash_BYTES_MAX) {
  623. zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
  624. RETURN_THROWS();
  625. }
  626. if (key_len != 0 &&
  627. (key_len < crypto_generichash_KEYBYTES_MIN ||
  628. key_len > crypto_generichash_KEYBYTES_MAX)) {
  629. zend_throw_exception(sodium_exception_ce, "unsupported key length", 0);
  630. RETURN_THROWS();
  631. }
  632. memset(&state_tmp, 0, sizeof state_tmp);
  633. if (crypto_generichash_init((void *) &state_tmp, key, (size_t) key_len,
  634. (size_t) hash_len) != 0) {
  635. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  636. RETURN_THROWS();
  637. }
  638. state = zend_string_alloc(state_len, 0);
  639. memcpy(ZSTR_VAL(state), &state_tmp, state_len);
  640. sodium_memzero(&state_tmp, sizeof state_tmp);
  641. ZSTR_VAL(state)[state_len] = 0;
  642. RETURN_STR(state);
  643. }
  644. PHP_FUNCTION(sodium_crypto_generichash_update)
  645. {
  646. crypto_generichash_state state_tmp;
  647. zval *state_zv;
  648. unsigned char *msg;
  649. unsigned char *state;
  650. size_t msg_len;
  651. size_t state_len;
  652. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs",
  653. &state_zv, &msg, &msg_len) == FAILURE) {
  654. sodium_remove_param_values_from_backtrace(EG(exception));
  655. RETURN_THROWS();
  656. }
  657. ZVAL_DEREF(state_zv);
  658. if (Z_TYPE_P(state_zv) != IS_STRING) {
  659. zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
  660. RETURN_THROWS();
  661. }
  662. sodium_separate_string(state_zv);
  663. state = (unsigned char *) Z_STRVAL(*state_zv);
  664. state_len = Z_STRLEN(*state_zv);
  665. if (state_len != sizeof (crypto_generichash_state)) {
  666. zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
  667. RETURN_THROWS();
  668. }
  669. memcpy(&state_tmp, state, sizeof state_tmp);
  670. if (crypto_generichash_update((void *) &state_tmp, msg,
  671. (unsigned long long) msg_len) != 0) {
  672. sodium_memzero(&state_tmp, sizeof state_tmp);
  673. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  674. RETURN_THROWS();
  675. }
  676. memcpy(state, &state_tmp, state_len);
  677. sodium_memzero(&state_tmp, sizeof state_tmp);
  678. RETURN_TRUE;
  679. }
  680. PHP_FUNCTION(sodium_crypto_generichash_final)
  681. {
  682. crypto_generichash_state state_tmp;
  683. zend_string *hash;
  684. zval *state_zv;
  685. unsigned char *state;
  686. size_t state_len;
  687. zend_long hash_len = crypto_generichash_BYTES;
  688. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l",
  689. &state_zv, &hash_len) == FAILURE) {
  690. sodium_remove_param_values_from_backtrace(EG(exception));
  691. RETURN_THROWS();
  692. }
  693. ZVAL_DEREF(state_zv);
  694. if (Z_TYPE_P(state_zv) != IS_STRING) {
  695. zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
  696. RETURN_THROWS();
  697. }
  698. sodium_separate_string(state_zv);
  699. state = (unsigned char *) Z_STRVAL(*state_zv);
  700. state_len = Z_STRLEN(*state_zv);
  701. if (state_len != sizeof (crypto_generichash_state)) {
  702. zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
  703. RETURN_THROWS();
  704. }
  705. if (hash_len < crypto_generichash_BYTES_MIN ||
  706. hash_len > crypto_generichash_BYTES_MAX) {
  707. zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
  708. RETURN_THROWS();
  709. }
  710. hash = zend_string_alloc(hash_len, 0);
  711. memcpy(&state_tmp, state, sizeof state_tmp);
  712. if (crypto_generichash_final((void *) &state_tmp,
  713. (unsigned char *) ZSTR_VAL(hash),
  714. (size_t) hash_len) != 0) {
  715. sodium_memzero(&state_tmp, sizeof state_tmp);
  716. zend_string_efree(hash);
  717. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  718. RETURN_THROWS();
  719. }
  720. sodium_memzero(&state_tmp, sizeof state_tmp);
  721. sodium_memzero(state, state_len);
  722. convert_to_null(state_zv);
  723. ZSTR_VAL(hash)[hash_len] = 0;
  724. RETURN_NEW_STR(hash);
  725. }
  726. PHP_FUNCTION(sodium_crypto_box_keypair)
  727. {
  728. zend_string *keypair;
  729. size_t keypair_len;
  730. if (zend_parse_parameters_none() == FAILURE) {
  731. RETURN_THROWS();
  732. }
  733. keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
  734. keypair = zend_string_alloc(keypair_len, 0);
  735. if (crypto_box_keypair((unsigned char *) ZSTR_VAL(keypair) +
  736. crypto_box_SECRETKEYBYTES,
  737. (unsigned char *) ZSTR_VAL(keypair)) != 0) {
  738. zend_string_efree(keypair);
  739. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  740. RETURN_THROWS();
  741. }
  742. ZSTR_VAL(keypair)[keypair_len] = 0;
  743. RETURN_NEW_STR(keypair);
  744. }
  745. PHP_FUNCTION(sodium_crypto_box_seed_keypair)
  746. {
  747. zend_string *keypair;
  748. unsigned char *seed;
  749. size_t keypair_len;
  750. size_t seed_len;
  751. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  752. &seed, &seed_len) == FAILURE) {
  753. sodium_remove_param_values_from_backtrace(EG(exception));
  754. RETURN_THROWS();
  755. }
  756. if (seed_len != crypto_box_SEEDBYTES) {
  757. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SEEDBYTES bytes long");
  758. RETURN_THROWS();
  759. }
  760. keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
  761. keypair = zend_string_alloc(keypair_len, 0);
  762. if (crypto_box_seed_keypair((unsigned char *) ZSTR_VAL(keypair) +
  763. crypto_box_SECRETKEYBYTES,
  764. (unsigned char *) ZSTR_VAL(keypair),
  765. seed) != 0) {
  766. zend_string_efree(keypair);
  767. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  768. RETURN_THROWS();
  769. }
  770. ZSTR_VAL(keypair)[keypair_len] = 0;
  771. RETURN_NEW_STR(keypair);
  772. }
  773. PHP_FUNCTION(sodium_crypto_box_keypair_from_secretkey_and_publickey)
  774. {
  775. zend_string *keypair;
  776. char *publickey;
  777. char *secretkey;
  778. size_t keypair_len;
  779. size_t publickey_len;
  780. size_t secretkey_len;
  781. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  782. &secretkey, &secretkey_len,
  783. &publickey, &publickey_len) == FAILURE) {
  784. sodium_remove_param_values_from_backtrace(EG(exception));
  785. RETURN_THROWS();
  786. }
  787. if (secretkey_len != crypto_box_SECRETKEYBYTES) {
  788. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SECRETKEYBYTES bytes long");
  789. RETURN_THROWS();
  790. }
  791. if (publickey_len != crypto_box_PUBLICKEYBYTES) {
  792. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_PUBLICKEYBYTES bytes long");
  793. RETURN_THROWS();
  794. }
  795. keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
  796. keypair = zend_string_alloc(keypair_len, 0);
  797. memcpy(ZSTR_VAL(keypair), secretkey, crypto_box_SECRETKEYBYTES);
  798. memcpy(ZSTR_VAL(keypair) + crypto_box_SECRETKEYBYTES, publickey,
  799. crypto_box_PUBLICKEYBYTES);
  800. ZSTR_VAL(keypair)[keypair_len] = 0;
  801. RETURN_STR(keypair);
  802. }
  803. PHP_FUNCTION(sodium_crypto_box_secretkey)
  804. {
  805. zend_string *secretkey;
  806. unsigned char *keypair;
  807. size_t keypair_len;
  808. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  809. &keypair, &keypair_len) == FAILURE) {
  810. sodium_remove_param_values_from_backtrace(EG(exception));
  811. RETURN_THROWS();
  812. }
  813. if (keypair_len !=
  814. crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
  815. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
  816. RETURN_THROWS();
  817. }
  818. secretkey = zend_string_alloc(crypto_box_SECRETKEYBYTES, 0);
  819. memcpy(ZSTR_VAL(secretkey), keypair, crypto_box_SECRETKEYBYTES);
  820. ZSTR_VAL(secretkey)[crypto_box_SECRETKEYBYTES] = 0;
  821. RETURN_STR(secretkey);
  822. }
  823. PHP_FUNCTION(sodium_crypto_box_publickey)
  824. {
  825. zend_string *publickey;
  826. unsigned char *keypair;
  827. size_t keypair_len;
  828. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  829. &keypair, &keypair_len) == FAILURE) {
  830. sodium_remove_param_values_from_backtrace(EG(exception));
  831. RETURN_THROWS();
  832. }
  833. if (keypair_len !=
  834. crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
  835. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
  836. RETURN_THROWS();
  837. }
  838. publickey = zend_string_alloc(crypto_box_PUBLICKEYBYTES, 0);
  839. memcpy(ZSTR_VAL(publickey), keypair + crypto_box_SECRETKEYBYTES,
  840. crypto_box_PUBLICKEYBYTES);
  841. ZSTR_VAL(publickey)[crypto_box_PUBLICKEYBYTES] = 0;
  842. RETURN_STR(publickey);
  843. }
  844. PHP_FUNCTION(sodium_crypto_box_publickey_from_secretkey)
  845. {
  846. zend_string *publickey;
  847. unsigned char *secretkey;
  848. size_t secretkey_len;
  849. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  850. &secretkey, &secretkey_len) == FAILURE) {
  851. sodium_remove_param_values_from_backtrace(EG(exception));
  852. RETURN_THROWS();
  853. }
  854. if (secretkey_len != crypto_box_SECRETKEYBYTES) {
  855. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SECRETKEYBYTES bytes long");
  856. RETURN_THROWS();
  857. }
  858. publickey = zend_string_alloc(crypto_box_PUBLICKEYBYTES, 0);
  859. (void) sizeof(int[crypto_scalarmult_BYTES ==
  860. crypto_box_PUBLICKEYBYTES ? 1 : -1]);
  861. (void) sizeof(int[crypto_scalarmult_SCALARBYTES ==
  862. crypto_box_SECRETKEYBYTES ? 1 : -1]);
  863. crypto_scalarmult_base((unsigned char *) ZSTR_VAL(publickey), secretkey);
  864. ZSTR_VAL(publickey)[crypto_box_PUBLICKEYBYTES] = 0;
  865. RETURN_STR(publickey);
  866. }
  867. PHP_FUNCTION(sodium_crypto_box)
  868. {
  869. zend_string *ciphertext;
  870. unsigned char *keypair;
  871. unsigned char *msg;
  872. unsigned char *nonce;
  873. unsigned char *publickey;
  874. unsigned char *secretkey;
  875. size_t keypair_len;
  876. size_t msg_len;
  877. size_t nonce_len;
  878. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  879. &msg, &msg_len,
  880. &nonce, &nonce_len,
  881. &keypair, &keypair_len) == FAILURE) {
  882. sodium_remove_param_values_from_backtrace(EG(exception));
  883. RETURN_THROWS();
  884. }
  885. if (nonce_len != crypto_box_NONCEBYTES) {
  886. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_NONCEBYTES bytes long");
  887. RETURN_THROWS();
  888. }
  889. if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
  890. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
  891. RETURN_THROWS();
  892. }
  893. secretkey = keypair;
  894. publickey = keypair + crypto_box_SECRETKEYBYTES;
  895. if (SIZE_MAX - msg_len <= crypto_box_MACBYTES) {
  896. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  897. RETURN_THROWS();
  898. }
  899. ciphertext = zend_string_alloc((size_t) msg_len + crypto_box_MACBYTES, 0);
  900. if (crypto_box_easy((unsigned char *) ZSTR_VAL(ciphertext), msg,
  901. (unsigned long long) msg_len,
  902. nonce, publickey, secretkey) != 0) {
  903. zend_string_efree(ciphertext);
  904. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  905. RETURN_THROWS();
  906. }
  907. ZSTR_VAL(ciphertext)[msg_len + crypto_box_MACBYTES] = 0;
  908. RETURN_NEW_STR(ciphertext);
  909. }
  910. PHP_FUNCTION(sodium_crypto_box_open)
  911. {
  912. zend_string *msg;
  913. unsigned char *ciphertext;
  914. unsigned char *keypair;
  915. unsigned char *nonce;
  916. unsigned char *publickey;
  917. unsigned char *secretkey;
  918. size_t ciphertext_len;
  919. size_t keypair_len;
  920. size_t nonce_len;
  921. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  922. &ciphertext, &ciphertext_len,
  923. &nonce, &nonce_len,
  924. &keypair, &keypair_len) == FAILURE) {
  925. sodium_remove_param_values_from_backtrace(EG(exception));
  926. RETURN_THROWS();
  927. }
  928. if (nonce_len != crypto_box_NONCEBYTES) {
  929. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_NONCEBYTES bytes long");
  930. RETURN_THROWS();
  931. }
  932. if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
  933. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
  934. RETURN_THROWS();
  935. }
  936. secretkey = keypair;
  937. publickey = keypair + crypto_box_SECRETKEYBYTES;
  938. if (ciphertext_len < crypto_box_MACBYTES) {
  939. RETURN_FALSE;
  940. }
  941. msg = zend_string_alloc((size_t) ciphertext_len - crypto_box_MACBYTES, 0);
  942. if (crypto_box_open_easy((unsigned char *) ZSTR_VAL(msg), ciphertext,
  943. (unsigned long long) ciphertext_len,
  944. nonce, publickey, secretkey) != 0) {
  945. zend_string_efree(msg);
  946. RETURN_FALSE;
  947. } else {
  948. ZSTR_VAL(msg)[ciphertext_len - crypto_box_MACBYTES] = 0;
  949. RETURN_NEW_STR(msg);
  950. }
  951. }
  952. PHP_FUNCTION(sodium_crypto_box_seal)
  953. {
  954. zend_string *ciphertext;
  955. unsigned char *msg;
  956. unsigned char *publickey;
  957. size_t msg_len;
  958. size_t publickey_len;
  959. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  960. &msg, &msg_len,
  961. &publickey, &publickey_len) == FAILURE) {
  962. sodium_remove_param_values_from_backtrace(EG(exception));
  963. RETURN_THROWS();
  964. }
  965. if (publickey_len != crypto_box_PUBLICKEYBYTES) {
  966. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_PUBLICKEYBYTES bytes long");
  967. RETURN_THROWS();
  968. }
  969. if (SIZE_MAX - msg_len <= crypto_box_SEALBYTES) {
  970. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  971. RETURN_THROWS();
  972. }
  973. ciphertext = zend_string_alloc((size_t) msg_len + crypto_box_SEALBYTES, 0);
  974. if (crypto_box_seal((unsigned char *) ZSTR_VAL(ciphertext), msg,
  975. (unsigned long long) msg_len, publickey) != 0) {
  976. zend_string_efree(ciphertext);
  977. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  978. RETURN_THROWS();
  979. }
  980. ZSTR_VAL(ciphertext)[msg_len + crypto_box_SEALBYTES] = 0;
  981. RETURN_NEW_STR(ciphertext);
  982. }
  983. PHP_FUNCTION(sodium_crypto_box_seal_open)
  984. {
  985. zend_string *msg;
  986. unsigned char *ciphertext;
  987. unsigned char *keypair;
  988. unsigned char *publickey;
  989. unsigned char *secretkey;
  990. size_t ciphertext_len;
  991. size_t keypair_len;
  992. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  993. &ciphertext, &ciphertext_len,
  994. &keypair, &keypair_len) == FAILURE) {
  995. sodium_remove_param_values_from_backtrace(EG(exception));
  996. RETURN_THROWS();
  997. }
  998. if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
  999. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
  1000. RETURN_THROWS();
  1001. }
  1002. secretkey = keypair;
  1003. publickey = keypair + crypto_box_SECRETKEYBYTES;
  1004. if (ciphertext_len < crypto_box_SEALBYTES) {
  1005. RETURN_FALSE;
  1006. }
  1007. msg = zend_string_alloc((size_t) ciphertext_len - crypto_box_SEALBYTES, 0);
  1008. if (crypto_box_seal_open((unsigned char *) ZSTR_VAL(msg), ciphertext,
  1009. (unsigned long long) ciphertext_len,
  1010. publickey, secretkey) != 0) {
  1011. zend_string_efree(msg);
  1012. RETURN_FALSE;
  1013. } else {
  1014. ZSTR_VAL(msg)[ciphertext_len - crypto_box_SEALBYTES] = 0;
  1015. RETURN_NEW_STR(msg);
  1016. }
  1017. }
  1018. PHP_FUNCTION(sodium_crypto_sign_keypair)
  1019. {
  1020. zend_string *keypair;
  1021. size_t keypair_len;
  1022. if (zend_parse_parameters_none() == FAILURE) {
  1023. RETURN_THROWS();
  1024. }
  1025. keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
  1026. keypair = zend_string_alloc(keypair_len, 0);
  1027. if (crypto_sign_keypair((unsigned char *) ZSTR_VAL(keypair) +
  1028. crypto_sign_SECRETKEYBYTES,
  1029. (unsigned char *) ZSTR_VAL(keypair)) != 0) {
  1030. zend_string_efree(keypair);
  1031. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1032. RETURN_THROWS();
  1033. }
  1034. ZSTR_VAL(keypair)[keypair_len] = 0;
  1035. RETURN_NEW_STR(keypair);
  1036. }
  1037. PHP_FUNCTION(sodium_crypto_sign_seed_keypair)
  1038. {
  1039. zend_string *keypair;
  1040. unsigned char *seed;
  1041. size_t keypair_len;
  1042. size_t seed_len;
  1043. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  1044. &seed, &seed_len) == FAILURE) {
  1045. sodium_remove_param_values_from_backtrace(EG(exception));
  1046. RETURN_THROWS();
  1047. }
  1048. if (seed_len != crypto_sign_SEEDBYTES) {
  1049. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SEEDBYTES bytes long");
  1050. RETURN_THROWS();
  1051. }
  1052. keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
  1053. keypair = zend_string_alloc(keypair_len, 0);
  1054. if (crypto_sign_seed_keypair((unsigned char *) ZSTR_VAL(keypair) +
  1055. crypto_sign_SECRETKEYBYTES,
  1056. (unsigned char *) ZSTR_VAL(keypair),
  1057. seed) != 0) {
  1058. zend_string_efree(keypair);
  1059. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1060. RETURN_THROWS();
  1061. }
  1062. ZSTR_VAL(keypair)[keypair_len] = 0;
  1063. RETURN_NEW_STR(keypair);
  1064. }
  1065. PHP_FUNCTION(sodium_crypto_sign_keypair_from_secretkey_and_publickey)
  1066. {
  1067. zend_string *keypair;
  1068. char *publickey;
  1069. char *secretkey;
  1070. size_t keypair_len;
  1071. size_t publickey_len;
  1072. size_t secretkey_len;
  1073. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1074. &secretkey, &secretkey_len,
  1075. &publickey, &publickey_len) == FAILURE) {
  1076. sodium_remove_param_values_from_backtrace(EG(exception));
  1077. RETURN_THROWS();
  1078. }
  1079. if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
  1080. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
  1081. RETURN_THROWS();
  1082. }
  1083. if (publickey_len != crypto_sign_PUBLICKEYBYTES) {
  1084. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
  1085. RETURN_THROWS();
  1086. }
  1087. keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
  1088. keypair = zend_string_alloc(keypair_len, 0);
  1089. memcpy(ZSTR_VAL(keypair), secretkey, crypto_sign_SECRETKEYBYTES);
  1090. memcpy(ZSTR_VAL(keypair) + crypto_sign_SECRETKEYBYTES, publickey,
  1091. crypto_sign_PUBLICKEYBYTES);
  1092. ZSTR_VAL(keypair)[keypair_len] = 0;
  1093. RETURN_STR(keypair);
  1094. }
  1095. PHP_FUNCTION(sodium_crypto_sign_publickey_from_secretkey)
  1096. {
  1097. zend_string *publickey;
  1098. char *secretkey;
  1099. size_t secretkey_len;
  1100. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  1101. &secretkey, &secretkey_len) == FAILURE) {
  1102. sodium_remove_param_values_from_backtrace(EG(exception));
  1103. RETURN_THROWS();
  1104. }
  1105. if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
  1106. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
  1107. RETURN_THROWS();
  1108. }
  1109. publickey = zend_string_alloc(crypto_sign_PUBLICKEYBYTES, 0);
  1110. if (crypto_sign_ed25519_sk_to_pk((unsigned char *) ZSTR_VAL(publickey),
  1111. (const unsigned char *) secretkey) != 0) {
  1112. zend_throw_exception(sodium_exception_ce,
  1113. "internal error", 0);
  1114. RETURN_THROWS();
  1115. }
  1116. ZSTR_VAL(publickey)[crypto_sign_PUBLICKEYBYTES] = 0;
  1117. RETURN_STR(publickey);
  1118. }
  1119. PHP_FUNCTION(sodium_crypto_sign_secretkey)
  1120. {
  1121. zend_string *secretkey;
  1122. unsigned char *keypair;
  1123. size_t keypair_len;
  1124. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  1125. &keypair, &keypair_len) == FAILURE) {
  1126. sodium_remove_param_values_from_backtrace(EG(exception));
  1127. RETURN_THROWS();
  1128. }
  1129. if (keypair_len !=
  1130. crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES) {
  1131. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_KEYPAIRBYTES bytes long");
  1132. RETURN_THROWS();
  1133. }
  1134. secretkey = zend_string_alloc(crypto_sign_SECRETKEYBYTES, 0);
  1135. memcpy(ZSTR_VAL(secretkey), keypair, crypto_sign_SECRETKEYBYTES);
  1136. ZSTR_VAL(secretkey)[crypto_sign_SECRETKEYBYTES] = 0;
  1137. RETURN_STR(secretkey);
  1138. }
  1139. PHP_FUNCTION(sodium_crypto_sign_publickey)
  1140. {
  1141. zend_string *publickey;
  1142. unsigned char *keypair;
  1143. size_t keypair_len;
  1144. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  1145. &keypair, &keypair_len) == FAILURE) {
  1146. sodium_remove_param_values_from_backtrace(EG(exception));
  1147. RETURN_THROWS();
  1148. }
  1149. if (keypair_len !=
  1150. crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES) {
  1151. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_KEYPAIRBYTES bytes long");
  1152. RETURN_THROWS();
  1153. }
  1154. publickey = zend_string_alloc(crypto_sign_PUBLICKEYBYTES, 0);
  1155. memcpy(ZSTR_VAL(publickey), keypair + crypto_sign_SECRETKEYBYTES,
  1156. crypto_sign_PUBLICKEYBYTES);
  1157. ZSTR_VAL(publickey)[crypto_sign_PUBLICKEYBYTES] = 0;
  1158. RETURN_STR(publickey);
  1159. }
  1160. PHP_FUNCTION(sodium_crypto_sign)
  1161. {
  1162. zend_string *msg_signed;
  1163. unsigned char *msg;
  1164. unsigned char *secretkey;
  1165. unsigned long long msg_signed_real_len;
  1166. size_t msg_len;
  1167. size_t msg_signed_len;
  1168. size_t secretkey_len;
  1169. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1170. &msg, &msg_len,
  1171. &secretkey, &secretkey_len) == FAILURE) {
  1172. sodium_remove_param_values_from_backtrace(EG(exception));
  1173. RETURN_THROWS();
  1174. }
  1175. if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
  1176. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
  1177. RETURN_THROWS();
  1178. }
  1179. if (SIZE_MAX - msg_len <= crypto_sign_BYTES) {
  1180. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1181. RETURN_THROWS();
  1182. }
  1183. msg_signed_len = msg_len + crypto_sign_BYTES;
  1184. msg_signed = zend_string_alloc((size_t) msg_signed_len, 0);
  1185. if (crypto_sign((unsigned char *) ZSTR_VAL(msg_signed),
  1186. &msg_signed_real_len, msg,
  1187. (unsigned long long) msg_len, secretkey) != 0) {
  1188. zend_string_efree(msg_signed);
  1189. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1190. RETURN_THROWS();
  1191. }
  1192. if (msg_signed_real_len >= SIZE_MAX || msg_signed_real_len > msg_signed_len) {
  1193. zend_string_efree(msg_signed);
  1194. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1195. RETURN_THROWS();
  1196. }
  1197. PHP_SODIUM_ZSTR_TRUNCATE(msg_signed, (size_t) msg_signed_real_len);
  1198. ZSTR_VAL(msg_signed)[msg_signed_real_len] = 0;
  1199. RETURN_NEW_STR(msg_signed);
  1200. }
  1201. PHP_FUNCTION(sodium_crypto_sign_open)
  1202. {
  1203. zend_string *msg;
  1204. unsigned char *msg_signed;
  1205. unsigned char *publickey;
  1206. unsigned long long msg_real_len;
  1207. size_t msg_len;
  1208. size_t msg_signed_len;
  1209. size_t publickey_len;
  1210. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1211. &msg_signed, &msg_signed_len,
  1212. &publickey, &publickey_len) == FAILURE) {
  1213. sodium_remove_param_values_from_backtrace(EG(exception));
  1214. RETURN_THROWS();
  1215. }
  1216. if (publickey_len != crypto_sign_PUBLICKEYBYTES) {
  1217. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
  1218. RETURN_THROWS();
  1219. }
  1220. msg_len = msg_signed_len;
  1221. if (msg_len >= SIZE_MAX) {
  1222. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1223. RETURN_THROWS();
  1224. }
  1225. msg = zend_string_alloc((size_t) msg_len, 0);
  1226. if (crypto_sign_open((unsigned char *) ZSTR_VAL(msg), &msg_real_len,
  1227. msg_signed, (unsigned long long) msg_signed_len,
  1228. publickey) != 0) {
  1229. zend_string_efree(msg);
  1230. RETURN_FALSE;
  1231. }
  1232. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_signed_len) {
  1233. zend_string_efree(msg);
  1234. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1235. RETURN_THROWS();
  1236. }
  1237. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  1238. ZSTR_VAL(msg)[msg_real_len] = 0;
  1239. RETURN_NEW_STR(msg);
  1240. }
  1241. PHP_FUNCTION(sodium_crypto_sign_detached)
  1242. {
  1243. zend_string *signature;
  1244. unsigned char *msg;
  1245. unsigned char *secretkey;
  1246. unsigned long long signature_real_len;
  1247. size_t msg_len;
  1248. size_t secretkey_len;
  1249. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1250. &msg, &msg_len,
  1251. &secretkey, &secretkey_len) == FAILURE) {
  1252. sodium_remove_param_values_from_backtrace(EG(exception));
  1253. RETURN_THROWS();
  1254. }
  1255. if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
  1256. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
  1257. RETURN_THROWS();
  1258. }
  1259. signature = zend_string_alloc((size_t) crypto_sign_BYTES, 0);
  1260. memset(ZSTR_VAL(signature), 0, (size_t) crypto_sign_BYTES);
  1261. if (crypto_sign_detached((unsigned char *) ZSTR_VAL(signature),
  1262. &signature_real_len, msg,
  1263. (unsigned long long) msg_len, secretkey) != 0) {
  1264. zend_string_efree(signature);
  1265. zend_throw_exception(sodium_exception_ce, "signature creation failed", 0);
  1266. RETURN_THROWS();
  1267. }
  1268. if (signature_real_len <= 0U || signature_real_len > crypto_sign_BYTES) {
  1269. zend_string_efree(signature);
  1270. zend_throw_exception(sodium_exception_ce, "signature has a bogus size", 0);
  1271. RETURN_THROWS();
  1272. }
  1273. PHP_SODIUM_ZSTR_TRUNCATE(signature, (size_t) signature_real_len);
  1274. ZSTR_VAL(signature)[signature_real_len] = 0;
  1275. RETURN_NEW_STR(signature);
  1276. }
  1277. PHP_FUNCTION(sodium_crypto_sign_verify_detached)
  1278. {
  1279. unsigned char *msg;
  1280. unsigned char *publickey;
  1281. unsigned char *signature;
  1282. size_t msg_len;
  1283. size_t publickey_len;
  1284. size_t signature_len;
  1285. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  1286. &signature, &signature_len,
  1287. &msg, &msg_len,
  1288. &publickey, &publickey_len) == FAILURE) {
  1289. sodium_remove_param_values_from_backtrace(EG(exception));
  1290. RETURN_THROWS();
  1291. }
  1292. if (signature_len != crypto_sign_BYTES) {
  1293. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_BYTES bytes long");
  1294. RETURN_THROWS();
  1295. }
  1296. if (publickey_len != crypto_sign_PUBLICKEYBYTES) {
  1297. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
  1298. RETURN_THROWS();
  1299. }
  1300. if (crypto_sign_verify_detached(signature,
  1301. msg, (unsigned long long) msg_len,
  1302. publickey) != 0) {
  1303. RETURN_FALSE;
  1304. }
  1305. RETURN_TRUE;
  1306. }
  1307. PHP_FUNCTION(sodium_crypto_stream)
  1308. {
  1309. zend_string *ciphertext;
  1310. unsigned char *key;
  1311. unsigned char *nonce;
  1312. zend_long ciphertext_len;
  1313. size_t key_len;
  1314. size_t nonce_len;
  1315. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lss",
  1316. &ciphertext_len,
  1317. &nonce, &nonce_len,
  1318. &key, &key_len) == FAILURE) {
  1319. sodium_remove_param_values_from_backtrace(EG(exception));
  1320. RETURN_THROWS();
  1321. }
  1322. if (ciphertext_len <= 0 || ciphertext_len >= SIZE_MAX) {
  1323. zend_argument_error(sodium_exception_ce, 1, "must be greater than 0");
  1324. RETURN_THROWS();
  1325. }
  1326. if (nonce_len != crypto_stream_NONCEBYTES) {
  1327. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_STREAM_NONCEBYTES bytes long");
  1328. RETURN_THROWS();
  1329. }
  1330. if (key_len != crypto_stream_KEYBYTES) {
  1331. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_STREAM_KEYBYTES bytes long");
  1332. RETURN_THROWS();
  1333. }
  1334. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  1335. if (crypto_stream((unsigned char *) ZSTR_VAL(ciphertext),
  1336. (unsigned long long) ciphertext_len, nonce, key) != 0) {
  1337. zend_string_efree(ciphertext);
  1338. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1339. RETURN_THROWS();
  1340. }
  1341. ZSTR_VAL(ciphertext)[ciphertext_len] = 0;
  1342. RETURN_NEW_STR(ciphertext);
  1343. }
  1344. PHP_FUNCTION(sodium_crypto_stream_xor)
  1345. {
  1346. zend_string *ciphertext;
  1347. unsigned char *key;
  1348. unsigned char *msg;
  1349. unsigned char *nonce;
  1350. size_t ciphertext_len;
  1351. size_t key_len;
  1352. size_t msg_len;
  1353. size_t nonce_len;
  1354. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  1355. &msg, &msg_len,
  1356. &nonce, &nonce_len,
  1357. &key, &key_len) == FAILURE) {
  1358. sodium_remove_param_values_from_backtrace(EG(exception));
  1359. RETURN_THROWS();
  1360. }
  1361. if (nonce_len != crypto_stream_NONCEBYTES) {
  1362. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_STREAM_NONCEBYTES bytes long");
  1363. RETURN_THROWS();
  1364. }
  1365. if (key_len != crypto_stream_KEYBYTES) {
  1366. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_STREAM_KEYBYTES bytes long");
  1367. RETURN_THROWS();
  1368. }
  1369. ciphertext_len = msg_len;
  1370. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  1371. if (crypto_stream_xor((unsigned char *) ZSTR_VAL(ciphertext), msg,
  1372. (unsigned long long) msg_len, nonce, key) != 0) {
  1373. zend_string_efree(ciphertext);
  1374. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1375. RETURN_THROWS();
  1376. }
  1377. ZSTR_VAL(ciphertext)[ciphertext_len] = 0;
  1378. RETURN_NEW_STR(ciphertext);
  1379. }
  1380. #ifdef crypto_stream_xchacha20_KEYBYTES
  1381. PHP_FUNCTION(sodium_crypto_stream_xchacha20)
  1382. {
  1383. zend_string *ciphertext;
  1384. unsigned char *key;
  1385. unsigned char *nonce;
  1386. zend_long ciphertext_len;
  1387. size_t key_len;
  1388. size_t nonce_len;
  1389. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lss",
  1390. &ciphertext_len,
  1391. &nonce, &nonce_len,
  1392. &key, &key_len) == FAILURE) {
  1393. sodium_remove_param_values_from_backtrace(EG(exception));
  1394. RETURN_THROWS();
  1395. }
  1396. if (ciphertext_len <= 0 || ciphertext_len >= SIZE_MAX) {
  1397. zend_argument_error(sodium_exception_ce, 1, "must be greater than 0");
  1398. RETURN_THROWS();
  1399. }
  1400. if (nonce_len != crypto_stream_xchacha20_NONCEBYTES) {
  1401. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES bytes long");
  1402. RETURN_THROWS();
  1403. }
  1404. if (key_len != crypto_stream_xchacha20_KEYBYTES) {
  1405. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES bytes long");
  1406. RETURN_THROWS();
  1407. }
  1408. ciphertext = zend_string_checked_alloc((size_t) ciphertext_len, 0);
  1409. if (crypto_stream_xchacha20((unsigned char *) ZSTR_VAL(ciphertext),
  1410. (unsigned long long) ciphertext_len, nonce, key) != 0) {
  1411. zend_string_free(ciphertext);
  1412. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1413. RETURN_THROWS();
  1414. }
  1415. ZSTR_VAL(ciphertext)[ciphertext_len] = 0;
  1416. RETURN_NEW_STR(ciphertext);
  1417. }
  1418. PHP_FUNCTION(sodium_crypto_stream_xchacha20_xor)
  1419. {
  1420. zend_string *ciphertext;
  1421. unsigned char *key;
  1422. unsigned char *msg;
  1423. unsigned char *nonce;
  1424. size_t ciphertext_len;
  1425. size_t key_len;
  1426. size_t msg_len;
  1427. size_t nonce_len;
  1428. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  1429. &msg, &msg_len,
  1430. &nonce, &nonce_len,
  1431. &key, &key_len) == FAILURE) {
  1432. sodium_remove_param_values_from_backtrace(EG(exception));
  1433. RETURN_THROWS();
  1434. }
  1435. if (nonce_len != crypto_stream_xchacha20_NONCEBYTES) {
  1436. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES bytes long");
  1437. RETURN_THROWS();
  1438. }
  1439. if (key_len != crypto_stream_xchacha20_KEYBYTES) {
  1440. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES bytes long");
  1441. RETURN_THROWS();
  1442. }
  1443. ciphertext_len = msg_len;
  1444. ciphertext = zend_string_checked_alloc((size_t) ciphertext_len, 0);
  1445. if (crypto_stream_xchacha20_xor((unsigned char *) ZSTR_VAL(ciphertext), msg,
  1446. (unsigned long long) msg_len, nonce, key) != 0) {
  1447. zend_string_free(ciphertext);
  1448. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1449. RETURN_THROWS();
  1450. }
  1451. ZSTR_VAL(ciphertext)[ciphertext_len] = 0;
  1452. RETURN_NEW_STR(ciphertext);
  1453. }
  1454. #endif
  1455. #ifdef crypto_pwhash_SALTBYTES
  1456. PHP_FUNCTION(sodium_crypto_pwhash)
  1457. {
  1458. zend_string *hash;
  1459. unsigned char *salt;
  1460. char *passwd;
  1461. zend_long hash_len;
  1462. zend_long memlimit;
  1463. zend_long opslimit;
  1464. zend_long alg;
  1465. size_t passwd_len;
  1466. size_t salt_len;
  1467. int ret;
  1468. alg = (zend_long) crypto_pwhash_ALG_DEFAULT;
  1469. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lssll|l",
  1470. &hash_len,
  1471. &passwd, &passwd_len,
  1472. &salt, &salt_len,
  1473. &opslimit, &memlimit, &alg) == FAILURE) {
  1474. sodium_remove_param_values_from_backtrace(EG(exception));
  1475. RETURN_THROWS();
  1476. }
  1477. if (hash_len <= 0) {
  1478. zend_argument_error(sodium_exception_ce, 1, "must be greater than 0");
  1479. RETURN_THROWS();
  1480. }
  1481. if (hash_len >= 0xffffffff) {
  1482. zend_argument_error(sodium_exception_ce, 1, "is too large");
  1483. RETURN_THROWS();
  1484. }
  1485. if (passwd_len >= 0xffffffff) {
  1486. zend_argument_error(sodium_exception_ce, 2, "is too long");
  1487. RETURN_THROWS();
  1488. }
  1489. if (opslimit <= 0) {
  1490. zend_argument_error(sodium_exception_ce, 4, "must be greater than 0");
  1491. RETURN_THROWS();
  1492. }
  1493. if (memlimit <= 0 || memlimit > SIZE_MAX) {
  1494. zend_argument_error(sodium_exception_ce, 5, "must be greater than 0");
  1495. RETURN_THROWS();
  1496. }
  1497. if (alg != crypto_pwhash_ALG_ARGON2I13
  1498. # ifdef crypto_pwhash_ALG_ARGON2ID13
  1499. && alg != crypto_pwhash_ALG_ARGON2ID13
  1500. # endif
  1501. && alg != crypto_pwhash_ALG_DEFAULT) {
  1502. zend_throw_exception(sodium_exception_ce, "unsupported password hashing algorithm", 0);
  1503. RETURN_THROWS();
  1504. }
  1505. if (passwd_len <= 0) {
  1506. zend_error(E_WARNING, "empty password");
  1507. }
  1508. if (salt_len != crypto_pwhash_SALTBYTES) {
  1509. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_PWHASH_SALTBYTES bytes long");
  1510. RETURN_THROWS();
  1511. }
  1512. if (opslimit < crypto_pwhash_OPSLIMIT_MIN) {
  1513. zend_argument_error(sodium_exception_ce, 4, "must be greater than or equal to %d", crypto_pwhash_OPSLIMIT_MIN);
  1514. RETURN_THROWS();
  1515. }
  1516. if (memlimit < crypto_pwhash_MEMLIMIT_MIN) {
  1517. zend_argument_error(sodium_exception_ce, 5, "must be greater than or equal to %d", crypto_pwhash_MEMLIMIT_MIN);
  1518. }
  1519. hash = zend_string_alloc((size_t) hash_len, 0);
  1520. ret = -1;
  1521. # ifdef crypto_pwhash_ALG_ARGON2ID13
  1522. if (alg == crypto_pwhash_ALG_ARGON2ID13) {
  1523. ret = crypto_pwhash_argon2id
  1524. ((unsigned char *) ZSTR_VAL(hash), (unsigned long long) hash_len,
  1525. passwd, (unsigned long long) passwd_len, salt,
  1526. (unsigned long long) opslimit, (size_t) memlimit, (int) alg);
  1527. }
  1528. # endif
  1529. if (ret == -1) {
  1530. ret = crypto_pwhash
  1531. ((unsigned char *) ZSTR_VAL(hash), (unsigned long long) hash_len,
  1532. passwd, (unsigned long long) passwd_len, salt,
  1533. (unsigned long long) opslimit, (size_t) memlimit, (int) alg);
  1534. }
  1535. if (ret != 0) {
  1536. zend_string_efree(hash);
  1537. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1538. RETURN_THROWS();
  1539. }
  1540. ZSTR_VAL(hash)[hash_len] = 0;
  1541. RETURN_NEW_STR(hash);
  1542. }
  1543. PHP_FUNCTION(sodium_crypto_pwhash_str)
  1544. {
  1545. zend_string *hash_str;
  1546. char *passwd;
  1547. zend_long memlimit;
  1548. zend_long opslimit;
  1549. size_t passwd_len;
  1550. size_t len;
  1551. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll",
  1552. &passwd, &passwd_len,
  1553. &opslimit, &memlimit) == FAILURE) {
  1554. sodium_remove_param_values_from_backtrace(EG(exception));
  1555. RETURN_THROWS();
  1556. }
  1557. if (opslimit <= 0) {
  1558. zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
  1559. RETURN_THROWS();
  1560. }
  1561. if (memlimit <= 0 || memlimit > SIZE_MAX) {
  1562. zend_argument_error(sodium_exception_ce, 3, "must be greater than 0");
  1563. RETURN_THROWS();
  1564. }
  1565. if (passwd_len >= 0xffffffff) {
  1566. zend_argument_error(sodium_exception_ce, 1, "is too long");
  1567. RETURN_THROWS();
  1568. }
  1569. if (passwd_len <= 0) {
  1570. zend_error(E_WARNING, "empty password");
  1571. }
  1572. if (opslimit < crypto_pwhash_OPSLIMIT_MIN) {
  1573. zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to %d", crypto_pwhash_OPSLIMIT_MIN);
  1574. }
  1575. if (memlimit < crypto_pwhash_MEMLIMIT_MIN) {
  1576. zend_argument_error(sodium_exception_ce, 3, "must be greater than or equal to %d", crypto_pwhash_MEMLIMIT_MIN);
  1577. }
  1578. hash_str = zend_string_alloc(crypto_pwhash_STRBYTES - 1, 0);
  1579. if (crypto_pwhash_str
  1580. (ZSTR_VAL(hash_str), passwd, (unsigned long long) passwd_len,
  1581. (unsigned long long) opslimit, (size_t) memlimit) != 0) {
  1582. zend_string_efree(hash_str);
  1583. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1584. RETURN_THROWS();
  1585. }
  1586. ZSTR_VAL(hash_str)[crypto_pwhash_STRBYTES - 1] = 0;
  1587. len = strlen(ZSTR_VAL(hash_str));
  1588. PHP_SODIUM_ZSTR_TRUNCATE(hash_str, len);
  1589. RETURN_NEW_STR(hash_str);
  1590. }
  1591. #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
  1592. PHP_FUNCTION(sodium_crypto_pwhash_str_needs_rehash)
  1593. {
  1594. char *hash_str;
  1595. zend_long memlimit;
  1596. zend_long opslimit;
  1597. size_t hash_str_len;
  1598. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll",
  1599. &hash_str, &hash_str_len, &opslimit, &memlimit) == FAILURE) {
  1600. RETURN_THROWS();
  1601. }
  1602. if (crypto_pwhash_str_needs_rehash(hash_str, opslimit, memlimit) == 0) {
  1603. RETURN_FALSE;
  1604. }
  1605. RETURN_TRUE;
  1606. }
  1607. #endif
  1608. PHP_FUNCTION(sodium_crypto_pwhash_str_verify)
  1609. {
  1610. char *hash_str;
  1611. char *passwd;
  1612. size_t hash_str_len;
  1613. size_t passwd_len;
  1614. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1615. &hash_str, &hash_str_len,
  1616. &passwd, &passwd_len) == FAILURE) {
  1617. sodium_remove_param_values_from_backtrace(EG(exception));
  1618. RETURN_THROWS();
  1619. }
  1620. if (passwd_len >= 0xffffffff) {
  1621. zend_argument_error(sodium_exception_ce, 2, "is too long");
  1622. RETURN_THROWS();
  1623. }
  1624. if (passwd_len <= 0) {
  1625. zend_error(E_WARNING, "empty password");
  1626. }
  1627. if (crypto_pwhash_str_verify
  1628. (hash_str, passwd, (unsigned long long) passwd_len) == 0) {
  1629. RETURN_TRUE;
  1630. }
  1631. RETURN_FALSE;
  1632. }
  1633. #endif
  1634. #ifdef crypto_pwhash_scryptsalsa208sha256_SALTBYTES
  1635. PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256)
  1636. {
  1637. zend_string *hash;
  1638. unsigned char *salt;
  1639. char *passwd;
  1640. zend_long hash_len;
  1641. zend_long memlimit;
  1642. zend_long opslimit;
  1643. size_t passwd_len;
  1644. size_t salt_len;
  1645. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lssll",
  1646. &hash_len,
  1647. &passwd, &passwd_len,
  1648. &salt, &salt_len,
  1649. &opslimit, &memlimit) == FAILURE) {
  1650. sodium_remove_param_values_from_backtrace(EG(exception));
  1651. RETURN_THROWS();
  1652. }
  1653. if (hash_len <= 0 || hash_len >= SIZE_MAX || hash_len > 0x1fffffffe0ULL) {
  1654. zend_argument_error(sodium_exception_ce, 1, "must be greater than 0");
  1655. RETURN_THROWS();
  1656. }
  1657. if (opslimit <= 0) {
  1658. zend_argument_error(sodium_exception_ce, 4, "must be greater than 0");
  1659. RETURN_THROWS();
  1660. }
  1661. if (memlimit <= 0 || memlimit > SIZE_MAX) {
  1662. zend_argument_error(sodium_exception_ce, 5, "must be greater than 0");
  1663. RETURN_THROWS();
  1664. }
  1665. if (passwd_len <= 0) {
  1666. zend_error(E_WARNING, "empty password");
  1667. }
  1668. if (salt_len != crypto_pwhash_scryptsalsa208sha256_SALTBYTES) {
  1669. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES bytes long");
  1670. RETURN_THROWS();
  1671. }
  1672. if (opslimit < crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE) {
  1673. zend_argument_error(sodium_exception_ce, 4, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
  1674. }
  1675. if (memlimit < crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) {
  1676. zend_argument_error(sodium_exception_ce, 5, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
  1677. }
  1678. hash = zend_string_alloc((size_t) hash_len, 0);
  1679. if (crypto_pwhash_scryptsalsa208sha256
  1680. ((unsigned char *) ZSTR_VAL(hash), (unsigned long long) hash_len,
  1681. passwd, (unsigned long long) passwd_len, salt,
  1682. (unsigned long long) opslimit, (size_t) memlimit) != 0) {
  1683. zend_string_efree(hash);
  1684. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1685. RETURN_THROWS();
  1686. }
  1687. ZSTR_VAL(hash)[hash_len] = 0;
  1688. RETURN_NEW_STR(hash);
  1689. }
  1690. PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256_str)
  1691. {
  1692. zend_string *hash_str;
  1693. char *passwd;
  1694. zend_long memlimit;
  1695. zend_long opslimit;
  1696. size_t passwd_len;
  1697. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll",
  1698. &passwd, &passwd_len,
  1699. &opslimit, &memlimit) == FAILURE) {
  1700. sodium_remove_param_values_from_backtrace(EG(exception));
  1701. RETURN_THROWS();
  1702. }
  1703. if (opslimit <= 0) {
  1704. zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
  1705. RETURN_THROWS();
  1706. }
  1707. if (memlimit <= 0 || memlimit > SIZE_MAX) {
  1708. zend_argument_error(sodium_exception_ce, 3, "must be greater than 0");
  1709. RETURN_THROWS();
  1710. }
  1711. if (passwd_len <= 0) {
  1712. zend_error(E_WARNING, "empty password");
  1713. }
  1714. if (opslimit < crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE) {
  1715. zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
  1716. }
  1717. if (memlimit < crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) {
  1718. zend_argument_error(sodium_exception_ce, 3, "must be greater than or equal to %d", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
  1719. }
  1720. hash_str = zend_string_alloc
  1721. (crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1, 0);
  1722. if (crypto_pwhash_scryptsalsa208sha256_str
  1723. (ZSTR_VAL(hash_str), passwd, (unsigned long long) passwd_len,
  1724. (unsigned long long) opslimit, (size_t) memlimit) != 0) {
  1725. zend_string_efree(hash_str);
  1726. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1727. RETURN_THROWS();
  1728. }
  1729. ZSTR_VAL(hash_str)[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1] = 0;
  1730. RETURN_NEW_STR(hash_str);
  1731. }
  1732. PHP_FUNCTION(sodium_crypto_pwhash_scryptsalsa208sha256_str_verify)
  1733. {
  1734. char *hash_str;
  1735. char *passwd;
  1736. size_t hash_str_len;
  1737. size_t passwd_len;
  1738. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1739. &hash_str, &hash_str_len,
  1740. &passwd, &passwd_len) == FAILURE) {
  1741. sodium_remove_param_values_from_backtrace(EG(exception));
  1742. RETURN_THROWS();
  1743. }
  1744. if (passwd_len <= 0) {
  1745. zend_error(E_WARNING, "empty password");
  1746. }
  1747. if (hash_str_len != crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1) {
  1748. zend_error(E_WARNING, "wrong size for the hashed password");
  1749. RETURN_FALSE;
  1750. }
  1751. if (crypto_pwhash_scryptsalsa208sha256_str_verify
  1752. (hash_str, passwd, (unsigned long long) passwd_len) == 0) {
  1753. RETURN_TRUE;
  1754. }
  1755. RETURN_FALSE;
  1756. }
  1757. #endif
  1758. PHP_FUNCTION(sodium_crypto_aead_aes256gcm_is_available)
  1759. {
  1760. if (zend_parse_parameters_none() == FAILURE) {
  1761. RETURN_THROWS();
  1762. }
  1763. #ifdef HAVE_AESGCM
  1764. RETURN_BOOL(crypto_aead_aes256gcm_is_available());
  1765. #else
  1766. RETURN_FALSE;
  1767. #endif
  1768. }
  1769. #ifdef HAVE_AESGCM
  1770. PHP_FUNCTION(sodium_crypto_aead_aes256gcm_encrypt)
  1771. {
  1772. zend_string *ciphertext;
  1773. unsigned char *ad;
  1774. unsigned char *msg;
  1775. unsigned char *npub;
  1776. unsigned char *secretkey;
  1777. unsigned long long ciphertext_real_len;
  1778. size_t ad_len;
  1779. size_t ciphertext_len;
  1780. size_t msg_len;
  1781. size_t npub_len;
  1782. size_t secretkey_len;
  1783. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  1784. &msg, &msg_len,
  1785. &ad, &ad_len,
  1786. &npub, &npub_len,
  1787. &secretkey, &secretkey_len) == FAILURE) {
  1788. sodium_remove_param_values_from_backtrace(EG(exception));
  1789. RETURN_THROWS();
  1790. }
  1791. if (npub_len != crypto_aead_aes256gcm_NPUBBYTES) {
  1792. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES bytes long");
  1793. RETURN_THROWS();
  1794. }
  1795. if (secretkey_len != crypto_aead_aes256gcm_KEYBYTES) {
  1796. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES bytes long");
  1797. RETURN_THROWS();
  1798. }
  1799. if (SIZE_MAX - msg_len <= crypto_aead_aes256gcm_ABYTES) {
  1800. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1801. RETURN_THROWS();
  1802. }
  1803. if ((unsigned long long) msg_len > (16ULL * ((1ULL << 32) - 2ULL)) - crypto_aead_aes256gcm_ABYTES) {
  1804. zend_throw_exception(sodium_exception_ce, "message too long for a single key", 0);
  1805. RETURN_THROWS();
  1806. }
  1807. ciphertext_len = msg_len + crypto_aead_aes256gcm_ABYTES;
  1808. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  1809. if (crypto_aead_aes256gcm_encrypt
  1810. ((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
  1811. (unsigned long long) msg_len,
  1812. ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
  1813. zend_string_efree(ciphertext);
  1814. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1815. RETURN_THROWS();
  1816. }
  1817. if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
  1818. ciphertext_real_len > ciphertext_len) {
  1819. zend_string_efree(ciphertext);
  1820. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1821. RETURN_THROWS();
  1822. }
  1823. PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
  1824. ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
  1825. RETURN_NEW_STR(ciphertext);
  1826. }
  1827. PHP_FUNCTION(sodium_crypto_aead_aes256gcm_decrypt)
  1828. {
  1829. zend_string *msg;
  1830. unsigned char *ad;
  1831. unsigned char *ciphertext;
  1832. unsigned char *npub;
  1833. unsigned char *secretkey;
  1834. unsigned long long msg_real_len;
  1835. size_t ad_len;
  1836. size_t ciphertext_len;
  1837. size_t msg_len;
  1838. size_t npub_len;
  1839. size_t secretkey_len;
  1840. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  1841. &ciphertext, &ciphertext_len,
  1842. &ad, &ad_len,
  1843. &npub, &npub_len,
  1844. &secretkey, &secretkey_len) == FAILURE) {
  1845. sodium_remove_param_values_from_backtrace(EG(exception));
  1846. RETURN_THROWS();
  1847. }
  1848. if (npub_len != crypto_aead_aes256gcm_NPUBBYTES) {
  1849. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES bytes long");
  1850. RETURN_THROWS();
  1851. }
  1852. if (secretkey_len != crypto_aead_aes256gcm_KEYBYTES) {
  1853. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES bytes long");
  1854. RETURN_THROWS();
  1855. }
  1856. if (ciphertext_len < crypto_aead_aes256gcm_ABYTES) {
  1857. RETURN_FALSE;
  1858. }
  1859. if (ciphertext_len - crypto_aead_aes256gcm_ABYTES > 16ULL * ((1ULL << 32) - 2ULL)) {
  1860. zend_argument_error(sodium_exception_ce, 1, "is too long");
  1861. RETURN_THROWS();
  1862. }
  1863. msg_len = ciphertext_len;
  1864. if (msg_len >= SIZE_MAX) {
  1865. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1866. RETURN_THROWS();
  1867. }
  1868. msg = zend_string_alloc((size_t) msg_len, 0);
  1869. if (crypto_aead_aes256gcm_decrypt
  1870. ((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
  1871. ciphertext, (unsigned long long) ciphertext_len,
  1872. ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
  1873. zend_string_efree(msg);
  1874. RETURN_FALSE;
  1875. }
  1876. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
  1877. zend_string_efree(msg);
  1878. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1879. RETURN_THROWS();
  1880. }
  1881. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  1882. ZSTR_VAL(msg)[msg_real_len] = 0;
  1883. RETURN_NEW_STR(msg);
  1884. }
  1885. #endif
  1886. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt)
  1887. {
  1888. zend_string *ciphertext;
  1889. unsigned char *ad;
  1890. unsigned char *msg;
  1891. unsigned char *npub;
  1892. unsigned char *secretkey;
  1893. unsigned long long ciphertext_real_len;
  1894. size_t ad_len;
  1895. size_t ciphertext_len;
  1896. size_t msg_len;
  1897. size_t npub_len;
  1898. size_t secretkey_len;
  1899. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  1900. &msg, &msg_len,
  1901. &ad, &ad_len,
  1902. &npub, &npub_len,
  1903. &secretkey, &secretkey_len) == FAILURE) {
  1904. sodium_remove_param_values_from_backtrace(EG(exception));
  1905. RETURN_THROWS();
  1906. }
  1907. if (npub_len != crypto_aead_chacha20poly1305_NPUBBYTES) {
  1908. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES bytes long");
  1909. RETURN_THROWS();
  1910. }
  1911. if (secretkey_len != crypto_aead_chacha20poly1305_KEYBYTES) {
  1912. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES bytes long");
  1913. RETURN_THROWS();
  1914. }
  1915. if (SIZE_MAX - msg_len <= crypto_aead_chacha20poly1305_ABYTES) {
  1916. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1917. RETURN_THROWS();
  1918. }
  1919. ciphertext_len = msg_len + crypto_aead_chacha20poly1305_ABYTES;
  1920. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  1921. if (crypto_aead_chacha20poly1305_encrypt
  1922. ((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
  1923. (unsigned long long) msg_len,
  1924. ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
  1925. zend_string_efree(ciphertext);
  1926. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  1927. RETURN_THROWS();
  1928. }
  1929. if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
  1930. ciphertext_real_len > ciphertext_len) {
  1931. zend_string_efree(ciphertext);
  1932. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1933. RETURN_THROWS();
  1934. }
  1935. PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
  1936. ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
  1937. RETURN_NEW_STR(ciphertext);
  1938. }
  1939. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_decrypt)
  1940. {
  1941. zend_string *msg;
  1942. unsigned char *ad;
  1943. unsigned char *ciphertext;
  1944. unsigned char *npub;
  1945. unsigned char *secretkey;
  1946. unsigned long long msg_real_len;
  1947. size_t ad_len;
  1948. size_t ciphertext_len;
  1949. size_t msg_len;
  1950. size_t npub_len;
  1951. size_t secretkey_len;
  1952. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  1953. &ciphertext, &ciphertext_len,
  1954. &ad, &ad_len,
  1955. &npub, &npub_len,
  1956. &secretkey, &secretkey_len) == FAILURE) {
  1957. sodium_remove_param_values_from_backtrace(EG(exception));
  1958. RETURN_THROWS();
  1959. }
  1960. if (npub_len != crypto_aead_chacha20poly1305_NPUBBYTES) {
  1961. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES bytes long");
  1962. RETURN_THROWS();
  1963. }
  1964. if (secretkey_len != crypto_aead_chacha20poly1305_KEYBYTES) {
  1965. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES bytes long");
  1966. RETURN_THROWS();
  1967. }
  1968. if (ciphertext_len < crypto_aead_chacha20poly1305_ABYTES) {
  1969. RETURN_FALSE;
  1970. }
  1971. msg_len = ciphertext_len;
  1972. if (msg_len >= SIZE_MAX) {
  1973. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1974. RETURN_THROWS();
  1975. }
  1976. msg = zend_string_alloc((size_t) msg_len, 0);
  1977. if (crypto_aead_chacha20poly1305_decrypt
  1978. ((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
  1979. ciphertext, (unsigned long long) ciphertext_len,
  1980. ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
  1981. zend_string_efree(msg);
  1982. RETURN_FALSE;
  1983. }
  1984. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
  1985. zend_string_efree(msg);
  1986. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  1987. RETURN_THROWS();
  1988. }
  1989. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  1990. ZSTR_VAL(msg)[msg_real_len] = 0;
  1991. RETURN_NEW_STR(msg);
  1992. }
  1993. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_encrypt)
  1994. {
  1995. zend_string *ciphertext;
  1996. unsigned char *ad;
  1997. unsigned char *msg;
  1998. unsigned char *npub;
  1999. unsigned char *secretkey;
  2000. unsigned long long ciphertext_real_len;
  2001. size_t ad_len;
  2002. size_t ciphertext_len;
  2003. size_t msg_len;
  2004. size_t npub_len;
  2005. size_t secretkey_len;
  2006. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  2007. &msg, &msg_len,
  2008. &ad, &ad_len,
  2009. &npub, &npub_len,
  2010. &secretkey, &secretkey_len) == FAILURE) {
  2011. sodium_remove_param_values_from_backtrace(EG(exception));
  2012. RETURN_THROWS();
  2013. }
  2014. if (npub_len != crypto_aead_chacha20poly1305_IETF_NPUBBYTES) {
  2015. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES bytes long");
  2016. RETURN_THROWS();
  2017. }
  2018. if (secretkey_len != crypto_aead_chacha20poly1305_IETF_KEYBYTES) {
  2019. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES bytes long");
  2020. RETURN_THROWS();
  2021. }
  2022. if (SIZE_MAX - msg_len <= crypto_aead_chacha20poly1305_IETF_ABYTES) {
  2023. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2024. RETURN_THROWS();
  2025. }
  2026. if ((unsigned long long) msg_len > 64ULL * (1ULL << 32) - 64ULL) {
  2027. zend_throw_exception(sodium_exception_ce, "message too long for a single key", 0);
  2028. RETURN_THROWS();
  2029. }
  2030. ciphertext_len = msg_len + crypto_aead_chacha20poly1305_IETF_ABYTES;
  2031. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  2032. if (crypto_aead_chacha20poly1305_ietf_encrypt
  2033. ((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
  2034. (unsigned long long) msg_len,
  2035. ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
  2036. zend_string_efree(ciphertext);
  2037. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2038. RETURN_THROWS();
  2039. }
  2040. if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
  2041. ciphertext_real_len > ciphertext_len) {
  2042. zend_string_efree(ciphertext);
  2043. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2044. RETURN_THROWS();
  2045. }
  2046. PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
  2047. ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
  2048. RETURN_NEW_STR(ciphertext);
  2049. }
  2050. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_decrypt)
  2051. {
  2052. zend_string *msg;
  2053. unsigned char *ad;
  2054. unsigned char *ciphertext;
  2055. unsigned char *npub;
  2056. unsigned char *secretkey;
  2057. unsigned long long msg_real_len;
  2058. size_t ad_len;
  2059. size_t ciphertext_len;
  2060. size_t msg_len;
  2061. size_t npub_len;
  2062. size_t secretkey_len;
  2063. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  2064. &ciphertext, &ciphertext_len,
  2065. &ad, &ad_len,
  2066. &npub, &npub_len,
  2067. &secretkey, &secretkey_len) == FAILURE) {
  2068. sodium_remove_param_values_from_backtrace(EG(exception));
  2069. RETURN_THROWS();
  2070. }
  2071. if (npub_len != crypto_aead_chacha20poly1305_IETF_NPUBBYTES) {
  2072. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES bytes long");
  2073. RETURN_THROWS();
  2074. }
  2075. if (secretkey_len != crypto_aead_chacha20poly1305_IETF_KEYBYTES) {
  2076. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES bytes long");
  2077. RETURN_THROWS();
  2078. }
  2079. msg_len = ciphertext_len;
  2080. if (msg_len >= SIZE_MAX) {
  2081. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2082. RETURN_THROWS();
  2083. }
  2084. if (ciphertext_len < crypto_aead_chacha20poly1305_IETF_ABYTES) {
  2085. RETURN_FALSE;
  2086. }
  2087. if ((unsigned long long) ciphertext_len -
  2088. crypto_aead_chacha20poly1305_IETF_ABYTES > 64ULL * (1ULL << 32) - 64ULL) {
  2089. zend_throw_exception(sodium_exception_ce, "message too long for a single key", 0);
  2090. RETURN_THROWS();
  2091. }
  2092. msg = zend_string_alloc((size_t) msg_len, 0);
  2093. if (crypto_aead_chacha20poly1305_ietf_decrypt
  2094. ((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
  2095. ciphertext, (unsigned long long) ciphertext_len,
  2096. ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
  2097. zend_string_efree(msg);
  2098. RETURN_FALSE;
  2099. }
  2100. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
  2101. zend_string_efree(msg);
  2102. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2103. RETURN_THROWS();
  2104. }
  2105. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  2106. ZSTR_VAL(msg)[msg_real_len] = 0;
  2107. RETURN_NEW_STR(msg);
  2108. }
  2109. #ifdef crypto_aead_xchacha20poly1305_IETF_NPUBBYTES
  2110. PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_encrypt)
  2111. {
  2112. zend_string *ciphertext;
  2113. unsigned char *ad;
  2114. unsigned char *msg;
  2115. unsigned char *npub;
  2116. unsigned char *secretkey;
  2117. unsigned long long ciphertext_real_len;
  2118. size_t ad_len;
  2119. size_t ciphertext_len;
  2120. size_t msg_len;
  2121. size_t npub_len;
  2122. size_t secretkey_len;
  2123. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  2124. &msg, &msg_len,
  2125. &ad, &ad_len,
  2126. &npub, &npub_len,
  2127. &secretkey, &secretkey_len) == FAILURE) {
  2128. sodium_remove_param_values_from_backtrace(EG(exception));
  2129. RETURN_THROWS();
  2130. }
  2131. if (npub_len != crypto_aead_xchacha20poly1305_IETF_NPUBBYTES) {
  2132. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES bytes long");
  2133. RETURN_THROWS();
  2134. }
  2135. if (secretkey_len != crypto_aead_xchacha20poly1305_IETF_KEYBYTES) {
  2136. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES bytes long");
  2137. RETURN_THROWS();
  2138. }
  2139. if (SIZE_MAX - msg_len <= crypto_aead_xchacha20poly1305_IETF_ABYTES) {
  2140. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2141. RETURN_THROWS();
  2142. }
  2143. ciphertext_len = msg_len + crypto_aead_xchacha20poly1305_IETF_ABYTES;
  2144. ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
  2145. if (crypto_aead_xchacha20poly1305_ietf_encrypt
  2146. ((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
  2147. (unsigned long long) msg_len,
  2148. ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
  2149. zend_string_efree(ciphertext);
  2150. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2151. RETURN_THROWS();
  2152. }
  2153. if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
  2154. ciphertext_real_len > ciphertext_len) {
  2155. zend_string_efree(ciphertext);
  2156. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2157. RETURN_THROWS();
  2158. }
  2159. PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
  2160. ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
  2161. RETURN_NEW_STR(ciphertext);
  2162. }
  2163. PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_decrypt)
  2164. {
  2165. zend_string *msg;
  2166. unsigned char *ad;
  2167. unsigned char *ciphertext;
  2168. unsigned char *npub;
  2169. unsigned char *secretkey;
  2170. unsigned long long msg_real_len;
  2171. size_t ad_len;
  2172. size_t ciphertext_len;
  2173. size_t msg_len;
  2174. size_t npub_len;
  2175. size_t secretkey_len;
  2176. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
  2177. &ciphertext, &ciphertext_len,
  2178. &ad, &ad_len,
  2179. &npub, &npub_len,
  2180. &secretkey, &secretkey_len) == FAILURE) {
  2181. sodium_remove_param_values_from_backtrace(EG(exception));
  2182. RETURN_THROWS();
  2183. }
  2184. if (npub_len != crypto_aead_xchacha20poly1305_IETF_NPUBBYTES) {
  2185. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES bytes long");
  2186. RETURN_THROWS();
  2187. }
  2188. if (secretkey_len != crypto_aead_xchacha20poly1305_IETF_KEYBYTES) {
  2189. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES bytes long");
  2190. RETURN_THROWS();
  2191. }
  2192. if (ciphertext_len < crypto_aead_xchacha20poly1305_IETF_ABYTES) {
  2193. RETURN_FALSE;
  2194. }
  2195. msg_len = ciphertext_len;
  2196. if (msg_len - crypto_aead_xchacha20poly1305_IETF_ABYTES >= SIZE_MAX) {
  2197. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2198. RETURN_THROWS();
  2199. }
  2200. if ((unsigned long long) ciphertext_len -
  2201. crypto_aead_xchacha20poly1305_IETF_ABYTES > 64ULL * (1ULL << 32) - 64ULL) {
  2202. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2203. RETURN_THROWS();
  2204. }
  2205. msg = zend_string_alloc((size_t) msg_len, 0);
  2206. if (crypto_aead_xchacha20poly1305_ietf_decrypt
  2207. ((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
  2208. ciphertext, (unsigned long long) ciphertext_len,
  2209. ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
  2210. zend_string_efree(msg);
  2211. RETURN_FALSE;
  2212. }
  2213. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
  2214. zend_string_efree(msg);
  2215. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2216. RETURN_THROWS();
  2217. }
  2218. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  2219. ZSTR_VAL(msg)[msg_real_len] = 0;
  2220. RETURN_NEW_STR(msg);
  2221. }
  2222. #endif
  2223. PHP_FUNCTION(sodium_bin2hex)
  2224. {
  2225. zend_string *hex;
  2226. unsigned char *bin;
  2227. size_t bin_len;
  2228. size_t hex_len;
  2229. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2230. &bin, &bin_len) == FAILURE) {
  2231. sodium_remove_param_values_from_backtrace(EG(exception));
  2232. RETURN_THROWS();
  2233. }
  2234. if (bin_len >= SIZE_MAX / 2U) {
  2235. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2236. RETURN_THROWS();
  2237. }
  2238. hex_len = bin_len * 2U;
  2239. hex = zend_string_alloc((size_t) hex_len, 0);
  2240. sodium_bin2hex(ZSTR_VAL(hex), hex_len + 1U, bin, bin_len);
  2241. ZSTR_VAL(hex)[hex_len] = 0;
  2242. RETURN_STR(hex);
  2243. }
  2244. PHP_FUNCTION(sodium_hex2bin)
  2245. {
  2246. zend_string *bin;
  2247. const char *end;
  2248. char *hex;
  2249. char *ignore = NULL;
  2250. size_t bin_real_len;
  2251. size_t bin_len;
  2252. size_t hex_len;
  2253. size_t ignore_len = 0;
  2254. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s",
  2255. &hex, &hex_len,
  2256. &ignore, &ignore_len) == FAILURE) {
  2257. sodium_remove_param_values_from_backtrace(EG(exception));
  2258. RETURN_THROWS();
  2259. }
  2260. bin_len = hex_len / 2;
  2261. bin = zend_string_alloc(bin_len, 0);
  2262. if (sodium_hex2bin((unsigned char *) ZSTR_VAL(bin), bin_len, hex, hex_len,
  2263. ignore, &bin_real_len, &end) != 0 ||
  2264. end != hex + hex_len) {
  2265. zend_string_efree(bin);
  2266. zend_argument_error(sodium_exception_ce, 1, "must be a valid hexadecimal string");
  2267. RETURN_THROWS();
  2268. }
  2269. if (bin_real_len >= SIZE_MAX || bin_real_len > bin_len) {
  2270. zend_string_efree(bin);
  2271. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2272. RETURN_THROWS();
  2273. }
  2274. PHP_SODIUM_ZSTR_TRUNCATE(bin, (size_t) bin_real_len);
  2275. ZSTR_VAL(bin)[bin_real_len] = 0;
  2276. RETURN_NEW_STR(bin);
  2277. }
  2278. #ifdef sodium_base64_VARIANT_ORIGINAL
  2279. PHP_FUNCTION(sodium_bin2base64)
  2280. {
  2281. zend_string *b64;
  2282. unsigned char *bin;
  2283. zend_long variant;
  2284. size_t bin_len;
  2285. size_t b64_len;
  2286. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl",
  2287. &bin, &bin_len, &variant) == FAILURE) {
  2288. sodium_remove_param_values_from_backtrace(EG(exception));
  2289. RETURN_THROWS();
  2290. }
  2291. if ((((unsigned int) variant) & ~ 0x6U) != 0x1U) {
  2292. zend_argument_error(sodium_exception_ce, 2, "must be a valid base64 variant identifier");
  2293. RETURN_THROWS();
  2294. }
  2295. if (bin_len >= SIZE_MAX / 4U * 3U - 3U - 1U) {
  2296. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2297. RETURN_THROWS();
  2298. }
  2299. b64_len = sodium_base64_ENCODED_LEN(bin_len, variant);
  2300. b64 = zend_string_alloc((size_t) b64_len - 1U, 0);
  2301. sodium_bin2base64(ZSTR_VAL(b64), b64_len, bin, bin_len, (int) variant);
  2302. RETURN_STR(b64);
  2303. }
  2304. PHP_FUNCTION(sodium_base642bin)
  2305. {
  2306. zend_string *bin;
  2307. char *b64;
  2308. const char *end;
  2309. char *ignore = NULL;
  2310. zend_long variant;
  2311. size_t bin_real_len;
  2312. size_t bin_len;
  2313. size_t b64_len;
  2314. size_t ignore_len = 0;
  2315. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s",
  2316. &b64, &b64_len, &variant,
  2317. &ignore, &ignore_len) == FAILURE) {
  2318. sodium_remove_param_values_from_backtrace(EG(exception));
  2319. RETURN_THROWS();
  2320. }
  2321. if ((((unsigned int) variant) & ~ 0x6U) != 0x1U) {
  2322. zend_argument_error(sodium_exception_ce, 2, "must be a valid base64 variant identifier");
  2323. RETURN_THROWS();
  2324. }
  2325. bin_len = b64_len / 4U * 3U + 2U;
  2326. bin = zend_string_alloc(bin_len, 0);
  2327. if (sodium_base642bin((unsigned char *) ZSTR_VAL(bin), bin_len,
  2328. b64, b64_len,
  2329. ignore, &bin_real_len, &end, (int) variant) != 0 ||
  2330. end != b64 + b64_len) {
  2331. zend_string_efree(bin);
  2332. zend_argument_error(sodium_exception_ce, 1, "must be a valid base64 string");
  2333. RETURN_THROWS();
  2334. }
  2335. if (bin_real_len >= SIZE_MAX || bin_real_len > bin_len) {
  2336. zend_string_efree(bin);
  2337. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  2338. RETURN_THROWS();
  2339. }
  2340. PHP_SODIUM_ZSTR_TRUNCATE(bin, (size_t) bin_real_len);
  2341. ZSTR_VAL(bin)[bin_real_len] = 0;
  2342. RETURN_NEW_STR(bin);
  2343. }
  2344. #endif
  2345. PHP_FUNCTION(sodium_crypto_scalarmult)
  2346. {
  2347. zend_string *q;
  2348. unsigned char *n;
  2349. unsigned char *p;
  2350. size_t n_len;
  2351. size_t p_len;
  2352. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2353. &n, &n_len, &p, &p_len) == FAILURE) {
  2354. sodium_remove_param_values_from_backtrace(EG(exception));
  2355. RETURN_THROWS();
  2356. }
  2357. if (n_len != crypto_scalarmult_SCALARBYTES) {
  2358. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SCALARMULT_SCALARBYTES bytes long");
  2359. RETURN_THROWS();
  2360. }
  2361. if (p_len != crypto_scalarmult_BYTES) {
  2362. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SCALARMULT_SCALARBYTES bytes long");
  2363. RETURN_THROWS();
  2364. }
  2365. q = zend_string_alloc(crypto_scalarmult_BYTES, 0);
  2366. if (crypto_scalarmult((unsigned char *) ZSTR_VAL(q), n, p) != 0) {
  2367. zend_string_efree(q);
  2368. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2369. RETURN_THROWS();
  2370. }
  2371. ZSTR_VAL(q)[crypto_scalarmult_BYTES] = 0;
  2372. RETURN_NEW_STR(q);
  2373. }
  2374. #ifdef crypto_core_ristretto255_HASHBYTES
  2375. PHP_FUNCTION(sodium_crypto_scalarmult_ristretto255)
  2376. {
  2377. zend_string *q;
  2378. unsigned char *n;
  2379. unsigned char *p;
  2380. size_t n_len;
  2381. size_t p_len;
  2382. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2383. &n, &n_len, &p, &p_len) == FAILURE) {
  2384. sodium_remove_param_values_from_backtrace(EG(exception));
  2385. RETURN_THROWS();
  2386. }
  2387. if (n_len != crypto_scalarmult_ristretto255_SCALARBYTES) {
  2388. zend_argument_error(sodium_exception_ce, 1,
  2389. "must be SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES bytes long");
  2390. RETURN_THROWS();
  2391. }
  2392. if (p_len != crypto_scalarmult_ristretto255_BYTES) {
  2393. zend_argument_error(sodium_exception_ce, 2,
  2394. "must be SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_BYTES bytes long");
  2395. RETURN_THROWS();
  2396. }
  2397. q = zend_string_alloc(crypto_scalarmult_ristretto255_BYTES, 0);
  2398. if (crypto_scalarmult_ristretto255((unsigned char *) ZSTR_VAL(q), n, p) != 0) {
  2399. zend_string_efree(q);
  2400. zend_throw_exception(sodium_exception_ce, "Result is identity element", 0);
  2401. RETURN_THROWS();
  2402. }
  2403. ZSTR_VAL(q)[crypto_scalarmult_ristretto255_BYTES] = 0;
  2404. RETURN_NEW_STR(q);
  2405. }
  2406. PHP_FUNCTION(sodium_crypto_scalarmult_ristretto255_base)
  2407. {
  2408. zend_string *q;
  2409. unsigned char *n;
  2410. size_t n_len;
  2411. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2412. &n, &n_len) == FAILURE) {
  2413. sodium_remove_param_values_from_backtrace(EG(exception));
  2414. RETURN_THROWS();
  2415. }
  2416. if (n_len != crypto_scalarmult_ristretto255_SCALARBYTES) {
  2417. zend_argument_error(sodium_exception_ce, 1,
  2418. "must be SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES bytes long");
  2419. RETURN_THROWS();
  2420. }
  2421. q = zend_string_alloc(crypto_scalarmult_ristretto255_BYTES, 0);
  2422. if (crypto_scalarmult_ristretto255_base((unsigned char *) ZSTR_VAL(q), n) != 0) {
  2423. zend_string_efree(q);
  2424. zend_argument_error(sodium_exception_ce, 1, "must not be zero", 0);
  2425. RETURN_THROWS();
  2426. }
  2427. ZSTR_VAL(q)[crypto_scalarmult_BYTES] = 0;
  2428. RETURN_NEW_STR(q);
  2429. }
  2430. #endif
  2431. PHP_FUNCTION(sodium_crypto_kx_seed_keypair)
  2432. {
  2433. unsigned char *sk;
  2434. unsigned char *pk;
  2435. unsigned char *seed;
  2436. size_t seed_len;
  2437. zend_string *keypair;
  2438. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2439. &seed, &seed_len) == FAILURE) {
  2440. sodium_remove_param_values_from_backtrace(EG(exception));
  2441. RETURN_THROWS();
  2442. }
  2443. if (seed_len != crypto_kx_SEEDBYTES) {
  2444. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_SEEDBYTES bytes long");
  2445. RETURN_THROWS();
  2446. }
  2447. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
  2448. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
  2449. keypair = zend_string_alloc(crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, 0);
  2450. sk = (unsigned char *) ZSTR_VAL(keypair);
  2451. pk = sk + crypto_kx_SECRETKEYBYTES;
  2452. crypto_generichash(sk, crypto_kx_SECRETKEYBYTES,
  2453. seed, crypto_kx_SEEDBYTES, NULL, 0);
  2454. if (crypto_scalarmult_base(pk, sk) != 0) {
  2455. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2456. RETURN_THROWS();
  2457. }
  2458. ZSTR_VAL(keypair)[crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES] = 0;
  2459. RETURN_STR(keypair);
  2460. }
  2461. PHP_FUNCTION(sodium_crypto_kx_keypair)
  2462. {
  2463. unsigned char *sk;
  2464. unsigned char *pk;
  2465. zend_string *keypair;
  2466. if (zend_parse_parameters_none() == FAILURE) {
  2467. RETURN_THROWS();
  2468. }
  2469. keypair = zend_string_alloc(crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, 0);
  2470. sk = (unsigned char *) ZSTR_VAL(keypair);
  2471. pk = sk + crypto_kx_SECRETKEYBYTES;
  2472. randombytes_buf(sk, crypto_kx_SECRETKEYBYTES);
  2473. if (crypto_scalarmult_base(pk, sk) != 0) {
  2474. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2475. RETURN_THROWS();
  2476. }
  2477. ZSTR_VAL(keypair)[crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES] = 0;
  2478. RETURN_STR(keypair);
  2479. }
  2480. PHP_FUNCTION(sodium_crypto_kx_secretkey)
  2481. {
  2482. zend_string *secretkey;
  2483. unsigned char *keypair;
  2484. size_t keypair_len;
  2485. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2486. &keypair, &keypair_len) == FAILURE) {
  2487. sodium_remove_param_values_from_backtrace(EG(exception));
  2488. RETURN_THROWS();
  2489. }
  2490. if (keypair_len !=
  2491. crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
  2492. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
  2493. RETURN_THROWS();
  2494. }
  2495. secretkey = zend_string_alloc(crypto_kx_SECRETKEYBYTES, 0);
  2496. memcpy(ZSTR_VAL(secretkey), keypair, crypto_kx_SECRETKEYBYTES);
  2497. ZSTR_VAL(secretkey)[crypto_kx_SECRETKEYBYTES] = 0;
  2498. RETURN_STR(secretkey);
  2499. }
  2500. PHP_FUNCTION(sodium_crypto_kx_publickey)
  2501. {
  2502. zend_string *publickey;
  2503. unsigned char *keypair;
  2504. size_t keypair_len;
  2505. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2506. &keypair, &keypair_len) == FAILURE) {
  2507. sodium_remove_param_values_from_backtrace(EG(exception));
  2508. RETURN_THROWS();
  2509. }
  2510. if (keypair_len !=
  2511. crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
  2512. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
  2513. RETURN_THROWS();
  2514. }
  2515. publickey = zend_string_alloc(crypto_kx_PUBLICKEYBYTES, 0);
  2516. memcpy(ZSTR_VAL(publickey), keypair + crypto_kx_SECRETKEYBYTES,
  2517. crypto_kx_PUBLICKEYBYTES);
  2518. ZSTR_VAL(publickey)[crypto_kx_PUBLICKEYBYTES] = 0;
  2519. RETURN_STR(publickey);
  2520. }
  2521. PHP_FUNCTION(sodium_crypto_kx_client_session_keys)
  2522. {
  2523. crypto_generichash_state h;
  2524. unsigned char q[crypto_scalarmult_BYTES];
  2525. unsigned char *keypair;
  2526. unsigned char *client_sk;
  2527. unsigned char *client_pk;
  2528. unsigned char *server_pk;
  2529. unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
  2530. size_t keypair_len;
  2531. size_t server_pk_len;
  2532. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2533. &keypair, &keypair_len,
  2534. &server_pk, &server_pk_len) == FAILURE) {
  2535. sodium_remove_param_values_from_backtrace(EG(exception));
  2536. RETURN_THROWS();
  2537. }
  2538. if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
  2539. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
  2540. RETURN_THROWS();
  2541. }
  2542. if (server_pk_len != crypto_kx_PUBLICKEYBYTES) {
  2543. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes long");
  2544. RETURN_THROWS();
  2545. }
  2546. client_sk = &keypair[0];
  2547. client_pk = &keypair[crypto_kx_SECRETKEYBYTES];
  2548. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
  2549. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
  2550. if (crypto_scalarmult(q, client_sk, server_pk) != 0) {
  2551. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2552. RETURN_THROWS();
  2553. }
  2554. crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
  2555. crypto_generichash_update(&h, q, sizeof q);
  2556. sodium_memzero(q, sizeof q);
  2557. crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
  2558. crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
  2559. crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
  2560. sodium_memzero(&h, sizeof h);
  2561. array_init(return_value);
  2562. add_next_index_stringl(return_value,
  2563. (const char *) session_keys,
  2564. crypto_kx_SESSIONKEYBYTES);
  2565. add_next_index_stringl(return_value,
  2566. (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
  2567. crypto_kx_SESSIONKEYBYTES);
  2568. }
  2569. PHP_FUNCTION(sodium_crypto_kx_server_session_keys)
  2570. {
  2571. crypto_generichash_state h;
  2572. unsigned char q[crypto_scalarmult_BYTES];
  2573. unsigned char *keypair;
  2574. unsigned char *server_sk;
  2575. unsigned char *server_pk;
  2576. unsigned char *client_pk;
  2577. unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
  2578. size_t keypair_len;
  2579. size_t client_pk_len;
  2580. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2581. &keypair, &keypair_len,
  2582. &client_pk, &client_pk_len) == FAILURE) {
  2583. sodium_remove_param_values_from_backtrace(EG(exception));
  2584. RETURN_THROWS();
  2585. }
  2586. if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
  2587. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
  2588. RETURN_THROWS();
  2589. }
  2590. if (client_pk_len != crypto_kx_PUBLICKEYBYTES) {
  2591. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes long");
  2592. RETURN_THROWS();
  2593. }
  2594. server_sk = &keypair[0];
  2595. server_pk = &keypair[crypto_kx_SECRETKEYBYTES];
  2596. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
  2597. (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
  2598. if (crypto_scalarmult(q, server_sk, client_pk) != 0) {
  2599. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2600. RETURN_THROWS();
  2601. }
  2602. crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
  2603. crypto_generichash_update(&h, q, sizeof q);
  2604. sodium_memzero(q, sizeof q);
  2605. crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
  2606. crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
  2607. crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
  2608. sodium_memzero(&h, sizeof h);
  2609. array_init(return_value);
  2610. add_next_index_stringl(return_value,
  2611. (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
  2612. crypto_kx_SESSIONKEYBYTES);
  2613. add_next_index_stringl(return_value,
  2614. (const char *) session_keys,
  2615. crypto_kx_SESSIONKEYBYTES);
  2616. }
  2617. PHP_FUNCTION(sodium_crypto_auth)
  2618. {
  2619. zend_string *mac;
  2620. char *key;
  2621. char *msg;
  2622. size_t msg_len;
  2623. size_t key_len;
  2624. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2625. &msg, &msg_len,
  2626. &key, &key_len) == FAILURE) {
  2627. sodium_remove_param_values_from_backtrace(EG(exception));
  2628. RETURN_THROWS();
  2629. }
  2630. if (key_len != crypto_auth_KEYBYTES) {
  2631. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_AUTH_KEYBYTES bytes long");
  2632. RETURN_THROWS();
  2633. }
  2634. mac = zend_string_alloc(crypto_auth_BYTES, 0);
  2635. if (crypto_auth((unsigned char *) ZSTR_VAL(mac),
  2636. (const unsigned char *) msg, msg_len,
  2637. (const unsigned char *) key) != 0) {
  2638. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2639. RETURN_THROWS();
  2640. }
  2641. ZSTR_VAL(mac)[crypto_auth_BYTES] = 0;
  2642. RETURN_STR(mac);
  2643. }
  2644. PHP_FUNCTION(sodium_crypto_auth_verify)
  2645. {
  2646. char *mac;
  2647. char *key;
  2648. char *msg;
  2649. size_t mac_len;
  2650. size_t msg_len;
  2651. size_t key_len;
  2652. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
  2653. &mac, &mac_len,
  2654. &msg, &msg_len,
  2655. &key, &key_len) == FAILURE) {
  2656. sodium_remove_param_values_from_backtrace(EG(exception));
  2657. RETURN_THROWS();
  2658. }
  2659. if (key_len != crypto_auth_KEYBYTES) {
  2660. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AUTH_KEYBYTES bytes long");
  2661. RETURN_THROWS();
  2662. }
  2663. if (mac_len != crypto_auth_BYTES) {
  2664. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_AUTH_BYTES bytes long");
  2665. RETURN_THROWS();
  2666. }
  2667. if (crypto_auth_verify((const unsigned char *) mac,
  2668. (const unsigned char *) msg, msg_len,
  2669. (const unsigned char *) key) != 0) {
  2670. RETURN_FALSE;
  2671. }
  2672. RETURN_TRUE;
  2673. }
  2674. PHP_FUNCTION(sodium_crypto_sign_ed25519_sk_to_curve25519)
  2675. {
  2676. zend_string *ecdhkey;
  2677. char *eddsakey;
  2678. size_t eddsakey_len;
  2679. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2680. &eddsakey, &eddsakey_len) == FAILURE) {
  2681. sodium_remove_param_values_from_backtrace(EG(exception));
  2682. RETURN_THROWS();
  2683. }
  2684. if (eddsakey_len != crypto_sign_SECRETKEYBYTES) {
  2685. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
  2686. RETURN_THROWS();
  2687. }
  2688. ecdhkey = zend_string_alloc(crypto_box_SECRETKEYBYTES, 0);
  2689. if (crypto_sign_ed25519_sk_to_curve25519((unsigned char *) ZSTR_VAL(ecdhkey),
  2690. (const unsigned char *) eddsakey) != 0) {
  2691. zend_throw_exception(sodium_exception_ce, "conversion failed", 0);
  2692. RETURN_THROWS();
  2693. }
  2694. ZSTR_VAL(ecdhkey)[crypto_box_SECRETKEYBYTES] = 0;
  2695. RETURN_STR(ecdhkey);
  2696. }
  2697. PHP_FUNCTION(sodium_crypto_sign_ed25519_pk_to_curve25519)
  2698. {
  2699. zend_string *ecdhkey;
  2700. char *eddsakey;
  2701. size_t eddsakey_len;
  2702. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  2703. &eddsakey, &eddsakey_len) == FAILURE) {
  2704. sodium_remove_param_values_from_backtrace(EG(exception));
  2705. RETURN_THROWS();
  2706. }
  2707. if (eddsakey_len != crypto_sign_PUBLICKEYBYTES) {
  2708. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
  2709. RETURN_THROWS();
  2710. }
  2711. ecdhkey = zend_string_alloc(crypto_sign_PUBLICKEYBYTES, 0);
  2712. if (crypto_sign_ed25519_pk_to_curve25519((unsigned char *) ZSTR_VAL(ecdhkey),
  2713. (const unsigned char *) eddsakey) != 0) {
  2714. zend_throw_exception(sodium_exception_ce, "conversion failed", 0);
  2715. RETURN_THROWS();
  2716. }
  2717. ZSTR_VAL(ecdhkey)[crypto_box_PUBLICKEYBYTES] = 0;
  2718. RETURN_STR(ecdhkey);
  2719. }
  2720. PHP_FUNCTION(sodium_compare)
  2721. {
  2722. char *buf1;
  2723. char *buf2;
  2724. size_t len1;
  2725. size_t len2;
  2726. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  2727. &buf1, &len1,
  2728. &buf2, &len2) == FAILURE) {
  2729. sodium_remove_param_values_from_backtrace(EG(exception));
  2730. RETURN_THROWS();
  2731. }
  2732. if (len1 != len2) {
  2733. zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
  2734. RETURN_THROWS();
  2735. } else {
  2736. RETURN_LONG(sodium_compare((const unsigned char *) buf1,
  2737. (const unsigned char *) buf2, (size_t) len1));
  2738. }
  2739. }
  2740. #ifdef HAVE_AESGCM
  2741. PHP_FUNCTION(sodium_crypto_aead_aes256gcm_keygen)
  2742. {
  2743. unsigned char key[crypto_aead_aes256gcm_KEYBYTES];
  2744. if (zend_parse_parameters_none() == FAILURE) {
  2745. RETURN_THROWS();
  2746. }
  2747. randombytes_buf(key, sizeof key);
  2748. RETURN_STRINGL((const char *) key, sizeof key);
  2749. }
  2750. #endif
  2751. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_keygen)
  2752. {
  2753. unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES];
  2754. if (zend_parse_parameters_none() == FAILURE) {
  2755. RETURN_THROWS();
  2756. }
  2757. randombytes_buf(key, sizeof key);
  2758. RETURN_STRINGL((const char *) key, sizeof key);
  2759. }
  2760. PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_keygen)
  2761. {
  2762. unsigned char key[crypto_aead_chacha20poly1305_IETF_KEYBYTES];
  2763. if (zend_parse_parameters_none() == FAILURE) {
  2764. RETURN_THROWS();
  2765. }
  2766. randombytes_buf(key, sizeof key);
  2767. RETURN_STRINGL((const char *) key, sizeof key);
  2768. }
  2769. #ifdef crypto_aead_xchacha20poly1305_IETF_NPUBBYTES
  2770. PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_keygen)
  2771. {
  2772. unsigned char key[crypto_aead_xchacha20poly1305_IETF_KEYBYTES];
  2773. if (zend_parse_parameters_none() == FAILURE) {
  2774. RETURN_THROWS();
  2775. }
  2776. randombytes_buf(key, sizeof key);
  2777. RETURN_STRINGL((const char *) key, sizeof key);
  2778. }
  2779. #endif
  2780. PHP_FUNCTION(sodium_crypto_auth_keygen)
  2781. {
  2782. unsigned char key[crypto_auth_KEYBYTES];
  2783. if (zend_parse_parameters_none() == FAILURE) {
  2784. RETURN_THROWS();
  2785. }
  2786. randombytes_buf(key, sizeof key);
  2787. RETURN_STRINGL((const char *) key, sizeof key);
  2788. }
  2789. PHP_FUNCTION(sodium_crypto_generichash_keygen)
  2790. {
  2791. unsigned char key[crypto_generichash_KEYBYTES];
  2792. if (zend_parse_parameters_none() == FAILURE) {
  2793. RETURN_THROWS();
  2794. }
  2795. randombytes_buf(key, sizeof key);
  2796. RETURN_STRINGL((const char *) key, sizeof key);
  2797. }
  2798. PHP_FUNCTION(sodium_crypto_kdf_keygen)
  2799. {
  2800. unsigned char key[crypto_kdf_KEYBYTES];
  2801. if (zend_parse_parameters_none() == FAILURE) {
  2802. RETURN_THROWS();
  2803. }
  2804. randombytes_buf(key, sizeof key);
  2805. RETURN_STRINGL((const char *) key, sizeof key);
  2806. }
  2807. PHP_FUNCTION(sodium_crypto_secretbox_keygen)
  2808. {
  2809. unsigned char key[crypto_secretbox_KEYBYTES];
  2810. if (zend_parse_parameters_none() == FAILURE) {
  2811. RETURN_THROWS();
  2812. }
  2813. randombytes_buf(key, sizeof key);
  2814. RETURN_STRINGL((const char *) key, sizeof key);
  2815. }
  2816. PHP_FUNCTION(sodium_crypto_shorthash_keygen)
  2817. {
  2818. unsigned char key[crypto_shorthash_KEYBYTES];
  2819. if (zend_parse_parameters_none() == FAILURE) {
  2820. RETURN_THROWS();
  2821. }
  2822. randombytes_buf(key, sizeof key);
  2823. RETURN_STRINGL((const char *) key, sizeof key);
  2824. }
  2825. PHP_FUNCTION(sodium_crypto_stream_keygen)
  2826. {
  2827. unsigned char key[crypto_stream_KEYBYTES];
  2828. if (zend_parse_parameters_none() == FAILURE) {
  2829. RETURN_THROWS();
  2830. }
  2831. randombytes_buf(key, sizeof key);
  2832. RETURN_STRINGL((const char *) key, sizeof key);
  2833. }
  2834. #ifdef crypto_stream_xchacha20_KEYBYTES
  2835. PHP_FUNCTION(sodium_crypto_stream_xchacha20_keygen)
  2836. {
  2837. unsigned char key[crypto_stream_xchacha20_KEYBYTES];
  2838. if (zend_parse_parameters_none() == FAILURE) {
  2839. return;
  2840. }
  2841. randombytes_buf(key, sizeof key);
  2842. RETURN_STRINGL((const char *) key, sizeof key);
  2843. }
  2844. #endif
  2845. PHP_FUNCTION(sodium_crypto_kdf_derive_from_key)
  2846. {
  2847. unsigned char ctx_padded[crypto_generichash_blake2b_PERSONALBYTES];
  2848. #ifndef crypto_kdf_PRIMITIVE
  2849. unsigned char salt[crypto_generichash_blake2b_SALTBYTES];
  2850. #endif
  2851. char *ctx;
  2852. char *key;
  2853. zend_string *subkey;
  2854. zend_long subkey_id;
  2855. zend_long subkey_len;
  2856. size_t ctx_len;
  2857. size_t key_len;
  2858. if (zend_parse_parameters(ZEND_NUM_ARGS(), "llss",
  2859. &subkey_len,
  2860. &subkey_id,
  2861. &ctx, &ctx_len,
  2862. &key, &key_len) == FAILURE) {
  2863. sodium_remove_param_values_from_backtrace(EG(exception));
  2864. RETURN_THROWS();
  2865. }
  2866. if (subkey_len < crypto_kdf_BYTES_MIN) {
  2867. zend_argument_error(sodium_exception_ce, 1, "must be greater than or equal to SODIUM_CRYPTO_KDF_BYTES_MIN");
  2868. RETURN_THROWS();
  2869. }
  2870. if (subkey_len > crypto_kdf_BYTES_MAX || subkey_len > SIZE_MAX) {
  2871. zend_argument_error(sodium_exception_ce, 1, "must be less than or equal to SODIUM_CRYPTO_KDF_BYTES_MAX");
  2872. RETURN_THROWS();
  2873. }
  2874. if (subkey_id < 0) {
  2875. zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to 0");
  2876. RETURN_THROWS();
  2877. }
  2878. if (ctx_len != crypto_kdf_CONTEXTBYTES) {
  2879. zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes long");
  2880. RETURN_THROWS();
  2881. }
  2882. if (key_len != crypto_kdf_KEYBYTES) {
  2883. zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_KDF_BYTES_MIN bytes long");
  2884. RETURN_THROWS();
  2885. }
  2886. memcpy(ctx_padded, ctx, crypto_kdf_CONTEXTBYTES);
  2887. memset(ctx_padded + crypto_kdf_CONTEXTBYTES, 0, sizeof ctx_padded - crypto_kdf_CONTEXTBYTES);
  2888. subkey = zend_string_alloc((size_t) subkey_len, 0);
  2889. #ifdef crypto_kdf_PRIMITIVE
  2890. crypto_kdf_derive_from_key((unsigned char *) ZSTR_VAL(subkey),
  2891. (size_t) subkey_len, (uint64_t) subkey_id,
  2892. ctx, (const unsigned char *) key);
  2893. #else
  2894. salt[0] = (unsigned char) (((uint64_t) subkey_id) );
  2895. salt[1] = (unsigned char) (((uint64_t) subkey_id) >> 8);
  2896. salt[2] = (unsigned char) (((uint64_t) subkey_id) >> 16);
  2897. salt[3] = (unsigned char) (((uint64_t) subkey_id) >> 24);
  2898. salt[4] = (unsigned char) (((uint64_t) subkey_id) >> 32);
  2899. salt[5] = (unsigned char) (((uint64_t) subkey_id) >> 40);
  2900. salt[6] = (unsigned char) (((uint64_t) subkey_id) >> 48);
  2901. salt[7] = (unsigned char) (((uint64_t) subkey_id) >> 56);
  2902. memset(salt + 8, 0, (sizeof salt) - 8);
  2903. crypto_generichash_blake2b_salt_personal((unsigned char *) ZSTR_VAL(subkey),
  2904. (size_t) subkey_len,
  2905. NULL, 0,
  2906. (const unsigned char *) key,
  2907. crypto_kdf_KEYBYTES,
  2908. salt, ctx_padded);
  2909. #endif
  2910. ZSTR_VAL(subkey)[subkey_len] = 0;
  2911. RETURN_STR(subkey);
  2912. }
  2913. PHP_FUNCTION(sodium_pad)
  2914. {
  2915. zend_string *padded;
  2916. char *unpadded;
  2917. zend_long blocksize;
  2918. volatile size_t st;
  2919. size_t i, j, k;
  2920. size_t unpadded_len;
  2921. size_t xpadlen;
  2922. size_t xpadded_len;
  2923. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl",
  2924. &unpadded, &unpadded_len, &blocksize) == FAILURE) {
  2925. sodium_remove_param_values_from_backtrace(EG(exception));
  2926. RETURN_THROWS();
  2927. }
  2928. if (blocksize <= 0) {
  2929. zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
  2930. RETURN_THROWS();
  2931. }
  2932. if (blocksize > SIZE_MAX) {
  2933. zend_argument_error(sodium_exception_ce, 2, "is too large");
  2934. RETURN_THROWS();
  2935. }
  2936. xpadlen = blocksize - 1U;
  2937. if ((blocksize & (blocksize - 1U)) == 0U) {
  2938. xpadlen -= unpadded_len & ((size_t) blocksize - 1U);
  2939. } else {
  2940. xpadlen -= unpadded_len % (size_t) blocksize;
  2941. }
  2942. if ((size_t) SIZE_MAX - unpadded_len <= xpadlen) {
  2943. zend_throw_exception(sodium_exception_ce, "input is too large", 0);
  2944. RETURN_THROWS();
  2945. }
  2946. xpadded_len = unpadded_len + xpadlen;
  2947. padded = zend_string_alloc(xpadded_len + 1U, 0);
  2948. if (unpadded_len > 0) {
  2949. st = 1U;
  2950. i = 0U;
  2951. k = unpadded_len;
  2952. for (j = 0U; j <= xpadded_len; j++) {
  2953. ZSTR_VAL(padded)[j] = unpadded[i];
  2954. k -= st;
  2955. st = (size_t) (~(((( (((uint64_t) k) >> 48) | (((uint64_t) k) >> 32) |
  2956. (k >> 16) | k) & 0xffff) - 1U) >> 16)) & 1U;
  2957. i += st;
  2958. }
  2959. }
  2960. #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
  2961. if (sodium_pad(NULL, (unsigned char *) ZSTR_VAL(padded), unpadded_len,
  2962. (size_t) blocksize, xpadded_len + 1U) != 0) {
  2963. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  2964. RETURN_THROWS();
  2965. }
  2966. #else
  2967. {
  2968. char *tail;
  2969. volatile unsigned char mask;
  2970. unsigned char barrier_mask;
  2971. tail = &ZSTR_VAL(padded)[xpadded_len];
  2972. mask = 0U;
  2973. for (i = 0; i < blocksize; i++) {
  2974. barrier_mask = (unsigned char)
  2975. (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT));
  2976. tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask);
  2977. mask |= barrier_mask;
  2978. }
  2979. }
  2980. #endif
  2981. ZSTR_VAL(padded)[xpadded_len + 1U] = 0;
  2982. RETURN_STR(padded);
  2983. }
  2984. PHP_FUNCTION(sodium_unpad)
  2985. {
  2986. zend_string *unpadded;
  2987. char *padded;
  2988. size_t padded_len;
  2989. size_t unpadded_len;
  2990. zend_long blocksize;
  2991. int ret;
  2992. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl",
  2993. &padded, &padded_len, &blocksize) == FAILURE) {
  2994. sodium_remove_param_values_from_backtrace(EG(exception));
  2995. RETURN_THROWS();
  2996. }
  2997. if (blocksize <= 0) {
  2998. zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
  2999. RETURN_THROWS();
  3000. }
  3001. if (blocksize > SIZE_MAX) {
  3002. zend_argument_error(sodium_exception_ce, 2, "is too large");
  3003. RETURN_THROWS();
  3004. }
  3005. if (padded_len < blocksize) {
  3006. zend_argument_error(sodium_exception_ce, 1, "must be at least as long as the block size");
  3007. RETURN_THROWS();
  3008. }
  3009. #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
  3010. ret = sodium_unpad(&unpadded_len, (const unsigned char *) padded,
  3011. padded_len, (size_t) blocksize);
  3012. #else
  3013. {
  3014. const char *tail;
  3015. unsigned char acc = 0U;
  3016. unsigned char c;
  3017. unsigned char valid = 0U;
  3018. volatile size_t pad_len = 0U;
  3019. size_t i;
  3020. size_t is_barrier;
  3021. tail = &padded[padded_len - 1U];
  3022. for (i = 0U; i < (size_t) blocksize; i++) {
  3023. c = tail[-i];
  3024. is_barrier =
  3025. (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U;
  3026. acc |= c;
  3027. pad_len |= i & (1U + ~is_barrier);
  3028. valid |= (unsigned char) is_barrier;
  3029. }
  3030. unpadded_len = padded_len - 1U - pad_len;
  3031. ret = (int) (valid - 1U);
  3032. }
  3033. #endif
  3034. if (ret != 0 || unpadded_len > LONG_MAX) {
  3035. zend_throw_exception(sodium_exception_ce, "invalid padding", 0);
  3036. RETURN_THROWS();
  3037. }
  3038. unpadded = zend_string_init(padded, padded_len, 0);
  3039. PHP_SODIUM_ZSTR_TRUNCATE(unpadded, unpadded_len);
  3040. ZSTR_VAL(unpadded)[unpadded_len] = 0;
  3041. RETURN_STR(unpadded);
  3042. }
  3043. #ifdef crypto_secretstream_xchacha20poly1305_ABYTES
  3044. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_keygen)
  3045. {
  3046. unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
  3047. if (zend_parse_parameters_none() == FAILURE) {
  3048. RETURN_THROWS();
  3049. }
  3050. randombytes_buf(key, sizeof key);
  3051. RETURN_STRINGL((const char *) key, sizeof key);
  3052. }
  3053. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_push)
  3054. {
  3055. crypto_secretstream_xchacha20poly1305_state state;
  3056. unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
  3057. unsigned char *key;
  3058. size_t key_len;
  3059. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3060. &key, &key_len) == FAILURE) {
  3061. sodium_remove_param_values_from_backtrace(EG(exception));
  3062. RETURN_THROWS();
  3063. }
  3064. if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
  3065. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes long");
  3066. RETURN_THROWS();
  3067. }
  3068. if (crypto_secretstream_xchacha20poly1305_init_push(&state,
  3069. header, key) != 0) {
  3070. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3071. RETURN_THROWS();
  3072. }
  3073. array_init(return_value);
  3074. add_next_index_stringl(return_value, (const char *) &state, sizeof state);
  3075. add_next_index_stringl(return_value, (const char *) header, sizeof header);
  3076. }
  3077. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_push)
  3078. {
  3079. zval *state_zv;
  3080. zend_string *c;
  3081. unsigned char *ad = NULL;
  3082. unsigned char *msg;
  3083. unsigned char *state;
  3084. unsigned long long c_real_len;
  3085. zend_long tag = crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
  3086. size_t ad_len = (size_t) 0U;
  3087. size_t c_len;
  3088. size_t msg_len;
  3089. size_t state_len;
  3090. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|sl",
  3091. &state_zv,
  3092. &msg, &msg_len, &ad, &ad_len, &tag) == FAILURE) {
  3093. sodium_remove_param_values_from_backtrace(EG(exception));
  3094. RETURN_THROWS();
  3095. }
  3096. ZVAL_DEREF(state_zv);
  3097. if (Z_TYPE_P(state_zv) != IS_STRING) {
  3098. zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
  3099. RETURN_THROWS();
  3100. }
  3101. sodium_separate_string(state_zv);
  3102. state = (unsigned char *) Z_STRVAL(*state_zv);
  3103. state_len = Z_STRLEN(*state_zv);
  3104. if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
  3105. zend_argument_error(sodium_exception_ce, 1, "must have a correct length");
  3106. RETURN_THROWS();
  3107. }
  3108. if (msg_len > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX ||
  3109. msg_len > SIZE_MAX - crypto_secretstream_xchacha20poly1305_ABYTES) {
  3110. zend_argument_error(sodium_exception_ce, 2, "must be at most SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes long");
  3111. RETURN_THROWS();
  3112. }
  3113. if (tag < 0 || tag > 255) {
  3114. zend_argument_error(sodium_exception_ce, 4, "must be in the range of 0-255");
  3115. RETURN_THROWS();
  3116. }
  3117. c_len = msg_len + crypto_secretstream_xchacha20poly1305_ABYTES;
  3118. c = zend_string_alloc((size_t) c_len, 0);
  3119. if (crypto_secretstream_xchacha20poly1305_push
  3120. ((void *) state, (unsigned char *) ZSTR_VAL(c), &c_real_len,
  3121. msg, (unsigned long long) msg_len, ad, (unsigned long long) ad_len,
  3122. (unsigned char) tag) != 0) {
  3123. zend_string_efree(c);
  3124. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3125. RETURN_THROWS();
  3126. }
  3127. if (c_real_len <= 0U || c_real_len >= SIZE_MAX || c_real_len > c_len) {
  3128. zend_string_efree(c);
  3129. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  3130. RETURN_THROWS();
  3131. }
  3132. PHP_SODIUM_ZSTR_TRUNCATE(c, (size_t) c_real_len);
  3133. ZSTR_VAL(c)[c_real_len] = 0;
  3134. RETURN_NEW_STR(c);
  3135. }
  3136. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_pull)
  3137. {
  3138. crypto_secretstream_xchacha20poly1305_state state;
  3139. unsigned char *header;
  3140. unsigned char *key;
  3141. size_t header_len;
  3142. size_t key_len;
  3143. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3144. &header, &header_len,
  3145. &key, &key_len) == FAILURE) {
  3146. sodium_remove_param_values_from_backtrace(EG(exception));
  3147. RETURN_THROWS();
  3148. }
  3149. if (header_len != crypto_secretstream_xchacha20poly1305_HEADERBYTES) {
  3150. zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes long");
  3151. RETURN_THROWS();
  3152. }
  3153. if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
  3154. zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes long");
  3155. RETURN_THROWS();
  3156. }
  3157. if (crypto_secretstream_xchacha20poly1305_init_pull(&state,
  3158. header, key) != 0) {
  3159. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3160. RETURN_THROWS();
  3161. }
  3162. RETURN_STRINGL((const char *) &state, sizeof state);
  3163. }
  3164. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_pull)
  3165. {
  3166. zval *state_zv;
  3167. zend_string *msg;
  3168. unsigned char *ad = NULL;
  3169. unsigned char *c;
  3170. unsigned char *state;
  3171. unsigned long long msg_real_len;
  3172. size_t ad_len = (size_t) 0U;
  3173. size_t msg_len;
  3174. size_t c_len;
  3175. size_t state_len;
  3176. unsigned char tag;
  3177. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|s",
  3178. &state_zv,
  3179. &c, &c_len, &ad, &ad_len) == FAILURE) {
  3180. sodium_remove_param_values_from_backtrace(EG(exception));
  3181. RETURN_THROWS();
  3182. }
  3183. ZVAL_DEREF(state_zv);
  3184. if (Z_TYPE_P(state_zv) != IS_STRING) {
  3185. zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
  3186. RETURN_THROWS();
  3187. }
  3188. sodium_separate_string(state_zv);
  3189. state = (unsigned char *) Z_STRVAL(*state_zv);
  3190. state_len = Z_STRLEN(*state_zv);
  3191. if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
  3192. zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
  3193. RETURN_THROWS();
  3194. }
  3195. if (c_len < crypto_secretstream_xchacha20poly1305_ABYTES) {
  3196. RETURN_FALSE;
  3197. }
  3198. msg_len = c_len - crypto_secretstream_xchacha20poly1305_ABYTES;
  3199. msg = zend_string_alloc((size_t) msg_len, 0);
  3200. if (crypto_secretstream_xchacha20poly1305_pull
  3201. ((void *) state, (unsigned char *) ZSTR_VAL(msg), &msg_real_len, &tag,
  3202. c, (unsigned long long) c_len, ad, (unsigned long long) ad_len) != 0) {
  3203. zend_string_efree(msg);
  3204. RETURN_FALSE;
  3205. }
  3206. if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
  3207. zend_string_efree(msg);
  3208. zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
  3209. RETURN_THROWS();
  3210. }
  3211. PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
  3212. ZSTR_VAL(msg)[msg_real_len] = 0;
  3213. array_init(return_value);
  3214. add_next_index_str(return_value, msg);
  3215. add_next_index_long(return_value, (long) tag);
  3216. }
  3217. PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_rekey)
  3218. {
  3219. zval *state_zv;
  3220. unsigned char *state;
  3221. size_t state_len;
  3222. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &state_zv) == FAILURE) {
  3223. sodium_remove_param_values_from_backtrace(EG(exception));
  3224. RETURN_THROWS();
  3225. }
  3226. ZVAL_DEREF(state_zv);
  3227. if (Z_TYPE_P(state_zv) != IS_STRING) {
  3228. zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
  3229. RETURN_THROWS();
  3230. }
  3231. sodium_separate_string(state_zv);
  3232. state = (unsigned char *) Z_STRVAL(*state_zv);
  3233. state_len = Z_STRLEN(*state_zv);
  3234. if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
  3235. zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
  3236. RETURN_THROWS();
  3237. }
  3238. crypto_secretstream_xchacha20poly1305_rekey((void *) state);
  3239. }
  3240. #endif
  3241. #ifdef crypto_core_ristretto255_HASHBYTES
  3242. PHP_FUNCTION(sodium_crypto_core_ristretto255_add)
  3243. {
  3244. zend_string *r;
  3245. unsigned char *p;
  3246. unsigned char *q;
  3247. size_t p_len;
  3248. size_t q_len;
  3249. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3250. &p, &p_len, &q, &q_len) == FAILURE) {
  3251. sodium_remove_param_values_from_backtrace(EG(exception));
  3252. RETURN_THROWS();
  3253. }
  3254. if (p_len != crypto_core_ristretto255_BYTES) {
  3255. zend_argument_error(sodium_exception_ce, 1,
  3256. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
  3257. RETURN_THROWS();
  3258. }
  3259. if (q_len != crypto_core_ristretto255_BYTES) {
  3260. zend_argument_error(sodium_exception_ce, 2,
  3261. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
  3262. RETURN_THROWS();
  3263. }
  3264. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3265. if (crypto_core_ristretto255_add((unsigned char *) ZSTR_VAL(r), p, q) != 0) {
  3266. zend_string_efree(r);
  3267. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3268. RETURN_THROWS();
  3269. }
  3270. ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
  3271. RETURN_NEW_STR(r);
  3272. }
  3273. PHP_FUNCTION(sodium_crypto_core_ristretto255_from_hash)
  3274. {
  3275. zend_string *r;
  3276. unsigned char *s;
  3277. size_t s_len;
  3278. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3279. &s, &s_len) == FAILURE) {
  3280. sodium_remove_param_values_from_backtrace(EG(exception));
  3281. RETURN_THROWS();
  3282. }
  3283. if (s_len != crypto_core_ristretto255_HASHBYTES) {
  3284. zend_argument_error(sodium_exception_ce, 1,
  3285. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES bytes long");
  3286. RETURN_THROWS();
  3287. }
  3288. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3289. if (crypto_core_ristretto255_from_hash((unsigned char *) ZSTR_VAL(r), s) != 0) {
  3290. zend_string_efree(r);
  3291. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3292. RETURN_THROWS();
  3293. }
  3294. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3295. RETURN_NEW_STR(r);
  3296. }
  3297. PHP_FUNCTION(sodium_crypto_core_ristretto255_is_valid_point)
  3298. {
  3299. unsigned char *s;
  3300. size_t s_len;
  3301. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3302. &s, &s_len) == FAILURE) {
  3303. sodium_remove_param_values_from_backtrace(EG(exception));
  3304. RETURN_THROWS();
  3305. }
  3306. if (s_len != crypto_core_ristretto255_BYTES) {
  3307. zend_argument_error(sodium_exception_ce, 1,
  3308. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
  3309. RETURN_THROWS();
  3310. }
  3311. RETURN_BOOL(crypto_core_ristretto255_is_valid_point(s));
  3312. }
  3313. PHP_FUNCTION(sodium_crypto_core_ristretto255_random)
  3314. {
  3315. zend_string *r;
  3316. if (zend_parse_parameters_none() == FAILURE) {
  3317. RETURN_THROWS();
  3318. }
  3319. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3320. crypto_core_ristretto255_random((unsigned char *) ZSTR_VAL(r));
  3321. ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
  3322. RETURN_NEW_STR(r);
  3323. }
  3324. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_add)
  3325. {
  3326. zend_string *r;
  3327. unsigned char *p;
  3328. unsigned char *q;
  3329. size_t p_len;
  3330. size_t q_len;
  3331. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3332. &p, &p_len, &q, &q_len) == FAILURE) {
  3333. sodium_remove_param_values_from_backtrace(EG(exception));
  3334. RETURN_THROWS();
  3335. }
  3336. if (p_len != crypto_core_ristretto255_SCALARBYTES) {
  3337. zend_argument_error(sodium_exception_ce, 1,
  3338. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3339. RETURN_THROWS();
  3340. }
  3341. if (q_len != crypto_core_ristretto255_SCALARBYTES) {
  3342. zend_argument_error(sodium_exception_ce, 2,
  3343. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3344. RETURN_THROWS();
  3345. }
  3346. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3347. crypto_core_ristretto255_scalar_add((unsigned char *) ZSTR_VAL(r), p, q);
  3348. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3349. RETURN_NEW_STR(r);
  3350. }
  3351. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_complement)
  3352. {
  3353. zend_string *r;
  3354. unsigned char *s;
  3355. size_t s_len;
  3356. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3357. &s, &s_len) == FAILURE) {
  3358. sodium_remove_param_values_from_backtrace(EG(exception));
  3359. RETURN_THROWS();
  3360. }
  3361. if (s_len != crypto_core_ristretto255_SCALARBYTES) {
  3362. zend_argument_error(sodium_exception_ce, 1,
  3363. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3364. RETURN_THROWS();
  3365. }
  3366. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3367. crypto_core_ristretto255_scalar_complement((unsigned char *) ZSTR_VAL(r), s);
  3368. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3369. RETURN_NEW_STR(r);
  3370. }
  3371. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_invert)
  3372. {
  3373. zend_string *r;
  3374. unsigned char *s;
  3375. size_t s_len;
  3376. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3377. &s, &s_len) == FAILURE) {
  3378. sodium_remove_param_values_from_backtrace(EG(exception));
  3379. RETURN_THROWS();
  3380. }
  3381. if (s_len != crypto_core_ristretto255_SCALARBYTES) {
  3382. zend_argument_error(sodium_exception_ce, 1,
  3383. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3384. RETURN_THROWS();
  3385. }
  3386. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3387. if (crypto_core_ristretto255_scalar_invert((unsigned char *) ZSTR_VAL(r), s) != 0) {
  3388. zend_string_efree(r);
  3389. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3390. RETURN_THROWS();
  3391. }
  3392. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3393. RETURN_NEW_STR(r);
  3394. }
  3395. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_mul)
  3396. {
  3397. zend_string *r;
  3398. unsigned char *x;
  3399. unsigned char *y;
  3400. size_t x_len;
  3401. size_t y_len;
  3402. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3403. &x, &x_len, &y, &y_len) == FAILURE) {
  3404. sodium_remove_param_values_from_backtrace(EG(exception));
  3405. RETURN_THROWS();
  3406. }
  3407. if (x_len != crypto_core_ristretto255_SCALARBYTES) {
  3408. zend_argument_error(sodium_exception_ce, 1,
  3409. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3410. RETURN_THROWS();
  3411. }
  3412. if (y_len != crypto_core_ristretto255_SCALARBYTES) {
  3413. zend_argument_error(sodium_exception_ce, 2,
  3414. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3415. RETURN_THROWS();
  3416. }
  3417. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3418. crypto_core_ristretto255_scalar_mul((unsigned char *) ZSTR_VAL(r), x, y);
  3419. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3420. RETURN_NEW_STR(r);
  3421. }
  3422. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_negate)
  3423. {
  3424. zend_string *r;
  3425. unsigned char *s;
  3426. size_t s_len;
  3427. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3428. &s, &s_len) == FAILURE) {
  3429. sodium_remove_param_values_from_backtrace(EG(exception));
  3430. RETURN_THROWS();
  3431. }
  3432. if (s_len != crypto_core_ristretto255_SCALARBYTES) {
  3433. zend_argument_error(sodium_exception_ce, 1,
  3434. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3435. RETURN_THROWS();
  3436. }
  3437. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3438. crypto_core_ristretto255_scalar_negate((unsigned char *) ZSTR_VAL(r), s);
  3439. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3440. RETURN_NEW_STR(r);
  3441. }
  3442. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_random)
  3443. {
  3444. zend_string *r;
  3445. if (zend_parse_parameters_none() == FAILURE) {
  3446. RETURN_THROWS();
  3447. };
  3448. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3449. crypto_core_ristretto255_scalar_random((unsigned char *) ZSTR_VAL(r));
  3450. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3451. RETURN_NEW_STR(r);
  3452. }
  3453. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_reduce)
  3454. {
  3455. zend_string *r;
  3456. unsigned char *s;
  3457. size_t s_len;
  3458. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
  3459. &s, &s_len) == FAILURE) {
  3460. sodium_remove_param_values_from_backtrace(EG(exception));
  3461. RETURN_THROWS();
  3462. }
  3463. if (s_len != crypto_core_ristretto255_NONREDUCEDSCALARBYTES) {
  3464. zend_argument_error(sodium_exception_ce, 1,
  3465. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES bytes long");
  3466. RETURN_THROWS();
  3467. }
  3468. r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
  3469. crypto_core_ristretto255_scalar_reduce((unsigned char *) ZSTR_VAL(r), s);
  3470. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3471. RETURN_NEW_STR(r);
  3472. }
  3473. PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_sub)
  3474. {
  3475. zend_string *r;
  3476. unsigned char *p;
  3477. unsigned char *q;
  3478. size_t p_len;
  3479. size_t q_len;
  3480. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3481. &p, &p_len, &q, &q_len) == FAILURE) {
  3482. sodium_remove_param_values_from_backtrace(EG(exception));
  3483. RETURN_THROWS();
  3484. }
  3485. if (p_len != crypto_core_ristretto255_SCALARBYTES) {
  3486. zend_argument_error(sodium_exception_ce, 1,
  3487. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3488. RETURN_THROWS();
  3489. }
  3490. if (q_len != crypto_core_ristretto255_SCALARBYTES) {
  3491. zend_argument_error(sodium_exception_ce, 2,
  3492. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
  3493. RETURN_THROWS();
  3494. }
  3495. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3496. crypto_core_ristretto255_scalar_sub((unsigned char *) ZSTR_VAL(r), p, q);
  3497. ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
  3498. RETURN_NEW_STR(r);
  3499. }
  3500. PHP_FUNCTION(sodium_crypto_core_ristretto255_sub)
  3501. {
  3502. zend_string *r;
  3503. unsigned char *p;
  3504. unsigned char *q;
  3505. size_t p_len;
  3506. size_t q_len;
  3507. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  3508. &p, &p_len, &q, &q_len) == FAILURE) {
  3509. sodium_remove_param_values_from_backtrace(EG(exception));
  3510. RETURN_THROWS();
  3511. }
  3512. if (p_len != crypto_core_ristretto255_BYTES) {
  3513. zend_argument_error(sodium_exception_ce, 1,
  3514. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
  3515. RETURN_THROWS();
  3516. }
  3517. if (q_len != crypto_core_ristretto255_BYTES) {
  3518. zend_argument_error(sodium_exception_ce, 2,
  3519. "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
  3520. RETURN_THROWS();
  3521. }
  3522. r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
  3523. if (crypto_core_ristretto255_sub((unsigned char *) ZSTR_VAL(r), p, q) != 0) {
  3524. zend_string_efree(r);
  3525. zend_throw_exception(sodium_exception_ce, "internal error", 0);
  3526. RETURN_THROWS();
  3527. }
  3528. ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
  3529. RETURN_NEW_STR(r);
  3530. }
  3531. #endif