2424#include "mysqlnd_priv.h"
2525#include "mysqlnd_charset.h"
2626#include "mysqlnd_debug.h"
27+ #ifdef MYSQLND_HAVE_LIBSODIUM
28+ #include <sodium.h>
29+ #include <sodium/crypto_hash_sha512.h>
30+ #include <sodium/crypto_scalarmult_ed25519.h>
31+ #include <sodium/crypto_core_ed25519.h>
32+ #endif
2733
2834static const char * const mysqlnd_old_passwd = "mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. "
2935"Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will "
@@ -1324,6 +1330,109 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_caching_sha2_auth_plugin
13241330#endif
13251331
13261332
1333+ #ifdef MYSQLND_HAVE_LIBSODIUM
1334+
1335+ static zend_uchar *
1336+ mysqlnd_ed25519_auth_data (struct st_mysqlnd_authentication_plugin * self ,
1337+ size_t * auth_data_len ,
1338+ MYSQLND_CONN_DATA * conn , const char * const user , const char * const passwd ,
1339+ const size_t passwd_len , zend_uchar * auth_plugin_data , const size_t auth_plugin_data_len ,
1340+ const MYSQLND_SESSION_OPTIONS * const session_options ,
1341+ const MYSQLND_PFC_DATA * const pfc_data ,
1342+ const zend_ulong mysql_flags
1343+ )
1344+ {
1345+ zend_uchar * ret = NULL ;
1346+ DBG_ENTER ("mysqlnd_ed25519_auth_data" );
1347+ DBG_INF_FMT ("salt(%zu)=[%.*s]" , auth_plugin_data_len , (int ) auth_plugin_data_len , auth_plugin_data );
1348+
1349+ // Ensure the salt length is exactly 32 bytes
1350+ if (auth_plugin_data_len != 32 ) {
1351+ DBG_ERR_FMT ("auth_plugin_data_len is %zu, expected 32" , auth_plugin_data_len );
1352+ DBG_RETURN (NULL );
1353+ }
1354+
1355+ * auth_data_len = 0 ;
1356+
1357+ // Inline signature creation logic
1358+ unsigned char h [64 ], r [64 ], k [64 ];
1359+ unsigned char * sm = NULL ;
1360+ unsigned char * s , * prefix ;
1361+
1362+ sm = malloc (auth_plugin_data_len + 64 );
1363+ if (!sm ) {
1364+ DBG_RETURN (NULL );
1365+ }
1366+
1367+ // h = SHA512(password)
1368+ crypto_hash_sha512 (h , (const unsigned char * )passwd , passwd_len );
1369+
1370+ // s = prune(h[0:31])
1371+ s = h ;
1372+ s [0 ] &= 248 ;
1373+ s [31 ] &= 127 ;
1374+ s [31 ] |= 64 ;
1375+
1376+ // prefix = h[32:63]
1377+ prefix = h + 32 ;
1378+
1379+ // r = SHA512(prefix || M)
1380+ memcpy (sm + 32 , prefix , 32 );
1381+ memcpy (sm + 64 , auth_plugin_data , auth_plugin_data_len );
1382+ crypto_hash_sha512 (r , sm + 32 , auth_plugin_data_len + 32 );
1383+
1384+ // R = encoded point [r]B
1385+ crypto_core_ed25519_scalar_reduce (r , r );
1386+ crypto_scalarmult_ed25519_base_noclamp (sm , r );
1387+
1388+ // A = encoded point [s]B
1389+ crypto_scalarmult_ed25519_base_noclamp (sm + 32 , s );
1390+
1391+ // k = SHA512(R || A || M)
1392+ crypto_hash_sha512 (k , sm , auth_plugin_data_len + 64 );
1393+
1394+ // S = (k * s + r) mod L
1395+ crypto_core_ed25519_scalar_reduce (k , k );
1396+ crypto_core_ed25519_scalar_mul (sm + 32 , k , s );
1397+ crypto_core_ed25519_scalar_add (sm + 32 , sm + 32 , r );
1398+
1399+ ret = malloc (64 );
1400+ if (ret ) {
1401+ memcpy (ret , sm , 64 );
1402+ * auth_data_len = 64 ;
1403+ }
1404+ free (sm );
1405+
1406+ DBG_RETURN (ret );
1407+ }
1408+ /* }}} */
1409+
1410+
1411+
1412+ static struct st_mysqlnd_authentication_plugin mysqlnd_ed25519_auth_plugin =
1413+ {
1414+ {
1415+ MYSQLND_PLUGIN_API_VERSION ,
1416+ "auth_plugin_client_ed25519" ,
1417+ MYSQLND_VERSION_ID ,
1418+ PHP_MYSQLND_VERSION ,
1419+ "PHP License 3.01" ,
1420+ "Diego Dupin <[email protected] >" ,
1421+ {
1422+ NULL , /* no statistics , will be filled later if there are some */
1423+ NULL , /* no statistics */
1424+ },
1425+ {
1426+ NULL /* plugin shutdown */
1427+ }
1428+ },
1429+ {/* methods */
1430+ mysqlnd_ed25519_auth_data ,
1431+ NULL
1432+ }
1433+ };
1434+ #endif
1435+
13271436/* {{{ mysqlnd_register_builtin_authentication_plugins */
13281437void
13291438mysqlnd_register_builtin_authentication_plugins (void )
@@ -1334,5 +1443,8 @@ mysqlnd_register_builtin_authentication_plugins(void)
13341443 mysqlnd_plugin_register_ex ((struct st_mysqlnd_plugin_header * ) & mysqlnd_caching_sha2_auth_plugin );
13351444 mysqlnd_plugin_register_ex ((struct st_mysqlnd_plugin_header * ) & mysqlnd_sha256_authentication_plugin );
13361445#endif
1446+ #ifdef MYSQLND_HAVE_LIBSODIUM
1447+ mysqlnd_plugin_register_ex ((struct st_mysqlnd_plugin_header * ) & mysqlnd_ed25519_auth_plugin );
1448+ #endif
13371449}
13381450/* }}} */
0 commit comments