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

http://github.com/zpao/v8monkey · C · 475 lines · 231 code · 75 blank · 169 comment · 32 complexity · f0bd32d85db3787f5f42f7c03d080d51 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_signaturechecker.c
  39. *
  40. * Functions for signature validation
  41. *
  42. */
  43. #include "pkix_signaturechecker.h"
  44. /*
  45. * FUNCTION: pkix_SignatureCheckerstate_Destroy
  46. * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
  47. */
  48. static PKIX_Error *
  49. pkix_SignatureCheckerState_Destroy(
  50. PKIX_PL_Object *object,
  51. void *plContext)
  52. {
  53. pkix_SignatureCheckerState *state = NULL;
  54. PKIX_ENTER(SIGNATURECHECKERSTATE,
  55. "pkix_SignatureCheckerState_Destroy");
  56. PKIX_NULLCHECK_ONE(object);
  57. /* Check that this object is a signature checker state */
  58. PKIX_CHECK(pkix_CheckType
  59. (object, PKIX_SIGNATURECHECKERSTATE_TYPE, plContext),
  60. PKIX_OBJECTNOTSIGNATURECHECKERSTATE);
  61. state = (pkix_SignatureCheckerState *) object;
  62. state->prevCertCertSign = PKIX_FALSE;
  63. PKIX_DECREF(state->prevPublicKey);
  64. PKIX_DECREF(state->prevPublicKeyList);
  65. PKIX_DECREF(state->keyUsageOID);
  66. cleanup:
  67. PKIX_RETURN(SIGNATURECHECKERSTATE);
  68. }
  69. /*
  70. * FUNCTION: pkix_SignatureCheckerState_RegisterSelf
  71. *
  72. * DESCRIPTION:
  73. * Registers PKIX_SIGNATURECHECKERSTATE_TYPE and its related functions
  74. * with systemClasses[]
  75. *
  76. * THREAD SAFETY:
  77. * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  78. *
  79. * Since this function is only called by PKIX_PL_Initialize, which should
  80. * only be called once, it is acceptable that this function is not
  81. * thread-safe.
  82. */
  83. PKIX_Error *
  84. pkix_SignatureCheckerState_RegisterSelf(void *plContext)
  85. {
  86. extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
  87. pkix_ClassTable_Entry entry;
  88. PKIX_ENTER(SIGNATURECHECKERSTATE,
  89. "pkix_SignatureCheckerState_RegisterSelf");
  90. entry.description = "SignatureCheckerState";
  91. entry.objCounter = 0;
  92. entry.typeObjectSize = sizeof(pkix_SignatureCheckerState);
  93. entry.destructor = pkix_SignatureCheckerState_Destroy;
  94. entry.equalsFunction = NULL;
  95. entry.hashcodeFunction = NULL;
  96. entry.toStringFunction = NULL;
  97. entry.comparator = NULL;
  98. entry.duplicateFunction = NULL;
  99. systemClasses[PKIX_SIGNATURECHECKERSTATE_TYPE] = entry;
  100. PKIX_RETURN(SIGNATURECHECKERSTATE);
  101. }
  102. /*
  103. * FUNCTION: pkix_SignatureCheckerState_Create
  104. *
  105. * DESCRIPTION:
  106. * Allocate and initialize SignatureChecker state data.
  107. *
  108. * PARAMETERS
  109. * "trustedPubKey"
  110. * Address of trusted Anchor Public Key for verifying first Cert in the
  111. * chain. Must be non-NULL.
  112. * "certsRemaining"
  113. * Number of certificates remaining in the chain.
  114. * "pCheckerState"
  115. * Address where SignatureCheckerState will be stored. Must be non-NULL.
  116. * "plContext"
  117. * Platform-specific context pointer.
  118. *
  119. * THREAD SAFETY:
  120. * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  121. *
  122. * RETURNS:
  123. * Returns NULL if the function succeeds.
  124. * Returns a SignatureCheckerState Error if the function fails in a
  125. * non-fatal way.
  126. * Returns a Fatal Error if the function fails in an unrecoverable way.
  127. */
  128. static PKIX_Error *
  129. pkix_SignatureCheckerState_Create(
  130. PKIX_PL_PublicKey *trustedPubKey,
  131. PKIX_UInt32 certsRemaining,
  132. pkix_SignatureCheckerState **pCheckerState,
  133. void *plContext)
  134. {
  135. pkix_SignatureCheckerState *state = NULL;
  136. PKIX_PL_OID *keyUsageOID = NULL;
  137. PKIX_ENTER(SIGNATURECHECKERSTATE, "pkix_SignatureCheckerState_Create");
  138. PKIX_NULLCHECK_TWO(trustedPubKey, pCheckerState);
  139. PKIX_CHECK(PKIX_PL_Object_Alloc
  140. (PKIX_SIGNATURECHECKERSTATE_TYPE,
  141. sizeof (pkix_SignatureCheckerState),
  142. (PKIX_PL_Object **)&state,
  143. plContext),
  144. PKIX_COULDNOTCREATESIGNATURECHECKERSTATEOBJECT);
  145. /* Initialize fields */
  146. state->prevCertCertSign = PKIX_TRUE;
  147. state->prevPublicKeyList = NULL;
  148. state->certsRemaining = certsRemaining;
  149. PKIX_INCREF(trustedPubKey);
  150. state->prevPublicKey = trustedPubKey;
  151. PKIX_CHECK(PKIX_PL_OID_Create
  152. (PKIX_CERTKEYUSAGE_OID,
  153. &keyUsageOID,
  154. plContext),
  155. PKIX_OIDCREATEFAILED);
  156. state->keyUsageOID = keyUsageOID;
  157. keyUsageOID = NULL;
  158. *pCheckerState = state;
  159. state = NULL;
  160. cleanup:
  161. PKIX_DECREF(keyUsageOID);
  162. PKIX_DECREF(state);
  163. PKIX_RETURN(SIGNATURECHECKERSTATE);
  164. }
  165. /* --Private-Functions-------------------------------------------- */
  166. /*
  167. * FUNCTION: pkix_SignatureChecker_Check
  168. * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
  169. */
  170. PKIX_Error *
  171. pkix_SignatureChecker_Check(
  172. PKIX_CertChainChecker *checker,
  173. PKIX_PL_Cert *cert,
  174. PKIX_List *unresolvedCriticalExtensions,
  175. void **pNBIOContext,
  176. void *plContext)
  177. {
  178. pkix_SignatureCheckerState *state = NULL;
  179. PKIX_PL_PublicKey *prevPubKey = NULL;
  180. PKIX_PL_PublicKey *currPubKey = NULL;
  181. PKIX_PL_PublicKey *newPubKey = NULL;
  182. PKIX_PL_PublicKey *pKey = NULL;
  183. PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
  184. PKIX_Error *checkKeyUsageFail = NULL;
  185. PKIX_Error *verifyFail = NULL;
  186. PKIX_Boolean certVerified = PKIX_FALSE;
  187. PKIX_ENTER(CERTCHAINCHECKER, "pkix_SignatureChecker_Check");
  188. PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
  189. *pNBIOContext = NULL; /* we never block on pending I/O */
  190. PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
  191. (checker, (PKIX_PL_Object **)&state, plContext),
  192. PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
  193. (state->certsRemaining)--;
  194. PKIX_INCREF(state->prevPublicKey);
  195. prevPubKey = state->prevPublicKey;
  196. /*
  197. * Previous Cert doesn't have CertSign bit on for signature
  198. * verification and it is not a self-issued Cert so there is no
  199. * old key saved. This is considered error.
  200. */
  201. if (state->prevCertCertSign == PKIX_FALSE &&
  202. state->prevPublicKeyList == NULL) {
  203. PKIX_ERROR(PKIX_KEYUSAGEKEYCERTSIGNBITNOTON);
  204. }
  205. /* Previous Cert is valid for signature verification, try it first */
  206. if (state->prevCertCertSign == PKIX_TRUE) {
  207. verifyFail = PKIX_PL_Cert_VerifySignature
  208. (cert, prevPubKey, plContext);
  209. if (verifyFail == NULL) {
  210. certVerified = PKIX_TRUE;
  211. } else {
  212. certVerified = PKIX_FALSE;
  213. PKIX_DECREF(verifyFail);
  214. }
  215. }
  216. #ifdef NIST_TEST_4_5_4_AND_4_5_6
  217. /*
  218. * Following codes under this compiler flag is implemented for
  219. * special cases of NIST tests 4.5.4 and 4.5.6. We are not sure
  220. * we should handle these two tests as what is implemented so the
  221. * codes are commented out, and the tests fails (for now).
  222. * For Cert chain validation, our assumption is all the Certs on
  223. * the chain are using its previous Cert's public key to decode
  224. * its current key. But for thses two tests, keys are used not
  225. * in this precedent order, we can either
  226. * 1) Use what is implemented here: take in what Cert order NIST
  227. * specified and for continuous self-issued Certs, stacking up
  228. * their keys and tries all of them in FILO order.
  229. * But this method breaks the idea of chain key presdency.
  230. * 2) Use Build Chain facility: we will specify the valid Certs
  231. * order (means key precedency is kept) and count on Build Chain
  232. * to get the Certs that can fill for the needed keys. This may have
  233. * performance impact.
  234. * 3) Fetch Certs from CertStore: we will specifiy the valid Certs
  235. * order and use CertSelector on SubjectName to get a list of
  236. * candidates Certs to fill in for the needed keys.
  237. * Anyhow, the codes are kept around just in case we want to use
  238. * solution one...
  239. */
  240. /* If failed and previous key is self-issued, try its old key(s) */
  241. if (certVerified == PKIX_FALSE && state->prevPublicKeyList != NULL) {
  242. /* Verify from keys on the list */
  243. PKIX_CHECK(PKIX_List_GetLength
  244. (state->prevPublicKeyList, &numKeys, plContext),
  245. PKIX_LISTGETLENGTHFAILED);
  246. for (i = numKeys - 1; i >= 0; i--) {
  247. PKIX_CHECK(PKIX_List_GetItem
  248. (state->prevPublicKeyList,
  249. i,
  250. (PKIX_PL_Object **) &pKey,
  251. plContext),
  252. PKIX_LISTGETITEMFAILED);
  253. verifyFail = PKIX_PL_Cert_VerifySignature
  254. (cert, pKey, plContext);
  255. if (verifyFail == NULL) {
  256. certVerified = PKIX_TRUE;
  257. break;
  258. } else {
  259. certVerified = PKIX_FALSE;
  260. PKIX_DECREF(verifyFail);
  261. }
  262. PKIX_DECREF(pKey);
  263. }
  264. }
  265. #endif
  266. if (certVerified == PKIX_FALSE) {
  267. PKIX_ERROR(PKIX_VALIDATIONFAILEDCERTSIGNATURECHECKING);
  268. }
  269. #ifdef NIST_TEST_4_5_4_AND_4_5_6
  270. /*
  271. * Check if Cert is self-issued. If so, the old key(s) is saved, in
  272. * conjunction to the new key, for verifying CERT validity later.
  273. */
  274. PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
  275. PKIX_ISCERTSELFISSUEFAILED);
  276. /*
  277. * Check if Cert is self-issued. If so, the public key of the Cert
  278. * that issues this Cert (old key) can be used together with this
  279. * current key (new key) for key verification. If there are multiple
  280. * self-issued certs, keys of those Certs (old keys) can also be used
  281. * for key verification. Old key(s) is saved in a list (PrevPublickKey-
  282. * List) and cleared when a Cert is no longer self-issued. PrevPublic-
  283. * Key keep key of the previous Cert.
  284. */
  285. if (selfIssued == PKIX_TRUE) {
  286. /* Make sure previous Cert is valid for signature verification */
  287. if (state->prevCertCertSign == PKIX_TRUE) {
  288. if (state->prevPublicKeyList == NULL) {
  289. PKIX_CHECK(PKIX_List_Create
  290. (&state->prevPublicKeyList, plContext),
  291. PKIX_LISTCREATEFALIED);
  292. }
  293. PKIX_CHECK(PKIX_List_AppendItem
  294. (state->prevPublicKeyList,
  295. (PKIX_PL_Object *) state->prevPublicKey,
  296. plContext),
  297. PKIX_LISTAPPENDITEMFAILED);
  298. }
  299. } else {
  300. /* Not self-issued Cert any more, clear old key(s) saved */
  301. PKIX_DECREF(state->prevPublicKeyList);
  302. }
  303. #endif
  304. /* Save current key as prevPublicKey */
  305. PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  306. (cert, &currPubKey, plContext),
  307. PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  308. PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
  309. (currPubKey, prevPubKey, &newPubKey, plContext),
  310. PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED);
  311. if (newPubKey == NULL){
  312. PKIX_INCREF(currPubKey);
  313. newPubKey = currPubKey;
  314. }
  315. PKIX_INCREF(newPubKey);
  316. PKIX_DECREF(state->prevPublicKey);
  317. state->prevPublicKey = newPubKey;
  318. /* Save this Cert key usage CertSign bit */
  319. if (state->certsRemaining != 0) {
  320. checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage
  321. (cert, PKIX_KEY_CERT_SIGN, plContext);
  322. state->prevCertCertSign = (checkKeyUsageFail == NULL)?
  323. PKIX_TRUE:PKIX_FALSE;
  324. PKIX_DECREF(checkKeyUsageFail);
  325. }
  326. /* Remove Key Usage Extension OID from list */
  327. if (unresolvedCriticalExtensions != NULL) {
  328. PKIX_CHECK(pkix_List_Remove
  329. (unresolvedCriticalExtensions,
  330. (PKIX_PL_Object *) state->keyUsageOID,
  331. plContext),
  332. PKIX_LISTREMOVEFAILED);
  333. }
  334. PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
  335. (checker, (PKIX_PL_Object *)state, plContext),
  336. PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
  337. cleanup:
  338. PKIX_DECREF(state);
  339. PKIX_DECREF(pKey);
  340. PKIX_DECREF(prevPubKey);
  341. PKIX_DECREF(currPubKey);
  342. PKIX_DECREF(newPubKey);
  343. PKIX_DECREF(basicConstraints);
  344. PKIX_DECREF(verifyFail);
  345. PKIX_DECREF(checkKeyUsageFail);
  346. PKIX_RETURN(CERTCHAINCHECKER);
  347. }
  348. /*
  349. * FUNCTION: pkix_SignatureChecker_Initialize
  350. * DESCRIPTION:
  351. *
  352. * Creates a new CertChainChecker and stores it at "pChecker", where it will
  353. * be used by pkix_SignatureChecker_Check to check that the public key in
  354. * the checker's state is able to successfully validate the certificate's
  355. * signature. The PublicKey pointed to by "trustedPubKey" is used to
  356. * initialize the checker's state.
  357. *
  358. * PARAMETERS:
  359. * "trustedPubKey"
  360. * Address of PublicKey representing the trusted public key used to
  361. * initialize the state of this checker. Must be non-NULL.
  362. * "certsRemaining"
  363. * Number of certificates remaining in the chain.
  364. * "pChecker"
  365. * Address where object pointer will be stored. Must be non-NULL.
  366. * "plContext"
  367. * Platform-specific context pointer.
  368. * THREAD SAFETY:
  369. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  370. * RETURNS:
  371. * Returns NULL if the function succeeds.
  372. * Returns a CertChainChecker Error if the function fails in a non-fatal way.
  373. * Returns a Fatal Error if the function fails in an unrecoverable way.
  374. */
  375. PKIX_Error *
  376. pkix_SignatureChecker_Initialize(
  377. PKIX_PL_PublicKey *trustedPubKey,
  378. PKIX_UInt32 certsRemaining,
  379. PKIX_CertChainChecker **pChecker,
  380. void *plContext)
  381. {
  382. pkix_SignatureCheckerState* state = NULL;
  383. PKIX_ENTER(CERTCHAINCHECKER, "PKIX_SignatureChecker_Initialize");
  384. PKIX_NULLCHECK_TWO(pChecker, trustedPubKey);
  385. PKIX_CHECK(pkix_SignatureCheckerState_Create
  386. (trustedPubKey, certsRemaining, &state, plContext),
  387. PKIX_SIGNATURECHECKERSTATECREATEFAILED);
  388. PKIX_CHECK(PKIX_CertChainChecker_Create
  389. (pkix_SignatureChecker_Check,
  390. PKIX_FALSE,
  391. PKIX_FALSE,
  392. NULL,
  393. (PKIX_PL_Object *) state,
  394. pChecker,
  395. plContext),
  396. PKIX_CERTCHAINCHECKERCREATEFAILED);
  397. cleanup:
  398. PKIX_DECREF(state);
  399. PKIX_RETURN(CERTCHAINCHECKER);
  400. }