Skip to content

[sodium] Add AEGIS-128L and AEGIS-256 #12867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ SOAP:
Sockets:
. Removed the deprecated inet_ntoa call support. (David Carlier)

Sodium:
. Add support for AEGIS-128L and AEGIS-256 (jedisct1)
. Enable AES-GCM on aarch64 with the ARM crypto extensions (jedisct1)

Standard:
. Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla)
. Partly fix GH-12143 (Incorrect round() result for 0.49999999999999994).
Expand Down
7 changes: 7 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ PHP 8.4 UPGRADE NOTES
. If JIT is enabled, PHP will now exit with a fatal error on startup in case
of JIT startup initialization issues.

- Sodium:
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
functions to support the AEGIS family of authenticated encryption algorithms,
that was introduced in libsodium 1.0.19.
. sodium_crypto_aead_aes256gcm_*() functions are now enabled on aarch64 CPUs
with the ARM cryptographic extensions.

========================================
7. New Classes and Interfaces
========================================
Expand Down
266 changes: 261 additions & 5 deletions ext/sodium/libsodium.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
static zend_class_entry *sodium_exception_ce;

#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || \
defined(_M_AMD64) || defined(_M_IX86))
defined(_M_AMD64) || defined(_M_IX86) || defined(__aarch64__) || defined(_M_ARM64))
# define HAVE_AESGCM 1
#endif

Expand Down Expand Up @@ -1866,6 +1866,236 @@ PHP_FUNCTION(sodium_crypto_aead_aes256gcm_decrypt)
}
#endif

#ifdef crypto_aead_aegis128l_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis128l_encrypt)
{
zend_string *ciphertext;
unsigned char *ad;
unsigned char *msg;
unsigned char *npub;
unsigned char *secretkey;
unsigned long long ciphertext_real_len;
size_t ad_len;
size_t ciphertext_len;
size_t msg_len;
size_t npub_len;
size_t secretkey_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
&msg, &msg_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (npub_len != crypto_aead_aegis128l_NPUBBYTES) {
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES bytes long");
RETURN_THROWS();
}
if (secretkey_len != crypto_aead_aegis128l_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES bytes long");
RETURN_THROWS();
}
if (SIZE_MAX - msg_len <= crypto_aead_aegis128l_ABYTES) {
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
ciphertext_len = msg_len + crypto_aead_aegis128l_ABYTES;
ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
if (crypto_aead_aegis128l_encrypt
((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
(unsigned long long) msg_len,
ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
zend_string_efree(ciphertext);
zend_throw_exception(sodium_exception_ce, "internal error", 0);
RETURN_THROWS();
}
if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
ciphertext_real_len > ciphertext_len) {
zend_string_efree(ciphertext);
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;

RETURN_NEW_STR(ciphertext);
}

PHP_FUNCTION(sodium_crypto_aead_aegis128l_decrypt)
{
zend_string *msg;
unsigned char *ad;
unsigned char *ciphertext;
unsigned char *npub;
unsigned char *secretkey;
unsigned long long msg_real_len;
size_t ad_len;
size_t ciphertext_len;
size_t msg_len;
size_t npub_len;
size_t secretkey_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
&ciphertext, &ciphertext_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (npub_len != crypto_aead_aegis128l_NPUBBYTES) {
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES bytes long");
RETURN_THROWS();
}
if (secretkey_len != crypto_aead_aegis128l_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES bytes long");
RETURN_THROWS();
}
if (ciphertext_len < crypto_aead_aegis128l_ABYTES) {
RETURN_FALSE;
}
msg_len = ciphertext_len;
if (msg_len >= SIZE_MAX) {
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
msg = zend_string_alloc((size_t) msg_len, 0);
if (crypto_aead_aegis128l_decrypt
((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
ciphertext, (unsigned long long) ciphertext_len,
ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
zend_string_efree(msg);
RETURN_FALSE;
}
if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
zend_string_efree(msg);
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
ZSTR_VAL(msg)[msg_real_len] = 0;

RETURN_NEW_STR(msg);
}
#endif

#ifdef crypto_aead_aegis256_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis256_encrypt)
{
zend_string *ciphertext;
unsigned char *ad;
unsigned char *msg;
unsigned char *npub;
unsigned char *secretkey;
unsigned long long ciphertext_real_len;
size_t ad_len;
size_t ciphertext_len;
size_t msg_len;
size_t npub_len;
size_t secretkey_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
&msg, &msg_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (npub_len != crypto_aead_aegis256_NPUBBYTES) {
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES bytes long");
RETURN_THROWS();
}
if (secretkey_len != crypto_aead_aegis256_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES bytes long");
RETURN_THROWS();
}
if (SIZE_MAX - msg_len <= crypto_aead_aegis256_ABYTES) {
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
ciphertext_len = msg_len + crypto_aead_aegis256_ABYTES;
ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
if (crypto_aead_aegis256_encrypt
((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
(unsigned long long) msg_len,
ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
zend_string_efree(ciphertext);
zend_throw_exception(sodium_exception_ce, "internal error", 0);
RETURN_THROWS();
}
if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
ciphertext_real_len > ciphertext_len) {
zend_string_efree(ciphertext);
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;

RETURN_NEW_STR(ciphertext);
}

PHP_FUNCTION(sodium_crypto_aead_aegis256_decrypt)
{
zend_string *msg;
unsigned char *ad;
unsigned char *ciphertext;
unsigned char *npub;
unsigned char *secretkey;
unsigned long long msg_real_len;
size_t ad_len;
size_t ciphertext_len;
size_t msg_len;
size_t npub_len;
size_t secretkey_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
&ciphertext, &ciphertext_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (npub_len != crypto_aead_aegis256_NPUBBYTES) {
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES bytes long");
RETURN_THROWS();
}
if (secretkey_len != crypto_aead_aegis256_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES bytes long");
RETURN_THROWS();
}
if (ciphertext_len < crypto_aead_aegis256_ABYTES) {
RETURN_FALSE;
}
msg_len = ciphertext_len;
if (msg_len >= SIZE_MAX) {
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
msg = zend_string_alloc((size_t) msg_len, 0);
if (crypto_aead_aegis256_decrypt
((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
ciphertext, (unsigned long long) ciphertext_len,
ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
zend_string_efree(msg);
RETURN_FALSE;
}
if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
zend_string_efree(msg);
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
RETURN_THROWS();
}
PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
ZSTR_VAL(msg)[msg_real_len] = 0;

RETURN_NEW_STR(msg);
}
#endif

PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt)
{
zend_string *ciphertext;
Expand All @@ -1881,10 +2111,10 @@ PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt)
size_t secretkey_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
&msg, &msg_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
&msg, &msg_len,
&ad, &ad_len,
&npub, &npub_len,
&secretkey, &secretkey_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
Expand Down Expand Up @@ -2801,6 +3031,32 @@ PHP_FUNCTION(sodium_crypto_aead_aes256gcm_keygen)
}
#endif

#ifdef crypto_aead_aegis128l_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis128l_keygen)
{
unsigned char key[crypto_aead_aegis128l_KEYBYTES];

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
crypto_aead_aegis128l_keygen(key);
RETURN_STRINGL((const char *) key, sizeof key);
}
#endif

#ifdef crypto_aead_aegis256_KEYBYTES
PHP_FUNCTION(sodium_crypto_aead_aegis256_keygen)
{
unsigned char key[crypto_aead_aegis256_KEYBYTES];

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
crypto_aead_aegis256_keygen(key);
RETURN_STRINGL((const char *) key, sizeof key);
}
#endif

PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_keygen)
{
unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES];
Expand Down
62 changes: 62 additions & 0 deletions ext/sodium/libsodium.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,52 @@
const SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES = UNKNOWN;
#endif

#ifdef crypto_aead_aegis128l_KEYBYTES
/**
* @var int
* @cvalue crypto_aead_aegis128l_KEYBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis128l_NSECBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS128L_NSECBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis128l_NPUBBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis128l_ABYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS128L_ABYTES = UNKNOWN;
#endif

#ifdef crypto_aead_aegis256_KEYBYTES
/**
* @var int
* @cvalue crypto_aead_aegis256_KEYBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis256_NSECBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis256_NPUBBYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_aead_aegis256_ABYTES
*/
const SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES = UNKNOWN;
#endif

/**
* @var int
* @cvalue crypto_aead_chacha20poly1305_KEYBYTES
Expand Down Expand Up @@ -507,6 +553,22 @@ function sodium_crypto_aead_aes256gcm_encrypt(#[\SensitiveParameter] string $mes
function sodium_crypto_aead_aes256gcm_keygen(): string {}
#endif

#ifdef crypto_aead_aegis128l_KEYBYTES
function sodium_crypto_aead_aegis128l_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}

function sodium_crypto_aead_aegis128l_encrypt(#[\SensitiveParameter] string $message, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string {}

function sodium_crypto_aead_aegis128l_keygen(): string {}
#endif

#ifdef crypto_aead_aegis256_KEYBYTES
function sodium_crypto_aead_aegis256_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}

function sodium_crypto_aead_aegis256_encrypt(#[\SensitiveParameter] string $message, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string {}

function sodium_crypto_aead_aegis256_keygen(): string {}
#endif

function sodium_crypto_aead_chacha20poly1305_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}

function sodium_crypto_aead_chacha20poly1305_encrypt(#[\SensitiveParameter] string $message, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string {}
Expand Down
Loading