diff options
author | Frank Denis <github@pureftpd.org> | 2017-10-02 21:59:51 +0200 |
---|---|---|
committer | Frank Denis <github@pureftpd.org> | 2017-10-02 21:59:51 +0200 |
commit | 72f7d0b1844bc97727bf936359d95e269281d1dc (patch) | |
tree | d6f5c0f2fdec8ac2b02d9774d7d8f92a6ea80202 /ext/sodium | |
parent | 7d53e65125e63f522a5ad6dbbabeb7d5fc243dea (diff) | |
download | php-git-72f7d0b1844bc97727bf936359d95e269281d1dc.tar.gz |
ext/sodium: import bindings for secretstream
Diffstat (limited to 'ext/sodium')
-rw-r--r-- | ext/sodium/libsodium.c | 250 | ||||
-rw-r--r-- | ext/sodium/php_libsodium.h | 6 |
2 files changed, 256 insertions, 0 deletions
diff --git a/ext/sodium/libsodium.c b/ext/sodium/libsodium.c index 6b192bc69d..674f806042 100644 --- a/ext/sodium/libsodium.c +++ b/ext/sodium/libsodium.c @@ -228,6 +228,10 @@ ZEND_END_ARG_INFO() # define crypto_aead_chacha20poly1305_IETF_ABYTES crypto_aead_chacha20poly1305_ABYTES #endif +#if defined(crypto_secretstream_xchacha20poly1305_ABYTES) && SODIUM_LIBRARY_VERSION_MAJOR < 10 +# undef crypto_secretstream_xchacha20poly1305_ABYTES +#endif + const zend_function_entry sodium_functions[] = { PHP_FE(sodium_crypto_aead_aes256gcm_is_available, AI_None) #ifdef HAVE_AESGCM @@ -289,6 +293,14 @@ const zend_function_entry sodium_functions[] = { PHP_FE(sodium_crypto_secretbox, AI_StringAndNonceAndKey) PHP_FE(sodium_crypto_secretbox_keygen, AI_None) PHP_FE(sodium_crypto_secretbox_open, AI_StringAndNonceAndKey) +#ifdef crypto_secretstream_xchacha20poly1305_ABYTES + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_keygen, AI_None) + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_init_push, AI_Key) + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_push, AI_StateByReferenceAndStringAndMaybeStringAndLong) + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_init_pull, AI_StringAndKey) + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_pull, AI_StateByReferenceAndStringAndMaybeString) + PHP_FE(sodium_crypto_secretstream_xchacha20poly1305_rekey, AI_StateByReference) +#endif PHP_FE(sodium_crypto_shorthash, AI_StringAndKey) PHP_FE(sodium_crypto_shorthash_keygen, AI_None) PHP_FE(sodium_crypto_sign, AI_StringAndKeyPair) @@ -491,6 +503,32 @@ PHP_MINIT_FUNCTION(sodium) REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_KX_KEYPAIRBYTES", crypto_kx_SECRETKEYBYTES + crypto_kx_PUBLICKEYBYTES, CONST_CS | CONST_PERSISTENT); +#ifdef crypto_secretstream_xchacha20poly1305_ABYTES + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES", + crypto_secretstream_xchacha20poly1305_ABYTES, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES", + crypto_secretstream_xchacha20poly1305_HEADERBYTES, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES", + crypto_secretstream_xchacha20poly1305_KEYBYTES, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX", + crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE", + crypto_secretstream_xchacha20poly1305_TAG_MESSAGE, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH", + crypto_secretstream_xchacha20poly1305_TAG_PUSH, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY", + crypto_secretstream_xchacha20poly1305_TAG_REKEY, + CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL", + crypto_secretstream_xchacha20poly1305_TAG_FINAL, + CONST_CS | CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES", crypto_generichash_BYTES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SODIUM_CRYPTO_GENERICHASH_BYTES_MIN", @@ -3448,6 +3486,218 @@ PHP_FUNCTION(sodium_unpad) RETURN_STR(unpadded); } +#ifdef crypto_secretstream_xchacha20poly1305_ABYTES +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_keygen) +{ + unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + randombytes_buf(key, sizeof key); + RETURN_STRINGL((const char *) key, sizeof key); +} + +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_push) +{ + crypto_secretstream_xchacha20poly1305_state state; + unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; + unsigned char *key; + size_t key_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", + &key, &key_len) == FAILURE) { + return; + } + if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) { + zend_throw_exception(sodium_exception_ce, + "key size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes", + 0); + return; + } + if (crypto_secretstream_xchacha20poly1305_init_push(&state, + header, key) != 0) { + zend_throw_exception(sodium_exception_ce, "internal error", 0); + return; + } + array_init(return_value); + add_next_index_stringl(return_value, (const char *) &state, sizeof state); + add_next_index_stringl(return_value, (const char *) header, sizeof header); +} + +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_push) +{ + zval *state_zv; + zend_string *c; + unsigned char *ad = NULL; + unsigned char *msg; + unsigned char *state; + unsigned long long c_real_len; + zend_long tag = crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; + size_t ad_len = (size_t) 0U; + size_t c_len; + size_t msg_len; + size_t state_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|sl", + &state_zv, + &msg, &msg_len, &ad, &ad_len, &tag) == FAILURE) { + return; + } + ZVAL_DEREF(state_zv); + if (Z_TYPE_P(state_zv) != IS_STRING) { + zend_throw_exception(sodium_exception_ce, "a reference to a state is required", 0); + return; + } + sodium_separate_string(state_zv); + state = (unsigned char *) Z_STRVAL(*state_zv); + state_len = Z_STRLEN(*state_zv); + if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) { + zend_throw_exception(sodium_exception_ce, "incorrect state length", 0); + return; + } + if (msg_len > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX || + msg_len > SIZE_MAX - crypto_secretstream_xchacha20poly1305_ABYTES) { + zend_throw_exception(sodium_exception_ce, "message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes", 0); + return; + } + if (tag < 0 || tag > 255) { + zend_throw_exception(sodium_exception_ce, "unsupported value for the tag", 0); + return; + } + c_len = msg_len + crypto_secretstream_xchacha20poly1305_ABYTES; + c = zend_string_alloc((size_t) c_len, 0); + if (crypto_secretstream_xchacha20poly1305_push + ((void *) state, (unsigned char *) ZSTR_VAL(c), &c_real_len, + msg, (unsigned long long) msg_len, ad, (unsigned long long) ad_len, + (unsigned char) tag) != 0) { + zend_string_free(c); + zend_throw_exception(sodium_exception_ce, "internal error", 0); + return; + } + if (c_real_len <= 0U || c_real_len >= SIZE_MAX || c_real_len > c_len) { + zend_string_free(c); + zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0); + return; + } + PHP_SODIUM_ZSTR_TRUNCATE(c, (size_t) c_real_len); + ZSTR_VAL(c)[c_real_len] = 0; + + RETURN_STR(c); +} + +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_pull) +{ + crypto_secretstream_xchacha20poly1305_state state; + unsigned char *header; + unsigned char *key; + size_t header_len; + size_t key_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", + &header, &header_len, + &key, &key_len) == FAILURE) { + return; + } + if (header_len != crypto_secretstream_xchacha20poly1305_HEADERBYTES) { + zend_throw_exception(sodium_exception_ce, + "header size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes", + 0); + return; + } + if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES) { + zend_throw_exception(sodium_exception_ce, + "key size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES bytes", + 0); + return; + } + if (crypto_secretstream_xchacha20poly1305_init_pull(&state, + header, key) != 0) { + zend_throw_exception(sodium_exception_ce, "internal error", 0); + return; + } + RETURN_STRINGL((const char *) &state, sizeof state); +} + +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_pull) +{ + zval *state_zv; + zend_string *msg; + unsigned char *ad = NULL; + unsigned char *c; + unsigned char *state; + unsigned long long msg_real_len; + size_t ad_len = (size_t) 0U; + size_t msg_len; + size_t c_len; + size_t state_len; + unsigned char tag; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|s", + &state_zv, + &c, &c_len, &ad, &ad_len) == FAILURE) { + return; + } + ZVAL_DEREF(state_zv); + if (Z_TYPE_P(state_zv) != IS_STRING) { + zend_throw_exception(sodium_exception_ce, "a reference to a state is required", 0); + return; + } + sodium_separate_string(state_zv); + state = (unsigned char *) Z_STRVAL(*state_zv); + state_len = Z_STRLEN(*state_zv); + if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) { + zend_throw_exception(sodium_exception_ce, "incorrect state length", 0); + return; + } + if (c_len < crypto_secretstream_xchacha20poly1305_ABYTES) { + RETURN_FALSE; + } + msg_len = c_len - crypto_secretstream_xchacha20poly1305_ABYTES; + msg = zend_string_alloc((size_t) msg_len, 0); + if (crypto_secretstream_xchacha20poly1305_pull + ((void *) state, (unsigned char *) ZSTR_VAL(msg), &msg_real_len, &tag, + c, (unsigned long long) c_len, ad, (unsigned long long) ad_len) != 0) { + zend_string_free(msg); + RETURN_FALSE; + } + if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) { + zend_string_free(msg); + zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0); + return; + } + PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len); + ZSTR_VAL(msg)[msg_real_len] = 0; + array_init(return_value); + add_next_index_str(return_value, msg); + add_next_index_long(return_value, (long) tag); +} + +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_rekey) +{ + zval *state_zv; + unsigned char *state; + size_t state_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &state_zv) == FAILURE) { + return; + } + ZVAL_DEREF(state_zv); + if (Z_TYPE_P(state_zv) != IS_STRING) { + zend_throw_exception(sodium_exception_ce, "a reference to a state is required", 0); + return; + } + sodium_separate_string(state_zv); + state = (unsigned char *) Z_STRVAL(*state_zv); + state_len = Z_STRLEN(*state_zv); + if (state_len != sizeof (crypto_secretstream_xchacha20poly1305_state)) { + zend_throw_exception(sodium_exception_ce, "incorrect state length", 0); + return; + } + crypto_secretstream_xchacha20poly1305_rekey((void *) state); +} +#endif + /* * Local variables: * tab-width: 4 diff --git a/ext/sodium/php_libsodium.h b/ext/sodium/php_libsodium.h index adfe40e8ae..b566490654 100644 --- a/ext/sodium/php_libsodium.h +++ b/ext/sodium/php_libsodium.h @@ -90,6 +90,12 @@ PHP_FUNCTION(sodium_crypto_scalarmult_base); PHP_FUNCTION(sodium_crypto_secretbox); PHP_FUNCTION(sodium_crypto_secretbox_keygen); PHP_FUNCTION(sodium_crypto_secretbox_open); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_keygen); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_push); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_push); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_init_pull); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_pull); +PHP_FUNCTION(sodium_crypto_secretstream_xchacha20poly1305_rekey); PHP_FUNCTION(sodium_crypto_shorthash); PHP_FUNCTION(sodium_crypto_shorthash_keygen); PHP_FUNCTION(sodium_crypto_sign); |