diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index bd73f6ad1..9b33c282d 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2801,6 +2801,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } +/* Create and init an new signer */ Signer* MakeSigner(void* heap) { Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap, @@ -2816,21 +2817,34 @@ Signer* MakeSigner(void* heap) } -void FreeSigners(Signer* signer, void* heap) +/* Free an individual signer */ +void FreeSigner(Signer* signer, void* heap) { - while (signer) { - Signer* next = signer->next; + XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); - XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); - XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); - - signer = next; - } (void)heap; } +/* Free the whole singer table with number of rows */ +void FreeSignerTable(Signer** table, int rows, void* heap) +{ + int i; + + for (i = 0; i < rows; i++) { + Signer* signer = table[i]; + while (signer) { + Signer* next = signer->next; + FreeSigner(signer, heap); + signer = next; + } + table[i] = NULL; + } +} + + #if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) static int SetMyVersion(word32 version, byte* output, int header) diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 4c25ebe0f..c5654276c 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -315,7 +315,8 @@ CYASSL_LOCAL word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); CYASSL_LOCAL Signer* MakeSigner(void*); -CYASSL_LOCAL void FreeSigners(Signer*, void*); +CYASSL_LOCAL void FreeSigner(Signer*, void*); +CYASSL_LOCAL void FreeSignerTable(Signer**, int, void*); CYASSL_LOCAL int ToTraditional(byte* buffer, word32 length); diff --git a/cyassl/internal.h b/cyassl/internal.h index aae92855b..c2a7a8adc 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1056,9 +1056,13 @@ struct CYASSL_CRL { #endif +#ifndef CA_TABLE_SIZE + #define CA_TABLE_SIZE 11 +#endif + /* CyaSSL Certificate Manager */ struct CYASSL_CERT_MANAGER { - Signer* caList; /* the CA signer list */ + Signer* caTable[CA_TABLE_SIZE]; /* the CA signer table */ CyaSSL_Mutex caLock; /* CA list lock */ CallbackCACache caCacheCallback; /* CA cache addition callback */ void* heap; /* heap helper */ diff --git a/src/ssl.c b/src/ssl.c index 2bb4e860c..c8aadc6e8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -664,7 +664,10 @@ CYASSL_CERT_MANAGER* CyaSSL_CertManagerNew(void) cm = (CYASSL_CERT_MANAGER*) XMALLOC(sizeof(CYASSL_CERT_MANAGER), 0, DYNAMIC_TYPE_CERT_MANAGER); if (cm) { - cm->caList = NULL; + int i; + + for (i = 0; i < CA_TABLE_SIZE; i++) + cm->caTable[i] = NULL; cm->heap = NULL; cm->caCacheCallback = NULL; cm->crl = NULL; @@ -692,7 +695,7 @@ void CyaSSL_CertManagerFree(CYASSL_CERT_MANAGER* cm) if (cm->crl) FreeCRL(cm->crl, 1); #endif - FreeSigners(cm->caList, NULL); + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); FreeMutex(&cm->caLock); XFREE(cm, NULL, DYNAMIC_TYPE_CERT_MANAGER); } @@ -703,8 +706,6 @@ void CyaSSL_CertManagerFree(CYASSL_CERT_MANAGER* cm) /* Unload the CA signer list */ int CyaSSL_CertManagerUnloadCAs(CYASSL_CERT_MANAGER* cm) { - Signer* signers; - CYASSL_ENTER("CyaSSL_CertManagerUnloadCAs"); if (cm == NULL) @@ -713,12 +714,10 @@ int CyaSSL_CertManagerUnloadCAs(CYASSL_CERT_MANAGER* cm) if (LockMutex(&cm->caLock) != 0) return BAD_MUTEX_ERROR; - signers = cm->caList; - cm->caList = NULL; + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); UnLockMutex(&cm->caLock); - FreeSigners(signers, NULL); return SSL_SUCCESS; } @@ -846,19 +845,40 @@ int CyaSSL_SetVersion(CYASSL* ssl, int version) return SSL_SUCCESS; } -#endif +#endif /* !leanpsk */ + + +#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE) + +/* Make a work from the front of random hash */ +static INLINE word32 MakeWordFromHash(const byte* hashID) +{ + return (hashID[0] << 24) | (hashID[1] << 16) | (hashID[2] << 8) | + hashID[3]; +} + +#endif /* !NO_CERTS || !NO_SESSION_CACHE */ + #ifndef NO_CERTS +/* hash is the SHA digest of name, just use first 32 bits as hash */ +static INLINE word32 HashSigner(const byte* hash) +{ + return MakeWordFromHash(hash) % CA_TABLE_SIZE; +} + + /* does CA already exist on signer list */ int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; + word32 row = HashSigner(hash); if (LockMutex(&cm->caLock) != 0) return ret; - signers = cm->caList; + signers = cm->caTable[row]; while (signers) { if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { ret = 1; @@ -878,15 +898,15 @@ Signer* GetCA(void* vp, byte* hash) CYASSL_CERT_MANAGER* cm = (CYASSL_CERT_MANAGER*)vp; Signer* ret = NULL; Signer* signers; + word32 row = HashSigner(hash); if (cm == NULL) return NULL; - if (LockMutex(&cm->caLock) != 0) return ret; - signers = cm->caList; + signers = cm->caTable[row]; while (signers) { if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { ret = signers; @@ -908,6 +928,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) int ret; DecodedCert cert; Signer* signer = 0; + word32 row; CYASSL_MSG("Adding a CA"); InitDecodedCert(&cert, der.buffer, der.length, cm->heap); @@ -938,9 +959,11 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) cert.publicKey = 0; /* don't free here */ cert.subjectCN = 0; + row = HashSigner(signer->hash); + if (LockMutex(&cm->caLock) == 0) { - signer->next = cm->caList; - cm->caList = signer; /* takes ownership */ + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; /* takes ownership */ UnLockMutex(&cm->caLock); if (cm->caCacheCallback) cm->caCacheCallback(der.buffer, (int)der.length, type); @@ -948,7 +971,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) else { CYASSL_MSG(" CA Mutex Lock failed"); ret = BAD_MUTEX_ERROR; - FreeSigners(signer, cm->heap); + FreeSigner(signer, cm->heap); } } } @@ -3330,14 +3353,6 @@ int CyaSSL_Cleanup(void) #ifndef NO_SESSION_CACHE -/* Make a work from the front of random hash */ -static INLINE word32 MakeWordFromHash(const byte* hashID) -{ - return (hashID[0] << 24) | (hashID[1] << 16) | (hashID[2] << 8) | - hashID[3]; -} - - #ifndef NO_MD5 /* some session IDs aren't random afterall, let's make them random */