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