1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5  * pkix_pl_crl.c
6  *
7  * CRL Function Definitions
8  *
9  */
10 
11 #include "pkix_pl_crl.h"
12 #include "certxutl.h"
13 
14 extern PKIX_PL_HashTable *cachedCrlSigTable;
15 
16 /* --Private-CRL-Functions------------------------------------- */
17 
18 /*
19  * FUNCTION: pkix_pl_CRL_GetVersion
20  * DESCRIPTION:
21  *
22  *  Retrieves the version of the CRL pointed to by "crl" and stores it at
23  *  "pVersion". The version number will either be 0 or 1 (corresponding to
24  *  v1 or v2, respectively).
25  *
26  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
27  *
28  * PARAMETERS:
29  *  "crl"
30  *      Address of CRL whose version is to be stored. Must be non-NULL.
31  *  "pVersion"
32  *      Address where a version will be stored. Must be non-NULL.
33  *  "plContext"
34  *      Platform-specific context pointer.
35  * THREAD SAFETY:
36  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
37  * RETURNS:
38  *  Returns NULL if the function succeeds.
39  *  Returns a CRL Error if the function fails in a non-fatal way.
40  *  Returns a Fatal Error if the function fails in an unrecoverable way.
41  */
42 static PKIX_Error *
pkix_pl_CRL_GetVersion(PKIX_PL_CRL * crl,PKIX_UInt32 * pVersion,void * plContext)43 pkix_pl_CRL_GetVersion(
44         PKIX_PL_CRL *crl,
45         PKIX_UInt32 *pVersion,
46         void *plContext)
47 {
48         PKIX_UInt32 myVersion;
49 
50         PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
51         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
52 
53         PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
54 
55         myVersion = *(crl->nssSignedCrl->crl.version.data);
56 
57         if (myVersion > 1) {
58                 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
59         }
60 
61         *pVersion = myVersion;
62 
63 cleanup:
64 
65         PKIX_RETURN(CRL);
66 }
67 
68 /*
69  * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
70  */
71 PKIX_Error *
PKIX_PL_CRL_GetCRLNumber(PKIX_PL_CRL * crl,PKIX_PL_BigInt ** pCrlNumber,void * plContext)72 PKIX_PL_CRL_GetCRLNumber(
73         PKIX_PL_CRL *crl,
74         PKIX_PL_BigInt **pCrlNumber,
75         void *plContext)
76 {
77         PKIX_PL_BigInt *crlNumber = NULL;
78         SECItem nssCrlNumber;
79         PLArenaPool *arena = NULL;
80         SECStatus status;
81         PKIX_UInt32 length = 0;
82         char *bytes = NULL;
83 
84         PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
85         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
86 
87         /* Can call this function only with der been adopted. */
88         PORT_Assert(crl->adoptedDerCrl);
89 
90         if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
91 
92             PKIX_OBJECT_LOCK(crl);
93 
94             if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
95 
96                 nssCrlNumber.type = 0;
97                 nssCrlNumber.len = 0;
98                 nssCrlNumber.data = NULL;
99 
100                 PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
101                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
102                 if (arena == NULL) {
103                         PKIX_ERROR(PKIX_OUTOFMEMORY);
104                 }
105 
106                 PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
107                 status = CERT_FindCRLNumberExten
108                         (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
109 
110                 if (status == SECSuccess) {
111                         /* Get data in bytes then convert to bigint */
112                         length = nssCrlNumber.len;
113                         bytes = (char *)nssCrlNumber.data;
114 
115                         PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
116                                     (bytes, length, &crlNumber, plContext),
117                                     PKIX_BIGINTCREATEWITHBYTESFAILED);
118 
119                         /* arena release does the job
120                         PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
121                         SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
122                         */
123                         crl->crlNumber = crlNumber;
124 
125                 } else {
126 
127                         crl->crlNumberAbsent = PKIX_TRUE;
128                 }
129             }
130 
131             PKIX_OBJECT_UNLOCK(crl);
132 
133         }
134 
135         PKIX_INCREF(crl->crlNumber);
136 
137         *pCrlNumber = crl->crlNumber;
138 
139 cleanup:
140 
141         if (arena){
142                 PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
143                 PORT_FreeArena(arena, PR_FALSE);
144         }
145 
146         PKIX_RETURN(CRL);
147 }
148 
149 /*
150  * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
151  *
152  * DESCRIPTION:
153  *  Retrieves a pointer to the OID that represents the signature algorithm of
154  *  the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
155  *
156  *  AlgorithmIdentifier  ::=  SEQUENCE  {
157  *      algorithm               OBJECT IDENTIFIER,
158  *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
159  *
160  * PARAMETERS:
161  *  "crl"
162  *      Address of CRL whose signature algorithm OID is to be stored.
163  *      Must be non-NULL.
164  *  "pSignatureAlgId"
165  *      Address where object pointer will be stored. Must be non-NULL.
166  *  "plContext"
167  *      Platform-specific context pointer.
168  * THREAD SAFETY:
169  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
170  * RETURNS:
171  *  Returns NULL if the function succeeds.
172  *  Returns a CRL Error if the function fails in a non-fatal way.
173  *  Returns a Fatal Error if the function fails in an unrecoverable way.
174  */
175 static PKIX_Error *
pkix_pl_CRL_GetSignatureAlgId(PKIX_PL_CRL * crl,PKIX_PL_OID ** pSignatureAlgId,void * plContext)176 pkix_pl_CRL_GetSignatureAlgId(
177         PKIX_PL_CRL *crl,
178         PKIX_PL_OID **pSignatureAlgId,
179         void *plContext)
180 {
181         PKIX_PL_OID *signatureAlgId = NULL;
182 
183         PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
184         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
185 
186         /* if we don't have a cached copy from before, we create one */
187         if (crl->signatureAlgId == NULL){
188                 PKIX_OBJECT_LOCK(crl);
189                 if (crl->signatureAlgId == NULL){
190                     CERTCrl *nssCrl = &(crl->nssSignedCrl->crl);
191                     SECAlgorithmID *algorithm = &nssCrl->signatureAlg;
192                     SECItem *algBytes = &algorithm->algorithm;
193 
194                     if (!algBytes->data || !algBytes->len) {
195                         PKIX_ERROR(PKIX_OIDBYTESLENGTH0);
196                     }
197                     PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
198                                (algBytes, &signatureAlgId, plContext),
199                                PKIX_OIDCREATEFAILED);
200 
201                     /* save a cached copy in case it is asked for again */
202                     crl->signatureAlgId = signatureAlgId;
203                     signatureAlgId = NULL;
204                 }
205                 PKIX_OBJECT_UNLOCK(crl);
206         }
207         PKIX_INCREF(crl->signatureAlgId);
208         *pSignatureAlgId = crl->signatureAlgId;
209 cleanup:
210         PKIX_DECREF(signatureAlgId);
211         PKIX_RETURN(CRL);
212 }
213 
214 /*
215  * FUNCTION: pkix_pl_CRL_GetCRLEntries
216  * DESCRIPTION:
217  *
218  *  Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
219  *  by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
220  *  this functions stores NULL at "pCRLEntries".
221  *
222  * PARAMETERS:
223  *  "crl"
224  *      Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
225  *  "pCRLEntries"
226  *      Address where object pointer will be stored. Must be non-NULL.
227  *  "plContext"
228  *      Platform-specific context pointer.
229  * THREAD SAFETY:
230  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
231  * RETURNS:
232  *  Returns NULL if the function succeeds.
233  *  Returns a CRL Error if the function fails in a non-fatal way.
234  *  Returns a Fatal Error if the function fails in an unrecoverable way.
235  */
236 static PKIX_Error *
pkix_pl_CRL_GetCRLEntries(PKIX_PL_CRL * crl,PKIX_List ** pCrlEntries,void * plContext)237 pkix_pl_CRL_GetCRLEntries(
238         PKIX_PL_CRL *crl,
239         PKIX_List **pCrlEntries,
240         void *plContext)
241 {
242         PKIX_List *entryList = NULL;
243         CERTCrl *nssCrl = NULL;
244 
245         PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
246         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
247 
248         /* if we don't have a cached copy from before, we create one */
249         if (crl->crlEntryList == NULL) {
250 
251                 PKIX_OBJECT_LOCK(crl);
252 
253                 if (crl->crlEntryList == NULL){
254 
255                         nssCrl = &(crl->nssSignedCrl->crl);
256 
257                         PKIX_CHECK(pkix_pl_CRLEntry_Create
258                                     (nssCrl->entries, &entryList, plContext),
259                                     PKIX_CRLENTRYCREATEFAILED);
260 
261                         PKIX_CHECK(PKIX_List_SetImmutable
262                                     (entryList, plContext),
263                                     PKIX_LISTSETIMMUTABLEFAILED);
264 
265                         crl->crlEntryList = entryList;
266                 }
267 
268                 PKIX_OBJECT_UNLOCK(crl);
269 
270         }
271 
272         PKIX_INCREF(crl->crlEntryList);
273 
274         *pCrlEntries = crl->crlEntryList;
275 
276 cleanup:
277 
278         PKIX_RETURN(CRL);
279 }
280 
281 /*
282  * FUNCTION: pkix_pl_CRL_Destroy
283  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
284  */
285 static PKIX_Error *
pkix_pl_CRL_Destroy(PKIX_PL_Object * object,void * plContext)286 pkix_pl_CRL_Destroy(
287         PKIX_PL_Object *object,
288         void *plContext)
289 {
290         PKIX_PL_CRL *crl = NULL;
291 
292         PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
293         PKIX_NULLCHECK_ONE(object);
294 
295         PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
296                     PKIX_OBJECTNOTCRL);
297 
298         crl = (PKIX_PL_CRL*)object;
299 
300         PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
301         if (crl->nssSignedCrl) {
302             CERT_DestroyCrl(crl->nssSignedCrl);
303         }
304         if (crl->adoptedDerCrl) {
305             SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE);
306         }
307         crl->nssSignedCrl = NULL;
308         crl->adoptedDerCrl = NULL;
309         crl->crlNumberAbsent = PKIX_FALSE;
310 
311         PKIX_DECREF(crl->issuer);
312         PKIX_DECREF(crl->signatureAlgId);
313         PKIX_DECREF(crl->crlNumber);
314         PKIX_DECREF(crl->crlEntryList);
315         PKIX_DECREF(crl->critExtOids);
316         if (crl->derGenName) {
317             SECITEM_FreeItem(crl->derGenName, PR_TRUE);
318         }
319 
320 cleanup:
321 
322         PKIX_RETURN(CRL);
323 }
324 
325 /*
326  * FUNCTION: pkix_pl_CRL_ToString_Helper
327  * DESCRIPTION:
328  *
329  *  Helper function that creates a string representation of the CRL pointed
330  *  to by "crl" and stores it at "pString".
331  *
332  * PARAMETERS
333  *  "crl"
334  *      Address of CRL whose string representation is desired.
335  *      Must be non-NULL.
336  *  "pString"
337  *      Address where object pointer will be stored. Must be non-NULL.
338  *  "plContext"
339  *      Platform-specific context pointer.
340  * THREAD SAFETY:
341  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
342  * RETURNS:
343  *  Returns NULL if the function succeeds.
344  *  Returns a CRL Error if the function fails in a non-fatal way.
345  *  Returns a Fatal Error if the function fails in an unrecoverable way.
346  */
347 static PKIX_Error *
pkix_pl_CRL_ToString_Helper(PKIX_PL_CRL * crl,PKIX_PL_String ** pString,void * plContext)348 pkix_pl_CRL_ToString_Helper(
349         PKIX_PL_CRL *crl,
350         PKIX_PL_String **pString,
351         void *plContext)
352 {
353         char *asciiFormat = NULL;
354         PKIX_UInt32 crlVersion = 0;
355         PKIX_PL_X500Name *crlIssuer = NULL;
356         PKIX_PL_OID *nssSignatureAlgId = NULL;
357         PKIX_PL_BigInt *crlNumber = NULL;
358         PKIX_List *crlEntryList = NULL;
359         PKIX_List *critExtOIDs = NULL;
360         PKIX_PL_String *formatString = NULL;
361         PKIX_PL_String *crlIssuerString = NULL;
362         PKIX_PL_String *lastUpdateString = NULL;
363         PKIX_PL_String *nextUpdateString = NULL;
364         PKIX_PL_String *nssSignatureAlgIdString = NULL;
365         PKIX_PL_String *crlNumberString = NULL;
366         PKIX_PL_String *crlEntryListString = NULL;
367         PKIX_PL_String *critExtOIDsString = NULL;
368         PKIX_PL_String *crlString = NULL;
369 
370         PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
371         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
372 
373         asciiFormat =
374                 "[\n"
375                 "\tVersion:         v%d\n"
376                 "\tIssuer:          %s\n"
377                 "\tUpdate:   [Last: %s\n"
378                 "\t           Next: %s]\n"
379                 "\tSignatureAlgId:  %s\n"
380                 "\tCRL Number     : %s\n"
381                 "\n"
382                 "\tEntry List:      %s\n"
383                 "\n"
384                 "\tCritExtOIDs:     %s\n"
385                 "]\n";
386 
387         PKIX_CHECK(PKIX_PL_String_Create
388                     (PKIX_ESCASCII,
389                     asciiFormat,
390                     0,
391                     &formatString,
392                     plContext),
393                     PKIX_STRINGCREATEFAILED);
394 
395         /* Version */
396         PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
397                     PKIX_CRLGETVERSIONFAILED);
398 
399         /* Issuer */
400         PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
401                     PKIX_CRLGETISSUERFAILED);
402 
403         PKIX_CHECK(PKIX_PL_Object_ToString
404                     ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
405                     PKIX_X500NAMETOSTRINGFAILED);
406 
407         /* This update - No Date object created, use nss data directly */
408         PKIX_CHECK(pkix_pl_Date_ToString_Helper
409                     (&(crl->nssSignedCrl->crl.lastUpdate),
410                     &lastUpdateString,
411                     plContext),
412                     PKIX_DATETOSTRINGHELPERFAILED);
413 
414         /* Next update - No Date object created, use nss data directly */
415         PKIX_CHECK(pkix_pl_Date_ToString_Helper
416                     (&(crl->nssSignedCrl->crl.nextUpdate),
417                     &nextUpdateString,
418                     plContext),
419                     PKIX_DATETOSTRINGHELPERFAILED);
420 
421         /* Signature Algorithm Id */
422         PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
423                     (crl, &nssSignatureAlgId, plContext),
424                     PKIX_CRLGETSIGNATUREALGIDFAILED);
425 
426         PKIX_CHECK(PKIX_PL_Object_ToString
427                     ((PKIX_PL_Object *)nssSignatureAlgId,
428                     &nssSignatureAlgIdString,
429                     plContext),
430                     PKIX_OIDTOSTRINGFAILED);
431 
432         /* CRL Number */
433         PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
434                     (crl, &crlNumber, plContext),
435                     PKIX_CRLGETCRLNUMBERFAILED);
436 
437         PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
438                     PKIX_BIGINTTOSTRINGFAILED);
439 
440         /* CRL Entries */
441         PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
442                     PKIX_CRLGETCRLENTRIESFAILED);
443 
444         PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
445                     PKIX_LISTTOSTRINGFAILED);
446 
447         /* CriticalExtensionOIDs */
448         PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
449                     (crl, &critExtOIDs, plContext),
450                     PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
451 
452         PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
453                     PKIX_LISTTOSTRINGFAILED);
454 
455         PKIX_CHECK(PKIX_PL_Sprintf
456                     (&crlString,
457                     plContext,
458                     formatString,
459                     crlVersion + 1,
460                     crlIssuerString,
461                     lastUpdateString,
462                     nextUpdateString,
463                     nssSignatureAlgIdString,
464                     crlNumberString,
465                     crlEntryListString,
466                     critExtOIDsString),
467                     PKIX_SPRINTFFAILED);
468 
469         *pString = crlString;
470 
471 cleanup:
472 
473         PKIX_DECREF(crlIssuer);
474         PKIX_DECREF(nssSignatureAlgId);
475         PKIX_DECREF(crlNumber);
476         PKIX_DECREF(crlEntryList);
477         PKIX_DECREF(critExtOIDs);
478         PKIX_DECREF(crlIssuerString);
479         PKIX_DECREF(lastUpdateString);
480         PKIX_DECREF(nextUpdateString);
481         PKIX_DECREF(nssSignatureAlgIdString);
482         PKIX_DECREF(crlNumberString);
483         PKIX_DECREF(crlEntryListString);
484         PKIX_DECREF(critExtOIDsString);
485         PKIX_DECREF(formatString);
486 
487         PKIX_RETURN(CRL);
488 }
489 
490 /*
491  * FUNCTION: pkix_pl_CRL_ToString
492  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
493  */
494 static PKIX_Error *
pkix_pl_CRL_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pString,void * plContext)495 pkix_pl_CRL_ToString(
496         PKIX_PL_Object *object,
497         PKIX_PL_String **pString,
498         void *plContext)
499 {
500         PKIX_PL_String *crlString = NULL;
501         PKIX_PL_CRL *crl = NULL;
502 
503         PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
504         PKIX_NULLCHECK_TWO(object, pString);
505 
506         PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
507                     PKIX_OBJECTNOTCRL);
508 
509         crl = (PKIX_PL_CRL *) object;
510 
511         PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
512                     PKIX_CRLTOSTRINGHELPERFAILED);
513 
514         *pString = crlString;
515 
516 cleanup:
517 
518         PKIX_RETURN(CRL);
519 }
520 
521 /*
522  * FUNCTION: pkix_pl_CRL_Hashcode
523  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
524  */
525 static PKIX_Error *
pkix_pl_CRL_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)526 pkix_pl_CRL_Hashcode(
527         PKIX_PL_Object *object,
528         PKIX_UInt32 *pHashcode,
529         void *plContext)
530 {
531         PKIX_PL_CRL *crl = NULL;
532         PKIX_UInt32 certHash;
533         SECItem *crlDer = NULL;
534 
535         PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
536         PKIX_NULLCHECK_TWO(object, pHashcode);
537 
538         PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
539                     PKIX_OBJECTNOTCRL);
540 
541         crl = (PKIX_PL_CRL *)object;
542         if (crl->adoptedDerCrl) {
543             crlDer = crl->adoptedDerCrl;
544         } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) {
545             crlDer = crl->nssSignedCrl->derCrl;
546         }
547         if (!crlDer || !crlDer->data) {
548             PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
549         }
550 
551         PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len,
552                              &certHash, plContext),
553                    PKIX_ERRORINHASH);
554 
555         *pHashcode = certHash;
556 
557 cleanup:
558 
559         PKIX_RETURN(CRL);
560 }
561 
562 /*
563  * FUNCTION: pkix_pl_CRL_Equals
564  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
565  */
566 static PKIX_Error *
pkix_pl_CRL_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)567 pkix_pl_CRL_Equals(
568         PKIX_PL_Object *firstObject,
569         PKIX_PL_Object *secondObject,
570         PKIX_Boolean *pResult,
571         void *plContext)
572 {
573         PKIX_PL_CRL *firstCrl = NULL;
574         PKIX_PL_CRL *secondCrl = NULL;
575         SECItem *crlDerOne = NULL, *crlDerTwo = NULL;
576         PKIX_UInt32 secondType;
577 
578         PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
579         PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
580 
581         /* test that firstObject is a CRL */
582         PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
583                     PKIX_FIRSTOBJECTNOTCRL);
584 
585         firstCrl = (PKIX_PL_CRL *)firstObject;
586         secondCrl = (PKIX_PL_CRL *)secondObject;
587 
588         /*
589          * Since we know firstObject is a CRL, if both references are
590          * identical, they must be equal
591          */
592         if (firstCrl == secondCrl){
593                 *pResult = PKIX_TRUE;
594                 goto cleanup;
595         }
596 
597         /*
598          * If secondCrl isn't a CRL, we don't throw an error.
599          * We simply return a Boolean result of FALSE
600          */
601         *pResult = PKIX_FALSE;
602         PKIX_CHECK(PKIX_PL_Object_GetType
603                     ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
604                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
605         if (secondType != PKIX_CRL_TYPE) goto cleanup;
606 
607         if (firstCrl->adoptedDerCrl) {
608             crlDerOne = firstCrl->adoptedDerCrl;
609         } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) {
610             crlDerOne = firstCrl->nssSignedCrl->derCrl;
611         }
612 
613         if (secondCrl->adoptedDerCrl) {
614             crlDerTwo = secondCrl->adoptedDerCrl;
615         } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) {
616             crlDerTwo = secondCrl->nssSignedCrl->derCrl;
617         }
618 
619         if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) {
620             *pResult = PKIX_TRUE;
621         }
622 
623 cleanup:
624 
625         PKIX_RETURN(CRL);
626 }
627 
628 /*
629  * FUNCTION: pkix_pl_CRL_RegisterSelf
630  *
631  * DESCRIPTION:
632  *  Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
633  * THREAD SAFETY:
634  *
635  *  Not Thread Safe - for performance and complexity reasons
636  *
637  *  Since this function is only called by PKIX_PL_Initialize, which should
638  *  only be called once, it is acceptable that this function is not
639  *  thread-safe.
640  */
641 PKIX_Error *
pkix_pl_CRL_RegisterSelf(void * plContext)642 pkix_pl_CRL_RegisterSelf(void *plContext)
643 {
644         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
645         pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE];
646 
647         PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
648 
649         entry->description = "CRL";
650         entry->typeObjectSize = sizeof(PKIX_PL_CRL);
651         entry->destructor = pkix_pl_CRL_Destroy;
652         entry->equalsFunction = pkix_pl_CRL_Equals;
653         entry->hashcodeFunction = pkix_pl_CRL_Hashcode;
654         entry->toStringFunction = pkix_pl_CRL_ToString;
655         entry->duplicateFunction = pkix_duplicateImmutable;
656 
657         PKIX_RETURN(CRL);
658 }
659 
660 /*
661  * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
662  */
663 PKIX_Error *
PKIX_PL_CRL_VerifyUpdateTime(PKIX_PL_CRL * crl,PKIX_PL_Date * date,PKIX_Boolean * pResult,void * plContext)664 PKIX_PL_CRL_VerifyUpdateTime(
665         PKIX_PL_CRL *crl,
666         PKIX_PL_Date *date,
667         PKIX_Boolean *pResult,
668         void *plContext)
669 {
670         PRTime timeToCheck;
671         PRTime nextUpdate;
672         PRTime lastUpdate;
673         SECStatus status;
674         CERTCrl *nssCrl = NULL;
675         SECItem *nextUpdateDer = NULL;
676         PKIX_Boolean haveNextUpdate = PR_FALSE;
677 
678         PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
679         PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
680 
681         /* Can call this function only with der been adopted. */
682         PORT_Assert(crl->adoptedDerCrl);
683 
684         nssCrl = &(crl->nssSignedCrl->crl);
685         timeToCheck = date->nssTime;
686 
687         /* nextUpdate can be NULL. Checking before using it */
688         nextUpdateDer = &nssCrl->nextUpdate;
689         if (nextUpdateDer->data && nextUpdateDer->len) {
690                 haveNextUpdate = PR_TRUE;
691                 status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
692                 if (status != SECSuccess) {
693                         PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
694                 }
695         }
696 
697         status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
698         if (status != SECSuccess) {
699                 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
700         }
701 
702         if (!haveNextUpdate || nextUpdate < timeToCheck) {
703                 *pResult = PKIX_FALSE;
704                 goto cleanup;
705         }
706 
707         if (lastUpdate <= timeToCheck) {
708                 *pResult = PKIX_TRUE;
709         } else {
710                 *pResult = PKIX_FALSE;
711         }
712 
713 cleanup:
714 
715         PKIX_RETURN(CRL);
716 }
717 
718 /*
719  * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
720  * DESCRIPTION:
721  *
722  *  Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
723  *  and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
724  *  a PKIX_Error is returned.
725  *
726  * PARAMETERS:
727  *  "nssSignedCrl"
728  *      Address of CERTSignedCrl. Must be non-NULL.
729  *  "adoptedDerCrl"
730  *      SECItem ponter that if not NULL is indicating that memory used
731  *      for der should be adopted by crl that is about to be created.
732  *  "pCRL"
733  *      Address where object pointer will be stored. Must be non-NULL.
734  *  "plContext"
735  *      Platform-specific context pointer.
736  * THREAD SAFETY:
737  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
738  * RETURNS:
739  *  Returns NULL if the function succeeds.
740  *  Returns a CRL Error if the function fails in a non-fatal way.
741  *  Returns a Fatal Error if the function fails in an unrecoverable way.
742  */
743 PKIX_Error *
pkix_pl_CRL_CreateWithSignedCRL(CERTSignedCrl * nssSignedCrl,SECItem * adoptedDerCrl,SECItem * derGenName,PKIX_PL_CRL ** pCrl,void * plContext)744 pkix_pl_CRL_CreateWithSignedCRL(
745         CERTSignedCrl *nssSignedCrl,
746         SECItem *adoptedDerCrl,
747         SECItem *derGenName,
748         PKIX_PL_CRL **pCrl,
749         void *plContext)
750 {
751         PKIX_PL_CRL *crl = NULL;
752 
753         PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
754         PKIX_NULLCHECK_ONE(pCrl);
755 
756         /* create a PKIX_PL_CRL object */
757         PKIX_CHECK(PKIX_PL_Object_Alloc
758                     (PKIX_CRL_TYPE,
759                     sizeof (PKIX_PL_CRL),
760                     (PKIX_PL_Object **)&crl,
761                     plContext),
762                     PKIX_COULDNOTCREATECRLOBJECT);
763 
764         /* populate the nssSignedCrl field */
765         crl->nssSignedCrl = nssSignedCrl;
766         crl->adoptedDerCrl = adoptedDerCrl;
767         crl->issuer = NULL;
768         crl->signatureAlgId = NULL;
769         crl->crlNumber = NULL;
770         crl->crlNumberAbsent = PKIX_FALSE;
771         crl->crlEntryList = NULL;
772         crl->critExtOids = NULL;
773         if (derGenName) {
774             crl->derGenName =
775                 SECITEM_DupItem(derGenName);
776             if (!crl->derGenName) {
777                 PKIX_ERROR(PKIX_ALLOCERROR);
778             }
779         }
780 
781         *pCrl = crl;
782 
783 cleanup:
784 
785         if (PKIX_ERROR_RECEIVED){
786                 PKIX_DECREF(crl);
787         }
788 
789         PKIX_RETURN(CRL);
790 }
791 
792 /* --Public-CRL-Functions------------------------------------- */
793 
794 /*
795  * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
796  */
797 PKIX_Error *
PKIX_PL_CRL_Create(PKIX_PL_ByteArray * byteArray,PKIX_PL_CRL ** pCrl,void * plContext)798 PKIX_PL_CRL_Create(
799         PKIX_PL_ByteArray *byteArray,
800         PKIX_PL_CRL **pCrl,
801         void *plContext)
802 {
803         CERTSignedCrl *nssSignedCrl = NULL;
804         SECItem derItem, *derCrl = NULL;
805         PKIX_PL_CRL *crl = NULL;
806 
807         PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
808         PKIX_NULLCHECK_TWO(byteArray, pCrl);
809 
810         if (byteArray->length == 0){
811             PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
812         }
813         derItem.type = siBuffer;
814         derItem.data = byteArray->array;
815         derItem.len = byteArray->length;
816         derCrl = SECITEM_DupItem(&derItem);
817         if (!derCrl) {
818             PKIX_ERROR(PKIX_ALLOCERROR);
819         }
820         nssSignedCrl =
821             CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
822                                        CRL_DECODE_DONT_COPY_DER |
823                                        CRL_DECODE_SKIP_ENTRIES);
824         if (!nssSignedCrl) {
825             PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
826         }
827         PKIX_CHECK(
828             pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
829                                             &crl, plContext),
830             PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
831         nssSignedCrl = NULL;
832         derCrl = NULL;
833         *pCrl = crl;
834 
835 cleanup:
836         if (derCrl) {
837             SECITEM_FreeItem(derCrl, PR_TRUE);
838         }
839         if (nssSignedCrl) {
840             SEC_DestroyCrl(nssSignedCrl);
841         }
842 
843         PKIX_RETURN(CRL);
844 }
845 
846 /*
847  * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
848  */
849 PKIX_Error *
PKIX_PL_CRL_GetIssuer(PKIX_PL_CRL * crl,PKIX_PL_X500Name ** pCRLIssuer,void * plContext)850 PKIX_PL_CRL_GetIssuer(
851         PKIX_PL_CRL *crl,
852         PKIX_PL_X500Name **pCRLIssuer,
853         void *plContext)
854 {
855         PKIX_PL_String *crlString = NULL;
856         PKIX_PL_X500Name *issuer = NULL;
857         SECItem  *derIssuerName = NULL;
858         CERTName *issuerName = NULL;
859 
860         PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
861         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
862 
863         /* Can call this function only with der been adopted. */
864         PORT_Assert(crl->adoptedDerCrl);
865 
866         /* if we don't have a cached copy from before, we create one */
867         if (crl->issuer == NULL){
868 
869                 PKIX_OBJECT_LOCK(crl);
870 
871                 if (crl->issuer == NULL) {
872 
873                         issuerName = &crl->nssSignedCrl->crl.name;
874                         derIssuerName = &crl->nssSignedCrl->crl.derName;
875 
876                         PKIX_CHECK(
877                             PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
878                                                                 issuerName,
879                                                                 &issuer,
880                                                                 plContext),
881                             PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
882 
883                         /* save a cached copy in case it is asked for again */
884                         crl->issuer = issuer;
885                 }
886 
887                 PKIX_OBJECT_UNLOCK(crl);
888 
889         }
890 
891         PKIX_INCREF(crl->issuer);
892 
893         *pCRLIssuer = crl->issuer;
894 
895 cleanup:
896 
897         PKIX_DECREF(crlString);
898 
899         PKIX_RETURN(CRL);
900 }
901 
902 
903 /*
904  * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
905  * (see comments in pkix_pl_pki.h)
906  */
907 PKIX_Error *
PKIX_PL_CRL_GetCriticalExtensionOIDs(PKIX_PL_CRL * crl,PKIX_List ** pExtensions,void * plContext)908 PKIX_PL_CRL_GetCriticalExtensionOIDs(
909         PKIX_PL_CRL *crl,
910         PKIX_List **pExtensions,   /* list of PKIX_PL_OID */
911         void *plContext)
912 {
913         PKIX_List *oidsList = NULL;
914         CERTCertExtension **extensions = NULL;
915         CERTCrl *nssSignedCrl = NULL;
916 
917         PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
918         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
919 
920         /* Can call this function only with der been adopted. */
921         PORT_Assert(crl->adoptedDerCrl);
922 
923         /* if we don't have a cached copy from before, we create one */
924         if (crl->critExtOids == NULL) {
925 
926                 PKIX_OBJECT_LOCK(crl);
927 
928                 nssSignedCrl = &(crl->nssSignedCrl->crl);
929                 extensions = nssSignedCrl->extensions;
930 
931                 if (crl->critExtOids == NULL) {
932 
933                         PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
934                                     (extensions, &oidsList, plContext),
935                                     PKIX_GETCRITICALEXTENSIONOIDSFAILED);
936 
937                         crl->critExtOids = oidsList;
938                 }
939 
940                 PKIX_OBJECT_UNLOCK(crl);
941 
942         }
943 
944         /* We should return a copy of the List since this list changes */
945         PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
946                 PKIX_OBJECTDUPLICATELISTFAILED);
947 
948 cleanup:
949 
950         PKIX_RETURN(CRL);
951 }
952 
953 /*
954  * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
955  */
956 PKIX_Error *
PKIX_PL_CRL_VerifySignature(PKIX_PL_CRL * crl,PKIX_PL_PublicKey * pubKey,void * plContext)957 PKIX_PL_CRL_VerifySignature(
958         PKIX_PL_CRL *crl,
959         PKIX_PL_PublicKey *pubKey,
960         void *plContext)
961 {
962         PKIX_PL_CRL *cachedCrl = NULL;
963         PKIX_Error *verifySig = NULL;
964         PKIX_Error *cachedSig = NULL;
965         PKIX_Boolean crlEqual = PKIX_FALSE;
966         PKIX_Boolean crlInHash= PKIX_FALSE;
967         CERTSignedCrl *nssSignedCrl = NULL;
968         SECKEYPublicKey *nssPubKey = NULL;
969         CERTSignedData *tbsCrl = NULL;
970         void* wincx = NULL;
971         SECStatus status;
972 
973         PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
974         PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
975 
976         /* Can call this function only with der been adopted. */
977         PORT_Assert(crl->adoptedDerCrl);
978 
979         verifySig = PKIX_PL_HashTable_Lookup
980                 (cachedCrlSigTable,
981                 (PKIX_PL_Object *) pubKey,
982                 (PKIX_PL_Object **) &cachedCrl,
983                 plContext);
984 
985         if (cachedCrl != NULL && verifySig == NULL) {
986                 /* Cached Signature Table lookup succeed */
987                 PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
988                             PKIX_OBJECTEQUALSFAILED);
989                 if (crlEqual == PKIX_TRUE) {
990                         goto cleanup;
991                 }
992                 /* Different PubKey may hash to same value, skip add */
993                 crlInHash = PKIX_TRUE;
994         }
995 
996         nssSignedCrl = crl->nssSignedCrl;
997         tbsCrl = &nssSignedCrl->signatureWrap;
998 
999         PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
1000         nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
1001         if (!nssPubKey){
1002                 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
1003         }
1004 
1005         PKIX_CHECK(pkix_pl_NssContext_GetWincx
1006                    ((PKIX_PL_NssContext *)plContext, &wincx),
1007                    PKIX_NSSCONTEXTGETWINCXFAILED);
1008 
1009         PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
1010         status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx);
1011 
1012         if (status != SECSuccess) {
1013                 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1014                 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
1015         }
1016 
1017         if (crlInHash == PKIX_FALSE) {
1018                 cachedSig = PKIX_PL_HashTable_Add
1019                         (cachedCrlSigTable,
1020                         (PKIX_PL_Object *) pubKey,
1021                         (PKIX_PL_Object *) crl,
1022                         plContext);
1023 
1024                 if (cachedSig != NULL) {
1025                         PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
1026                 }
1027         }
1028 
1029 cleanup:
1030 
1031         if (nssPubKey){
1032                 PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
1033                 SECKEY_DestroyPublicKey(nssPubKey);
1034                 nssPubKey = NULL;
1035         }
1036 
1037         PKIX_DECREF(cachedCrl);
1038         PKIX_DECREF(verifySig);
1039         PKIX_DECREF(cachedSig);
1040 
1041         PKIX_RETURN(CRL);
1042 }
1043 
1044 PKIX_Error*
PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL * crl,SECItem ** derCrl,void * plContext)1045 PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
1046                          SECItem **derCrl,
1047                          void *plContext)
1048 {
1049     PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl");
1050     *derCrl = crl->adoptedDerCrl;
1051     crl->adoptedDerCrl = NULL;
1052 
1053     PKIX_RETURN(CRL);
1054 }
1055 
1056 PKIX_Error*
PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL * crl,SECItem * derCrl,void * plContext)1057 PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
1058                          SECItem *derCrl,
1059                          void *plContext)
1060 {
1061     PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl");
1062     if (crl->adoptedDerCrl) {
1063         PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
1064     }
1065     crl->adoptedDerCrl = derCrl;
1066 cleanup:
1067     PKIX_RETURN(CRL);
1068 }
1069