Skip to content

Commit 0cce5bd

Browse files
authored
Merge pull request #185 from AlexLanzano/keywrap-demo-rebase
Implement Key Wrap Demo
2 parents 2e2281a + 0e94a29 commit 0cce5bd

File tree

11 files changed

+322
-139
lines changed

11 files changed

+322
-139
lines changed

examples/demo/client/wh_demo_client_all.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ int wh_DemoClient_All(whClientContext* clientContext)
4747
#endif
4848

4949
#ifdef WOLFHSM_CFG_KEYWRAP
50-
rc = wh_DemoClient_KeyWrapBasic(clientContext);
50+
rc = wh_DemoClient_KeyWrap(clientContext);
5151
if (rc != 0) {
5252
return rc;
5353
}

examples/demo/client/wh_demo_client_keywrap.c

Lines changed: 167 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,29 @@
3535

3636
#ifdef WOLFHSM_CFG_KEYWRAP
3737

38+
#define WH_TEST_KEKID 1
39+
static int _InitServerKek(whClientContext* ctx)
40+
{
41+
/* IMPORTANT NOTE: Server KEK is typically intrinsic or set during
42+
* provisioning. Uploading the KEK via the client is for testing purposes
43+
* only and not intended as a recommendation */
44+
whKeyId serverKeyId = WH_TEST_KEKID;
45+
whNvmFlags flags = WH_NVM_FLAGS_NONEXPORTABLE;
46+
uint8_t label[WH_NVM_LABEL_LEN] = "Server KEK key";
47+
uint8_t kek[] = {0x03, 0x03, 0x0d, 0xd9, 0xeb, 0x18, 0x17, 0x2e,
48+
0x06, 0x6e, 0x19, 0xce, 0x98, 0x44, 0x54, 0x0d,
49+
0x78, 0xa0, 0xbe, 0xe7, 0x35, 0x43, 0x40, 0xa4,
50+
0x22, 0x8a, 0xd1, 0x0e, 0xa3, 0x63, 0x1c, 0x0b};
51+
52+
return wh_Client_KeyCache(ctx, flags, label, sizeof(label), kek,
53+
sizeof(kek), &serverKeyId);
54+
}
55+
56+
static int _CleanupServerKek(whClientContext* ctx)
57+
{
58+
return wh_Client_KeyErase(ctx, WH_TEST_KEKID);
59+
}
60+
3861
#ifndef NO_AES
3962
#ifdef HAVE_AESGCM
4063

@@ -45,120 +68,202 @@
4568
#define WH_TEST_AES_WRAPPED_KEYSIZE \
4669
(WH_TEST_AES_IVSIZE + WH_TEST_AES_TAGSIZE + WH_TEST_AES_KEYSIZE + \
4770
sizeof(whNvmMetadata))
48-
#define WH_TEST_WRAPKEY_ID 8
71+
#define WH_TEST_AESGCM_WRAPKEY_ID 8
4972

50-
int wh_DemoClient_AesGcmKeyWrapBasic(whClientContext* ctx, WC_RNG* rng)
73+
int wh_DemoClient_AesGcmKeyWrap(whClientContext* client)
5174
{
5275
int ret = 0;
53-
uint8_t kek[WH_TEST_AES_KEYSIZE];
54-
uint8_t clientKey[WH_TEST_AES_KEYSIZE];
55-
uint8_t tmpClientKey[WH_TEST_AES_KEYSIZE];
76+
Aes aes[1];
77+
WC_RNG rng[1];
78+
uint8_t key[WH_TEST_AES_KEYSIZE];
79+
uint8_t exportedKey[WH_TEST_AES_KEYSIZE];
80+
whNvmMetadata metadata = {
81+
.id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, 0, WH_TEST_AESGCM_WRAPKEY_ID),
82+
.label = "AES Key Label",
83+
.access = WH_NVM_ACCESS_ANY,
84+
.len = WH_TEST_AES_KEYSIZE};
85+
whNvmMetadata exportedMetadata;
5686
uint8_t wrappedKey[WH_TEST_AES_WRAPPED_KEYSIZE];
57-
uint8_t label[WH_NVM_LABEL_LEN] = "Server AES Key Label";
58-
whKeyId serverKeyId;
5987
whKeyId wrappedKeyId;
60-
whNvmMetadata metadata = {.id = WH_TEST_WRAPKEY_ID,
61-
.label = "AES Key Label",
62-
.access = WH_NVM_ACCESS_ANY,
63-
.len = WH_TEST_AES_KEYSIZE};
64-
whNvmMetadata tmpMetadata;
65-
66-
/* Generate a random KEK to encrypt the client key */
67-
ret = wc_RNG_GenerateBlock(rng, kek, sizeof(kek));
68-
if (ret != 0) {
69-
printf("Failed to wc_RNG_GenerateBlock for key %d\n", ret);
88+
89+
const uint8_t plaintext[] = "hello, wolfSSL AES-GCM!";
90+
uint8_t ciphertext[sizeof(plaintext)];
91+
uint8_t decrypted[sizeof(plaintext)];
92+
93+
uint8_t tag[WH_TEST_AES_TAGSIZE];
94+
uint8_t iv[WH_TEST_AES_IVSIZE];
95+
const uint8_t aad[] = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe,
96+
0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
97+
0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2};
98+
99+
/* Initialize the server KEK */
100+
101+
/* The key wrap feature requires the server to have a Key Encryption Key
102+
* (I.E. KEK) available for the client to use. In the case of this demo we
103+
* have the client initializing the KEK which is not recommended. Typically
104+
* the KEK ID would be a hard coded value that the client and server share
105+
* and the KEK would be provisioned on the server prior to runtime */
106+
ret = _InitServerKek(client);
107+
if (ret != WH_ERROR_OK) {
108+
printf("Failed to _InitServerKek %d\n", ret);
70109
return ret;
71110
}
72111

73-
/* Generate a random client key */
74-
ret = wc_RNG_GenerateBlock(rng, clientKey, sizeof(clientKey));
112+
/* Generating and wrapping a key */
113+
114+
/* Initialize the RNG so we can generate an AES GCM key to wrap */
115+
ret = wc_InitRng_ex(rng, NULL, WH_DEV_ID);
75116
if (ret != 0) {
76-
printf("Failed to wc_RNG_GenerateBlock for key data %d\n", ret);
77-
return ret;
117+
printf("Failed to wc_InitRng_ex %d\n", ret);
118+
goto cleanup_kek;
78119
}
79120

80-
/* Request the server to cache the KEK and give us back a key ID*/
81-
ret = wh_Client_KeyCache(ctx, 0, label, sizeof(label), kek, sizeof(kek),
82-
&serverKeyId);
121+
/* Now we generate the AES GCM key using the RNG */
122+
ret = wc_RNG_GenerateBlock(rng, key, sizeof(key));
83123
if (ret != 0) {
84-
printf("Failed to wh_Client_KeyCache %d\n", ret);
85-
return ret;
124+
printf("Failed to wc_RNG_GenerateBlock for key data %d\n", ret);
125+
goto cleanup_rng;
86126
}
87127

88-
/* Request the server to wrap the client key using the KEK we just cached */
89-
ret = wh_Client_KeyWrap(ctx, WC_CIPHER_AES_GCM, serverKeyId, clientKey,
90-
sizeof(clientKey), &metadata, wrappedKey,
128+
/* Now we request the server to wrap the key using the KEK we
129+
* establish above in the first step. */
130+
ret = wh_Client_KeyWrap(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID, key,
131+
sizeof(key), &metadata, wrappedKey,
91132
sizeof(wrappedKey));
92133
if (ret != 0) {
93134
printf("Failed to wh_Client_KeyWrap %d\n", ret);
94-
return ret;
135+
goto cleanup_rng;
95136
}
96137

97-
/* Request the server to unwrap and cache the wrapped key we just created */
98-
ret = wh_Client_KeyUnwrapAndCache(ctx, WC_CIPHER_AES_GCM, serverKeyId,
138+
/* Now that the key is wrapped you store this in Non-Volatile Memory however
139+
* you wish */
140+
141+
142+
/* Using a wrapped key to do crypto operations*/
143+
144+
/* Request the server to unwrap and cache the wrapped key we just created.
145+
* This will provide us back a key ID that the client can use to do crypto
146+
* operations */
147+
ret = wh_Client_KeyUnwrapAndCache(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID,
99148
wrappedKey, sizeof(wrappedKey),
100149
&wrappedKeyId);
101150
if (ret != 0) {
102151
printf("Failed to wh_Client_KeyUnwrapAndCache %d\n", ret);
103-
return ret;
152+
goto cleanup_rng;
153+
}
154+
155+
/* Initialize AES context */
156+
ret = wc_AesInit(aes, NULL, WH_DEV_ID);
157+
if (ret != 0) {
158+
printf("Failed to wc_AesInit %d\n", ret);
159+
goto cleanup_cached_key;
160+
}
161+
162+
/* Set the key id for this AES context to the wrapped key ID that the server
163+
* provided us */
164+
ret = wh_Client_AesSetKeyId(aes, wrappedKeyId);
165+
if (ret != 0) {
166+
printf("Failed to wh_Client_AesSetKeyId %d\n", ret);
167+
goto cleanup_aes;
168+
}
169+
170+
/* Generate a random IV for the AES GCM encryption operation we are about to
171+
* do */
172+
ret = wc_RNG_GenerateBlock(rng, iv, sizeof(iv));
173+
if (ret != 0) {
174+
printf("Failed to wc_RNG_GenerateBlock for AES-GCM key %d\n", ret);
175+
goto cleanup_aes;
104176
}
105177

178+
/* Request the server to encrypt some data using the
179+
* unwrapped and cached key via the key ID */
180+
ret = wc_AesGcmEncrypt(aes, ciphertext, plaintext, sizeof(plaintext), iv,
181+
sizeof(iv), tag, sizeof(tag), aad, sizeof(aad));
182+
if (ret != 0) {
183+
printf("Failed to wc_AesGcmEncrypt %d\n", ret);
184+
goto cleanup_aes;
185+
}
186+
187+
/* Request the server to decrypt the encrypted data using the
188+
* unwrapped and cached key via the key ID */
189+
ret = wc_AesGcmDecrypt(aes, decrypted, /* out */
190+
ciphertext, sizeof(ciphertext), /* in, inLen */
191+
iv, sizeof(iv), /* iv, ivLen */
192+
tag, sizeof(tag), /* authTag, authTagSz */
193+
aad, sizeof(aad)); /* authIn (AAD), authInSz */
194+
if (ret != 0) {
195+
ret = WH_ERROR_ABORTED;
196+
printf("Failed to wc_AesGcmDecrypt %d\n", ret);
197+
goto cleanup_aes;
198+
}
199+
200+
/* Check if the decrypted data matches an expected value */
201+
if (memcmp(decrypted, plaintext, sizeof(decrypted)) != 0) {
202+
ret = WH_ERROR_ABORTED;
203+
printf("Decrypted value does not match expected value\n");
204+
goto cleanup_aes;
205+
}
206+
207+
/* Exporting a wrapped key */
208+
106209
/* Request the server to unwrap and export the wrapped key we created */
107-
ret = wh_Client_KeyUnwrapAndExport(
108-
ctx, WC_CIPHER_AES_GCM, serverKeyId, wrappedKey, sizeof(wrappedKey),
109-
&tmpMetadata, tmpClientKey, sizeof(tmpClientKey));
210+
ret = wh_Client_KeyUnwrapAndExport(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID,
211+
wrappedKey, sizeof(wrappedKey),
212+
&exportedMetadata, exportedKey,
213+
sizeof(exportedKey));
110214
if (ret != 0) {
111215
printf("Failed to wh_Client_KeyUnwrapAndCache %d\n", ret);
112-
return ret;
216+
goto cleanup_aes;
113217
}
114218

115-
116219
/* Compare the exported key to the client key we requested to wrap */
117-
if (memcmp(clientKey, tmpClientKey, sizeof(clientKey)) != 0) {
220+
if (memcmp(key, exportedKey, sizeof(key)) != 0) {
221+
ret = WH_ERROR_ABORTED;
118222
printf("AES GCM wrap/unwrap key failed to match\n");
119-
return ret;
223+
goto cleanup_aes;
120224
}
121225

122226
/* Compare the exported metadata to the metadata we requested to wrap */
123-
if (memcmp(&metadata, &tmpMetadata, sizeof(metadata)) != 0) {
227+
if (memcmp(&metadata, &exportedMetadata, sizeof(metadata)) != 0) {
228+
ret = WH_ERROR_ABORTED;
124229
printf("AES GCM wrap/unwrap metadata failed to match\n");
125-
return ret;
230+
goto cleanup_aes;
126231
}
127232

233+
cleanup_aes:
234+
wc_AesFree(aes);
235+
cleanup_cached_key:
236+
wh_Client_KeyErase(client, wrappedKeyId);
237+
cleanup_rng:
238+
wc_FreeRng(rng);
239+
cleanup_kek:
240+
_CleanupServerKek(client);
241+
128242
return ret;
129243
}
130244

131245
#endif /* HAVE_AESGCM */
132246

133-
int wh_DemoClient_AesKeyWrapBasic(whClientContext* clientContext, WC_RNG* rng)
134-
{
135-
int ret = WH_ERROR_OK;
136-
137-
#ifdef HAVE_AESGCM
138-
ret = wh_DemoClient_AesGcmKeyWrapBasic(clientContext, rng);
139-
#endif
140-
141-
return ret;
142-
}
143247

144248
#endif /* !NO_AES */
145-
int wh_DemoClient_KeyWrapBasic(whClientContext* clientContext)
249+
250+
int wh_DemoClient_KeyWrap(whClientContext* client)
146251
{
147252

148-
int ret;
149-
WC_RNG rng[1];
253+
int ret;
150254

151-
ret = wc_InitRng_ex(rng, NULL, WH_DEV_ID);
152-
if (ret != 0) {
153-
printf("Failed to wc_InitRng_ex %d\n", ret);
255+
#ifndef NO_AES
256+
#ifdef HAVE_AESGCM
257+
258+
ret = wh_DemoClient_AesGcmKeyWrap(client);
259+
if (ret != WH_ERROR_OK) {
260+
printf("Failed to wh_DemoClient_AesGcmKeyWrap %d\n", ret);
154261
return ret;
155262
}
156263

157-
#ifndef NO_AES
158-
ret = wh_DemoClient_AesKeyWrapBasic(clientContext, rng);
159-
#endif
264+
#endif /* !NO_AES */
265+
#endif /* HAVE_AESGCM */
160266

161-
wc_FreeRng(rng);
162267
return ret;
163268
}
164269
#endif /* WOLFHSM_CFG_KEYWRAP */

examples/demo/client/wh_demo_client_keywrap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44
#include "wolfhsm/wh_client.h"
55

6-
int wh_DemoClient_KeyWrapBasic(whClientContext* clientContext);
6+
int wh_DemoClient_KeyWrap(whClientContext* clientContext);
77

88
#endif /* !DEMO_CLIENT_KEYWRAP_H_ */

examples/posix/wh_posix_client/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c)
108108
# wolfHSM port/HAL code
109109
SRC_C += $(wildcard $(WOLFHSM_PORT_DIR)/*.c)
110110

111+
111112
# Project
112113
SRC_C += $(wildcard $(PROJECT_DIR)/*.c)
113114

examples/posix/wh_posix_client/wolfhsm_cfg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/** wolfHSM settings */
2929
#define WOLFHSM_CFG_ENABLE_CLIENT
3030
#define WOLFHSM_CFG_HEXDUMP
31-
#define WOLFHSM_CFG_COMM_DATA_LEN 1280
31+
#define WOLFHSM_CFG_COMM_DATA_LEN 5000
3232
#define WOLFHSM_CFG_KEYWRAP
3333

3434
#endif /* WOLFHSM_CFG_H_ */

examples/posix/wh_posix_server/wolfhsm_cfg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
#define WOLFHSM_CFG_CERTIFICATE_MANAGER
4545
#define WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT
4646

47+
#define WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE 5000
48+
4749
#define XMEMFENCE() __atomic_thread_fence(__ATOMIC_SEQ_CST)
4850
#define WOLFHSM_CFG_KEYWRAP
4951

src/wh_client_keywrap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Pick up compile-time configuration */
22
#include "wolfhsm/wh_settings.h"
33

4+
#if defined(WOLFHSM_CFG_KEYWRAP)
45
#if defined(WOLFHSM_CFG_ENABLE_CLIENT)
56
#include <stdint.h>
67
#include <wolfhsm/wh_client.h>
@@ -326,3 +327,4 @@ int wh_Client_KeyUnwrapAndCache(whClientContext* ctx,
326327
}
327328

328329
#endif /* WOLFHSM_CFG_ENABLE_CLIENT */
330+
#endif /* WOLFHSM_CFG_KEYWRAP */

test/config/wolfhsm_cfg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@
4646
/* Enable Image Manager feature */
4747
#define WOLFHSM_CFG_SERVER_IMG_MGR
4848

49+
#ifndef WOLFHSM_CFG_NO_CRYPTO
4950
#define WOLFHSM_CFG_KEYWRAP
51+
#endif
5052

5153
/* Only enable cancellation tests in POSIX test harness if using the
5254
* instrumented tests server. Otherwise CMAC is too fast to test cancellation */

0 commit comments

Comments
 (0)