1. Add server auth support for RSA signing with SHA2-256 and SHA2-512.
pull/517/head
John Safranek 2023-05-24 10:35:04 -07:00
parent f41135dbd9
commit 826a045bf4
4 changed files with 611 additions and 504 deletions

View File

@ -668,8 +668,8 @@ static WOLFSSH_AGENT_ID* FindKeyId(WOLFSSH_AGENT_ID* id,
}
#if !defined(WOLFSSH_NO_SSH_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_SSH_RSA_SHA2_512)
#if !defined(WOLFSSH_NO_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_RSA_SHA2_512)
static int SignHashRsa(WOLFSSH_AGENT_KEY_RSA* rawKey, enum wc_HashType hashType,
const byte* digest, word32 digestSz, byte* sig, word32* sigSz,
@ -710,7 +710,7 @@ static int SignHashRsa(WOLFSSH_AGENT_KEY_RSA* rawKey, enum wc_HashType hashType,
return ret;
}
#endif /* WOLFSSH_NO_SSH_RSA_SHA2_256/512 */
#endif /* WOLFSSH_NO_RSA_SHA2_256/512 */
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
@ -804,16 +804,16 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
if (ret == WS_SUCCESS) {
switch (id->keyType) {
#if !defined(WOLFSSH_NO_SSH_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_SSH_RSA_SHA2_512)
#if !defined(WOLFSSH_NO_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_RSA_SHA2_512)
case ID_SSH_RSA:
signRsa = 1;
#ifndef WOLFSSH_NO_SSH_RSA_SHA2_256
#ifndef WOLFSSH_NO_RSA_SHA2_256
if (flags & AGENT_SIGN_RSA_SHA2_256)
hashType = WC_HASH_TYPE_SHA256;
else
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA2_512
#ifndef WOLFSSH_NO_RSA_SHA2_512
if (flags & AGENT_SIGN_RSA_SHA2_512)
hashType = WC_HASH_TYPE_SHA512;
else
@ -854,8 +854,8 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
}
if (ret == WS_SUCCESS) {
#if !defined(WOLFSSH_NO_SSH_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_SSH_RSA_SHA2_512)
#if !defined(WOLFSSH_NO_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_RSA_SHA2_512)
if (signRsa)
ret = SignHashRsa(&id->key.rsa, hashType,
digest, digestSz, sig, &sigSz, &agent->rng, agent->heap);

File diff suppressed because it is too large Load Diff

View File

@ -283,7 +283,7 @@ static const char serverKeyEccDer[] =
static const byte serverKeyEccCurveId = ID_ECDSA_SHA2_NISTP521;
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
#ifndef WOLFSSH_NO_RSA
static const char serverKeyRsaDer[] =
"308204a30201000282010100da5dad2514761559f340fd3cb86230b36dc0f9ec"
"ec8b831e9e429cca416ad38ae15234e00d13627ed40fae5c4d04f18dfac5ad77"
@ -330,13 +330,11 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void)
{
#ifndef WOLFSSH_NO_SERVER
WOLFSSH_CTX* ctx;
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
#ifndef WOLFSSH_NO_ECDSA
byte* eccKey;
word32 eccKeySz;
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
#ifndef WOLFSSH_NO_RSA
byte* rsaKey;
word32 rsaKeySz;
#endif
@ -344,16 +342,14 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void)
word32 lastKeySz = 0;
int i;
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
#ifndef WOLFSSH_NO_ECC
AssertIntEQ(0,
ConvertHexToBin(serverKeyEccDer, &eccKey, &eccKeySz,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL));
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
#ifndef WOLFSSH_NO_RSA
AssertIntEQ(0,
ConvertHexToBin(serverKeyRsaDer, &rsaKey, &rsaKeySz,
NULL, NULL, NULL,
@ -363,85 +359,85 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void)
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
for (i = 0; i < WOLFSSH_MAX_PVT_KEYS; i++) {
AssertNull(ctx->privateKey[i]);
AssertIntEQ(0, ctx->privateKeySz[i]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[i]);
AssertNull(ctx->privateKey[i].key);
AssertIntEQ(0, ctx->privateKey[i].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[i].publicKeyFmt);
}
AssertIntEQ(0, ctx->privateKeyCount);
/* Fail: all NULL/BAD */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(NULL, NULL, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey[0]);
AssertIntEQ(0, ctx->privateKeySz[0]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[0]);
AssertNull(ctx->privateKey[0].key);
AssertIntEQ(0, ctx->privateKey[0].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, ctx->privateKeyCount);
/* Fail: ctx set, others NULL/bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, NULL, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey[0]);
AssertIntEQ(0, ctx->privateKeySz[0]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[0]);
AssertNull(ctx->privateKey[0].key);
AssertIntEQ(0, ctx->privateKey[0].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, ctx->privateKeyCount);
/* Fail: ctx set, key set, others bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx,
lastKey, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey[0]);
AssertIntEQ(0, ctx->privateKeySz[0]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[0]);
AssertNull(ctx->privateKey[0].key);
AssertIntEQ(0, ctx->privateKey[0].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, ctx->privateKeyCount);
/* Fail: ctx set, keySz set, others NULL/bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, NULL, 1, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey[0]);
AssertIntEQ(0, ctx->privateKeySz[0]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[0]);
AssertNull(ctx->privateKey[0].key);
AssertIntEQ(0, ctx->privateKey[0].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, ctx->privateKeyCount);
/* Fail: ctx set, key set, keySz set, format invalid */
AssertIntNE(WS_SUCCESS, wolfSSH_CTX_UsePrivateKey_buffer(ctx,
lastKey, lastKeySz, TEST_GOOD_FORMAT_PEM));
AssertNull(ctx->privateKey[0]);
AssertIntEQ(0, ctx->privateKeySz[0]);
AssertIntEQ(ID_NONE, ctx->privateKeyId[0]);
AssertNull(ctx->privateKey[0].key);
AssertIntEQ(0, ctx->privateKey[0].keySz);
AssertIntEQ(ID_NONE, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, ctx->privateKeyCount);
/* Pass */
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
lastKey = ctx->privateKey[ctx->privateKeyCount];
lastKeySz = ctx->privateKeySz[ctx->privateKeyCount];
lastKey = ctx->privateKey[ctx->privateKeyCount].key;
lastKeySz = ctx->privateKey[ctx->privateKeyCount].keySz;
AssertIntEQ(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, eccKey, eccKeySz,
TEST_GOOD_FORMAT_ASN1));
AssertIntEQ(1, ctx->privateKeyCount);
AssertNotNull(ctx->privateKey[0]);
AssertIntNE(0, ctx->privateKeySz[0]);
AssertIntEQ(serverKeyEccCurveId, ctx->privateKeyId[0]);
AssertNotNull(ctx->privateKey[0].key);
AssertIntNE(0, ctx->privateKey[0].keySz);
AssertIntEQ(serverKeyEccCurveId, ctx->privateKey[0].publicKeyFmt);
AssertIntEQ(0, (lastKey == ctx->privateKey[0]));
AssertIntNE(lastKeySz, ctx->privateKeySz[0]);
AssertIntEQ(0, (lastKey == ctx->privateKey[0].key));
AssertIntNE(lastKeySz, ctx->privateKey[0].keySz);
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
lastKey = ctx->privateKey[ctx->privateKeyCount];
lastKeySz = ctx->privateKeySz[ctx->privateKeyCount];
lastKey = ctx->privateKey[ctx->privateKeyCount].key;
lastKeySz = ctx->privateKey[ctx->privateKeyCount].keySz;
AssertIntEQ(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, rsaKey, rsaKeySz,
TEST_GOOD_FORMAT_ASN1));
AssertIntNE(0, ctx->privateKeyCount);
AssertNotNull(ctx->privateKey[0]);
AssertIntNE(0, ctx->privateKeySz[0]);
AssertNotNull(ctx->privateKey[0].key);
AssertIntNE(0, ctx->privateKey[0].keySz);
AssertIntEQ(0, (lastKey == ctx->privateKey[0]));
AssertIntNE(lastKeySz, ctx->privateKeySz[0]);
AssertIntEQ(0, (lastKey == ctx->privateKey[0].key));
AssertIntNE(lastKeySz, ctx->privateKey[0].keySz);
#endif
/* Add the same keys again. This should succeed. */
@ -464,7 +460,7 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer(void)
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
FreeBins(eccKey, NULL, NULL, NULL);
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
#ifndef WOLFSSH_NO_RSA
FreeBins(rsaKey, NULL, NULL, NULL);
#endif
#endif /* WOLFSSH_NO_SERVER */

View File

@ -65,9 +65,26 @@ extern "C" {
#endif
/* Check options set by wolfSSL and set wolfSSH options as appropriate. If
/*
* Force some options. Do not want ssh-rsa with SHA1 at anymore. Not ready
* for rsa-sha2-512 yet.
*/
#undef WOLFSSH_NO_SSH_RSA_SHA1
#ifndef WOLFSSH_YES_SSH_RSA_SHA1
#define WOLFSSH_NO_SSH_RSA_SHA1
#endif
#undef WOLFSSH_NO_RSA_SHA2_512
#ifndef WOLFSSH_YES_RSA_SHA2_512
#define WOLFSSH_NO_RSA_SHA2_512
#endif
/*
* Check options set by wolfSSL and set wolfSSH options as appropriate. If
* the derived options and any override options leave wolfSSH without
* at least one algorithm to use, throw an error. */
* at least one algorithm to use, throw an error.
*/
#ifdef NO_RSA
#undef WOLFSSH_NO_RSA
@ -123,15 +140,18 @@ extern "C" {
#undef WOLFSSH_NO_DH_GEX_SHA256
#define WOLFSSH_NO_DH_GEX_SHA256
#endif
#if defined(WOLFSSH_NO_ECDH) || defined(NO_SHA256) || defined(NO_ECC256)
#if defined(WOLFSSH_NO_ECDH) \
|| defined(NO_SHA256) || defined(NO_ECC256)
#undef WOLFSSH_NO_ECDH_SHA2_NISTP256
#define WOLFSSH_NO_ECDH_SHA2_NISTP256
#endif
#if defined(WOLFSSH_NO_ECDH) || !defined(WOLFSSL_SHA384) || !defined(HAVE_ECC384)
#if defined(WOLFSSH_NO_ECDH) \
|| !defined(WOLFSSL_SHA384) || !defined(HAVE_ECC384)
#undef WOLFSSH_NO_ECDH_SHA2_NISTP384
#define WOLFSSH_NO_ECDH_SHA2_NISTP384
#endif
#if defined(WOLFSSH_NO_ECDH) || !defined(WOLFSSL_SHA512) || !defined(HAVE_ECC521)
#if defined(WOLFSSH_NO_ECDH) \
|| !defined(WOLFSSL_SHA512) || !defined(HAVE_ECC521)
#undef WOLFSSH_NO_ECDH_SHA2_NISTP521
#define WOLFSSH_NO_ECDH_SHA2_NISTP521
#endif
@ -174,12 +194,12 @@ extern "C" {
#define WOLFSSH_NO_SSH_RSA_SHA1
#endif
#if defined(WOLFSSH_NO_RSA) || defined(NO_SHA256)
#undef WOLFSSH_NO_SSH_RSA_SHA2_256
#define WOLFSSH_NO_SSH_RSA_SHA2_256
#undef WOLFSSH_NO_RSA_SHA2_256
#define WOLFSSH_NO_RSA_SHA2_256
#endif
#if defined(WOLFSSH_NO_RSA) || !defined(WOLFSSL_SHA512)
#undef WOLFSSH_NO_SSH_RSA_SHA2_512
#define WOLFSSH_NO_SSH_RSA_SHA2_512
#undef WOLFSSH_NO_RSA_SHA2_512
#define WOLFSSH_NO_RSA_SHA2_512
#endif
#if defined(WOLFSSH_NO_ECDSA) || \
@ -198,13 +218,17 @@ extern "C" {
#define WOLFSSH_NO_ECDSA_SHA2_NISTP521
#endif
#if defined(WOLFSSH_NO_SSH_RSA_SHA1) && \
defined(WOLFSSH_NO_RSA_SHA2_256) && \
defined(WOLFSSH_NO_RSA_SHA2_512) && \
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && \
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && \
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
#error "You need at least one signing algorithm."
#endif
#ifdef WOLFSSH_NO_SSH_RSA_SHA1
#if defined(WOLFSSH_NO_SSH_RSA_SHA1) && \
defined(WOLFSSH_NO_RSA_SHA2_256) && \
defined(WOLFSSH_NO_RSA_SHA2_512)
#undef WOLFSSH_NO_RSA
#define WOLFSSH_NO_RSA
#endif
@ -290,7 +314,9 @@ enum {
#endif
/* Public Key IDs */
ID_SSH_RSA,
ID_SSH_RSA, /* 0x16 */
ID_RSA_SHA2_256, /* 0x17 */
ID_RSA_SHA2_512,
ID_ECDSA_SHA2_NISTP256,
ID_ECDSA_SHA2_NISTP384,
ID_ECDSA_SHA2_NISTP521,
@ -383,6 +409,9 @@ enum {
#ifndef WOLFSSH_MAX_PVT_KEYS
#define WOLFSSH_MAX_PVT_KEYS 2
#endif
#ifndef WOLFSSH_MAX_PUB_KEY_ALGO
#define WOLFSSH_MAX_PUB_KEY_ALGO (WOLFSSH_MAX_PVT_KEYS + 2)
#endif
WOLFSSH_LOCAL byte NameToId(const char*, word32);
WOLFSSH_LOCAL const char* IdToName(byte);
@ -410,6 +439,21 @@ WOLFSSH_LOCAL int GrowBuffer(WOLFSSH_BUFFER* buf, word32 sz, word32 usedSz);
WOLFSSH_LOCAL void ShrinkBuffer(WOLFSSH_BUFFER* buf, int forcedFree);
typedef struct WOLFSSH_PVT_KEY {
byte* key;
/* List of pointers to raw private keys. Owned by CTX. */
word32 keySz;
#ifdef WOLFSSH_CERTS
byte* cert;
/* Pointer to certificates for the private key. Owned by CTX. */
word32 certSz;
#endif
byte publicKeyFmt;
/* Public key format for the private key. Note, some public key
* formats are used with multiple public key signing algorithms. */
} WOLFSSH_PVT_KEY;
/* our wolfSSH Context */
struct WOLFSSH_CTX {
void* heap; /* heap hint */
@ -438,17 +482,11 @@ struct WOLFSSH_CTX {
WOLFSSH_CERTMAN* certMan;
#endif /* WOLFSSH_CERTS */
WS_CallbackPublicKeyCheck publicKeyCheckCb;
/* Check server's public key callback */
byte* privateKey[WOLFSSH_MAX_PVT_KEYS];
/* Owned by CTX */
word32 privateKeySz[WOLFSSH_MAX_PVT_KEYS];
#ifdef WOLFSSH_CERTS
/* public certificate matching the private key */
byte* cert[WOLFSSH_MAX_PVT_KEYS];
word32 certSz[WOLFSSH_MAX_PVT_KEYS];
#endif
byte privateKeyId[WOLFSSH_MAX_PVT_KEYS];
/* Check server's public key callback */
WOLFSSH_PVT_KEY privateKey[WOLFSSH_MAX_PVT_KEYS];
word32 privateKeyCount;
byte publicKeyAlgo[WOLFSSH_MAX_PUB_KEY_ALGO];
word32 publicKeyAlgoCount;
word32 highwaterMark;
const char* banner;
word32 bannerSz;
@ -480,11 +518,10 @@ typedef struct Keys {
typedef struct HandshakeInfo {
byte kexId;
byte kexIdGuess;
byte kexHashId;
byte pubKeyId;
byte sigId;
byte encryptId;
byte macId;
byte hashId;
byte kexPacketFollows;
byte aeadMode;
@ -493,9 +530,9 @@ typedef struct HandshakeInfo {
Keys keys;
Keys peerKeys;
wc_HashAlg hash;
wc_HashAlg kexHash;
byte e[MAX_KEX_KEY_SZ+1]; /* May have a leading zero for unsigned
or is a Q_S value. */
or is a Q_S value. */
word32 eSz;
byte x[MAX_KEX_KEY_SZ+1]; /* May have a leading zero, for unsigned. */
word32 xSz;