1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/tests/api/test_keystore.c
Tobias Frauenschläger ba8ab7069e cryptocb: let wc_KeyStore_Derive() request the key size
Derive is the only key store operation that creates a key without any way to
say how big it should be. Every other one has an answer: ImportPlain has the
plaintext's length, ImportWrapped reads it from the blob, the exports and
GetInfo report a property of a key that already exists. Derive has keyType,
which is a purpose rather than a length - AES is 128 or 256 either way -
derivSz, which measures the input rather than the output, and attrs, which is
three flag bits. So the device picks, the caller cannot ask, and GetInfo then
reports a size the API gave no way to request.

Add keySz, in bytes, beside the keyType it qualifies. Zero keeps the current
behaviour and leaves the choice to the device, which is the right answer for a
key store whose derivation has only one output size.

PKCS#11 carries this in C_DeriveKey's template as CKA_VALUE_LEN and PSA in the
attributes passed to psa_key_derivation_output_key(); this is the same
parameter under a name that matches wc_KeyStore_ImportPlain().

The key store API reached master without a ChangeLog entry. Add one here, since
this is the last change to that API and the entry can describe it as it ships.
2026-09-10 12:16:57 +02:00

567 lines
23 KiB
C

/* test_keystore.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <tests/unit.h>
#include <tests/api/test_keystore.h>
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
#include <wolfssl/wolfcrypt/wc_keystore.h>
#include <wolfssl/wolfcrypt/cryptocb.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#define KS_TEST_DEVID 7654
/* What the last dispatch carried, so a test can assert the callback saw the
* arguments the caller passed rather than only that the call returned 0. */
typedef struct KsSeen {
int op;
int calls;
const void* ctx;
const byte* outBuf; /* the caller's output buffer, for exports */
const byte* keyRef;
word32 keyRefSz;
const byte* otherRef;
word32 otherRefSz;
word32 format;
word32 kdfType;
word32 attrs;
word32 keyType;
word32 keySz;
word32 blobSz;
const byte* deriv;
word32 derivSz;
} KsSeen;
static int KsCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
KsSeen* seen = (KsSeen*)ctx;
(void)devIdArg;
if (info == NULL || info->algo_type != WC_ALGO_TYPE_KEYSTORE) {
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
/* Clear what this call does not set, so an assertion can never pass on a
* value the previous call left behind. */
{
int calls = seen->calls;
XMEMSET(seen, 0, sizeof(*seen));
seen->calls = calls;
}
seen->calls++;
seen->op = info->keystore.type;
seen->ctx = info->keystore.ctx;
switch (info->keystore.type) {
case WC_KEYSTORE_IMPORT_PLAIN:
seen->keyRef = info->keystore.op.importPlain.keyRef;
seen->keyRefSz = info->keystore.op.importPlain.keyRefSz;
seen->keyType = info->keystore.op.importPlain.keyType;
seen->otherRef = info->keystore.op.importPlain.key;
seen->keySz = info->keystore.op.importPlain.keySz;
seen->attrs = info->keystore.op.importPlain.attrs;
break;
case WC_KEYSTORE_EXPORT_PLAIN:
seen->keyRef = info->keystore.op.exportPlain.keyRef;
seen->keyRefSz = info->keystore.op.exportPlain.keyRefSz;
seen->outBuf = info->keystore.op.exportPlain.key;
/* answer the size query so the caller can check it propagates */
if (info->keystore.op.exportPlain.key == NULL) {
*info->keystore.op.exportPlain.keySz = 32;
}
break;
case WC_KEYSTORE_IMPORT_WRAPPED:
seen->keyRef = info->keystore.op.importWrapped.keyRef;
seen->keyRefSz = info->keystore.op.importWrapped.keyRefSz;
seen->keyType = info->keystore.op.importWrapped.keyType;
seen->otherRef = info->keystore.op.importWrapped.wrapKeyRef;
seen->otherRefSz = info->keystore.op.importWrapped.wrapKeyRefSz;
seen->format = info->keystore.op.importWrapped.format;
seen->blobSz = info->keystore.op.importWrapped.blobSz;
seen->attrs = info->keystore.op.importWrapped.attrs;
break;
case WC_KEYSTORE_EXPORT_WRAPPED:
seen->keyRef = info->keystore.op.exportWrapped.keyRef;
seen->keyRefSz = info->keystore.op.exportWrapped.keyRefSz;
seen->otherRef = info->keystore.op.exportWrapped.wrapKeyRef;
seen->otherRefSz = info->keystore.op.exportWrapped.wrapKeyRefSz;
seen->format = info->keystore.op.exportWrapped.format;
seen->outBuf = info->keystore.op.exportWrapped.blob;
/* answer the size query so the caller can check it propagates */
if (info->keystore.op.exportWrapped.blob == NULL) {
*info->keystore.op.exportWrapped.blobSz = 40;
}
break;
case WC_KEYSTORE_DERIVE:
seen->keyRef = info->keystore.op.derive.keyRef;
seen->keyRefSz = info->keystore.op.derive.keyRefSz;
seen->otherRef = info->keystore.op.derive.srcKeyRef;
seen->otherRefSz = info->keystore.op.derive.srcKeyRefSz;
seen->keyType = info->keystore.op.derive.keyType;
seen->keySz = info->keystore.op.derive.keySz;
seen->attrs = info->keystore.op.derive.attrs;
seen->kdfType = info->keystore.op.derive.kdfType;
seen->deriv = info->keystore.op.derive.deriv;
seen->derivSz = info->keystore.op.derive.derivSz;
break;
case WC_KEYSTORE_DELETE:
seen->keyRef = info->keystore.op.deleteKey.keyRef;
seen->keyRefSz = info->keystore.op.deleteKey.keyRefSz;
break;
case WC_KEYSTORE_GET_INFO:
seen->keyRef = info->keystore.op.getInfo.keyRef;
seen->keyRefSz = info->keystore.op.getInfo.keyRefSz;
/* each output is optional; a device must not assume otherwise */
if (info->keystore.op.getInfo.keyType != NULL) {
*info->keystore.op.getInfo.keyType = WC_KEYSTORE_KEY_WRAP;
}
if (info->keystore.op.getInfo.keyBits != NULL) {
*info->keystore.op.getInfo.keyBits = 256;
}
if (info->keystore.op.getInfo.attrs != NULL) {
*info->keystore.op.getInfo.attrs = WC_KEYSTORE_ATTR_UNWRAP_ONLY;
}
break;
default:
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
}
return 0;
}
static const byte ksPlain[] = { 0x30, 0x31, 0x32, 0x33, 0x34 };
static const byte ksKeyRef[] = { 0x01, 0x02, 0x03, 0x04 };
static const byte ksOtherRef[] = { 0x11, 0x12 };
static const byte ksBlob[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static const byte ksDeriv[] = { 0x21, 0x22, 0x23 };
/* Sentinel for the caller context every entry point forwards untouched. */
static const byte ksCallerCtx[] = { 0x5a };
#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_KEYSTORE */
int test_wc_KeyStore_ImportPlain(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
/* WC_KEYSTORE_KEY_WRAP and WC_KEYSTORE_ATTR_EXPORTABLE are both 1, so a
* swap would compile and run. Assert each landed in its own field. */
ExpectIntEQ(wc_KeyStore_ImportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
WC_KEYSTORE_KEY_HMAC, ksPlain, (word32)sizeof(ksPlain),
WC_KEYSTORE_ATTR_EXPORTABLE, ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_IMPORT_PLAIN);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectIntEQ(seen.keyType, WC_KEYSTORE_KEY_HMAC);
ExpectPtrEq(seen.otherRef, ksPlain);
ExpectIntEQ(seen.keySz, (word32)sizeof(ksPlain));
ExpectIntEQ(seen.attrs, WC_KEYSTORE_ATTR_EXPORTABLE);
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* arguments are validated before the device is consulted */
seen.calls = 0;
ExpectIntEQ(wc_KeyStore_ImportPlain(KS_TEST_DEVID, NULL, 0,
WC_KEYSTORE_KEY_AES, ksPlain, (word32)sizeof(ksPlain), 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_KeyStore_ImportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
WC_KEYSTORE_KEY_AES, NULL, 0, 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_ExportPlain(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
byte out[64];
word32 outSz = (word32)sizeof(out);
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
ExpectIntEQ(wc_KeyStore_ExportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), out, &outSz, ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_EXPORT_PLAIN);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* the device must be handed the caller's own buffer to write into */
ExpectPtrEq(seen.outBuf, out);
/* key == NULL is the size query and must still reach the device */
outSz = 0;
ExpectIntEQ(wc_KeyStore_ExportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, &outSz, NULL), 0);
ExpectIntEQ(outSz, 32);
ExpectPtrEq(seen.outBuf, NULL);
/* a buffer with no size is not a size query, it is a mistake */
seen.calls = 0;
outSz = 0;
ExpectIntEQ(wc_KeyStore_ExportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), out, &outSz, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_KeyStore_ExportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), out, NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_ImportWrapped(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_VENDOR, ksBlob, (word32)sizeof(ksBlob),
WC_KEYSTORE_ATTR_PERSISTENT, ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_IMPORT_WRAPPED);
ExpectIntEQ(seen.keyType, WC_KEYSTORE_KEY_AES);
ExpectIntEQ(seen.attrs, WC_KEYSTORE_ATTR_PERSISTENT);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectPtrEq(seen.otherRef, ksOtherRef);
ExpectIntEQ(seen.otherRefSz, (word32)sizeof(ksOtherRef));
ExpectIntEQ(seen.format, WC_KEYWRAP_FORMAT_VENDOR);
ExpectIntEQ(seen.blobSz, (word32)sizeof(ksBlob));
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* arguments are validated before the device is consulted */
seen.calls = 0;
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID, NULL, 0,
WC_KEYSTORE_KEY_AES, ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_VENDOR, ksBlob, (word32)sizeof(ksBlob), 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_VENDOR, NULL, 0, 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* A NULL wrapping key means "use the device's own", so a length beside
* it is a caller mistake rather than an implicit-key request. */
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES,
NULL, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_VENDOR, ksBlob, (word32)sizeof(ksBlob), 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
/* The implicit wrapping key: NULL with no length reaches the device. */
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES, NULL, 0,
WC_KEYWRAP_FORMAT_VENDOR, ksBlob, (word32)sizeof(ksBlob), 0, NULL),
0);
ExpectIntEQ(seen.op, WC_KEYSTORE_IMPORT_WRAPPED);
ExpectPtrEq(seen.otherRef, NULL);
ExpectIntEQ(seen.otherRefSz, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_ExportWrapped(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
byte out[64];
word32 outSz = (word32)sizeof(out);
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, out, &outSz, ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_EXPORT_WRAPPED);
/* Which reference is the key and which is the KEK: a transposition in the
* dispatcher is invisible without this. */
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectPtrEq(seen.otherRef, ksOtherRef);
ExpectIntEQ(seen.otherRefSz, (word32)sizeof(ksOtherRef));
ExpectIntEQ(seen.format, WC_KEYWRAP_FORMAT_AESKW);
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* the device must be handed the caller's own buffer to write into */
ExpectPtrEq(seen.outBuf, out);
/* blob == NULL is the size query and must still reach the device */
outSz = 0;
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, NULL, &outSz, NULL), 0);
ExpectIntEQ(outSz, 40);
ExpectPtrEq(seen.outBuf, NULL);
/* a buffer with no size is not a size query, it is a mistake */
seen.calls = 0;
outSz = 0;
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, out, &outSz, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, out, NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
outSz = (word32)sizeof(out);
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
NULL, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, out, &outSz, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
/* The implicit wrapping key: NULL with no length reaches the device. */
outSz = (word32)sizeof(out);
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, 0,
WC_KEYWRAP_FORMAT_AESKW, out, &outSz, NULL), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_EXPORT_WRAPPED);
ExpectPtrEq(seen.otherRef, NULL);
ExpectIntEQ(seen.otherRefSz, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_Derive(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
/* WC_KDF_TYPE_HKDF and WC_KEYSTORE_ATTR_EXPORTABLE are both 1, so keep
* kdfType and attrs numerically apart or a transposition reads as equal. */
ExpectIntEQ(wc_KeyStore_Derive(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES,
AES_256_KEY_SIZE, ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KDF_TYPE_HKDF, ksDeriv, (word32)sizeof(ksDeriv),
WC_KEYSTORE_ATTR_PERSISTENT, ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_DERIVE);
ExpectIntEQ(seen.keyType, WC_KEYSTORE_KEY_AES);
ExpectIntEQ(seen.keySz, AES_256_KEY_SIZE);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectPtrEq(seen.otherRef, ksOtherRef);
ExpectIntEQ(seen.otherRefSz, (word32)sizeof(ksOtherRef));
ExpectIntEQ(seen.attrs, WC_KEYSTORE_ATTR_PERSISTENT);
ExpectIntEQ(seen.kdfType, WC_KDF_TYPE_HKDF);
ExpectPtrEq(seen.deriv, ksDeriv);
ExpectIntEQ(seen.derivSz, (word32)sizeof(ksDeriv));
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* WC_KDF_TYPE_NONE asks for the device's own derivation */
ExpectIntEQ(wc_KeyStore_Derive(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_NONE, 0,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KDF_TYPE_NONE, ksDeriv, (word32)sizeof(ksDeriv),
WC_KEYSTORE_ATTR_EXPORTABLE, NULL), 0);
ExpectIntEQ(seen.kdfType, WC_KDF_TYPE_NONE);
ExpectIntEQ(seen.keySz, 0); /* 0 leaves the size to the device */
ExpectIntEQ(seen.attrs, WC_KEYSTORE_ATTR_EXPORTABLE);
seen.calls = 0;
ExpectIntEQ(wc_KeyStore_Derive(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES, 0, NULL, 0,
WC_KDF_TYPE_NONE, ksDeriv, (word32)sizeof(ksDeriv), 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* No derivation data means no length beside it. */
ExpectIntEQ(wc_KeyStore_Derive(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES, 0,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KDF_TYPE_NONE, NULL, (word32)sizeof(ksDeriv), 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_Delete(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
ExpectIntEQ(wc_KeyStore_Delete(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_DELETE);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectPtrEq(seen.ctx, ksCallerCtx);
seen.calls = 0;
ExpectIntEQ(wc_KeyStore_Delete(KS_TEST_DEVID, ksKeyRef, 0, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_GetInfo(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
KsSeen seen;
word32 keyType = 0xDEADBEEF;
word32 keySz = 0xDEADBEEF;
word32 attrs = 0xDEADBEEF;
XMEMSET(&seen, 0, sizeof(seen));
ExpectIntEQ(wc_CryptoCb_RegisterDevice(KS_TEST_DEVID, KsCb, &seen), 0);
/* A wrapping key must be nameable: NONE here is indistinguishable from
* an empty slot. */
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), &keyType, &keySz, &attrs,
ksCallerCtx), 0);
ExpectIntEQ(seen.op, WC_KEYSTORE_GET_INFO);
ExpectPtrEq(seen.keyRef, ksKeyRef);
ExpectIntEQ(seen.keyRefSz, (word32)sizeof(ksKeyRef));
ExpectIntEQ(keyType, WC_KEYSTORE_KEY_WRAP);
ExpectIntEQ(keySz, 256);
ExpectIntEQ(attrs, WC_KEYSTORE_ATTR_UNWRAP_ONLY);
ExpectPtrEq(seen.ctx, ksCallerCtx);
/* Each output is optional and asked for on its own. */
keyType = 0xDEADBEEF;
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), &keyType, NULL, NULL, NULL), 0);
ExpectIntEQ(keyType, WC_KEYSTORE_KEY_WRAP);
keySz = 0xDEADBEEF;
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, &keySz, NULL, NULL), 0);
ExpectIntEQ(keySz, 256);
attrs = 0xDEADBEEF;
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, NULL, &attrs, NULL), 0);
ExpectIntEQ(attrs, WC_KEYSTORE_ATTR_UNWRAP_ONLY);
/* Asking for nothing still reaches the device, and writes nowhere. */
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, NULL, NULL, NULL), 0);
/* arguments are validated before the device is consulted */
seen.calls = 0;
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID, NULL, 0,
&keyType, &keySz, &attrs, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID, ksKeyRef, 0,
&keyType, &keySz, &attrs, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(seen.calls, 0);
wc_CryptoCb_UnRegisterDevice(KS_TEST_DEVID);
#endif
return EXPECT_RESULT();
}
int test_wc_KeyStore_NoDevice(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_KEYSTORE)
/* Poisoned, not zeroed: with nothing registered the dispatcher's own clear
* is the only thing that can touch these, so this is where it is
* observable at all. */
word32 keyType = 0xDEADBEEF, keySz = 0xDEADBEEF, attrs = 0xDEADBEEF;
/* Nothing registered: every entry point must decline. */
ExpectIntEQ(wc_KeyStore_Delete(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
ExpectIntEQ(wc_KeyStore_GetInfo(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), &keyType, &keySz, &attrs, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
/* Cleared before dispatch, so a declined query cannot leave the caller
* reading its own stack - attrs in particular gates an export. */
ExpectIntEQ(keyType, 0);
ExpectIntEQ(keySz, 0);
ExpectIntEQ(attrs, 0);
ExpectIntEQ(wc_KeyStore_Derive(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES, 0,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KDF_TYPE_NONE, ksDeriv, (word32)sizeof(ksDeriv), 0, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
ExpectIntEQ(wc_KeyStore_ImportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
WC_KEYSTORE_KEY_AES, ksPlain, (word32)sizeof(ksPlain), 0, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
keySz = 0xDEADBEEF;
ExpectIntEQ(wc_KeyStore_ExportPlain(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), NULL, &keySz, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
/* the size-query form clears it too */
ExpectIntEQ(keySz, 0);
ExpectIntEQ(wc_KeyStore_ImportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef), WC_KEYSTORE_KEY_AES,
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, ksBlob, (word32)sizeof(ksBlob), 0, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
keySz = 0xDEADBEEF;
ExpectIntEQ(wc_KeyStore_ExportWrapped(KS_TEST_DEVID,
ksKeyRef, (word32)sizeof(ksKeyRef),
ksOtherRef, (word32)sizeof(ksOtherRef),
WC_KEYWRAP_FORMAT_AESKW, NULL, &keySz, NULL),
WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE));
ExpectIntEQ(keySz, 0);
#endif
return EXPECT_RESULT();
}