@@ -1484,6 +1484,91 @@ int test_aes_gcm_tls_iv_fixed_oversized(void *data)
14841484 return err ;
14851485}
14861486
1487+ /*
1488+ * Test that GCM tags are at 32 bits.
1489+ */
1490+ static int test_aes_gcm_tag_len_undersized_helper (OSSL_LIB_CTX * libCtx ,
1491+ const char * cipherName , int keyLen )
1492+ {
1493+ int err ;
1494+ EVP_CIPHER * cipher = NULL ;
1495+ EVP_CIPHER_CTX * ctx = NULL ;
1496+ unsigned char key [32 ];
1497+ unsigned char iv [12 ];
1498+ unsigned char aad [] = "additional data" ;
1499+ unsigned char pt [] = "GCM plaintext for tag length test" ;
1500+ int ptLen = (int )(sizeof (pt ) - 1 );
1501+ unsigned char ct [64 ];
1502+ unsigned char tag [16 ];
1503+ int outLen = 0 , fLen = 0 ;
1504+
1505+ memset (key , 0xAA , keyLen );
1506+ memset (iv , 0xBB , sizeof (iv ));
1507+
1508+ cipher = EVP_CIPHER_fetch (libCtx , cipherName , "" );
1509+ err = cipher == NULL ;
1510+
1511+ /* Encrypt normally to get a valid ciphertext/full-size tag pair. */
1512+ if (err == 0 ) {
1513+ ctx = EVP_CIPHER_CTX_new ();
1514+ err = ctx == NULL ;
1515+ }
1516+ if (err == 0 ) {
1517+ err = EVP_EncryptInit (ctx , cipher , key , iv ) != 1 ;
1518+ }
1519+ if (err == 0 ) {
1520+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , aad ,
1521+ (int )(sizeof (aad ) - 1 )) != 1 ;
1522+ }
1523+ if (err == 0 ) {
1524+ err = EVP_EncryptUpdate (ctx , ct , & outLen , pt , ptLen ) != 1 ;
1525+ }
1526+ if (err == 0 ) {
1527+ err = EVP_EncryptFinal_ex (ctx , ct + outLen , & fLen ) != 1 ;
1528+ outLen += fLen ;
1529+ }
1530+ if (err == 0 ) {
1531+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_GET_TAG , sizeof (tag ),
1532+ tag ) != 1 ;
1533+ }
1534+ EVP_CIPHER_CTX_free (ctx );
1535+ ctx = NULL ;
1536+
1537+ /* A 1-byte tag length is below the NIST-mandated minimum (4 bytes)
1538+ * and must be rejected here. */
1539+ if (err == 0 ) {
1540+ ctx = EVP_CIPHER_CTX_new ();
1541+ err = ctx == NULL ;
1542+ }
1543+ if (err == 0 ) {
1544+ err = EVP_DecryptInit (ctx , cipher , NULL , NULL ) != 1 ;
1545+ }
1546+ if (err == 0 ) {
1547+ if (EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 1 , tag ) == 1 ) {
1548+ PRINT_ERR_MSG ("%s: EVP_CTRL_AEAD_SET_TAG incorrectly accepted "
1549+ "a 1-byte tag length" , cipherName );
1550+ err = 1 ;
1551+ }
1552+ }
1553+
1554+ EVP_CIPHER_CTX_free (ctx );
1555+ EVP_CIPHER_free (cipher );
1556+ return err ;
1557+ }
1558+
1559+ int test_aes_gcm_tag_len_undersized (void * data )
1560+ {
1561+ int err ;
1562+
1563+ (void )data ;
1564+
1565+ PRINT_MSG ("AES-128-GCM undersized tag length rejection" );
1566+ err = test_aes_gcm_tag_len_undersized_helper (wpLibCtx , "AES-128-GCM" ,
1567+ 16 );
1568+
1569+ return err ;
1570+ }
1571+
14871572#endif /* WP_HAVE_AESGCM */
14881573
14891574/******************************************************************************/
@@ -1669,5 +1754,108 @@ int test_aes_ccm_bad_tag(void *data)
16691754 return err ;
16701755}
16711756
1757+ /*
1758+ * Test that CCM tags are at least 32 bits.
1759+ */
1760+ static int test_aes_ccm_tag_len_undersized_helper (OSSL_LIB_CTX * libCtx ,
1761+ const char * cipherName , int keyLen )
1762+ {
1763+ int err ;
1764+ EVP_CIPHER * cipher = NULL ;
1765+ EVP_CIPHER_CTX * ctx = NULL ;
1766+ unsigned char key [32 ];
1767+ unsigned char iv [13 ];
1768+ unsigned char aad [] = "additional data" ;
1769+ unsigned char pt [] = "CCM plaintext for tag length test" ;
1770+ int ptLen = (int )(sizeof (pt ) - 1 );
1771+ unsigned char ct [64 ];
1772+ unsigned char tag [16 ];
1773+ int outLen = 0 , fLen = 0 ;
1774+
1775+ memset (key , 0xAA , keyLen );
1776+ memset (iv , 0xBB , sizeof (iv ));
1777+
1778+ cipher = EVP_CIPHER_fetch (libCtx , cipherName , "" );
1779+ err = cipher == NULL ;
1780+
1781+ /* Encrypt normally to get a valid ciphertext/full-size tag pair. */
1782+ if (err == 0 ) {
1783+ ctx = EVP_CIPHER_CTX_new ();
1784+ err = ctx == NULL ;
1785+ }
1786+ if (err == 0 ) {
1787+ err = EVP_EncryptInit (ctx , cipher , NULL , NULL ) != 1 ;
1788+ }
1789+ if (err == 0 ) {
1790+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_IVLEN ,
1791+ (int )sizeof (iv ), NULL ) != 1 ;
1792+ }
1793+ if (err == 0 ) {
1794+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , sizeof (tag ),
1795+ NULL ) != 1 ;
1796+ }
1797+ if (err == 0 ) {
1798+ err = EVP_EncryptInit (ctx , NULL , key , iv ) != 1 ;
1799+ }
1800+ if (err == 0 ) {
1801+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , NULL , ptLen ) != 1 ;
1802+ }
1803+ if (err == 0 ) {
1804+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , aad ,
1805+ (int )(sizeof (aad ) - 1 )) != 1 ;
1806+ }
1807+ if (err == 0 ) {
1808+ err = EVP_EncryptUpdate (ctx , ct , & outLen , pt , ptLen ) != 1 ;
1809+ }
1810+ if (err == 0 ) {
1811+ err = EVP_EncryptFinal_ex (ctx , ct + outLen , & fLen ) != 1 ;
1812+ outLen += fLen ;
1813+ }
1814+ if (err == 0 ) {
1815+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_GET_TAG , sizeof (tag ),
1816+ tag ) != 1 ;
1817+ }
1818+ EVP_CIPHER_CTX_free (ctx );
1819+ ctx = NULL ;
1820+
1821+ /* A 1-byte tag length is below the NIST-mandated minimum (4 bytes)
1822+ * and must be rejected here. */
1823+ if (err == 0 ) {
1824+ ctx = EVP_CIPHER_CTX_new ();
1825+ err = ctx == NULL ;
1826+ }
1827+ if (err == 0 ) {
1828+ err = EVP_DecryptInit (ctx , cipher , NULL , NULL ) != 1 ;
1829+ }
1830+ if (err == 0 ) {
1831+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_IVLEN ,
1832+ (int )sizeof (iv ), NULL ) != 1 ;
1833+ }
1834+ if (err == 0 ) {
1835+ if (EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 1 , tag ) == 1 ) {
1836+ PRINT_ERR_MSG ("%s: EVP_CTRL_AEAD_SET_TAG incorrectly accepted "
1837+ "a 1-byte tag length" , cipherName );
1838+ err = 1 ;
1839+ }
1840+ }
1841+
1842+ EVP_CIPHER_CTX_free (ctx );
1843+ EVP_CIPHER_free (cipher );
1844+ return err ;
1845+ }
1846+
1847+ int test_aes_ccm_tag_len_undersized (void * data )
1848+ {
1849+ int err ;
1850+
1851+ (void )data ;
1852+
1853+ PRINT_MSG ("AES-128-CCM undersized tag length rejection" );
1854+ err = test_aes_ccm_tag_len_undersized_helper (wpLibCtx , "AES-128-CCM" ,
1855+ 16 );
1856+
1857+ return err ;
1858+ }
1859+
16721860#endif /* WP_HAVE_AESCCM */
16731861
0 commit comments