Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c

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

Powered by Google App Engine
This is Rietveld 408576698