@@ -1304,6 +1304,115 @@ int test_aes128_gcm_key_then_iv(void *data)
13041304 PRINT_MSG ("GCM key-then-iv with wolfProvider" );
13051305 err = test_gcm_key_then_iv_helper (wpLibCtx );
13061306 }
1307+
1308+ return err ;
1309+ }
1310+
1311+ /*
1312+ * GCM streaming decryption with a tampered authentication tag.
1313+ * Verifies that DecryptFinal correctly rejects a forged tag.
1314+ */
1315+ static int test_aes_gcm_bad_tag_helper (OSSL_LIB_CTX * libCtx ,
1316+ const char * cipherName , int keyLen )
1317+ {
1318+ int err = 0 ;
1319+ EVP_CIPHER * cipher = NULL ;
1320+ EVP_CIPHER_CTX * ctx = NULL ;
1321+ unsigned char key [32 ];
1322+ unsigned char iv [12 ];
1323+ unsigned char aad [] = "additional data" ;
1324+ unsigned char pt [] = "GCM plaintext for tag test" ;
1325+ int ptLen = (int )(sizeof (pt ) - 1 );
1326+ unsigned char ct [64 ];
1327+ unsigned char tag [16 ];
1328+ unsigned char dec [64 ];
1329+ int outLen = 0 , fLen = 0 ;
1330+
1331+ memset (key , 0xAA , keyLen );
1332+ memset (iv , 0xBB , sizeof (iv ));
1333+
1334+ cipher = EVP_CIPHER_fetch (libCtx , cipherName , "" );
1335+ if (cipher == NULL ) {
1336+ err = 1 ;
1337+ }
1338+
1339+ /* Encrypt */
1340+ if (err == 0 ) {
1341+ ctx = EVP_CIPHER_CTX_new ();
1342+ if (ctx == NULL )
1343+ err = 1 ;
1344+ }
1345+ if (err == 0 ) {
1346+ err = EVP_EncryptInit_ex (ctx , cipher , NULL , key , iv ) != 1 ;
1347+ }
1348+ if (err == 0 ) {
1349+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , aad ,
1350+ (int )(sizeof (aad ) - 1 )) != 1 ;
1351+ }
1352+ if (err == 0 ) {
1353+ err = EVP_EncryptUpdate (ctx , ct , & outLen , pt , ptLen ) != 1 ;
1354+ }
1355+ if (err == 0 ) {
1356+ err = EVP_EncryptFinal_ex (ctx , ct + outLen , & fLen ) != 1 ;
1357+ outLen += fLen ;
1358+ }
1359+ if (err == 0 ) {
1360+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_GET_TAG , 16 , tag ) != 1 ;
1361+ }
1362+ EVP_CIPHER_CTX_free (ctx );
1363+ ctx = NULL ;
1364+
1365+ /* Tamper with the tag */
1366+ if (err == 0 ) {
1367+ tag [0 ] ^= 0x01 ;
1368+ }
1369+
1370+ /* Decrypt with tampered tag -- must fail at DecryptFinal */
1371+ if (err == 0 ) {
1372+ ctx = EVP_CIPHER_CTX_new ();
1373+ if (ctx == NULL )
1374+ err = 1 ;
1375+ }
1376+ if (err == 0 ) {
1377+ err = EVP_DecryptInit_ex (ctx , cipher , NULL , key , iv ) != 1 ;
1378+ }
1379+ if (err == 0 ) {
1380+ err = EVP_DecryptUpdate (ctx , NULL , & fLen , aad ,
1381+ (int )(sizeof (aad ) - 1 )) != 1 ;
1382+ }
1383+ if (err == 0 ) {
1384+ err = EVP_DecryptUpdate (ctx , dec , & fLen , ct , outLen ) != 1 ;
1385+ }
1386+ if (err == 0 ) {
1387+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 16 , tag ) != 1 ;
1388+ }
1389+ if (err == 0 ) {
1390+ int ret = EVP_DecryptFinal_ex (ctx , dec + fLen , & fLen );
1391+ if (ret == 1 ) {
1392+ PRINT_ERR_MSG ("%s bad-tag: DecryptFinal should have failed" ,
1393+ cipherName );
1394+ err = 1 ;
1395+ }
1396+ }
1397+
1398+ EVP_CIPHER_CTX_free (ctx );
1399+ EVP_CIPHER_free (cipher );
1400+ return err ;
1401+ }
1402+
1403+ int test_aes_gcm_bad_tag (void * data )
1404+ {
1405+ int err = 0 ;
1406+
1407+ (void )data ;
1408+
1409+ PRINT_MSG ("AES-128-GCM streaming decryption with tampered tag" );
1410+ err = test_aes_gcm_bad_tag_helper (wpLibCtx , "AES-128-GCM" , 16 );
1411+ if (err == 0 ) {
1412+ PRINT_MSG ("AES-256-GCM streaming decryption with tampered tag" );
1413+ err = test_aes_gcm_bad_tag_helper (wpLibCtx , "AES-256-GCM" , 32 );
1414+ }
1415+
13071416 return err ;
13081417}
13091418
@@ -1356,5 +1465,141 @@ int test_aes128_ccm_tls(void *data)
13561465 EVP_CCM_TLS_FIXED_IV_LEN , 1 );
13571466}
13581467
1468+ /******************************************************************************/
1469+
1470+ /*
1471+ * CCM streaming decryption with a tampered authentication tag.
1472+ * Verifies that DecryptFinal correctly rejects a forged tag.
1473+ */
1474+ static int test_aes_ccm_bad_tag_helper (OSSL_LIB_CTX * libCtx ,
1475+ const char * cipherName , int keyLen )
1476+ {
1477+ int err = 0 ;
1478+ EVP_CIPHER * cipher = NULL ;
1479+ EVP_CIPHER_CTX * ctx = NULL ;
1480+ unsigned char key [32 ];
1481+ unsigned char iv [13 ];
1482+ unsigned char aad [] = "additional data" ;
1483+ unsigned char pt [] = "CCM plaintext for tag test" ;
1484+ int ptLen = (int )(sizeof (pt ) - 1 );
1485+ unsigned char ct [64 ];
1486+ unsigned char tag [16 ];
1487+ unsigned char dec [64 ];
1488+ int outLen = 0 , fLen = 0 ;
1489+
1490+ memset (key , 0xAA , keyLen );
1491+ memset (iv , 0xBB , sizeof (iv ));
1492+
1493+ cipher = EVP_CIPHER_fetch (libCtx , cipherName , "" );
1494+ if (cipher == NULL ) {
1495+ err = 1 ;
1496+ }
1497+
1498+ /* Encrypt */
1499+ if (err == 0 ) {
1500+ ctx = EVP_CIPHER_CTX_new ();
1501+ if (ctx == NULL )
1502+ err = 1 ;
1503+ }
1504+ if (err == 0 ) {
1505+ err = EVP_EncryptInit (ctx , cipher , NULL , NULL ) != 1 ;
1506+ }
1507+ if (err == 0 ) {
1508+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_IVLEN ,
1509+ (int )sizeof (iv ), NULL ) != 1 ;
1510+ }
1511+ if (err == 0 ) {
1512+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 16 , NULL ) != 1 ;
1513+ }
1514+ if (err == 0 ) {
1515+ err = EVP_EncryptInit (ctx , NULL , key , iv ) != 1 ;
1516+ }
1517+ if (err == 0 ) {
1518+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , NULL , ptLen ) != 1 ;
1519+ }
1520+ if (err == 0 ) {
1521+ err = EVP_EncryptUpdate (ctx , NULL , & outLen , aad ,
1522+ (int )(sizeof (aad ) - 1 )) != 1 ;
1523+ }
1524+ if (err == 0 ) {
1525+ err = EVP_EncryptUpdate (ctx , ct , & outLen , pt , ptLen ) != 1 ;
1526+ }
1527+ if (err == 0 ) {
1528+ err = EVP_EncryptFinal_ex (ctx , ct + outLen , & fLen ) != 1 ;
1529+ outLen += fLen ;
1530+ }
1531+ if (err == 0 ) {
1532+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_GET_TAG , 16 , tag ) != 1 ;
1533+ }
1534+ EVP_CIPHER_CTX_free (ctx );
1535+ ctx = NULL ;
1536+
1537+ /* Tamper with the tag */
1538+ if (err == 0 ) {
1539+ tag [0 ] ^= 0x01 ;
1540+ }
1541+
1542+ /* Decrypt with tampered tag -- must fail */
1543+ if (err == 0 ) {
1544+ ctx = EVP_CIPHER_CTX_new ();
1545+ if (ctx == NULL )
1546+ err = 1 ;
1547+ }
1548+ if (err == 0 ) {
1549+ err = EVP_DecryptInit (ctx , cipher , NULL , NULL ) != 1 ;
1550+ }
1551+ if (err == 0 ) {
1552+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_IVLEN ,
1553+ (int )sizeof (iv ), NULL ) != 1 ;
1554+ }
1555+ if (err == 0 ) {
1556+ err = EVP_CIPHER_CTX_ctrl (ctx , EVP_CTRL_AEAD_SET_TAG , 16 , tag ) != 1 ;
1557+ }
1558+ if (err == 0 ) {
1559+ err = EVP_DecryptInit (ctx , NULL , key , iv ) != 1 ;
1560+ }
1561+ if (err == 0 ) {
1562+ err = EVP_DecryptUpdate (ctx , NULL , & fLen , NULL , outLen ) != 1 ;
1563+ }
1564+ if (err == 0 ) {
1565+ err = EVP_DecryptUpdate (ctx , NULL , & fLen , aad ,
1566+ (int )(sizeof (aad ) - 1 )) != 1 ;
1567+ }
1568+ if (err == 0 ) {
1569+ /* CCM DecryptUpdate should fail with bad tag */
1570+ int ret = EVP_DecryptUpdate (ctx , dec , & fLen , ct , outLen );
1571+ if (ret == 1 ) {
1572+ /* If Update succeeded, Final must fail */
1573+ ret = EVP_DecryptFinal_ex (ctx , dec + fLen , & fLen );
1574+ if (ret == 1 ) {
1575+ PRINT_ERR_MSG ("%s bad-tag: decryption should have failed" ,
1576+ cipherName );
1577+ err = 1 ;
1578+ }
1579+ }
1580+ /* else: Update failed, which is also correct for CCM bad tag */
1581+ }
1582+
1583+ EVP_CIPHER_CTX_free (ctx );
1584+ EVP_CIPHER_free (cipher );
1585+ return err ;
1586+ }
1587+
1588+ int test_aes_ccm_bad_tag (void * data )
1589+ {
1590+ int err = 0 ;
1591+
1592+ (void )data ;
1593+
1594+ PRINT_MSG ("AES-128-CCM streaming decryption with tampered tag" );
1595+ err = test_aes_ccm_bad_tag_helper (wpLibCtx , "AES-128-CCM" , 16 );
1596+ if (err == 0 ) {
1597+ PRINT_MSG ("AES-256-CCM streaming decryption with tampered tag" );
1598+ err = test_aes_ccm_bad_tag_helper (wpLibCtx , "AES-256-CCM" , 32 );
1599+ }
1600+
1601+ return err ;
1602+ }
1603+
13591604#endif /* WP_HAVE_AESCCM */
13601605
0 commit comments