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