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