@@ -1562,44 +1562,86 @@ static int openssl_derive(lua_State *L)
15621562 /* OpenSSL 3.0+ way: use PARAM API compatible check */
15631563 luaL_argcheck (L ,
15641564 (ptype == EVP_PKEY_DH && pkey_is_type (pkey , EVP_PKEY_DH ))
1565- || (ptype == EVP_PKEY_EC && pkey_is_type (pkey , EVP_PKEY_EC )),
1565+ || (ptype == EVP_PKEY_EC && pkey_is_type (pkey , EVP_PKEY_EC ))
1566+ #ifdef EVP_PKEY_X25519
1567+ || ptype == EVP_PKEY_X25519
1568+ #ifdef EVP_PKEY_X448
1569+ || ptype == EVP_PKEY_X448
1570+ #endif
1571+ #endif
1572+ ,
15661573 1 ,
1567- "only support DH or EC private key" );
1574+ "only support DH, EC, X25519 or X448 private key" );
15681575#else
15691576 /* OpenSSL 1.x way */
15701577 luaL_argcheck (L ,
15711578 (ptype == EVP_PKEY_DH && EVP_PKEY_get0_DH (pkey ) != NULL )
1572- || (ptype == EVP_PKEY_EC && EVP_PKEY_get0_EC_KEY (pkey ) != NULL ),
1579+ || (ptype == EVP_PKEY_EC && EVP_PKEY_get0_EC_KEY (pkey ) != NULL )
1580+ #ifdef EVP_PKEY_X25519
1581+ || ptype == EVP_PKEY_X25519
1582+ #ifdef EVP_PKEY_X448
1583+ || ptype == EVP_PKEY_X448
1584+ #endif
1585+ #endif
1586+ ,
15731587 1 ,
1574- "only support DH or EC private key" );
1588+ "only support DH, EC, X25519 or X448 private key" );
15751589#endif
15761590#elif !defined(OPENSSL_NO_DH )
15771591#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER )
15781592 /* OpenSSL 3.0+ way: use PARAM API compatible check */
15791593 luaL_argcheck (L ,
1580- ptype == EVP_PKEY_DH && pkey_is_type (pkey , EVP_PKEY_DH ),
1594+ (ptype == EVP_PKEY_DH && pkey_is_type (pkey , EVP_PKEY_DH ))
1595+ #ifdef EVP_PKEY_X25519
1596+ || ptype == EVP_PKEY_X25519
1597+ #ifdef EVP_PKEY_X448
1598+ || ptype == EVP_PKEY_X448
1599+ #endif
1600+ #endif
1601+ ,
15811602 1 ,
1582- "only support DH or EC private key" );
1603+ "only support DH, X25519 or X448 private key" );
15831604#else
15841605 /* OpenSSL 1.x way */
15851606 luaL_argcheck (L ,
1586- ptype == EVP_PKEY_DH && EVP_PKEY_get0_DH (pkey ) != NULL ,
1607+ (ptype == EVP_PKEY_DH && EVP_PKEY_get0_DH (pkey ) != NULL )
1608+ #ifdef EVP_PKEY_X25519
1609+ || ptype == EVP_PKEY_X25519
1610+ #ifdef EVP_PKEY_X448
1611+ || ptype == EVP_PKEY_X448
1612+ #endif
1613+ #endif
1614+ ,
15871615 1 ,
1588- "only support DH or EC private key" );
1616+ "only support DH, X25519 or X448 private key" );
15891617#endif
15901618#elif !defined(OPENSSL_NO_EC )
15911619#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER )
15921620 /* OpenSSL 3.0+ way: use PARAM API compatible check */
15931621 luaL_argcheck (L ,
1594- ptype == EVP_PKEY_EC && pkey_is_type (pkey , EVP_PKEY_EC ),
1622+ (ptype == EVP_PKEY_EC && pkey_is_type (pkey , EVP_PKEY_EC ))
1623+ #ifdef EVP_PKEY_X25519
1624+ || ptype == EVP_PKEY_X25519
1625+ #ifdef EVP_PKEY_X448
1626+ || ptype == EVP_PKEY_X448
1627+ #endif
1628+ #endif
1629+ ,
15951630 1 ,
1596- "only support DH or EC private key" );
1631+ "only support EC, X25519 or X448 private key" );
15971632#else
15981633 /* OpenSSL 1.x way */
15991634 luaL_argcheck (L ,
1600- ptype == EVP_PKEY_EC && EVP_PKEY_get0_EC_KEY (pkey ) != NULL ,
1635+ (ptype == EVP_PKEY_EC && EVP_PKEY_get0_EC_KEY (pkey ) != NULL )
1636+ #ifdef EVP_PKEY_X25519
1637+ || ptype == EVP_PKEY_X25519
1638+ #ifdef EVP_PKEY_X448
1639+ || ptype == EVP_PKEY_X448
1640+ #endif
1641+ #endif
1642+ ,
16011643 1 ,
1602- "only support DH or EC private key" );
1644+ "only support EC, X25519 or X448 private key" );
16031645#endif
16041646#endif
16051647
@@ -1663,9 +1705,27 @@ static int openssl_sign(lua_State *L)
16631705 if (is_SM2 ) md_alg = "sm3" ;
16641706#endif
16651707
1708+ /* For EdDSA keys (Ed25519, Ed448), allow NULL digest as they use
1709+ * internal hash functions. Detect EdDSA and allow omitting or explicitly passing nil. */
1710+ #ifdef EVP_PKEY_ED25519
1711+ {
1712+ int pkey_type = EVP_PKEY_type (EVP_PKEY_id (pkey ));
1713+ if (pkey_type == EVP_PKEY_ED25519
1714+ #ifdef EVP_PKEY_ED448
1715+ || pkey_type == EVP_PKEY_ED448
1716+ #endif
1717+ ) {
1718+ /* EdDSA keys don't need a digest - use NULL */
1719+ md = NULL ;
1720+ } else {
1721+ md = get_digest (L , 3 , md_alg );
1722+ }
1723+ }
1724+ #else
16661725 md = get_digest (L , 3 , md_alg );
1726+ #endif
16671727#if defined(OPENSSL_SUPPORT_SM2 )
1668- if (is_SM2 ) is_SM2 = EVP_MD_type (md ) == NID_sm3 ;
1728+ if (is_SM2 && md ) is_SM2 = EVP_MD_type (md ) == NID_sm3 ;
16691729#endif
16701730
16711731 ctx = EVP_MD_CTX_new ();
@@ -1682,20 +1742,38 @@ static int openssl_sign(lua_State *L)
16821742
16831743 ret = EVP_DigestSignInit (ctx , NULL , md , NULL , pkey );
16841744 if (ret == 1 ) {
1685- ret = EVP_DigestSignUpdate ( ctx , data , data_len );
1686- if ( ret == 1 ) {
1687- size_t siglen = 0 ;
1688- unsigned char * sigbuf = NULL ;
1689- ret = EVP_DigestSignFinal (ctx , NULL , & siglen );
1745+ #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined( LIBRESSL_VERSION_NUMBER )
1746+ /* For EdDSA (and other algorithms), use one-shot API if available (OpenSSL >= 1.1.1) */
1747+ if ( md == NULL ) {
1748+ size_t siglen = 0 ;
1749+ ret = EVP_DigestSign (ctx , NULL , & siglen , ( const unsigned char * ) data , data_len );
16901750 if (ret == 1 ) {
1691- siglen += 2 ;
1692- sigbuf = OPENSSL_malloc (siglen );
1693- ret = EVP_DigestSignFinal (ctx , sigbuf , & siglen );
1751+ unsigned char * sigbuf = OPENSSL_malloc (siglen );
1752+ ret = EVP_DigestSign (ctx , sigbuf , & siglen , (const unsigned char * )data , data_len );
16941753 if (ret == 1 ) {
16951754 lua_pushlstring (L , (char * )sigbuf , siglen );
16961755 }
16971756 OPENSSL_free (sigbuf );
16981757 }
1758+ } else
1759+ #endif
1760+ {
1761+ /* Traditional three-step approach for algorithms with digest */
1762+ ret = EVP_DigestSignUpdate (ctx , data , data_len );
1763+ if (ret == 1 ) {
1764+ size_t siglen = 0 ;
1765+ unsigned char * sigbuf = NULL ;
1766+ ret = EVP_DigestSignFinal (ctx , NULL , & siglen );
1767+ if (ret == 1 ) {
1768+ siglen += 2 ;
1769+ sigbuf = OPENSSL_malloc (siglen );
1770+ ret = EVP_DigestSignFinal (ctx , sigbuf , & siglen );
1771+ if (ret == 1 ) {
1772+ lua_pushlstring (L , (char * )sigbuf , siglen );
1773+ }
1774+ OPENSSL_free (sigbuf );
1775+ }
1776+ }
16991777 }
17001778 }
17011779
@@ -1741,7 +1819,25 @@ static int openssl_verify(lua_State *L)
17411819 if (is_SM2 ) md_alg = "sm3" ;
17421820#endif
17431821
1822+ /* For EdDSA keys (Ed25519, Ed448), allow NULL digest as they use
1823+ * internal hash functions. Detect EdDSA and allow omitting or explicitly passing nil. */
1824+ #ifdef EVP_PKEY_ED25519
1825+ {
1826+ int pkey_type = EVP_PKEY_type (EVP_PKEY_id (pkey ));
1827+ if (pkey_type == EVP_PKEY_ED25519
1828+ #ifdef EVP_PKEY_ED448
1829+ || pkey_type == EVP_PKEY_ED448
1830+ #endif
1831+ ) {
1832+ /* EdDSA keys don't need a digest - use NULL */
1833+ md = NULL ;
1834+ } else {
1835+ md = get_digest (L , 4 , md_alg );
1836+ }
1837+ }
1838+ #else
17441839 md = get_digest (L , 4 , md_alg );
1840+ #endif
17451841
17461842 ctx = EVP_MD_CTX_new ();
17471843#if defined(OPENSSL_SUPPORT_SM2 )
@@ -1758,11 +1854,24 @@ static int openssl_verify(lua_State *L)
17581854
17591855 ret = EVP_DigestVerifyInit (ctx , NULL , md , NULL , pkey );
17601856 if (ret == 1 ) {
1761- ret = EVP_DigestVerifyUpdate (ctx , data , data_len );
1762- if (ret == 1 ) {
1763- ret = EVP_DigestVerifyFinal (ctx , (unsigned char * )signature , signature_len );
1857+ #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER )
1858+ /* For EdDSA (and other algorithms), use one-shot API if available (OpenSSL >= 1.1.1) */
1859+ if (md == NULL ) {
1860+ ret = EVP_DigestVerify (ctx , (const unsigned char * )signature , signature_len ,
1861+ (const unsigned char * )data , data_len );
17641862 if (ret == 1 ) {
1765- lua_pushboolean (L , ret == 1 );
1863+ lua_pushboolean (L , 1 );
1864+ }
1865+ } else
1866+ #endif
1867+ {
1868+ /* Traditional three-step approach for algorithms with digest */
1869+ ret = EVP_DigestVerifyUpdate (ctx , data , data_len );
1870+ if (ret == 1 ) {
1871+ ret = EVP_DigestVerifyFinal (ctx , (unsigned char * )signature , signature_len );
1872+ if (ret == 1 ) {
1873+ lua_pushboolean (L , ret == 1 );
1874+ }
17661875 }
17671876 }
17681877 }
0 commit comments