Skip to content

Commit dc89635

Browse files
authored
Merge pull request #669 from ejohnstown/certs
Certificate OK
2 parents aa84950 + 0a2a413 commit dc89635

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
@@ -4300,60 +4300,61 @@ static int ParseECCPubKey(WOLFSSH *ssh,
43004300

43014301

43024302
#ifdef WOLFSSH_CERTS
4303-
/* finds the leaf certificate and verifies it with known CA's
4303+
/* finds the leaf certificate and optionally the bounds of the cert chain,
43044304
* returns WS_SUCCESS on success */
4305-
static int ParseAndVerifyCert(WOLFSSH* ssh, byte* in, word32 inSz,
4306-
byte** leafOut, word32* leafOutSz)
4305+
static int ParseCertChain(byte* in, word32 inSz,
4306+
byte** certChain, word32* certChainSz, word32* certCount,
4307+
byte** leafOut, word32* leafOutSz)
43074308
{
43084309
int ret;
4309-
word32 l = 0, m = 0;
4310+
word32 sz = 0, idx = 0;
43104311
word32 ocspCount = 0;
4311-
word32 certCount = 0;
4312-
byte* certChain = NULL;
4313-
word32 certChainSz = 0;
4314-
word32 count;
4312+
byte* chain = NULL;
4313+
word32 chainSz = 0;
4314+
word32 count, countIdx;
43154315

43164316
/* Skip the name */
4317-
ret = GetSize(&l, in, inSz, &m);
4318-
m += l;
4317+
ret = GetSize(&sz, in, inSz, &idx);
43194318

43204319
if (ret == WS_SUCCESS) {
4320+
idx += sz;
4321+
43214322
/* Get the cert count */
4322-
ret = GetUint32(&certCount, in, inSz, &m);
4323+
ret = GetUint32(&count, in, inSz, &idx);
43234324
}
43244325

43254326
if (ret == WS_SUCCESS) {
4326-
WLOG(WS_LOG_INFO, "Peer sent certificate count of %d", certCount);
4327-
certChain = in + m;
4328-
4329-
for (count = certCount; count > 0; count--) {
4330-
word32 certSz = 0;
4327+
WLOG(WS_LOG_INFO, "Peer sent certificate count of %d", count);
4328+
chain = in + idx;
43314329

4332-
ret = GetSize(&certSz, in, inSz, &m);
4330+
for (countIdx = count; countIdx > 0; countIdx--) {
4331+
ret = GetSize(&sz, in, inSz, &idx);
43334332
if (ret != WS_SUCCESS) {
43344333
break;
43354334
}
4336-
WLOG(WS_LOG_INFO, "Adding certificate size %u", certSz);
4335+
WLOG(WS_LOG_INFO, "Adding certificate size %u", sz);
43374336

43384337
/* store leaf cert size to present to user callback */
4339-
if (count == certCount && leafOut != NULL) {
4340-
*leafOutSz = certSz;
4341-
*leafOut = in + m;
4338+
if (countIdx == count) {
4339+
if (leafOut != NULL && leafOutSz != NULL) {
4340+
*leafOutSz = sz;
4341+
*leafOut = in + idx;
4342+
}
43424343
}
4343-
certChainSz += certSz + UINT32_SZ;
4344-
m += certSz;
4344+
chainSz += sz + UINT32_SZ;
4345+
idx += sz;
43454346
}
43464347

43474348
/* get OCSP count */
43484349
if (ret == WS_SUCCESS) {
4349-
ret = GetUint32(&ocspCount, in, inSz, &m);
4350+
ret = GetUint32(&ocspCount, in, inSz, &idx);
43504351
}
43514352

43524353
if (ret == WS_SUCCESS) {
43534354
WLOG(WS_LOG_INFO, "Peer sent OCSP count of %u", ocspCount);
43544355

43554356
/* RFC 6187 section 2.1 OCSP count must not exceed cert count */
4356-
if (ocspCount > certCount) {
4357+
if (ocspCount > count) {
43574358
WLOG(WS_LOG_ERROR, "Error more OCSP then Certs");
43584359
ret = WS_FATAL_ERROR;
43594360
}
@@ -4367,7 +4368,36 @@ static int ParseAndVerifyCert(WOLFSSH* ssh, byte* in, word32 inSz,
43674368
}
43684369
}
43694370

4370-
/* verify the certificate chain */
4371+
if (ret == WS_SUCCESS) {
4372+
if (certChain != NULL && certChainSz != NULL && certCount != NULL) {
4373+
*certChain = chain;
4374+
*certChainSz = chainSz;
4375+
*certCount = count;
4376+
}
4377+
}
4378+
4379+
return ret;
4380+
}
4381+
4382+
4383+
static int ParseLeafCert(byte* in, word32 inSz,
4384+
byte** leafOut, word32* leafOutSz)
4385+
{
4386+
return ParseCertChain(in, inSz, NULL, NULL, NULL, leafOut, leafOutSz);
4387+
}
4388+
4389+
4390+
static int ParseCertChainVerify(WOLFSSH* ssh, byte* in, word32 inSz,
4391+
byte** leafOut, word32* leafOutSz)
4392+
{
4393+
byte *certChain = NULL;
4394+
word32 certChainSz = 0, certCount = 0;
4395+
int ret;
4396+
4397+
ret = ParseCertChain(in, inSz,
4398+
&certChain, &certChainSz, &certCount,
4399+
leafOut, leafOutSz);
4400+
43714401
if (ret == WS_SUCCESS) {
43724402
ret = wolfSSH_CERTMAN_VerifyCerts_buffer(ssh->ctx->certMan,
43734403
certChain, certChainSz, certCount);
@@ -4388,7 +4418,7 @@ static int ParsePubKeyCert(WOLFSSH* ssh, byte* in, word32 inSz, byte** out,
43884418
byte* leaf = NULL;
43894419
word32 leafSz = 0;
43904420

4391-
ret = ParseAndVerifyCert(ssh, in, inSz, &leaf, &leafSz);
4421+
ret = ParseCertChainVerify(ssh, in, inSz, &leaf, &leafSz);
43924422
if (ret == WS_SUCCESS) {
43934423
int error = 0;
43944424
struct DecodedCert dCert;
@@ -6549,22 +6579,29 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
65496579

65506580
#ifdef WOLFSSH_CERTS
65516581
if (ret == WS_SUCCESS && !authFailure) {
6552-
if (pkTypeId == ID_X509V3_SSH_RSA ||
6553-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256 ||
6554-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384 ||
6555-
pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
6556-
byte *cert = NULL;
6582+
if (pkTypeId == ID_X509V3_SSH_RSA
6583+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP256
6584+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP384
6585+
|| pkTypeId == ID_X509V3_ECDSA_SHA2_NISTP521) {
6586+
byte *cert = NULL;
65576587
word32 certSz = 0;
65586588

6559-
ret = ParseAndVerifyCert(ssh, (byte*)pubKeyBlob, pubKeyBlobSz,
6560-
&cert, &certSz);
6589+
if (hasSig) {
6590+
ret = ParseCertChainVerify(ssh,
6591+
(byte*)pubKeyBlob, pubKeyBlobSz, &cert, &certSz);
6592+
}
6593+
else {
6594+
ret = ParseLeafCert((byte*)pubKeyBlob, pubKeyBlobSz,
6595+
&cert, &certSz);
6596+
}
65616597
if (ret == WS_SUCCESS) {
65626598
authData->sf.publicKey.publicKey = cert;
65636599
authData->sf.publicKey.publicKeySz = certSz;
65646600
authData->sf.publicKey.isCert = 1;
65656601
}
65666602
else {
6567-
WLOG(WS_LOG_DEBUG, "DUARPK: client cert not verified");
6603+
WLOG(WS_LOG_DEBUG, "DUARPK: cannot parse client cert chain");
6604+
ret = WS_SUCCESS;
65686605
authFailure = 1;
65696606
}
65706607
}
@@ -6757,13 +6794,11 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
67576794
}
67586795
}
67596796

6760-
if (ret == WS_SUCCESS) {
6761-
if (authFailure) {
6762-
ret = SendUserAuthFailure(ssh, 0);
6763-
}
6764-
else if (partialSuccess && hasSig) {
6765-
ret = SendUserAuthFailure(ssh, 1);
6766-
}
6797+
if (authFailure) {
6798+
ret = SendUserAuthFailure(ssh, 0);
6799+
}
6800+
else if (partialSuccess && hasSig) {
6801+
ret = SendUserAuthFailure(ssh, 1);
67676802
}
67686803

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

0 commit comments

Comments
 (0)