/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c

http://github.com/zpao/v8monkey · C · 549 lines · 305 code · 93 blank · 151 comment · 36 complexity · 5d6d3205b2275afc04f18a40e9368815 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  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/
  8. *
  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
  12. * License.
  13. *
  14. * The Original Code is the PKIX-C library.
  15. *
  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.
  20. *
  21. * Contributor(s):
  22. * Sun Microsystems, Inc.
  23. *
  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.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * pkix_targetcertchecker.c
  39. *
  40. * Functions for target cert validation
  41. *
  42. */
  43. #include "pkix_targetcertchecker.h"
  44. /* --Private-TargetCertCheckerState-Functions------------------------------- */
  45. /*
  46. * FUNCTION: pkix_TargetCertCheckerState_Destroy
  47. * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
  48. */
  49. static PKIX_Error *
  50. pkix_TargetCertCheckerState_Destroy(
  51. PKIX_PL_Object *object,
  52. void *plContext)
  53. {
  54. pkix_TargetCertCheckerState *state = NULL;
  55. PKIX_ENTER(TARGETCERTCHECKERSTATE,
  56. "pkix_TargetCertCheckerState_Destroy");
  57. PKIX_NULLCHECK_ONE(object);
  58. /* Check that this object is a target cert checker state */
  59. PKIX_CHECK(pkix_CheckType
  60. (object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
  61. PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
  62. state = (pkix_TargetCertCheckerState *)object;
  63. PKIX_DECREF(state->certSelector);
  64. PKIX_DECREF(state->extKeyUsageOID);
  65. PKIX_DECREF(state->subjAltNameOID);
  66. PKIX_DECREF(state->pathToNameList);
  67. PKIX_DECREF(state->extKeyUsageList);
  68. PKIX_DECREF(state->subjAltNameList);
  69. cleanup:
  70. PKIX_RETURN(TARGETCERTCHECKERSTATE);
  71. }
  72. /*
  73. * FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
  74. * DESCRIPTION:
  75. * Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
  76. * systemClasses[]
  77. * THREAD SAFETY:
  78. * Not Thread Safe - for performance and complexity reasons
  79. *
  80. * Since this function is only called by PKIX_PL_Initialize, which should
  81. * only be called once, it is acceptable that this function is not
  82. * thread-safe.
  83. */
  84. PKIX_Error *
  85. pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
  86. {
  87. extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
  88. pkix_ClassTable_Entry entry;
  89. PKIX_ENTER(TARGETCERTCHECKERSTATE,
  90. "pkix_TargetCertCheckerState_RegisterSelf");
  91. entry.description = "TargetCertCheckerState";
  92. entry.objCounter = 0;
  93. entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
  94. entry.destructor = pkix_TargetCertCheckerState_Destroy;
  95. entry.equalsFunction = NULL;
  96. entry.hashcodeFunction = NULL;
  97. entry.toStringFunction = NULL;
  98. entry.comparator = NULL;
  99. entry.duplicateFunction = NULL;
  100. systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
  101. PKIX_RETURN(TARGETCERTCHECKERSTATE);
  102. }
  103. /*
  104. * FUNCTION: pkix_TargetCertCheckerState_Create
  105. * DESCRIPTION:
  106. *
  107. * Creates a new TargetCertCheckerState using the CertSelector pointed to
  108. * by "certSelector" and the number of certs represented by "certsRemaining"
  109. * and stores it at "pState".
  110. *
  111. * PARAMETERS:
  112. * "certSelector"
  113. * Address of CertSelector representing the criteria against which the
  114. * final certificate in a chain is to be matched. Must be non-NULL.
  115. * "certsRemaining"
  116. * Number of certificates remaining in the chain.
  117. * "pState"
  118. * Address where object pointer will be stored. Must be non-NULL.
  119. * "plContext"
  120. * Platform-specific context pointer.
  121. * THREAD SAFETY:
  122. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  123. * RETURNS:
  124. * Returns NULL if the function succeeds.
  125. * Returns a TargetCertCheckerState Error if the function fails in a
  126. * non-fatal way.
  127. * Returns a Fatal Error if the function fails in an unrecoverable way.
  128. */
  129. PKIX_Error *
  130. pkix_TargetCertCheckerState_Create(
  131. PKIX_CertSelector *certSelector,
  132. PKIX_UInt32 certsRemaining,
  133. pkix_TargetCertCheckerState **pState,
  134. void *plContext)
  135. {
  136. pkix_TargetCertCheckerState *state = NULL;
  137. PKIX_ComCertSelParams *certSelectorParams = NULL;
  138. PKIX_List *pathToNameList = NULL;
  139. PKIX_List *extKeyUsageList = NULL;
  140. PKIX_List *subjAltNameList = NULL;
  141. PKIX_PL_OID *extKeyUsageOID = NULL;
  142. PKIX_PL_OID *subjAltNameOID = NULL;
  143. PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
  144. PKIX_ENTER(TARGETCERTCHECKERSTATE,
  145. "pkix_TargetCertCheckerState_Create");
  146. PKIX_NULLCHECK_ONE(pState);
  147. PKIX_CHECK(PKIX_PL_OID_Create
  148. (PKIX_EXTENDEDKEYUSAGE_OID,
  149. &extKeyUsageOID,
  150. plContext),
  151. PKIX_OIDCREATEFAILED);
  152. PKIX_CHECK(PKIX_PL_OID_Create
  153. (PKIX_CERTSUBJALTNAME_OID,
  154. &subjAltNameOID,
  155. plContext),
  156. PKIX_OIDCREATEFAILED);
  157. PKIX_CHECK(PKIX_PL_Object_Alloc
  158. (PKIX_TARGETCERTCHECKERSTATE_TYPE,
  159. sizeof (pkix_TargetCertCheckerState),
  160. (PKIX_PL_Object **)&state,
  161. plContext),
  162. PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
  163. /* initialize fields */
  164. if (certSelector != NULL) {
  165. PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  166. (certSelector, &certSelectorParams, plContext),
  167. PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
  168. if (certSelectorParams != NULL) {
  169. PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
  170. (certSelectorParams,
  171. &pathToNameList,
  172. plContext),
  173. PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
  174. PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
  175. (certSelectorParams,
  176. &extKeyUsageList,
  177. plContext),
  178. PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
  179. PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
  180. (certSelectorParams,
  181. &subjAltNameList,
  182. plContext),
  183. PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
  184. PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
  185. (certSelectorParams,
  186. &subjAltNameMatchAll,
  187. plContext),
  188. PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
  189. }
  190. }
  191. state->certsRemaining = certsRemaining;
  192. state->subjAltNameMatchAll = subjAltNameMatchAll;
  193. PKIX_INCREF(certSelector);
  194. state->certSelector = certSelector;
  195. state->pathToNameList = pathToNameList;
  196. pathToNameList = NULL;
  197. state->extKeyUsageList = extKeyUsageList;
  198. extKeyUsageList = NULL;
  199. state->subjAltNameList = subjAltNameList;
  200. subjAltNameList = NULL;
  201. state->extKeyUsageOID = extKeyUsageOID;
  202. extKeyUsageOID = NULL;
  203. state->subjAltNameOID = subjAltNameOID;
  204. subjAltNameOID = NULL;
  205. *pState = state;
  206. state = NULL;
  207. cleanup:
  208. PKIX_DECREF(extKeyUsageOID);
  209. PKIX_DECREF(subjAltNameOID);
  210. PKIX_DECREF(pathToNameList);
  211. PKIX_DECREF(extKeyUsageList);
  212. PKIX_DECREF(subjAltNameList);
  213. PKIX_DECREF(state);
  214. PKIX_DECREF(certSelectorParams);
  215. PKIX_RETURN(TARGETCERTCHECKERSTATE);
  216. }
  217. /* --Private-TargetCertChecker-Functions------------------------------- */
  218. /*
  219. * FUNCTION: pkix_TargetCertChecker_Check
  220. * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
  221. */
  222. PKIX_Error *
  223. pkix_TargetCertChecker_Check(
  224. PKIX_CertChainChecker *checker,
  225. PKIX_PL_Cert *cert,
  226. PKIX_List *unresolvedCriticalExtensions,
  227. void **pNBIOContext,
  228. void *plContext)
  229. {
  230. pkix_TargetCertCheckerState *state = NULL;
  231. PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
  232. PKIX_PL_CertNameConstraints *nameConstraints = NULL;
  233. PKIX_List *certSubjAltNames = NULL;
  234. PKIX_List *certExtKeyUsageList = NULL;
  235. PKIX_PL_GeneralName *name = NULL;
  236. PKIX_PL_X500Name *certSubjectName = NULL;
  237. PKIX_Boolean checkPassed = PKIX_FALSE;
  238. PKIX_UInt32 numItems, i;
  239. PKIX_UInt32 matchCount = 0;
  240. PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
  241. PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
  242. *pNBIOContext = NULL; /* we never block on pending I/O */
  243. PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
  244. (checker, (PKIX_PL_Object **)&state, plContext),
  245. PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
  246. (state->certsRemaining)--;
  247. if (state->pathToNameList != NULL) {
  248. PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
  249. (cert, &nameConstraints, plContext),
  250. PKIX_CERTGETNAMECONSTRAINTSFAILED);
  251. /*
  252. * XXX We should either make the following call a public one
  253. * so it is legal to call from the portability layer or we
  254. * should try to create pathToNameList as CertNameConstraints
  255. * then call the existing check function.
  256. */
  257. PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
  258. (state->pathToNameList,
  259. nameConstraints,
  260. &checkPassed,
  261. plContext),
  262. PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
  263. if (checkPassed != PKIX_TRUE) {
  264. PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
  265. }
  266. }
  267. PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
  268. (cert, &certSubjAltNames, plContext),
  269. PKIX_CERTGETSUBJALTNAMESFAILED);
  270. if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
  271. PKIX_CHECK(PKIX_List_GetLength
  272. (state->subjAltNameList, &numItems, plContext),
  273. PKIX_LISTGETLENGTHFAILED);
  274. for (i = 0; i < numItems; i++) {
  275. PKIX_CHECK(PKIX_List_GetItem
  276. (state->subjAltNameList,
  277. i,
  278. (PKIX_PL_Object **) &name,
  279. plContext),
  280. PKIX_LISTGETITEMFAILED);
  281. PKIX_CHECK(pkix_List_Contains
  282. (certSubjAltNames,
  283. (PKIX_PL_Object *) name,
  284. &checkPassed,
  285. plContext),
  286. PKIX_LISTCONTAINSFAILED);
  287. PKIX_DECREF(name);
  288. if (checkPassed == PKIX_TRUE) {
  289. if (state->subjAltNameMatchAll == PKIX_FALSE) {
  290. matchCount = numItems;
  291. break;
  292. } else {
  293. /* else continue checking next */
  294. matchCount++;
  295. }
  296. }
  297. }
  298. if (matchCount != numItems) {
  299. PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
  300. }
  301. }
  302. if (state->certsRemaining == 0) {
  303. if (state->certSelector != NULL) {
  304. PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  305. (state->certSelector,
  306. &certSelectorMatch,
  307. plContext),
  308. PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  309. PKIX_CHECK(certSelectorMatch
  310. (state->certSelector,
  311. cert,
  312. plContext),
  313. PKIX_CERTSELECTORMATCHFAILED);
  314. } else {
  315. /* Check at least cert/key usages if target cert selector
  316. * is not set. */
  317. PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
  318. PKIX_FALSE /* is chain cert*/,
  319. plContext),
  320. PKIX_CERTVERIFYCERTTYPEFAILED);
  321. }
  322. /*
  323. * There are two Extended Key Usage Checkings
  324. * available :
  325. * 1) here at the targetcertchecker where we
  326. * verify the Extended Key Usage OIDs application
  327. * specifies via ComCertSelParams are included
  328. * in Cert's Extended Key Usage OID's. Note,
  329. * this is an OID to OID comparison and only last
  330. * Cert is checked.
  331. * 2) at user defined ekuchecker where checking
  332. * is applied to all Certs on the chain and
  333. * the NSS Extended Key Usage algorithm is
  334. * used. In order to invoke this checking, not
  335. * only does the ComCertSelparams needs to be
  336. * set, the EKU initialize call is required to
  337. * activate the checking.
  338. *
  339. * XXX We use the same ComCertSelParams Set/Get
  340. * functions to set the parameters for both cases.
  341. * We may want to separate them in the future.
  342. */
  343. PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
  344. (cert, &certExtKeyUsageList, plContext),
  345. PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
  346. if (state->extKeyUsageList != NULL &&
  347. certExtKeyUsageList != NULL) {
  348. PKIX_CHECK(PKIX_List_GetLength
  349. (state->extKeyUsageList, &numItems, plContext),
  350. PKIX_LISTGETLENGTHFAILED);
  351. for (i = 0; i < numItems; i++) {
  352. PKIX_CHECK(PKIX_List_GetItem
  353. (state->extKeyUsageList,
  354. i,
  355. (PKIX_PL_Object **) &name,
  356. plContext),
  357. PKIX_LISTGETITEMFAILED);
  358. PKIX_CHECK(pkix_List_Contains
  359. (certExtKeyUsageList,
  360. (PKIX_PL_Object *) name,
  361. &checkPassed,
  362. plContext),
  363. PKIX_LISTCONTAINSFAILED);
  364. PKIX_DECREF(name);
  365. if (checkPassed != PKIX_TRUE) {
  366. PKIX_ERROR
  367. (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
  368. }
  369. }
  370. }
  371. } else {
  372. /* Check key usage and cert type based on certificate usage. */
  373. PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
  374. plContext),
  375. PKIX_CERTVERIFYCERTTYPEFAILED);
  376. }
  377. /* Remove Critical Extension OID from list */
  378. if (unresolvedCriticalExtensions != NULL) {
  379. PKIX_CHECK(pkix_List_Remove
  380. (unresolvedCriticalExtensions,
  381. (PKIX_PL_Object *) state->extKeyUsageOID,
  382. plContext),
  383. PKIX_LISTREMOVEFAILED);
  384. PKIX_CHECK(PKIX_PL_Cert_GetSubject
  385. (cert, &certSubjectName, plContext),
  386. PKIX_CERTGETSUBJECTFAILED);
  387. if (certSubjAltNames != NULL) {
  388. PKIX_CHECK(pkix_List_Remove
  389. (unresolvedCriticalExtensions,
  390. (PKIX_PL_Object *) state->subjAltNameOID,
  391. plContext),
  392. PKIX_LISTREMOVEFAILED);
  393. }
  394. }
  395. cleanup:
  396. PKIX_DECREF(name);
  397. PKIX_DECREF(nameConstraints);
  398. PKIX_DECREF(certSubjAltNames);
  399. PKIX_DECREF(certExtKeyUsageList);
  400. PKIX_DECREF(certSubjectName);
  401. PKIX_DECREF(state);
  402. PKIX_RETURN(CERTCHAINCHECKER);
  403. }
  404. /*
  405. * FUNCTION: pkix_TargetCertChecker_Initialize
  406. * DESCRIPTION:
  407. *
  408. * Creates a new CertChainChecker and stores it at "pChecker", where it will
  409. * used by pkix_TargetCertChecker_Check to check that the final certificate
  410. * of a chain meets the criteria of the CertSelector pointed to by
  411. * "certSelector". The number of certs remaining in the chain, represented by
  412. * "certsRemaining" is used to initialize the checker's state.
  413. *
  414. * PARAMETERS:
  415. * "certSelector"
  416. * Address of CertSelector representing the criteria against which the
  417. * final certificate in a chain is to be matched. May be NULL.
  418. * "certsRemaining"
  419. * Number of certificates remaining in the chain.
  420. * "pChecker"
  421. * Address where object pointer will be stored. Must be non-NULL.
  422. * "plContext"
  423. * Platform-specific context pointer.
  424. * THREAD SAFETY:
  425. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  426. * RETURNS:
  427. * Returns NULL if the function succeeds.
  428. * Returns a CertChainChecker Error if the function fails in a non-fatal way.
  429. * Returns a Fatal Error if the function fails in an unrecoverable way.
  430. */
  431. PKIX_Error *
  432. pkix_TargetCertChecker_Initialize(
  433. PKIX_CertSelector *certSelector,
  434. PKIX_UInt32 certsRemaining,
  435. PKIX_CertChainChecker **pChecker,
  436. void *plContext)
  437. {
  438. pkix_TargetCertCheckerState *state = NULL;
  439. PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
  440. PKIX_NULLCHECK_ONE(pChecker);
  441. PKIX_CHECK(pkix_TargetCertCheckerState_Create
  442. (certSelector, certsRemaining, &state, plContext),
  443. PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
  444. PKIX_CHECK(PKIX_CertChainChecker_Create
  445. (pkix_TargetCertChecker_Check,
  446. PKIX_FALSE,
  447. PKIX_FALSE,
  448. NULL,
  449. (PKIX_PL_Object *)state,
  450. pChecker,
  451. plContext),
  452. PKIX_CERTCHAINCHECKERCREATEFAILED);
  453. cleanup:
  454. PKIX_DECREF(state);
  455. PKIX_RETURN(CERTCHAINCHECKER);
  456. }