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