1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the PKIX-C library.
16
* The Initial Developer of the Original Code is
17
* Sun Microsystems, Inc.
18
* Portions created by the Initial Developer are
19
* Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22
* Sun Microsystems, Inc.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
38
* pkix_targetcertchecker.c
40
* Functions for target cert validation
45
#include "pkix_targetcertchecker.h"
47
/* --Private-TargetCertCheckerState-Functions------------------------------- */
50
* FUNCTION: pkix_TargetCertCheckerState_Destroy
51
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
54
pkix_TargetCertCheckerState_Destroy(
55
PKIX_PL_Object *object,
58
pkix_TargetCertCheckerState *state = NULL;
60
PKIX_ENTER(TARGETCERTCHECKERSTATE,
61
"pkix_TargetCertCheckerState_Destroy");
62
PKIX_NULLCHECK_ONE(object);
64
/* Check that this object is a target cert checker state */
65
PKIX_CHECK(pkix_CheckType
66
(object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
67
PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
69
state = (pkix_TargetCertCheckerState *)object;
71
PKIX_DECREF(state->certSelector);
72
PKIX_DECREF(state->extKeyUsageOID);
73
PKIX_DECREF(state->subjAltNameOID);
74
PKIX_DECREF(state->pathToNameList);
75
PKIX_DECREF(state->extKeyUsageList);
76
PKIX_DECREF(state->subjAltNameList);
80
PKIX_RETURN(TARGETCERTCHECKERSTATE);
84
* FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
86
* Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
89
* Not Thread Safe - for performance and complexity reasons
91
* Since this function is only called by PKIX_PL_Initialize, which should
92
* only be called once, it is acceptable that this function is not
96
pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
98
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
99
pkix_ClassTable_Entry entry;
101
PKIX_ENTER(TARGETCERTCHECKERSTATE,
102
"pkix_TargetCertCheckerState_RegisterSelf");
104
entry.description = "TargetCertCheckerState";
105
entry.objCounter = 0;
106
entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
107
entry.destructor = pkix_TargetCertCheckerState_Destroy;
108
entry.equalsFunction = NULL;
109
entry.hashcodeFunction = NULL;
110
entry.toStringFunction = NULL;
111
entry.comparator = NULL;
112
entry.duplicateFunction = NULL;
114
systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
116
PKIX_RETURN(TARGETCERTCHECKERSTATE);
120
* FUNCTION: pkix_TargetCertCheckerState_Create
123
* Creates a new TargetCertCheckerState using the CertSelector pointed to
124
* by "certSelector" and the number of certs represented by "certsRemaining"
125
* and stores it at "pState".
129
* Address of CertSelector representing the criteria against which the
130
* final certificate in a chain is to be matched. Must be non-NULL.
132
* Number of certificates remaining in the chain.
134
* Address where object pointer will be stored. Must be non-NULL.
136
* Platform-specific context pointer.
138
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
140
* Returns NULL if the function succeeds.
141
* Returns a TargetCertCheckerState Error if the function fails in a
143
* Returns a Fatal Error if the function fails in an unrecoverable way.
146
pkix_TargetCertCheckerState_Create(
147
PKIX_CertSelector *certSelector,
148
PKIX_UInt32 certsRemaining,
149
pkix_TargetCertCheckerState **pState,
152
pkix_TargetCertCheckerState *state = NULL;
153
PKIX_ComCertSelParams *certSelectorParams = NULL;
154
PKIX_List *pathToNameList = NULL;
155
PKIX_List *extKeyUsageList = NULL;
156
PKIX_List *subjAltNameList = NULL;
157
PKIX_PL_OID *extKeyUsageOID = NULL;
158
PKIX_PL_OID *subjAltNameOID = NULL;
159
PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
161
PKIX_ENTER(TARGETCERTCHECKERSTATE,
162
"pkix_TargetCertCheckerState_Create");
163
PKIX_NULLCHECK_ONE(pState);
165
PKIX_CHECK(PKIX_PL_OID_Create
166
(PKIX_EXTENDEDKEYUSAGE_OID,
169
PKIX_OIDCREATEFAILED);
171
PKIX_CHECK(PKIX_PL_OID_Create
172
(PKIX_CERTSUBJALTNAME_OID,
175
PKIX_OIDCREATEFAILED);
177
PKIX_CHECK(PKIX_PL_Object_Alloc
178
(PKIX_TARGETCERTCHECKERSTATE_TYPE,
179
sizeof (pkix_TargetCertCheckerState),
180
(PKIX_PL_Object **)&state,
182
PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
184
/* initialize fields */
186
if (certSelector != NULL) {
188
PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
189
(certSelector, &certSelectorParams, plContext),
190
PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
192
if (certSelectorParams != NULL) {
194
PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
198
PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
200
PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
204
PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
206
PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
210
PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
212
PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
214
&subjAltNameMatchAll,
216
PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
220
state->certsRemaining = certsRemaining;
221
state->subjAltNameMatchAll = subjAltNameMatchAll;
223
PKIX_INCREF(certSelector);
224
state->certSelector = certSelector;
226
state->pathToNameList = pathToNameList;
227
pathToNameList = NULL;
229
state->extKeyUsageList = extKeyUsageList;
230
extKeyUsageList = NULL;
232
state->subjAltNameList = subjAltNameList;
233
subjAltNameList = NULL;
235
state->extKeyUsageOID = extKeyUsageOID;
236
extKeyUsageOID = NULL;
238
state->subjAltNameOID = subjAltNameOID;
239
subjAltNameOID = NULL;
246
PKIX_DECREF(extKeyUsageOID);
247
PKIX_DECREF(subjAltNameOID);
248
PKIX_DECREF(pathToNameList);
249
PKIX_DECREF(extKeyUsageList);
250
PKIX_DECREF(subjAltNameList);
253
PKIX_DECREF(certSelectorParams);
255
PKIX_RETURN(TARGETCERTCHECKERSTATE);
259
/* --Private-TargetCertChecker-Functions------------------------------- */
262
* FUNCTION: pkix_TargetCertChecker_Check
263
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
266
pkix_TargetCertChecker_Check(
267
PKIX_CertChainChecker *checker,
269
PKIX_List *unresolvedCriticalExtensions,
273
pkix_TargetCertCheckerState *state = NULL;
274
PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
275
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
276
PKIX_List *certSubjAltNames = NULL;
277
PKIX_List *certExtKeyUsageList = NULL;
278
PKIX_PL_GeneralName *name = NULL;
279
PKIX_PL_X500Name *certSubjectName = NULL;
280
PKIX_Boolean checkPassed = PKIX_FALSE;
281
PKIX_UInt32 numItems, i;
282
PKIX_UInt32 matchCount = 0;
284
PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
285
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
287
*pNBIOContext = NULL; /* we never block on pending I/O */
289
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
290
(checker, (PKIX_PL_Object **)&state, plContext),
291
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
293
(state->certsRemaining)--;
295
if (state->pathToNameList != NULL) {
297
PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
298
(cert, &nameConstraints, plContext),
299
PKIX_CERTGETNAMECONSTRAINTSFAILED);
302
* XXX We should either make the following call a public one
303
* so it is legal to call from the portability layer or we
304
* should try to create pathToNameList as CertNameConstraints
305
* then call the existing check function.
307
PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
308
(state->pathToNameList,
312
PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
314
if (checkPassed != PKIX_TRUE) {
315
PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
320
PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
321
(cert, &certSubjAltNames, plContext),
322
PKIX_CERTGETSUBJALTNAMESFAILED);
324
if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
326
PKIX_CHECK(PKIX_List_GetLength
327
(state->subjAltNameList, &numItems, plContext),
328
PKIX_LISTGETLENGTHFAILED);
330
for (i = 0; i < numItems; i++) {
332
PKIX_CHECK(PKIX_List_GetItem
333
(state->subjAltNameList,
335
(PKIX_PL_Object **) &name,
337
PKIX_LISTGETITEMFAILED);
339
PKIX_CHECK(pkix_List_Contains
341
(PKIX_PL_Object *) name,
344
PKIX_LISTCONTAINSFAILED);
348
if (checkPassed == PKIX_TRUE) {
350
if (state->subjAltNameMatchAll == PKIX_FALSE) {
351
matchCount = numItems;
354
/* else continue checking next */
361
if (matchCount != numItems) {
362
PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
368
if (state->certsRemaining == 0) {
370
if (state->certSelector != NULL) {
372
PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
373
(state->certSelector,
376
PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
378
PKIX_CHECK(certSelectorMatch
379
(state->certSelector,
383
PKIX_CERTSELECTORMATCHFAILED);
385
if (checkPassed != PKIX_TRUE){
386
PKIX_ERROR(PKIX_CERTSELECTORCHECKFAILED);
390
* There are two Extended Key Usage Checkings
392
* 1) here at the targetcertchecker where we
393
* verify the Extended Key Usage OIDs application
394
* specifies via ComCertSelParams are included
395
* in Cert's Extended Key Usage OID's. Note,
396
* this is an OID to OID comparison and only last
398
* 2) at user defined ekuchecker where checking
399
* is applied to all Certs on the chain and
400
* the NSS Extended Key Usage algorithm is
401
* used. In order to invoke this checking, not
402
* only does the ComCertSelparams needs to be
403
* set, the EKU initialize call is required to
404
* activate the checking.
406
* XXX We use the same ComCertSelParams Set/Get
407
* functions to set the parameters for both cases.
408
* We may want to separate them in the future.
411
PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
412
(cert, &certExtKeyUsageList, plContext),
413
PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
416
if (state->extKeyUsageList != NULL &&
417
certExtKeyUsageList != NULL) {
419
PKIX_CHECK(PKIX_List_GetLength
420
(state->extKeyUsageList, &numItems, plContext),
421
PKIX_LISTGETLENGTHFAILED);
423
for (i = 0; i < numItems; i++) {
425
PKIX_CHECK(PKIX_List_GetItem
426
(state->extKeyUsageList,
428
(PKIX_PL_Object **) &name,
430
PKIX_LISTGETITEMFAILED);
432
PKIX_CHECK(pkix_List_Contains
433
(certExtKeyUsageList,
434
(PKIX_PL_Object *) name,
437
PKIX_LISTCONTAINSFAILED);
441
if (checkPassed != PKIX_TRUE) {
443
(PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
453
/* Remove Critical Extension OID from list */
454
if (unresolvedCriticalExtensions != NULL) {
456
PKIX_CHECK(pkix_List_Remove
457
(unresolvedCriticalExtensions,
458
(PKIX_PL_Object *) state->extKeyUsageOID,
460
PKIX_LISTREMOVEFAILED);
462
PKIX_CHECK(PKIX_PL_Cert_GetSubject
463
(cert, &certSubjectName, plContext),
464
PKIX_CERTGETSUBJECTFAILED);
466
if (certSubjAltNames != NULL) {
467
PKIX_CHECK(pkix_List_Remove
468
(unresolvedCriticalExtensions,
469
(PKIX_PL_Object *) state->subjAltNameOID,
471
PKIX_LISTREMOVEFAILED);
478
PKIX_DECREF(nameConstraints);
479
PKIX_DECREF(certSubjAltNames);
480
PKIX_DECREF(certExtKeyUsageList);
481
PKIX_DECREF(certSubjectName);
484
PKIX_RETURN(CERTCHAINCHECKER);
489
* FUNCTION: pkix_TargetCertChecker_Initialize
492
* Creates a new CertChainChecker and stores it at "pChecker", where it will
493
* used by pkix_TargetCertChecker_Check to check that the final certificate
494
* of a chain meets the criteria of the CertSelector pointed to by
495
* "certSelector". The number of certs remaining in the chain, represented by
496
* "certsRemaining" is used to initialize the checker's state.
500
* Address of CertSelector representing the criteria against which the
501
* final certificate in a chain is to be matched. May be NULL.
503
* Number of certificates remaining in the chain.
505
* Address where object pointer will be stored. Must be non-NULL.
507
* Platform-specific context pointer.
509
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
511
* Returns NULL if the function succeeds.
512
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
513
* Returns a Fatal Error if the function fails in an unrecoverable way.
516
pkix_TargetCertChecker_Initialize(
517
PKIX_CertSelector *certSelector,
518
PKIX_UInt32 certsRemaining,
519
PKIX_CertChainChecker **pChecker,
522
pkix_TargetCertCheckerState *state = NULL;
524
PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
525
PKIX_NULLCHECK_ONE(pChecker);
527
PKIX_CHECK(pkix_TargetCertCheckerState_Create
528
(certSelector, certsRemaining, &state, plContext),
529
PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
531
PKIX_CHECK(PKIX_CertChainChecker_Create
532
(pkix_TargetCertChecker_Check,
536
(PKIX_PL_Object *)state,
539
PKIX_CERTCHAINCHECKERCREATEFAILED);
545
PKIX_RETURN(CERTCHAINCHECKER);