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 "ext/standard/info.h"
23 #include "php_libsodium.h"
24 #include "zend_attributes.h"
25 #include "zend_exceptions.h"
26
27 #include <sodium.h>
28 #include <stdint.h>
29 #include <string.h>
30
31 #define PHP_SODIUM_ZSTR_TRUNCATE(zs, len) do { ZSTR_LEN(zs) = (len); } while(0)
32
33 static zend_class_entry *sodium_exception_ce;
34
35 #if (defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || \
36 defined(_M_AMD64) || defined(_M_IX86) || defined(__aarch64__) || defined(_M_ARM64))
37 # define HAVE_AESGCM 1
38 #endif
39
zend_string_checked_alloc(size_t len,int persistent)40 static zend_always_inline zend_string *zend_string_checked_alloc(size_t len, int persistent)
41 {
42 zend_string *zs;
43
44 if (ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)) < len) {
45 zend_error_noreturn(E_ERROR, "Memory allocation too large (%zu bytes)", len);
46 }
47 zs = zend_string_alloc(len, persistent);
48 ZSTR_VAL(zs)[len] = 0;
49
50 return zs;
51 }
52
53 #ifndef crypto_kdf_BYTES_MIN
54 # define crypto_kdf_BYTES_MIN 16
55 # define crypto_kdf_BYTES_MAX 64
56 # define crypto_kdf_CONTEXTBYTES 8
57 # define crypto_kdf_KEYBYTES 32
58 #endif
59
60 #ifndef crypto_kx_SEEDBYTES
61 # define crypto_kx_SEEDBYTES 32
62 # define crypto_kx_SESSIONKEYBYTES 32
63 # define crypto_kx_PUBLICKEYBYTES 32
64 # define crypto_kx_SECRETKEYBYTES 32
65 #endif
66
67 #include "libsodium_arginfo.h"
68
69 #ifndef crypto_aead_chacha20poly1305_IETF_KEYBYTES
70 # define crypto_aead_chacha20poly1305_IETF_KEYBYTES crypto_aead_chacha20poly1305_KEYBYTES
71 #endif
72 #ifndef crypto_aead_chacha20poly1305_IETF_NSECBYTES
73 # define crypto_aead_chacha20poly1305_IETF_NSECBYTES crypto_aead_chacha20poly1305_NSECBYTES
74 #endif
75 #ifndef crypto_aead_chacha20poly1305_IETF_ABYTES
76 # define crypto_aead_chacha20poly1305_IETF_ABYTES crypto_aead_chacha20poly1305_ABYTES
77 #endif
78
79 #if defined(crypto_secretstream_xchacha20poly1305_ABYTES) && SODIUM_LIBRARY_VERSION_MAJOR < 10
80 # undef crypto_secretstream_xchacha20poly1305_ABYTES
81 #endif
82
83 #ifndef crypto_pwhash_OPSLIMIT_MIN
84 # define crypto_pwhash_OPSLIMIT_MIN crypto_pwhash_OPSLIMIT_INTERACTIVE
85 #endif
86 #ifndef crypto_pwhash_MEMLIMIT_MIN
87 # define crypto_pwhash_MEMLIMIT_MIN crypto_pwhash_MEMLIMIT_INTERACTIVE
88 #endif
89 #ifndef crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN
90 # define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
91 #endif
92 #ifndef crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN
93 # define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
94 #endif
95
96 /* Load after the "standard" module in order to give it
97 * priority in registering argon2i/argon2id password hashers.
98 */
99 static const zend_module_dep sodium_deps[] = {
100 ZEND_MOD_REQUIRED("standard")
101 ZEND_MOD_END
102 };
103
104 zend_module_entry sodium_module_entry = {
105 STANDARD_MODULE_HEADER_EX,
106 NULL,
107 sodium_deps,
108 "sodium",
109 ext_functions,
110 PHP_MINIT(sodium),
111 PHP_MSHUTDOWN(sodium),
112 NULL,
113 NULL,
114 PHP_MINFO(sodium),
115 PHP_SODIUM_VERSION,
116 STANDARD_MODULE_PROPERTIES
117 };
118 /* }}} */
119
120 #ifdef COMPILE_DL_SODIUM
ZEND_GET_MODULE(sodium)121 ZEND_GET_MODULE(sodium)
122 #endif
123
124 /* Remove argument information from backtrace to prevent information leaks */
125 static void sodium_remove_param_values_from_backtrace(zend_object *obj) {
126 zval rv;
127 zval *trace = zend_read_property_ex(zend_get_exception_base(obj), obj, ZSTR_KNOWN(ZEND_STR_TRACE), /* silent */ false, &rv);
128 if (trace && Z_TYPE_P(trace) == IS_ARRAY) {
129 zval *frame;
130 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(trace), frame) {
131 if (Z_TYPE_P(frame) == IS_ARRAY) {
132 zval *args = zend_hash_find(Z_ARRVAL_P(frame), ZSTR_KNOWN(ZEND_STR_ARGS));
133 if (args) {
134 zval_ptr_dtor(args);
135 ZVAL_EMPTY_ARRAY(args);
136 }
137 }
138 } ZEND_HASH_FOREACH_END();
139 }
140 }
141
sodium_exception_create_object(zend_class_entry * ce)142 static zend_object *sodium_exception_create_object(zend_class_entry *ce) {
143 zend_object *obj = zend_ce_exception->create_object(ce);
144 sodium_remove_param_values_from_backtrace(obj);
145 return obj;
146 }
147
sodium_separate_string(zval * zv)148 static void sodium_separate_string(zval *zv) {
149 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
150 if (!Z_REFCOUNTED_P(zv) || Z_REFCOUNT_P(zv) > 1) {
151 zend_string *copy = zend_string_init(Z_STRVAL_P(zv), Z_STRLEN_P(zv), 0);
152 Z_TRY_DELREF_P(zv);
153 ZVAL_STR(zv, copy);
154 }
155 }
156
PHP_MINIT_FUNCTION(sodium)157 PHP_MINIT_FUNCTION(sodium)
158 {
159 if (sodium_init() < 0) {
160 zend_error_noreturn(E_ERROR, "sodium_init()");
161 }
162
163 sodium_exception_ce = register_class_SodiumException(zend_ce_exception);
164 sodium_exception_ce->create_object = sodium_exception_create_object;
165
166 #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
167 if (FAILURE == PHP_MINIT(sodium_password_hash)(INIT_FUNC_ARGS_PASSTHRU)) {
168 return FAILURE;
169 }
170 #endif
171
172 register_libsodium_symbols(module_number);
173
174 return SUCCESS;
175 }
176
PHP_MSHUTDOWN_FUNCTION(sodium)177 PHP_MSHUTDOWN_FUNCTION(sodium)
178 {
179 randombytes_close();
180 return SUCCESS;
181 }
182
PHP_MINFO_FUNCTION(sodium)183 PHP_MINFO_FUNCTION(sodium)
184 {
185 php_info_print_table_start();
186 php_info_print_table_row(2, "sodium support", "enabled");
187 php_info_print_table_row(2, "libsodium headers version", SODIUM_VERSION_STRING);
188 php_info_print_table_row(2, "libsodium library version", sodium_version_string());
189 php_info_print_table_end();
190 }
191
PHP_FUNCTION(sodium_memzero)192 PHP_FUNCTION(sodium_memzero)
193 {
194 zval *buf_zv;
195
196 if (zend_parse_parameters(ZEND_NUM_ARGS(),
197 "z", &buf_zv) == FAILURE) {
198 sodium_remove_param_values_from_backtrace(EG(exception));
199 RETURN_THROWS();
200 }
201 ZVAL_DEREF(buf_zv);
202 if (Z_TYPE_P(buf_zv) != IS_STRING) {
203 zend_throw_exception(sodium_exception_ce, "a PHP string is required", 0);
204 RETURN_THROWS();
205 }
206 if (Z_REFCOUNTED_P(buf_zv) && Z_REFCOUNT_P(buf_zv) == 1) {
207 char *buf = Z_STRVAL(*buf_zv);
208 size_t buf_len = Z_STRLEN(*buf_zv);
209 if (buf_len > 0) {
210 sodium_memzero(buf, (size_t) buf_len);
211 }
212 }
213 convert_to_null(buf_zv);
214 }
215
PHP_FUNCTION(sodium_increment)216 PHP_FUNCTION(sodium_increment)
217 {
218 zval *val_zv;
219 unsigned char *val;
220 size_t val_len;
221
222 if (zend_parse_parameters(ZEND_NUM_ARGS(),
223 "z", &val_zv) == FAILURE) {
224 sodium_remove_param_values_from_backtrace(EG(exception));
225 RETURN_THROWS();
226 }
227 ZVAL_DEREF(val_zv);
228 if (Z_TYPE_P(val_zv) != IS_STRING) {
229 zend_throw_exception(sodium_exception_ce, "a PHP string is required", 0);
230 RETURN_THROWS();
231 }
232
233 sodium_separate_string(val_zv);
234 val = (unsigned char *) Z_STRVAL(*val_zv);
235 val_len = Z_STRLEN(*val_zv);
236 sodium_increment(val, val_len);
237 }
238
PHP_FUNCTION(sodium_add)239 PHP_FUNCTION(sodium_add)
240 {
241 zval *val_zv;
242 unsigned char *val;
243 unsigned char *addv;
244 size_t val_len;
245 size_t addv_len;
246
247 if (zend_parse_parameters(ZEND_NUM_ARGS(),
248 "zs", &val_zv, &addv, &addv_len) == FAILURE) {
249 sodium_remove_param_values_from_backtrace(EG(exception));
250 RETURN_THROWS();
251 }
252 ZVAL_DEREF(val_zv);
253 if (Z_TYPE_P(val_zv) != IS_STRING) {
254 zend_throw_exception(sodium_exception_ce, "PHP strings are required", 0);
255 RETURN_THROWS();
256 }
257
258 sodium_separate_string(val_zv);
259 val = (unsigned char *) Z_STRVAL(*val_zv);
260 val_len = Z_STRLEN(*val_zv);
261 if (val_len != addv_len) {
262 zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
263 RETURN_THROWS();
264 }
265 sodium_add(val, addv, val_len);
266 }
267
PHP_FUNCTION(sodium_memcmp)268 PHP_FUNCTION(sodium_memcmp)
269 {
270 char *buf1;
271 char *buf2;
272 size_t len1;
273 size_t len2;
274
275 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
276 &buf1, &len1,
277 &buf2, &len2) == FAILURE) {
278 sodium_remove_param_values_from_backtrace(EG(exception));
279 RETURN_THROWS();
280 }
281 if (len1 != len2) {
282 zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
283 RETURN_THROWS();
284 }
285 RETURN_LONG(sodium_memcmp(buf1, buf2, len1));
286 }
287
PHP_FUNCTION(sodium_crypto_shorthash)288 PHP_FUNCTION(sodium_crypto_shorthash)
289 {
290 zend_string *hash;
291 unsigned char *key;
292 unsigned char *msg;
293 size_t key_len;
294 size_t msg_len;
295
296 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
297 &msg, &msg_len,
298 &key, &key_len) == FAILURE) {
299 sodium_remove_param_values_from_backtrace(EG(exception));
300 RETURN_THROWS();
301 }
302 if (key_len != crypto_shorthash_KEYBYTES) {
303 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SHORTHASH_KEYBYTES bytes long");
304 RETURN_THROWS();
305 }
306 hash = zend_string_alloc(crypto_shorthash_BYTES, 0);
307 if (crypto_shorthash((unsigned char *) ZSTR_VAL(hash), msg,
308 (unsigned long long) msg_len, key) != 0) {
309 zend_string_efree(hash);
310 zend_throw_exception(sodium_exception_ce, "internal error", 0);
311 RETURN_THROWS();
312 }
313 ZSTR_VAL(hash)[crypto_shorthash_BYTES] = 0;
314
315 RETURN_NEW_STR(hash);
316 }
317
PHP_FUNCTION(sodium_crypto_secretbox)318 PHP_FUNCTION(sodium_crypto_secretbox)
319 {
320 zend_string *ciphertext;
321 unsigned char *key;
322 unsigned char *msg;
323 unsigned char *nonce;
324 size_t key_len;
325 size_t msg_len;
326 size_t nonce_len;
327
328 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
329 &msg, &msg_len,
330 &nonce, &nonce_len,
331 &key, &key_len) == FAILURE) {
332 sodium_remove_param_values_from_backtrace(EG(exception));
333 RETURN_THROWS();
334 }
335 if (nonce_len != crypto_secretbox_NONCEBYTES) {
336 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETBOX_NONCEBYTES bytes long");
337 RETURN_THROWS();
338 }
339 if (key_len != crypto_secretbox_KEYBYTES) {
340 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long");
341 RETURN_THROWS();
342 }
343 if (SIZE_MAX - msg_len <= crypto_secretbox_MACBYTES) {
344 zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
345 RETURN_THROWS();
346 }
347 ciphertext = zend_string_alloc((size_t) msg_len + crypto_secretbox_MACBYTES, 0);
348 if (crypto_secretbox_easy((unsigned char *) ZSTR_VAL(ciphertext),
349 msg, (unsigned long long) msg_len,
350 nonce, key) != 0) {
351 zend_string_efree(ciphertext);
352 zend_throw_exception(sodium_exception_ce, "internal error", 0);
353 RETURN_THROWS();
354 }
355 ZSTR_VAL(ciphertext)[msg_len + crypto_secretbox_MACBYTES] = 0;
356
357 RETURN_NEW_STR(ciphertext);
358 }
359
PHP_FUNCTION(sodium_crypto_secretbox_open)360 PHP_FUNCTION(sodium_crypto_secretbox_open)
361 {
362 zend_string *msg;
363 unsigned char *key;
364 unsigned char *ciphertext;
365 unsigned char *nonce;
366 size_t key_len;
367 size_t ciphertext_len;
368 size_t nonce_len;
369
370 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
371 &ciphertext, &ciphertext_len,
372 &nonce, &nonce_len,
373 &key, &key_len) == FAILURE) {
374 sodium_remove_param_values_from_backtrace(EG(exception));
375 RETURN_THROWS();
376 }
377 if (nonce_len != crypto_secretbox_NONCEBYTES) {
378 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETBOX_NONCEBYTES bytes long");
379 RETURN_THROWS();
380 }
381 if (key_len != crypto_secretbox_KEYBYTES) {
382 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long");
383 RETURN_THROWS();
384 }
385 if (ciphertext_len < crypto_secretbox_MACBYTES) {
386 RETURN_FALSE;
387 }
388 msg = zend_string_alloc
389 ((size_t) ciphertext_len - crypto_secretbox_MACBYTES, 0);
390 if (crypto_secretbox_open_easy((unsigned char *) ZSTR_VAL(msg), ciphertext,
391 (unsigned long long) ciphertext_len,
392 nonce, key) != 0) {
393 zend_string_efree(msg);
394 RETURN_FALSE;
395 } else {
396 ZSTR_VAL(msg)[ciphertext_len - crypto_secretbox_MACBYTES] = 0;
397 RETURN_NEW_STR(msg);
398 }
399 }
400
PHP_FUNCTION(sodium_crypto_generichash)401 PHP_FUNCTION(sodium_crypto_generichash)
402 {
403 zend_string *hash;
404 unsigned char *key = NULL;
405 unsigned char *msg;
406 zend_long hash_len = crypto_generichash_BYTES;
407 size_t key_len = 0;
408 size_t msg_len;
409
410 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl",
411 &msg, &msg_len,
412 &key, &key_len,
413 &hash_len) == FAILURE) {
414 sodium_remove_param_values_from_backtrace(EG(exception));
415 RETURN_THROWS();
416 }
417 if (hash_len < crypto_generichash_BYTES_MIN ||
418 hash_len > crypto_generichash_BYTES_MAX) {
419 zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
420 RETURN_THROWS();
421 }
422 if (key_len != 0 &&
423 (key_len < crypto_generichash_KEYBYTES_MIN ||
424 key_len > crypto_generichash_KEYBYTES_MAX)) {
425 zend_throw_exception(sodium_exception_ce, "unsupported key length", 0);
426 RETURN_THROWS();
427 }
428 hash = zend_string_alloc(hash_len, 0);
429 if (crypto_generichash((unsigned char *) ZSTR_VAL(hash), (size_t) hash_len,
430 msg, (unsigned long long) msg_len,
431 key, (size_t) key_len) != 0) {
432 zend_string_efree(hash);
433 zend_throw_exception(sodium_exception_ce, "internal error", 0);
434 RETURN_THROWS();
435 }
436 ZSTR_VAL(hash)[hash_len] = 0;
437
438 RETURN_NEW_STR(hash);
439 }
440
PHP_FUNCTION(sodium_crypto_generichash_init)441 PHP_FUNCTION(sodium_crypto_generichash_init)
442 {
443 crypto_generichash_state state_tmp;
444 zend_string *state;
445 unsigned char *key = NULL;
446 size_t state_len = sizeof (crypto_generichash_state);
447 zend_long hash_len = crypto_generichash_BYTES;
448 size_t key_len = 0;
449
450 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sl",
451 &key, &key_len,
452 &hash_len) == FAILURE) {
453 sodium_remove_param_values_from_backtrace(EG(exception));
454 RETURN_THROWS();
455 }
456 if (hash_len < crypto_generichash_BYTES_MIN ||
457 hash_len > crypto_generichash_BYTES_MAX) {
458 zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
459 RETURN_THROWS();
460 }
461 if (key_len != 0 &&
462 (key_len < crypto_generichash_KEYBYTES_MIN ||
463 key_len > crypto_generichash_KEYBYTES_MAX)) {
464 zend_throw_exception(sodium_exception_ce, "unsupported key length", 0);
465 RETURN_THROWS();
466 }
467 memset(&state_tmp, 0, sizeof state_tmp);
468 if (crypto_generichash_init((void *) &state_tmp, key, (size_t) key_len,
469 (size_t) hash_len) != 0) {
470 zend_throw_exception(sodium_exception_ce, "internal error", 0);
471 RETURN_THROWS();
472 }
473 state = zend_string_alloc(state_len, 0);
474 memcpy(ZSTR_VAL(state), &state_tmp, state_len);
475 sodium_memzero(&state_tmp, sizeof state_tmp);
476 ZSTR_VAL(state)[state_len] = 0;
477
478 RETURN_STR(state);
479 }
480
PHP_FUNCTION(sodium_crypto_generichash_update)481 PHP_FUNCTION(sodium_crypto_generichash_update)
482 {
483 crypto_generichash_state state_tmp;
484 zval *state_zv;
485 unsigned char *msg;
486 unsigned char *state;
487 size_t msg_len;
488 size_t state_len;
489
490 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs",
491 &state_zv, &msg, &msg_len) == FAILURE) {
492 sodium_remove_param_values_from_backtrace(EG(exception));
493 RETURN_THROWS();
494 }
495 ZVAL_DEREF(state_zv);
496 if (Z_TYPE_P(state_zv) != IS_STRING) {
497 zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
498 RETURN_THROWS();
499 }
500 sodium_separate_string(state_zv);
501 state = (unsigned char *) Z_STRVAL(*state_zv);
502 state_len = Z_STRLEN(*state_zv);
503 if (state_len != sizeof (crypto_generichash_state)) {
504 zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
505 RETURN_THROWS();
506 }
507 memcpy(&state_tmp, state, sizeof state_tmp);
508 if (crypto_generichash_update((void *) &state_tmp, msg,
509 (unsigned long long) msg_len) != 0) {
510 sodium_memzero(&state_tmp, sizeof state_tmp);
511 zend_throw_exception(sodium_exception_ce, "internal error", 0);
512 RETURN_THROWS();
513 }
514 memcpy(state, &state_tmp, state_len);
515 sodium_memzero(&state_tmp, sizeof state_tmp);
516
517 RETURN_TRUE;
518 }
519
PHP_FUNCTION(sodium_crypto_generichash_final)520 PHP_FUNCTION(sodium_crypto_generichash_final)
521 {
522 crypto_generichash_state state_tmp;
523 zend_string *hash;
524 zval *state_zv;
525 unsigned char *state;
526 size_t state_len;
527 zend_long hash_len = crypto_generichash_BYTES;
528
529 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l",
530 &state_zv, &hash_len) == FAILURE) {
531 sodium_remove_param_values_from_backtrace(EG(exception));
532 RETURN_THROWS();
533 }
534 ZVAL_DEREF(state_zv);
535 if (Z_TYPE_P(state_zv) != IS_STRING) {
536 zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
537 RETURN_THROWS();
538 }
539 sodium_separate_string(state_zv);
540 state = (unsigned char *) Z_STRVAL(*state_zv);
541 state_len = Z_STRLEN(*state_zv);
542 if (state_len != sizeof (crypto_generichash_state)) {
543 zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
544 RETURN_THROWS();
545 }
546 if (hash_len < crypto_generichash_BYTES_MIN ||
547 hash_len > crypto_generichash_BYTES_MAX) {
548 zend_throw_exception(sodium_exception_ce, "unsupported output length", 0);
549 RETURN_THROWS();
550 }
551 hash = zend_string_alloc(hash_len, 0);
552 memcpy(&state_tmp, state, sizeof state_tmp);
553 if (crypto_generichash_final((void *) &state_tmp,
554 (unsigned char *) ZSTR_VAL(hash),
555 (size_t) hash_len) != 0) {
556 sodium_memzero(&state_tmp, sizeof state_tmp);
557 zend_string_efree(hash);
558 zend_throw_exception(sodium_exception_ce, "internal error", 0);
559 RETURN_THROWS();
560 }
561 sodium_memzero(&state_tmp, sizeof state_tmp);
562 sodium_memzero(state, state_len);
563 convert_to_null(state_zv);
564 ZSTR_VAL(hash)[hash_len] = 0;
565
566 RETURN_NEW_STR(hash);
567 }
568
PHP_FUNCTION(sodium_crypto_box_keypair)569 PHP_FUNCTION(sodium_crypto_box_keypair)
570 {
571 zend_string *keypair;
572 size_t keypair_len;
573
574 if (zend_parse_parameters_none() == FAILURE) {
575 RETURN_THROWS();
576 }
577 keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
578 keypair = zend_string_alloc(keypair_len, 0);
579 if (crypto_box_keypair((unsigned char *) ZSTR_VAL(keypair) +
580 crypto_box_SECRETKEYBYTES,
581 (unsigned char *) ZSTR_VAL(keypair)) != 0) {
582 zend_string_efree(keypair);
583 zend_throw_exception(sodium_exception_ce, "internal error", 0);
584 RETURN_THROWS();
585 }
586 ZSTR_VAL(keypair)[keypair_len] = 0;
587
588 RETURN_NEW_STR(keypair);
589 }
590
PHP_FUNCTION(sodium_crypto_box_seed_keypair)591 PHP_FUNCTION(sodium_crypto_box_seed_keypair)
592 {
593 zend_string *keypair;
594 unsigned char *seed;
595 size_t keypair_len;
596 size_t seed_len;
597
598 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
599 &seed, &seed_len) == FAILURE) {
600 sodium_remove_param_values_from_backtrace(EG(exception));
601 RETURN_THROWS();
602 }
603 if (seed_len != crypto_box_SEEDBYTES) {
604 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SEEDBYTES bytes long");
605 RETURN_THROWS();
606 }
607 keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
608 keypair = zend_string_alloc(keypair_len, 0);
609 if (crypto_box_seed_keypair((unsigned char *) ZSTR_VAL(keypair) +
610 crypto_box_SECRETKEYBYTES,
611 (unsigned char *) ZSTR_VAL(keypair),
612 seed) != 0) {
613 zend_string_efree(keypair);
614 zend_throw_exception(sodium_exception_ce, "internal error", 0);
615 RETURN_THROWS();
616 }
617 ZSTR_VAL(keypair)[keypair_len] = 0;
618
619 RETURN_NEW_STR(keypair);
620 }
621
PHP_FUNCTION(sodium_crypto_box_keypair_from_secretkey_and_publickey)622 PHP_FUNCTION(sodium_crypto_box_keypair_from_secretkey_and_publickey)
623 {
624 zend_string *keypair;
625 char *publickey;
626 char *secretkey;
627 size_t keypair_len;
628 size_t publickey_len;
629 size_t secretkey_len;
630
631 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
632 &secretkey, &secretkey_len,
633 &publickey, &publickey_len) == FAILURE) {
634 sodium_remove_param_values_from_backtrace(EG(exception));
635 RETURN_THROWS();
636 }
637 if (secretkey_len != crypto_box_SECRETKEYBYTES) {
638 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SECRETKEYBYTES bytes long");
639 RETURN_THROWS();
640 }
641 if (publickey_len != crypto_box_PUBLICKEYBYTES) {
642 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_PUBLICKEYBYTES bytes long");
643 RETURN_THROWS();
644 }
645 keypair_len = crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES;
646 keypair = zend_string_alloc(keypair_len, 0);
647 memcpy(ZSTR_VAL(keypair), secretkey, crypto_box_SECRETKEYBYTES);
648 memcpy(ZSTR_VAL(keypair) + crypto_box_SECRETKEYBYTES, publickey,
649 crypto_box_PUBLICKEYBYTES);
650 ZSTR_VAL(keypair)[keypair_len] = 0;
651
652 RETURN_STR(keypair);
653 }
654
PHP_FUNCTION(sodium_crypto_box_secretkey)655 PHP_FUNCTION(sodium_crypto_box_secretkey)
656 {
657 zend_string *secretkey;
658 unsigned char *keypair;
659 size_t keypair_len;
660
661 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
662 &keypair, &keypair_len) == FAILURE) {
663 sodium_remove_param_values_from_backtrace(EG(exception));
664 RETURN_THROWS();
665 }
666 if (keypair_len !=
667 crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
668 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
669 RETURN_THROWS();
670 }
671 secretkey = zend_string_alloc(crypto_box_SECRETKEYBYTES, 0);
672 memcpy(ZSTR_VAL(secretkey), keypair, crypto_box_SECRETKEYBYTES);
673 ZSTR_VAL(secretkey)[crypto_box_SECRETKEYBYTES] = 0;
674
675 RETURN_STR(secretkey);
676 }
677
PHP_FUNCTION(sodium_crypto_box_publickey)678 PHP_FUNCTION(sodium_crypto_box_publickey)
679 {
680 zend_string *publickey;
681 unsigned char *keypair;
682 size_t keypair_len;
683
684 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
685 &keypair, &keypair_len) == FAILURE) {
686 sodium_remove_param_values_from_backtrace(EG(exception));
687 RETURN_THROWS();
688 }
689 if (keypair_len !=
690 crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
691 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
692 RETURN_THROWS();
693 }
694 publickey = zend_string_alloc(crypto_box_PUBLICKEYBYTES, 0);
695 memcpy(ZSTR_VAL(publickey), keypair + crypto_box_SECRETKEYBYTES,
696 crypto_box_PUBLICKEYBYTES);
697 ZSTR_VAL(publickey)[crypto_box_PUBLICKEYBYTES] = 0;
698
699 RETURN_STR(publickey);
700 }
701
PHP_FUNCTION(sodium_crypto_box_publickey_from_secretkey)702 PHP_FUNCTION(sodium_crypto_box_publickey_from_secretkey)
703 {
704 zend_string *publickey;
705 unsigned char *secretkey;
706 size_t secretkey_len;
707
708 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
709 &secretkey, &secretkey_len) == FAILURE) {
710 sodium_remove_param_values_from_backtrace(EG(exception));
711 RETURN_THROWS();
712 }
713 if (secretkey_len != crypto_box_SECRETKEYBYTES) {
714 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_BOX_SECRETKEYBYTES bytes long");
715 RETURN_THROWS();
716 }
717 publickey = zend_string_alloc(crypto_box_PUBLICKEYBYTES, 0);
718 (void) sizeof(int[crypto_scalarmult_BYTES ==
719 crypto_box_PUBLICKEYBYTES ? 1 : -1]);
720 (void) sizeof(int[crypto_scalarmult_SCALARBYTES ==
721 crypto_box_SECRETKEYBYTES ? 1 : -1]);
722 crypto_scalarmult_base((unsigned char *) ZSTR_VAL(publickey), secretkey);
723 ZSTR_VAL(publickey)[crypto_box_PUBLICKEYBYTES] = 0;
724
725 RETURN_STR(publickey);
726 }
727
PHP_FUNCTION(sodium_crypto_box)728 PHP_FUNCTION(sodium_crypto_box)
729 {
730 zend_string *ciphertext;
731 unsigned char *keypair;
732 unsigned char *msg;
733 unsigned char *nonce;
734 unsigned char *publickey;
735 unsigned char *secretkey;
736 size_t keypair_len;
737 size_t msg_len;
738 size_t nonce_len;
739
740 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
741 &msg, &msg_len,
742 &nonce, &nonce_len,
743 &keypair, &keypair_len) == FAILURE) {
744 sodium_remove_param_values_from_backtrace(EG(exception));
745 RETURN_THROWS();
746 }
747 if (nonce_len != crypto_box_NONCEBYTES) {
748 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_NONCEBYTES bytes long");
749 RETURN_THROWS();
750 }
751 if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
752 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
753 RETURN_THROWS();
754 }
755 secretkey = keypair;
756 publickey = keypair + crypto_box_SECRETKEYBYTES;
757 if (SIZE_MAX - msg_len <= crypto_box_MACBYTES) {
758 zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
759 RETURN_THROWS();
760 }
761 ciphertext = zend_string_alloc((size_t) msg_len + crypto_box_MACBYTES, 0);
762 if (crypto_box_easy((unsigned char *) ZSTR_VAL(ciphertext), msg,
763 (unsigned long long) msg_len,
764 nonce, publickey, secretkey) != 0) {
765 zend_string_efree(ciphertext);
766 zend_throw_exception(sodium_exception_ce, "internal error", 0);
767 RETURN_THROWS();
768 }
769 ZSTR_VAL(ciphertext)[msg_len + crypto_box_MACBYTES] = 0;
770
771 RETURN_NEW_STR(ciphertext);
772 }
773
PHP_FUNCTION(sodium_crypto_box_open)774 PHP_FUNCTION(sodium_crypto_box_open)
775 {
776 zend_string *msg;
777 unsigned char *ciphertext;
778 unsigned char *keypair;
779 unsigned char *nonce;
780 unsigned char *publickey;
781 unsigned char *secretkey;
782 size_t ciphertext_len;
783 size_t keypair_len;
784 size_t nonce_len;
785
786 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
787 &ciphertext, &ciphertext_len,
788 &nonce, &nonce_len,
789 &keypair, &keypair_len) == FAILURE) {
790 sodium_remove_param_values_from_backtrace(EG(exception));
791 RETURN_THROWS();
792 }
793 if (nonce_len != crypto_box_NONCEBYTES) {
794 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_NONCEBYTES bytes long");
795 RETURN_THROWS();
796 }
797 if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
798 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
799 RETURN_THROWS();
800 }
801 secretkey = keypair;
802 publickey = keypair + crypto_box_SECRETKEYBYTES;
803 if (ciphertext_len < crypto_box_MACBYTES) {
804 RETURN_FALSE;
805 }
806 msg = zend_string_alloc((size_t) ciphertext_len - crypto_box_MACBYTES, 0);
807 if (crypto_box_open_easy((unsigned char *) ZSTR_VAL(msg), ciphertext,
808 (unsigned long long) ciphertext_len,
809 nonce, publickey, secretkey) != 0) {
810 zend_string_efree(msg);
811 RETURN_FALSE;
812 } else {
813 ZSTR_VAL(msg)[ciphertext_len - crypto_box_MACBYTES] = 0;
814 RETURN_NEW_STR(msg);
815 }
816 }
817
PHP_FUNCTION(sodium_crypto_box_seal)818 PHP_FUNCTION(sodium_crypto_box_seal)
819 {
820 zend_string *ciphertext;
821 unsigned char *msg;
822 unsigned char *publickey;
823 size_t msg_len;
824 size_t publickey_len;
825
826 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
827 &msg, &msg_len,
828 &publickey, &publickey_len) == FAILURE) {
829 sodium_remove_param_values_from_backtrace(EG(exception));
830 RETURN_THROWS();
831 }
832 if (publickey_len != crypto_box_PUBLICKEYBYTES) {
833 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_PUBLICKEYBYTES bytes long");
834 RETURN_THROWS();
835 }
836 if (SIZE_MAX - msg_len <= crypto_box_SEALBYTES) {
837 zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
838 RETURN_THROWS();
839 }
840 ciphertext = zend_string_alloc((size_t) msg_len + crypto_box_SEALBYTES, 0);
841 if (crypto_box_seal((unsigned char *) ZSTR_VAL(ciphertext), msg,
842 (unsigned long long) msg_len, publickey) != 0) {
843 zend_string_efree(ciphertext);
844 zend_throw_exception(sodium_exception_ce, "internal error", 0);
845 RETURN_THROWS();
846 }
847 ZSTR_VAL(ciphertext)[msg_len + crypto_box_SEALBYTES] = 0;
848
849 RETURN_NEW_STR(ciphertext);
850 }
851
PHP_FUNCTION(sodium_crypto_box_seal_open)852 PHP_FUNCTION(sodium_crypto_box_seal_open)
853 {
854 zend_string *msg;
855 unsigned char *ciphertext;
856 unsigned char *keypair;
857 unsigned char *publickey;
858 unsigned char *secretkey;
859 size_t ciphertext_len;
860 size_t keypair_len;
861
862 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
863 &ciphertext, &ciphertext_len,
864 &keypair, &keypair_len) == FAILURE) {
865 sodium_remove_param_values_from_backtrace(EG(exception));
866 RETURN_THROWS();
867 }
868 if (keypair_len != crypto_box_SECRETKEYBYTES + crypto_box_PUBLICKEYBYTES) {
869 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes long");
870 RETURN_THROWS();
871 }
872 secretkey = keypair;
873 publickey = keypair + crypto_box_SECRETKEYBYTES;
874 if (ciphertext_len < crypto_box_SEALBYTES) {
875 RETURN_FALSE;
876 }
877 msg = zend_string_alloc((size_t) ciphertext_len - crypto_box_SEALBYTES, 0);
878 if (crypto_box_seal_open((unsigned char *) ZSTR_VAL(msg), ciphertext,
879 (unsigned long long) ciphertext_len,
880 publickey, secretkey) != 0) {
881 zend_string_efree(msg);
882 RETURN_FALSE;
883 } else {
884 ZSTR_VAL(msg)[ciphertext_len - crypto_box_SEALBYTES] = 0;
885 RETURN_NEW_STR(msg);
886 }
887 }
888
PHP_FUNCTION(sodium_crypto_sign_keypair)889 PHP_FUNCTION(sodium_crypto_sign_keypair)
890 {
891 zend_string *keypair;
892 size_t keypair_len;
893
894 if (zend_parse_parameters_none() == FAILURE) {
895 RETURN_THROWS();
896 }
897 keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
898 keypair = zend_string_alloc(keypair_len, 0);
899 if (crypto_sign_keypair((unsigned char *) ZSTR_VAL(keypair) +
900 crypto_sign_SECRETKEYBYTES,
901 (unsigned char *) ZSTR_VAL(keypair)) != 0) {
902 zend_string_efree(keypair);
903 zend_throw_exception(sodium_exception_ce, "internal error", 0);
904 RETURN_THROWS();
905 }
906 ZSTR_VAL(keypair)[keypair_len] = 0;
907
908 RETURN_NEW_STR(keypair);
909 }
910
PHP_FUNCTION(sodium_crypto_sign_seed_keypair)911 PHP_FUNCTION(sodium_crypto_sign_seed_keypair)
912 {
913 zend_string *keypair;
914 unsigned char *seed;
915 size_t keypair_len;
916 size_t seed_len;
917
918 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
919 &seed, &seed_len) == FAILURE) {
920 sodium_remove_param_values_from_backtrace(EG(exception));
921 RETURN_THROWS();
922 }
923 if (seed_len != crypto_sign_SEEDBYTES) {
924 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SEEDBYTES bytes long");
925 RETURN_THROWS();
926 }
927 keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
928 keypair = zend_string_alloc(keypair_len, 0);
929 if (crypto_sign_seed_keypair((unsigned char *) ZSTR_VAL(keypair) +
930 crypto_sign_SECRETKEYBYTES,
931 (unsigned char *) ZSTR_VAL(keypair),
932 seed) != 0) {
933 zend_string_efree(keypair);
934 zend_throw_exception(sodium_exception_ce, "internal error", 0);
935 RETURN_THROWS();
936 }
937 ZSTR_VAL(keypair)[keypair_len] = 0;
938
939 RETURN_NEW_STR(keypair);
940 }
941
PHP_FUNCTION(sodium_crypto_sign_keypair_from_secretkey_and_publickey)942 PHP_FUNCTION(sodium_crypto_sign_keypair_from_secretkey_and_publickey)
943 {
944 zend_string *keypair;
945 char *publickey;
946 char *secretkey;
947 size_t keypair_len;
948 size_t publickey_len;
949 size_t secretkey_len;
950
951 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
952 &secretkey, &secretkey_len,
953 &publickey, &publickey_len) == FAILURE) {
954 sodium_remove_param_values_from_backtrace(EG(exception));
955 RETURN_THROWS();
956 }
957 if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
958 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
959 RETURN_THROWS();
960 }
961 if (publickey_len != crypto_sign_PUBLICKEYBYTES) {
962 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
963 RETURN_THROWS();
964 }
965 keypair_len = crypto_sign_SECRETKEYBYTES + crypto_sign_PUBLICKEYBYTES;
966 keypair = zend_string_alloc(keypair_len, 0);
967 memcpy(ZSTR_VAL(keypair), secretkey, crypto_sign_SECRETKEYBYTES);
968 memcpy(ZSTR_VAL(keypair) + crypto_sign_SECRETKEYBYTES, publickey,
969 crypto_sign_PUBLICKEYBYTES);
970 ZSTR_VAL(keypair)[keypair_len] = 0;
971
972 RETURN_STR(keypair);
973 }
974
PHP_FUNCTION(sodium_crypto_sign_publickey_from_secretkey)975 PHP_FUNCTION(sodium_crypto_sign_publickey_from_secretkey)
976 {
977 zend_string *publickey;
978 char *secretkey;
979 size_t secretkey_len;
980
981 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
982 &secretkey, &secretkey_len) == FAILURE) {
983 sodium_remove_param_values_from_backtrace(EG(exception));
984 RETURN_THROWS();
985 }
986 if (secretkey_len != crypto_sign_SECRETKEYBYTES) {
987 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
988 RETURN_THROWS();
989 }
990 publickey = zend_string_alloc(crypto_sign_PUBLICKEYBYTES, 0);
991
992 if (crypto_sign_ed25519_sk_to_pk((unsigned char *) ZSTR_VAL(publickey),
993 (const unsigned char *) secretkey) != 0) {
994 zend_string_efree(publickey);
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_string_efree(keypair);
2709 zend_throw_exception(sodium_exception_ce, "internal error", 0);
2710 RETURN_THROWS();
2711 }
2712 ZSTR_VAL(keypair)[crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES] = 0;
2713 RETURN_STR(keypair);
2714 }
2715
PHP_FUNCTION(sodium_crypto_kx_keypair)2716 PHP_FUNCTION(sodium_crypto_kx_keypair)
2717 {
2718 unsigned char *sk;
2719 unsigned char *pk;
2720 zend_string *keypair;
2721
2722 if (zend_parse_parameters_none() == FAILURE) {
2723 RETURN_THROWS();
2724 }
2725 keypair = zend_string_alloc(crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, 0);
2726 sk = (unsigned char *) ZSTR_VAL(keypair);
2727 pk = sk + crypto_kx_SECRETKEYBYTES;
2728 randombytes_buf(sk, crypto_kx_SECRETKEYBYTES);
2729 if (crypto_scalarmult_base(pk, sk) != 0) {
2730 zend_string_efree(keypair);
2731 zend_throw_exception(sodium_exception_ce, "internal error", 0);
2732 RETURN_THROWS();
2733 }
2734 ZSTR_VAL(keypair)[crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES] = 0;
2735 RETURN_STR(keypair);
2736 }
2737
PHP_FUNCTION(sodium_crypto_kx_secretkey)2738 PHP_FUNCTION(sodium_crypto_kx_secretkey)
2739 {
2740 zend_string *secretkey;
2741 unsigned char *keypair;
2742 size_t keypair_len;
2743
2744 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
2745 &keypair, &keypair_len) == FAILURE) {
2746 sodium_remove_param_values_from_backtrace(EG(exception));
2747 RETURN_THROWS();
2748 }
2749 if (keypair_len !=
2750 crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
2751 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
2752 RETURN_THROWS();
2753 }
2754 secretkey = zend_string_alloc(crypto_kx_SECRETKEYBYTES, 0);
2755 memcpy(ZSTR_VAL(secretkey), keypair, crypto_kx_SECRETKEYBYTES);
2756 ZSTR_VAL(secretkey)[crypto_kx_SECRETKEYBYTES] = 0;
2757
2758 RETURN_STR(secretkey);
2759 }
2760
PHP_FUNCTION(sodium_crypto_kx_publickey)2761 PHP_FUNCTION(sodium_crypto_kx_publickey)
2762 {
2763 zend_string *publickey;
2764 unsigned char *keypair;
2765 size_t keypair_len;
2766
2767 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
2768 &keypair, &keypair_len) == FAILURE) {
2769 sodium_remove_param_values_from_backtrace(EG(exception));
2770 RETURN_THROWS();
2771 }
2772 if (keypair_len !=
2773 crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
2774 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
2775 RETURN_THROWS();
2776 }
2777 publickey = zend_string_alloc(crypto_kx_PUBLICKEYBYTES, 0);
2778 memcpy(ZSTR_VAL(publickey), keypair + crypto_kx_SECRETKEYBYTES,
2779 crypto_kx_PUBLICKEYBYTES);
2780 ZSTR_VAL(publickey)[crypto_kx_PUBLICKEYBYTES] = 0;
2781
2782 RETURN_STR(publickey);
2783 }
2784
PHP_FUNCTION(sodium_crypto_kx_client_session_keys)2785 PHP_FUNCTION(sodium_crypto_kx_client_session_keys)
2786 {
2787 crypto_generichash_state h;
2788 unsigned char q[crypto_scalarmult_BYTES];
2789 unsigned char *keypair;
2790 unsigned char *client_sk;
2791 unsigned char *client_pk;
2792 unsigned char *server_pk;
2793 unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
2794 size_t keypair_len;
2795 size_t server_pk_len;
2796
2797 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
2798 &keypair, &keypair_len,
2799 &server_pk, &server_pk_len) == FAILURE) {
2800 sodium_remove_param_values_from_backtrace(EG(exception));
2801 RETURN_THROWS();
2802 }
2803 if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
2804 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
2805 RETURN_THROWS();
2806 }
2807 if (server_pk_len != crypto_kx_PUBLICKEYBYTES) {
2808 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes long");
2809 RETURN_THROWS();
2810 }
2811 client_sk = &keypair[0];
2812 client_pk = &keypair[crypto_kx_SECRETKEYBYTES];
2813 (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
2814 (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
2815 if (crypto_scalarmult(q, client_sk, server_pk) != 0) {
2816 zend_throw_exception(sodium_exception_ce, "internal error", 0);
2817 RETURN_THROWS();
2818 }
2819 crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
2820 crypto_generichash_update(&h, q, sizeof q);
2821 sodium_memzero(q, sizeof q);
2822 crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
2823 crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
2824 crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
2825 sodium_memzero(&h, sizeof h);
2826 array_init(return_value);
2827 add_next_index_stringl(return_value,
2828 (const char *) session_keys,
2829 crypto_kx_SESSIONKEYBYTES);
2830 add_next_index_stringl(return_value,
2831 (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
2832 crypto_kx_SESSIONKEYBYTES);
2833 }
2834
PHP_FUNCTION(sodium_crypto_kx_server_session_keys)2835 PHP_FUNCTION(sodium_crypto_kx_server_session_keys)
2836 {
2837 crypto_generichash_state h;
2838 unsigned char q[crypto_scalarmult_BYTES];
2839 unsigned char *keypair;
2840 unsigned char *server_sk;
2841 unsigned char *server_pk;
2842 unsigned char *client_pk;
2843 unsigned char session_keys[2 * crypto_kx_SESSIONKEYBYTES];
2844 size_t keypair_len;
2845 size_t client_pk_len;
2846
2847 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
2848 &keypair, &keypair_len,
2849 &client_pk, &client_pk_len) == FAILURE) {
2850 sodium_remove_param_values_from_backtrace(EG(exception));
2851 RETURN_THROWS();
2852 }
2853 if (keypair_len != crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES) {
2854 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes long");
2855 RETURN_THROWS();
2856 }
2857 if (client_pk_len != crypto_kx_PUBLICKEYBYTES) {
2858 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes long");
2859 RETURN_THROWS();
2860 }
2861 server_sk = &keypair[0];
2862 server_pk = &keypair[crypto_kx_SECRETKEYBYTES];
2863 (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_PUBLICKEYBYTES ? 1 : -1]);
2864 (void) sizeof(int[crypto_scalarmult_SCALARBYTES == crypto_kx_SECRETKEYBYTES ? 1 : -1]);
2865 if (crypto_scalarmult(q, server_sk, client_pk) != 0) {
2866 zend_throw_exception(sodium_exception_ce, "internal error", 0);
2867 RETURN_THROWS();
2868 }
2869 crypto_generichash_init(&h, NULL, 0U, 2 * crypto_kx_SESSIONKEYBYTES);
2870 crypto_generichash_update(&h, q, sizeof q);
2871 sodium_memzero(q, sizeof q);
2872 crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
2873 crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
2874 crypto_generichash_final(&h, session_keys, 2 * crypto_kx_SESSIONKEYBYTES);
2875 sodium_memzero(&h, sizeof h);
2876 array_init(return_value);
2877 add_next_index_stringl(return_value,
2878 (const char *) session_keys + crypto_kx_SESSIONKEYBYTES,
2879 crypto_kx_SESSIONKEYBYTES);
2880 add_next_index_stringl(return_value,
2881 (const char *) session_keys,
2882 crypto_kx_SESSIONKEYBYTES);
2883 }
2884
PHP_FUNCTION(sodium_crypto_auth)2885 PHP_FUNCTION(sodium_crypto_auth)
2886 {
2887 zend_string *mac;
2888 char *key;
2889 char *msg;
2890 size_t msg_len;
2891 size_t key_len;
2892
2893 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
2894 &msg, &msg_len,
2895 &key, &key_len) == FAILURE) {
2896 sodium_remove_param_values_from_backtrace(EG(exception));
2897 RETURN_THROWS();
2898 }
2899 if (key_len != crypto_auth_KEYBYTES) {
2900 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_AUTH_KEYBYTES bytes long");
2901 RETURN_THROWS();
2902 }
2903 mac = zend_string_alloc(crypto_auth_BYTES, 0);
2904 if (crypto_auth((unsigned char *) ZSTR_VAL(mac),
2905 (const unsigned char *) msg, msg_len,
2906 (const unsigned char *) key) != 0) {
2907 zend_string_efree(mac);
2908 zend_throw_exception(sodium_exception_ce, "internal error", 0);
2909 RETURN_THROWS();
2910 }
2911 ZSTR_VAL(mac)[crypto_auth_BYTES] = 0;
2912
2913 RETURN_STR(mac);
2914 }
2915
PHP_FUNCTION(sodium_crypto_auth_verify)2916 PHP_FUNCTION(sodium_crypto_auth_verify)
2917 {
2918 char *mac;
2919 char *key;
2920 char *msg;
2921 size_t mac_len;
2922 size_t msg_len;
2923 size_t key_len;
2924
2925 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
2926 &mac, &mac_len,
2927 &msg, &msg_len,
2928 &key, &key_len) == FAILURE) {
2929 sodium_remove_param_values_from_backtrace(EG(exception));
2930 RETURN_THROWS();
2931 }
2932 if (key_len != crypto_auth_KEYBYTES) {
2933 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AUTH_KEYBYTES bytes long");
2934 RETURN_THROWS();
2935 }
2936 if (mac_len != crypto_auth_BYTES) {
2937 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_AUTH_BYTES bytes long");
2938 RETURN_THROWS();
2939 }
2940 if (crypto_auth_verify((const unsigned char *) mac,
2941 (const unsigned char *) msg, msg_len,
2942 (const unsigned char *) key) != 0) {
2943 RETURN_FALSE;
2944 }
2945 RETURN_TRUE;
2946 }
2947
PHP_FUNCTION(sodium_crypto_sign_ed25519_sk_to_curve25519)2948 PHP_FUNCTION(sodium_crypto_sign_ed25519_sk_to_curve25519)
2949 {
2950 zend_string *ecdhkey;
2951 char *eddsakey;
2952 size_t eddsakey_len;
2953
2954 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
2955 &eddsakey, &eddsakey_len) == FAILURE) {
2956 sodium_remove_param_values_from_backtrace(EG(exception));
2957 RETURN_THROWS();
2958 }
2959 if (eddsakey_len != crypto_sign_SECRETKEYBYTES) {
2960 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes long");
2961 RETURN_THROWS();
2962 }
2963 ecdhkey = zend_string_alloc(crypto_box_SECRETKEYBYTES, 0);
2964
2965 if (crypto_sign_ed25519_sk_to_curve25519((unsigned char *) ZSTR_VAL(ecdhkey),
2966 (const unsigned char *) eddsakey) != 0) {
2967 zend_string_efree(ecdhkey);
2968 zend_throw_exception(sodium_exception_ce, "conversion failed", 0);
2969 RETURN_THROWS();
2970 }
2971 ZSTR_VAL(ecdhkey)[crypto_box_SECRETKEYBYTES] = 0;
2972
2973 RETURN_STR(ecdhkey);
2974 }
2975
PHP_FUNCTION(sodium_crypto_sign_ed25519_pk_to_curve25519)2976 PHP_FUNCTION(sodium_crypto_sign_ed25519_pk_to_curve25519)
2977 {
2978 zend_string *ecdhkey;
2979 char *eddsakey;
2980 size_t eddsakey_len;
2981
2982 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
2983 &eddsakey, &eddsakey_len) == FAILURE) {
2984 sodium_remove_param_values_from_backtrace(EG(exception));
2985 RETURN_THROWS();
2986 }
2987 if (eddsakey_len != crypto_sign_PUBLICKEYBYTES) {
2988 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes long");
2989 RETURN_THROWS();
2990 }
2991 ecdhkey = zend_string_alloc(crypto_sign_PUBLICKEYBYTES, 0);
2992
2993 if (crypto_sign_ed25519_pk_to_curve25519((unsigned char *) ZSTR_VAL(ecdhkey),
2994 (const unsigned char *) eddsakey) != 0) {
2995 zend_string_efree(ecdhkey);
2996 zend_throw_exception(sodium_exception_ce, "conversion failed", 0);
2997 RETURN_THROWS();
2998 }
2999 ZSTR_VAL(ecdhkey)[crypto_box_PUBLICKEYBYTES] = 0;
3000
3001 RETURN_STR(ecdhkey);
3002 }
3003
PHP_FUNCTION(sodium_compare)3004 PHP_FUNCTION(sodium_compare)
3005 {
3006 char *buf1;
3007 char *buf2;
3008 size_t len1;
3009 size_t len2;
3010
3011 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3012 &buf1, &len1,
3013 &buf2, &len2) == FAILURE) {
3014 sodium_remove_param_values_from_backtrace(EG(exception));
3015 RETURN_THROWS();
3016 }
3017 if (len1 != len2) {
3018 zend_argument_error(sodium_exception_ce, 1, "and argument #2 ($string_2) must have the same length");
3019 RETURN_THROWS();
3020 } else {
3021 RETURN_LONG(sodium_compare((const unsigned char *) buf1,
3022 (const unsigned char *) buf2, (size_t) len1));
3023 }
3024 }
3025
3026 #ifdef HAVE_AESGCM
PHP_FUNCTION(sodium_crypto_aead_aes256gcm_keygen)3027 PHP_FUNCTION(sodium_crypto_aead_aes256gcm_keygen)
3028 {
3029 unsigned char key[crypto_aead_aes256gcm_KEYBYTES];
3030
3031 if (zend_parse_parameters_none() == FAILURE) {
3032 RETURN_THROWS();
3033 }
3034 randombytes_buf(key, sizeof key);
3035 RETURN_STRINGL((const char *) key, sizeof key);
3036 }
3037 #endif
3038
3039 #ifdef crypto_aead_aegis128l_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis128l_keygen)3040 PHP_FUNCTION(sodium_crypto_aead_aegis128l_keygen)
3041 {
3042 unsigned char key[crypto_aead_aegis128l_KEYBYTES];
3043
3044 if (zend_parse_parameters_none() == FAILURE) {
3045 RETURN_THROWS();
3046 }
3047 crypto_aead_aegis128l_keygen(key);
3048 RETURN_STRINGL((const char *) key, sizeof key);
3049 }
3050 #endif
3051
3052 #ifdef crypto_aead_aegis256_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis256_keygen)3053 PHP_FUNCTION(sodium_crypto_aead_aegis256_keygen)
3054 {
3055 unsigned char key[crypto_aead_aegis256_KEYBYTES];
3056
3057 if (zend_parse_parameters_none() == FAILURE) {
3058 RETURN_THROWS();
3059 }
3060 crypto_aead_aegis256_keygen(key);
3061 RETURN_STRINGL((const char *) key, sizeof key);
3062 }
3063 #endif
3064
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_keygen)3065 PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_keygen)
3066 {
3067 unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES];
3068
3069 if (zend_parse_parameters_none() == FAILURE) {
3070 RETURN_THROWS();
3071 }
3072 randombytes_buf(key, sizeof key);
3073 RETURN_STRINGL((const char *) key, sizeof key);
3074 }
3075
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_keygen)3076 PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_ietf_keygen)
3077 {
3078 unsigned char key[crypto_aead_chacha20poly1305_IETF_KEYBYTES];
3079
3080 if (zend_parse_parameters_none() == FAILURE) {
3081 RETURN_THROWS();
3082 }
3083 randombytes_buf(key, sizeof key);
3084 RETURN_STRINGL((const char *) key, sizeof key);
3085 }
3086
3087 #ifdef crypto_aead_xchacha20poly1305_IETF_NPUBBYTES
PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_keygen)3088 PHP_FUNCTION(sodium_crypto_aead_xchacha20poly1305_ietf_keygen)
3089 {
3090 unsigned char key[crypto_aead_xchacha20poly1305_IETF_KEYBYTES];
3091
3092 if (zend_parse_parameters_none() == FAILURE) {
3093 RETURN_THROWS();
3094 }
3095 randombytes_buf(key, sizeof key);
3096 RETURN_STRINGL((const char *) key, sizeof key);
3097 }
3098 #endif
3099
PHP_FUNCTION(sodium_crypto_auth_keygen)3100 PHP_FUNCTION(sodium_crypto_auth_keygen)
3101 {
3102 unsigned char key[crypto_auth_KEYBYTES];
3103
3104 if (zend_parse_parameters_none() == FAILURE) {
3105 RETURN_THROWS();
3106 }
3107 randombytes_buf(key, sizeof key);
3108 RETURN_STRINGL((const char *) key, sizeof key);
3109 }
3110
PHP_FUNCTION(sodium_crypto_generichash_keygen)3111 PHP_FUNCTION(sodium_crypto_generichash_keygen)
3112 {
3113 unsigned char key[crypto_generichash_KEYBYTES];
3114
3115 if (zend_parse_parameters_none() == FAILURE) {
3116 RETURN_THROWS();
3117 }
3118 randombytes_buf(key, sizeof key);
3119 RETURN_STRINGL((const char *) key, sizeof key);
3120 }
3121
PHP_FUNCTION(sodium_crypto_kdf_keygen)3122 PHP_FUNCTION(sodium_crypto_kdf_keygen)
3123 {
3124 unsigned char key[crypto_kdf_KEYBYTES];
3125
3126 if (zend_parse_parameters_none() == FAILURE) {
3127 RETURN_THROWS();
3128 }
3129 randombytes_buf(key, sizeof key);
3130 RETURN_STRINGL((const char *) key, sizeof key);
3131 }
3132
PHP_FUNCTION(sodium_crypto_secretbox_keygen)3133 PHP_FUNCTION(sodium_crypto_secretbox_keygen)
3134 {
3135 unsigned char key[crypto_secretbox_KEYBYTES];
3136
3137 if (zend_parse_parameters_none() == FAILURE) {
3138 RETURN_THROWS();
3139 }
3140 randombytes_buf(key, sizeof key);
3141 RETURN_STRINGL((const char *) key, sizeof key);
3142 }
3143
PHP_FUNCTION(sodium_crypto_shorthash_keygen)3144 PHP_FUNCTION(sodium_crypto_shorthash_keygen)
3145 {
3146 unsigned char key[crypto_shorthash_KEYBYTES];
3147
3148 if (zend_parse_parameters_none() == FAILURE) {
3149 RETURN_THROWS();
3150 }
3151 randombytes_buf(key, sizeof key);
3152 RETURN_STRINGL((const char *) key, sizeof key);
3153 }
3154
PHP_FUNCTION(sodium_crypto_stream_keygen)3155 PHP_FUNCTION(sodium_crypto_stream_keygen)
3156 {
3157 unsigned char key[crypto_stream_KEYBYTES];
3158
3159 if (zend_parse_parameters_none() == FAILURE) {
3160 RETURN_THROWS();
3161 }
3162 randombytes_buf(key, sizeof key);
3163 RETURN_STRINGL((const char *) key, sizeof key);
3164 }
3165 #ifdef crypto_stream_xchacha20_KEYBYTES
PHP_FUNCTION(sodium_crypto_stream_xchacha20_keygen)3166 PHP_FUNCTION(sodium_crypto_stream_xchacha20_keygen)
3167 {
3168 unsigned char key[crypto_stream_xchacha20_KEYBYTES];
3169
3170 if (zend_parse_parameters_none() == FAILURE) {
3171 return;
3172 }
3173 randombytes_buf(key, sizeof key);
3174 RETURN_STRINGL((const char *) key, sizeof key);
3175 }
3176 #endif
3177
PHP_FUNCTION(sodium_crypto_kdf_derive_from_key)3178 PHP_FUNCTION(sodium_crypto_kdf_derive_from_key)
3179 {
3180 unsigned char ctx_padded[crypto_generichash_blake2b_PERSONALBYTES];
3181 #ifndef crypto_kdf_PRIMITIVE
3182 unsigned char salt[crypto_generichash_blake2b_SALTBYTES];
3183 #endif
3184 char *ctx;
3185 char *key;
3186 zend_string *subkey;
3187 zend_long subkey_id;
3188 zend_long subkey_len;
3189 size_t ctx_len;
3190 size_t key_len;
3191
3192 if (zend_parse_parameters(ZEND_NUM_ARGS(), "llss",
3193 &subkey_len,
3194 &subkey_id,
3195 &ctx, &ctx_len,
3196 &key, &key_len) == FAILURE) {
3197 sodium_remove_param_values_from_backtrace(EG(exception));
3198 RETURN_THROWS();
3199 }
3200 if (subkey_len < crypto_kdf_BYTES_MIN) {
3201 zend_argument_error(sodium_exception_ce, 1, "must be greater than or equal to SODIUM_CRYPTO_KDF_BYTES_MIN");
3202 RETURN_THROWS();
3203 }
3204 if (subkey_len > crypto_kdf_BYTES_MAX || subkey_len > SIZE_MAX) {
3205 zend_argument_error(sodium_exception_ce, 1, "must be less than or equal to SODIUM_CRYPTO_KDF_BYTES_MAX");
3206 RETURN_THROWS();
3207 }
3208 if (subkey_id < 0) {
3209 zend_argument_error(sodium_exception_ce, 2, "must be greater than or equal to 0");
3210 RETURN_THROWS();
3211 }
3212 if (ctx_len != crypto_kdf_CONTEXTBYTES) {
3213 zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes long");
3214 RETURN_THROWS();
3215 }
3216 if (key_len != crypto_kdf_KEYBYTES) {
3217 zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_KDF_BYTES_MIN bytes long");
3218 RETURN_THROWS();
3219 }
3220 memcpy(ctx_padded, ctx, crypto_kdf_CONTEXTBYTES);
3221 memset(ctx_padded + crypto_kdf_CONTEXTBYTES, 0, sizeof ctx_padded - crypto_kdf_CONTEXTBYTES);
3222 subkey = zend_string_alloc((size_t) subkey_len, 0);
3223 #ifdef crypto_kdf_PRIMITIVE
3224 crypto_kdf_derive_from_key((unsigned char *) ZSTR_VAL(subkey),
3225 (size_t) subkey_len, (uint64_t) subkey_id,
3226 ctx, (const unsigned char *) key);
3227 #else
3228 salt[0] = (unsigned char) (((uint64_t) subkey_id) );
3229 salt[1] = (unsigned char) (((uint64_t) subkey_id) >> 8);
3230 salt[2] = (unsigned char) (((uint64_t) subkey_id) >> 16);
3231 salt[3] = (unsigned char) (((uint64_t) subkey_id) >> 24);
3232 salt[4] = (unsigned char) (((uint64_t) subkey_id) >> 32);
3233 salt[5] = (unsigned char) (((uint64_t) subkey_id) >> 40);
3234 salt[6] = (unsigned char) (((uint64_t) subkey_id) >> 48);
3235 salt[7] = (unsigned char) (((uint64_t) subkey_id) >> 56);
3236 memset(salt + 8, 0, (sizeof salt) - 8);
3237 crypto_generichash_blake2b_salt_personal((unsigned char *) ZSTR_VAL(subkey),
3238 (size_t) subkey_len,
3239 NULL, 0,
3240 (const unsigned char *) key,
3241 crypto_kdf_KEYBYTES,
3242 salt, ctx_padded);
3243 #endif
3244 ZSTR_VAL(subkey)[subkey_len] = 0;
3245
3246 RETURN_STR(subkey);
3247 }
3248
PHP_FUNCTION(sodium_pad)3249 PHP_FUNCTION(sodium_pad)
3250 {
3251 zend_string *padded;
3252 char *unpadded;
3253 zend_long blocksize;
3254 volatile size_t st;
3255 size_t i, j, k;
3256 size_t unpadded_len;
3257 size_t xpadlen;
3258 size_t xpadded_len;
3259
3260 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl",
3261 &unpadded, &unpadded_len, &blocksize) == FAILURE) {
3262 sodium_remove_param_values_from_backtrace(EG(exception));
3263 RETURN_THROWS();
3264 }
3265 if (blocksize <= 0) {
3266 zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
3267 RETURN_THROWS();
3268 }
3269 if (blocksize > SIZE_MAX) {
3270 zend_argument_error(sodium_exception_ce, 2, "is too large");
3271 RETURN_THROWS();
3272 }
3273 xpadlen = blocksize - 1U;
3274 if ((blocksize & (blocksize - 1U)) == 0U) {
3275 xpadlen -= unpadded_len & ((size_t) blocksize - 1U);
3276 } else {
3277 xpadlen -= unpadded_len % (size_t) blocksize;
3278 }
3279 if ((size_t) SIZE_MAX - unpadded_len <= xpadlen) {
3280 zend_throw_exception(sodium_exception_ce, "input is too large", 0);
3281 RETURN_THROWS();
3282 }
3283 xpadded_len = unpadded_len + xpadlen;
3284 padded = zend_string_alloc(xpadded_len + 1U, 0);
3285 if (unpadded_len > 0) {
3286 st = 1U;
3287 i = 0U;
3288 k = unpadded_len;
3289 for (j = 0U; j <= xpadded_len; j++) {
3290 ZSTR_VAL(padded)[j] = unpadded[i];
3291 k -= st;
3292 st = (size_t) (~(((( (((uint64_t) k) >> 48) | (((uint64_t) k) >> 32) |
3293 (k >> 16) | k) & 0xffff) - 1U) >> 16)) & 1U;
3294 i += st;
3295 }
3296 }
3297 #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
3298 if (sodium_pad(NULL, (unsigned char *) ZSTR_VAL(padded), unpadded_len,
3299 (size_t) blocksize, xpadded_len + 1U) != 0) {
3300 zend_string_efree(padded);
3301 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3302 RETURN_THROWS();
3303 }
3304 #else
3305 {
3306 char *tail;
3307 volatile unsigned char mask;
3308 unsigned char barrier_mask;
3309
3310 tail = &ZSTR_VAL(padded)[xpadded_len];
3311 mask = 0U;
3312 for (i = 0; i < blocksize; i++) {
3313 barrier_mask = (unsigned char)
3314 (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT));
3315 tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask);
3316 mask |= barrier_mask;
3317 }
3318 }
3319 #endif
3320 ZSTR_VAL(padded)[xpadded_len + 1U] = 0;
3321
3322 RETURN_STR(padded);
3323 }
3324
PHP_FUNCTION(sodium_unpad)3325 PHP_FUNCTION(sodium_unpad)
3326 {
3327 zend_string *unpadded;
3328 char *padded;
3329 size_t padded_len;
3330 size_t unpadded_len;
3331 zend_long blocksize;
3332 int ret;
3333
3334 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl",
3335 &padded, &padded_len, &blocksize) == FAILURE) {
3336 sodium_remove_param_values_from_backtrace(EG(exception));
3337 RETURN_THROWS();
3338 }
3339 if (blocksize <= 0) {
3340 zend_argument_error(sodium_exception_ce, 2, "must be greater than 0");
3341 RETURN_THROWS();
3342 }
3343 if (blocksize > SIZE_MAX) {
3344 zend_argument_error(sodium_exception_ce, 2, "is too large");
3345 RETURN_THROWS();
3346 }
3347 if (padded_len < blocksize) {
3348 zend_argument_error(sodium_exception_ce, 1, "must be at least as long as the block size");
3349 RETURN_THROWS();
3350 }
3351
3352 #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
3353 ret = sodium_unpad(&unpadded_len, (const unsigned char *) padded,
3354 padded_len, (size_t) blocksize);
3355 #else
3356 {
3357 const char *tail;
3358 unsigned char acc = 0U;
3359 unsigned char c;
3360 unsigned char valid = 0U;
3361 volatile size_t pad_len = 0U;
3362 size_t i;
3363 size_t is_barrier;
3364
3365 tail = &padded[padded_len - 1U];
3366
3367 for (i = 0U; i < (size_t) blocksize; i++) {
3368 c = tail[-i];
3369 is_barrier =
3370 (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U;
3371 acc |= c;
3372 pad_len |= i & (1U + ~is_barrier);
3373 valid |= (unsigned char) is_barrier;
3374 }
3375 unpadded_len = padded_len - 1U - pad_len;
3376 ret = (int) (valid - 1U);
3377 }
3378 #endif
3379 if (ret != 0 || unpadded_len > LONG_MAX) {
3380 zend_throw_exception(sodium_exception_ce, "invalid padding", 0);
3381 RETURN_THROWS();
3382 }
3383 unpadded = zend_string_init(padded, padded_len, 0);
3384 PHP_SODIUM_ZSTR_TRUNCATE(unpadded, unpadded_len);
3385 ZSTR_VAL(unpadded)[unpadded_len] = 0;
3386 RETURN_STR(unpadded);
3387 }
3388
3389 #ifdef crypto_secretstream_xchacha20poly1305_ABYTES
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_keygen)3390 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_keygen)
3391 {
3392 unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
3393
3394 if (zend_parse_parameters_none() == FAILURE) {
3395 RETURN_THROWS();
3396 }
3397 randombytes_buf(key, sizeof key);
3398 RETURN_STRINGL((const char *) key, sizeof key);
3399 }
3400
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_push)3401 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_push)
3402 {
3403 crypto_secretstream_xchacha20poly1305_state state;
3404 unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
3405 unsigned char *key;
3406 size_t key_len;
3407
3408 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3409 &key, &key_len) == FAILURE) {
3410 sodium_remove_param_values_from_backtrace(EG(exception));
3411 RETURN_THROWS();
3412 }
3413 if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
3414 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes long");
3415 RETURN_THROWS();
3416 }
3417 if (crypto_secretstream_xchacha20poly1305_init_push(&state,
3418 header, key) != 0) {
3419 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3420 RETURN_THROWS();
3421 }
3422 array_init(return_value);
3423 add_next_index_stringl(return_value, (const char *) &state, sizeof state);
3424 add_next_index_stringl(return_value, (const char *) header, sizeof header);
3425 }
3426
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_push)3427 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_push)
3428 {
3429 zval *state_zv;
3430 zend_string *c;
3431 unsigned char *ad = NULL;
3432 unsigned char *msg;
3433 unsigned char *state;
3434 unsigned long long c_real_len;
3435 zend_long tag = crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
3436 size_t ad_len = (size_t) 0U;
3437 size_t c_len;
3438 size_t msg_len;
3439 size_t state_len;
3440
3441 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|sl",
3442 &state_zv,
3443 &msg, &msg_len, &ad, &ad_len, &tag) == FAILURE) {
3444 sodium_remove_param_values_from_backtrace(EG(exception));
3445 RETURN_THROWS();
3446 }
3447 ZVAL_DEREF(state_zv);
3448 if (Z_TYPE_P(state_zv) != IS_STRING) {
3449 zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
3450 RETURN_THROWS();
3451 }
3452 sodium_separate_string(state_zv);
3453 state = (unsigned char *) Z_STRVAL(*state_zv);
3454 state_len = Z_STRLEN(*state_zv);
3455 if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
3456 zend_argument_error(sodium_exception_ce, 1, "must have a correct length");
3457 RETURN_THROWS();
3458 }
3459 if (msg_len > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX ||
3460 msg_len > SIZE_MAX - crypto_secretstream_xchacha20poly1305_ABYTES) {
3461 zend_argument_error(sodium_exception_ce, 2, "must be at most SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes long");
3462 RETURN_THROWS();
3463 }
3464 if (tag < 0 || tag > 255) {
3465 zend_argument_error(sodium_exception_ce, 4, "must be in the range of 0-255");
3466 RETURN_THROWS();
3467 }
3468 c_len = msg_len + crypto_secretstream_xchacha20poly1305_ABYTES;
3469 c = zend_string_alloc((size_t) c_len, 0);
3470 if (crypto_secretstream_xchacha20poly1305_push
3471 ((void *) state, (unsigned char *) ZSTR_VAL(c), &c_real_len,
3472 msg, (unsigned long long) msg_len, ad, (unsigned long long) ad_len,
3473 (unsigned char) tag) != 0) {
3474 zend_string_efree(c);
3475 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3476 RETURN_THROWS();
3477 }
3478 if (c_real_len <= 0U || c_real_len >= SIZE_MAX || c_real_len > c_len) {
3479 zend_string_efree(c);
3480 zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
3481 RETURN_THROWS();
3482 }
3483 PHP_SODIUM_ZSTR_TRUNCATE(c, (size_t) c_real_len);
3484 ZSTR_VAL(c)[c_real_len] = 0;
3485
3486 RETURN_NEW_STR(c);
3487 }
3488
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_pull)3489 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_pull)
3490 {
3491 crypto_secretstream_xchacha20poly1305_state state;
3492 unsigned char *header;
3493 unsigned char *key;
3494 size_t header_len;
3495 size_t key_len;
3496
3497 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3498 &header, &header_len,
3499 &key, &key_len) == FAILURE) {
3500 sodium_remove_param_values_from_backtrace(EG(exception));
3501 RETURN_THROWS();
3502 }
3503 if (header_len != crypto_secretstream_xchacha20poly1305_HEADERBYTES) {
3504 zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes long");
3505 RETURN_THROWS();
3506 }
3507 if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
3508 zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes long");
3509 RETURN_THROWS();
3510 }
3511 if (crypto_secretstream_xchacha20poly1305_init_pull(&state,
3512 header, key) != 0) {
3513 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3514 RETURN_THROWS();
3515 }
3516 RETURN_STRINGL((const char *) &state, sizeof state);
3517 }
3518
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_pull)3519 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_pull)
3520 {
3521 zval *state_zv;
3522 zend_string *msg;
3523 unsigned char *ad = NULL;
3524 unsigned char *c;
3525 unsigned char *state;
3526 unsigned long long msg_real_len;
3527 size_t ad_len = (size_t) 0U;
3528 size_t msg_len;
3529 size_t c_len;
3530 size_t state_len;
3531 unsigned char tag;
3532
3533 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|s",
3534 &state_zv,
3535 &c, &c_len, &ad, &ad_len) == FAILURE) {
3536 sodium_remove_param_values_from_backtrace(EG(exception));
3537 RETURN_THROWS();
3538 }
3539 ZVAL_DEREF(state_zv);
3540 if (Z_TYPE_P(state_zv) != IS_STRING) {
3541 zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
3542 RETURN_THROWS();
3543 }
3544 sodium_separate_string(state_zv);
3545 state = (unsigned char *) Z_STRVAL(*state_zv);
3546 state_len = Z_STRLEN(*state_zv);
3547 if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
3548 zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
3549 RETURN_THROWS();
3550 }
3551 if (c_len < crypto_secretstream_xchacha20poly1305_ABYTES) {
3552 RETURN_FALSE;
3553 }
3554 msg_len = c_len - crypto_secretstream_xchacha20poly1305_ABYTES;
3555 msg = zend_string_alloc((size_t) msg_len, 0);
3556 if (crypto_secretstream_xchacha20poly1305_pull
3557 ((void *) state, (unsigned char *) ZSTR_VAL(msg), &msg_real_len, &tag,
3558 c, (unsigned long long) c_len, ad, (unsigned long long) ad_len) != 0) {
3559 zend_string_efree(msg);
3560 RETURN_FALSE;
3561 }
3562 if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
3563 zend_string_efree(msg);
3564 zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
3565 RETURN_THROWS();
3566 }
3567 PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
3568 ZSTR_VAL(msg)[msg_real_len] = 0;
3569 array_init(return_value);
3570 add_next_index_str(return_value, msg);
3571 add_next_index_long(return_value, (long) tag);
3572 }
3573
PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_rekey)3574 PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_rekey)
3575 {
3576 zval *state_zv;
3577 unsigned char *state;
3578 size_t state_len;
3579
3580 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &state_zv) == FAILURE) {
3581 sodium_remove_param_values_from_backtrace(EG(exception));
3582 RETURN_THROWS();
3583 }
3584 ZVAL_DEREF(state_zv);
3585 if (Z_TYPE_P(state_zv) != IS_STRING) {
3586 zend_argument_error(sodium_exception_ce, 1, "must be a reference to a state");
3587 RETURN_THROWS();
3588 }
3589 sodium_separate_string(state_zv);
3590 state = (unsigned char *) Z_STRVAL(*state_zv);
3591 state_len = Z_STRLEN(*state_zv);
3592 if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) {
3593 zend_throw_exception(sodium_exception_ce, "incorrect state length", 0);
3594 RETURN_THROWS();
3595 }
3596 crypto_secretstream_xchacha20poly1305_rekey((void *) state);
3597 }
3598 #endif
3599
3600 #ifdef crypto_core_ristretto255_HASHBYTES
PHP_FUNCTION(sodium_crypto_core_ristretto255_add)3601 PHP_FUNCTION(sodium_crypto_core_ristretto255_add)
3602 {
3603 zend_string *r;
3604 unsigned char *p;
3605 unsigned char *q;
3606 size_t p_len;
3607 size_t q_len;
3608
3609 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3610 &p, &p_len, &q, &q_len) == FAILURE) {
3611 sodium_remove_param_values_from_backtrace(EG(exception));
3612 RETURN_THROWS();
3613 }
3614 if (p_len != crypto_core_ristretto255_BYTES) {
3615 zend_argument_error(sodium_exception_ce, 1,
3616 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
3617 RETURN_THROWS();
3618 }
3619 if (q_len != crypto_core_ristretto255_BYTES) {
3620 zend_argument_error(sodium_exception_ce, 2,
3621 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
3622 RETURN_THROWS();
3623 }
3624 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3625 if (crypto_core_ristretto255_add((unsigned char *) ZSTR_VAL(r), p, q) != 0) {
3626 zend_string_efree(r);
3627 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3628 RETURN_THROWS();
3629 }
3630 ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
3631 RETURN_NEW_STR(r);
3632 }
3633
PHP_FUNCTION(sodium_crypto_core_ristretto255_from_hash)3634 PHP_FUNCTION(sodium_crypto_core_ristretto255_from_hash)
3635 {
3636 zend_string *r;
3637 unsigned char *s;
3638 size_t s_len;
3639
3640 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3641 &s, &s_len) == FAILURE) {
3642 sodium_remove_param_values_from_backtrace(EG(exception));
3643 RETURN_THROWS();
3644 }
3645 if (s_len != crypto_core_ristretto255_HASHBYTES) {
3646 zend_argument_error(sodium_exception_ce, 1,
3647 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES bytes long");
3648 RETURN_THROWS();
3649 }
3650 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3651 if (crypto_core_ristretto255_from_hash((unsigned char *) ZSTR_VAL(r), s) != 0) {
3652 zend_string_efree(r);
3653 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3654 RETURN_THROWS();
3655 }
3656 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3657 RETURN_NEW_STR(r);
3658 }
3659
PHP_FUNCTION(sodium_crypto_core_ristretto255_is_valid_point)3660 PHP_FUNCTION(sodium_crypto_core_ristretto255_is_valid_point)
3661 {
3662 unsigned char *s;
3663 size_t s_len;
3664
3665 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3666 &s, &s_len) == FAILURE) {
3667 sodium_remove_param_values_from_backtrace(EG(exception));
3668 RETURN_THROWS();
3669 }
3670 if (s_len != crypto_core_ristretto255_BYTES) {
3671 zend_argument_error(sodium_exception_ce, 1,
3672 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
3673 RETURN_THROWS();
3674 }
3675 RETURN_BOOL(crypto_core_ristretto255_is_valid_point(s));
3676 }
3677
PHP_FUNCTION(sodium_crypto_core_ristretto255_random)3678 PHP_FUNCTION(sodium_crypto_core_ristretto255_random)
3679 {
3680 zend_string *r;
3681
3682 if (zend_parse_parameters_none() == FAILURE) {
3683 RETURN_THROWS();
3684 }
3685 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3686 crypto_core_ristretto255_random((unsigned char *) ZSTR_VAL(r));
3687 ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
3688 RETURN_NEW_STR(r);
3689 }
3690
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_add)3691 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_add)
3692 {
3693 zend_string *r;
3694 unsigned char *p;
3695 unsigned char *q;
3696 size_t p_len;
3697 size_t q_len;
3698
3699 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3700 &p, &p_len, &q, &q_len) == FAILURE) {
3701 sodium_remove_param_values_from_backtrace(EG(exception));
3702 RETURN_THROWS();
3703 }
3704 if (p_len != crypto_core_ristretto255_SCALARBYTES) {
3705 zend_argument_error(sodium_exception_ce, 1,
3706 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3707 RETURN_THROWS();
3708 }
3709 if (q_len != crypto_core_ristretto255_SCALARBYTES) {
3710 zend_argument_error(sodium_exception_ce, 2,
3711 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3712 RETURN_THROWS();
3713 }
3714 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3715 crypto_core_ristretto255_scalar_add((unsigned char *) ZSTR_VAL(r), p, q);
3716 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3717 RETURN_NEW_STR(r);
3718 }
3719
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_complement)3720 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_complement)
3721 {
3722 zend_string *r;
3723 unsigned char *s;
3724 size_t s_len;
3725
3726 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3727 &s, &s_len) == FAILURE) {
3728 sodium_remove_param_values_from_backtrace(EG(exception));
3729 RETURN_THROWS();
3730 }
3731 if (s_len != crypto_core_ristretto255_SCALARBYTES) {
3732 zend_argument_error(sodium_exception_ce, 1,
3733 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3734 RETURN_THROWS();
3735 }
3736 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3737 crypto_core_ristretto255_scalar_complement((unsigned char *) ZSTR_VAL(r), s);
3738 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3739 RETURN_NEW_STR(r);
3740 }
3741
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_invert)3742 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_invert)
3743 {
3744 zend_string *r;
3745 unsigned char *s;
3746 size_t s_len;
3747
3748 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3749 &s, &s_len) == FAILURE) {
3750 sodium_remove_param_values_from_backtrace(EG(exception));
3751 RETURN_THROWS();
3752 }
3753 if (s_len != crypto_core_ristretto255_SCALARBYTES) {
3754 zend_argument_error(sodium_exception_ce, 1,
3755 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3756 RETURN_THROWS();
3757 }
3758 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3759 if (crypto_core_ristretto255_scalar_invert((unsigned char *) ZSTR_VAL(r), s) != 0) {
3760 zend_string_efree(r);
3761 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3762 RETURN_THROWS();
3763 }
3764 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3765 RETURN_NEW_STR(r);
3766 }
3767
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_mul)3768 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_mul)
3769 {
3770 zend_string *r;
3771 unsigned char *x;
3772 unsigned char *y;
3773 size_t x_len;
3774 size_t y_len;
3775
3776 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3777 &x, &x_len, &y, &y_len) == FAILURE) {
3778 sodium_remove_param_values_from_backtrace(EG(exception));
3779 RETURN_THROWS();
3780 }
3781 if (x_len != crypto_core_ristretto255_SCALARBYTES) {
3782 zend_argument_error(sodium_exception_ce, 1,
3783 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3784 RETURN_THROWS();
3785 }
3786 if (y_len != crypto_core_ristretto255_SCALARBYTES) {
3787 zend_argument_error(sodium_exception_ce, 2,
3788 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3789 RETURN_THROWS();
3790 }
3791 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3792 crypto_core_ristretto255_scalar_mul((unsigned char *) ZSTR_VAL(r), x, y);
3793 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3794 RETURN_NEW_STR(r);
3795 }
3796
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_negate)3797 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_negate)
3798 {
3799 zend_string *r;
3800 unsigned char *s;
3801 size_t s_len;
3802
3803 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3804 &s, &s_len) == FAILURE) {
3805 sodium_remove_param_values_from_backtrace(EG(exception));
3806 RETURN_THROWS();
3807 }
3808 if (s_len != crypto_core_ristretto255_SCALARBYTES) {
3809 zend_argument_error(sodium_exception_ce, 1,
3810 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3811 RETURN_THROWS();
3812 }
3813 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3814 crypto_core_ristretto255_scalar_negate((unsigned char *) ZSTR_VAL(r), s);
3815 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3816 RETURN_NEW_STR(r);
3817 }
3818
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_random)3819 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_random)
3820 {
3821 zend_string *r;
3822
3823 if (zend_parse_parameters_none() == FAILURE) {
3824 RETURN_THROWS();
3825 };
3826 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3827 crypto_core_ristretto255_scalar_random((unsigned char *) ZSTR_VAL(r));
3828 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3829 RETURN_NEW_STR(r);
3830 }
3831
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_reduce)3832 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_reduce)
3833 {
3834 zend_string *r;
3835 unsigned char *s;
3836 size_t s_len;
3837
3838 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
3839 &s, &s_len) == FAILURE) {
3840 sodium_remove_param_values_from_backtrace(EG(exception));
3841 RETURN_THROWS();
3842 }
3843 if (s_len != crypto_core_ristretto255_NONREDUCEDSCALARBYTES) {
3844 zend_argument_error(sodium_exception_ce, 1,
3845 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES bytes long");
3846 RETURN_THROWS();
3847 }
3848 r = zend_string_alloc(crypto_core_ristretto255_SCALARBYTES, 0);
3849 crypto_core_ristretto255_scalar_reduce((unsigned char *) ZSTR_VAL(r), s);
3850 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3851 RETURN_NEW_STR(r);
3852 }
3853
PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_sub)3854 PHP_FUNCTION(sodium_crypto_core_ristretto255_scalar_sub)
3855 {
3856 zend_string *r;
3857 unsigned char *p;
3858 unsigned char *q;
3859 size_t p_len;
3860 size_t q_len;
3861
3862 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3863 &p, &p_len, &q, &q_len) == FAILURE) {
3864 sodium_remove_param_values_from_backtrace(EG(exception));
3865 RETURN_THROWS();
3866 }
3867 if (p_len != crypto_core_ristretto255_SCALARBYTES) {
3868 zend_argument_error(sodium_exception_ce, 1,
3869 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3870 RETURN_THROWS();
3871 }
3872 if (q_len != crypto_core_ristretto255_SCALARBYTES) {
3873 zend_argument_error(sodium_exception_ce, 2,
3874 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES bytes long");
3875 RETURN_THROWS();
3876 }
3877 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3878 crypto_core_ristretto255_scalar_sub((unsigned char *) ZSTR_VAL(r), p, q);
3879 ZSTR_VAL(r)[crypto_core_ristretto255_SCALARBYTES] = 0;
3880 RETURN_NEW_STR(r);
3881 }
3882
PHP_FUNCTION(sodium_crypto_core_ristretto255_sub)3883 PHP_FUNCTION(sodium_crypto_core_ristretto255_sub)
3884 {
3885 zend_string *r;
3886 unsigned char *p;
3887 unsigned char *q;
3888 size_t p_len;
3889 size_t q_len;
3890
3891 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
3892 &p, &p_len, &q, &q_len) == FAILURE) {
3893 sodium_remove_param_values_from_backtrace(EG(exception));
3894 RETURN_THROWS();
3895 }
3896 if (p_len != crypto_core_ristretto255_BYTES) {
3897 zend_argument_error(sodium_exception_ce, 1,
3898 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
3899 RETURN_THROWS();
3900 }
3901 if (q_len != crypto_core_ristretto255_BYTES) {
3902 zend_argument_error(sodium_exception_ce, 2,
3903 "must be SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES bytes long");
3904 RETURN_THROWS();
3905 }
3906 r = zend_string_alloc(crypto_core_ristretto255_BYTES, 0);
3907 if (crypto_core_ristretto255_sub((unsigned char *) ZSTR_VAL(r), p, q) != 0) {
3908 zend_string_efree(r);
3909 zend_throw_exception(sodium_exception_ce, "internal error", 0);
3910 RETURN_THROWS();
3911 }
3912 ZSTR_VAL(r)[crypto_core_ristretto255_BYTES] = 0;
3913 RETURN_NEW_STR(r);
3914 }
3915 #endif
3916