diff --git a/src/agent.c b/src/agent.c index 1522f3b4..9706706f 100644 --- a/src/agent.c +++ b/src/agent.c @@ -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); diff --git a/src/internal.c b/src/internal.c index 3136115e..bd9df979 100644 --- a/src/internal.c +++ b/src/internal.c @@ -489,12 +489,11 @@ static HandshakeInfo* HandshakeInfoNew(void* heap) if (newHs != NULL) { WMEMSET(newHs, 0, sizeof(HandshakeInfo)); newHs->kexId = ID_NONE; + newHs->kexHashId = WC_HASH_TYPE_NONE; newHs->pubKeyId = ID_NONE; - newHs->sigId = ID_NONE; newHs->encryptId = ID_NONE; newHs->macId = ID_NONE; newHs->blockSz = MIN_BLOCK_SZ; - newHs->hashId = WC_HASH_TYPE_NONE; newHs->eSz = sizeof newHs->e; newHs->xSz = sizeof newHs->x; #ifndef WOLFSSH_NO_DH_GEX_SHA256 @@ -519,8 +518,9 @@ static void HandshakeInfoFree(HandshakeInfo* hs, void* heap) WFREE(hs->primeGroup, heap, DYNTYPE_MPINT); WFREE(hs->generator, heap, DYNTYPE_MPINT); #endif - if (hs->hashId != WC_HASH_TYPE_NONE) - wc_HashFree(&hs->hash, (enum wc_HashType)hs->hashId); + if (hs->kexHashId != WC_HASH_TYPE_NONE) { + wc_HashFree(&hs->kexHash, (enum wc_HashType)hs->kexHashId); + } ForceZero(hs, sizeof(HandshakeInfo)); WFREE(hs, heap, DYNTYPE_HS); } @@ -542,7 +542,7 @@ static const word32 cannedBannerSz = sizeof(cannedBanner) - 1; WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap) { - word32 idx; + word32 idx, count; WLOG(WS_LOG_DEBUG, "Entering CtxInit()"); @@ -577,8 +577,13 @@ WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap) ctx->windowSz = DEFAULT_WINDOW_SZ; ctx->maxPacketSz = DEFAULT_MAX_PACKET_SZ; - for (idx = 0; idx < WOLFSSH_MAX_PVT_KEYS; idx++) { - ctx->privateKeyId[idx] = ID_NONE; + count = sizeof(ctx->privateKey) / sizeof(ctx->privateKey[0]); + for (idx = 0; idx < count; idx++) { + ctx->privateKey[idx].publicKeyFmt = ID_NONE; + } + count = sizeof(ctx->publicKeyAlgo) / sizeof(ctx->publicKeyAlgo[0]); + for (idx = 0; idx < count; idx++) { + ctx->publicKeyAlgo[idx] = ID_NONE; } return ctx; @@ -593,20 +598,20 @@ void CtxResourceFree(WOLFSSH_CTX* ctx) word32 i; for (i = 0; i < ctx->privateKeyCount; i++) { - if (ctx->privateKey[i] != NULL) { - ForceZero(ctx->privateKey[i], ctx->privateKeySz[i]); - WFREE(ctx->privateKey[i], ctx->heap, DYNTYPE_PRIVKEY); - ctx->privateKey[i] = NULL; - ctx->privateKeySz[i] = 0; + if (ctx->privateKey[i].key != NULL) { + ForceZero(ctx->privateKey[i].key, ctx->privateKey[i].keySz); + WFREE(ctx->privateKey[i].key, ctx->heap, DYNTYPE_PRIVKEY); + ctx->privateKey[i].key = NULL; + ctx->privateKey[i].keySz = 0; } #ifdef WOLFSSH_CERTS - if (ctx->cert[i] != NULL) { - WFREE(ctx->cert[i], ctx->heap, DYNTYPE_CERT); - ctx->cert[i] = NULL; - ctx->certSz[i] = 0; + if (ctx->privateKey[i].cert != NULL) { + WFREE(ctx->privateKey[i].cert, ctx->heap, DYNTYPE_CERT); + ctx->privateKey[i].cert = NULL; + ctx->privateKey[i].certSz = 0; } #endif - ctx->privateKeyId[i] = ID_NONE; + ctx->privateKey[i].publicKeyFmt = ID_NONE; } ctx->privateKeyCount = 0; } @@ -624,47 +629,46 @@ void CtxResourceFree(WOLFSSH_CTX* ctx) static void UpdateKeyID(WOLFSSH_CTX* ctx) { #ifdef WOLFSSH_CERTS + WOLFSSH_PVT_KEY* pvtKey; word32 idx; - for (idx = 0; idx < ctx->privateKeyCount && - idx < WOLFSSH_MAX_PVT_KEYS; idx++) { - if (ctx->cert[idx] != NULL && ctx->certSz[idx] > 0) { - byte keyId; + for (idx = 0, pvtKey = ctx->privateKey; + idx < ctx->privateKeyCount && idx < WOLFSSH_MAX_PVT_KEYS; + idx++, pvtKey++) { + if (pvtKey->cert != NULL && pvtKey->certSz > 0) { byte* der; /* matching certificate was set, convert private key id */ - keyId = ctx->privateKeyId[idx]; - switch (keyId) { + switch (pvtKey->publicKeyFmt) { #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521 case ID_ECDSA_SHA2_NISTP521: - ctx->privateKeyId[idx] = ID_X509V3_ECDSA_SHA2_NISTP521; + pvtKey->publicKeyFmt = ID_X509V3_ECDSA_SHA2_NISTP521; break; #endif #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384 case ID_ECDSA_SHA2_NISTP384: - ctx->privateKeyId[idx] = ID_X509V3_ECDSA_SHA2_NISTP384; + pvtKey->publicKeyFmt = ID_X509V3_ECDSA_SHA2_NISTP384; break; #endif #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 case ID_ECDSA_SHA2_NISTP256: - ctx->privateKeyId[idx] = ID_X509V3_ECDSA_SHA2_NISTP256; + pvtKey->publicKeyFmt = ID_X509V3_ECDSA_SHA2_NISTP256; break; #endif #ifndef WOLFSSH_NO_SSH_RSA_SHA1 case ID_SSH_RSA: - ctx->privateKeyId[idx] = ID_X509V3_SSH_RSA; + pvtKey->publicKeyFmt = ID_X509V3_SSH_RSA; break; #endif } /* can use the key for non X509v3 connections too */ - der = (byte*)WMALLOC(ctx->privateKeySz[idx], ctx->heap, - DYNTYPE_PRIVKEY); + der = (byte*)WMALLOC(pvtKey->keySz, ctx->heap, DYNTYPE_PRIVKEY); if (der != NULL) { int ret; - WMEMCPY(der, ctx->privateKey[idx], ctx->privateKeySz[idx]); - ret = SetHostPrivateKey(ctx, keyId, 1, der, - ctx->privateKeySz[idx], DYNTYPE_PRIVKEY); + WMEMCPY(der, pvtKey->key, pvtKey->keySz); + ret = SetHostPrivateKey(ctx, pvtKey->publicKeyFmt, 1, + der, pvtKey->keySz, DYNTYPE_PRIVKEY); if (ret != 0) { WFREE(der, ctx->heap, DYNTYPE_PRIVKEY); } @@ -867,6 +871,7 @@ union wolfSSH_key { * Identifies the flavor of a key, RSA or ECDSA, and returns the key type ID. * The process is to decode the key as if it was RSA and if that fails try * to load it as if ECDSA. Both public and private keys can be decoded. + * For RSA keys, the key format is described as "ssh-rsa". * * @param in key to identify * @param inSz size of key @@ -908,7 +913,7 @@ int IdentifyKey(const byte* in, word32 inSz, int isPrivate, void* heap) wc_FreeRsaKey(&key->rsa); } } -#endif +#endif /* WOLFSSH_NO_RSA */ #ifndef WOLFSSH_NO_ECDSA if (key != NULL) { /* Check ECDSA key */ @@ -943,7 +948,7 @@ int IdentifyKey(const byte* in, word32 inSz, int isPrivate, void* heap) wc_ecc_free(&key->ecc); } } -#endif /* ! WOLFSSH_NO_ECDSA */ +#endif /* WOLFSSH_NO_ECDSA */ if (key == NULL) { ret = WS_MEMORY_E; @@ -1027,6 +1032,48 @@ static int IdentifyCert(const byte* in, word32 inSz, void* heap) #endif /* WOLFSSH_CERTS */ +static void RefreshPublicKeyAlgo(WOLFSSH_CTX* ctx) +{ + WOLFSSH_PVT_KEY* key; + byte* publicKeyAlgo = ctx->publicKeyAlgo; + word32 keyCount = ctx->privateKeyCount, publicKeyAlgoCount = 0, idx; + + for (idx = 0, key = ctx->privateKey; idx < keyCount; idx++, key++) { + if (key->publicKeyFmt == ID_SSH_RSA) { + #ifndef WOLFSSH_NO_RSA_SHA2_512 + if (publicKeyAlgoCount < WOLFSSH_MAX_PUB_KEY_ALGO) { + *publicKeyAlgo = ID_RSA_SHA2_512; + publicKeyAlgo++; + publicKeyAlgoCount++; + } + #endif + #ifndef WOLFSSH_NO_RSA_SHA2_256 + if (publicKeyAlgoCount < WOLFSSH_MAX_PUB_KEY_ALGO) { + *publicKeyAlgo = ID_RSA_SHA2_256; + publicKeyAlgo++; + publicKeyAlgoCount++; + } + #endif + #ifndef WOLFSSH_NO_SSH_RSA_SHA1 + if (publicKeyAlgoCount < WOLFSSH_MAX_PUB_KEY_ALGO) { + *publicKeyAlgo = ID_SSH_RSA; + publicKeyAlgo++; + publicKeyAlgoCount++; + } + #endif + } + else { + if (publicKeyAlgoCount < WOLFSSH_MAX_PUB_KEY_ALGO) { + *publicKeyAlgo = key->publicKeyFmt; + publicKeyAlgo++; + publicKeyAlgoCount++; + } + } + } + ctx->publicKeyAlgoCount = publicKeyAlgoCount; +} + + int SetHostPrivateKey(WOLFSSH_CTX* ctx, byte keyId, int isKey, byte* der, word32 derSz, int dynamicType) { @@ -1035,8 +1082,8 @@ int SetHostPrivateKey(WOLFSSH_CTX* ctx, byte keyId, int isKey, WOLFSSH_UNUSED(dynamicType); - while (destIdx < ctx->privateKeyCount && - ctx->privateKeyId[destIdx] != keyId) { + while (destIdx < ctx->privateKeyCount + && ctx->privateKey[destIdx].publicKeyFmt != keyId) { destIdx++; } @@ -1044,37 +1091,39 @@ int SetHostPrivateKey(WOLFSSH_CTX* ctx, byte keyId, int isKey, ret = WS_CTX_KEY_COUNT_E; } else { - if (ctx->privateKeyId[destIdx] == keyId) { + WOLFSSH_PVT_KEY* pvtKey = ctx->privateKey + destIdx; + if (pvtKey->publicKeyFmt == keyId) { if (isKey) { - if (ctx->privateKey[destIdx] != NULL) { - ForceZero(ctx->privateKey[destIdx], - ctx->privateKeySz[destIdx]); - WFREE(ctx->privateKey[destIdx], heap, dynamicType); + if (pvtKey->key != NULL) { + ForceZero(pvtKey->key, pvtKey->keySz); + WFREE(pvtKey->key, heap, dynamicType); } } #ifdef WOLFSSH_CERTS else { - if (ctx->cert[destIdx] != NULL) { - WFREE(ctx->cert[destIdx], heap, dynamicType); + if (pvtKey->cert != NULL) { + WFREE(pvtKey->cert, heap, dynamicType); } } #endif /* WOLFSSH_CERTS */ } else { ctx->privateKeyCount++; - ctx->privateKeyId[destIdx] = keyId; + pvtKey->publicKeyFmt = keyId; } if (isKey) { - ctx->privateKey[destIdx] = der; - ctx->privateKeySz[destIdx] = derSz; + pvtKey->key = der; + pvtKey->keySz = derSz; } #ifdef WOLFSSH_CERTS else { - ctx->cert[destIdx] = der; - ctx->certSz[destIdx] = derSz; + pvtKey->cert = der; + pvtKey->certSz = derSz; } #endif /* WOLFSSH_CERTS */ + + RefreshPublicKeyAlgo(ctx); } return ret; @@ -1456,12 +1505,18 @@ static const NameIdPair NameIdMap[] = { #ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 /* We use kyber-512 here to achieve interop with OQS's fork. */ { ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256, - "ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org" }, + "ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org" }, #endif /* Public Key IDs */ -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 +#ifndef WOLFSSH_NO_RSA { ID_SSH_RSA, "ssh-rsa" }, +#ifndef WOLFSSH_NO_RSA_SHA2_256 + { ID_RSA_SHA2_256, "rsa-sha2-256" }, #endif +#ifndef WOLFSSH_NO_RSA_SHA2_512 + { ID_RSA_SHA2_512, "rsa-sha2-512" }, +#endif +#endif /* WOLFSSH_NO_RSA */ #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 { ID_ECDSA_SHA2_NISTP256, "ecdsa-sha2-nistp256" }, #endif @@ -2454,6 +2509,12 @@ static const byte cannedKeyAlgoClient[] = { #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 ID_ECDSA_SHA2_NISTP256, #endif +#ifndef WOLFSSH_NO_RSA_SHA2_512 + ID_RSA_SHA2_512, +#endif +#ifndef WOLFSSH_NO_RSA_SHA2_256 + ID_RSA_SHA2_256, +#endif #ifndef WOLFSSH_NO_SSH_RSA_SHA1 ID_SSH_RSA, #endif @@ -2657,6 +2718,10 @@ static INLINE enum wc_HashType HashForId(byte id) case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256: return WC_HASH_TYPE_SHA256; #endif +#ifndef WOLFSSH_NO_RSA_SHA2_256 + case ID_RSA_SHA2_256: + return WC_HASH_TYPE_SHA256; +#endif /* SHA2-384 */ #ifndef WOLFSSH_NO_ECDH_SHA2_NISTP384 @@ -2683,6 +2748,11 @@ static INLINE enum wc_HashType HashForId(byte id) #endif return WC_HASH_TYPE_SHA512; #endif +#ifndef WOLFSSH_NO_RSA_SHA2_512 + case ID_RSA_SHA2_512: + return WC_HASH_TYPE_SHA512; +#endif + default: return WC_HASH_TYPE_NONE; } @@ -2763,45 +2833,6 @@ static INLINE byte AeadModeForId(byte id) } -/* We have pairs of PubKey types that use the same signature, - * i.e. ecdsa-sha2-nistp256 and x509v3-ecdsa-sha2-nistp256. */ -static INLINE byte SigTypeForId(byte id) -{ - switch (id) { -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 - #ifdef WOLFSSH_CERTS - case ID_X509V3_SSH_RSA: - #endif - case ID_SSH_RSA: - return ID_SSH_RSA; -#endif -#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 - #ifdef WOLFSSH_CERTS - case ID_X509V3_ECDSA_SHA2_NISTP256: - #endif - case ID_ECDSA_SHA2_NISTP256: - return ID_ECDSA_SHA2_NISTP256; -#endif -#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384 - #ifdef WOLFSSH_CERTS - case ID_X509V3_ECDSA_SHA2_NISTP384: - #endif - case ID_ECDSA_SHA2_NISTP384: - return ID_ECDSA_SHA2_NISTP384; -#endif -#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521 - #ifdef WOLFSSH_CERTS - case ID_X509V3_ECDSA_SHA2_NISTP521: - #endif - case ID_ECDSA_SHA2_NISTP521: - return ID_ECDSA_SHA2_NISTP521; -#endif - default: - return 0; - } -} - - static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) { int ret = WS_SUCCESS; @@ -2868,7 +2899,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } else { ssh->handshake->kexId = algoId; - ssh->handshake->hashId = HashForId(algoId); + ssh->handshake->kexHashId = HashForId(algoId); } } } @@ -2883,11 +2914,10 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) word32 cannedKeyAlgoSz = 0; if (side == WOLFSSH_ENDPOINT_SERVER) { - cannedKeyAlgo = ssh->ctx->privateKeyId; - cannedKeyAlgoSz = ssh->ctx->privateKeyCount; + cannedKeyAlgo = ssh->ctx->publicKeyAlgo; + cannedKeyAlgoSz = ssh->ctx->publicKeyAlgoCount; } else { - /* XXX Does this need to be different for client? */ cannedKeyAlgo = cannedKeyAlgoClient; cannedKeyAlgoSz = cannedKeyAlgoClientSz; } @@ -2899,7 +2929,6 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } else { ssh->handshake->pubKeyId = algoId; - ssh->handshake->sigId = SigTypeForId(algoId); } } } @@ -3050,7 +3079,8 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } if (ret == WS_SUCCESS) { - enum wc_HashType enmhashId = (enum wc_HashType)ssh->handshake->hashId; + wc_HashAlg* hash = &ssh->handshake->kexHash; + enum wc_HashType hashId = ssh->handshake->kexHashId; byte scratchLen[LENGTH_SZ]; word32 strSz; @@ -3061,13 +3091,12 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) /* account for possible want write case from SendKexInit */ if (ret == WS_SUCCESS || ret == WS_WANT_WRITE) - ret = wc_HashInit(&ssh->handshake->hash, enmhashId); + ret = wc_HashInit(hash, hashId); if (ret == WS_SUCCESS) { if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) { - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->peerProtoId, ssh->peerProtoIdSz); + ret = HashUpdate(hash, hashId, + ssh->peerProtoId, ssh->peerProtoIdSz); } } @@ -3076,51 +3105,41 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) strSz = (word32)WSTRLEN(sshProtoIdStr) - SSH_PROTO_EOL_SZ; c32toa(strSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } if (ret == WS_SUCCESS) { - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - (const byte*)sshProtoIdStr, strSz); + ret = HashUpdate(hash, hashId, (const byte*)sshProtoIdStr, strSz); } if (ret == WS_SUCCESS) { if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT) { - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->peerProtoId, ssh->peerProtoIdSz); + ret = HashUpdate(hash, hashId, + ssh->peerProtoId, ssh->peerProtoIdSz); if (ret == WS_SUCCESS) { - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->handshake->kexInit, - ssh->handshake->kexInitSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->kexInit, ssh->handshake->kexInitSz); } } } if (ret == WS_SUCCESS) { c32toa(len + 1, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } if (ret == WS_SUCCESS) { scratchLen[0] = MSGID_KEXINIT; - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, MSG_ID_SZ); + ret = HashUpdate(hash, hashId, scratchLen, MSG_ID_SZ); } if (ret == WS_SUCCESS) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - buf, len); + ret = HashUpdate(hash, hashId, buf, len); if (ret == WS_SUCCESS) { if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->handshake->kexInit, - ssh->handshake->kexInitSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->kexInit, ssh->handshake->kexInitSz); } if (ret == WS_SUCCESS) { @@ -3130,9 +3149,9 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) else ssh->serverState = SERVER_KEXINIT_DONE; + /* Propagate potential want write case from SendKexInit. */ if (ssh->error != 0) - ret = ssh->error; /* propogate potential want write case from - SendKexInit*/ + ret = ssh->error; } } WLOG(WS_LOG_DEBUG, "Leaving DoKexInit(), ret = %d", ret); @@ -3660,6 +3679,8 @@ static int ParsePubKey(WOLFSSH *ssh, switch (ssh->handshake->pubKeyId) { case ID_SSH_RSA: + case ID_RSA_SHA2_256: + case ID_RSA_SHA2_512: sigKeyBlock_ptr->useRsa = 1; ret = ParseRSAPubKey(ssh, sigKeyBlock_ptr, pubKey, pubKeySz); break; @@ -3697,19 +3718,20 @@ static int ParsePubKey(WOLFSSH *ssh, static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) { - enum wc_HashType enmhashId; + struct wolfSSH_sigKeyBlock *sigKeyBlock_ptr = NULL; + wc_HashAlg* hash = NULL; byte* pubKey = NULL; - word32 pubKeySz; byte* f = NULL; - word32 fSz; byte* sig; + word32 pubKeySz; + word32 fSz; word32 sigSz; word32 scratch; - byte scratchLen[LENGTH_SZ]; - byte kPad = 0; word32 begin; int ret = WS_SUCCESS; - struct wolfSSH_sigKeyBlock *sigKeyBlock_ptr = NULL; + enum wc_HashType hashId; + byte scratchLen[LENGTH_SZ]; + byte kPad = 0; byte keyAllocated = 0; #ifndef WOLFSSH_NO_ECDH ecc_key *key_ptr = NULL; @@ -3764,14 +3786,14 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } } - enmhashId = (enum wc_HashType)ssh->handshake->hashId; + hash = &ssh->handshake->kexHash; + hashId = ssh->handshake->kexHashId; if (ret == WS_SUCCESS) { /* Hash in the raw public key blob from the server including its * length which is at LENGTH_SZ offset ahead of pubKey. */ - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - pubKey - LENGTH_SZ, pubKeySz + LENGTH_SZ); + ret = HashUpdate(hash, hashId, + pubKey - LENGTH_SZ, pubKeySz + LENGTH_SZ); } if (ret == WS_SUCCESS) @@ -3792,23 +3814,17 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) /* Hash in the client's requested minimum key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexMinSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's requested preferred key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexPreferredSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's requested maximum key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexMaxSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Add a pad byte if the mpint has the MSB set. */ if (ret == 0) { @@ -3819,25 +3835,19 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) /* Hash in the length of the GEX prime group. */ c32toa(ssh->handshake->primeGroupSz + primeGroupPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the GEX prime group. */ if (ret == 0) { if (primeGroupPad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the GEX prime group. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->handshake->primeGroup, - ssh->handshake->primeGroupSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->primeGroup, ssh->handshake->primeGroupSz); /* Add a pad byte if the mpint has the MSB set. */ if (ret == 0) { if (ssh->handshake->generator[0] & 0x80) @@ -3845,38 +3855,31 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) /* Hash in the length of the GEX generator. */ c32toa(ssh->handshake->generatorSz + generatorPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the GEX generator. */ if (ret == 0) { if (generatorPad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the GEX generator. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - ssh->handshake->generator, - ssh->handshake->generatorSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->generator, ssh->handshake->generatorSz); } #endif /* Hash in the size of the client's DH e-value (ECDH Q-value). */ if (ret == 0) { c32toa(ssh->handshake->eSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's DH e-value (ECDH Q-value). */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - ssh->handshake->e, ssh->handshake->eSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->e, ssh->handshake->eSz); /* Get and hash in the server's DH f-value (ECDH Q-value) */ if (ret == WS_SUCCESS) { @@ -3892,9 +3895,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) } if (ret == WS_SUCCESS) { - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - f, fSz + LENGTH_SZ); + ret = HashUpdate(hash, hashId, f, fSz + LENGTH_SZ); } if (ret == WS_SUCCESS) { @@ -4091,31 +4092,27 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) if (ret == 0) { c32toa(ssh->kSz + kPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } if ((ret == 0) && (kPad)) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } if (ret == 0) { - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - ssh->k, ssh->kSz); + ret = HashUpdate(hash, hashId, ssh->k, ssh->kSz); } /* Save the exchange hash value H, and session ID. */ if (ret == 0) { - ret = wc_HashFinal(&ssh->handshake->hash, - enmhashId, ssh->h); - wc_HashFree(&ssh->handshake->hash, enmhashId); - ssh->handshake->hashId = WC_HASH_TYPE_NONE; + ret = wc_HashFinal(hash, hashId, ssh->h); + wc_HashFree(hash, hashId); + ssh->handshake->kexHashId = WC_HASH_TYPE_NONE; } if (ret == 0) { - ssh->hSz = wc_HashGetDigestSize(enmhashId); + ssh->hSz = wc_HashGetDigestSize(hashId); if (ssh->sessionIdSz == 0) { WMEMCPY(ssh->sessionId, ssh->h, ssh->hSz); ssh->sessionIdSz = ssh->hSz; @@ -4173,10 +4170,10 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) if (ret == WS_SUCCESS) { ret = wc_SignatureVerify( - HashForId(ssh->handshake->pubKeyId), - WC_SIGNATURE_TYPE_RSA_W_ENC, - ssh->h, ssh->hSz, sig, sigSz, - &sigKeyBlock_ptr->sk, sigKeyBlock_ptr->keySz); + HashForId(ssh->handshake->pubKeyId), + WC_SIGNATURE_TYPE_RSA_W_ENC, + ssh->h, ssh->hSz, sig, sigSz, + &sigKeyBlock_ptr->sk, sigKeyBlock_ptr->keySz); if (ret != 0) { WLOG(WS_LOG_DEBUG, "DoKexDhReply: Signature Verify fail (%d)", @@ -4209,10 +4206,10 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) if (ret == WS_SUCCESS) { ret = wc_SignatureVerify( - HashForId(ssh->handshake->pubKeyId), - WC_SIGNATURE_TYPE_ECC, - ssh->h, ssh->hSz, asnSig, asnSigSz, - &sigKeyBlock_ptr->sk, sigKeyBlock_ptr->keySz); + HashForId(ssh->handshake->pubKeyId), + WC_SIGNATURE_TYPE_ECC, + ssh->h, ssh->hSz, asnSig, asnSigSz, + &sigKeyBlock_ptr->sk, sigKeyBlock_ptr->keySz); if (ret != 0) { WLOG(WS_LOG_DEBUG, "DoKexDhReply: Signature Verify fail (%d)", @@ -4244,7 +4241,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) #ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 useKeyPadding = !ssh->handshake->useEccKyber; #endif - ret = GenerateKeys(ssh, enmhashId, useKeyPadding); + ret = GenerateKeys(ssh, hashId, useKeyPadding); } if (ret == WS_SUCCESS) @@ -7747,31 +7744,35 @@ static int BuildNameList(char* buf, word32 bufSz, int nameSz, idx; WLOG(WS_LOG_DEBUG, "Entering BuildNameList()"); + idx = 0; + do { name = IdToName(*src); nameSz = (int)WSTRLEN(name); - WLOG(WS_LOG_DEBUG, "\tAdding name : %s", name); - if (nameSz + 1 + idx > (int)bufSz) { - idx = WS_BUFFER_E; - break; - } + if (buf != NULL) { + WLOG(WS_LOG_DEBUG, "\tAdding name : %s", name); + if (nameSz + 1 + idx > (int)bufSz) { + idx = WS_BUFFER_E; + break; + } - WMEMCPY(buf + idx, name, nameSz); - idx += nameSz; + WMEMCPY(buf + idx, name, nameSz); + idx += nameSz; - src++; - srcSz--; - if (srcSz == 0) { - buf[idx] = '\0'; + src++; + srcSz--; + buf[idx++] = (srcSz > 0) ? ',' : '\0'; } else { - buf[idx++] = ','; + src++; + srcSz--; + idx += nameSz + 1; } } while (srcSz > 0); - return idx; + return idx - 1; } @@ -7792,10 +7793,6 @@ static const char cannedEncAlgoNames[] = "aes128-cbc," #endif ""; -#if defined(WOLFSSH_NO_AES_GCM) && defined(WOLFSSH_NO_AES_CTR) && \ - defined(WOLFSSH_NO_AES_CBC) -#warning "You need at least one encryption algorithm." -#endif static const char cannedMacAlgoNames[] = #if !defined(WOLFSSH_NO_HMAC_SHA2_256) @@ -7808,20 +7805,8 @@ static const char cannedMacAlgoNames[] = "hmac-sha1," #endif ""; -#if defined(WOLFSSH_NO_HMAC_SHA2_256) && \ - defined(WOLFSSH_NO_HMAC_SHA1_96) && \ - defined(WOLFSSH_NO_HMAC_SHA1) - #warning "You need at least one MAC algorithm." -#endif -#if defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && \ - defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && \ - defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521) && \ - defined(WOLFSSH_NO_SSH_RSA_SHA1) - #warning "You need at least one signing algorithm." -#endif -#define KEY_ALGO_SIZE_GUESS 28 #ifndef WOLFSSH_NO_SSH_RSA_SHA1 #ifdef WOLFSSH_CERTS static const char cannedKeyAlgoX509RsaNames[] = "x509v3-ssh-rsa"; @@ -7848,6 +7833,16 @@ static const char cannedMacAlgoNames[] = "x509v3-ecdsa-sha2-nistp521"; #endif #endif +#ifndef WOLFSSH_NO_SSH_RSA_SHA1 + /* Used for both the signature algorithm and the RSA key format. */ + static const char cannedKeyAlgoSshRsaNames[] = "ssh-rsa"; +#endif +#ifndef WOLFSSH_NO_RSA_SHA2_256 + static const char cannedKeyAlgoRsaSha2_256Names[] = "rsa-sha2-256"; +#endif +#ifndef WOLFSSH_NO_RSA_SHA2_512 + static const char cannedKeyAlgoRsaSha2_512Names[] = "rsa-sha2-512"; +#endif static const char cannedKexAlgoNames[] = #if !defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256) @@ -7873,24 +7868,29 @@ static const char cannedKexAlgoNames[] = #endif ""; -#if defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && \ - defined(WOLFSSH_NO_DH_GEX_SHA256) && \ - defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \ - defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \ - defined(WOLFSSH_NO_ECDH_SHA2_NISTP521) && \ - defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \ - defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256) - #warning "You need at least one key exchange algorithm." -#endif static const char cannedNoneNames[] = "none"; -/* -1 for the null, some are -1 for the comma */ +/* -1 for the null, some are -2 for the null and comma */ static const word32 cannedEncAlgoNamesSz = sizeof(cannedEncAlgoNames) - 2; static const word32 cannedMacAlgoNamesSz = sizeof(cannedMacAlgoNames) - 2; static const word32 cannedKexAlgoNamesSz = sizeof(cannedKexAlgoNames) - 2; static const word32 cannedNoneNamesSz = sizeof(cannedNoneNames) - 1; +#define KEY_ALGO_SIZE_GUESS 28 + +#ifndef WOLFSSH_NO_SSH_RSA_SHA1 + static const word32 cannedKeyAlgoSshRsaNamesSz = + sizeof(cannedKeyAlgoSshRsaNames) - 1; +#endif +#ifndef WOLFSSH_NO_RSA_SHA2_256 + static const word32 cannedKeyAlgoRsaSha2_256NamesSz = + sizeof(cannedKeyAlgoRsaSha2_256Names) - 1; +#endif +#ifndef WOLFSSH_NO_RSA_SHA2_512 + static const word32 cannedKeyAlgoRsaSha2_512NamesSz = + sizeof(cannedKeyAlgoRsaSha2_512Names) - 1; +#endif #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 static const word32 cannedKeyAlgoEcc256NamesSz = sizeof(cannedKeyAlgoEcc256Names) - 1; @@ -7923,8 +7923,8 @@ int SendKexInit(WOLFSSH* ssh) byte* output = NULL; byte* payload = NULL; char* keyAlgoNames = NULL; - const byte* privateKey; - word32 idx = 0, payloadSz = 0, keyAlgoNamesSz = 0, privateKeyCount; + const byte* publicKeyAlgo; + word32 idx = 0, payloadSz = 0, keyAlgoNamesSz = 0, publicKeyAlgoCount; int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering SendKexInit()"); @@ -7952,14 +7952,15 @@ int SendKexInit(WOLFSSH* ssh) if (ret == WS_SUCCESS) { if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) { UpdateKeyID(ssh->ctx); - privateKeyCount = ssh->ctx->privateKeyCount; - privateKey = ssh->ctx->privateKeyId; + publicKeyAlgoCount = ssh->ctx->publicKeyAlgoCount; + publicKeyAlgo = ssh->ctx->publicKeyAlgo; } else { - privateKeyCount = cannedKeyAlgoClientSz; - privateKey = cannedKeyAlgoClient; + publicKeyAlgoCount = cannedKeyAlgoClientSz; + publicKeyAlgo = cannedKeyAlgoClient; } - keyAlgoNamesSz = privateKeyCount * (KEY_ALGO_SIZE_GUESS + 1); + keyAlgoNamesSz = BuildNameList(NULL, 0, + publicKeyAlgo, publicKeyAlgoCount) + 1; keyAlgoNames = (char*)WMALLOC(keyAlgoNamesSz, ssh->ctx->heap, DYNTYPE_STRING); if (keyAlgoNames == NULL) { @@ -7969,7 +7970,7 @@ int SendKexInit(WOLFSSH* ssh) if (ret == WS_SUCCESS) { ret = BuildNameList(keyAlgoNames, keyAlgoNamesSz, - privateKey, privateKeyCount); + publicKeyAlgo, publicKeyAlgoCount); if (ret > 0) { keyAlgoNamesSz = (word32)ret; ret = WS_SUCCESS; @@ -8056,13 +8057,15 @@ int SendKexInit(WOLFSSH* ssh) struct wolfSSH_sigKeyBlockFull { - byte pubKeyId; - byte sigId; + byte pubKeyId; /* handshake->pubKeyId */ + byte pubKeyFmtId; word32 sz; - const char *name; - word32 nameSz; + const char *pubKeyName; /* IdToName(handshake->pubKeyId) */ + word32 pubKeyNameSz; + const char *pubKeyFmtName; + word32 pubKeyFmtNameSz; union { -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 +#ifndef WOLFSSH_NO_RSA struct { RsaKey key; byte e[257]; @@ -8205,9 +8208,9 @@ static int BuildRFC6187Info(WOLFSSH* ssh, int pubKeyID, * returns WS_SUCCESS on success */ static int SendKexGetSigningKey(WOLFSSH* ssh, struct wolfSSH_sigKeyBlockFull *sigKeyBlock_ptr, - enum wc_HashType enmhashId, word32 keyIdx) + enum wc_HashType hashId, wc_HashAlg* hash, word32 keyIdx) { - int ret; + int ret = 0; byte isCert = 0; void* heap; byte scratchLen[LENGTH_SZ]; @@ -8222,27 +8225,24 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, heap = ssh->ctx->heap; - #ifdef WOLFSSH_CERTS switch (sigKeyBlock_ptr->pubKeyId) { + #ifndef WOLFSSH_NO_RSA + #ifdef WOLFSSH_CERTS case ID_X509V3_SSH_RSA: - case ID_X509V3_ECDSA_SHA2_NISTP256: - case ID_X509V3_ECDSA_SHA2_NISTP384: - case ID_X509V3_ECDSA_SHA2_NISTP521: - isCert = 1; - } - #endif - - switch (sigKeyBlock_ptr->sigId) { - #ifndef WOLFSSH_NO_SSH_RSA_SHA1 + isCert = 1; + NO_BREAK; + #endif case ID_SSH_RSA: + case ID_RSA_SHA2_256: + case ID_RSA_SHA2_512: /* Decode the user-configured RSA private key. */ sigKeyBlock_ptr->sk.rsa.eSz = sizeof(sigKeyBlock_ptr->sk.rsa.e); sigKeyBlock_ptr->sk.rsa.nSz = sizeof(sigKeyBlock_ptr->sk.rsa.n); ret = wc_InitRsaKey(&sigKeyBlock_ptr->sk.rsa.key, heap); if (ret == 0) - ret = wc_RsaPrivateKeyDecode(ssh->ctx->privateKey[keyIdx], + ret = wc_RsaPrivateKeyDecode(ssh->ctx->privateKey[keyIdx].key, &scratch, &sigKeyBlock_ptr->sk.rsa.key, - (int)ssh->ctx->privateKeySz[keyIdx]); + (int)ssh->ctx->privateKey[keyIdx].keySz); /* hash in usual public key if not RFC6187 style cert use */ if (!isCert) { @@ -8267,77 +8267,78 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, } if (ret == 0) { sigKeyBlock_ptr->sz = (LENGTH_SZ * 3) + - sigKeyBlock_ptr->nameSz + + sigKeyBlock_ptr->pubKeyFmtNameSz + sigKeyBlock_ptr->sk.rsa.eSz + sigKeyBlock_ptr->sk.rsa.ePad + sigKeyBlock_ptr->sk.rsa.nSz + sigKeyBlock_ptr->sk.rsa.nPad; c32toa(sigKeyBlock_ptr->sz, scratchLen); /* Hash in the length of the public key block. */ - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the length of the key type string. */ if (ret == 0) { - c32toa(sigKeyBlock_ptr->nameSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, scratchLen); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the key type string. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - (byte*)sigKeyBlock_ptr->name, - sigKeyBlock_ptr->nameSz); + ret = HashUpdate(hash, hashId, + (byte*)sigKeyBlock_ptr->pubKeyFmtName, + sigKeyBlock_ptr->pubKeyFmtNameSz); /* Hash in the length of the RSA public key E value. */ if (ret == 0) { c32toa(sigKeyBlock_ptr->sk.rsa.eSz + sigKeyBlock_ptr->sk.rsa.ePad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the RSA public key E value. */ if (ret == 0) { if (sigKeyBlock_ptr->sk.rsa.ePad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the RSA public key E value. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - sigKeyBlock_ptr->sk.rsa.e, - sigKeyBlock_ptr->sk.rsa.eSz); + ret = HashUpdate(hash, hashId, + sigKeyBlock_ptr->sk.rsa.e, + sigKeyBlock_ptr->sk.rsa.eSz); /* Hash in the length of the RSA public key N value. */ if (ret == 0) { c32toa(sigKeyBlock_ptr->sk.rsa.nSz + sigKeyBlock_ptr->sk.rsa.nPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the RSA public key N value. */ if (ret == 0) { if (sigKeyBlock_ptr->sk.rsa.nPad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the RSA public key N value. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - sigKeyBlock_ptr->sk.rsa.n, - sigKeyBlock_ptr->sk.rsa.nSz); + ret = HashUpdate(hash, hashId, + sigKeyBlock_ptr->sk.rsa.n, + sigKeyBlock_ptr->sk.rsa.nSz); } break; - #endif /* WOLFSSH_NO_SSH_RSA_SHA1 */ + #endif /* WOLFSSH_NO_RSA */ #ifndef WOLFSSH_NO_ECDSA + #ifdef WOLFSSH_CERTS + case ID_X509V3_ECDSA_SHA2_NISTP256: + case ID_X509V3_ECDSA_SHA2_NISTP384: + case ID_X509V3_ECDSA_SHA2_NISTP521: + isCert = 1; + NO_BREAK; + #endif case ID_ECDSA_SHA2_NISTP256: case ID_ECDSA_SHA2_NISTP384: case ID_ECDSA_SHA2_NISTP521: sigKeyBlock_ptr->sk.ecc.primeName = - PrimeNameForId(ssh->handshake->sigId); + PrimeNameForId(ssh->handshake->pubKeyId); sigKeyBlock_ptr->sk.ecc.primeNameSz = (word32)strlen(sigKeyBlock_ptr->sk.ecc.primeName); @@ -8347,9 +8348,9 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, INVALID_DEVID); scratch = 0; if (ret == 0) - ret = wc_EccPrivateKeyDecode(ssh->ctx->privateKey[keyIdx], + ret = wc_EccPrivateKeyDecode(ssh->ctx->privateKey[keyIdx].key, &scratch, &sigKeyBlock_ptr->sk.ecc.key, - ssh->ctx->privateKeySz[keyIdx]); + ssh->ctx->privateKey[keyIdx].keySz); /* hash in usual public key if not RFC6187 style cert use */ if (!isCert) { @@ -8364,46 +8365,42 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, /* Hash in the length of the public key block. */ if (ret == 0) { sigKeyBlock_ptr->sz = (LENGTH_SZ * 3) + - sigKeyBlock_ptr->nameSz + + sigKeyBlock_ptr->pubKeyFmtNameSz + sigKeyBlock_ptr->sk.ecc.primeNameSz + sigKeyBlock_ptr->sk.ecc.qSz; c32toa(sigKeyBlock_ptr->sz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the length of the key type string. */ if (ret == 0) { - c32toa(sigKeyBlock_ptr->nameSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, scratchLen); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the key type string. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - (byte*)sigKeyBlock_ptr->name, - sigKeyBlock_ptr->nameSz); + ret = HashUpdate(hash, hashId, + (byte*)sigKeyBlock_ptr->pubKeyFmtName, + sigKeyBlock_ptr->pubKeyFmtNameSz); /* Hash in the length of the name of the prime. */ if (ret == 0) { c32toa(sigKeyBlock_ptr->sk.ecc.primeNameSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the name of the prime. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - (const byte*)sigKeyBlock_ptr->sk.ecc.primeName, - sigKeyBlock_ptr->sk.ecc.primeNameSz); + ret = HashUpdate(hash, hashId, + (const byte*)sigKeyBlock_ptr->sk.ecc.primeName, + sigKeyBlock_ptr->sk.ecc.primeNameSz); /* Hash in the length of the public key. */ if (ret == 0) { c32toa(sigKeyBlock_ptr->sk.ecc.qSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the public key. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - sigKeyBlock_ptr->sk.ecc.q, - sigKeyBlock_ptr->sk.ecc.qSz); + ret = HashUpdate(hash, hashId, + sigKeyBlock_ptr->sk.ecc.q, + sigKeyBlock_ptr->sk.ecc.qSz); } break; #endif @@ -8420,8 +8417,9 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, word32 idx = 0; BuildRFC6187Info(ssh, sigKeyBlock_ptr->pubKeyId, - ssh->ctx->cert[keyIdx], ssh->ctx->certSz[keyIdx], NULL, 0, - NULL, &sigKeyBlock_ptr->sz, &idx); + ssh->ctx->privateKey[keyIdx].cert, + ssh->ctx->privateKey[keyIdx].certSz, + NULL, 0, NULL, &sigKeyBlock_ptr->sz, &idx); tmp = (byte*)WMALLOC(sigKeyBlock_ptr->sz, heap, DYNTYPE_TEMP); if (tmp == NULL) { ret = WS_MEMORY_E; @@ -8429,10 +8427,10 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, else { idx = 0; BuildRFC6187Info(ssh, sigKeyBlock_ptr->pubKeyId, - ssh->ctx->cert[keyIdx], ssh->ctx->certSz[keyIdx], NULL, 0, - tmp, &sigKeyBlock_ptr->sz, &idx); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - tmp, sigKeyBlock_ptr->sz); + ssh->ctx->privateKey[keyIdx].cert, + ssh->ctx->privateKey[keyIdx].certSz, + NULL, 0, tmp, &sigKeyBlock_ptr->sz, &idx); + ret = HashUpdate(hash, hashId, tmp, sigKeyBlock_ptr->sz); WFREE(tmp, heap, DYNTYPE_TEMP); } #else @@ -8449,23 +8447,17 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, /* Hash in the client's requested minimum key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexMinSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's requested preferred key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexPreferredSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's requested maximum key size. */ if (ret == 0) { c32toa(ssh->handshake->dhGexMaxSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Add a pad byte if the mpint has the MSB set. */ if (ret == 0) { @@ -8475,24 +8467,18 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, if (ret == 0) { /* Hash in the length of the GEX prime group. */ c32toa(primeGroupSz + primeGroupPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the GEX prime group. */ if (ret == 0) { if (primeGroupPad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the GEX prime group. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - primeGroup, primeGroupSz); + ret = HashUpdate(hash, hashId, primeGroup, primeGroupSz); /* Add a pad byte if the mpint has the MSB set. */ if (ret == 0) { ret = CreateMpint((byte*)generator, @@ -8501,39 +8487,66 @@ static int SendKexGetSigningKey(WOLFSSH* ssh, if (ret == 0) { /* Hash in the length of the GEX generator. */ c32toa(generatorSz + generatorPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the pad byte for the GEX generator. */ if (ret == 0) { if (generatorPad) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } } /* Hash in the GEX generator. */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, - generator, generatorSz); + ret = HashUpdate(hash, hashId, generator, generatorSz); } #endif /* Hash in the size of the client's DH e-value (ECDH Q-value). */ if (ret == 0) { c32toa(ssh->handshake->eSz, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } /* Hash in the client's DH e-value (ECDH Q-value). */ if (ret == 0) - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - ssh->handshake->e, ssh->handshake->eSz); + ret = HashUpdate(hash, hashId, + ssh->handshake->e, ssh->handshake->eSz); - return (ret == 0)? WS_SUCCESS : ret; + return (ret == 0) ? WS_SUCCESS : ret; +} + + +/* We have pairs of PubKey types that use the same signature, + * i.e. ecdsa-sha2-nistp256 and x509v3-ecdsa-sha2-nistp256. */ +static INLINE byte SigTypeForId(byte id) +{ + WOLFSSH_UNUSED(id); +#ifdef WOLFSSH_CERTS + switch (id) { + #ifndef WOLFSSH_NO_SSH_RSA_SHA1 + case ID_X509V3_SSH_RSA: + id = ID_SSH_RSA; + break; + #endif + #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 + case ID_X509V3_ECDSA_SHA2_NISTP256: + id = ID_ECDSA_SHA2_NISTP256; + break; + #endif + #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384 + case ID_X509V3_ECDSA_SHA2_NISTP384: + id = ID_ECDSA_SHA2_NISTP384; + break; + #endif + #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521 + case ID_X509V3_ECDSA_SHA2_NISTP521: + id = ID_ECDSA_SHA2_NISTP521; + break; + #endif + } +#endif + + return id; } @@ -8567,7 +8580,8 @@ int SendKexDhReply(WOLFSSH* ssh) word32 idx; word32 keyIdx = 0; byte msgId = MSGID_KEXDH_REPLY; - enum wc_HashType enmhashId = WC_HASH_TYPE_NONE; + enum wc_HashType hashId = WC_HASH_TYPE_NONE; + wc_HashAlg* hash = NULL; struct wolfSSH_sigKeyBlockFull *sigKeyBlock_ptr = NULL; #ifndef WOLFSSH_SMALL_STACK byte f_s[KEX_F_SIZE]; @@ -8607,9 +8621,19 @@ int SendKexDhReply(WOLFSSH* ssh) if (ret == WS_SUCCESS) { sigKeyBlock_ptr->pubKeyId = ssh->handshake->pubKeyId; - sigKeyBlock_ptr->sigId = ssh->handshake->sigId; - sigKeyBlock_ptr->name = IdToName(ssh->handshake->sigId); - sigKeyBlock_ptr->nameSz = (word32)strlen(sigKeyBlock_ptr->name); + sigKeyBlock_ptr->pubKeyName = + IdToName(SigTypeForId(sigKeyBlock_ptr->pubKeyId)); + sigKeyBlock_ptr->pubKeyNameSz = + (word32)strlen(sigKeyBlock_ptr->pubKeyName); + sigKeyBlock_ptr->pubKeyFmtId = sigKeyBlock_ptr->pubKeyId; + if (sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_256 + || sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_512) { + sigKeyBlock_ptr->pubKeyFmtId = ID_SSH_RSA; + } + sigKeyBlock_ptr->pubKeyFmtName = + IdToName(sigKeyBlock_ptr->pubKeyFmtId); + sigKeyBlock_ptr->pubKeyFmtNameSz = + (word32)strlen(sigKeyBlock_ptr->pubKeyFmtName); switch (ssh->handshake->kexId) { #ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256 @@ -8638,12 +8662,14 @@ int SendKexDhReply(WOLFSSH* ssh) #endif } - enmhashId = (enum wc_HashType)ssh->handshake->hashId; + hash = &ssh->handshake->kexHash; + hashId = (enum wc_HashType)ssh->handshake->kexHashId; } if (ret == WS_SUCCESS) { for (keyIdx = 0; keyIdx < ssh->ctx->privateKeyCount; keyIdx++) { - if (ssh->ctx->privateKeyId[keyIdx] == ssh->handshake->pubKeyId) { + if (ssh->ctx->privateKey[keyIdx].publicKeyFmt + == sigKeyBlock_ptr->pubKeyFmtId) { break; } } @@ -8656,7 +8682,7 @@ int SendKexDhReply(WOLFSSH* ssh) * and I_S. Next add K_S, the server's public host key. K_S will * either be RSA or ECDSA public key blob. */ if (ret == WS_SUCCESS) { - ret = SendKexGetSigningKey(ssh, sigKeyBlock_ptr, enmhashId, keyIdx); + ret = SendKexGetSigningKey(ssh, sigKeyBlock_ptr, hashId, hash, keyIdx); } if (ret == WS_SUCCESS) { @@ -8925,7 +8951,7 @@ int SendKexDhReply(WOLFSSH* ssh) /* Replace the concatenated shared secrets with the hash. That * will become the new shared secret.*/ if (ret == 0) { - sharedSecretHashSz = wc_HashGetDigestSize(enmhashId); + sharedSecretHashSz = wc_HashGetDigestSize(hashId); sharedSecretHash = (byte *)WMALLOC(sharedSecretHashSz, heap, DYNTYPE_PRIVKEY); if (sharedSecretHash == NULL) { @@ -8933,7 +8959,7 @@ int SendKexDhReply(WOLFSSH* ssh) } } if (ret == 0) { - ret = wc_Hash(enmhashId, ssh->k, ssh->kSz, sharedSecretHash, + ret = wc_Hash(hashId, ssh->k, ssh->kSz, sharedSecretHash, sharedSecretHashSz); } if (ret == 0) { @@ -8961,15 +8987,14 @@ int SendKexDhReply(WOLFSSH* ssh) } if (ret == 0) { c32toa(fSz + fPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, scratchLen, - LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } if ((ret == 0) && (fPad)) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, enmhashId, scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } if (ret == 0) { - ret = HashUpdate(&ssh->handshake->hash, enmhashId, f_ptr, fSz); + ret = HashUpdate(hash, hashId, f_ptr, fSz); } /* Hash in the shared secret K. */ @@ -8982,28 +9007,30 @@ int SendKexDhReply(WOLFSSH* ssh) } if (ret == 0) { c32toa(ssh->kSz + kPad, scratchLen); - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - scratchLen, LENGTH_SZ); + ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); } if ((ret == 0) && (kPad)) { scratchLen[0] = 0; - ret = HashUpdate(&ssh->handshake->hash, - enmhashId, scratchLen, 1); + ret = HashUpdate(hash, hashId, scratchLen, 1); } if (ret == 0) { - ret = HashUpdate(&ssh->handshake->hash, enmhashId, - ssh->k, ssh->kSz); + ret = HashUpdate(hash, hashId, ssh->k, ssh->kSz); } /* Save the exchange hash value H, and session ID. */ if (ret == 0) { - ret = wc_HashFinal(&ssh->handshake->hash, - enmhashId, ssh->h); - wc_HashFree(&ssh->handshake->hash, enmhashId); - ssh->handshake->hashId = WC_HASH_TYPE_NONE; + ret = wc_HashGetDigestSize(hashId); + if (ret > 0) { + ssh->hSz = ret; + ret = 0; + } + } + if (ret == 0) { + ret = wc_HashFinal(hash, hashId, ssh->h); + wc_HashFree(hash, hashId); + ssh->handshake->kexHashId = WC_HASH_TYPE_NONE; } if (ret == 0) { - ssh->hSz = wc_HashGetDigestSize(enmhashId); if (ssh->sessionIdSz == 0) { WMEMCPY(ssh->sessionId, ssh->h, ssh->hSz); ssh->sessionIdSz = ssh->hSz; @@ -9021,7 +9048,6 @@ int SendKexDhReply(WOLFSSH* ssh) enum wc_HashType sigHashId; sigHashId = HashForId(ssh->handshake->pubKeyId); - ret = wc_HashInit(&digestHash, sigHashId); if (ret == 0) ret = HashUpdate(&digestHash, sigHashId, ssh->h, ssh->hSz); @@ -9036,8 +9062,10 @@ int SendKexDhReply(WOLFSSH* ssh) #ifdef WOLFSSH_CERTS || sigKeyBlock_ptr->pubKeyId == ID_X509V3_SSH_RSA #endif + || sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_256 + || sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_512 ) { -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 +#ifndef WOLFSSH_NO_RSA word32 encSigSz; #ifdef WOLFSSH_SMALL_STACK byte *encSig = (byte*)WMALLOC(MAX_ENCODED_SIG_SZ, heap, @@ -9073,15 +9101,15 @@ int SendKexDhReply(WOLFSSH* ssh) WFREE(encSig, heap, DYNTYPE_TEMP); #endif } -#endif +#endif /* WOLFSSH_NO_RSA */ } - else if (sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP256 || - sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP384 || - sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP521 + else if (sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP256 + || sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP384 + || sigKeyBlock_ptr->pubKeyId == ID_ECDSA_SHA2_NISTP521 #ifdef WOLFSSH_CERTS - || sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP256 || - sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP384 || - sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP521 + || sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP256 + || sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP384 + || sigKeyBlock_ptr->pubKeyId == ID_X509V3_ECDSA_SHA2_NISTP521 #endif ) { #ifndef WOLFSSH_NO_ECDSA @@ -9142,20 +9170,20 @@ int SendKexDhReply(WOLFSSH* ssh) WFREE(s_ptr, heap, DYNTYPE_BUFFER); #endif } -#endif +#endif /* WOLFSSH_NO_ECDSA */ } } } if (sigKeyBlock_ptr != NULL) { - if (sigKeyBlock_ptr->sigId == ID_SSH_RSA) { -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 + if (sigKeyBlock_ptr->pubKeyFmtId == ID_SSH_RSA) { +#ifndef WOLFSSH_NO_RSA wc_FreeRsaKey(&sigKeyBlock_ptr->sk.rsa.key); #endif } - else if (sigKeyBlock_ptr->sigId == ID_ECDSA_SHA2_NISTP256 || - sigKeyBlock_ptr->sigId == ID_ECDSA_SHA2_NISTP384 || - sigKeyBlock_ptr->sigId == ID_ECDSA_SHA2_NISTP521) { + else if (sigKeyBlock_ptr->pubKeyFmtId == ID_ECDSA_SHA2_NISTP256 + || sigKeyBlock_ptr->pubKeyFmtId == ID_ECDSA_SHA2_NISTP384 + || sigKeyBlock_ptr->pubKeyFmtId == ID_ECDSA_SHA2_NISTP521) { #ifndef WOLFSSH_NO_ECDSA wc_ecc_free(&sigKeyBlock_ptr->sk.ecc.key); #endif @@ -9167,13 +9195,13 @@ int SendKexDhReply(WOLFSSH* ssh) #ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 doKeyPadding = !useEccKyber; #endif - ret = GenerateKeys(ssh, enmhashId, doKeyPadding); + ret = GenerateKeys(ssh, hashId, doKeyPadding); } /* Get the buffer, copy the packet data, once f is laid into the buffer, * add it to the hash and then add K. */ if (ret == WS_SUCCESS) { - sigBlockSz = (LENGTH_SZ * 2) + sigKeyBlock_ptr->nameSz + sigSz; + sigBlockSz = (LENGTH_SZ * 2) + sigKeyBlock_ptr->pubKeyNameSz + sigSz; payloadSz = MSG_ID_SZ + (LENGTH_SZ * 3) + sigKeyBlock_ptr->sz + fSz + fPad + sigBlockSz; ret = PreparePacket(ssh, payloadSz); @@ -9186,31 +9214,35 @@ int SendKexDhReply(WOLFSSH* ssh) output[idx++] = msgId; /* add host public key */ - switch (sigKeyBlock_ptr->pubKeyId) { + switch (sigKeyBlock_ptr->pubKeyFmtId) { case ID_SSH_RSA: { -#ifndef WOLFSSH_NO_SSH_RSA_SHA1 +#ifndef WOLFSSH_NO_RSA /* Copy the rsaKeyBlock into the buffer. */ c32toa(sigKeyBlock_ptr->sz, output + idx); idx += LENGTH_SZ; - c32toa(sigKeyBlock_ptr->nameSz, output + idx); + c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, output + idx); idx += LENGTH_SZ; - WMEMCPY(output + idx, sigKeyBlock_ptr->name, sigKeyBlock_ptr->nameSz); - idx += sigKeyBlock_ptr->nameSz; + WMEMCPY(output + idx, + sigKeyBlock_ptr->pubKeyFmtName, + sigKeyBlock_ptr->pubKeyFmtNameSz); + idx += sigKeyBlock_ptr->pubKeyFmtNameSz; c32toa(sigKeyBlock_ptr->sk.rsa.eSz + sigKeyBlock_ptr->sk.rsa.ePad, output + idx); idx += LENGTH_SZ; if (sigKeyBlock_ptr->sk.rsa.ePad) output[idx++] = 0; - WMEMCPY(output + idx, sigKeyBlock_ptr->sk.rsa.e, sigKeyBlock_ptr->sk.rsa.eSz); + WMEMCPY(output + idx, + sigKeyBlock_ptr->sk.rsa.e, sigKeyBlock_ptr->sk.rsa.eSz); idx += sigKeyBlock_ptr->sk.rsa.eSz; c32toa(sigKeyBlock_ptr->sk.rsa.nSz + sigKeyBlock_ptr->sk.rsa.nPad, output + idx); idx += LENGTH_SZ; if (sigKeyBlock_ptr->sk.rsa.nPad) output[idx++] = 0; - WMEMCPY(output + idx, sigKeyBlock_ptr->sk.rsa.n, sigKeyBlock_ptr->sk.rsa.nSz); + WMEMCPY(output + idx, + sigKeyBlock_ptr->sk.rsa.n, sigKeyBlock_ptr->sk.rsa.nSz); idx += sigKeyBlock_ptr->sk.rsa.nSz; -#endif +#endif /* WOLFSSH_NO_RSA */ } break; @@ -9219,13 +9251,15 @@ int SendKexDhReply(WOLFSSH* ssh) case ID_ECDSA_SHA2_NISTP521: { #ifndef WOLFSSH_NO_ECDSA - /* Copy the rsaKeyBlock into the buffer. */ + /* Copy the ecdsaKeyBlock into the buffer. */ c32toa(sigKeyBlock_ptr->sz, output + idx); idx += LENGTH_SZ; - c32toa(sigKeyBlock_ptr->nameSz, output + idx); + c32toa(sigKeyBlock_ptr->pubKeyFmtNameSz, output + idx); idx += LENGTH_SZ; - WMEMCPY(output + idx, sigKeyBlock_ptr->name, sigKeyBlock_ptr->nameSz); - idx += sigKeyBlock_ptr->nameSz; + WMEMCPY(output + idx, + sigKeyBlock_ptr->pubKeyFmtName, + sigKeyBlock_ptr->pubKeyFmtNameSz); + idx += sigKeyBlock_ptr->pubKeyFmtNameSz; c32toa(sigKeyBlock_ptr->sk.ecc.primeNameSz, output + idx); idx += LENGTH_SZ; @@ -9248,8 +9282,9 @@ int SendKexDhReply(WOLFSSH* ssh) case ID_X509V3_ECDSA_SHA2_NISTP521: { ret = BuildRFC6187Info(ssh, sigKeyBlock_ptr->pubKeyId, - ssh->ctx->cert[keyIdx], ssh->ctx->certSz[keyIdx], NULL, 0, - output, &ssh->outputBuffer.bufferSz, &idx); + ssh->ctx->privateKey[keyIdx].cert, + ssh->ctx->privateKey[keyIdx].certSz, + NULL, 0, output, &ssh->outputBuffer.bufferSz, &idx); } break; #endif @@ -9257,7 +9292,7 @@ int SendKexDhReply(WOLFSSH* ssh) } if (ret == WS_SUCCESS) { - /* Copy the server's public key. F for DE, or Q_S for ECDH. */ + /* Copy the server's public key. F for DHE, or Q_S for ECDH. */ c32toa(fSz + fPad, output + idx); idx += LENGTH_SZ; if (fPad) output[idx++] = 0; @@ -9267,10 +9302,11 @@ int SendKexDhReply(WOLFSSH* ssh) /* Copy the signature of the exchange hash. */ c32toa(sigBlockSz, output + idx); idx += LENGTH_SZ; - c32toa(sigKeyBlock_ptr->nameSz, output + idx); + c32toa(sigKeyBlock_ptr->pubKeyNameSz, output + idx); idx += LENGTH_SZ; - WMEMCPY(output + idx, sigKeyBlock_ptr->name, sigKeyBlock_ptr->nameSz); - idx += sigKeyBlock_ptr->nameSz; + WMEMCPY(output + idx, + sigKeyBlock_ptr->pubKeyName, sigKeyBlock_ptr->pubKeyNameSz); + idx += sigKeyBlock_ptr->pubKeyNameSz; c32toa(sigSz, output + idx); idx += LENGTH_SZ; WMEMCPY(output + idx, sig_ptr, sigSz); @@ -10195,39 +10231,70 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh, #endif { if (ret == WS_SUCCESS) { - byte encDigest[MAX_ENCODED_SIG_SZ]; - int encDigestSz; - WMEMSET(digest, 0, sizeof(digest)); ret = wc_HashInit(&hash, hashId); if (ret == WS_SUCCESS) ret = HashUpdate(&hash, hashId, checkData, checkDataSz); if (ret == WS_SUCCESS) ret = wc_HashFinal(&hash, hashId, digest); + } - c32toa(keySig->sigSz + 7 + LENGTH_SZ * 2, output + begin); - begin += LENGTH_SZ; - c32toa(7, output + begin); - begin += LENGTH_SZ; - WMEMCPY(output + begin, "ssh-rsa", 7); - begin += 7; - c32toa(keySig->sigSz, output + begin); - begin += LENGTH_SZ; - encDigestSz = wc_EncodeSignature(encDigest, digest, digestSz, - wc_HashGetOID(hashId)); - if (encDigestSz <= 0) { - WLOG(WS_LOG_DEBUG, "SUAR: Bad Encode Sig"); - ret = WS_CRYPTO_FAILED; + if (ret == WS_SUCCESS) { + const char* names; + word32 namesSz; + byte encDigest[MAX_ENCODED_SIG_SZ]; + int encDigestSz; + + switch (keySig->keySigId) { + #ifndef WOLFSSH_NO_SSH_RSA_SHA1 + case ID_SSH_RSA: + names = cannedKeyAlgoSshRsaNames; + namesSz = cannedKeyAlgoSshRsaNamesSz; + break; + #endif + #ifndef WOLFSSH_NO_RSA_SHA2_256 + case ID_RSA_SHA2_256: + names = cannedKeyAlgoRsaSha2_256Names; + namesSz = cannedKeyAlgoRsaSha2_256NamesSz; + break; + #endif + #ifndef WOLFSSH_NO_RSA_SHA2_512 + case ID_RSA_SHA2_512: + names = cannedKeyAlgoRsaSha2_512Names; + namesSz = cannedKeyAlgoRsaSha2_512NamesSz; + break; + #endif + default: + WLOG(WS_LOG_DEBUG, "SUAR: RSA invalid algo"); + ret = WS_INVALID_ALGO_ID; } - else { - int sigSz; - WLOG(WS_LOG_INFO, "Signing hash with RSA."); - sigSz = wc_RsaSSL_Sign(encDigest, encDigestSz, - output + begin, keySig->sigSz, - &keySig->ks.rsa.key, ssh->rng); - if (sigSz <= 0 || (word32)sigSz != keySig->sigSz) { - WLOG(WS_LOG_DEBUG, "SUAR: Bad RSA Sign"); - ret = WS_RSA_E; + + if (ret == WS_SUCCESS) { + c32toa(keySig->sigSz + namesSz + LENGTH_SZ * 2, output + begin); + begin += LENGTH_SZ; + c32toa(namesSz, output + begin); + begin += LENGTH_SZ; + + WMEMCPY(output + begin, names, namesSz); + begin += namesSz; + c32toa(keySig->sigSz, output + begin); + begin += LENGTH_SZ; + encDigestSz = wc_EncodeSignature(encDigest, digest, digestSz, + wc_HashGetOID(hashId)); + if (encDigestSz <= 0) { + WLOG(WS_LOG_DEBUG, "SUAR: Bad Encode Sig"); + ret = WS_CRYPTO_FAILED; + } + else { + int sigSz; + WLOG(WS_LOG_INFO, "Signing hash with RSA."); + sigSz = wc_RsaSSL_Sign(encDigest, encDigestSz, + output + begin, keySig->sigSz, + &keySig->ks.rsa.key, ssh->rng); + if (sigSz <= 0 || (word32)sigSz != keySig->sigSz) { + WLOG(WS_LOG_DEBUG, "SUAR: Bad RSA Sign"); + ret = WS_RSA_E; + } } } @@ -11018,6 +11085,8 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, switch (keySig->keySigId) { #ifndef WOLFSSH_NO_RSA case ID_SSH_RSA: + case ID_RSA_SHA2_256: + case ID_RSA_SHA2_512: c32toa(pk->publicKeyTypeSz, output + begin); begin += LENGTH_SZ; WMEMCPY(output + begin, @@ -11126,7 +11195,7 @@ static void CleanupUserAuthRequestPublicKey(WS_KeySignature* keySig) #endif -int SendUserAuthRequest(WOLFSSH* ssh, byte authId, int addSig) +int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig) { byte* output; word32 idx; @@ -11138,6 +11207,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authId, int addSig) int ret = WS_SUCCESS; WS_UserAuthData authData; WS_KeySignature *keySig_ptr = NULL; + byte authId = ID_NONE; WOLFSSH_UNUSED(addSig); @@ -11161,26 +11231,29 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authId, int addSig) WLOG(WS_LOG_DEBUG, "SUAR: Calling the userauth callback"); WMEMSET(&authData, 0, sizeof(authData)); - authData.type = authId; + authData.type = authType; authData.username = (const byte*)ssh->userName; authData.usernameSz = ssh->userNameSz; - if (authId & WOLFSSH_USERAUTH_PASSWORD) { + if (authType & WOLFSSH_USERAUTH_PASSWORD) { ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD, &authData, ssh->userAuthCtx); if (ret != WOLFSSH_USERAUTH_SUCCESS) { WLOG(WS_LOG_DEBUG, "SUAR: Couldn't get password"); ret = WS_FATAL_ERROR; + authType &= ~WOLFSSH_USERAUTH_PASSWORD; } else { WLOG(WS_LOG_DEBUG, "SUAR: Callback successful password"); - authData.type = authId = ID_USERAUTH_PASSWORD; + authId = ID_USERAUTH_PASSWORD; + authType = WOLFSSH_USERAUTH_PASSWORD; + authData.type = authType; } } /* fall into public key case if password case was not successful */ if ((ret == WS_FATAL_ERROR || - !(authId & WOLFSSH_USERAUTH_PASSWORD)) && - (authId & WOLFSSH_USERAUTH_PUBLICKEY)) { + !(authType & WOLFSSH_USERAUTH_PASSWORD)) && + (authType & WOLFSSH_USERAUTH_PUBLICKEY)) { ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY, &authData, ssh->userAuthCtx); if (ret != WOLFSSH_USERAUTH_SUCCESS) { @@ -11189,7 +11262,8 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authId, int addSig) } else { WLOG(WS_LOG_DEBUG, "SUAR: Callback successful public key"); - authData.type = authId = ID_USERAUTH_PUBLICKEY; + authData.type = WOLFSSH_USERAUTH_PUBLICKEY; + authId = ID_USERAUTH_PUBLICKEY; } } diff --git a/tests/api.c b/tests/api.c index eaccd418..d556b9dd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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 */ diff --git a/wolfssh/internal.h b/wolfssh/internal.h index ebb3452a..39f1b0d0 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -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;