KDF Update

1. Move wolfSSH's KDF into wolfCrypt.
This commit is contained in:
John Safranek
2020-12-14 11:09:56 -08:00
parent 2672856042
commit 131fb2c1e6
4 changed files with 424 additions and 0 deletions

View File

@@ -6006,6 +6006,8 @@ if test "x$ENABLED_OPENSSLCOEXIST" = "xyes"; then
fi
fi
AS_IF([test "x$ENABLED_WOLFSSH" = "xyes"],[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSL_WOLFSSH"])
if test "x$ENABLED_CERTS" = "xno" || test "x$ENABLED_LEANPSK" = "xyes" || test "x$ENABLED_ASN" = "xno"; then
AM_CFLAGS="$AM_CFLAGS -DNO_ASN -DNO_CERTS"
fi

View File

@@ -1590,5 +1590,249 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
#endif /* HAVE_HKDF */
#ifdef WOLFSSL_WOLFSSH
static
int _HashInit(byte hashId, wc_Hmac_Hash* hash)
{
int ret = BAD_FUNC_ARG;
switch (hashId) {
#ifndef NO_SHA
case WC_SHA:
ret = wc_InitSha(&hash->sha);
break;
#endif /* !NO_SHA */
#ifndef NO_SHA256
case WC_SHA256:
ret = wc_InitSha256(&hash->sha256);
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
case WC_SHA384:
ret = wc_InitSha384(&hash->sha384);
break;
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
case WC_SHA512:
ret = wc_InitSha512(&hash->sha512);
break;
#endif /* WOLFSSL_SHA512 */
}
return ret;
}
static
int _HashUpdate(byte hashId, wc_Hmac_Hash* hash,
const byte* data, word32 dataSz)
{
int ret = BAD_FUNC_ARG;
switch (hashId) {
#ifndef NO_SHA
case WC_SHA:
ret = wc_ShaUpdate(&hash->sha, data, dataSz);
break;
#endif /* !NO_SHA */
#ifndef NO_SHA256
case WC_SHA256:
ret = wc_Sha256Update(&hash->sha256, data, dataSz);
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
case WC_SHA384:
ret = wc_Sha384Update(&hash->sha384, data, dataSz);
break;
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
case WC_SHA512:
ret = wc_Sha512Update(&hash->sha512, data, dataSz);
break;
#endif /* WOLFSSL_SHA512 */
}
return ret;
}
static
int _HashFinal(byte hashId, wc_Hmac_Hash* hash, byte* digest)
{
int ret = BAD_FUNC_ARG;
switch (hashId) {
#ifndef NO_SHA
case WC_SHA:
ret = wc_ShaFinal(&hash->sha, digest);
break;
#endif /* !NO_SHA */
#ifndef NO_SHA256
case WC_SHA256:
ret = wc_Sha256Final(&hash->sha256, digest);
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
case WC_SHA384:
ret = wc_Sha384Final(&hash->sha384, digest);
break;
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
case WC_SHA512:
ret = wc_Sha512Final(&hash->sha512, digest);
break;
#endif /* WOLFSSL_SHA512 */
}
return ret;
}
static
void _HashFree(byte hashId, wc_Hmac_Hash* hash)
{
switch (hashId) {
#ifndef NO_SHA
case WC_SHA:
wc_ShaFree(&hash->sha);
break;
#endif /* !NO_SHA */
#ifndef NO_SHA256
case WC_SHA256:
wc_Sha256Free(&hash->sha256);
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA384
case WC_SHA384:
wc_Sha384Free(&hash->sha384);
break;
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
case WC_SHA512:
wc_Sha512Free(&hash->sha512);
break;
#endif /* WOLFSSL_SHA512 */
}
}
#define LENGTH_SZ 4
int wc_SSH_KDF(byte hashId, byte keyId, byte* key, word32 keySz,
const byte* k, word32 kSz, const byte* h, word32 hSz,
const byte* sessionId, word32 sessionIdSz)
{
word32 blocks, remainder;
wc_Hmac_Hash hash;
enum wc_HashType enmhashId = (enum wc_HashType)hashId;
byte kPad = 0;
byte pad = 0;
byte kSzFlat[LENGTH_SZ];
int digestSz;
int ret;
if (key == NULL || keySz == 0 ||
k == NULL || kSz == 0 ||
h == NULL || hSz == 0 ||
sessionId == NULL || sessionIdSz == 0) {
return BAD_FUNC_ARG;
}
digestSz = wc_HmacSizeByType(enmhashId);
if (digestSz < 0) {
return BAD_FUNC_ARG;
}
if (k[0] & 0x80) kPad = 1;
c32toa(kSz + kPad, kSzFlat);
blocks = keySz / digestSz;
remainder = keySz % digestSz;
ret = _HashInit(enmhashId, &hash);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
if (ret == 0 && kPad)
ret = _HashUpdate(enmhashId, &hash, &pad, 1);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, k, kSz);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, h, hSz);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, &keyId, sizeof(keyId));
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, sessionId, sessionIdSz);
if (ret == 0) {
if (blocks == 0) {
if (remainder > 0) {
byte lastBlock[WC_MAX_DIGEST_SIZE];
ret = _HashFinal(enmhashId, &hash, lastBlock);
if (ret == 0)
XMEMCPY(key, lastBlock, remainder);
}
}
else {
word32 runningKeySz, curBlock;
runningKeySz = digestSz;
ret = _HashFinal(enmhashId, &hash, key);
for (curBlock = 1; curBlock < blocks; curBlock++) {
ret = _HashInit(enmhashId, &hash);
if (ret != 0) break;
ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
if (ret != 0) break;
if (kPad)
ret = _HashUpdate(enmhashId, &hash, &pad, 1);
if (ret != 0) break;
ret = _HashUpdate(enmhashId, &hash, k, kSz);
if (ret != 0) break;
ret = _HashUpdate(enmhashId, &hash, h, hSz);
if (ret != 0) break;
ret = _HashUpdate(enmhashId, &hash, key, runningKeySz);
if (ret != 0) break;
ret = _HashFinal(enmhashId, &hash, key + runningKeySz);
if (ret != 0) break;
runningKeySz += digestSz;
}
if (remainder > 0) {
byte lastBlock[WC_MAX_DIGEST_SIZE];
if (ret == 0)
ret = _HashInit(enmhashId, &hash);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
if (ret == 0 && kPad)
ret = _HashUpdate(enmhashId, &hash, &pad, 1);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, k, kSz);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, h, hSz);
if (ret == 0)
ret = _HashUpdate(enmhashId, &hash, key, runningKeySz);
if (ret == 0)
ret = _HashFinal(enmhashId, &hash, lastBlock);
if (ret == 0)
XMEMCPY(key + runningKeySz, lastBlock, remainder);
}
}
}
_HashFree(enmhashId, &hash);
return ret;
}
#endif /* WOLFSSL_SSH */
#endif /* HAVE_FIPS */
#endif /* NO_HMAC */

View File

@@ -934,6 +934,13 @@ initDefaultName();
#endif
#endif /* !NO_HMAC */
#ifdef WOLFSSL_WOLFSSH
if ( (ret = sshkdf_test()) != 0)
return err_sys("SSH-KDF test failed!\n", ret);
else
test_pass("SSH-KDF test passed!\n");
#endif /* WOLFSSL_WOLFSSH */
#if defined(HAVE_X963_KDF) && defined(HAVE_ECC)
if ( (ret = x963kdf_test()) != 0)
return err_sys("X963-KDF test failed!\n", ret);
@@ -19905,6 +19912,167 @@ WOLFSSL_TEST_SUBROUTINE int pwdbased_test(void)
#endif /* HAVE_HKDF */
#ifdef WOLFSSL_WOLFSSH
typedef struct {
byte hashId;
byte keyId;
const byte* k;
word32 kSz;
const byte* h;
word32 hSz;
const byte* sessionId;
word32 sessionIdSz;
const byte* expectedKey;
word32 expectedKeySz;
} SshKdfTestVector;
/** Test Vector Set #3: SHA-256 **/
const byte sshKdfTvSet3k[] = {
0x6A, 0xC3, 0x82, 0xEA, 0xAC, 0xA0, 0x93, 0xE1,
0x25, 0xE2, 0x5C, 0x24, 0xBE, 0xBC, 0x84, 0x64,
0x0C, 0x11, 0x98, 0x75, 0x07, 0x34, 0x4B, 0x5C,
0x73, 0x9C, 0xEB, 0x84, 0xA9, 0xE0, 0xB2, 0x22,
0xB9, 0xA8, 0xB5, 0x1C, 0x83, 0x9E, 0x5E, 0xBE,
0x49, 0xCF, 0xAD, 0xBF, 0xB3, 0x95, 0x99, 0x76,
0x4E, 0xD5, 0x22, 0x09, 0x9D, 0xC9, 0x12, 0x75,
0x19, 0x50, 0xDC, 0x7D, 0xC9, 0x7F, 0xBD, 0xC0,
0x63, 0x28, 0xB6, 0x8F, 0x22, 0x78, 0x1F, 0xD3,
0x15, 0xAF, 0x56, 0x80, 0x09, 0xA5, 0x50, 0x9E,
0x5B, 0x87, 0xA1, 0x1B, 0xF5, 0x27, 0xC0, 0x56,
0xDA, 0xFF, 0xD8, 0x2A, 0xB6, 0xCB, 0xC2, 0x5C,
0xCA, 0x37, 0x14, 0x34, 0x59, 0xE7, 0xBC, 0x63,
0xBC, 0xDE, 0x52, 0x75, 0x7A, 0xDE, 0xB7, 0xDF,
0x01, 0xCF, 0x12, 0x17, 0x3F, 0x1F, 0xEF, 0x81,
0x02, 0xEC, 0x5A, 0xB1, 0x42, 0xC2, 0x13, 0xDD,
0x9D, 0x30, 0x69, 0x62, 0x78, 0xA8, 0xD8, 0xBC,
0x32, 0xDD, 0xE9, 0x59, 0x2D, 0x28, 0xC0, 0x78,
0xC6, 0xD9, 0x2B, 0x94, 0x7D, 0x82, 0x5A, 0xCA,
0xAB, 0x64, 0x94, 0x84, 0x6A, 0x49, 0xDE, 0x24,
0xB9, 0x62, 0x3F, 0x48, 0x89, 0xE8, 0xAD, 0xC3,
0x8E, 0x8C, 0x66, 0x9E, 0xFF, 0xEF, 0x17, 0x60,
0x40, 0xAD, 0x94, 0x5E, 0x90, 0xA7, 0xD3, 0xEE,
0xC1, 0x5E, 0xFE, 0xEE, 0x78, 0xAE, 0x71, 0x04,
0x3C, 0x96, 0x51, 0x11, 0x03, 0xA1, 0x6B, 0xA7,
0xCA, 0xF0, 0xAC, 0xD0, 0x64, 0x2E, 0xFD, 0xBE,
0x80, 0x99, 0x34, 0xFA, 0xA1, 0xA5, 0xF1, 0xBD,
0x11, 0x04, 0x36, 0x49, 0xB2, 0x5C, 0xCD, 0x1F,
0xEE, 0x2E, 0x38, 0x81, 0x5D, 0x4D, 0x5F, 0x5F,
0xC6, 0xB4, 0x10, 0x29, 0x69, 0xF2, 0x1C, 0x22,
0xAE, 0x1B, 0x0E, 0x7D, 0x36, 0x03, 0xA5, 0x56,
0xA1, 0x32, 0x62, 0xFF, 0x62, 0x8D, 0xE2, 0x22
};
const byte sshKdfTvSet3h[] = {
0x7B, 0x70, 0x01, 0x18, 0x5E, 0x25, 0x6D, 0x44,
0x93, 0x44, 0x5F, 0x39, 0xA5, 0x5F, 0xB9, 0x05,
0xE6, 0x32, 0x1F, 0x4B, 0x5D, 0xD8, 0xBB, 0xF3,
0x10, 0x0D, 0x51, 0xBA, 0x0B, 0xDA, 0x3D, 0x2D
};
const byte sshKdfTvSet3sid[] = {
0x7B, 0x70, 0x01, 0x18, 0x5E, 0x25, 0x6D, 0x44,
0x93, 0x44, 0x5F, 0x39, 0xA5, 0x5F, 0xB9, 0x05,
0xE6, 0x32, 0x1F, 0x4B, 0x5D, 0xD8, 0xBB, 0xF3,
0x10, 0x0D, 0x51, 0xBA, 0x0B, 0xDA, 0x3D, 0x2D
};
const byte sshKdfTvSet3a[] = {
0x81, 0xF0, 0x33, 0x0E, 0xF6, 0xF0, 0x53, 0x61,
0xB3, 0x82, 0x3B, 0xFD, 0xED, 0x6E, 0x1D, 0xE9
};
const byte sshKdfTvSet3b[] = {
0x3F, 0x6F, 0xD2, 0x06, 0x5E, 0xEB, 0x2B, 0x0B,
0x1D, 0x93, 0x19, 0x5A, 0x1F, 0xED, 0x48, 0xA5
};
const byte sshKdfTvSet3c[] = {
0xC3, 0x54, 0x71, 0x03, 0x4E, 0x6F, 0xD6, 0x54,
0x76, 0x13, 0x17, 0x8E, 0x23, 0x43, 0x5F, 0x21
};
const byte sshKdfTvSet3d[] = {
0x7E, 0x9D, 0x79, 0x03, 0x20, 0x90, 0xD9, 0x9F,
0x98, 0xB0, 0x15, 0x63, 0x4D, 0xD9, 0xF4, 0x62
};
const byte sshKdfTvSet3e[] = {
0x24, 0xEE, 0x55, 0x9A, 0xD7, 0xCE, 0x71, 0x2B,
0x68, 0x5D, 0x0B, 0x22, 0x71, 0xE4, 0x43, 0xC1,
0x7A, 0xB1, 0xD1, 0xDC, 0xEB, 0x5A, 0x36, 0x05,
0x69, 0xD2, 0x5D, 0x5D, 0xC2, 0x43, 0x00, 0x2F
};
const byte sshKdfTvSet3f[] = {
0xC3, 0x41, 0x9C, 0x2B, 0x96, 0x62, 0x35, 0x86,
0x9D, 0x71, 0x4B, 0xA5, 0xAC, 0x48, 0xDD, 0xB7,
0xD9, 0xE3, 0x5C, 0x8C, 0x19, 0xAA, 0xC7, 0x34,
0x22, 0x33, 0x7A, 0x37, 0x34, 0x53, 0x60, 0x7E
};
static const SshKdfTestVector sshKdfTestVectors[] = {
{WC_HASH_TYPE_SHA256, 'A',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3a, sizeof(sshKdfTvSet3a)},
{WC_HASH_TYPE_SHA256, 'B',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3b, sizeof(sshKdfTvSet3b)},
{WC_HASH_TYPE_SHA256, 'C',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3c, sizeof(sshKdfTvSet3c)},
{WC_HASH_TYPE_SHA256, 'D',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3d, sizeof(sshKdfTvSet3d)},
{WC_HASH_TYPE_SHA256, 'E',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3e, sizeof(sshKdfTvSet3e)},
{WC_HASH_TYPE_SHA256, 'F',
sshKdfTvSet3k, sizeof(sshKdfTvSet3k),
sshKdfTvSet3h, sizeof(sshKdfTvSet3h),
sshKdfTvSet3sid, sizeof(sshKdfTvSet3sid),
sshKdfTvSet3f, sizeof(sshKdfTvSet3f)},
};
int sshkdf_test(void)
{
int result = 0;
word32 i;
word32 tc = sizeof(sshKdfTestVectors)/sizeof(SshKdfTestVector);
const SshKdfTestVector* tv = NULL;
byte cKey[32]; /* Greater of SHA256_DIGEST_SIZE and AES_BLOCK_SIZE */
/* sId - Session ID, eKey - Expected Key, cKey - Calculated Key */
for (i = 0, tv = sshKdfTestVectors; i < tc; i++, tv++) {
result = wc_SSH_KDF(tv->hashId, tv->keyId,
cKey, tv->expectedKeySz,
tv->k, tv->kSz, tv->h, tv->hSz,
tv->sessionId, tv->sessionIdSz);
if (result != 0) {
printf("KDF: Could not derive key.\n");
result = -101;
}
else {
if (memcmp(cKey, tv->expectedKey, tv->expectedKeySz) != 0) {
printf("KDF: Calculated Key does not match Expected Key.\n");
result = -102;
}
}
if (result != 0) break;
}
return result;
}
#endif /* WOLFSSL_WOLFSSH */
#if defined(HAVE_ECC) && defined(HAVE_X963_KDF)
WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void)

View File

@@ -236,6 +236,16 @@ WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
#endif /* HAVE_HKDF */
#ifdef WOLFSSL_WOLFSSH
WOLFSSL_API int wc_SSH_KDF(byte hashId, byte keyId,
byte* key, word32 keySz,
const byte* k, word32 kSz,
const byte* h, word32 hSz,
const byte* sessionId, word32 sessionIdSz);
#endif /* WOLFSSL_SSH */
#ifdef __cplusplus
} /* extern "C" */
#endif