Skip to content

Commit 55bbd58

Browse files
committed
LMS/HSS: cleanup, and safer write/read callbacks
1 parent 67bef21 commit 55bbd58

6 files changed

Lines changed: 127 additions & 69 deletions

File tree

INSTALL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
276276
$ git clone https://github.com/cisco/hash-sigs.git src
277277
$ cd src
278278

279-
In sha256.h, set USE_OPENSSl to 0:
279+
In sha256.h, set USE_OPENSSL to 0:
280280
#define USE_OPENSSL 0
281281

282282
Now build:

wolfcrypt/benchmark/benchmark.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7818,6 +7818,23 @@ static const byte lms_pub_L4_H5_W8[60] =
78187818
0x74,0x24,0x12,0xC8
78197819
};
78207820

7821+
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
7822+
{
7823+
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
7824+
* BE USED FOR TESTING PURPOSES! Production applications should
7825+
* write only to non-volatile storage. */
7826+
XMEMCPY(context, priv, privSz);
7827+
return WC_LMS_RC_SAVED_TO_NV_MEMORY;
7828+
}
7829+
7830+
static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
7831+
{
7832+
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
7833+
* BE USED FOR TESTING PURPOSES! */
7834+
XMEMCPY(priv, context, privSz);
7835+
return WC_LMS_RC_READ_TO_MEMORY;
7836+
}
7837+
78217838
static void bench_lms_sign_verify(enum wc_LmsParm parm)
78227839
{
78237840
LmsKey key;
@@ -7831,6 +7848,7 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
78317848
int times = 0;
78327849
int count = 0;
78337850
double start = 0.0F;
7851+
byte priv[HSS_MAX_PRIVATE_KEY_LEN];
78347852
const char * str = wc_LmsKey_ParmToStr(parm);
78357853

78367854
ret = wc_LmsKey_Init(&key, parm);
@@ -7841,32 +7859,32 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
78417859

78427860
switch (parm) {
78437861
case WC_LMS_PARM_L2_H10_W2:
7844-
XMEMCPY(key.priv, lms_priv_L2_H10_W2, sizeof(lms_priv_L2_H10_W2));
7862+
XMEMCPY(priv, lms_priv_L2_H10_W2, sizeof(lms_priv_L2_H10_W2));
78457863
XMEMCPY(key.pub, lms_pub_L2_H10_W2, sizeof(lms_pub_L2_H10_W2));
78467864
break;
78477865

78487866
case WC_LMS_PARM_L2_H10_W4:
7849-
XMEMCPY(key.priv, lms_priv_L2_H10_W4, sizeof(lms_priv_L2_H10_W4));
7867+
XMEMCPY(priv, lms_priv_L2_H10_W4, sizeof(lms_priv_L2_H10_W4));
78507868
XMEMCPY(key.pub, lms_pub_L2_H10_W4, sizeof(lms_pub_L2_H10_W4));
78517869
break;
78527870

78537871
case WC_LMS_PARM_L3_H5_W4:
7854-
XMEMCPY(key.priv, lms_priv_L3_H5_W4, sizeof(lms_priv_L3_H5_W4));
7872+
XMEMCPY(priv, lms_priv_L3_H5_W4, sizeof(lms_priv_L3_H5_W4));
78557873
XMEMCPY(key.pub, lms_pub_L3_H5_W4, sizeof(lms_pub_L3_H5_W4));
78567874
break;
78577875

78587876
case WC_LMS_PARM_L3_H5_W8:
7859-
XMEMCPY(key.priv, lms_priv_L3_H5_W8, sizeof(lms_priv_L3_H5_W8));
7877+
XMEMCPY(priv, lms_priv_L3_H5_W8, sizeof(lms_priv_L3_H5_W8));
78607878
XMEMCPY(key.pub, lms_pub_L3_H5_W8, sizeof(lms_pub_L3_H5_W8));
78617879
break;
78627880

78637881
case WC_LMS_PARM_L3_H10_W4:
7864-
XMEMCPY(key.priv, lms_priv_L3_H10_W4, sizeof(lms_priv_L3_H10_W4));
7882+
XMEMCPY(priv, lms_priv_L3_H10_W4, sizeof(lms_priv_L3_H10_W4));
78657883
XMEMCPY(key.pub, lms_pub_L3_H10_W4, sizeof(lms_pub_L3_H10_W4));
78667884
break;
78677885

78687886
case WC_LMS_PARM_L4_H5_W8:
7869-
XMEMCPY(key.priv, lms_priv_L4_H5_W8, sizeof(lms_priv_L4_H5_W8));
7887+
XMEMCPY(priv, lms_priv_L4_H5_W8, sizeof(lms_priv_L4_H5_W8));
78707888
XMEMCPY(key.pub, lms_pub_L4_H5_W8, sizeof(lms_pub_L4_H5_W8));
78717889
break;
78727890

@@ -7880,6 +7898,24 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
78807898
goto exit_lms_sign_verify;
78817899
}
78827900

7901+
ret = wc_LmsKey_SetWriteCb(&key, lms_write_key_mem);
7902+
if (ret) {
7903+
fprintf(stderr, "error: wc_LmsKey_SetWriteCb failed: %d\n", ret);
7904+
goto exit_lms_sign_verify;
7905+
}
7906+
7907+
ret = wc_LmsKey_SetReadCb(&key, lms_read_key_mem);
7908+
if (ret) {
7909+
fprintf(stderr, "error: wc_LmsKey_SetReadCb failed: %d\n", ret);
7910+
goto exit_lms_sign_verify;
7911+
}
7912+
7913+
ret = wc_LmsKey_SetContext(&key, (void *) priv);
7914+
if (ret) {
7915+
fprintf(stderr, "error: wc_LmsKey_SetContext failed: %d\n", ret);
7916+
goto exit_lms_sign_verify;
7917+
}
7918+
78837919
/* Even with saved priv/pub keys, we must still reload the private
78847920
* key before using it. Reloading the private key is the bottleneck
78857921
* for larger heights. Only print load time in debug builds. */
@@ -7933,12 +7969,6 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
79337969
printf("wc_LmsKey_Sign failed: %d\n", ret);
79347970
goto exit_lms_sign_verify;
79357971
}
7936-
7937-
/*ret = wc_LmsKey_Verify(&key, sig, sigSz, (byte *) msg, msgSz);
7938-
if (ret) {
7939-
printf("wc_LmsKey_Verify failed: %d\n", ret);
7940-
goto exit_lms_sign_verify;
7941-
}*/
79427972
}
79437973

79447974
count += times;

wolfcrypt/src/ext_lms.c

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,20 @@ static bool LmsWritePrivKey(unsigned char *private_key,
8383
return false;
8484
}
8585

86-
if (key->write_private_key != NULL) {
87-
/* Use write callback. */
88-
ret = key->write_private_key(private_key, len_private_key, key->context);
89-
90-
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
91-
WOLFSSL_MSG("error: LmsKey write_private_key failed");
92-
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
93-
key->state = WC_LMS_STATE_BAD;
94-
return false;
95-
}
86+
if (key->write_private_key == NULL) {
87+
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
88+
key->state = WC_LMS_STATE_NOT_INITED;
89+
return false;
9690
}
97-
else {
98-
/* Save to memory. */
99-
if (len_private_key > sizeof(key->priv)) {
100-
WOLFSSL_MSG("error: LmsWritePrivKey: private key too large");
101-
key->state = WC_LMS_STATE_BAD;
102-
return false;
103-
}
10491

105-
XMEMSET(key->priv, 0, sizeof(key->priv));
106-
XMEMCPY(key->priv, private_key, len_private_key);
92+
/* Use write callback. */
93+
ret = key->write_private_key(private_key, len_private_key, key->context);
94+
95+
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
96+
WOLFSSL_MSG("error: LmsKey write_private_key failed");
97+
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
98+
key->state = WC_LMS_STATE_BAD;
99+
return false;
107100
}
108101

109102
return true;
@@ -128,26 +121,20 @@ static bool LmsReadPrivKey(unsigned char *private_key,
128121
return false;
129122
}
130123

131-
if (key->read_private_key != NULL) {
132-
/* Use read callback. */
133-
ret = key->read_private_key(private_key, len_private_key, key->context);
134-
135-
if (ret != WC_LMS_RC_READ_TO_MEMORY) {
136-
WOLFSSL_MSG("error: LmsKey read_private_key failed");
137-
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
138-
key->state = WC_LMS_STATE_BAD;
139-
return false;
140-
}
124+
if (key->read_private_key == NULL) {
125+
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
126+
key->state = WC_LMS_STATE_NOT_INITED;
127+
return false;
141128
}
142-
else {
143-
/* Read from memory. */
144-
if (len_private_key > sizeof(key->priv)) {
145-
WOLFSSL_MSG("error: LmsReadPrivKey: private key too large");
146-
key->state = WC_LMS_STATE_BAD;
147-
return false;
148-
}
149129

150-
XMEMCPY(private_key, key->priv, len_private_key);
130+
/* Use read callback. */
131+
ret = key->read_private_key(private_key, len_private_key, key->context);
132+
133+
if (ret != WC_LMS_RC_READ_TO_MEMORY) {
134+
WOLFSSL_MSG("error: LmsKey read_private_key failed");
135+
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
136+
key->state = WC_LMS_STATE_BAD;
137+
return false;
151138
}
152139

153140
return true;
@@ -362,11 +349,6 @@ int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height,
362349

363350
hss_init_extra_info(&key->info);
364351

365-
/* The hash-sigs lib API will accept either:
366-
* 1. private key callbacks with context pointer, or
367-
* 2. context that points at private key.
368-
* Do the 2nd by default, unless user sets the callbacks through API. */
369-
370352
key->working_key = NULL;
371353
key->write_private_key = NULL;
372354
key->read_private_key = NULL;
@@ -407,6 +389,16 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
407389
return -1;
408390
}
409391

392+
if (key->write_private_key == NULL || key->read_private_key == NULL) {
393+
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
394+
return -1;
395+
}
396+
397+
if (key->context == NULL) {
398+
WOLFSSL_MSG("error: LmsKey context is not set");
399+
return -1;
400+
}
401+
410402
LmsRng = rng;
411403

412404
/* todo: The has-sigs lib allows you to save variable length auxiliary
@@ -449,24 +441,24 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
449441
return 0;
450442
}
451443

452-
int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb wf)
444+
int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb)
453445
{
454-
if (key == NULL || wf == NULL) {
446+
if (key == NULL || write_cb == NULL) {
455447
return BAD_FUNC_ARG;
456448
}
457449

458-
key->write_private_key = wf;
450+
key->write_private_key = write_cb;
459451

460452
return 0;
461453
}
462454

463-
int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb rf)
455+
int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb)
464456
{
465-
if (key == NULL || rf == NULL) {
457+
if (key == NULL || read_cb == NULL) {
466458
return BAD_FUNC_ARG;
467459
}
468460

469-
key->read_private_key = rf;
461+
key->read_private_key = read_cb;
470462

471463
return 0;
472464
}
@@ -499,6 +491,16 @@ int wc_LmsKey_Reload(LmsKey * key)
499491
return -1;
500492
}
501493

494+
if (key->write_private_key == NULL || key->read_private_key == NULL) {
495+
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
496+
return -1;
497+
}
498+
499+
if (key->context == NULL) {
500+
WOLFSSL_MSG("error: LmsKey context is not set");
501+
return -1;
502+
}
503+
502504
key->working_key = hss_load_private_key(LmsReadPrivKey, key,
503505
0, NULL, 0, &key->info);
504506

wolfcrypt/test/test.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34823,6 +34823,23 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void)
3482334823

3482434824

3482534825
#ifdef WOLFSSL_HAVE_LMS
34826+
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
34827+
{
34828+
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
34829+
* BE USED FOR TESTING PURPOSES! Production applications should
34830+
* write only to non-volatile storage. */
34831+
XMEMCPY(context, priv, privSz);
34832+
return WC_LMS_RC_SAVED_TO_NV_MEMORY;
34833+
}
34834+
34835+
static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
34836+
{
34837+
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
34838+
* BE USED FOR TESTING PURPOSES! */
34839+
XMEMCPY(priv, context, privSz);
34840+
return WC_LMS_RC_READ_TO_MEMORY;
34841+
}
34842+
3482634843
WOLFSSL_TEST_SUBROUTINE int lms_test(void)
3482734844
{
3482834845
int ret;
@@ -34834,6 +34851,7 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
3483434851
word32 sigSz = 0;
3483534852
const char * msg = "LMS HSS post quantum signature test";
3483634853
word32 msgSz = (word32) XSTRLEN(msg);
34854+
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
3483734855
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
3483834856

3483934857
XMEMSET(old_priv, 0, sizeof(old_priv));
@@ -34856,10 +34874,19 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
3485634874
ret = wc_LmsKey_Init_ex(&signingKey, 1, 5, 1, NULL, INVALID_DEVID);
3485734875
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
3485834876

34877+
ret = wc_LmsKey_SetWriteCb(&signingKey, lms_write_key_mem);
34878+
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
34879+
34880+
ret = wc_LmsKey_SetReadCb(&signingKey, lms_read_key_mem);
34881+
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
34882+
34883+
ret = wc_LmsKey_SetContext(&signingKey, (void *) priv);
34884+
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
34885+
3485934886
ret = wc_LmsKey_MakeKey(&signingKey, &rng);
3486034887
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
3486134888

34862-
XMEMCPY(old_priv, signingKey.priv, sizeof(signingKey.priv));
34889+
XMEMCPY(old_priv, priv, sizeof(priv));
3486334890

3486434891
ret = wc_LmsKey_ExportPub(&verifyKey, &signingKey);
3486534892
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
@@ -34885,12 +34912,12 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
3488534912
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
3488634913

3488734914
/* The updated private key should not match the old one. */
34888-
if (XMEMCMP(old_priv, signingKey.priv, sizeof(signingKey.priv)) == 0) {
34915+
if (XMEMCMP(old_priv, priv, sizeof(priv)) == 0) {
3488934916
printf("error: current priv key should not match old: %zu\n", i);
3489034917
return WC_TEST_RET_ENC_I(i);
3489134918
}
3489234919

34893-
XMEMCPY(old_priv, signingKey.priv, sizeof(signingKey.priv));
34920+
XMEMCPY(old_priv, priv, sizeof(priv));
3489434921

3489534922
ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
3489634923
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }

wolfssl/wolfcrypt/ext_lms.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ struct LmsKey {
5050
unsigned levels; /* Number of tree levels. */
5151
param_set_t lm_type[MAX_HSS_LEVELS]; /* Height parm per level. */
5252
param_set_t lm_ots_type[MAX_HSS_LEVELS]; /* Winternitz parm per level. */
53-
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
5453
unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN];
5554
hss_working_key * working_key;
5655
write_private_key_cb write_private_key; /* Callback to write/update key. */

wolfssl/wolfcrypt/lms.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ enum wc_LmsState {
104104
WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm);
105105
WOLFSSL_API int wc_LmsKey_Init_ex(LmsKey * key, int levels,
106106
int height, int winternitz, void* heap, int devId);
107-
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb wf);
108-
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb rf);
107+
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key,
108+
write_private_key_cb write_cb);
109+
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key,
110+
read_private_key_cb read_cb);
109111
WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context);
110112
WOLFSSL_API void wc_LmsKey_Free(LmsKey * key);
111113
WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng);
@@ -126,6 +128,4 @@ WOLFSSL_API const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsRc);
126128
#endif
127129

128130
#endif /* WOLFSSL_HAVE_LMS */
129-
130131
#endif /* WOLF_CRYPT_LMS_H */
131-

0 commit comments

Comments
 (0)