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