@@ -1274,6 +1274,311 @@ int wolfCLU_genKey_Dilithium(WC_RNG* rng, char* fName, int directive, int fmt,
12741274#endif /* HAVE_DILITHIUM */
12751275}
12761276
1277+ /* The call back function of the writting xmss key */
1278+ #ifdef WOLFSSL_HAVE_XMSS
1279+ enum wc_XmssRc wolfCLU_XmssKey_WriteCb (const byte * priv ,
1280+ word32 privSz , void * context )
1281+ {
1282+ FILE * file = NULL ;
1283+ const char * filename = NULL ;
1284+ int n_cmp = 0 ;
1285+ size_t n_read = 0 ;
1286+ size_t n_write = 0 ;
1287+ byte * buff = NULL ;
1288+ int err = 0 ;
1289+
1290+ if (priv == NULL || context == NULL || privSz == 0 ) {
1291+ fprintf (stderr , "error: invalid write args\n" );
1292+ return WC_XMSS_RC_BAD_ARG ;
1293+ }
1294+
1295+ filename = context ;
1296+
1297+ /* Open file for read and write. */
1298+ file = fopen (filename , "rb+" );
1299+ if (!file ) {
1300+ /* Create the file if it didn't exist. */
1301+ file = fopen (filename , "wb+" );
1302+ if (!file ) {
1303+ fprintf (stderr , "error: fopen(%s, \"w+\") failed.\n" , filename );
1304+ return WC_XMSS_RC_WRITE_FAIL ;
1305+ }
1306+ }
1307+
1308+ n_write = fwrite (priv , 1 , privSz , file );
1309+
1310+ if (n_write != privSz ) {
1311+ fprintf (stderr , "error: wrote %zu, expected %d: %d\n" , n_write , privSz ,
1312+ ferror (file ));
1313+ return WC_XMSS_RC_WRITE_FAIL ;
1314+ }
1315+
1316+ err = fclose (file );
1317+ if (err ) {
1318+ fprintf (stderr , "error: fclose returned %d\n" , err );
1319+ return WC_XMSS_RC_WRITE_FAIL ;
1320+ }
1321+
1322+ /* Verify private key data has actually been written to persistent
1323+ * storage correctly. */
1324+ file = fopen (filename , "rb+" );
1325+ if (!file ) {
1326+ fprintf (stderr , "error: fopen(%s, \"r+\") failed.\n" , filename );
1327+ return WC_XMSS_RC_WRITE_FAIL ;
1328+ }
1329+
1330+ buff = malloc (privSz );
1331+ if (buff == NULL ) {
1332+ fprintf (stderr , "error: malloc(%d) failed\n" , privSz );
1333+ return WC_XMSS_RC_WRITE_FAIL ;
1334+ }
1335+
1336+ XMEMSET (buff , 0 , n_write );
1337+
1338+ n_read = fread (buff , 1 , n_write , file );
1339+
1340+ if (n_read != n_write ) {
1341+ fprintf (stderr , "error: read %zu, expected %zu: %d\n" , n_read , n_write ,
1342+ ferror (file ));
1343+ free (buff );
1344+ return WC_XMSS_RC_WRITE_FAIL ;
1345+ }
1346+
1347+ n_cmp = XMEMCMP (buff , priv , n_write );
1348+ free (buff );
1349+ buff = NULL ;
1350+
1351+ if (n_cmp != 0 ) {
1352+ fprintf (stderr , "error: write data was corrupted: %d\n" , n_cmp );
1353+ return WC_XMSS_RC_WRITE_FAIL ;
1354+ }
1355+
1356+ err = fclose (file );
1357+ if (err ) {
1358+ fprintf (stderr , "error: fclose returned %d\n" , err );
1359+ return WC_XMSS_RC_WRITE_FAIL ;
1360+ }
1361+
1362+ return WC_XMSS_RC_SAVED_TO_NV_MEMORY ;
1363+ }
1364+
1365+ enum wc_XmssRc wolfCLU_XmssKey_ReadCb (byte * priv ,
1366+ word32 privSz , void * context )
1367+ {
1368+ FILE * file = NULL ;
1369+ const char * filename = NULL ;
1370+ size_t n_read = 0 ;
1371+
1372+ if (priv == NULL || context == NULL || privSz == 0 ) {
1373+ fprintf (stderr , "error: invalid read args\n" );
1374+ return WC_XMSS_RC_BAD_ARG ;
1375+ }
1376+
1377+ filename = context ;
1378+
1379+ file = fopen (filename , "rb" );
1380+ if (!file ) {
1381+ fprintf (stderr , "error: fopen(%s, \"rb\") failed\n" , filename );
1382+ return WC_XMSS_RC_READ_FAIL ;
1383+ }
1384+
1385+ n_read = fread (priv , 1 , privSz , file );
1386+
1387+ if (n_read != privSz ) {
1388+ fprintf (stderr , "error: read %zu, expected %d: %d\n" , n_read , privSz ,
1389+ ferror (file ));
1390+ return WC_XMSS_RC_READ_FAIL ;
1391+ }
1392+
1393+ fclose (file );
1394+
1395+ return WC_XMSS_RC_READ_TO_MEMORY ;
1396+ }
1397+ #endif /* WOLFSSL_HAVE_XMSS */
1398+
1399+ int wolfCLU_genKey_XMSS (WC_RNG * rng , char * fName ,
1400+ int directive , const char * paramStr )
1401+ {
1402+ #ifdef WOLFSSL_HAVE_XMSS
1403+ int ret = 0 ;
1404+ int fNameSz = 0 ; /* file name without append */
1405+ int fExtSz = 6 ; /* size of ".priv\0" and ".pub\0\0" */
1406+ char fExtPriv [6 ] = ".priv\0" ;
1407+ char fExtPub [6 ] = ".pub\0\0" ;
1408+ char * fOutNameBuf = NULL ; /* file name + fExt */
1409+ XFILE file = NULL ; /* public key file */
1410+ byte * pubOutBuf = NULL ; /* public key buffer */
1411+ word32 pubOutBufSz = 0 ; /* public key buffer size */
1412+
1413+ #ifdef WOLFSSL_SMALL_STACK
1414+ XmssKey * key ;
1415+ key = (XmssKey * )XMALLOC (sizeof (XmssKey ),
1416+ HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
1417+ if (key == NULL ) {
1418+ wolfCLU_LogError ("Failed to allocate memory for XMSS key.\n" );
1419+ return MEMORY_E ;
1420+ }
1421+ #else
1422+ XmssKey key [1 ];
1423+ #endif
1424+
1425+ if (rng == NULL || fName == NULL ) {
1426+ wolfCLU_LogError ("Invalid arguments.\n" );
1427+ ret = BAD_FUNC_ARG ;
1428+ }
1429+
1430+ /* init the xmss key */
1431+ if (ret == 0 ) {
1432+ XMEMSET (key , 0 , sizeof (XmssKey ));
1433+ ret = wc_XmssKey_Init (key , HEAP_HINT , 0 );
1434+ if (ret != 0 ) {
1435+ wolfCLU_LogError ("Failed to initialize XMSS Key."
1436+ "\nRET: %d" , ret );
1437+ }
1438+ }
1439+
1440+ /* set the XMSS/XMSS^MT parametar strings */
1441+ if (ret == 0 ) {
1442+ ret = wc_XmssKey_SetParamStr (key , paramStr );
1443+ if (ret != 0 ) {
1444+ wolfCLU_LogError ("Failed to set parameter string."
1445+ "\nRET: %d" , ret );
1446+ }
1447+ }
1448+
1449+ /* set the CallBack function of wrtitting the XMSS/XMSS^MT key */
1450+ if (ret == 0 ) {
1451+ ret = wc_XmssKey_SetWriteCb (key , wolfCLU_XmssKey_WriteCb );
1452+ if (ret != 0 ) {
1453+ wolfCLU_LogError ("Failed to set write callback function."
1454+ "\nRET: %d" , ret );
1455+ }
1456+ }
1457+
1458+ /* set up the file name output buffer */
1459+ if (ret == 0 ) {
1460+ fNameSz = (int )XSTRLEN (fName );
1461+ fOutNameBuf = (char * )XMALLOC (fNameSz + fExtSz + 1 , HEAP_HINT ,
1462+ DYNAMIC_TYPE_TMP_BUFFER );
1463+ if (fOutNameBuf == NULL ) {
1464+ ret = MEMORY_E ;
1465+ wolfCLU_LogError ("Failed to allocate memory for file name buffer."
1466+ "\nRET: %d" , ret );
1467+ }
1468+ else {
1469+ XMEMSET (fOutNameBuf , 0 , fNameSz + fExtSz );
1470+ XMEMCPY (fOutNameBuf , fName , fNameSz );
1471+ XMEMCPY (fOutNameBuf + fNameSz , fExtPriv , fExtSz );
1472+
1473+ /* replace from '/' to '-' */
1474+ for (int i = 0 ; fOutNameBuf [i ] != '\0' ; i ++ ) {
1475+ if (fOutNameBuf [i ] == '/' ) {
1476+ fOutNameBuf [i ] = '-' ;
1477+ WOLFCLU_LOG (WOLFCLU_L0 , "INFO: Replace '/' to '-' in file name.\n" );
1478+ break ;
1479+ }
1480+ }
1481+
1482+ WOLFCLU_LOG (WOLFCLU_L0 , "Private key file = %s" , fOutNameBuf );
1483+ }
1484+ }
1485+
1486+ /* set the context of the XMSS/XMSS^MT key */
1487+ if (ret == 0 ) {
1488+ ret = wc_XmssKey_SetContext (key , fOutNameBuf );
1489+ if (ret != 0 ) {
1490+ wolfCLU_LogError ("Failed to set context.\nRET: %d" , ret );
1491+ }
1492+ }
1493+
1494+ /* make the xmss key */
1495+ if (ret == 0 ) {
1496+ ret = wc_XmssKey_MakeKey (key , rng );
1497+ if (ret != 0 ) {
1498+ wolfCLU_LogError ("Failed to make XMSS Key.\nRET: %d" , ret );
1499+ }
1500+ }
1501+
1502+ /* output XMSS/XMSS^MT public key */
1503+ if (ret == 0 && directive != PRIV_ONLY_FILE ) {
1504+ /* add on the final part of the file name ".pub" */
1505+ XMEMCPY (fOutNameBuf + fNameSz , fExtPub , fExtSz );
1506+ WOLFCLU_LOG (WOLFCLU_L0 , "Public key file = %s" , fOutNameBuf );
1507+
1508+ /* open the file for writing the public key */
1509+ file = XFOPEN (fOutNameBuf , "wb" );
1510+ if (file == NULL ) {
1511+ ret = OUTPUT_FILE_ERROR ;
1512+ wolfCLU_LogError ("unable to open file %s\nRET: %d" , fOutNameBuf , ret );
1513+ }
1514+
1515+ /* get the public key length */
1516+ if (ret == 0 ) {
1517+ ret = wc_XmssKey_GetPubLen (key , & pubOutBufSz );
1518+ if (ret != 0 ) {
1519+ wolfCLU_LogError ("Failed to get public key length."
1520+ "\nRET: %d" , ret );
1521+ }
1522+
1523+ if (pubOutBufSz == 0 ) {
1524+ WOLFCLU_LOG (WOLFCLU_L0 , "Public key length is 0.\n" );
1525+ ret = BAD_FUNC_ARG ;
1526+ }
1527+ }
1528+
1529+ /* allocate output public key buffer */
1530+ if (ret == 0 ) {
1531+ pubOutBuf = (byte * )XMALLOC (pubOutBufSz , HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
1532+ if (pubOutBuf == NULL ) {
1533+ wolfCLU_LogError ("Failed to allocate memory for public key buffer.\n" );
1534+ ret = MEMORY_E ;
1535+ }
1536+ }
1537+
1538+ /* write the public key to buffer */
1539+ if (ret == 0 ) {
1540+ ret = wc_XmssKey_ExportPubRaw (key , pubOutBuf , & pubOutBufSz );
1541+ if (ret != 0 ) {
1542+ wolfCLU_LogError ("Failed to write public key.\nRET: %d" , ret );
1543+ }
1544+ }
1545+
1546+ /* write to file */
1547+ if (ret == 0 ) {
1548+ if ((int )XFWRITE (pubOutBuf , 1 , pubOutBufSz , file ) <= 0 ) {
1549+ ret = OUTPUT_FILE_ERROR ;
1550+ }
1551+ }
1552+
1553+ if (file != NULL ) {
1554+ XFCLOSE (file );
1555+ }
1556+ }
1557+
1558+ /* clean allocated memory */
1559+ if (fOutNameBuf != NULL ) {
1560+ XFREE (fOutNameBuf , HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
1561+ }
1562+ if (pubOutBuf != NULL ) {
1563+ XFREE (pubOutBuf , HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
1564+ }
1565+
1566+ wc_XmssKey_Free (key );
1567+ #ifdef WOLFSSL_SMALL_STACK
1568+ XFREE (key , HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
1569+ #endif
1570+
1571+ return (ret == 0 ) ? WOLFCLU_SUCCESS : ret ;
1572+ #else
1573+ (void )rng ;
1574+ (void )fName ;
1575+ (void )directive ;
1576+ (void )paramStr ;
1577+
1578+ return NOT_COMPILED_IN ;
1579+ #endif /* HAVE_XMSS */
1580+ }
1581+
12771582#endif /* WOLFSSL_KEY_GEN && !NO_ASN*/
12781583
12791584
0 commit comments