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