Skip to content

Commit ff8ebc8

Browse files
authored
Merge pull request #159 from JacobBarthelmeh/wrap_seed
use DHUK to wrap/unwrap seed value used for token
2 parents 9f8a3a1 + 3e013fe commit ff8ebc8

File tree

1 file changed

+141
-6
lines changed

1 file changed

+141
-6
lines changed

src/internal.c

Lines changed: 141 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,12 @@ static int wolfPKCS11_Store_GetMaxSize(int type, int variableSz)
982982
FIELD_SIZE(WP11_Token, userFailedLogin) +
983983
FIELD_SIZE(WP11_Token, userLastFailedLogin) +
984984
FIELD_SIZE(WP11_Token, userFailLoginTimeout) +
985+
#ifdef WOLFSSL_STM32U5_DHUK
986+
(sizeof(word32) + 16 + PIN_SEED_SZ) + /* length + IV +
987+
* encrypted seed */
988+
#else
985989
FIELD_SIZE(WP11_Token, seed) +
990+
#endif
986991
FIELD_SIZE(WP11_Token, objCnt) +
987992
FIELD_SIZE(WP11_Token, tokenFlags) +
988993
FIELD_SIZE(WP11_Token, nextObjId) +
@@ -5150,6 +5155,137 @@ static void wp11_Token_Final(WP11_Token* token)
51505155
static int HashPIN(char* pin, int pinLen, byte* seed, int seedLen, byte* hash,
51515156
int hashLen, WP11_Slot* slot);
51525157

5158+
#ifdef WOLFSSL_STM32U5_DHUK
5159+
/* DHUK seed storage: IV (16) + AES-CBC ciphertext of seed (16).
5160+
* Uses AES-CBC with DHUK so the decrypted seed is placed in token->seed
5161+
* for use by AES-GCM and other operations. */
5162+
#define WP11_SEED_DHUK_IV_SZ 16
5163+
#define WP11_SEED_WRAPPED_SZ (WP11_SEED_DHUK_IV_SZ + PIN_SEED_SZ)
5164+
5165+
#if defined(HAVE_AES_CBC)
5166+
/* Dummy key for wc_AesSetKey when using DHUK; hardware uses DHUK. */
5167+
static const byte wp11_dhuk_dummy_key[32] = {0};
5168+
5169+
static int wp11_token_write_seed_dhuk(void* storage, WP11_Token* token)
5170+
{
5171+
int ret;
5172+
Aes aes;
5173+
byte iv[WP11_SEED_DHUK_IV_SZ];
5174+
byte wrappedSeed[PIN_SEED_SZ];
5175+
/* Single buffer: big-endian word32 length + IV + encrypted seed */
5176+
byte buf[sizeof(word32) + WP11_SEED_DHUK_IV_SZ + PIN_SEED_SZ];
5177+
5178+
WP11_Lock_LockRW(&token->rngLock);
5179+
ret = wc_RNG_GenerateBlock(&token->rng, iv, sizeof(iv));
5180+
WP11_Lock_UnlockRW(&token->rngLock);
5181+
if (ret != 0)
5182+
return ret;
5183+
5184+
ret = wc_AesInit(&aes, NULL, WOLFSSL_STM32U5_DHUK_DEVID);
5185+
if (ret != 0)
5186+
return ret;
5187+
ret = wc_AesSetKey(&aes, wp11_dhuk_dummy_key, sizeof(wp11_dhuk_dummy_key),
5188+
iv, AES_ENCRYPTION);
5189+
if (ret != 0) {
5190+
wc_AesFree(&aes);
5191+
return ret;
5192+
}
5193+
ret = wc_AesCbcEncrypt(&aes, wrappedSeed, (const byte*)token->seed,
5194+
(word32)PIN_SEED_SZ);
5195+
wc_AesFree(&aes);
5196+
if (ret != 0)
5197+
return ret;
5198+
5199+
/* Assemble length (big-endian) + IV + encrypted seed into one buffer */
5200+
buf[0] = (byte)(WP11_SEED_WRAPPED_SZ >> 24);
5201+
buf[1] = (byte)(WP11_SEED_WRAPPED_SZ >> 16);
5202+
buf[2] = (byte)(WP11_SEED_WRAPPED_SZ >> 8);
5203+
buf[3] = (byte)(WP11_SEED_WRAPPED_SZ >> 0);
5204+
XMEMCPY(buf + sizeof(word32), iv, WP11_SEED_DHUK_IV_SZ);
5205+
XMEMCPY(buf + sizeof(word32) + WP11_SEED_DHUK_IV_SZ, wrappedSeed,
5206+
PIN_SEED_SZ);
5207+
5208+
/* Single write to avoid multiple flash size-update round-trips */
5209+
return wp11_storage_write(storage, buf, (int)sizeof(buf));
5210+
}
5211+
5212+
static int wp11_token_read_seed_dhuk(void* storage, WP11_Token* token)
5213+
{
5214+
int ret;
5215+
Aes aes;
5216+
byte iv[WP11_SEED_DHUK_IV_SZ];
5217+
word32 wrappedLen;
5218+
byte wrappedSeed[PIN_SEED_SZ];
5219+
/* Single buffer: big-endian word32 length + IV + encrypted seed */
5220+
byte buf[sizeof(word32) + WP11_SEED_DHUK_IV_SZ + PIN_SEED_SZ];
5221+
5222+
/* Single read to mirror the single write */
5223+
ret = wp11_storage_read(storage, buf, (int)sizeof(buf));
5224+
if (ret != 0)
5225+
return ret;
5226+
5227+
/* Parse length (big-endian word32) from the first 4 bytes */
5228+
wrappedLen = ((word32)buf[0] << 24) |
5229+
((word32)buf[1] << 16) |
5230+
((word32)buf[2] << 8) |
5231+
((word32)buf[3] << 0);
5232+
if (wrappedLen != WP11_SEED_WRAPPED_SZ) {
5233+
return BUFFER_E; /* This size check will likely catch if an older style
5234+
* token was read without DHUK wrapping. Treating it
5235+
* as a failure rather than continuing on to avoid
5236+
* using an unwrapped key when it is assumed that the
5237+
* seed was wrapped. */
5238+
}
5239+
5240+
/* Extract IV and encrypted seed from the buffer */
5241+
XMEMCPY(iv, buf + sizeof(word32), WP11_SEED_DHUK_IV_SZ);
5242+
XMEMCPY(wrappedSeed, buf + sizeof(word32) + WP11_SEED_DHUK_IV_SZ,
5243+
PIN_SEED_SZ);
5244+
5245+
ret = wc_AesInit(&aes, NULL, WOLFSSL_STM32U5_DHUK_DEVID);
5246+
if (ret != 0)
5247+
return ret;
5248+
ret = wc_AesSetKey(&aes, wp11_dhuk_dummy_key, sizeof(wp11_dhuk_dummy_key),
5249+
iv, AES_DECRYPTION);
5250+
if (ret != 0) {
5251+
wc_AesFree(&aes);
5252+
return ret;
5253+
}
5254+
ret = wc_AesCbcDecrypt(&aes, token->seed, wrappedSeed, PIN_SEED_SZ);
5255+
wc_AesFree(&aes);
5256+
return ret;
5257+
}
5258+
#else /* !HAVE_AES_CBC */
5259+
#error WOLFSSL_STM32U5_DHUK token seed storage requires HAVE_AES_CBC
5260+
#endif /* HAVE_AES_CBC */
5261+
#endif /* WOLFSSL_STM32U5_DHUK */
5262+
5263+
/**
5264+
* Read token seed from storage.
5265+
*/
5266+
static int wp11_token_read_seed(void* storage, WP11_Token* token)
5267+
{
5268+
#ifdef WOLFSSL_STM32U5_DHUK
5269+
return wp11_token_read_seed_dhuk(storage, token);
5270+
#else
5271+
return wp11_storage_read_fixed_array(storage, token->seed,
5272+
sizeof(token->seed));
5273+
#endif
5274+
}
5275+
5276+
/**
5277+
* Write token seed to storage.
5278+
*/
5279+
static int wp11_token_write_seed(void* storage, WP11_Token* token)
5280+
{
5281+
#ifdef WOLFSSL_STM32U5_DHUK
5282+
return wp11_token_write_seed_dhuk(storage, token);
5283+
#else
5284+
return wp11_storage_write_fixed_array(storage, token->seed,
5285+
sizeof(token->seed));
5286+
#endif
5287+
}
5288+
51535289
/**
51545290
* Load a token from storage.
51555291
*
@@ -5225,9 +5361,8 @@ static int wp11_Token_Load(WP11_Slot* slot, int tokenId, WP11_Token* token)
52255361
ret = wp11_storage_read_time(storage, &token->userFailLoginTimeout);
52265362
}
52275363
if (ret == 0) {
5228-
/* Read seed used to calculate key. (16) */
5229-
ret = wp11_storage_read_fixed_array(storage, token->seed,
5230-
sizeof(token->seed));
5364+
/* Read seed used to calculate key. */
5365+
ret = wp11_token_read_seed(storage, token);
52315366
}
52325367
if (ret == 0) {
52335368
/* Read count of object on token. (4) */
@@ -5426,9 +5561,8 @@ static int wp11_Token_Store(WP11_Token* token, int tokenId)
54265561
ret = wp11_storage_write_time(storage, token->userFailLoginTimeout);
54275562
}
54285563
if (ret == 0) {
5429-
/* Write seed used to calculate key. (16) */
5430-
ret = wp11_storage_write_fixed_array(storage, token->seed,
5431-
sizeof(token->seed));
5564+
/* Write seed used to calculate key. */
5565+
ret = wp11_token_write_seed(storage, token);
54325566
}
54335567

54345568
if (ret == 0) {
@@ -6304,6 +6438,7 @@ int WP11_Slot_UserLogin(WP11_Slot* slot, char* pin, int pinLen)
63046438
if (ret == 0) {
63056439
ret = WP11_Slot_CheckUserPin(slot, pin, pinLen);
63066440
#ifndef WOLFPKCS11_NO_STORE
6441+
/* Re-create token->key from PIN + token->seed (HashPIN) on load. */
63076442
if (ret == 0) {
63086443
ret = HashPIN(pin, pinLen, token->seed, sizeof(token->seed),
63096444
token->key, sizeof(token->key), slot);

0 commit comments

Comments
 (0)