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