@@ -98,6 +98,35 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
9898}
9999
100100
101+ #ifdef CRL_STATIC_REVOKED_LIST
102+ /* Compare two RevokedCert entries by (serialSz, serialNumber) for sorting.
103+ * Returns < 0, 0, or > 0 like memcmp. */
104+ static int CompareRevokedCert (const RevokedCert * a , const RevokedCert * b )
105+ {
106+ if (a -> serialSz != b -> serialSz )
107+ return a -> serialSz - b -> serialSz ;
108+ return XMEMCMP (a -> serialNumber , b -> serialNumber , (size_t )a -> serialSz );
109+ }
110+
111+ /* Sort revoked cert array in-place using insertion sort. The array is bounded
112+ * by CRL_MAX_REVOKED_CERTS so O(n^2) is fine. */
113+ static void SortCRL_CertList (RevokedCert * certs , int totalCerts )
114+ {
115+ int i , j ;
116+ RevokedCert tmp ;
117+
118+ for (i = 1 ; i < totalCerts ; i ++ ) {
119+ XMEMCPY (& tmp , & certs [i ], sizeof (RevokedCert ));
120+ j = i - 1 ;
121+ while (j >= 0 && CompareRevokedCert (& certs [j ], & tmp ) > 0 ) {
122+ XMEMCPY (& certs [j + 1 ], & certs [j ], sizeof (RevokedCert ));
123+ j -- ;
124+ }
125+ XMEMCPY (& certs [j + 1 ], & tmp , sizeof (RevokedCert ));
126+ }
127+ }
128+ #endif /* CRL_STATIC_REVOKED_LIST */
129+
101130/* Initialize CRL Entry */
102131static int InitCRL_Entry (CRL_Entry * crle , DecodedCRL * dcrl , const byte * buff ,
103132 int verified , void * heap )
@@ -132,12 +161,15 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
132161#endif
133162#ifdef CRL_STATIC_REVOKED_LIST
134163 /* ParseCRL_CertList() has already cached the Revoked certs into
135- the crle->certs array */
164+ the crle->certs array. Sort it so binary search in
165+ FindRevokedSerial works correctly. */
166+ crle -> totalCerts = dcrl -> totalCerts ;
167+ SortCRL_CertList (crle -> certs , crle -> totalCerts );
136168#else
137169 crle -> certs = dcrl -> certs ; /* take ownership */
170+ crle -> totalCerts = dcrl -> totalCerts ;
138171#endif
139172 dcrl -> certs = NULL ;
140- crle -> totalCerts = dcrl -> totalCerts ;
141173 crle -> crlNumberSet = dcrl -> crlNumberSet ;
142174 if (crle -> crlNumberSet ) {
143175 XMEMCPY (crle -> crlNumber , dcrl -> crlNumber , sizeof (crle -> crlNumber ));
@@ -313,25 +345,52 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz,
313345 int ret = 0 ;
314346 byte hash [SIGNER_DIGEST_SIZE ];
315347#ifdef CRL_STATIC_REVOKED_LIST
316- /* do binary search */
317- int low , high , mid ;
348+ if (serialHash == NULL ) {
349+ /* Binary search by (serialSz, serialNumber). The array was sorted in
350+ * InitCRL_Entry by the same comparison key. */
351+ int low = 0 ;
352+ int high = totalCerts - 1 ;
318353
319- low = 0 ;
320- high = totalCerts - 1 ;
354+ while (low <= high ) {
355+ int mid = (low + high ) / 2 ;
356+ int cmp ;
321357
322- while (low <= high ) {
323- mid = (low + high ) / 2 ;
358+ /* Compare by serial size first, then by serial content. Shorter
359+ * serials sort before longer ones. */
360+ if (rc [mid ].serialSz != serialSz ) {
361+ cmp = rc [mid ].serialSz - serialSz ;
362+ }
363+ else {
364+ cmp = XMEMCMP (rc [mid ].serialNumber , serial ,
365+ (size_t )rc [mid ].serialSz );
366+ }
324367
325- if (XMEMCMP (rc [mid ].serialNumber , serial , rc -> serialSz ) < 0 ) {
326- low = mid + 1 ;
327- }
328- else if (XMEMCMP (rc [mid ].serialNumber , serial , rc -> serialSz ) > 0 ) {
329- high = mid - 1 ;
368+ if (cmp < 0 ) {
369+ low = mid + 1 ;
370+ }
371+ else if (cmp > 0 ) {
372+ high = mid - 1 ;
373+ }
374+ else {
375+ WOLFSSL_MSG ("Cert revoked" );
376+ ret = CRL_CERT_REVOKED ;
377+ break ;
378+ }
330379 }
331- else {
332- WOLFSSL_MSG ("Cert revoked" );
333- ret = CRL_CERT_REVOKED ;
334- break ;
380+ }
381+ else {
382+ /* Hash-based lookup -- linear scan required since the array is sorted
383+ * by serial number, not by hash. */
384+ int i ;
385+ for (i = 0 ; i < totalCerts ; i ++ ) {
386+ ret = CalcHashId (rc [i ].serialNumber , (word32 )rc [i ].serialSz , hash );
387+ if (ret != 0 )
388+ break ;
389+ if (XMEMCMP (hash , serialHash , SIGNER_DIGEST_SIZE ) == 0 ) {
390+ WOLFSSL_MSG ("Cert revoked" );
391+ ret = CRL_CERT_REVOKED ;
392+ break ;
393+ }
335394 }
336395 }
337396#else
0 commit comments