Skip to content

Commit 0a2a413

Browse files
committed
Certificate OK
1. Split ParseAndVerifyCert() into ParseCertChainVerify() and ParseCert() with a common ParseCertChain() function. 2. When the server is checking the user's certificate, don't do the verify step. Verify when the user's client sends a signature. The server needs to tell the client the cert is OK as a cert. Make the client do a PK sign. 3. If the certificate check fails, we still need to be able to send the failure message to the peer. Set the `ret` value back to `WS_SUCCESS`. All other auth actions are gated on the `authFailed`. 4. Whitespace. (ZD 17555)
1 parent 902cff3 commit 0a2a413

1 file changed

Lines changed: 77 additions & 42 deletions

File tree

src/internal.c

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4204,60 +4204,61 @@ static int ParseECCPubKey(WOLFSSH *ssh,
42044204

42054205

42064206
#ifdef WOLFSSH_CERTS
4207-
/* finds the leaf certificate and verifies it with known CA's
4207+
/* finds the leaf certificate and optionally the bounds of the cert chain,
42084208
* returns WS_SUCCESS on success */
4209-
static int ParseAndVerifyCert(WOLFSSH* ssh, byte* in, word32 inSz,
4210-
byte** leafOut, word32* leafOutSz)
4209+
static int ParseCertChain(byte* in, word32 inSz,
4210+
byte** certChain, word32* certChainSz, word32* certCount,
4211+
byte** leafOut, word32* leafOutSz)
42114212
{
42124213
int ret;
4213-
word32 l = 0, m = 0;
4214+
word32 sz = 0, idx = 0;
42144215
word32 ocspCount = 0;
4215-
word32 certCount = 0;
4216-
byte* certChain = NULL;
4217-
word32 certChainSz = 0;
4218-
word32 count;
4216+
byte* chain = NULL;
4217+
word32 chainSz = 0;
4218+
word32 count, countIdx;
42194219

42204220
/* Skip the name */
4221-
ret = GetSize(&l, in, inSz, &m);
4222-
m += l;
4221+
ret = GetSize(&sz, in, inSz, &idx);
42234222

42244223
if (ret == WS_SUCCESS) {
4224+
idx += sz;
4225+
42254226
/* Get the cert count */
4226-
ret = GetUint32(&certCount, in, inSz, &m);
4227+
ret = GetUint32(&count, in, inSz, &idx);
42274228
}
42284229

42294230
if (ret == WS_SUCCESS) {
4230-
WLOG(WS_LOG_INFO, "Peer sent certificate count of %d", certCount);
4231-
certChain = in + m;
4232-
4233-
for (count = certCount; count > 0; count--) {
4234-
word32 certSz = 0;
4231+
WLOG(WS_LOG_INFO, "Peer sent certificate count of %d", count);
4232+
chain = in + idx;
42354233

4236-
ret = GetSize(&certSz, in, inSz, &m);
4234+
for (countIdx = count; countIdx > 0; countIdx--) {
4235+
ret = GetSize(&sz, in, inSz, &idx);
42374236
if (ret != WS_SUCCESS) {
42384237
break;
42394238
}
4240-
WLOG(WS_LOG_INFO, "Adding certificate size %u", certSz);
4239+
WLOG(WS_LOG_INFO, "Adding certificate size %u", sz);
42414240

42424241
/* store leaf cert size to present to user callback */
4243-
if (count == certCount && leafOut != NULL) {
4244-
*leafOutSz = certSz;
4245-
*leafOut = in + m;
4242+
if (countIdx == count) {
4243+
if (leafOut != NULL && leafOutSz != NULL) {
4244+
*leafOutSz = sz;
4245+
*leafOut = in + idx;
4246+
}
42464247
}
4247-
certChainSz += certSz + UINT32_SZ;
4248-
m += certSz;
4248+
chainSz += sz + UINT32_SZ;
4249+
idx += sz;
42494250
}
42504251

42514252
/* get OCSP count */
42524253
if (ret == WS_SUCCESS) {
4253-
ret = GetUint32(&ocspCount, in, inSz, &m);
4254+
ret = GetUint32(&ocspCount, in, inSz, &idx);
42544255
}
42554256

42564257
if (ret == WS_SUCCESS) {
42574258
WLOG(WS_LOG_INFO, "Peer sent OCSP count of %u", ocspCount);
42584259

42594260
/* RFC 6187 section 2.1 OCSP count must not exceed cert count */
4260-
if (ocspCount > certCount) {
4261+
if (ocspCount > count) {
42614262
WLOG(WS_LOG_ERROR, "Error more OCSP then Certs");
42624263
ret = WS_FATAL_ERROR;
42634264
}
@@ -4271,7 +4272,36 @@ static int ParseAndVerifyCert(WOLFSSH* ssh, byte* in, word32 inSz,
42714272
}
42724273
}
42734274

4274-
/* verify the certificate chain */
4275+
if (ret == WS_SUCCESS) {
4276+
if (certChain != NULL && certChainSz != NULL && certCount != NULL) {
4277+
*certChain = chain;
4278+
*certChainSz = chainSz;
4279+
*certCount = count;
4280+
}
4281+
}
4282+
4283+
return ret;
4284+
}
4285+
4286+
4287+
static int ParseLeafCert(byte* in, word32 inSz,
4288+
byte** leafOut, word32* leafOutSz)
4289+
{
4290+
return ParseCertChain(in, inSz, NULL, NULL, NULL, leafOut, leafOutSz);
4291+
}
4292+
4293+
4294+
static int ParseCertChainVerify(WOLFSSH* ssh, byte* in, word32 inSz,
4295+
byte** leafOut, word32* leafOutSz)
4296+
{
4297+
byte *certChain = NULL;
4298+
word32 certChainSz = 0, certCount = 0;
4299+
int ret;
4300+
4301+
ret = ParseCertChain(in, inSz,
4302+
&certChain, &certChainSz, &certCount,
4303+
leafOut, leafOutSz);
4304+
42754305
if (ret == WS_SUCCESS) {
42764306
ret = wolfSSH_CERTMAN_VerifyCerts_buffer(ssh->ctx->certMan,
42774307
certChain, certChainSz, certCount);
@@ -4292,7 +4322,7 @@ static int ParsePubKeyCert(WOLFSSH* ssh, byte* in, word32 inSz, byte** out,
42924322
byte* leaf = NULL;
42934323
word32 leafSz = 0;
42944324

4295-
ret = ParseAndVerifyCert(ssh, in, inSz, &leaf, &leafSz);
4325+
ret = ParseCertChainVerify(ssh, in, inSz, &leaf, &leafSz);
42964326
if (ret == WS_SUCCESS) {
42974327
int error = 0;
42984328
struct DecodedCert dCert;
@@ -6453,22 +6483,29 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
64536483

64546484
#ifdef WOLFSSH_CERTS
64556485
if (ret == WS_SUCCESS && !authFailure) {
6456-
if (pkTypeId == ID_X509V3_SSH_RSA ||
6457-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256 ||
6458-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384 ||
6459-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
6460-
byte *cert = NULL;
6486+
if (pkTypeId == ID_X509V3_SSH_RSA
6487+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256
6488+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384
6489+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
6490+
byte *cert = NULL;
64616491
word32 certSz = 0;
64626492

6463-
ret = ParseAndVerifyCert(ssh, (byte*)pubKeyBlob, pubKeyBlobSz,
6464-
&cert, &certSz);
6493+
if (hasSig) {
6494+
ret = ParseCertChainVerify(ssh,
6495+
(byte*)pubKeyBlob, pubKeyBlobSz, &cert, &certSz);
6496+
}
6497+
else {
6498+
ret = ParseLeafCert((byte*)pubKeyBlob, pubKeyBlobSz,
6499+
&cert, &certSz);
6500+
}
64656501
if (ret == WS_SUCCESS) {
64666502
authData->sf.publicKey.publicKey = cert;
64676503
authData->sf.publicKey.publicKeySz = certSz;
64686504
authData->sf.publicKey.isCert = 1;
64696505
}
64706506
else {
6471-
WLOG(WS_LOG_DEBUG, "DUARPK: client cert not verified");
6507+
WLOG(WS_LOG_DEBUG, "DUARPK: cannot parse client cert chain");
6508+
ret = WS_SUCCESS;
64726509
authFailure = 1;
64736510
}
64746511
}
@@ -6661,13 +6698,11 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
66616698
}
66626699
}
66636700

6664-
if (ret == WS_SUCCESS) {
6665-
if (authFailure) {
6666-
ret = SendUserAuthFailure(ssh, 0);
6667-
}
6668-
else if (partialSuccess && hasSig) {
6669-
ret = SendUserAuthFailure(ssh, 1);
6670-
}
6701+
if (authFailure) {
6702+
ret = SendUserAuthFailure(ssh, 0);
6703+
}
6704+
else if (partialSuccess && hasSig) {
6705+
ret = SendUserAuthFailure(ssh, 1);
66716706
}
66726707

66736708
WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPublicKey(), ret = %d", ret);

0 commit comments

Comments
 (0)