mirror of https://github.com/wolfSSL/wolfTPM.git
F-12710 - Advertise supported ECC curves
parent
17c6926f80
commit
3507da0429
|
|
@ -556,6 +556,7 @@ if(WOLFTPM_FWTPM)
|
|||
)
|
||||
target_compile_definitions(fwtpm_unit_test PRIVATE
|
||||
"WOLFTPM_FWTPM"
|
||||
"WOLFTPM_FWTPM_UNIT_TEST"
|
||||
"FWTPM_NV_FILE=\"fwtpm_test_nv.bin\""
|
||||
)
|
||||
if(WOLFTPM_FWTPM_NV_APPEND_ONLY)
|
||||
|
|
|
|||
|
|
@ -643,7 +643,8 @@ disabled, the corresponding TPM commands are excluded from the build.
|
|||
| `NO_RSA` | not defined | Excludes RSA keygen, sign, verify, `RSA_Encrypt`, `RSA_Decrypt` |
|
||||
| `HAVE_ECC` | defined | Enables ECC keygen, sign, verify, `ECDH_KeyGen`, `ECDH_ZGen`, `ECC_Parameters` |
|
||||
| `HAVE_ECC384` | defined | Enables P-384 curve support |
|
||||
| `HAVE_ECC521` | defined | Enables P-521 curve support |
|
||||
| `HAVE_ECC521` or `HAVE_ALL_CURVES` | build-dependent | Enables P-521 when `MAX_ECC_KEY_BITS >= 521` provides 66-byte TPM ECC fields |
|
||||
| `ECC_MIN_KEY_SZ` | wolfCrypt-defined | Excludes smaller curves from `ECC_Parameters` and `TPM_CAP_ECC_CURVES` |
|
||||
| `NO_AES` | not defined | Excludes `EncryptDecrypt`, `EncryptDecrypt2`, AES parameter encryption |
|
||||
| `WOLFSSL_SHA384` | defined | Enables SHA-384 PCR bank |
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <wolftpm/fwtpm/fwtpm_nv.h>
|
||||
#include <wolftpm/fwtpm/fwtpm_crypto.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -1207,6 +1208,55 @@ static void FwPatchMoreData(TPM2_Packet* rsp, int pos, byte v)
|
|||
rsp->buf[pos] = v;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
typedef struct FWTPM_ECC_CURVE_INFO {
|
||||
UINT16 tpmCurve;
|
||||
UINT16 keyBits;
|
||||
} FWTPM_ECC_CURVE_INFO;
|
||||
|
||||
static const FWTPM_ECC_CURVE_INFO gFwEccCurves[] = {
|
||||
{ TPM_ECC_NIST_P256, 256 },
|
||||
{ TPM_ECC_NIST_P384, 384 },
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
{ TPM_ECC_NIST_P521, 521 },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const FWTPM_ECC_CURVE_INFO* FwGetEccCurveInfo(UINT16 curve)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(gFwEccCurves) /
|
||||
sizeof(gFwEccCurves[0])); i++) {
|
||||
if (gFwEccCurves[i].tpmCurve == curve) {
|
||||
return &gFwEccCurves[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const ecc_set_type* FwGetEccCurveParams(UINT16 curve)
|
||||
{
|
||||
const FWTPM_ECC_CURVE_INFO* curveInfo;
|
||||
int wcCurve;
|
||||
int curveIdx;
|
||||
|
||||
curveInfo = FwGetEccCurveInfo(curve);
|
||||
if (curveInfo == NULL || curveInfo->keyBits < ECC_MIN_KEY_SZ) {
|
||||
return NULL;
|
||||
}
|
||||
wcCurve = FwGetWcCurveId(curve);
|
||||
if (wcCurve < 0) {
|
||||
return NULL;
|
||||
}
|
||||
curveIdx = wc_ecc_get_curve_idx(wcCurve);
|
||||
if (curveIdx < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return wc_ecc_get_curve_params(curveIdx);
|
||||
}
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
/* Select the numerically lowest handle in handleClass that is at or above
|
||||
* property and, after the first selection, greater than previous. The slot
|
||||
* tables are intentionally rescanned per result: their configured defaults
|
||||
|
|
@ -1789,9 +1839,35 @@ static TPM_RC FwCmd_GetCapability(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TPM_CAP_ECC_CURVES: {
|
||||
#ifdef HAVE_ECC
|
||||
UINT32 count = 0;
|
||||
int countPos = rsp->pos;
|
||||
|
||||
TPM2_Packet_AppendU32(rsp, 0); /* back-patched below */
|
||||
for (i = 0; i < (UINT32)(sizeof(gFwEccCurves) /
|
||||
sizeof(gFwEccCurves[0])); i++) {
|
||||
if ((UINT32)gFwEccCurves[i].tpmCurve >= property &&
|
||||
FwGetEccCurveParams(gFwEccCurves[i].tpmCurve) != NULL) {
|
||||
if (count < propertyCount) {
|
||||
TPM2_Packet_AppendU16(rsp,
|
||||
gFwEccCurves[i].tpmCurve);
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
FwPatchMoreData(rsp, moreDataPos, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
FwPatchU32BE(rsp, countPos, count);
|
||||
#else
|
||||
TPM2_Packet_AppendU32(rsp, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case TPM_CAP_PP_COMMANDS:
|
||||
case TPM_CAP_AUDIT_COMMANDS:
|
||||
case TPM_CAP_ECC_CURVES:
|
||||
TPM2_Packet_AppendU32(rsp, 0);
|
||||
break;
|
||||
|
||||
|
|
@ -15515,59 +15591,89 @@ static TPM_RC FwCmd_ActivateCredential(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* ================================================================== */
|
||||
|
||||
#ifndef FWTPM_NO_ECDH
|
||||
/* Convert hex string to binary. Returns byte count, or -1 on error. */
|
||||
static int FwHexNibble(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return c - 'A' + 10;
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a big-endian hex value to binary. An odd leading digit is the low
|
||||
* nibble of the first output byte. Returns byte count, or -1 on error. */
|
||||
static int FwHexToBin(const char* hex, byte* out, int outSz)
|
||||
{
|
||||
int i, len;
|
||||
if (hex == NULL) return -1;
|
||||
len = (int)XSTRLEN(hex);
|
||||
if (len & 1) return -1;
|
||||
len /= 2;
|
||||
if (len > outSz) return -1;
|
||||
for (i = 0; i < len; i++) {
|
||||
byte hi, lo;
|
||||
char ch = hex[i * 2];
|
||||
char cl = hex[i * 2 + 1];
|
||||
hi = (byte)((ch >= 'A' && ch <= 'F') ? (ch - 'A' + 10) :
|
||||
(ch >= 'a' && ch <= 'f') ? (ch - 'a' + 10) : (ch - '0'));
|
||||
lo = (byte)((cl >= 'A' && cl <= 'F') ? (cl - 'A' + 10) :
|
||||
(cl >= 'a' && cl <= 'f') ? (cl - 'a' + 10) : (cl - '0'));
|
||||
out[i] = (byte)((hi << 4) | lo);
|
||||
int i, len, decodedLen, outPos = 0;
|
||||
int hi, lo;
|
||||
size_t hexLen;
|
||||
|
||||
if (hex == NULL || out == NULL || outSz < 0) return -1;
|
||||
hexLen = XSTRLEN(hex);
|
||||
if (hexLen > (size_t)INT_MAX) return -1;
|
||||
len = (int)hexLen;
|
||||
decodedLen = len / 2 + (len & 1);
|
||||
if (decodedLen > outSz) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
|
||||
i = 0;
|
||||
if ((len & 1) != 0) {
|
||||
lo = FwHexNibble(hex[i++]);
|
||||
if (lo < 0) return -1;
|
||||
out[outPos++] = (byte)lo;
|
||||
}
|
||||
while (i < len) {
|
||||
hi = FwHexNibble(hex[i++]);
|
||||
lo = FwHexNibble(hex[i++]);
|
||||
if (hi < 0 || lo < 0) return -1;
|
||||
out[outPos++] = (byte)((hi << 4) | lo);
|
||||
}
|
||||
return outPos;
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_FWTPM_UNIT_TEST
|
||||
int FWTPM_TestHexToBin(const char* hex, byte* out, int outSz);
|
||||
|
||||
int FWTPM_TestHexToBin(const char* hex, byte* out, int outSz)
|
||||
{
|
||||
return FwHexToBin(hex, out, outSz);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --- TPM2_ECC_Parameters (CC 0x0178) ---
|
||||
* Returns curve parameters from wolfCrypt's ecc_set_type via
|
||||
* wc_ecc_get_curve_params(). Automatically supports P-256, P-384,
|
||||
* and P-521 (when HAVE_ECC521 is defined). */
|
||||
* and P-521 when wolfCrypt and the TPM ECC buffers support it. */
|
||||
static TPM_RC FwCmd_ECC_Parameters(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
||||
int cmdSize, TPM2_Packet* rsp, UINT16 cmdTag)
|
||||
{
|
||||
TPM_RC rc = TPM_RC_SUCCESS;
|
||||
UINT16 curveID;
|
||||
int wcCurve, curveIdx, f;
|
||||
UINT16 keyBits;
|
||||
int f;
|
||||
const FWTPM_ECC_CURVE_INFO* curveInfo = NULL;
|
||||
const ecc_set_type* params = NULL;
|
||||
byte paramBuf[MAX_ECC_BYTES];
|
||||
int paramSz;
|
||||
int padSz;
|
||||
const char* fields[6];
|
||||
|
||||
(void)ctx; (void)cmdSize; (void)cmdTag;
|
||||
|
||||
TPM2_Packet_ParseU16(cmd, &curveID);
|
||||
|
||||
wcCurve = FwGetWcCurveId(curveID);
|
||||
if (wcCurve < 0) {
|
||||
curveInfo = FwGetEccCurveInfo(curveID);
|
||||
params = FwGetEccCurveParams(curveID);
|
||||
if (curveInfo == NULL || params == NULL) {
|
||||
rc = TPM_RC_CURVE;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
curveIdx = wc_ecc_get_curve_idx(wcCurve);
|
||||
params = wc_ecc_get_curve_params(curveIdx);
|
||||
if (params == NULL) {
|
||||
rc = TPM_RC_CURVE;
|
||||
}
|
||||
}
|
||||
keyBits = (curveInfo != NULL) ? curveInfo->keyBits : 0;
|
||||
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
if (rc == 0) {
|
||||
|
|
@ -15578,7 +15684,7 @@ static TPM_RC FwCmd_ECC_Parameters(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
|
||||
if (rc == 0) {
|
||||
TPM2_Packet_AppendU16(rsp, curveID);
|
||||
TPM2_Packet_AppendU16(rsp, (UINT16)(params->size * 8)); /* bits */
|
||||
TPM2_Packet_AppendU16(rsp, keyBits);
|
||||
TPM2_Packet_AppendU16(rsp, TPM_ALG_NULL); /* kdf */
|
||||
TPM2_Packet_AppendU16(rsp, TPM_ALG_NULL); /* sign */
|
||||
|
||||
|
|
@ -15597,7 +15703,15 @@ static TPM_RC FwCmd_ECC_Parameters(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
rc = TPM_RC_FAILURE;
|
||||
break;
|
||||
}
|
||||
TPM2_Packet_AppendU16(rsp, (UINT16)paramSz);
|
||||
if (paramSz > params->size) {
|
||||
rc = TPM_RC_FAILURE;
|
||||
break;
|
||||
}
|
||||
padSz = params->size - paramSz;
|
||||
TPM2_Packet_AppendU16(rsp, (UINT16)(padSz + paramSz));
|
||||
while (padSz-- > 0) {
|
||||
TPM2_Packet_AppendU8(rsp, 0);
|
||||
}
|
||||
TPM2_Packet_AppendBytes(rsp, paramBuf, paramSz);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -417,36 +417,63 @@ int FwAppendCreationHashAndTicket(FWTPM_CTX* ctx, TPM2_Packet* rsp,
|
|||
/* Map TPM ECC curve to wolfCrypt curve ID */
|
||||
int FwGetWcCurveId(UINT16 tpmCurve)
|
||||
{
|
||||
int curveIdx;
|
||||
int keyBits;
|
||||
int wcCurve;
|
||||
|
||||
switch (tpmCurve) {
|
||||
case TPM_ECC_NIST_P256:
|
||||
return ECC_SECP256R1;
|
||||
keyBits = 256;
|
||||
wcCurve = ECC_SECP256R1;
|
||||
break;
|
||||
case TPM_ECC_NIST_P384:
|
||||
return ECC_SECP384R1;
|
||||
#ifdef HAVE_ECC521
|
||||
keyBits = 384;
|
||||
wcCurve = ECC_SECP384R1;
|
||||
break;
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
case TPM_ECC_NIST_P521:
|
||||
return ECC_SECP521R1;
|
||||
keyBits = 521;
|
||||
wcCurve = ECC_SECP521R1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (keyBits < ECC_MIN_KEY_SZ) {
|
||||
return -1;
|
||||
}
|
||||
curveIdx = wc_ecc_get_curve_idx(wcCurve);
|
||||
if (curveIdx < 0 || wc_ecc_get_curve_params(curveIdx) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return wcCurve;
|
||||
}
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
/* Get ECC key size in bytes from TPM curve */
|
||||
int FwGetEccKeySize(UINT16 tpmCurve)
|
||||
{
|
||||
#ifdef HAVE_ECC
|
||||
if (FwGetWcCurveId(tpmCurve) < 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (tpmCurve) {
|
||||
case TPM_ECC_NIST_P256:
|
||||
return 32;
|
||||
case TPM_ECC_NIST_P384:
|
||||
return 48;
|
||||
#ifdef HAVE_ECC521
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
case TPM_ECC_NIST_P521:
|
||||
return 66;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
(void)tpmCurve;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
@ -532,7 +559,7 @@ TPM_RC FwGenerateEccKey(WC_RNG* rng,
|
|||
|
||||
FWTPM_ALLOC_VAR(eccKey, ecc_key);
|
||||
|
||||
if (wcCurve < 0 || keySz == 0) {
|
||||
if (wcCurve < 0 || keySz == 0 || keySz > MAX_ECC_KEY_BYTES) {
|
||||
FWTPM_FREE_VAR(eccKey);
|
||||
return TPM_RC_CURVE;
|
||||
}
|
||||
|
|
@ -1147,7 +1174,7 @@ static int FwDhkemParamsLookup(int wcCurve, TPMI_ALG_HASH kdfHash,
|
|||
*hkdfHashOut = WC_HASH_TYPE_SHA384;
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_ECC521
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
if (wcCurve == ECC_SECP521R1 && kdfHash == TPM_ALG_SHA512) {
|
||||
*kemIdOut = 0x0012; *nSecretOut = 64; *nPkOut = 133;
|
||||
*hkdfHashOut = WC_HASH_TYPE_SHA512;
|
||||
|
|
|
|||
|
|
@ -1161,6 +1161,213 @@ static void test_fwtpm_getcap_paging(void)
|
|||
fwtpm_pass("GetCapability paging convergence:", 0);
|
||||
}
|
||||
|
||||
static int getcap_ecc_curves(FWTPM_CTX* ctx, UINT32 property,
|
||||
UINT32 propertyCount, UINT16* curves, int curveCapacity, byte* moreData)
|
||||
{
|
||||
UINT32 count;
|
||||
int rc, rspSize, cmdSz, i;
|
||||
|
||||
cmdSz = BuildCmdHeader(gCmd, TPM_ST_NO_SESSIONS, 0,
|
||||
TPM_CC_GetCapability);
|
||||
PutU32BE(gCmd + cmdSz, TPM_CAP_ECC_CURVES); cmdSz += 4;
|
||||
PutU32BE(gCmd + cmdSz, property); cmdSz += 4;
|
||||
PutU32BE(gCmd + cmdSz, propertyCount); cmdSz += 4;
|
||||
PutU32BE(gCmd + 2, (UINT32)cmdSz);
|
||||
rspSize = 0;
|
||||
rc = FWTPM_ProcessCommand(ctx, gCmd, cmdSz, gRsp, &rspSize, 0);
|
||||
AssertIntEQ(rc, TPM_RC_SUCCESS);
|
||||
AssertIntEQ(GetRspRC(gRsp), TPM_RC_SUCCESS);
|
||||
AssertTrue(rspSize >= TPM2_HEADER_SIZE + 9);
|
||||
AssertIntEQ(GetU32BE(gRsp + TPM2_HEADER_SIZE + 1),
|
||||
(int)TPM_CAP_ECC_CURVES);
|
||||
|
||||
*moreData = gRsp[TPM2_HEADER_SIZE];
|
||||
count = GetU32BE(gRsp + TPM2_HEADER_SIZE + 5);
|
||||
AssertTrue((int)count <= curveCapacity);
|
||||
AssertTrue(rspSize >= TPM2_HEADER_SIZE + 9 + ((int)count * 2));
|
||||
for (i = 0; i < (int)count; i++) {
|
||||
curves[i] = GetU16BE(gRsp + TPM2_HEADER_SIZE + 9 + (i * 2));
|
||||
}
|
||||
return (int)count;
|
||||
}
|
||||
|
||||
#if defined(HAVE_ECC) && !defined(FWTPM_NO_ECDH)
|
||||
static UINT16 test_ecc_curve_bits(UINT16 curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case TPM_ECC_NIST_P256:
|
||||
return 256;
|
||||
case TPM_ECC_NIST_P384:
|
||||
return 384;
|
||||
case TPM_ECC_NIST_P521:
|
||||
return 521;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_ecc_parameters(FWTPM_CTX* ctx, UINT16 curve)
|
||||
{
|
||||
UINT16 fieldSz;
|
||||
UINT16 keyBits;
|
||||
int rc, rspSize, cmdSz, pos, field;
|
||||
int keyBytes;
|
||||
|
||||
cmdSz = BuildCmdHeader(gCmd, TPM_ST_NO_SESSIONS, 0,
|
||||
TPM_CC_ECC_Parameters);
|
||||
PutU16BE(gCmd + cmdSz, curve); cmdSz += 2;
|
||||
PutU32BE(gCmd + 2, (UINT32)cmdSz);
|
||||
rspSize = 0;
|
||||
rc = FWTPM_ProcessCommand(ctx, gCmd, cmdSz, gRsp, &rspSize, 0);
|
||||
AssertIntEQ(rc, TPM_RC_SUCCESS);
|
||||
AssertIntEQ(GetRspRC(gRsp), TPM_RC_SUCCESS);
|
||||
pos = TPM2_HEADER_SIZE;
|
||||
AssertIntEQ(GetU16BE(gRsp + pos), curve);
|
||||
pos += 2;
|
||||
|
||||
keyBits = test_ecc_curve_bits(curve);
|
||||
AssertIntNE(keyBits, 0);
|
||||
AssertIntEQ(GetU16BE(gRsp + pos), keyBits);
|
||||
pos += 2;
|
||||
keyBytes = (keyBits + 7) / 8;
|
||||
|
||||
AssertIntEQ(GetU16BE(gRsp + pos), TPM_ALG_NULL); /* kdf */
|
||||
pos += 2;
|
||||
AssertIntEQ(GetU16BE(gRsp + pos), TPM_ALG_NULL); /* sign */
|
||||
pos += 2;
|
||||
|
||||
/* Curve parameters use a consistent fixed-width big-endian encoding. */
|
||||
for (field = 0; field < 6; field++) {
|
||||
AssertTrue(pos + 2 <= rspSize);
|
||||
fieldSz = GetU16BE(gRsp + pos);
|
||||
pos += 2;
|
||||
AssertIntEQ(fieldSz, keyBytes);
|
||||
AssertTrue(pos + fieldSz <= rspSize);
|
||||
if (curve == TPM_ECC_NIST_P521 && field == 0) {
|
||||
/* p = 0x01 followed by 65 0xff bytes. */
|
||||
AssertIntEQ(gRsp[pos], 0x01);
|
||||
AssertIntEQ(gRsp[pos + fieldSz - 1], 0xff);
|
||||
}
|
||||
else if (curve == TPM_ECC_NIST_P521 && field == 3) {
|
||||
/* Gx is 65 bytes and must be left-padded to the 66-byte field. */
|
||||
AssertIntEQ(gRsp[pos], 0x00);
|
||||
AssertIntEQ(gRsp[pos + 1], 0xc6);
|
||||
}
|
||||
pos += fieldSz;
|
||||
}
|
||||
|
||||
AssertTrue(pos + 2 <= rspSize);
|
||||
fieldSz = GetU16BE(gRsp + pos); /* cofactor h */
|
||||
pos += 2;
|
||||
AssertIntEQ(fieldSz, 1);
|
||||
AssertTrue(pos + fieldSz <= rspSize);
|
||||
pos += fieldSz;
|
||||
AssertIntEQ(pos, rspSize);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ECC && !FWTPM_NO_ECDH */
|
||||
|
||||
/* Curve capability pages expose every compiled curve in ascending order and
|
||||
* each advertised curve is accepted by ECC_Parameters when that command is
|
||||
* enabled. */
|
||||
static void test_fwtpm_getcap_ecc_curves(void)
|
||||
{
|
||||
FWTPM_CTX ctx;
|
||||
UINT16 expected[3];
|
||||
UINT16 actual[3];
|
||||
UINT32 property;
|
||||
byte moreData;
|
||||
int expectedCount = 0;
|
||||
int count, i;
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
int curveIdx;
|
||||
static const struct {
|
||||
UINT16 tpmCurve;
|
||||
UINT16 keyBits;
|
||||
int wcCurve;
|
||||
} candidates[] = {
|
||||
{ TPM_ECC_NIST_P256, 256, ECC_SECP256R1 },
|
||||
{ TPM_ECC_NIST_P384, 384, ECC_SECP384R1 },
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
{ TPM_ECC_NIST_P521, 521, ECC_SECP521R1 },
|
||||
#endif
|
||||
};
|
||||
|
||||
for (i = 0; i < (int)(sizeof(candidates) /
|
||||
sizeof(candidates[0])); i++) {
|
||||
curveIdx = wc_ecc_get_curve_idx(candidates[i].wcCurve);
|
||||
if (candidates[i].keyBits >= ECC_MIN_KEY_SZ && curveIdx >= 0 &&
|
||||
wc_ecc_get_curve_params(curveIdx) != NULL) {
|
||||
AssertIntEQ(FwGetWcCurveId(candidates[i].tpmCurve),
|
||||
candidates[i].wcCurve);
|
||||
AssertIntEQ(FwGetEccKeySize(candidates[i].tpmCurve),
|
||||
(candidates[i].keyBits + 7) / 8);
|
||||
expected[expectedCount++] = candidates[i].tpmCurve;
|
||||
}
|
||||
else {
|
||||
AssertIntEQ(FwGetWcCurveId(candidates[i].tpmCurve), -1);
|
||||
AssertIntEQ(FwGetEccKeySize(candidates[i].tpmCurve), 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
XMEMSET(&ctx, 0, sizeof(ctx));
|
||||
AssertIntEQ(fwtpm_test_startup(&ctx), 0);
|
||||
|
||||
count = getcap_ecc_curves(&ctx, 0, 0, actual, 3, &moreData);
|
||||
AssertIntEQ(count, 0);
|
||||
AssertIntEQ(moreData, expectedCount > 0);
|
||||
|
||||
count = getcap_ecc_curves(&ctx, 0, 3, actual, 3, &moreData);
|
||||
AssertIntEQ(count, expectedCount);
|
||||
AssertIntEQ(moreData, 0);
|
||||
for (i = 0; i < expectedCount; i++) {
|
||||
AssertIntEQ(actual[i], expected[i]);
|
||||
#if defined(HAVE_ECC) && !defined(FWTPM_NO_ECDH)
|
||||
check_ecc_parameters(&ctx, actual[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
property = 0;
|
||||
for (i = 0; i < expectedCount; i++) {
|
||||
count = getcap_ecc_curves(&ctx, property, 1, actual, 3,
|
||||
&moreData);
|
||||
AssertIntEQ(count, 1);
|
||||
AssertIntEQ(actual[0], expected[i]);
|
||||
AssertIntEQ(moreData, i + 1 < expectedCount);
|
||||
property = (UINT32)actual[0] + 1u;
|
||||
}
|
||||
count = getcap_ecc_curves(&ctx, property, 1, actual, 3, &moreData);
|
||||
AssertIntEQ(count, 0);
|
||||
AssertIntEQ(moreData, 0);
|
||||
|
||||
FWTPM_Cleanup(&ctx);
|
||||
fwtpm_pass("GetCapability(ECC_CURVES):", 0);
|
||||
}
|
||||
|
||||
#if defined(HAVE_ECC) && !defined(FWTPM_NO_ECDH) && \
|
||||
defined(WOLFTPM_FWTPM_UNIT_TEST)
|
||||
int FWTPM_TestHexToBin(const char* hex, byte* out, int outSz);
|
||||
|
||||
static void test_fwtpm_hex_to_bin(void)
|
||||
{
|
||||
byte out[2];
|
||||
|
||||
XMEMSET(out, 0, sizeof(out));
|
||||
AssertIntEQ(FWTPM_TestHexToBin("abc", out, sizeof(out)), 2);
|
||||
AssertIntEQ(out[0], 0x0a);
|
||||
AssertIntEQ(out[1], 0xbc);
|
||||
AssertIntEQ(FWTPM_TestHexToBin("f", out, sizeof(out)), 1);
|
||||
AssertIntEQ(out[0], 0x0f);
|
||||
AssertIntEQ(FWTPM_TestHexToBin("0g", out, sizeof(out)), -1);
|
||||
AssertIntEQ(FWTPM_TestHexToBin("1234", out, 1), -1);
|
||||
AssertIntEQ(FWTPM_TestHexToBin(NULL, out, sizeof(out)), -1);
|
||||
|
||||
fwtpm_pass("ECC parameter hex decoding:", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWTPM_MAX_OBJECTS >= 2 || FWTPM_MAX_PERSISTENT >= 2 || \
|
||||
FWTPM_MAX_SESSIONS >= 2 || \
|
||||
(!defined(FWTPM_NO_NV) && FWTPM_MAX_NV_INDICES >= 2)
|
||||
|
|
@ -2681,7 +2888,7 @@ static void test_fwtpm_ecc_dhkem_p384_roundtrip(void)
|
|||
"Encap/Decap ECC DHKEM (P-384/HKDF-SHA384) Roundtrip:");
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC521
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
static void test_fwtpm_ecc_dhkem_p521_roundtrip(void)
|
||||
{
|
||||
RunEccDhkemRoundtrip(TPM_ECC_NIST_P521, TPM_ALG_SHA512,
|
||||
|
|
@ -13487,6 +13694,11 @@ int fwtpm_unit_tests(int argc, char *argv[])
|
|||
test_fwtpm_getcap_properties();
|
||||
test_fwtpm_getcap_pcrs();
|
||||
test_fwtpm_getcap_paging();
|
||||
test_fwtpm_getcap_ecc_curves();
|
||||
#if defined(HAVE_ECC) && !defined(FWTPM_NO_ECDH) && \
|
||||
defined(WOLFTPM_FWTPM_UNIT_TEST)
|
||||
test_fwtpm_hex_to_bin();
|
||||
#endif
|
||||
#if FWTPM_MAX_OBJECTS >= 2 || FWTPM_MAX_PERSISTENT >= 2 || \
|
||||
FWTPM_MAX_SESSIONS >= 2 || \
|
||||
(!defined(FWTPM_NO_NV) && FWTPM_MAX_NV_INDICES >= 2)
|
||||
|
|
@ -13567,7 +13779,7 @@ int fwtpm_unit_tests(int argc, char *argv[])
|
|||
test_fwtpm_signsequence_handle_auth_required();
|
||||
test_fwtpm_verifysequence_long_message();
|
||||
test_fwtpm_ecc_dhkem_p384_roundtrip();
|
||||
#ifdef HAVE_ECC521
|
||||
#ifdef FWTPM_HAVE_ECC521
|
||||
test_fwtpm_ecc_dhkem_p521_roundtrip();
|
||||
#endif
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ tests_fwtpm_unit_test_SOURCES = \
|
|||
src/tpm2_crypto.c \
|
||||
src/tpm2_param_enc.c
|
||||
tests_fwtpm_unit_test_CFLAGS = -DWOLFTPM_FWTPM -DFWTPM_NV_FILE=\"fwtpm_test_nv.bin\" $(AM_CFLAGS)
|
||||
tests_fwtpm_unit_test_CPPFLAGS = -DWOLFTPM_FWTPM $(AM_CPPFLAGS)
|
||||
tests_fwtpm_unit_test_CPPFLAGS = \
|
||||
-DWOLFTPM_FWTPM -DWOLFTPM_FWTPM_UNIT_TEST $(AM_CPPFLAGS)
|
||||
tests_fwtpm_unit_test_LDADD = $(LIB_STATIC_ADD)
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,15 @@
|
|||
#include <wolftpm/fwtpm/fwtpm_tis.h>
|
||||
#endif
|
||||
|
||||
/* P-521 needs both wolfCrypt curve support and 66-byte TPM ECC fields. */
|
||||
#if defined(HAVE_ECC) && \
|
||||
(defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && \
|
||||
MAX_ECC_KEY_BYTES >= 66
|
||||
#if !defined(ECC_MIN_KEY_SZ) || ECC_MIN_KEY_SZ <= 521
|
||||
#define FWTPM_HAVE_ECC521
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Endian byte-array helpers - use shared TPM2_Packet helpers.
|
||||
* Note: argument order differs (Fw: buf,val; TPM2_Packet: val,buf) */
|
||||
#define FwStoreU16BE(buf, val) TPM2_Packet_U16ToByteArray((val), (buf))
|
||||
|
|
|
|||
Loading…
Reference in New Issue