Skip to content

Commit 1816403

Browse files
authored
[sodium] Add AEGIS-128L and AEGIS-256 (#12867)
Also don't prevent usage of AES-GCM on aarch64, it's been supported since libsodium 1.0.18. Fixes #12312
1 parent e74bf42 commit 1816403

File tree

6 files changed

+525
-6
lines changed

6 files changed

+525
-6
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ SOAP:
8787
Sockets:
8888
. Removed the deprecated inet_ntoa call support. (David Carlier)
8989

90+
Sodium:
91+
. Add support for AEGIS-128L and AEGIS-256 (jedisct1)
92+
. Enable AES-GCM on aarch64 with the ARM crypto extensions (jedisct1)
93+
9094
Standard:
9195
. Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla)
9296
. Partly fix GH-12143 (Incorrect round() result for 0.49999999999999994).

UPGRADING

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@ PHP 8.4 UPGRADE NOTES
243243
. If JIT is enabled, PHP will now exit with a fatal error on startup in case
244244
of JIT startup initialization issues.
245245

246+
- Sodium:
247+
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
248+
functions to support the AEGIS family of authenticated encryption algorithms,
249+
that was introduced in libsodium 1.0.19.
250+
. sodium_crypto_aead_aes256gcm_*() functions are now enabled on aarch64 CPUs
251+
with the ARM cryptographic extensions.
252+
246253
========================================
247254
7. New Classes and Interfaces
248255
========================================

ext/sodium/libsodium.c

Lines changed: 261 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
static zend_class_entry *sodium_exception_ce;
3535

3636
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || \
37-
defined(_M_AMD64) || defined(_M_IX86))
37+
defined(_M_AMD64) || defined(_M_IX86) || defined(__aarch64__) || defined(_M_ARM64))
3838
# define HAVE_AESGCM 1
3939
#endif
4040

@@ -1866,6 +1866,236 @@ PHP_FUNCTION(sodium_crypto_aead_aes256gcm_decrypt)
18661866
}
18671867
#endif
18681868

1869+
#ifdef crypto_aead_aegis128l_KEYBYTES
1870+
PHP_FUNCTION(sodium_crypto_aead_aegis128l_encrypt)
1871+
{
1872+
zend_string *ciphertext;
1873+
unsigned char *ad;
1874+
unsigned char *msg;
1875+
unsigned char *npub;
1876+
unsigned char *secretkey;
1877+
unsigned long long ciphertext_real_len;
1878+
size_t ad_len;
1879+
size_t ciphertext_len;
1880+
size_t msg_len;
1881+
size_t npub_len;
1882+
size_t secretkey_len;
1883+
1884+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
1885+
&msg, &msg_len,
1886+
&ad, &ad_len,
1887+
&npub, &npub_len,
1888+
&secretkey, &secretkey_len) == FAILURE) {
1889+
sodium_remove_param_values_from_backtrace(EG(exception));
1890+
RETURN_THROWS();
1891+
}
1892+
if (npub_len != crypto_aead_aegis128l_NPUBBYTES) {
1893+
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES bytes long");
1894+
RETURN_THROWS();
1895+
}
1896+
if (secretkey_len != crypto_aead_aegis128l_KEYBYTES) {
1897+
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES bytes long");
1898+
RETURN_THROWS();
1899+
}
1900+
if (SIZE_MAX - msg_len <= crypto_aead_aegis128l_ABYTES) {
1901+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
1902+
RETURN_THROWS();
1903+
}
1904+
ciphertext_len = msg_len + crypto_aead_aegis128l_ABYTES;
1905+
ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
1906+
if (crypto_aead_aegis128l_encrypt
1907+
((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
1908+
(unsigned long long) msg_len,
1909+
ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
1910+
zend_string_efree(ciphertext);
1911+
zend_throw_exception(sodium_exception_ce, "internal error", 0);
1912+
RETURN_THROWS();
1913+
}
1914+
if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
1915+
ciphertext_real_len > ciphertext_len) {
1916+
zend_string_efree(ciphertext);
1917+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
1918+
RETURN_THROWS();
1919+
}
1920+
PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
1921+
ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
1922+
1923+
RETURN_NEW_STR(ciphertext);
1924+
}
1925+
1926+
PHP_FUNCTION(sodium_crypto_aead_aegis128l_decrypt)
1927+
{
1928+
zend_string *msg;
1929+
unsigned char *ad;
1930+
unsigned char *ciphertext;
1931+
unsigned char *npub;
1932+
unsigned char *secretkey;
1933+
unsigned long long msg_real_len;
1934+
size_t ad_len;
1935+
size_t ciphertext_len;
1936+
size_t msg_len;
1937+
size_t npub_len;
1938+
size_t secretkey_len;
1939+
1940+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
1941+
&ciphertext, &ciphertext_len,
1942+
&ad, &ad_len,
1943+
&npub, &npub_len,
1944+
&secretkey, &secretkey_len) == FAILURE) {
1945+
sodium_remove_param_values_from_backtrace(EG(exception));
1946+
RETURN_THROWS();
1947+
}
1948+
if (npub_len != crypto_aead_aegis128l_NPUBBYTES) {
1949+
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES bytes long");
1950+
RETURN_THROWS();
1951+
}
1952+
if (secretkey_len != crypto_aead_aegis128l_KEYBYTES) {
1953+
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES bytes long");
1954+
RETURN_THROWS();
1955+
}
1956+
if (ciphertext_len < crypto_aead_aegis128l_ABYTES) {
1957+
RETURN_FALSE;
1958+
}
1959+
msg_len = ciphertext_len;
1960+
if (msg_len >= SIZE_MAX) {
1961+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
1962+
RETURN_THROWS();
1963+
}
1964+
msg = zend_string_alloc((size_t) msg_len, 0);
1965+
if (crypto_aead_aegis128l_decrypt
1966+
((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
1967+
ciphertext, (unsigned long long) ciphertext_len,
1968+
ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
1969+
zend_string_efree(msg);
1970+
RETURN_FALSE;
1971+
}
1972+
if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
1973+
zend_string_efree(msg);
1974+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
1975+
RETURN_THROWS();
1976+
}
1977+
PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
1978+
ZSTR_VAL(msg)[msg_real_len] = 0;
1979+
1980+
RETURN_NEW_STR(msg);
1981+
}
1982+
#endif
1983+
1984+
#ifdef crypto_aead_aegis256_KEYBYTES
1985+
PHP_FUNCTION(sodium_crypto_aead_aegis256_encrypt)
1986+
{
1987+
zend_string *ciphertext;
1988+
unsigned char *ad;
1989+
unsigned char *msg;
1990+
unsigned char *npub;
1991+
unsigned char *secretkey;
1992+
unsigned long long ciphertext_real_len;
1993+
size_t ad_len;
1994+
size_t ciphertext_len;
1995+
size_t msg_len;
1996+
size_t npub_len;
1997+
size_t secretkey_len;
1998+
1999+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
2000+
&msg, &msg_len,
2001+
&ad, &ad_len,
2002+
&npub, &npub_len,
2003+
&secretkey, &secretkey_len) == FAILURE) {
2004+
sodium_remove_param_values_from_backtrace(EG(exception));
2005+
RETURN_THROWS();
2006+
}
2007+
if (npub_len != crypto_aead_aegis256_NPUBBYTES) {
2008+
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES bytes long");
2009+
RETURN_THROWS();
2010+
}
2011+
if (secretkey_len != crypto_aead_aegis256_KEYBYTES) {
2012+
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES bytes long");
2013+
RETURN_THROWS();
2014+
}
2015+
if (SIZE_MAX - msg_len <= crypto_aead_aegis256_ABYTES) {
2016+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
2017+
RETURN_THROWS();
2018+
}
2019+
ciphertext_len = msg_len + crypto_aead_aegis256_ABYTES;
2020+
ciphertext = zend_string_alloc((size_t) ciphertext_len, 0);
2021+
if (crypto_aead_aegis256_encrypt
2022+
((unsigned char *) ZSTR_VAL(ciphertext), &ciphertext_real_len, msg,
2023+
(unsigned long long) msg_len,
2024+
ad, (unsigned long long) ad_len, NULL, npub, secretkey) != 0) {
2025+
zend_string_efree(ciphertext);
2026+
zend_throw_exception(sodium_exception_ce, "internal error", 0);
2027+
RETURN_THROWS();
2028+
}
2029+
if (ciphertext_real_len <= 0U || ciphertext_real_len >= SIZE_MAX ||
2030+
ciphertext_real_len > ciphertext_len) {
2031+
zend_string_efree(ciphertext);
2032+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
2033+
RETURN_THROWS();
2034+
}
2035+
PHP_SODIUM_ZSTR_TRUNCATE(ciphertext, (size_t) ciphertext_real_len);
2036+
ZSTR_VAL(ciphertext)[ciphertext_real_len] = 0;
2037+
2038+
RETURN_NEW_STR(ciphertext);
2039+
}
2040+
2041+
PHP_FUNCTION(sodium_crypto_aead_aegis256_decrypt)
2042+
{
2043+
zend_string *msg;
2044+
unsigned char *ad;
2045+
unsigned char *ciphertext;
2046+
unsigned char *npub;
2047+
unsigned char *secretkey;
2048+
unsigned long long msg_real_len;
2049+
size_t ad_len;
2050+
size_t ciphertext_len;
2051+
size_t msg_len;
2052+
size_t npub_len;
2053+
size_t secretkey_len;
2054+
2055+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
2056+
&ciphertext, &ciphertext_len,
2057+
&ad, &ad_len,
2058+
&npub, &npub_len,
2059+
&secretkey, &secretkey_len) == FAILURE) {
2060+
sodium_remove_param_values_from_backtrace(EG(exception));
2061+
RETURN_THROWS();
2062+
}
2063+
if (npub_len != crypto_aead_aegis256_NPUBBYTES) {
2064+
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES bytes long");
2065+
RETURN_THROWS();
2066+
}
2067+
if (secretkey_len != crypto_aead_aegis256_KEYBYTES) {
2068+
zend_argument_error(sodium_exception_ce, 4, "must be SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES bytes long");
2069+
RETURN_THROWS();
2070+
}
2071+
if (ciphertext_len < crypto_aead_aegis256_ABYTES) {
2072+
RETURN_FALSE;
2073+
}
2074+
msg_len = ciphertext_len;
2075+
if (msg_len >= SIZE_MAX) {
2076+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
2077+
RETURN_THROWS();
2078+
}
2079+
msg = zend_string_alloc((size_t) msg_len, 0);
2080+
if (crypto_aead_aegis256_decrypt
2081+
((unsigned char *) ZSTR_VAL(msg), &msg_real_len, NULL,
2082+
ciphertext, (unsigned long long) ciphertext_len,
2083+
ad, (unsigned long long) ad_len, npub, secretkey) != 0) {
2084+
zend_string_efree(msg);
2085+
RETURN_FALSE;
2086+
}
2087+
if (msg_real_len >= SIZE_MAX || msg_real_len > msg_len) {
2088+
zend_string_efree(msg);
2089+
zend_throw_exception(sodium_exception_ce, "arithmetic overflow", 0);
2090+
RETURN_THROWS();
2091+
}
2092+
PHP_SODIUM_ZSTR_TRUNCATE(msg, (size_t) msg_real_len);
2093+
ZSTR_VAL(msg)[msg_real_len] = 0;
2094+
2095+
RETURN_NEW_STR(msg);
2096+
}
2097+
#endif
2098+
18692099
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt)
18702100
{
18712101
zend_string *ciphertext;
@@ -1881,10 +2111,10 @@ PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_encrypt)
18812111
size_t secretkey_len;
18822112

18832113
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssss",
1884-
&msg, &msg_len,
1885-
&ad, &ad_len,
1886-
&npub, &npub_len,
1887-
&secretkey, &secretkey_len) == FAILURE) {
2114+
&msg, &msg_len,
2115+
&ad, &ad_len,
2116+
&npub, &npub_len,
2117+
&secretkey, &secretkey_len) == FAILURE) {
18882118
sodium_remove_param_values_from_backtrace(EG(exception));
18892119
RETURN_THROWS();
18902120
}
@@ -2801,6 +3031,32 @@ PHP_FUNCTION(sodium_crypto_aead_aes256gcm_keygen)
28013031
}
28023032
#endif
28033033

3034+
#ifdef crypto_aead_aegis128l_KEYBYTES
3035+
PHP_FUNCTION(sodium_crypto_aead_aegis128l_keygen)
3036+
{
3037+
unsigned char key[crypto_aead_aegis128l_KEYBYTES];
3038+
3039+
if (zend_parse_parameters_none() == FAILURE) {
3040+
RETURN_THROWS();
3041+
}
3042+
crypto_aead_aegis128l_keygen(key);
3043+
RETURN_STRINGL((const char *) key, sizeof key);
3044+
}
3045+
#endif
3046+
3047+
#ifdef crypto_aead_aegis256_KEYBYTES
3048+
PHP_FUNCTION(sodium_crypto_aead_aegis256_keygen)
3049+
{
3050+
unsigned char key[crypto_aead_aegis256_KEYBYTES];
3051+
3052+
if (zend_parse_parameters_none() == FAILURE) {
3053+
RETURN_THROWS();
3054+
}
3055+
crypto_aead_aegis256_keygen(key);
3056+
RETURN_STRINGL((const char *) key, sizeof key);
3057+
}
3058+
#endif
3059+
28043060
PHP_FUNCTION(sodium_crypto_aead_chacha20poly1305_keygen)
28053061
{
28063062
unsigned char key[crypto_aead_chacha20poly1305_KEYBYTES];

ext/sodium/libsodium.stub.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,52 @@
4040
const SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES = UNKNOWN;
4141
#endif
4242

43+
#ifdef crypto_aead_aegis128l_KEYBYTES
44+
/**
45+
* @var int
46+
* @cvalue crypto_aead_aegis128l_KEYBYTES
47+
*/
48+
const SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES = UNKNOWN;
49+
/**
50+
* @var int
51+
* @cvalue crypto_aead_aegis128l_NSECBYTES
52+
*/
53+
const SODIUM_CRYPTO_AEAD_AEGIS128L_NSECBYTES = UNKNOWN;
54+
/**
55+
* @var int
56+
* @cvalue crypto_aead_aegis128l_NPUBBYTES
57+
*/
58+
const SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES = UNKNOWN;
59+
/**
60+
* @var int
61+
* @cvalue crypto_aead_aegis128l_ABYTES
62+
*/
63+
const SODIUM_CRYPTO_AEAD_AEGIS128L_ABYTES = UNKNOWN;
64+
#endif
65+
66+
#ifdef crypto_aead_aegis256_KEYBYTES
67+
/**
68+
* @var int
69+
* @cvalue crypto_aead_aegis256_KEYBYTES
70+
*/
71+
const SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES = UNKNOWN;
72+
/**
73+
* @var int
74+
* @cvalue crypto_aead_aegis256_NSECBYTES
75+
*/
76+
const SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES = UNKNOWN;
77+
/**
78+
* @var int
79+
* @cvalue crypto_aead_aegis256_NPUBBYTES
80+
*/
81+
const SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES = UNKNOWN;
82+
/**
83+
* @var int
84+
* @cvalue crypto_aead_aegis256_ABYTES
85+
*/
86+
const SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES = UNKNOWN;
87+
#endif
88+
4389
/**
4490
* @var int
4591
* @cvalue crypto_aead_chacha20poly1305_KEYBYTES
@@ -507,6 +553,22 @@ function sodium_crypto_aead_aes256gcm_encrypt(#[\SensitiveParameter] string $mes
507553
function sodium_crypto_aead_aes256gcm_keygen(): string {}
508554
#endif
509555

556+
#ifdef crypto_aead_aegis128l_KEYBYTES
557+
function sodium_crypto_aead_aegis128l_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}
558+
559+
function sodium_crypto_aead_aegis128l_encrypt(#[\SensitiveParameter] string $message, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string {}
560+
561+
function sodium_crypto_aead_aegis128l_keygen(): string {}
562+
#endif
563+
564+
#ifdef crypto_aead_aegis256_KEYBYTES
565+
function sodium_crypto_aead_aegis256_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}
566+
567+
function sodium_crypto_aead_aegis256_encrypt(#[\SensitiveParameter] string $message, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string {}
568+
569+
function sodium_crypto_aead_aegis256_keygen(): string {}
570+
#endif
571+
510572
function sodium_crypto_aead_chacha20poly1305_decrypt(string $ciphertext, string $additional_data, string $nonce, #[\SensitiveParameter] string $key): string|false {}
511573

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

0 commit comments

Comments
 (0)