From 7df22ee21095ddb5e95145438eef269c125c7efd Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Feb 2016 15:51:29 -0700 Subject: [PATCH 1/7] Trusted peer certificate use --- examples/server/server.c | 6 + src/ssl.c | 309 ++++++++++++++++++++++++++++++++- wolfcrypt/src/asn.c | 78 ++++++++- wolfssl/internal.h | 21 +++ wolfssl/ssl.h | 11 ++ wolfssl/wolfcrypt/asn.h | 30 +++- wolfssl/wolfcrypt/asn_public.h | 3 +- 7 files changed, 454 insertions(+), 4 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 0bea91863..a8320733b 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -685,6 +685,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) SSL_VERIFY_FAIL_IF_NO_PEER_CERT),0); if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); + #ifdef WOLFSSL_TRUST_PEER_CERT + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, + "./certs/client-cert.pem", SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + err_sys("can't load trusted peer cert file"); + } + #endif /* WOLFSSL_TRUST_PEER_CERT */ } #endif diff --git a/src/ssl.c b/src/ssl.c index c2762ffdb..f16934157 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1705,6 +1705,14 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void) wolfSSL_CertManagerFree(cm); return NULL; } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (InitMutex(&cm->tpLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + #endif } return cm; @@ -1731,6 +1739,12 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) #endif FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); FreeMutex(&cm->caLock); + + #ifdef WOLFSSL_TRUST_PEER_CERT + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL); + FreeMutex(&cm->tpLock); + #endif + XFREE(cm, NULL, DYNAMIC_TYPE_CERT_MANAGER); } @@ -1757,6 +1771,27 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) } +#ifdef WOLFSSL_TRUST_PEER_CERT +int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers"); + + if (cm == NULL) + return BAD_FUNC_ARG; + + if (LockMutex(&cm->tpLock) != 0) + return BAD_MUTEX_E; + + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL); + + UnLockMutex(&cm->tpLock); + + + return SSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* Return bytes written to buff or < 0 for error */ int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, int buffSz, int type) @@ -2179,6 +2214,95 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) } +#ifdef WOLFSSL_TRUST_PEER_CERT +/* does trusted peer already exist on signer list */ +int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) +{ + TrustedPeerCert* tp; + int ret = 0; + word32 row = HashSigner(hash); + + if (LockMutex(&cm->tpLock) != 0) + return ret; + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = tp->subjectKeyIdHash; + #else + subjectHash = tp->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = 1; + break; + } + tp = tp->next; + } + UnLockMutex(&cm->tpLock); + + return ret; +} + + +/* return Trusted Peer if found, otherwise NULL */ +TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash) +{ + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; + TrustedPeerCert* ret = NULL; + TrustedPeerCert* tp = NULL; + word32 row; + + if (cm == NULL || hash == NULL) + return NULL; + + row = HashSigner(hash); + + if (LockMutex(&cm->tpLock) != 0) + return ret; + + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = tp->subjectKeyIdHash; + #else + subjectHash = tp->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = tp; + break; + } + tp = tp->next; + } + UnLockMutex(&cm->tpLock); + + return ret; +} + + +int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) +{ + if (tp == NULL || cert == NULL) + return BAD_FUNC_ARG; + + /* subject key id or subject hash has been compared when searching + tpTable for the cert from function GetTrustedPeer */ + + /* compare signatures */ + if (tp->sigLen == cert->sigLength) { + /* compare first four before comparing all */ + if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) { + return SSL_FAILURE; + } + } + else { + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + /* return CA if found, otherwise NULL */ Signer* GetCA(void* vp, byte* hash) { @@ -2245,6 +2369,123 @@ Signer* GetCAByName(void* vp, byte* hash) #endif +#ifdef WOLFSSL_TRUST_PEER_CERT +/* add a trusted peer cert to linked list */ +int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) +{ + int ret, row; + TrustedPeerCert* peerCert; + DecodedCert* cert = NULL; + byte* subjectHash = NULL; + + WOLFSSL_MSG("Adding a Trusted Peer Cert"); + + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) { + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + WOLFSSL_MSG(" Parsed new trusted peer cert"); + + peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), NULL, + DYNAMIC_TYPE_CERT); + if (peerCert == NULL) { + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); + +#ifndef NO_SKID + subjectHash = cert->extSubjKeyId; +#else + subjectHash = cert->subjectHash; +#endif + + #ifndef IGNORE_NAME_CONSTRAINTS + if (peerCert->permittedNames) + FreeNameSubtrees(peerCert->permittedNames, cm->heap); + if (peerCert->excludedNames) + FreeNameSubtrees(peerCert->excludedNames, cm->heap); + #endif + + if (AlreadyTrustedPeer(cm, subjectHash)) { + WOLFSSL_MSG(" Already have this CA, not adding again"); + (void)ret; + } + else { + /* add trusted peer signature */ + peerCert->sigLen = cert->sigLength; + peerCert->sig = XMALLOC(cert->sigLength, cm->heap, + DYNAMIC_TYPE_SIGNATURE); + if (peerCert->sig == NULL) { + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + FreeTrustedPeer(peerCert, cm->heap); + return MEMORY_E; + } + XMEMCPY(peerCert->sig, cert->signature, cert->sigLength); + + /* add trusted peer name */ + peerCert->nameLen = cert->subjectCNLen; + peerCert->name = cert->subjectCN; + #ifndef IGNORE_NAME_CONSTRAINTS + peerCert->permittedNames = cert->permittedNames; + peerCert->excludedNames = cert->excludedNames; + #endif + + /* add SKID when available and hash of name */ + #ifndef NO_SKID + XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(peerCert->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + peerCert->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + + #ifndef NO_SKID + row = HashSigner(peerCert->subjectKeyIdHash); + #else + row = HashSigner(peerCert->subjectNameHash); + #endif + + if (LockMutex(&cm->tpLock) == 0) { + peerCert->next = cm->tpTable[row]; + cm->tpTable[row] = peerCert; /* takes ownership */ + UnLockMutex(&cm->tpLock); + } + else { + WOLFSSL_MSG(" Trusted Peer Cert Mutex Lock failed"); + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + FreeTrustedPeer(peerCert, cm->heap); + return BAD_MUTEX_E; + } + } + + WOLFSSL_MSG(" Freeing parsed trusted peer cert"); + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG(" Freeing der trusted peer cert"); + FreeDer(der); + WOLFSSL_MSG(" OK Freeing der trusted peer cert"); + WOLFSSL_LEAVE("AddTrustedPeer", ret); + + return SSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify don't allow chain ones to be added w/o isCA extension */ @@ -2647,6 +2888,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, switch (type) { case CA_TYPE: /* same as below */ + case TRUSTED_PEER_TYPE: case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; @@ -3085,6 +3327,17 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* verify CA unless user set to no verify */ return AddCA(ctx->cm, &der, WOLFSSL_USER_CA, !ctx->verifyNone); } +#ifdef WOLFSSL_TRUST_PEER_CERT + else if (type == TRUSTED_PEER_TYPE) { + if (ctx == NULL) { + WOLFSSL_MSG("Need context for trusted peer cert load"); + XFREE(der.buffer, heap, dynamicType); + return BAD_FUNC_ARG; + } + /* add trusted peer cert */ + return AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ else if (type == CERT_TYPE) { if (ssl) { /* Make sure previous is free'd */ @@ -3817,7 +4070,8 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) ret = SSL_BAD_FILE; else { - if (type == CA_TYPE && format == SSL_FILETYPE_PEM) + if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) + && format == SSL_FILETYPE_PEM) ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); #ifdef HAVE_CRL else if (type == CRL_TYPE) @@ -3947,6 +4201,31 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, } +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Used to specify a peer cert to match when connecting + ctx : the ctx structure to load in peer cert + file: the string name of cert file + type: type of format such as PEM/DER + */ +int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); + + if (ctx == NULL || file == NULL) { + return SSL_FAILURE; + } + + if ((ret = ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL)) + == SSL_SUCCESS) { + } + + return ret; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* Verify the certificate, SSL_SUCCESS for ok, < 0 for error */ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, int format) @@ -7364,6 +7643,22 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); + if (format == SSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, + TRUSTED_PEER_TYPE, NULL); + else + return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, + NULL,NULL,0); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, long sz, int format) { @@ -7548,6 +7843,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return wolfSSL_CertManagerUnloadCAs(ctx->cm); } + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ /* old NO_FILESYSTEM end */ #endif /* !NO_CERTS */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4bb809e23..5cf59418d 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4905,6 +4905,10 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) extern "C" { #endif WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* signers, byte* hash); + WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert); +#endif /* WOLFSSL_TRUST_PEER_CERT */ #ifndef NO_SKID WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); #endif @@ -4999,7 +5003,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } #endif - if (verify && type != CA_TYPE) { + if (verify && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { Signer* ca = NULL; #ifndef NO_SKID if (cert->extAuthKeyIdSet) @@ -5011,6 +5015,36 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) #endif /* NO SKID */ WOLFSSL_MSG("About to verify certificate signature"); +#ifdef WOLFSSL_TRUST_PEER_CERT + /* check for trusted peer cert */ + { + TrustedPeerCert* tp = NULL; + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + tp = GetTrustedPeer(cm, cert->extAuthKeyId); + #else /* NO_SKID */ + tp = GetTrustedPeer(cm, cert->issuerHash); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert checking CAs"); + } else if (MatchTrustedPeer(tp, cert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + if (badDate != 0) + return badDate; + + if (criticalExt != 0) + return criticalExt; + + return 0; + } else { + WOLFSSL_MSG("No matching trusted peer cert"); + } + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + if (ca) { #ifdef HAVE_OCSP /* Need the ca's public key hash for OCSP */ @@ -5115,6 +5149,48 @@ void FreeSignerTable(Signer** table, int rows, void* heap) } } +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Free an individual trusted peer cert */ +void FreeTrustedPeer(TrustedPeerCert* tp, void* heap) +{ + if (tp == NULL) { + return; + } + + if (tp->name) { + XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + } + + if (tp->sig) { + XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE); + } + #ifndef IGNORE_NAME_CONSTRAINTS + if (tp->permittedNames) + FreeNameSubtrees(tp->permittedNames, heap); + if (tp->excludedNames) + FreeNameSubtrees(tp->excludedNames, heap); + #endif + XFREE(tp, heap, DYNAMIC_TYPE_CERT); + + (void)heap; +} + +/* Free the whole Trusted Peer linked list */ +void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap) +{ + int i; + + for (i = 0; i < rows; i++) { + TrustedPeerCert* tp = table[i]; + while (tp) { + TrustedPeerCert* next = tp->next; + FreeTrustedPeer(tp, heap); + tp = next; + } + table[i] = NULL; + } +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index fa513da99..1a5b68cf6 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1435,17 +1435,27 @@ struct WOLFSSL_CRL { #ifdef NO_ASN typedef struct Signer Signer; +#ifdef WOLFSSL_TRUST_PEER_CERT + typedef struct TrustedPeerCert TrustedPeerCert; +#endif #endif #ifndef CA_TABLE_SIZE #define CA_TABLE_SIZE 11 #endif +#ifdef WOLFSSL_TRUST_PEER_CERT + #define TP_TABLE_SIZE 11 +#endif /* wolfSSL Certificate Manager */ struct WOLFSSL_CERT_MANAGER { Signer* caTable[CA_TABLE_SIZE]; /* the CA signer table */ void* heap; /* heap helper */ +#ifdef WOLFSSL_TRUST_PEER_CERT + TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */ + wolfSSL_Mutex tpLock; /* trusted peer list lock */ +#endif WOLFSSL_CRL* crl; /* CRL checker */ WOLFSSL_OCSP* ocsp; /* OCSP checker */ #if !defined(NO_WOLFSSL_SEVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ @@ -1934,6 +1944,12 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int AddCA(WOLFSSL_CERT_MANAGER* ctx, DerBuffer* der, int type, int verify); WOLFSSL_LOCAL int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_LOCAL + int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify); + WOLFSSL_LOCAL + int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#endif #endif /* All cipher suite related info */ @@ -2820,6 +2836,11 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); const byte* plain, word32 plainSz, RsaKey* key); #endif + #ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash); + WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, + DecodedCert* cert); + #endif WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash); #ifndef NO_SKID WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 6e965561e..ea9ba0801 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -229,6 +229,9 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int) WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, const char*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int); +#endif WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *, const char *file); WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); @@ -968,6 +971,11 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, #ifndef NO_CERTS /* SSL_CTX versions */ WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); +#endif WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*, @@ -1247,6 +1255,9 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*, const unsigned char* in, long sz, int format); WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm); +#endif WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f, int format); WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index fbf4db2e4..c7a4e340b 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -365,6 +365,9 @@ struct DecodedName { typedef struct DecodedCert DecodedCert; typedef struct DecodedName DecodedName; typedef struct Signer Signer; +#ifdef WOLFSSL_TRUST_PEER_CERT +typedef struct TrustedPeerCert TrustedPeerCert; +#endif /* WOLFSSL_TRUST_PEER_CERT */ struct DecodedCert { @@ -554,6 +557,28 @@ struct Signer { }; +#ifdef WOLFSSL_TRUST_PEER_CERT +/* used for having trusted peer certs rather then CA */ +struct TrustedPeerCert { + int nameLen; + char* name; /* common name */ + #ifndef IGNORE_NAME_CONSTRAINTS + Base_entry* permittedNames; + Base_entry* excludedNames; + #endif /* IGNORE_NAME_CONSTRAINTS */ + byte subjectNameHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #ifndef NO_SKID + byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #endif + word32 sigLen; + byte* sig; + struct TrustedPeerCert* next; +}; +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* not for public consumption but may use for testing sometimes */ #ifdef WOLFSSL_TEST_CERT #define WOLFSSL_TEST_API WOLFSSL_API @@ -575,7 +600,10 @@ WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify); WOLFSSL_LOCAL Signer* MakeSigner(void*); WOLFSSL_LOCAL void FreeSigner(Signer*, void*); WOLFSSL_LOCAL void FreeSignerTable(Signer**, int, void*); - +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_LOCAL void FreeTrustedPeer(TrustedPeerCert*, void*); +WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); +#endif /* WOLFSSL_TRUST_PEER_CERT */ WOLFSSL_LOCAL int ToTraditional(byte* buffer, word32 length); WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index fee49760f..f450e4784 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -50,7 +50,8 @@ enum CertType { RSA_TYPE, PUBLICKEY_TYPE, RSA_PUBLICKEY_TYPE, - ECC_PUBLICKEY_TYPE + ECC_PUBLICKEY_TYPE, + TRUSTED_PEER_TYPE }; From 05d2cec7c10d8ba370181ae0869eda7a4674bf2f Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 29 Feb 2016 11:02:18 -0700 Subject: [PATCH 2/7] addition to api tests and refactor location of trusted peer cert check --- examples/client/client.c | 6 +++++ examples/server/server.c | 4 ++-- src/internal.c | 43 +++++++++++++++++++++++++++++++++ src/ssl.c | 10 ++------ tests/api.c | 52 ++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/asn.c | 30 ----------------------- 6 files changed, 105 insertions(+), 40 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 021e97958..417b3267f 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -977,6 +977,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); #endif /* HAVE_ECC */ +#ifdef WOLFSSL_TRUST_PEER_CERT + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, svrCert, SSL_FILETYPE_PEM)) + != SSL_SUCCESS) { + err_sys("can't load trusted peer cert file"); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ } #endif /* !NO_FILESYSTEM && !NO_CERTS */ #if !defined(NO_CERTS) diff --git a/examples/server/server.c b/examples/server/server.c index a8320733b..adfb895a3 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -686,8 +686,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #ifdef WOLFSSL_TRUST_PEER_CERT - if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, - "./certs/client-cert.pem", SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM)) + != SSL_SUCCESS) { err_sys("can't load trusted peer cert file"); } #endif /* WOLFSSL_TRUST_PEER_CERT */ diff --git a/src/internal.c b/src/internal.c index 10aa7349a..523daf1e2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4554,6 +4554,10 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_X509_STORE_CTX store[1]; #endif +#ifdef WOLFSSL_TRUST_PEER_CERT + byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */ +#endif + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); @@ -4624,6 +4628,34 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, return MEMORY_E; #endif +#ifdef WOLFSSL_TRUST_PEER_CERT + /* if using trusted peer certs check before verify chain and CA test */ + if (count > 0) { + TrustedPeerCert* tp = NULL; + + InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); + ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); + #ifndef NO_SKID + if (dCert->extAuthKeyIdSet) + tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId); + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, dCert->issuerHash); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); + } else if (MatchTrustedPeer(tp, dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + } + } + if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ +#endif /* WOLFSSL_TRUST_PEER_CERT */ + /* verify up to peer's first */ while (count > 1) { DerBuffer myCert = certs[count - 1]; @@ -4716,6 +4748,10 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, count--; } +#ifdef WOLFSSL_TRUST_PEER_CERT + } /* end of if (haveTrustPeer) -- a check for if already verified */ +#endif + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ if (count) { DerBuffer myCert = certs[0]; @@ -4723,9 +4759,16 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("Verifying Peer's cert"); +#ifdef WOLFSSL_TRUST_PEER_CERT + if (!haveTrustPeer) { /* do not parse again if previously verified */ +#endif InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, ssl->ctx->cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + } +#endif + if (ret == 0) { WOLFSSL_MSG("Verified Peer's cert"); fatal = 0; diff --git a/src/ssl.c b/src/ssl.c index f16934157..22ed142fd 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2290,7 +2290,6 @@ int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) /* compare signatures */ if (tp->sigLen == cert->sigLength) { - /* compare first four before comparing all */ if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) { return SSL_FAILURE; } @@ -2303,6 +2302,7 @@ int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) } #endif /* WOLFSSL_TRUST_PEER_CERT */ + /* return CA if found, otherwise NULL */ Signer* GetCA(void* vp, byte* hash) { @@ -4209,19 +4209,13 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, */ int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) { - int ret; - WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); if (ctx == NULL || file == NULL) { return SSL_FAILURE; } - if ((ret = ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL)) - == SSL_SUCCESS) { - } - - return ret; + return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL); } #endif /* WOLFSSL_TRUST_PEER_CERT */ diff --git a/tests/api.c b/tests/api.c index f2340c224..83b77ea3c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -211,6 +211,57 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(void) } +/* test both file and buffer versions along with unloading trusted peer certs */ +static void test_wolfSSL_CTX_trust_peer_cert(void) +{ +#if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) + WOLFSSL_CTX *ctx; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + +#if !defined(NO_FILESYSTEM) + /* invalid file */ + assert(wolfSSL_CTX_trust_peer_cert(ctx, NULL, + SSL_FILETYPE_PEM) != SSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, + SSL_FILETYPE_PEM) != SSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, + SSL_FILETYPE_ASN1) != SSL_SUCCESS); + + /* success */ + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM) + == SSL_SUCCESS); + + /* unload cert */ + assert(wolfSSL_CTX_Unload_trust_peers(NULL) != SSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(ctx) == SSL_SUCCESS); +#endif + + /* Test of loading certs from buffers */ + + /* invalid ca buffer */ + assert(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, + SSL_FILETYPE_ASN1) != SSL_SUCCESS); + + /* success */ +#ifdef USE_CERT_BUFFERS_1024 + assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, + sizeof_client_cert_der_1024, SSL_FILETYPE_ASN1) == SSL_SUCCESS); +#endif +#ifdef USE_CERT_BUFFERS_2048 + assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, + sizeof_client_cert_der_2048, SSL_FILETYPE_ASN1) == SSL_SUCCESS); +#endif + + /* unload cert */ + assert(wolfSSL_CTX_Unload_trust_peers(NULL) != SSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(ctx) == SSL_SUCCESS); + + wolfSSL_CTX_free(ctx); +#endif +} + + static void test_wolfSSL_CTX_load_verify_locations(void) { #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) @@ -1599,6 +1650,7 @@ void ApiTest(void) test_wolfSSL_CTX_use_certificate_file(); test_wolfSSL_CTX_use_PrivateKey_file(); test_wolfSSL_CTX_load_verify_locations(); + test_wolfSSL_CTX_trust_peer_cert(); test_wolfSSL_CTX_SetTmpDH_file(); test_wolfSSL_CTX_SetTmpDH_buffer(); test_server_wolfSSL_new(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5cf59418d..a8e2bcc2b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5015,36 +5015,6 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) #endif /* NO SKID */ WOLFSSL_MSG("About to verify certificate signature"); -#ifdef WOLFSSL_TRUST_PEER_CERT - /* check for trusted peer cert */ - { - TrustedPeerCert* tp = NULL; - #ifndef NO_SKID - if (cert->extAuthKeyIdSet) - tp = GetTrustedPeer(cm, cert->extAuthKeyId); - #else /* NO_SKID */ - tp = GetTrustedPeer(cm, cert->issuerHash); - #endif /* NO SKID */ - WOLFSSL_MSG("Checking for trusted peer cert"); - - if (tp == NULL) { - /* no trusted peer cert */ - WOLFSSL_MSG("No matching trusted peer cert checking CAs"); - } else if (MatchTrustedPeer(tp, cert)){ - WOLFSSL_MSG("Found matching trusted peer cert"); - if (badDate != 0) - return badDate; - - if (criticalExt != 0) - return criticalExt; - - return 0; - } else { - WOLFSSL_MSG("No matching trusted peer cert"); - } - } -#endif /* WOLFSSL_TRUST_PEER_CERT */ - if (ca) { #ifdef HAVE_OCSP /* Need the ca's public key hash for OCSP */ From d969e2ba1152767d74e8d38e876f58c396bc6ff4 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 1 Mar 2016 16:35:32 -0700 Subject: [PATCH 3/7] automated test for trusted peer certs --- configure.ac | 12 +++ examples/client/client.c | 23 ++++- examples/server/server.c | 23 ++++- scripts/include.am | 4 + scripts/trusted_peer.test | 210 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 264 insertions(+), 8 deletions(-) create mode 100755 scripts/trusted_peer.test diff --git a/configure.ac b/configure.ac index 2301a64ce..6c5041040 100644 --- a/configure.ac +++ b/configure.ac @@ -2501,6 +2501,18 @@ AM_CONDITIONAL([BUILD_MCAPI], [test "x$ENABLED_MCAPI" = "xyes"]) # check if PSK was enabled for conditionally running psk.test script AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"]) + +# check if should run the trusted peer certs test +case $C_EXTRA_FLAGS in + *WOLFSSL_TRUST_PEER_CERT*) + have_tp=yes + break;; + *) + have_tp=no ;; +esac +AM_CONDITIONAL([BUILD_TRUST_PEER_CERT], [test "x$have_tp" = "xyes"]) + + ################################################################################ # Check for build-type conflicts # ################################################################################ diff --git a/examples/client/client.c b/examples/client/client.c index 417b3267f..32e4edc07 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -380,6 +380,9 @@ static void Usage(void) #ifdef HAVE_CRL printf("-C Disable CRL\n"); #endif +#ifdef WOLFSSL_TRUST_PEER_CERT + printf("-T Path to load trusted peer cert\n"); +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -438,6 +441,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) const char* ourCert = cliCert; const char* ourKey = cliKey; +#ifdef WOLFSSL_TRUST_PEER_CERT + const char* trustCert = NULL; +#endif + #ifdef HAVE_SNI char* sniHostName = NULL; #endif @@ -490,7 +497,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:")) != -1) { + "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:")) != -1) { switch (ch) { case '?' : Usage(); @@ -532,6 +539,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + #ifdef WOLFSSL_TRUST_PEER_CERT + case 'E' : + trustCert = myoptarg; + break; + #endif + case 'm' : matchName = 1; break; @@ -978,9 +991,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); #endif /* HAVE_ECC */ #ifdef WOLFSSL_TRUST_PEER_CERT - if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, svrCert, SSL_FILETYPE_PEM)) - != SSL_SUCCESS) { - err_sys("can't load trusted peer cert file"); + if (trustCert) { + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, + SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + err_sys("can't load trusted peer cert file"); + } } #endif /* WOLFSSL_TRUST_PEER_CERT */ } diff --git a/examples/server/server.c b/examples/server/server.c index adfb895a3..d3ab1cb95 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -238,6 +238,9 @@ static void Usage(void) printf("-n Use NTRU key (needed for NTRU suites)\n"); #endif printf("-B Benchmark throughput using bytes and print stats\n"); +#ifdef WOLFSSL_TRUST_PEER_CERT + printf("-E Path to load trusted peer cert\n"); +#endif } THREAD_RETURN CYASSL_THREAD server_test(void* args) @@ -288,6 +291,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; +#ifdef WOLFSSL_TRUST_PEER_CERT + const char* trustCert = NULL; +#endif + #ifndef NO_PSK int sendPskIdentityHint = 1; #endif @@ -330,7 +337,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, "?dbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:j")) + while ((ch = mygetopt(argc, argv, "?dbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:j:E:")) != -1) { switch (ch) { case '?' : @@ -507,6 +514,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } break; + #ifdef WOLFSSL_TRUST_PEER_CERT + case 'E' : + trustCert = myoptarg; + break; + #endif + default: Usage(); exit(MY_EX_USAGE); @@ -686,9 +699,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #ifdef WOLFSSL_TRUST_PEER_CERT - if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM)) - != SSL_SUCCESS) { - err_sys("can't load trusted peer cert file"); + if (trustCert) { + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, + SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + err_sys("can't load trusted peer cert file"); + } } #endif /* WOLFSSL_TRUST_PEER_CERT */ } diff --git a/scripts/include.am b/scripts/include.am index 5866a554e..2d9ea0346 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -51,6 +51,10 @@ if BUILD_PSK dist_noinst_SCRIPTS+= scripts/psk.test endif +if BUILD_TRUST_PEER_CERT +dist_noinst_SCRIPTS+= scripts/trusted_peer.test +endif + EXTRA_DIST += scripts/testsuite.pcap # leave openssl.test as extra until non bash works EXTRA_DIST += scripts/openssl.test diff --git a/scripts/trusted_peer.test b/scripts/trusted_peer.test new file mode 100755 index 000000000..a07836280 --- /dev/null +++ b/scripts/trusted_peer.test @@ -0,0 +1,210 @@ +#!/bin/sh + +# trusted_peer.test +# copyright wolfSSL 2016 + +# getting unique port is modeled after resume.test script +# need a unique port since may run the same time as testsuite +# use server port zero hack to get one +port=0 +no_pid=-1 +server_pid=$no_pid +counter=0 +# let's use absolute path to a local dir (make distcheck may be in sub dir) +# also let's add some randomness by adding pid in case multiple 'make check's +# per source tree +ready_file=`pwd`/wolfssl_tp_ready$$ + +echo "ready file $ready_file" + +create_port() { + while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + + # get created port 0 ephemeral port + port=`cat $ready_file` + else + echo -e "NO ready file ending test..." + do_cleanup + fi +} + +remove_ready_file() { + if test -e $ready_file; then + echo -e "removing existing ready file" + rm $ready_file + fi +} + +do_cleanup() { + echo "in cleanup" + + if [ $server_pid != $no_pid ] + then + echo "killing server" + kill -9 $server_pid + fi + remove_ready_file +} + +do_trap() { + echo "got trap" + do_cleanup + exit -1 +} + +trap do_trap INT TERM + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# Test for trusted peer certs build +echo "" +echo "Checking built with trusted peer certs " +echo "-----------------------------------------------------" +port=0 +./examples/server/server -E certs/client-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -p $port +RESULT=$? +remove_ready_file +# if fail here then is a settings issue so return 0 +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTrusted peer certs not enabled \"WOLFSSL_TRUST_PEER_CERT\"" + do_cleanup + exit 0 +fi +echo "" + +# Test that using no CA's and only trusted peer certs works +echo "Server and Client relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/client-cert.pem -c certs/server-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A certs/wolfssl-website-ca.pem -E certs/server-cert.pem -c certs/client-cert.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer and Client trusted peer cert failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that using server trusted peer certs works +echo "Server relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/client-cert.pem -c certs/server-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -c certs/client-cert.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that using client trusted peer certs works +echo "Client relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -c certs/server-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -E certs/server-cert.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nClient trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that client fall through to CA works +echo "Client fall through to loaded CAs" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -E certs/server-revoked-cert.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nClient trusted peer cert fall through to CA test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that client can fail +echo "Client wrong CA and wrong trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A certs/wolfssl-website-ca.pem -E certs/server-revoked-cert.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\nClient trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that server can fail +echo "Server wrong CA and wrong trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/server-revoked-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\nServer trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that server fall through to CA works +echo "Server fall through to loaded CAs" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -E certs/server-revoked-cert.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer trusted peer cert fall through to CA test failed!" + do_cleanup + exit 1 +fi +echo "" + +echo "-----------------------------------------------------" +echo "ALL TESTS PASSED" +echo "-----------------------------------------------------" + +exit 0 + + From 267dc48d955b60b49569a8ab1c20f27fe1bbad7c Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 2 Mar 2016 15:23:50 -0700 Subject: [PATCH 4/7] fixs after testing : hash table, using NO_SKID, sanity check, and freeing dCert --- src/internal.c | 40 +++++++++++++++++++++------------------- src/ssl.c | 20 ++++++++++++++++---- tests/api.c | 2 +- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/internal.c b/src/internal.c index 523daf1e2..b5f24fcc7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4631,27 +4631,29 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_TRUST_PEER_CERT /* if using trusted peer certs check before verify chain and CA test */ if (count > 0) { - TrustedPeerCert* tp = NULL; + TrustedPeerCert* tp = NULL; - InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); - #ifndef NO_SKID - if (dCert->extAuthKeyIdSet) - tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId); - #else /* NO_SKID */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->issuerHash); - #endif /* NO SKID */ - WOLFSSL_MSG("Checking for trusted peer cert"); + InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); + ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); + #ifndef NO_SKID + if (dCert->extAuthKeyIdSet) + tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId); + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); - if (tp == NULL) { - /* no trusted peer cert */ - WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); - } else if (MatchTrustedPeer(tp, dCert)){ - WOLFSSL_MSG("Found matching trusted peer cert"); - haveTrustPeer = 1; - } else { - WOLFSSL_MSG("Trusted peer cert did not match!"); - } + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); + FreeDecodedCert(dCert); + } else if (MatchTrustedPeer(tp, dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + FreeDecodedCert(dCert); + } } if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ #endif /* WOLFSSL_TRUST_PEER_CERT */ diff --git a/src/ssl.c b/src/ssl.c index 22ed142fd..e896f0be8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2215,12 +2215,18 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) #ifdef WOLFSSL_TRUST_PEER_CERT +/* hash is the SHA digest of name, just use first 32 bits as hash */ +static INLINE word32 TrustedPeerHashSigner(const byte* hash) +{ + return MakeWordFromHash(hash) % TP_TABLE_SIZE; +} + /* does trusted peer already exist on signer list */ int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) { TrustedPeerCert* tp; int ret = 0; - word32 row = HashSigner(hash); + word32 row = TrustedPeerHashSigner(hash); if (LockMutex(&cm->tpLock) != 0) return ret; @@ -2255,7 +2261,7 @@ TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash) if (cm == NULL || hash == NULL) return NULL; - row = HashSigner(hash); + row = TrustedPeerHashSigner(hash); if (LockMutex(&cm->tpLock) != 0) return ret; @@ -2454,9 +2460,9 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) #endif #ifndef NO_SKID - row = HashSigner(peerCert->subjectKeyIdHash); + row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); #else - row = HashSigner(peerCert->subjectNameHash); + row = TrustedPeerHashSigner(peerCert->subjectNameHash); #endif if (LockMutex(&cm->tpLock) == 0) { @@ -7643,6 +7649,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long sz, int format) { WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); + + /* sanity check on arguments */ + if (sz < 0 || in == NULL || ctx == NULL) { + return BAD_FUNC_ARG; + } + if (format == SSL_FILETYPE_PEM) return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL); diff --git a/tests/api.c b/tests/api.c index 83b77ea3c..59fcb4d51 100644 --- a/tests/api.c +++ b/tests/api.c @@ -239,7 +239,7 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) /* Test of loading certs from buffers */ - /* invalid ca buffer */ + /* invalid buffer */ assert(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, SSL_FILETYPE_ASN1) != SSL_SUCCESS); From aab44eb26b016a6454911ced4d5169a43eefac6b Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 2 Mar 2016 15:43:17 -0700 Subject: [PATCH 5/7] adjest example server PSK plus flag --- examples/server/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/server/server.c b/examples/server/server.c index d3ab1cb95..d4937d280 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -337,7 +337,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, "?dbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:j:E:")) + while ((ch = mygetopt(argc, argv, "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:")) != -1) { switch (ch) { case '?' : From 112cf1f0c92a1137581532a25e70a2ec448284cc Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 2 Mar 2016 16:51:57 -0700 Subject: [PATCH 6/7] fix example client help print out --- examples/client/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/client/client.c b/examples/client/client.c index 32e4edc07..1614ecdf9 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -381,7 +381,7 @@ static void Usage(void) printf("-C Disable CRL\n"); #endif #ifdef WOLFSSL_TRUST_PEER_CERT - printf("-T Path to load trusted peer cert\n"); + printf("-E Path to load trusted peer cert\n"); #endif } From db758dc98be0a91f0a6f9688c24b5929e75b2c4e Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Sat, 12 Mar 2016 09:37:32 -0700 Subject: [PATCH 7/7] update test script, fall back to cert name search, fix der free --- configure.ac | 10 ++++ scripts/include.am | 16 +++--- scripts/trusted_peer.test | 108 ++++++++++++++++++++++++++++++++------ src/internal.c | 13 +++-- src/ssl.c | 46 +++++++++++----- wolfcrypt/src/asn.c | 4 -- wolfssl/internal.h | 10 +++- 7 files changed, 162 insertions(+), 45 deletions(-) diff --git a/configure.ac b/configure.ac index 45c859c16..c7e14cc9d 100644 --- a/configure.ac +++ b/configure.ac @@ -2510,6 +2510,7 @@ AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"]) # check if should run the trusted peer certs test +# (for now checking both C_FLAGS and C_EXTRA_FLAGS) case $C_EXTRA_FLAGS in *WOLFSSL_TRUST_PEER_CERT*) have_tp=yes @@ -2517,6 +2518,15 @@ case $C_EXTRA_FLAGS in *) have_tp=no ;; esac +if test "$have_tp" = "no"; then + case $C_FLAGS in + *WOLFSSL_TRUST_PEER_CERT*) + have_tp=yes + break;; + *) + have_tp=no ;; + esac +fi AM_CONDITIONAL([BUILD_TRUST_PEER_CERT], [test "x$have_tp" = "xyes"]) diff --git a/scripts/include.am b/scripts/include.am index 2a0c8f4a7..53087fdc5 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -39,8 +39,16 @@ endif endif +if BUILD_PSK +dist_noinst_SCRIPTS+= scripts/psk.test endif +if BUILD_TRUST_PEER_CERT +dist_noinst_SCRIPTS+= scripts/trusted_peer.test +endif + +endif # end of BUILD_EXAMPLE_SERVERS + if BUILD_EXAMPLE_CLIENTS if !BUILD_IPV6 dist_noinst_SCRIPTS+= scripts/external.test @@ -49,14 +57,6 @@ dist_noinst_SCRIPTS+= scripts/google.test endif endif -if BUILD_PSK -dist_noinst_SCRIPTS+= scripts/psk.test -endif - -if BUILD_TRUST_PEER_CERT -dist_noinst_SCRIPTS+= scripts/trusted_peer.test -endif - EXTRA_DIST += scripts/testsuite.pcap # leave openssl.test as extra until non bash works EXTRA_DIST += scripts/openssl.test diff --git a/scripts/trusted_peer.test b/scripts/trusted_peer.test index a07836280..a4faf1c18 100755 --- a/scripts/trusted_peer.test +++ b/scripts/trusted_peer.test @@ -15,6 +15,17 @@ counter=0 # per source tree ready_file=`pwd`/wolfssl_tp_ready$$ +# variables for certs so can use RSA or ECC +client_cert=`pwd`/certs/client-cert.pem +client_ca=`pwd`/certs/ca-cert.pem +client_key=`pwd`/certs/client-key.pem +ca_key=`pwd`/certs/ca-key.pem +server_cert=`pwd`/certs/server-cert.pem +server_key=`pwd`/certs/server-key.pem +combined_cert=`pwd`/certs/client_combined.pem +wrong_ca=`pwd`/certs/wolfssl-website-ca.pem +wrong_cert=`pwd`/certs/server-revoked-cert.pem + echo "ready file $ready_file" create_port() { @@ -63,15 +74,41 @@ trap do_trap INT TERM [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 +# Look for if RSA and/or ECC is enabled and adjust certs/keys +ciphers=`./examples/client/client -e` +if [[ $ciphers != *"RSA"* ]]; then + if [[ $ciphers == *"ECDSA"* ]]; then + client_cert=`pwd`/certs/client-ecc-cert.pem + client_ca=`pwd`/certs/server-ecc.pem + client_key=`pwd`/certs/ecc-client-key.pem + ca_key=`pwd`/certs/ecc-key.pem + server_cert=`pwd`/certs/server-ecc.pem + server_key=`pwd`/certs/ecc-key.pem + wrong_ca=`pwd`/certs/server-ecc-comp.pem + wrong_cert=`pwd`/certs/server-ecc-comp.pem + else + echo "configure options not set up for test. No RSA or ECC" + exit 0 + fi +fi + +# CRL list not set up for tests +crl_test=`./examples/client/client -h` +if [[ $crl_test == *"-C "* ]]; then + echo "test not set up to run with CRL" + exit 0 +fi + # Test for trusted peer certs build echo "" echo "Checking built with trusted peer certs " echo "-----------------------------------------------------" port=0 -./examples/server/server -E certs/client-cert.pem -R $ready_file -p $port & +remove_ready_file +./examples/server/server -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -p $port +./examples/client/client -A $client_ca -p $port RESULT=$? remove_ready_file # if fail here then is a settings issue so return 0 @@ -86,10 +123,10 @@ echo "" echo "Server and Client relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/client-cert.pem -c certs/server-cert.pem -R $ready_file -p $port & +./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -A certs/wolfssl-website-ca.pem -E certs/server-cert.pem -c certs/client-cert.pem -p $port +./examples/client/client -A $wrong_ca -E $server_cert -c $client_cert -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -103,10 +140,10 @@ echo "" echo "Server relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/client-cert.pem -c certs/server-cert.pem -R $ready_file -p $port & +./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -c certs/client-cert.pem -p $port +./examples/client/client -A $client_ca -c $client_cert -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -120,10 +157,10 @@ echo "" echo "Client relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -c certs/server-cert.pem -R $ready_file -p $port & +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -E certs/server-cert.pem -p $port +./examples/client/client -A $wrong_ca -E $server_cert -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -137,10 +174,10 @@ echo "" echo "Client fall through to loaded CAs" echo "-----------------------------------------------------" port=0 -./examples/server/server -R $ready_file -p $port & +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -E certs/server-revoked-cert.pem -p $port +./examples/client/client -A $client_ca -E $wrong_cert -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -151,13 +188,15 @@ fi echo "" # Test that client can fail +# check if using ECC client example is hard coded to load correct ECC ca so skip +if [[ $wrong_ca != *"ecc"* ]]; then echo "Client wrong CA and wrong trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -R $ready_file -p $port & +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -A certs/wolfssl-website-ca.pem -E certs/server-revoked-cert.pem -p $port +./examples/client/client -A $wrong_ca -E $wrong_cert -p $port RESULT=$? remove_ready_file if [ $RESULT -eq 0 ]; then @@ -166,15 +205,16 @@ if [ $RESULT -eq 0 ]; then exit 1 fi echo "" +fi # Test that server can fail echo "Server wrong CA and wrong trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A certs/wolfssl-website-ca.pem -E certs/server-revoked-cert.pem -R $ready_file -p $port & +./examples/server/server -A $wrong_ca -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -p $port +./examples/client/client -A $client_ca -p $port RESULT=$? remove_ready_file if [ $RESULT -eq 0 ]; then @@ -188,10 +228,10 @@ echo "" echo "Server fall through to loaded CAs" echo "-----------------------------------------------------" port=0 -./examples/server/server -E certs/server-revoked-cert.pem -R $ready_file -p $port & +./examples/server/server -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & server_pid=$! create_port -./examples/client/client -p $port +./examples/client/client -A $client_ca -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -201,6 +241,42 @@ if [ $RESULT -ne 0 ]; then fi echo "" +# test loading multiple certs +echo "Server loading multiple trusted peer certs" +echo "Test two success cases and one fail case" +echo "-----------------------------------------------------" +port=0 +cat $client_cert $client_ca > $combined_cert +./examples/server/server -i -A $wrong_ca -E $combined_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -c $client_cert -k $client_key -p $port +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi +./examples/client/client -A $client_ca -c $client_ca -k $ca_key -p $port +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi +./examples/client/client -A $client_ca -c $wrong_cert -k $client_key -p $port +RESULT=$? +if [ $RESULT -eq 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi + +do_cleanup # kill PID of server running in infinit loop +rm $combined_cert +remove_ready_file +echo "" + echo "-----------------------------------------------------" echo "ALL TESTS PASSED" echo "-----------------------------------------------------" diff --git a/src/internal.c b/src/internal.c index d78ab2acd..c1fa85438 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4630,10 +4630,17 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); #ifndef NO_SKID - if (dCert->extAuthKeyIdSet) - tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId); + if (dCert->extAuthKeyIdSet) { + tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId, + WC_MATCH_SKID); + } + else { /* if the cert has no SKID try to match by name */ + tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, + WC_MATCH_NAME); + } #else /* NO_SKID */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash); + tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, + WC_MATCH_NAME); #endif /* NO SKID */ WOLFSSL_MSG("Checking for trusted peer cert"); diff --git a/src/ssl.c b/src/ssl.c index 5abb4a2b5..dd2d392f0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2239,8 +2239,10 @@ int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) } -/* return Trusted Peer if found, otherwise NULL */ -TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash) +/* return Trusted Peer if found, otherwise NULL + type is what to match on + */ +TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type) { WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; TrustedPeerCert* ret = NULL; @@ -2258,11 +2260,20 @@ TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash) tp = cm->tpTable[row]; while (tp) { byte* subjectHash; - #ifndef NO_SKID - subjectHash = tp->subjectKeyIdHash; - #else - subjectHash = tp->subjectNameHash; - #endif + switch (type) { + #ifndef NO_SKID + case WC_MATCH_SKID: + subjectHash = tp->subjectKeyIdHash; + break; + #endif + case WC_MATCH_NAME: + subjectHash = tp->subjectNameHash; + break; + default: + WOLFSSL_MSG("Unknown search type"); + UnLockMutex(&cm->tpLock); + return NULL; + } if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { ret = tp; break; @@ -2366,11 +2377,12 @@ Signer* GetCAByName(void* vp, byte* hash) #ifdef WOLFSSL_TRUST_PEER_CERT /* add a trusted peer cert to linked list */ -int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) +int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) { int ret, row; TrustedPeerCert* peerCert; DecodedCert* cert = NULL; + DerBuffer* der = *pDer; byte* subjectHash = NULL; WOLFSSL_MSG("Adding a Trusted Peer Cert"); @@ -2397,7 +2409,12 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); #ifndef NO_SKID - subjectHash = cert->extSubjKeyId; + if (cert->extAuthKeyIdSet) { + subjectHash = cert->extSubjKeyId; + } + else { + subjectHash = cert->subjectHash; + } #else subjectHash = cert->subjectHash; #endif @@ -2449,7 +2466,12 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) #endif #ifndef NO_SKID - row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); + if (cert->extAuthKeyIdSet) { + row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); + } + else { + row = TrustedPeerHashSigner(peerCert->subjectNameHash); + } #else row = TrustedPeerHashSigner(peerCert->subjectNameHash); #endif @@ -2472,7 +2494,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify) FreeDecodedCert(cert); XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_MSG(" Freeing der trusted peer cert"); - FreeDer(der); + FreeDer(&der); WOLFSSL_MSG(" OK Freeing der trusted peer cert"); WOLFSSL_LEAVE("AddTrustedPeer", ret); @@ -3320,7 +3342,7 @@ static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (type == TRUSTED_PEER_TYPE) { if (ctx == NULL) { WOLFSSL_MSG("Need context for trusted peer cert load"); - XFREE(der.buffer, heap, dynamicType); + FreeDer(&der); return BAD_FUNC_ARG; } /* add trusted peer cert */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a44e93523..79ed25d03 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4900,10 +4900,6 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) extern "C" { #endif WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash); -#ifdef WOLFSSL_TRUST_PEER_CERT - WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* signers, byte* hash); - WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert); -#endif /* WOLFSSL_TRUST_PEER_CERT */ #ifndef NO_SKID WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); #endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 2524a7334..1bdad174d 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1946,7 +1946,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash); #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_LOCAL - int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer* der, int verify); + int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify); WOLFSSL_LOCAL int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash); #endif @@ -2839,7 +2839,13 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); RsaKey* key); #endif #ifdef WOLFSSL_TRUST_PEER_CERT - WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash); + + /* options for searching hash table for a matching trusted peer cert */ + #define WC_MATCH_SKID 0 + #define WC_MATCH_NAME 1 + + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, + int type); WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert); #endif