Skip to content

Commit 493a182

Browse files
Merge pull request #163 from Yu-Ma28051503/xmss
Support XMSS-XMSS^MT gnkey, sign and verify
2 parents 5f231f6 + 9d5d433 commit 493a182

File tree

12 files changed

+1517
-2
lines changed

12 files changed

+1517
-2
lines changed

src/clu_main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static const struct option mode_options[] = {
6161
{"ecc", no_argument, 0, WOLFCLU_ECC },
6262
{"ed25519", no_argument, 0, WOLFCLU_ED25519 },
6363
{"dilithium", no_argument, 0, WOLFCLU_DILITHIUM },
64+
{"xmss", no_argument, 0, WOLFCLU_XMSS },
65+
{"xmssmt", no_argument, 0, WOLFCLU_XMSSMT },
6466
{"dgst", no_argument, 0, WOLFCLU_DGST },
6567
{"verify", no_argument, 0, WOLFCLU_VERIFY },
6668
{"pkcs7", no_argument, 0, WOLFCLU_PKCS7 },
@@ -278,6 +280,8 @@ int main(int argc, char** argv)
278280
case WOLFCLU_ECC:
279281
case WOLFCLU_ED25519:
280282
case WOLFCLU_DILITHIUM:
283+
case WOLFCLU_XMSS:
284+
case WOLFCLU_XMSSMT:
281285
ret = wolfCLU_sign_verify_setup(argc, argv);
282286
break;
283287

src/genkey/clu_genkey.c

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)