Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | /* |
michael@0 | 5 | * nss_pkix_proxy.h |
michael@0 | 6 | * |
michael@0 | 7 | * PKIX - NSS proxy functions |
michael@0 | 8 | * |
michael@0 | 9 | * NOTE: All structures, functions, data types are parts of library private |
michael@0 | 10 | * api and are subjects to change in any following releases. |
michael@0 | 11 | * |
michael@0 | 12 | */ |
michael@0 | 13 | #include "prerror.h" |
michael@0 | 14 | #include "prprf.h" |
michael@0 | 15 | |
michael@0 | 16 | #include "nspr.h" |
michael@0 | 17 | #include "pk11func.h" |
michael@0 | 18 | #include "certdb.h" |
michael@0 | 19 | #include "cert.h" |
michael@0 | 20 | #include "secerr.h" |
michael@0 | 21 | #include "nssb64.h" |
michael@0 | 22 | #include "secasn1.h" |
michael@0 | 23 | #include "secder.h" |
michael@0 | 24 | #include "pkit.h" |
michael@0 | 25 | |
michael@0 | 26 | #include "pkix_pl_common.h" |
michael@0 | 27 | |
michael@0 | 28 | extern PRLogModuleInfo *pkixLog; |
michael@0 | 29 | |
michael@0 | 30 | #ifdef DEBUG_volkov |
michael@0 | 31 | /* Temporary declarations of functioins. Will be removed with fix for |
michael@0 | 32 | * 391183 */ |
michael@0 | 33 | extern char * |
michael@0 | 34 | pkix_Error2ASCII(PKIX_Error *error, void *plContext); |
michael@0 | 35 | |
michael@0 | 36 | extern void |
michael@0 | 37 | cert_PrintCert(PKIX_PL_Cert *pkixCert, void *plContext); |
michael@0 | 38 | |
michael@0 | 39 | extern PKIX_Error * |
michael@0 | 40 | cert_PrintCertChain(PKIX_List *pkixCertChain, void *plContext); |
michael@0 | 41 | |
michael@0 | 42 | #endif /* DEBUG */ |
michael@0 | 43 | |
michael@0 | 44 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 45 | |
michael@0 | 46 | extern PKIX_UInt32 |
michael@0 | 47 | pkix_pl_lifecycle_ObjectLeakCheck(int *); |
michael@0 | 48 | |
michael@0 | 49 | extern SECStatus |
michael@0 | 50 | pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable); |
michael@0 | 51 | |
michael@0 | 52 | PRInt32 parallelFnInvocationCount; |
michael@0 | 53 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 54 | |
michael@0 | 55 | |
michael@0 | 56 | static PRBool usePKIXValidationEngine = PR_FALSE; |
michael@0 | 57 | |
michael@0 | 58 | /* |
michael@0 | 59 | * FUNCTION: CERT_SetUsePKIXForValidation |
michael@0 | 60 | * DESCRIPTION: |
michael@0 | 61 | * |
michael@0 | 62 | * Enables or disables use of libpkix for certificate validation |
michael@0 | 63 | * |
michael@0 | 64 | * PARAMETERS: |
michael@0 | 65 | * "enable" |
michael@0 | 66 | * PR_TRUE: enables use of libpkix for cert validation. |
michael@0 | 67 | * PR_FALSE: disables. |
michael@0 | 68 | * THREAD SAFETY: |
michael@0 | 69 | * NOT Thread Safe. |
michael@0 | 70 | * RETURNS: |
michael@0 | 71 | * Returns SECSuccess if successfully enabled |
michael@0 | 72 | */ |
michael@0 | 73 | SECStatus |
michael@0 | 74 | CERT_SetUsePKIXForValidation(PRBool enable) |
michael@0 | 75 | { |
michael@0 | 76 | usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE; |
michael@0 | 77 | return SECSuccess; |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | /* |
michael@0 | 81 | * FUNCTION: CERT_GetUsePKIXForValidation |
michael@0 | 82 | * DESCRIPTION: |
michael@0 | 83 | * |
michael@0 | 84 | * Checks if libpkix building function should be use for certificate |
michael@0 | 85 | * chain building. |
michael@0 | 86 | * |
michael@0 | 87 | * PARAMETERS: |
michael@0 | 88 | * NONE |
michael@0 | 89 | * THREAD SAFETY: |
michael@0 | 90 | * NOT Thread Safe |
michael@0 | 91 | * RETURNS: |
michael@0 | 92 | * Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise. |
michael@0 | 93 | */ |
michael@0 | 94 | PRBool |
michael@0 | 95 | CERT_GetUsePKIXForValidation() |
michael@0 | 96 | { |
michael@0 | 97 | return usePKIXValidationEngine; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | #ifdef NOTDEF |
michael@0 | 101 | /* |
michael@0 | 102 | * FUNCTION: cert_NssKeyUsagesToPkix |
michael@0 | 103 | * DESCRIPTION: |
michael@0 | 104 | * |
michael@0 | 105 | * Converts nss key usage bit field(PRUint32) to pkix key usage |
michael@0 | 106 | * bit field. |
michael@0 | 107 | * |
michael@0 | 108 | * PARAMETERS: |
michael@0 | 109 | * "nssKeyUsage" |
michael@0 | 110 | * Nss key usage bit field. |
michael@0 | 111 | * "pkixKeyUsage" |
michael@0 | 112 | * Pkix key usage big field. |
michael@0 | 113 | * "plContext" |
michael@0 | 114 | * Platform-specific context pointer. |
michael@0 | 115 | * THREAD SAFETY: |
michael@0 | 116 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 117 | * RETURNS: |
michael@0 | 118 | * Returns NULL if the function succeeds. |
michael@0 | 119 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 120 | */ |
michael@0 | 121 | static PKIX_Error* |
michael@0 | 122 | cert_NssKeyUsagesToPkix( |
michael@0 | 123 | PRUint32 nssKeyUsage, |
michael@0 | 124 | PKIX_UInt32 *pPkixKeyUsage, |
michael@0 | 125 | void *plContext) |
michael@0 | 126 | { |
michael@0 | 127 | PKIX_UInt32 pkixKeyUsage = 0; |
michael@0 | 128 | |
michael@0 | 129 | PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix"); |
michael@0 | 130 | PKIX_NULLCHECK_ONE(pPkixKeyUsage); |
michael@0 | 131 | |
michael@0 | 132 | *pPkixKeyUsage = 0; |
michael@0 | 133 | |
michael@0 | 134 | if (nssKeyUsage & KU_DIGITAL_SIGNATURE) { |
michael@0 | 135 | pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE; |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | if (nssKeyUsage & KU_NON_REPUDIATION) { |
michael@0 | 139 | pkixKeyUsage |= PKIX_NON_REPUDIATION; |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | if (nssKeyUsage & KU_KEY_ENCIPHERMENT) { |
michael@0 | 143 | pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT; |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | if (nssKeyUsage & KU_DATA_ENCIPHERMENT) { |
michael@0 | 147 | pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT; |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | if (nssKeyUsage & KU_KEY_AGREEMENT) { |
michael@0 | 151 | pkixKeyUsage |= PKIX_KEY_AGREEMENT; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | if (nssKeyUsage & KU_KEY_CERT_SIGN) { |
michael@0 | 155 | pkixKeyUsage |= PKIX_KEY_CERT_SIGN; |
michael@0 | 156 | } |
michael@0 | 157 | |
michael@0 | 158 | if (nssKeyUsage & KU_CRL_SIGN) { |
michael@0 | 159 | pkixKeyUsage |= PKIX_CRL_SIGN; |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | if (nssKeyUsage & KU_ENCIPHER_ONLY) { |
michael@0 | 163 | pkixKeyUsage |= PKIX_ENCIPHER_ONLY; |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | /* Not supported. XXX we should support this once it is |
michael@0 | 167 | * fixed in NSS */ |
michael@0 | 168 | /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */ |
michael@0 | 169 | |
michael@0 | 170 | *pPkixKeyUsage = pkixKeyUsage; |
michael@0 | 171 | |
michael@0 | 172 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | extern SECOidTag ekuOidStrings[]; |
michael@0 | 176 | |
michael@0 | 177 | enum { |
michael@0 | 178 | ekuIndexSSLServer = 0, |
michael@0 | 179 | ekuIndexSSLClient, |
michael@0 | 180 | ekuIndexCodeSigner, |
michael@0 | 181 | ekuIndexEmail, |
michael@0 | 182 | ekuIndexTimeStamp, |
michael@0 | 183 | ekuIndexStatusResponder, |
michael@0 | 184 | ekuIndexUnknown |
michael@0 | 185 | } ekuIndex; |
michael@0 | 186 | |
michael@0 | 187 | typedef struct { |
michael@0 | 188 | SECCertUsage certUsage; |
michael@0 | 189 | PRUint32 ekuStringIndex; |
michael@0 | 190 | } SECCertUsageToEku; |
michael@0 | 191 | |
michael@0 | 192 | const SECCertUsageToEku certUsageEkuStringMap[] = { |
michael@0 | 193 | {certUsageSSLClient, ekuIndexSSLClient}, |
michael@0 | 194 | {certUsageSSLServer, ekuIndexSSLServer}, |
michael@0 | 195 | {certUsageSSLCA, ekuIndexSSLServer}, |
michael@0 | 196 | {certUsageEmailSigner, ekuIndexEmail}, |
michael@0 | 197 | {certUsageEmailRecipient, ekuIndexEmail}, |
michael@0 | 198 | {certUsageObjectSigner, ekuIndexCodeSigner}, |
michael@0 | 199 | {certUsageUserCertImport, ekuIndexUnknown}, |
michael@0 | 200 | {certUsageVerifyCA, ekuIndexUnknown}, |
michael@0 | 201 | {certUsageProtectedObjectSigner, ekuIndexUnknown}, |
michael@0 | 202 | {certUsageStatusResponder, ekuIndexStatusResponder}, |
michael@0 | 203 | {certUsageAnyCA, ekuIndexUnknown}, |
michael@0 | 204 | }; |
michael@0 | 205 | |
michael@0 | 206 | /* |
michael@0 | 207 | * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU |
michael@0 | 208 | * DESCRIPTION: |
michael@0 | 209 | * |
michael@0 | 210 | * Converts nss CERTCertificateUsage bit field to pkix key and |
michael@0 | 211 | * extended key usages. |
michael@0 | 212 | * |
michael@0 | 213 | * PARAMETERS: |
michael@0 | 214 | * "cert" |
michael@0 | 215 | * Pointer to CERTCertificate structure of validating cert. |
michael@0 | 216 | * "requiredCertUsages" |
michael@0 | 217 | * Required usage that will be converted to pkix eku and ku. |
michael@0 | 218 | * "requiredKeyUsage", |
michael@0 | 219 | * Additional key usages impose to cert. |
michael@0 | 220 | * "isCA", |
michael@0 | 221 | * it true, convert usages for cert that is a CA cert. |
michael@0 | 222 | * "ppkixEKUList" |
michael@0 | 223 | * Returned address of a list of pkix extended key usages. |
michael@0 | 224 | * "ppkixKU" |
michael@0 | 225 | * Returned address of pkix required key usages bit field. |
michael@0 | 226 | * "plContext" |
michael@0 | 227 | * Platform-specific context pointer. |
michael@0 | 228 | * THREAD SAFETY: |
michael@0 | 229 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 230 | * RETURNS: |
michael@0 | 231 | * Returns NULL if the function succeeds. |
michael@0 | 232 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 233 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 234 | */ |
michael@0 | 235 | static PKIX_Error* |
michael@0 | 236 | cert_NssCertificateUsageToPkixKUAndEKU( |
michael@0 | 237 | CERTCertificate *cert, |
michael@0 | 238 | SECCertUsage requiredCertUsage, |
michael@0 | 239 | PRUint32 requiredKeyUsages, |
michael@0 | 240 | PRBool isCA, |
michael@0 | 241 | PKIX_List **ppkixEKUList, |
michael@0 | 242 | PKIX_UInt32 *ppkixKU, |
michael@0 | 243 | void *plContext) |
michael@0 | 244 | { |
michael@0 | 245 | PKIX_List *ekuOidsList = NULL; |
michael@0 | 246 | PKIX_PL_OID *ekuOid = NULL; |
michael@0 | 247 | int i = 0; |
michael@0 | 248 | int ekuIndex = ekuIndexUnknown; |
michael@0 | 249 | |
michael@0 | 250 | PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku"); |
michael@0 | 251 | PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU); |
michael@0 | 252 | |
michael@0 | 253 | PKIX_CHECK( |
michael@0 | 254 | PKIX_List_Create(&ekuOidsList, plContext), |
michael@0 | 255 | PKIX_LISTCREATEFAILED); |
michael@0 | 256 | |
michael@0 | 257 | for (;i < PR_ARRAY_SIZE(certUsageEkuStringMap);i++) { |
michael@0 | 258 | const SECCertUsageToEku *usageToEkuElem = |
michael@0 | 259 | &certUsageEkuStringMap[i]; |
michael@0 | 260 | if (usageToEkuElem->certUsage == requiredCertUsage) { |
michael@0 | 261 | ekuIndex = usageToEkuElem->ekuStringIndex; |
michael@0 | 262 | break; |
michael@0 | 263 | } |
michael@0 | 264 | } |
michael@0 | 265 | if (ekuIndex != ekuIndexUnknown) { |
michael@0 | 266 | PRUint32 reqKeyUsage = 0; |
michael@0 | 267 | PRUint32 reqCertType = 0; |
michael@0 | 268 | |
michael@0 | 269 | CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA, |
michael@0 | 270 | &reqKeyUsage, |
michael@0 | 271 | &reqCertType); |
michael@0 | 272 | |
michael@0 | 273 | requiredKeyUsages |= reqKeyUsage; |
michael@0 | 274 | |
michael@0 | 275 | PKIX_CHECK( |
michael@0 | 276 | PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid, |
michael@0 | 277 | plContext), |
michael@0 | 278 | PKIX_OIDCREATEFAILED); |
michael@0 | 279 | |
michael@0 | 280 | PKIX_CHECK( |
michael@0 | 281 | PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid, |
michael@0 | 282 | plContext), |
michael@0 | 283 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 284 | |
michael@0 | 285 | PKIX_DECREF(ekuOid); |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | PKIX_CHECK( |
michael@0 | 289 | cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext), |
michael@0 | 290 | PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED); |
michael@0 | 291 | |
michael@0 | 292 | *ppkixEKUList = ekuOidsList; |
michael@0 | 293 | ekuOidsList = NULL; |
michael@0 | 294 | |
michael@0 | 295 | cleanup: |
michael@0 | 296 | |
michael@0 | 297 | PKIX_DECREF(ekuOid); |
michael@0 | 298 | PKIX_DECREF(ekuOidsList); |
michael@0 | 299 | |
michael@0 | 300 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | #endif |
michael@0 | 304 | |
michael@0 | 305 | /* |
michael@0 | 306 | * FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage |
michael@0 | 307 | * DESCRIPTION: |
michael@0 | 308 | * |
michael@0 | 309 | * Converts cert usage to pkix KU type and sets |
michael@0 | 310 | * converted data into PKIX_ProcessingParams object. It also sets |
michael@0 | 311 | * proper cert usage into nsscontext object. |
michael@0 | 312 | * |
michael@0 | 313 | * PARAMETERS: |
michael@0 | 314 | * "procParams" |
michael@0 | 315 | * Pointer to PKIX_ProcessingParams used during validation. |
michael@0 | 316 | * "requiredCertUsage" |
michael@0 | 317 | * Required certificate usages the certificate and chain is built and |
michael@0 | 318 | * validated for. |
michael@0 | 319 | * "requiredKeyUsage" |
michael@0 | 320 | * Request additional key usages the certificate should be validated for. |
michael@0 | 321 | * "plContext" |
michael@0 | 322 | * Platform-specific context pointer. |
michael@0 | 323 | * THREAD SAFETY: |
michael@0 | 324 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 325 | * RETURNS: |
michael@0 | 326 | * Returns NULL if the function succeeds. |
michael@0 | 327 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 328 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 329 | */ |
michael@0 | 330 | static PKIX_Error* |
michael@0 | 331 | cert_ProcessingParamsSetKeyAndCertUsage( |
michael@0 | 332 | PKIX_ProcessingParams *procParams, |
michael@0 | 333 | SECCertUsage requiredCertUsage, |
michael@0 | 334 | PRUint32 requiredKeyUsages, |
michael@0 | 335 | void *plContext) |
michael@0 | 336 | { |
michael@0 | 337 | PKIX_CertSelector *certSelector = NULL; |
michael@0 | 338 | PKIX_ComCertSelParams *certSelParams = NULL; |
michael@0 | 339 | PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext*)plContext; |
michael@0 | 340 | |
michael@0 | 341 | PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage"); |
michael@0 | 342 | PKIX_NULLCHECK_TWO(procParams, nssContext); |
michael@0 | 343 | |
michael@0 | 344 | PKIX_CHECK( |
michael@0 | 345 | pkix_pl_NssContext_SetCertUsage( |
michael@0 | 346 | ((SECCertificateUsage)1) << requiredCertUsage, nssContext), |
michael@0 | 347 | PKIX_NSSCONTEXTSETCERTUSAGEFAILED); |
michael@0 | 348 | |
michael@0 | 349 | if (requiredKeyUsages) { |
michael@0 | 350 | PKIX_CHECK( |
michael@0 | 351 | PKIX_ProcessingParams_GetTargetCertConstraints(procParams, |
michael@0 | 352 | &certSelector, plContext), |
michael@0 | 353 | PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); |
michael@0 | 354 | |
michael@0 | 355 | PKIX_CHECK( |
michael@0 | 356 | PKIX_CertSelector_GetCommonCertSelectorParams(certSelector, |
michael@0 | 357 | &certSelParams, plContext), |
michael@0 | 358 | PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); |
michael@0 | 359 | |
michael@0 | 360 | |
michael@0 | 361 | PKIX_CHECK( |
michael@0 | 362 | PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages, |
michael@0 | 363 | plContext), |
michael@0 | 364 | PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED); |
michael@0 | 365 | } |
michael@0 | 366 | cleanup: |
michael@0 | 367 | PKIX_DECREF(certSelector); |
michael@0 | 368 | PKIX_DECREF(certSelParams); |
michael@0 | 369 | |
michael@0 | 370 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 371 | } |
michael@0 | 372 | |
michael@0 | 373 | /* |
michael@0 | 374 | * Unused parameters: |
michael@0 | 375 | * |
michael@0 | 376 | * CERTCertList *initialChain, |
michael@0 | 377 | * CERTCertStores certStores, |
michael@0 | 378 | * CERTCertRevCheckers certRevCheckers, |
michael@0 | 379 | * CERTCertChainCheckers certChainCheckers, |
michael@0 | 380 | * SECItem *initPolicies, |
michael@0 | 381 | * PRBool policyQualifierRejected, |
michael@0 | 382 | * PRBool anyPolicyInhibited, |
michael@0 | 383 | * PRBool reqExplicitPolicy, |
michael@0 | 384 | * PRBool policyMappingInhibited, |
michael@0 | 385 | * PKIX_CertSelector certConstraints, |
michael@0 | 386 | */ |
michael@0 | 387 | |
michael@0 | 388 | /* |
michael@0 | 389 | * FUNCTION: cert_CreatePkixProcessingParams |
michael@0 | 390 | * DESCRIPTION: |
michael@0 | 391 | * |
michael@0 | 392 | * Creates and fills in PKIX_ProcessingParams structure to be used |
michael@0 | 393 | * for certificate chain building. |
michael@0 | 394 | * |
michael@0 | 395 | * PARAMETERS: |
michael@0 | 396 | * "cert" |
michael@0 | 397 | * Pointer to the CERTCertificate: the leaf certificate of a chain. |
michael@0 | 398 | * "time" |
michael@0 | 399 | * Validity time. |
michael@0 | 400 | * "wincx" |
michael@0 | 401 | * Nss db password token. |
michael@0 | 402 | * "useArena" |
michael@0 | 403 | * Flags to use arena for data allocation during chain building process. |
michael@0 | 404 | * "pprocParams" |
michael@0 | 405 | * Address to return created processing parameters. |
michael@0 | 406 | * "plContext" |
michael@0 | 407 | * Platform-specific context pointer. |
michael@0 | 408 | * THREAD SAFETY: |
michael@0 | 409 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 410 | * RETURNS: |
michael@0 | 411 | * Returns NULL if the function succeeds. |
michael@0 | 412 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 413 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 414 | */ |
michael@0 | 415 | static PKIX_Error* |
michael@0 | 416 | cert_CreatePkixProcessingParams( |
michael@0 | 417 | CERTCertificate *cert, |
michael@0 | 418 | PRBool checkSig, /* not used yet. See bug 391476 */ |
michael@0 | 419 | PRTime time, |
michael@0 | 420 | void *wincx, |
michael@0 | 421 | PRBool useArena, |
michael@0 | 422 | PRBool disableOCSPRemoteFetching, |
michael@0 | 423 | PKIX_ProcessingParams **pprocParams, |
michael@0 | 424 | void **pplContext) |
michael@0 | 425 | { |
michael@0 | 426 | PKIX_List *anchors = NULL; |
michael@0 | 427 | PKIX_PL_Cert *targetCert = NULL; |
michael@0 | 428 | PKIX_PL_Date *date = NULL; |
michael@0 | 429 | PKIX_ProcessingParams *procParams = NULL; |
michael@0 | 430 | PKIX_CertSelector *certSelector = NULL; |
michael@0 | 431 | PKIX_ComCertSelParams *certSelParams = NULL; |
michael@0 | 432 | PKIX_CertStore *certStore = NULL; |
michael@0 | 433 | PKIX_List *certStores = NULL; |
michael@0 | 434 | PKIX_RevocationChecker *revChecker = NULL; |
michael@0 | 435 | PKIX_UInt32 methodFlags = 0; |
michael@0 | 436 | void *plContext = NULL; |
michael@0 | 437 | CERTStatusConfig *statusConfig = NULL; |
michael@0 | 438 | |
michael@0 | 439 | PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams"); |
michael@0 | 440 | PKIX_NULLCHECK_TWO(cert, pprocParams); |
michael@0 | 441 | |
michael@0 | 442 | PKIX_CHECK( |
michael@0 | 443 | PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext), |
michael@0 | 444 | PKIX_NSSCONTEXTCREATEFAILED); |
michael@0 | 445 | |
michael@0 | 446 | *pplContext = plContext; |
michael@0 | 447 | |
michael@0 | 448 | #ifdef PKIX_NOTDEF |
michael@0 | 449 | /* Functions should be implemented in patch for 390532 */ |
michael@0 | 450 | PKIX_CHECK( |
michael@0 | 451 | pkix_pl_NssContext_SetCertSignatureCheck(checkSig, |
michael@0 | 452 | (PKIX_PL_NssContext*)plContext), |
michael@0 | 453 | PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED); |
michael@0 | 454 | |
michael@0 | 455 | #endif /* PKIX_NOTDEF */ |
michael@0 | 456 | |
michael@0 | 457 | PKIX_CHECK( |
michael@0 | 458 | PKIX_ProcessingParams_Create(&procParams, plContext), |
michael@0 | 459 | PKIX_PROCESSINGPARAMSCREATEFAILED); |
michael@0 | 460 | |
michael@0 | 461 | PKIX_CHECK( |
michael@0 | 462 | PKIX_ComCertSelParams_Create(&certSelParams, plContext), |
michael@0 | 463 | PKIX_COMCERTSELPARAMSCREATEFAILED); |
michael@0 | 464 | |
michael@0 | 465 | PKIX_CHECK( |
michael@0 | 466 | PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext), |
michael@0 | 467 | PKIX_CERTCREATEWITHNSSCERTFAILED); |
michael@0 | 468 | |
michael@0 | 469 | PKIX_CHECK( |
michael@0 | 470 | PKIX_ComCertSelParams_SetCertificate(certSelParams, |
michael@0 | 471 | targetCert, plContext), |
michael@0 | 472 | PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED); |
michael@0 | 473 | |
michael@0 | 474 | PKIX_CHECK( |
michael@0 | 475 | PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext), |
michael@0 | 476 | PKIX_COULDNOTCREATECERTSELECTOROBJECT); |
michael@0 | 477 | |
michael@0 | 478 | PKIX_CHECK( |
michael@0 | 479 | PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, |
michael@0 | 480 | certSelParams, plContext), |
michael@0 | 481 | PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); |
michael@0 | 482 | |
michael@0 | 483 | PKIX_CHECK( |
michael@0 | 484 | PKIX_ProcessingParams_SetTargetCertConstraints(procParams, |
michael@0 | 485 | certSelector, plContext), |
michael@0 | 486 | PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED); |
michael@0 | 487 | |
michael@0 | 488 | /* Turn off quialification of target cert since leaf cert is |
michael@0 | 489 | * already check for date validity, key usages and extended |
michael@0 | 490 | * key usages. */ |
michael@0 | 491 | PKIX_CHECK( |
michael@0 | 492 | PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE, |
michael@0 | 493 | plContext), |
michael@0 | 494 | PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED); |
michael@0 | 495 | |
michael@0 | 496 | PKIX_CHECK( |
michael@0 | 497 | PKIX_PL_Pk11CertStore_Create(&certStore, plContext), |
michael@0 | 498 | PKIX_PK11CERTSTORECREATEFAILED); |
michael@0 | 499 | |
michael@0 | 500 | PKIX_CHECK( |
michael@0 | 501 | PKIX_List_Create(&certStores, plContext), |
michael@0 | 502 | PKIX_UNABLETOCREATELIST); |
michael@0 | 503 | |
michael@0 | 504 | PKIX_CHECK( |
michael@0 | 505 | PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, |
michael@0 | 506 | plContext), |
michael@0 | 507 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 508 | |
michael@0 | 509 | PKIX_CHECK( |
michael@0 | 510 | PKIX_ProcessingParams_SetCertStores(procParams, certStores, |
michael@0 | 511 | plContext), |
michael@0 | 512 | PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED); |
michael@0 | 513 | |
michael@0 | 514 | PKIX_CHECK( |
michael@0 | 515 | PKIX_PL_Date_CreateFromPRTime(time, &date, plContext), |
michael@0 | 516 | PKIX_DATECREATEFROMPRTIMEFAILED); |
michael@0 | 517 | |
michael@0 | 518 | PKIX_CHECK( |
michael@0 | 519 | PKIX_ProcessingParams_SetDate(procParams, date, plContext), |
michael@0 | 520 | PKIX_PROCESSINGPARAMSSETDATEFAILED); |
michael@0 | 521 | |
michael@0 | 522 | PKIX_CHECK( |
michael@0 | 523 | PKIX_RevocationChecker_Create( |
michael@0 | 524 | PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST | |
michael@0 | 525 | PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT, |
michael@0 | 526 | PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST | |
michael@0 | 527 | PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT, |
michael@0 | 528 | &revChecker, plContext), |
michael@0 | 529 | PKIX_REVOCATIONCHECKERCREATEFAILED); |
michael@0 | 530 | |
michael@0 | 531 | PKIX_CHECK( |
michael@0 | 532 | PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker, |
michael@0 | 533 | plContext), |
michael@0 | 534 | PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED); |
michael@0 | 535 | |
michael@0 | 536 | /* CRL method flags */ |
michael@0 | 537 | methodFlags = |
michael@0 | 538 | PKIX_REV_M_TEST_USING_THIS_METHOD | |
michael@0 | 539 | PKIX_REV_M_FORBID_NETWORK_FETCHING | |
michael@0 | 540 | PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */ |
michael@0 | 541 | PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */ |
michael@0 | 542 | PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO; |
michael@0 | 543 | |
michael@0 | 544 | /* add CRL revocation method to check the leaf certificate */ |
michael@0 | 545 | PKIX_CHECK( |
michael@0 | 546 | PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, |
michael@0 | 547 | PKIX_RevocationMethod_CRL, methodFlags, |
michael@0 | 548 | 0, NULL, PKIX_TRUE, plContext), |
michael@0 | 549 | PKIX_REVOCATIONCHECKERADDMETHODFAILED); |
michael@0 | 550 | |
michael@0 | 551 | /* add CRL revocation method for other certs in the chain. */ |
michael@0 | 552 | PKIX_CHECK( |
michael@0 | 553 | PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, |
michael@0 | 554 | PKIX_RevocationMethod_CRL, methodFlags, |
michael@0 | 555 | 0, NULL, PKIX_FALSE, plContext), |
michael@0 | 556 | PKIX_REVOCATIONCHECKERADDMETHODFAILED); |
michael@0 | 557 | |
michael@0 | 558 | /* For compatibility with the old code, need to check that |
michael@0 | 559 | * statusConfig is set in the db handle and status checker |
michael@0 | 560 | * is defined befor allow ocsp status check on the leaf cert.*/ |
michael@0 | 561 | statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB()); |
michael@0 | 562 | if (statusConfig != NULL && statusConfig->statusChecker != NULL) { |
michael@0 | 563 | |
michael@0 | 564 | /* Enable OCSP revocation checking for the leaf cert. */ |
michael@0 | 565 | /* OCSP method flags */ |
michael@0 | 566 | methodFlags = |
michael@0 | 567 | PKIX_REV_M_TEST_USING_THIS_METHOD | |
michael@0 | 568 | PKIX_REV_M_ALLOW_NETWORK_FETCHING | /* 0 */ |
michael@0 | 569 | PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE | /* 0 */ |
michael@0 | 570 | PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */ |
michael@0 | 571 | PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */ |
michael@0 | 572 | PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO; |
michael@0 | 573 | |
michael@0 | 574 | /* Disabling ocsp fetching when checking the status |
michael@0 | 575 | * of ocsp response signer. Here and in the next if, |
michael@0 | 576 | * adjust flags for ocsp signer cert validation case. */ |
michael@0 | 577 | if (disableOCSPRemoteFetching) { |
michael@0 | 578 | methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING; |
michael@0 | 579 | } |
michael@0 | 580 | |
michael@0 | 581 | if (ocsp_FetchingFailureIsVerificationFailure() |
michael@0 | 582 | && !disableOCSPRemoteFetching) { |
michael@0 | 583 | methodFlags |= |
michael@0 | 584 | PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO; |
michael@0 | 585 | } |
michael@0 | 586 | |
michael@0 | 587 | /* add OCSP revocation method to check only the leaf certificate.*/ |
michael@0 | 588 | PKIX_CHECK( |
michael@0 | 589 | PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, |
michael@0 | 590 | PKIX_RevocationMethod_OCSP, methodFlags, |
michael@0 | 591 | 1, NULL, PKIX_TRUE, plContext), |
michael@0 | 592 | PKIX_REVOCATIONCHECKERADDMETHODFAILED); |
michael@0 | 593 | } |
michael@0 | 594 | |
michael@0 | 595 | PKIX_CHECK( |
michael@0 | 596 | PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE, |
michael@0 | 597 | plContext), |
michael@0 | 598 | PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED); |
michael@0 | 599 | |
michael@0 | 600 | PKIX_CHECK( |
michael@0 | 601 | PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE, |
michael@0 | 602 | plContext), |
michael@0 | 603 | PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED); |
michael@0 | 604 | |
michael@0 | 605 | PKIX_CHECK( |
michael@0 | 606 | PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE, |
michael@0 | 607 | plContext), |
michael@0 | 608 | PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED); |
michael@0 | 609 | |
michael@0 | 610 | *pprocParams = procParams; |
michael@0 | 611 | procParams = NULL; |
michael@0 | 612 | |
michael@0 | 613 | cleanup: |
michael@0 | 614 | PKIX_DECREF(anchors); |
michael@0 | 615 | PKIX_DECREF(targetCert); |
michael@0 | 616 | PKIX_DECREF(date); |
michael@0 | 617 | PKIX_DECREF(certSelector); |
michael@0 | 618 | PKIX_DECREF(certSelParams); |
michael@0 | 619 | PKIX_DECREF(certStore); |
michael@0 | 620 | PKIX_DECREF(certStores); |
michael@0 | 621 | PKIX_DECREF(procParams); |
michael@0 | 622 | PKIX_DECREF(revChecker); |
michael@0 | 623 | |
michael@0 | 624 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 625 | } |
michael@0 | 626 | |
michael@0 | 627 | /* |
michael@0 | 628 | * FUNCTION: cert_PkixToNssCertsChain |
michael@0 | 629 | * DESCRIPTION: |
michael@0 | 630 | * |
michael@0 | 631 | * Converts pkix cert list into nss cert list. |
michael@0 | 632 | * |
michael@0 | 633 | * PARAMETERS: |
michael@0 | 634 | * "pkixCertChain" |
michael@0 | 635 | * Pkix certificate list. |
michael@0 | 636 | * "pvalidChain" |
michael@0 | 637 | * An address of returned nss certificate list. |
michael@0 | 638 | * "plContext" |
michael@0 | 639 | * Platform-specific context pointer. |
michael@0 | 640 | * THREAD SAFETY: |
michael@0 | 641 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 642 | * RETURNS: |
michael@0 | 643 | * Returns NULL if the function succeeds. |
michael@0 | 644 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 645 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 646 | */ |
michael@0 | 647 | static PKIX_Error* |
michael@0 | 648 | cert_PkixToNssCertsChain( |
michael@0 | 649 | PKIX_List *pkixCertChain, |
michael@0 | 650 | CERTCertList **pvalidChain, |
michael@0 | 651 | void *plContext) |
michael@0 | 652 | { |
michael@0 | 653 | PLArenaPool *arena = NULL; |
michael@0 | 654 | CERTCertificate *nssCert = NULL; |
michael@0 | 655 | CERTCertList *validChain = NULL; |
michael@0 | 656 | PKIX_PL_Object *certItem = NULL; |
michael@0 | 657 | PKIX_UInt32 length = 0; |
michael@0 | 658 | PKIX_UInt32 i = 0; |
michael@0 | 659 | |
michael@0 | 660 | PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain"); |
michael@0 | 661 | PKIX_NULLCHECK_ONE(pvalidChain); |
michael@0 | 662 | |
michael@0 | 663 | if (pkixCertChain == NULL) { |
michael@0 | 664 | goto cleanup; |
michael@0 | 665 | } |
michael@0 | 666 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 667 | if (arena == NULL) { |
michael@0 | 668 | PKIX_ERROR(PKIX_OUTOFMEMORY); |
michael@0 | 669 | } |
michael@0 | 670 | validChain = (CERTCertList*)PORT_ArenaZAlloc(arena, sizeof(CERTCertList)); |
michael@0 | 671 | if (validChain == NULL) { |
michael@0 | 672 | PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); |
michael@0 | 673 | } |
michael@0 | 674 | PR_INIT_CLIST(&validChain->list); |
michael@0 | 675 | validChain->arena = arena; |
michael@0 | 676 | arena = NULL; |
michael@0 | 677 | |
michael@0 | 678 | PKIX_CHECK( |
michael@0 | 679 | PKIX_List_GetLength(pkixCertChain, &length, plContext), |
michael@0 | 680 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 681 | |
michael@0 | 682 | for (i = 0; i < length; i++){ |
michael@0 | 683 | CERTCertListNode *node = NULL; |
michael@0 | 684 | |
michael@0 | 685 | PKIX_CHECK( |
michael@0 | 686 | PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext), |
michael@0 | 687 | PKIX_LISTGETITEMFAILED); |
michael@0 | 688 | |
michael@0 | 689 | PKIX_CHECK( |
michael@0 | 690 | PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert*)certItem, &nssCert, |
michael@0 | 691 | plContext), |
michael@0 | 692 | PKIX_CERTGETCERTCERTIFICATEFAILED); |
michael@0 | 693 | |
michael@0 | 694 | node = |
michael@0 | 695 | (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena, |
michael@0 | 696 | sizeof(CERTCertListNode)); |
michael@0 | 697 | if ( node == NULL ) { |
michael@0 | 698 | PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); |
michael@0 | 699 | } |
michael@0 | 700 | |
michael@0 | 701 | PR_INSERT_BEFORE(&node->links, &validChain->list); |
michael@0 | 702 | |
michael@0 | 703 | node->cert = nssCert; |
michael@0 | 704 | nssCert = NULL; |
michael@0 | 705 | |
michael@0 | 706 | PKIX_DECREF(certItem); |
michael@0 | 707 | } |
michael@0 | 708 | |
michael@0 | 709 | *pvalidChain = validChain; |
michael@0 | 710 | |
michael@0 | 711 | cleanup: |
michael@0 | 712 | if (PKIX_ERROR_RECEIVED){ |
michael@0 | 713 | if (validChain) { |
michael@0 | 714 | CERT_DestroyCertList(validChain); |
michael@0 | 715 | } else if (arena) { |
michael@0 | 716 | PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 717 | } |
michael@0 | 718 | if (nssCert) { |
michael@0 | 719 | CERT_DestroyCertificate(nssCert); |
michael@0 | 720 | } |
michael@0 | 721 | } |
michael@0 | 722 | PKIX_DECREF(certItem); |
michael@0 | 723 | |
michael@0 | 724 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | |
michael@0 | 728 | /* |
michael@0 | 729 | * FUNCTION: cert_BuildAndValidateChain |
michael@0 | 730 | * DESCRIPTION: |
michael@0 | 731 | * |
michael@0 | 732 | * The function builds and validates a cert chain based on certificate |
michael@0 | 733 | * selection criterias from procParams. This function call PKIX_BuildChain |
michael@0 | 734 | * to accomplish chain building. If PKIX_BuildChain returns with incomplete |
michael@0 | 735 | * IO, the function waits with PR_Poll until the blocking IO is finished and |
michael@0 | 736 | * return control back to PKIX_BuildChain. |
michael@0 | 737 | * |
michael@0 | 738 | * PARAMETERS: |
michael@0 | 739 | * "procParams" |
michael@0 | 740 | * Processing parameters to be used during chain building. |
michael@0 | 741 | * "pResult" |
michael@0 | 742 | * Returned build result. |
michael@0 | 743 | * "pVerifyNode" |
michael@0 | 744 | * Returned pointed to verify node structure: the tree-like structure |
michael@0 | 745 | * that reports points of chain building failures. |
michael@0 | 746 | * "plContext" |
michael@0 | 747 | * Platform-specific context pointer. |
michael@0 | 748 | * THREAD SAFETY: |
michael@0 | 749 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 750 | * RETURNS: |
michael@0 | 751 | * Returns NULL if the function succeeds. |
michael@0 | 752 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 753 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 754 | */ |
michael@0 | 755 | static PKIX_Error* |
michael@0 | 756 | cert_BuildAndValidateChain( |
michael@0 | 757 | PKIX_ProcessingParams *procParams, |
michael@0 | 758 | PKIX_BuildResult **pResult, |
michael@0 | 759 | PKIX_VerifyNode **pVerifyNode, |
michael@0 | 760 | void *plContext) |
michael@0 | 761 | { |
michael@0 | 762 | PKIX_BuildResult *result = NULL; |
michael@0 | 763 | PKIX_VerifyNode *verifyNode = NULL; |
michael@0 | 764 | void *nbioContext = NULL; |
michael@0 | 765 | void *state = NULL; |
michael@0 | 766 | |
michael@0 | 767 | PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain"); |
michael@0 | 768 | PKIX_NULLCHECK_TWO(procParams, pResult); |
michael@0 | 769 | |
michael@0 | 770 | do { |
michael@0 | 771 | if (nbioContext && state) { |
michael@0 | 772 | /* PKIX-XXX: need to test functionality of NBIO handling in libPkix. |
michael@0 | 773 | * See bug 391180 */ |
michael@0 | 774 | PRInt32 filesReady = 0; |
michael@0 | 775 | PRPollDesc *pollDesc = (PRPollDesc*)nbioContext; |
michael@0 | 776 | filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 777 | if (filesReady <= 0) { |
michael@0 | 778 | PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM); |
michael@0 | 779 | } |
michael@0 | 780 | } |
michael@0 | 781 | |
michael@0 | 782 | PKIX_CHECK( |
michael@0 | 783 | PKIX_BuildChain(procParams, &nbioContext, &state, |
michael@0 | 784 | &result, &verifyNode, plContext), |
michael@0 | 785 | PKIX_UNABLETOBUILDCHAIN); |
michael@0 | 786 | |
michael@0 | 787 | } while (nbioContext && state); |
michael@0 | 788 | |
michael@0 | 789 | *pResult = result; |
michael@0 | 790 | |
michael@0 | 791 | cleanup: |
michael@0 | 792 | if (pVerifyNode) { |
michael@0 | 793 | *pVerifyNode = verifyNode; |
michael@0 | 794 | } |
michael@0 | 795 | |
michael@0 | 796 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 797 | } |
michael@0 | 798 | |
michael@0 | 799 | |
michael@0 | 800 | /* |
michael@0 | 801 | * FUNCTION: cert_PkixErrorToNssCode |
michael@0 | 802 | * DESCRIPTION: |
michael@0 | 803 | * |
michael@0 | 804 | * Converts pkix error(PKIX_Error) structure to PR error codes. |
michael@0 | 805 | * |
michael@0 | 806 | * PKIX-XXX to be implemented. See 391183. |
michael@0 | 807 | * |
michael@0 | 808 | * PARAMETERS: |
michael@0 | 809 | * "error" |
michael@0 | 810 | * Pkix error that will be converted. |
michael@0 | 811 | * "nssCode" |
michael@0 | 812 | * Corresponding nss error code. |
michael@0 | 813 | * "plContext" |
michael@0 | 814 | * Platform-specific context pointer. |
michael@0 | 815 | * THREAD SAFETY: |
michael@0 | 816 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 817 | * RETURNS: |
michael@0 | 818 | * Returns NULL if the function succeeds. |
michael@0 | 819 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 820 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 821 | */ |
michael@0 | 822 | static PKIX_Error * |
michael@0 | 823 | cert_PkixErrorToNssCode( |
michael@0 | 824 | PKIX_Error *error, |
michael@0 | 825 | SECErrorCodes *pNssErr, |
michael@0 | 826 | void *plContext) |
michael@0 | 827 | { |
michael@0 | 828 | int errLevel = 0; |
michael@0 | 829 | PKIX_Int32 nssErr = 0; |
michael@0 | 830 | PKIX_Error *errPtr = error; |
michael@0 | 831 | |
michael@0 | 832 | PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode"); |
michael@0 | 833 | PKIX_NULLCHECK_TWO(error, pNssErr); |
michael@0 | 834 | |
michael@0 | 835 | /* Loop until we find at least one error with non-null |
michael@0 | 836 | * plErr code, that is going to be nss error code. */ |
michael@0 | 837 | while (errPtr) { |
michael@0 | 838 | if (errPtr->plErr && !nssErr) { |
michael@0 | 839 | nssErr = errPtr->plErr; |
michael@0 | 840 | if (!pkixLog) break; |
michael@0 | 841 | } |
michael@0 | 842 | if (pkixLog) { |
michael@0 | 843 | #ifdef PKIX_ERROR_DESCRIPTION |
michael@0 | 844 | PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel, |
michael@0 | 845 | PKIX_ErrorText[errPtr->errCode])); |
michael@0 | 846 | #else |
michael@0 | 847 | PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel, |
michael@0 | 848 | errPtr->errCode)); |
michael@0 | 849 | #endif /* PKIX_ERROR_DESCRIPTION */ |
michael@0 | 850 | } |
michael@0 | 851 | errPtr = errPtr->cause; |
michael@0 | 852 | errLevel += 1; |
michael@0 | 853 | } |
michael@0 | 854 | PORT_Assert(nssErr); |
michael@0 | 855 | if (!nssErr) { |
michael@0 | 856 | *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL; |
michael@0 | 857 | } else { |
michael@0 | 858 | *pNssErr = nssErr; |
michael@0 | 859 | } |
michael@0 | 860 | |
michael@0 | 861 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 862 | } |
michael@0 | 863 | |
michael@0 | 864 | /* |
michael@0 | 865 | * FUNCTION: cert_GetLogFromVerifyNode |
michael@0 | 866 | * DESCRIPTION: |
michael@0 | 867 | * |
michael@0 | 868 | * Recursive function that converts verify node tree-like set of structures |
michael@0 | 869 | * to CERTVerifyLog. |
michael@0 | 870 | * |
michael@0 | 871 | * PARAMETERS: |
michael@0 | 872 | * "log" |
michael@0 | 873 | * Pointed to already allocated CERTVerifyLog structure. |
michael@0 | 874 | * "node" |
michael@0 | 875 | * A node of PKIX_VerifyNode tree. |
michael@0 | 876 | * "plContext" |
michael@0 | 877 | * Platform-specific context pointer. |
michael@0 | 878 | * THREAD SAFETY: |
michael@0 | 879 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 880 | * RETURNS: |
michael@0 | 881 | * Returns NULL if the function succeeds. |
michael@0 | 882 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 883 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 884 | */ |
michael@0 | 885 | static PKIX_Error * |
michael@0 | 886 | cert_GetLogFromVerifyNode( |
michael@0 | 887 | CERTVerifyLog *log, |
michael@0 | 888 | PKIX_VerifyNode *node, |
michael@0 | 889 | void *plContext) |
michael@0 | 890 | { |
michael@0 | 891 | PKIX_List *children = NULL; |
michael@0 | 892 | PKIX_VerifyNode *childNode = NULL; |
michael@0 | 893 | |
michael@0 | 894 | PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode"); |
michael@0 | 895 | |
michael@0 | 896 | children = node->children; |
michael@0 | 897 | |
michael@0 | 898 | if (children == NULL) { |
michael@0 | 899 | PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT; |
michael@0 | 900 | if (node->error && node->error->errCode != errCode) { |
michael@0 | 901 | #ifdef DEBUG_volkov |
michael@0 | 902 | char *string = pkix_Error2ASCII(node->error, plContext); |
michael@0 | 903 | fprintf(stderr, "Branch search finished with error: \t%s\n", string); |
michael@0 | 904 | PKIX_PL_Free(string, NULL); |
michael@0 | 905 | #endif |
michael@0 | 906 | if (log != NULL) { |
michael@0 | 907 | SECErrorCodes nssErrorCode = 0; |
michael@0 | 908 | CERTCertificate *cert = NULL; |
michael@0 | 909 | |
michael@0 | 910 | cert = node->verifyCert->nssCert; |
michael@0 | 911 | |
michael@0 | 912 | PKIX_CHECK( |
michael@0 | 913 | cert_PkixErrorToNssCode(node->error, &nssErrorCode, |
michael@0 | 914 | plContext), |
michael@0 | 915 | PKIX_GETPKIXERRORCODEFAILED); |
michael@0 | 916 | |
michael@0 | 917 | cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL); |
michael@0 | 918 | } |
michael@0 | 919 | } |
michael@0 | 920 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 921 | } else { |
michael@0 | 922 | PRUint32 i = 0; |
michael@0 | 923 | PKIX_UInt32 length = 0; |
michael@0 | 924 | |
michael@0 | 925 | PKIX_CHECK( |
michael@0 | 926 | PKIX_List_GetLength(children, &length, plContext), |
michael@0 | 927 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 928 | |
michael@0 | 929 | for (i = 0; i < length; i++){ |
michael@0 | 930 | |
michael@0 | 931 | PKIX_CHECK( |
michael@0 | 932 | PKIX_List_GetItem(children, i, (PKIX_PL_Object**)&childNode, |
michael@0 | 933 | plContext), |
michael@0 | 934 | PKIX_LISTGETITEMFAILED); |
michael@0 | 935 | |
michael@0 | 936 | PKIX_CHECK( |
michael@0 | 937 | cert_GetLogFromVerifyNode(log, childNode, plContext), |
michael@0 | 938 | PKIX_ERRORINRECURSIVEEQUALSCALL); |
michael@0 | 939 | |
michael@0 | 940 | PKIX_DECREF(childNode); |
michael@0 | 941 | } |
michael@0 | 942 | } |
michael@0 | 943 | |
michael@0 | 944 | cleanup: |
michael@0 | 945 | PKIX_DECREF(childNode); |
michael@0 | 946 | |
michael@0 | 947 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 948 | } |
michael@0 | 949 | |
michael@0 | 950 | /* |
michael@0 | 951 | * FUNCTION: cert_GetBuildResults |
michael@0 | 952 | * DESCRIPTION: |
michael@0 | 953 | * |
michael@0 | 954 | * Converts pkix build results to nss results. This function is called |
michael@0 | 955 | * regardless of build result. |
michael@0 | 956 | * |
michael@0 | 957 | * If it called after chain was successfully constructed, then it will |
michael@0 | 958 | * convert: |
michael@0 | 959 | * * pkix cert list that represent the chain to nss cert list |
michael@0 | 960 | * * trusted root the chain was anchored to nss certificate. |
michael@0 | 961 | * |
michael@0 | 962 | * In case of failure it will convert: |
michael@0 | 963 | * * pkix error to PR error code(will set it with PORT_SetError) |
michael@0 | 964 | * * pkix validation log to nss CERTVerifyLog |
michael@0 | 965 | * |
michael@0 | 966 | * PARAMETERS: |
michael@0 | 967 | * "buildResult" |
michael@0 | 968 | * Build results returned by PKIX_BuildChain. |
michael@0 | 969 | * "verifyNode" |
michael@0 | 970 | * Tree-like structure of chain building/validation failures |
michael@0 | 971 | * returned by PKIX_BuildChain. Ignored in case of success. |
michael@0 | 972 | * "error" |
michael@0 | 973 | * Final error returned by PKIX_BuildChain. Should be NULL in |
michael@0 | 974 | * case of success. |
michael@0 | 975 | * "log" |
michael@0 | 976 | * Address of pre-allocated(if not NULL) CERTVerifyLog structure. |
michael@0 | 977 | * "ptrustedRoot" |
michael@0 | 978 | * Address of returned trusted root the chain was anchored to. |
michael@0 | 979 | * "pvalidChain" |
michael@0 | 980 | * Address of returned valid chain. |
michael@0 | 981 | * "plContext" |
michael@0 | 982 | * Platform-specific context pointer. |
michael@0 | 983 | * THREAD SAFETY: |
michael@0 | 984 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 985 | * RETURNS: |
michael@0 | 986 | * Returns NULL if the function succeeds. |
michael@0 | 987 | * Returns a Cert Verify Error if the function fails in an unrecoverable way. |
michael@0 | 988 | * Returns a Fatal Error if the function fails in an unrecoverable way. |
michael@0 | 989 | */ |
michael@0 | 990 | static PKIX_Error* |
michael@0 | 991 | cert_GetBuildResults( |
michael@0 | 992 | PKIX_BuildResult *buildResult, |
michael@0 | 993 | PKIX_VerifyNode *verifyNode, |
michael@0 | 994 | PKIX_Error *error, |
michael@0 | 995 | CERTVerifyLog *log, |
michael@0 | 996 | CERTCertificate **ptrustedRoot, |
michael@0 | 997 | CERTCertList **pvalidChain, |
michael@0 | 998 | void *plContext) |
michael@0 | 999 | { |
michael@0 | 1000 | PKIX_ValidateResult *validResult = NULL; |
michael@0 | 1001 | CERTCertList *validChain = NULL; |
michael@0 | 1002 | CERTCertificate *trustedRoot = NULL; |
michael@0 | 1003 | PKIX_TrustAnchor *trustAnchor = NULL; |
michael@0 | 1004 | PKIX_PL_Cert *trustedCert = NULL; |
michael@0 | 1005 | PKIX_List *pkixCertChain = NULL; |
michael@0 | 1006 | #ifdef DEBUG_volkov |
michael@0 | 1007 | PKIX_Error *tmpPkixError = NULL; |
michael@0 | 1008 | #endif /* DEBUG */ |
michael@0 | 1009 | |
michael@0 | 1010 | PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults"); |
michael@0 | 1011 | if (buildResult == NULL && error == NULL) { |
michael@0 | 1012 | PKIX_ERROR(PKIX_NULLARGUMENT); |
michael@0 | 1013 | } |
michael@0 | 1014 | |
michael@0 | 1015 | if (error) { |
michael@0 | 1016 | SECErrorCodes nssErrorCode = 0; |
michael@0 | 1017 | #ifdef DEBUG_volkov |
michael@0 | 1018 | char *temp = pkix_Error2ASCII(error, plContext); |
michael@0 | 1019 | fprintf(stderr, "BUILD ERROR:\n%s\n", temp); |
michael@0 | 1020 | PKIX_PL_Free(temp, NULL); |
michael@0 | 1021 | #endif /* DEBUG */ |
michael@0 | 1022 | if (verifyNode) { |
michael@0 | 1023 | PKIX_Error *tmpError = |
michael@0 | 1024 | cert_GetLogFromVerifyNode(log, verifyNode, plContext); |
michael@0 | 1025 | if (tmpError) { |
michael@0 | 1026 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext); |
michael@0 | 1027 | } |
michael@0 | 1028 | } |
michael@0 | 1029 | cert_PkixErrorToNssCode(error, &nssErrorCode, plContext); |
michael@0 | 1030 | PORT_SetError(nssErrorCode); |
michael@0 | 1031 | goto cleanup; |
michael@0 | 1032 | } |
michael@0 | 1033 | |
michael@0 | 1034 | if (pvalidChain) { |
michael@0 | 1035 | PKIX_CHECK( |
michael@0 | 1036 | PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain, |
michael@0 | 1037 | plContext), |
michael@0 | 1038 | PKIX_BUILDRESULTGETCERTCHAINFAILED); |
michael@0 | 1039 | |
michael@0 | 1040 | #ifdef DEBUG_volkov |
michael@0 | 1041 | tmpPkixError = cert_PrintCertChain(pkixCertChain, plContext); |
michael@0 | 1042 | if (tmpPkixError) { |
michael@0 | 1043 | PKIX_PL_Object_DecRef((PKIX_PL_Object*)tmpPkixError, plContext); |
michael@0 | 1044 | } |
michael@0 | 1045 | #endif |
michael@0 | 1046 | |
michael@0 | 1047 | PKIX_CHECK( |
michael@0 | 1048 | cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext), |
michael@0 | 1049 | PKIX_CERTCHAINTONSSCHAINFAILED); |
michael@0 | 1050 | } |
michael@0 | 1051 | |
michael@0 | 1052 | if (ptrustedRoot) { |
michael@0 | 1053 | PKIX_CHECK( |
michael@0 | 1054 | PKIX_BuildResult_GetValidateResult(buildResult, &validResult, |
michael@0 | 1055 | plContext), |
michael@0 | 1056 | PKIX_BUILDRESULTGETVALIDATERESULTFAILED); |
michael@0 | 1057 | |
michael@0 | 1058 | PKIX_CHECK( |
michael@0 | 1059 | PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor, |
michael@0 | 1060 | plContext), |
michael@0 | 1061 | PKIX_VALIDATERESULTGETTRUSTANCHORFAILED); |
michael@0 | 1062 | |
michael@0 | 1063 | PKIX_CHECK( |
michael@0 | 1064 | PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert, |
michael@0 | 1065 | plContext), |
michael@0 | 1066 | PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); |
michael@0 | 1067 | |
michael@0 | 1068 | #ifdef DEBUG_volkov |
michael@0 | 1069 | if (pvalidChain == NULL) { |
michael@0 | 1070 | cert_PrintCert(trustedCert, plContext); |
michael@0 | 1071 | } |
michael@0 | 1072 | #endif |
michael@0 | 1073 | |
michael@0 | 1074 | PKIX_CHECK( |
michael@0 | 1075 | PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot, |
michael@0 | 1076 | plContext), |
michael@0 | 1077 | PKIX_CERTGETCERTCERTIFICATEFAILED); |
michael@0 | 1078 | } |
michael@0 | 1079 | |
michael@0 | 1080 | PORT_Assert(!PKIX_ERROR_RECEIVED); |
michael@0 | 1081 | |
michael@0 | 1082 | if (trustedRoot) { |
michael@0 | 1083 | *ptrustedRoot = trustedRoot; |
michael@0 | 1084 | } |
michael@0 | 1085 | if (validChain) { |
michael@0 | 1086 | *pvalidChain = validChain; |
michael@0 | 1087 | } |
michael@0 | 1088 | |
michael@0 | 1089 | cleanup: |
michael@0 | 1090 | if (PKIX_ERROR_RECEIVED) { |
michael@0 | 1091 | if (trustedRoot) { |
michael@0 | 1092 | CERT_DestroyCertificate(trustedRoot); |
michael@0 | 1093 | } |
michael@0 | 1094 | if (validChain) { |
michael@0 | 1095 | CERT_DestroyCertList(validChain); |
michael@0 | 1096 | } |
michael@0 | 1097 | } |
michael@0 | 1098 | PKIX_DECREF(trustAnchor); |
michael@0 | 1099 | PKIX_DECREF(trustedCert); |
michael@0 | 1100 | PKIX_DECREF(pkixCertChain); |
michael@0 | 1101 | PKIX_DECREF(validResult); |
michael@0 | 1102 | PKIX_DECREF(error); |
michael@0 | 1103 | PKIX_DECREF(verifyNode); |
michael@0 | 1104 | PKIX_DECREF(buildResult); |
michael@0 | 1105 | |
michael@0 | 1106 | PKIX_RETURN(CERTVFYPKIX); |
michael@0 | 1107 | } |
michael@0 | 1108 | |
michael@0 | 1109 | /* |
michael@0 | 1110 | * FUNCTION: cert_VerifyCertChainPkix |
michael@0 | 1111 | * DESCRIPTION: |
michael@0 | 1112 | * |
michael@0 | 1113 | * The main wrapper function that is called from CERT_VerifyCert and |
michael@0 | 1114 | * CERT_VerifyCACertForUsage functions to validate cert with libpkix. |
michael@0 | 1115 | * |
michael@0 | 1116 | * PARAMETERS: |
michael@0 | 1117 | * "cert" |
michael@0 | 1118 | * Leaf certificate of a chain we want to build. |
michael@0 | 1119 | * "checkSig" |
michael@0 | 1120 | * Certificate signatures will not be verified if this |
michael@0 | 1121 | * flag is set to PR_FALSE. |
michael@0 | 1122 | * "requiredUsage" |
michael@0 | 1123 | * Required usage for certificate and chain. |
michael@0 | 1124 | * "time" |
michael@0 | 1125 | * Validity time. |
michael@0 | 1126 | * "wincx" |
michael@0 | 1127 | * Nss database password token. |
michael@0 | 1128 | * "log" |
michael@0 | 1129 | * Address of already allocated CERTVerifyLog structure. Not |
michael@0 | 1130 | * used if NULL; |
michael@0 | 1131 | * "pSigerror" |
michael@0 | 1132 | * Address of PRBool. If not NULL, returns true is cert chain |
michael@0 | 1133 | * was invalidated because of bad certificate signature. |
michael@0 | 1134 | * "pRevoked" |
michael@0 | 1135 | * Address of PRBool. If not NULL, returns true is cert chain |
michael@0 | 1136 | * was invalidated because a revoked certificate was found in |
michael@0 | 1137 | * the chain. |
michael@0 | 1138 | * THREAD SAFETY: |
michael@0 | 1139 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1140 | * RETURNS: |
michael@0 | 1141 | * SECFailure is chain building process has failed. SECSuccess otherwise. |
michael@0 | 1142 | */ |
michael@0 | 1143 | SECStatus |
michael@0 | 1144 | cert_VerifyCertChainPkix( |
michael@0 | 1145 | CERTCertificate *cert, |
michael@0 | 1146 | PRBool checkSig, |
michael@0 | 1147 | SECCertUsage requiredUsage, |
michael@0 | 1148 | PRTime time, |
michael@0 | 1149 | void *wincx, |
michael@0 | 1150 | CERTVerifyLog *log, |
michael@0 | 1151 | PRBool *pSigerror, |
michael@0 | 1152 | PRBool *pRevoked) |
michael@0 | 1153 | { |
michael@0 | 1154 | PKIX_ProcessingParams *procParams = NULL; |
michael@0 | 1155 | PKIX_BuildResult *result = NULL; |
michael@0 | 1156 | PKIX_VerifyNode *verifyNode = NULL; |
michael@0 | 1157 | PKIX_Error *error = NULL; |
michael@0 | 1158 | |
michael@0 | 1159 | SECStatus rv = SECFailure; |
michael@0 | 1160 | void *plContext = NULL; |
michael@0 | 1161 | #ifdef DEBUG_volkov |
michael@0 | 1162 | CERTCertificate *trustedRoot = NULL; |
michael@0 | 1163 | CERTCertList *validChain = NULL; |
michael@0 | 1164 | #endif /* DEBUG */ |
michael@0 | 1165 | |
michael@0 | 1166 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 1167 | int leakedObjNum = 0; |
michael@0 | 1168 | int memLeakLoopCount = 0; |
michael@0 | 1169 | int objCountTable[PKIX_NUMTYPES]; |
michael@0 | 1170 | int fnInvLocalCount = 0; |
michael@0 | 1171 | PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine; |
michael@0 | 1172 | |
michael@0 | 1173 | if (usePKIXValidationEngine) { |
michael@0 | 1174 | /* current memory leak testing implementation does not allow |
michael@0 | 1175 | * to run simultaneous tests one the same or a different threads. |
michael@0 | 1176 | * Setting the variable to false, to make additional chain |
michael@0 | 1177 | * validations be handled by old nss. */ |
michael@0 | 1178 | usePKIXValidationEngine = PR_FALSE; |
michael@0 | 1179 | } |
michael@0 | 1180 | testStartFnStackPosition = 2; |
michael@0 | 1181 | fnStackNameArr[0] = "cert_VerifyCertChainPkix"; |
michael@0 | 1182 | fnStackInvCountArr[0] = 0; |
michael@0 | 1183 | PKIX_Boolean abortOnLeak = |
michael@0 | 1184 | (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? |
michael@0 | 1185 | PKIX_FALSE : PKIX_TRUE; |
michael@0 | 1186 | runningLeakTest = PKIX_TRUE; |
michael@0 | 1187 | |
michael@0 | 1188 | /* Prevent multi-threaded run of object leak test */ |
michael@0 | 1189 | fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount); |
michael@0 | 1190 | PORT_Assert(fnInvLocalCount == 1); |
michael@0 | 1191 | |
michael@0 | 1192 | do { |
michael@0 | 1193 | rv = SECFailure; |
michael@0 | 1194 | plContext = NULL; |
michael@0 | 1195 | procParams = NULL; |
michael@0 | 1196 | result = NULL; |
michael@0 | 1197 | verifyNode = NULL; |
michael@0 | 1198 | error = NULL; |
michael@0 | 1199 | #ifdef DEBUG_volkov |
michael@0 | 1200 | trustedRoot = NULL; |
michael@0 | 1201 | validChain = NULL; |
michael@0 | 1202 | #endif /* DEBUG */ |
michael@0 | 1203 | errorGenerated = PKIX_FALSE; |
michael@0 | 1204 | stackPosition = 0; |
michael@0 | 1205 | |
michael@0 | 1206 | if (leakedObjNum) { |
michael@0 | 1207 | pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); |
michael@0 | 1208 | } |
michael@0 | 1209 | memLeakLoopCount += 1; |
michael@0 | 1210 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 1211 | |
michael@0 | 1212 | error = |
michael@0 | 1213 | cert_CreatePkixProcessingParams(cert, checkSig, time, wincx, |
michael@0 | 1214 | PR_FALSE/*use arena*/, |
michael@0 | 1215 | requiredUsage == certUsageStatusResponder, |
michael@0 | 1216 | &procParams, &plContext); |
michael@0 | 1217 | if (error) { |
michael@0 | 1218 | goto cleanup; |
michael@0 | 1219 | } |
michael@0 | 1220 | |
michael@0 | 1221 | error = |
michael@0 | 1222 | cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0, |
michael@0 | 1223 | plContext); |
michael@0 | 1224 | if (error) { |
michael@0 | 1225 | goto cleanup; |
michael@0 | 1226 | } |
michael@0 | 1227 | |
michael@0 | 1228 | error = |
michael@0 | 1229 | cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext); |
michael@0 | 1230 | if (error) { |
michael@0 | 1231 | goto cleanup; |
michael@0 | 1232 | } |
michael@0 | 1233 | |
michael@0 | 1234 | if (pRevoked) { |
michael@0 | 1235 | /* Currently always PR_FALSE. Will be fixed as a part of 394077 */ |
michael@0 | 1236 | *pRevoked = PR_FALSE; |
michael@0 | 1237 | } |
michael@0 | 1238 | if (pSigerror) { |
michael@0 | 1239 | /* Currently always PR_FALSE. Will be fixed as a part of 394077 */ |
michael@0 | 1240 | *pSigerror = PR_FALSE; |
michael@0 | 1241 | } |
michael@0 | 1242 | rv = SECSuccess; |
michael@0 | 1243 | |
michael@0 | 1244 | cleanup: |
michael@0 | 1245 | error = cert_GetBuildResults(result, verifyNode, error, log, |
michael@0 | 1246 | #ifdef DEBUG_volkov |
michael@0 | 1247 | &trustedRoot, &validChain, |
michael@0 | 1248 | #else |
michael@0 | 1249 | NULL, NULL, |
michael@0 | 1250 | #endif /* DEBUG */ |
michael@0 | 1251 | plContext); |
michael@0 | 1252 | if (error) { |
michael@0 | 1253 | #ifdef DEBUG_volkov |
michael@0 | 1254 | char *temp = pkix_Error2ASCII(error, plContext); |
michael@0 | 1255 | fprintf(stderr, "GET BUILD RES ERRORS:\n%s\n", temp); |
michael@0 | 1256 | PKIX_PL_Free(temp, NULL); |
michael@0 | 1257 | #endif /* DEBUG */ |
michael@0 | 1258 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 1259 | } |
michael@0 | 1260 | #ifdef DEBUG_volkov |
michael@0 | 1261 | if (trustedRoot) { |
michael@0 | 1262 | CERT_DestroyCertificate(trustedRoot); |
michael@0 | 1263 | } |
michael@0 | 1264 | if (validChain) { |
michael@0 | 1265 | CERT_DestroyCertList(validChain); |
michael@0 | 1266 | } |
michael@0 | 1267 | #endif /* DEBUG */ |
michael@0 | 1268 | if (procParams) { |
michael@0 | 1269 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext); |
michael@0 | 1270 | } |
michael@0 | 1271 | if (plContext) { |
michael@0 | 1272 | PKIX_PL_NssContext_Destroy(plContext); |
michael@0 | 1273 | } |
michael@0 | 1274 | |
michael@0 | 1275 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 1276 | leakedObjNum = |
michael@0 | 1277 | pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL); |
michael@0 | 1278 | |
michael@0 | 1279 | if (pkixLog && leakedObjNum) { |
michael@0 | 1280 | PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d." |
michael@0 | 1281 | "Stack %s\n", memLeakLoopCount, errorFnStackString)); |
michael@0 | 1282 | } |
michael@0 | 1283 | PR_Free(errorFnStackString); |
michael@0 | 1284 | errorFnStackString = NULL; |
michael@0 | 1285 | if (abortOnLeak) { |
michael@0 | 1286 | PORT_Assert(leakedObjNum == 0); |
michael@0 | 1287 | } |
michael@0 | 1288 | |
michael@0 | 1289 | } while (errorGenerated); |
michael@0 | 1290 | |
michael@0 | 1291 | runningLeakTest = PKIX_FALSE; |
michael@0 | 1292 | PR_ATOMIC_DECREMENT(¶llelFnInvocationCount); |
michael@0 | 1293 | usePKIXValidationEngine = savedUsePkixEngFlag; |
michael@0 | 1294 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 1295 | |
michael@0 | 1296 | return rv; |
michael@0 | 1297 | } |
michael@0 | 1298 | |
michael@0 | 1299 | PKIX_CertSelector * |
michael@0 | 1300 | cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext) |
michael@0 | 1301 | { |
michael@0 | 1302 | PKIX_ComCertSelParams *certSelParams = NULL; |
michael@0 | 1303 | PKIX_CertSelector *certSelector = NULL; |
michael@0 | 1304 | PKIX_CertSelector *r= NULL; |
michael@0 | 1305 | PKIX_PL_Cert *eeCert = NULL; |
michael@0 | 1306 | PKIX_Error *error = NULL; |
michael@0 | 1307 | |
michael@0 | 1308 | error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext); |
michael@0 | 1309 | if (error != NULL) goto cleanup; |
michael@0 | 1310 | |
michael@0 | 1311 | error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext); |
michael@0 | 1312 | if (error != NULL) goto cleanup; |
michael@0 | 1313 | |
michael@0 | 1314 | error = PKIX_ComCertSelParams_Create(&certSelParams, plContext); |
michael@0 | 1315 | if (error != NULL) goto cleanup; |
michael@0 | 1316 | |
michael@0 | 1317 | error = PKIX_ComCertSelParams_SetCertificate( |
michael@0 | 1318 | certSelParams, eeCert, plContext); |
michael@0 | 1319 | if (error != NULL) goto cleanup; |
michael@0 | 1320 | |
michael@0 | 1321 | error = PKIX_CertSelector_SetCommonCertSelectorParams |
michael@0 | 1322 | (certSelector, certSelParams, plContext); |
michael@0 | 1323 | if (error != NULL) goto cleanup; |
michael@0 | 1324 | |
michael@0 | 1325 | error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext); |
michael@0 | 1326 | if (error == NULL) r = certSelector; |
michael@0 | 1327 | |
michael@0 | 1328 | cleanup: |
michael@0 | 1329 | if (certSelParams != NULL) |
michael@0 | 1330 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext); |
michael@0 | 1331 | |
michael@0 | 1332 | if (eeCert != NULL) |
michael@0 | 1333 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext); |
michael@0 | 1334 | |
michael@0 | 1335 | if (certSelector != NULL) |
michael@0 | 1336 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext); |
michael@0 | 1337 | |
michael@0 | 1338 | if (error != NULL) { |
michael@0 | 1339 | SECErrorCodes nssErr; |
michael@0 | 1340 | |
michael@0 | 1341 | cert_PkixErrorToNssCode(error, &nssErr, plContext); |
michael@0 | 1342 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 1343 | PORT_SetError(nssErr); |
michael@0 | 1344 | } |
michael@0 | 1345 | |
michael@0 | 1346 | return r; |
michael@0 | 1347 | } |
michael@0 | 1348 | |
michael@0 | 1349 | static PKIX_List * |
michael@0 | 1350 | cert_GetCertStores(void *plContext) |
michael@0 | 1351 | { |
michael@0 | 1352 | PKIX_CertStore *certStore = NULL; |
michael@0 | 1353 | PKIX_List *certStores = NULL; |
michael@0 | 1354 | PKIX_List *r = NULL; |
michael@0 | 1355 | PKIX_Error *error = NULL; |
michael@0 | 1356 | |
michael@0 | 1357 | error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext); |
michael@0 | 1358 | if (error != NULL) goto cleanup; |
michael@0 | 1359 | |
michael@0 | 1360 | error = PKIX_List_Create(&certStores, plContext); |
michael@0 | 1361 | if (error != NULL) goto cleanup; |
michael@0 | 1362 | |
michael@0 | 1363 | error = PKIX_List_AppendItem( certStores, |
michael@0 | 1364 | (PKIX_PL_Object *)certStore, plContext); |
michael@0 | 1365 | if (error != NULL) goto cleanup; |
michael@0 | 1366 | |
michael@0 | 1367 | error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext); |
michael@0 | 1368 | if (error == NULL) r = certStores; |
michael@0 | 1369 | |
michael@0 | 1370 | cleanup: |
michael@0 | 1371 | if (certStores != NULL) |
michael@0 | 1372 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext); |
michael@0 | 1373 | |
michael@0 | 1374 | if (certStore != NULL) |
michael@0 | 1375 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext); |
michael@0 | 1376 | |
michael@0 | 1377 | if (error != NULL) { |
michael@0 | 1378 | SECErrorCodes nssErr; |
michael@0 | 1379 | |
michael@0 | 1380 | cert_PkixErrorToNssCode(error, &nssErr, plContext); |
michael@0 | 1381 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 1382 | PORT_SetError(nssErr); |
michael@0 | 1383 | } |
michael@0 | 1384 | |
michael@0 | 1385 | return r; |
michael@0 | 1386 | } |
michael@0 | 1387 | |
michael@0 | 1388 | |
michael@0 | 1389 | struct fake_PKIX_PL_CertStruct { |
michael@0 | 1390 | CERTCertificate *nssCert; |
michael@0 | 1391 | }; |
michael@0 | 1392 | |
michael@0 | 1393 | /* This needs to be part of the PKIX_PL_* */ |
michael@0 | 1394 | /* This definitely needs to go away, and be replaced with |
michael@0 | 1395 | a real accessor function in PKIX */ |
michael@0 | 1396 | static CERTCertificate * |
michael@0 | 1397 | cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert) |
michael@0 | 1398 | { |
michael@0 | 1399 | struct fake_PKIX_PL_CertStruct *fcert = NULL; |
michael@0 | 1400 | |
michael@0 | 1401 | fcert = (struct fake_PKIX_PL_CertStruct*)pkix_cert; |
michael@0 | 1402 | |
michael@0 | 1403 | return CERT_DupCertificate(fcert->nssCert); |
michael@0 | 1404 | } |
michael@0 | 1405 | |
michael@0 | 1406 | PKIX_List *cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext) |
michael@0 | 1407 | { |
michael@0 | 1408 | PKIX_List *r = NULL; |
michael@0 | 1409 | PKIX_List *policyList = NULL; |
michael@0 | 1410 | PKIX_PL_OID *policyOID = NULL; |
michael@0 | 1411 | PKIX_Error *error = NULL; |
michael@0 | 1412 | int i; |
michael@0 | 1413 | |
michael@0 | 1414 | error = PKIX_List_Create(&policyList, plContext); |
michael@0 | 1415 | if (error != NULL) { |
michael@0 | 1416 | goto cleanup; |
michael@0 | 1417 | } |
michael@0 | 1418 | |
michael@0 | 1419 | for (i=0; i<oidCount; i++) { |
michael@0 | 1420 | error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext); |
michael@0 | 1421 | if (error) { |
michael@0 | 1422 | goto cleanup; |
michael@0 | 1423 | } |
michael@0 | 1424 | error = PKIX_List_AppendItem(policyList, |
michael@0 | 1425 | (PKIX_PL_Object *)policyOID, plContext); |
michael@0 | 1426 | if (error != NULL) { |
michael@0 | 1427 | goto cleanup; |
michael@0 | 1428 | } |
michael@0 | 1429 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext); |
michael@0 | 1430 | policyOID = NULL; |
michael@0 | 1431 | } |
michael@0 | 1432 | |
michael@0 | 1433 | error = PKIX_List_SetImmutable(policyList, plContext); |
michael@0 | 1434 | if (error != NULL) goto cleanup; |
michael@0 | 1435 | |
michael@0 | 1436 | error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext); |
michael@0 | 1437 | if (error == NULL) r = policyList; |
michael@0 | 1438 | |
michael@0 | 1439 | cleanup: |
michael@0 | 1440 | if (policyOID != NULL) { |
michael@0 | 1441 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext); |
michael@0 | 1442 | } |
michael@0 | 1443 | if (policyList != NULL) { |
michael@0 | 1444 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext); |
michael@0 | 1445 | } |
michael@0 | 1446 | if (error != NULL) { |
michael@0 | 1447 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 1448 | } |
michael@0 | 1449 | |
michael@0 | 1450 | return r; |
michael@0 | 1451 | } |
michael@0 | 1452 | |
michael@0 | 1453 | CERTValOutParam * |
michael@0 | 1454 | cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t) |
michael@0 | 1455 | { |
michael@0 | 1456 | CERTValOutParam *i; |
michael@0 | 1457 | if (params == NULL) { |
michael@0 | 1458 | return NULL; |
michael@0 | 1459 | } |
michael@0 | 1460 | for (i = params; i->type != cert_po_end; i++) { |
michael@0 | 1461 | if (i->type == t) { |
michael@0 | 1462 | return i; |
michael@0 | 1463 | } |
michael@0 | 1464 | } |
michael@0 | 1465 | return NULL; |
michael@0 | 1466 | } |
michael@0 | 1467 | |
michael@0 | 1468 | |
michael@0 | 1469 | static PKIX_Error* |
michael@0 | 1470 | setRevocationMethod(PKIX_RevocationChecker *revChecker, |
michael@0 | 1471 | PKIX_ProcessingParams *procParams, |
michael@0 | 1472 | const CERTRevocationTests *revTest, |
michael@0 | 1473 | CERTRevocationMethodIndex certRevMethod, |
michael@0 | 1474 | PKIX_RevocationMethodType pkixRevMethod, |
michael@0 | 1475 | PKIX_Boolean verifyResponderUsages, |
michael@0 | 1476 | PKIX_Boolean isLeafTest, |
michael@0 | 1477 | void *plContext) |
michael@0 | 1478 | { |
michael@0 | 1479 | PKIX_UInt32 methodFlags = 0; |
michael@0 | 1480 | PKIX_Error *error = NULL; |
michael@0 | 1481 | int priority = 0; |
michael@0 | 1482 | |
michael@0 | 1483 | if (revTest->number_of_defined_methods <= certRevMethod) { |
michael@0 | 1484 | return NULL; |
michael@0 | 1485 | } |
michael@0 | 1486 | if (revTest->preferred_methods) { |
michael@0 | 1487 | int i = 0; |
michael@0 | 1488 | for (;i < revTest->number_of_preferred_methods;i++) { |
michael@0 | 1489 | if (revTest->preferred_methods[i] == certRevMethod) |
michael@0 | 1490 | break; |
michael@0 | 1491 | } |
michael@0 | 1492 | priority = i; |
michael@0 | 1493 | } |
michael@0 | 1494 | methodFlags = revTest->cert_rev_flags_per_method[certRevMethod]; |
michael@0 | 1495 | if (verifyResponderUsages && |
michael@0 | 1496 | pkixRevMethod == PKIX_RevocationMethod_OCSP) { |
michael@0 | 1497 | methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING; |
michael@0 | 1498 | } |
michael@0 | 1499 | error = |
michael@0 | 1500 | PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams, |
michael@0 | 1501 | pkixRevMethod, methodFlags, |
michael@0 | 1502 | priority, NULL, |
michael@0 | 1503 | isLeafTest, plContext); |
michael@0 | 1504 | return error; |
michael@0 | 1505 | } |
michael@0 | 1506 | |
michael@0 | 1507 | |
michael@0 | 1508 | SECStatus |
michael@0 | 1509 | cert_pkixSetParam(PKIX_ProcessingParams *procParams, |
michael@0 | 1510 | const CERTValInParam *param, void *plContext) |
michael@0 | 1511 | { |
michael@0 | 1512 | PKIX_Error * error = NULL; |
michael@0 | 1513 | SECStatus r=SECSuccess; |
michael@0 | 1514 | PKIX_PL_Date *date = NULL; |
michael@0 | 1515 | PKIX_List *policyOIDList = NULL; |
michael@0 | 1516 | PKIX_List *certListPkix = NULL; |
michael@0 | 1517 | const CERTRevocationFlags *flags; |
michael@0 | 1518 | SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS; |
michael@0 | 1519 | const CERTCertList *certList = NULL; |
michael@0 | 1520 | CERTCertListNode *node; |
michael@0 | 1521 | PKIX_PL_Cert *certPkix = NULL; |
michael@0 | 1522 | PKIX_TrustAnchor *trustAnchor = NULL; |
michael@0 | 1523 | PKIX_PL_Date *revDate = NULL; |
michael@0 | 1524 | PKIX_RevocationChecker *revChecker = NULL; |
michael@0 | 1525 | PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext; |
michael@0 | 1526 | |
michael@0 | 1527 | /* XXX we need a way to map generic PKIX error to generic NSS errors */ |
michael@0 | 1528 | |
michael@0 | 1529 | switch (param->type) { |
michael@0 | 1530 | |
michael@0 | 1531 | case cert_pi_policyOID: |
michael@0 | 1532 | |
michael@0 | 1533 | /* needed? */ |
michael@0 | 1534 | error = PKIX_ProcessingParams_SetExplicitPolicyRequired( |
michael@0 | 1535 | procParams, PKIX_TRUE, plContext); |
michael@0 | 1536 | |
michael@0 | 1537 | if (error != NULL) { |
michael@0 | 1538 | break; |
michael@0 | 1539 | } |
michael@0 | 1540 | |
michael@0 | 1541 | policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids, |
michael@0 | 1542 | param->value.arraySize,plContext); |
michael@0 | 1543 | if (policyOIDList == NULL) { |
michael@0 | 1544 | r = SECFailure; |
michael@0 | 1545 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 1546 | break; |
michael@0 | 1547 | } |
michael@0 | 1548 | |
michael@0 | 1549 | error = PKIX_ProcessingParams_SetInitialPolicies( |
michael@0 | 1550 | procParams,policyOIDList,plContext); |
michael@0 | 1551 | break; |
michael@0 | 1552 | |
michael@0 | 1553 | case cert_pi_date: |
michael@0 | 1554 | if (param->value.scalar.time == 0) { |
michael@0 | 1555 | error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext); |
michael@0 | 1556 | if (error != NULL) { |
michael@0 | 1557 | errCode = SEC_ERROR_INVALID_TIME; |
michael@0 | 1558 | break; |
michael@0 | 1559 | } |
michael@0 | 1560 | } else { |
michael@0 | 1561 | error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time, |
michael@0 | 1562 | &date, plContext); |
michael@0 | 1563 | if (error != NULL) { |
michael@0 | 1564 | errCode = SEC_ERROR_INVALID_TIME; |
michael@0 | 1565 | break; |
michael@0 | 1566 | } |
michael@0 | 1567 | } |
michael@0 | 1568 | |
michael@0 | 1569 | error = PKIX_ProcessingParams_SetDate(procParams, date, plContext); |
michael@0 | 1570 | if (error != NULL) { |
michael@0 | 1571 | errCode = SEC_ERROR_INVALID_TIME; |
michael@0 | 1572 | } |
michael@0 | 1573 | break; |
michael@0 | 1574 | |
michael@0 | 1575 | case cert_pi_revocationFlags: |
michael@0 | 1576 | { |
michael@0 | 1577 | PKIX_UInt32 leafIMFlags = 0; |
michael@0 | 1578 | PKIX_UInt32 chainIMFlags = 0; |
michael@0 | 1579 | PKIX_Boolean validatingResponderCert = PKIX_FALSE; |
michael@0 | 1580 | |
michael@0 | 1581 | flags = param->value.pointer.revocation; |
michael@0 | 1582 | if (!flags) { |
michael@0 | 1583 | PORT_SetError(errCode); |
michael@0 | 1584 | r = SECFailure; |
michael@0 | 1585 | break; |
michael@0 | 1586 | } |
michael@0 | 1587 | |
michael@0 | 1588 | leafIMFlags = |
michael@0 | 1589 | flags->leafTests.cert_rev_method_independent_flags; |
michael@0 | 1590 | chainIMFlags = |
michael@0 | 1591 | flags->chainTests.cert_rev_method_independent_flags; |
michael@0 | 1592 | |
michael@0 | 1593 | error = |
michael@0 | 1594 | PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags, |
michael@0 | 1595 | &revChecker, plContext); |
michael@0 | 1596 | if (error) { |
michael@0 | 1597 | break; |
michael@0 | 1598 | } |
michael@0 | 1599 | |
michael@0 | 1600 | error = |
michael@0 | 1601 | PKIX_ProcessingParams_SetRevocationChecker(procParams, |
michael@0 | 1602 | revChecker, plContext); |
michael@0 | 1603 | if (error) { |
michael@0 | 1604 | break; |
michael@0 | 1605 | } |
michael@0 | 1606 | |
michael@0 | 1607 | if (((PKIX_PL_NssContext*)plContext)->certificateUsage & |
michael@0 | 1608 | certificateUsageStatusResponder) { |
michael@0 | 1609 | validatingResponderCert = PKIX_TRUE; |
michael@0 | 1610 | } |
michael@0 | 1611 | |
michael@0 | 1612 | error = setRevocationMethod(revChecker, |
michael@0 | 1613 | procParams, &flags->leafTests, |
michael@0 | 1614 | cert_revocation_method_crl, |
michael@0 | 1615 | PKIX_RevocationMethod_CRL, |
michael@0 | 1616 | validatingResponderCert, |
michael@0 | 1617 | PKIX_TRUE, plContext); |
michael@0 | 1618 | if (error) { |
michael@0 | 1619 | break; |
michael@0 | 1620 | } |
michael@0 | 1621 | |
michael@0 | 1622 | error = setRevocationMethod(revChecker, |
michael@0 | 1623 | procParams, &flags->leafTests, |
michael@0 | 1624 | cert_revocation_method_ocsp, |
michael@0 | 1625 | PKIX_RevocationMethod_OCSP, |
michael@0 | 1626 | validatingResponderCert, |
michael@0 | 1627 | PKIX_TRUE, plContext); |
michael@0 | 1628 | if (error) { |
michael@0 | 1629 | break; |
michael@0 | 1630 | } |
michael@0 | 1631 | |
michael@0 | 1632 | error = setRevocationMethod(revChecker, |
michael@0 | 1633 | procParams, &flags->chainTests, |
michael@0 | 1634 | cert_revocation_method_crl, |
michael@0 | 1635 | PKIX_RevocationMethod_CRL, |
michael@0 | 1636 | validatingResponderCert, |
michael@0 | 1637 | PKIX_FALSE, plContext); |
michael@0 | 1638 | if (error) { |
michael@0 | 1639 | break; |
michael@0 | 1640 | } |
michael@0 | 1641 | |
michael@0 | 1642 | error = setRevocationMethod(revChecker, |
michael@0 | 1643 | procParams, &flags->chainTests, |
michael@0 | 1644 | cert_revocation_method_ocsp, |
michael@0 | 1645 | PKIX_RevocationMethod_OCSP, |
michael@0 | 1646 | validatingResponderCert, |
michael@0 | 1647 | PKIX_FALSE, plContext); |
michael@0 | 1648 | if (error) { |
michael@0 | 1649 | break; |
michael@0 | 1650 | } |
michael@0 | 1651 | |
michael@0 | 1652 | } |
michael@0 | 1653 | break; |
michael@0 | 1654 | |
michael@0 | 1655 | case cert_pi_trustAnchors: |
michael@0 | 1656 | certList = param->value.pointer.chain; |
michael@0 | 1657 | if (!certList) { |
michael@0 | 1658 | PORT_SetError(errCode); |
michael@0 | 1659 | r = SECFailure; |
michael@0 | 1660 | break; |
michael@0 | 1661 | } |
michael@0 | 1662 | error = PKIX_List_Create(&certListPkix, plContext); |
michael@0 | 1663 | if (error != NULL) { |
michael@0 | 1664 | break; |
michael@0 | 1665 | } |
michael@0 | 1666 | for(node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); |
michael@0 | 1667 | node = CERT_LIST_NEXT(node) ) { |
michael@0 | 1668 | error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert, |
michael@0 | 1669 | &certPkix, plContext); |
michael@0 | 1670 | if (error) { |
michael@0 | 1671 | break; |
michael@0 | 1672 | } |
michael@0 | 1673 | error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor, |
michael@0 | 1674 | plContext); |
michael@0 | 1675 | if (error) { |
michael@0 | 1676 | break; |
michael@0 | 1677 | } |
michael@0 | 1678 | error = PKIX_List_AppendItem(certListPkix, |
michael@0 | 1679 | (PKIX_PL_Object*)trustAnchor, plContext); |
michael@0 | 1680 | if (error) { |
michael@0 | 1681 | break; |
michael@0 | 1682 | } |
michael@0 | 1683 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); |
michael@0 | 1684 | trustAnchor = NULL; |
michael@0 | 1685 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext); |
michael@0 | 1686 | certPkix = NULL; |
michael@0 | 1687 | } |
michael@0 | 1688 | error = |
michael@0 | 1689 | PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix, |
michael@0 | 1690 | plContext); |
michael@0 | 1691 | break; |
michael@0 | 1692 | |
michael@0 | 1693 | case cert_pi_useAIACertFetch: |
michael@0 | 1694 | error = |
michael@0 | 1695 | PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams, |
michael@0 | 1696 | (PRBool)(param->value.scalar.b != 0), |
michael@0 | 1697 | plContext); |
michael@0 | 1698 | break; |
michael@0 | 1699 | |
michael@0 | 1700 | case cert_pi_chainVerifyCallback: |
michael@0 | 1701 | { |
michael@0 | 1702 | const CERTChainVerifyCallback *chainVerifyCallback = |
michael@0 | 1703 | param->value.pointer.chainVerifyCallback; |
michael@0 | 1704 | if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) { |
michael@0 | 1705 | PORT_SetError(errCode); |
michael@0 | 1706 | r = SECFailure; |
michael@0 | 1707 | break; |
michael@0 | 1708 | } |
michael@0 | 1709 | |
michael@0 | 1710 | nssContext->chainVerifyCallback = *chainVerifyCallback; |
michael@0 | 1711 | } |
michael@0 | 1712 | break; |
michael@0 | 1713 | |
michael@0 | 1714 | case cert_pi_useOnlyTrustAnchors: |
michael@0 | 1715 | error = |
michael@0 | 1716 | PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams, |
michael@0 | 1717 | (PRBool)(param->value.scalar.b != 0), |
michael@0 | 1718 | plContext); |
michael@0 | 1719 | break; |
michael@0 | 1720 | |
michael@0 | 1721 | default: |
michael@0 | 1722 | PORT_SetError(errCode); |
michael@0 | 1723 | r = SECFailure; |
michael@0 | 1724 | break; |
michael@0 | 1725 | } |
michael@0 | 1726 | |
michael@0 | 1727 | if (policyOIDList != NULL) |
michael@0 | 1728 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext); |
michael@0 | 1729 | |
michael@0 | 1730 | if (date != NULL) |
michael@0 | 1731 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext); |
michael@0 | 1732 | |
michael@0 | 1733 | if (revDate != NULL) |
michael@0 | 1734 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)revDate, plContext); |
michael@0 | 1735 | |
michael@0 | 1736 | if (revChecker != NULL) |
michael@0 | 1737 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext); |
michael@0 | 1738 | |
michael@0 | 1739 | if (certListPkix) |
michael@0 | 1740 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext); |
michael@0 | 1741 | |
michael@0 | 1742 | if (trustAnchor) |
michael@0 | 1743 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); |
michael@0 | 1744 | |
michael@0 | 1745 | if (certPkix) |
michael@0 | 1746 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext); |
michael@0 | 1747 | |
michael@0 | 1748 | if (error != NULL) { |
michael@0 | 1749 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 1750 | PORT_SetError(errCode); |
michael@0 | 1751 | r = SECFailure; |
michael@0 | 1752 | } |
michael@0 | 1753 | |
michael@0 | 1754 | return r; |
michael@0 | 1755 | |
michael@0 | 1756 | } |
michael@0 | 1757 | |
michael@0 | 1758 | void |
michael@0 | 1759 | cert_pkixDestroyValOutParam(CERTValOutParam *params) |
michael@0 | 1760 | { |
michael@0 | 1761 | CERTValOutParam *i; |
michael@0 | 1762 | |
michael@0 | 1763 | if (params == NULL) { |
michael@0 | 1764 | return; |
michael@0 | 1765 | } |
michael@0 | 1766 | for (i = params; i->type != cert_po_end; i++) { |
michael@0 | 1767 | switch (i->type) { |
michael@0 | 1768 | case cert_po_trustAnchor: |
michael@0 | 1769 | if (i->value.pointer.cert) { |
michael@0 | 1770 | CERT_DestroyCertificate(i->value.pointer.cert); |
michael@0 | 1771 | i->value.pointer.cert = NULL; |
michael@0 | 1772 | } |
michael@0 | 1773 | break; |
michael@0 | 1774 | |
michael@0 | 1775 | case cert_po_certList: |
michael@0 | 1776 | if (i->value.pointer.chain) { |
michael@0 | 1777 | CERT_DestroyCertList(i->value.pointer.chain); |
michael@0 | 1778 | i->value.pointer.chain = NULL; |
michael@0 | 1779 | } |
michael@0 | 1780 | break; |
michael@0 | 1781 | |
michael@0 | 1782 | default: |
michael@0 | 1783 | break; |
michael@0 | 1784 | } |
michael@0 | 1785 | } |
michael@0 | 1786 | } |
michael@0 | 1787 | |
michael@0 | 1788 | static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = { |
michael@0 | 1789 | /* crl */ |
michael@0 | 1790 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1791 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1792 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1793 | /* ocsp */ |
michael@0 | 1794 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1795 | }; |
michael@0 | 1796 | |
michael@0 | 1797 | static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = { |
michael@0 | 1798 | /* crl */ |
michael@0 | 1799 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1800 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1801 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1802 | /* ocsp */ |
michael@0 | 1803 | 0 |
michael@0 | 1804 | }; |
michael@0 | 1805 | |
michael@0 | 1806 | static CERTRevocationMethodIndex |
michael@0 | 1807 | certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = { |
michael@0 | 1808 | cert_revocation_method_crl |
michael@0 | 1809 | }; |
michael@0 | 1810 | |
michael@0 | 1811 | static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = { |
michael@0 | 1812 | { |
michael@0 | 1813 | /* leafTests */ |
michael@0 | 1814 | 2, |
michael@0 | 1815 | certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags, |
michael@0 | 1816 | 1, |
michael@0 | 1817 | &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference, |
michael@0 | 1818 | 0 |
michael@0 | 1819 | }, |
michael@0 | 1820 | { |
michael@0 | 1821 | /* chainTests */ |
michael@0 | 1822 | 2, |
michael@0 | 1823 | certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags, |
michael@0 | 1824 | 0, |
michael@0 | 1825 | 0, |
michael@0 | 1826 | 0 |
michael@0 | 1827 | } |
michael@0 | 1828 | }; |
michael@0 | 1829 | |
michael@0 | 1830 | extern const CERTRevocationFlags* |
michael@0 | 1831 | CERT_GetClassicOCSPEnabledSoftFailurePolicy() |
michael@0 | 1832 | { |
michael@0 | 1833 | return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy; |
michael@0 | 1834 | } |
michael@0 | 1835 | |
michael@0 | 1836 | |
michael@0 | 1837 | static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = { |
michael@0 | 1838 | /* crl */ |
michael@0 | 1839 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1840 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1841 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1842 | /* ocsp */ |
michael@0 | 1843 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1844 | | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
michael@0 | 1845 | }; |
michael@0 | 1846 | |
michael@0 | 1847 | static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = { |
michael@0 | 1848 | /* crl */ |
michael@0 | 1849 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1850 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1851 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1852 | /* ocsp */ |
michael@0 | 1853 | 0 |
michael@0 | 1854 | }; |
michael@0 | 1855 | |
michael@0 | 1856 | static CERTRevocationMethodIndex |
michael@0 | 1857 | certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = { |
michael@0 | 1858 | cert_revocation_method_crl |
michael@0 | 1859 | }; |
michael@0 | 1860 | |
michael@0 | 1861 | static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = { |
michael@0 | 1862 | { |
michael@0 | 1863 | /* leafTests */ |
michael@0 | 1864 | 2, |
michael@0 | 1865 | certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags, |
michael@0 | 1866 | 1, |
michael@0 | 1867 | &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference, |
michael@0 | 1868 | 0 |
michael@0 | 1869 | }, |
michael@0 | 1870 | { |
michael@0 | 1871 | /* chainTests */ |
michael@0 | 1872 | 2, |
michael@0 | 1873 | certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags, |
michael@0 | 1874 | 0, |
michael@0 | 1875 | 0, |
michael@0 | 1876 | 0 |
michael@0 | 1877 | } |
michael@0 | 1878 | }; |
michael@0 | 1879 | |
michael@0 | 1880 | extern const CERTRevocationFlags* |
michael@0 | 1881 | CERT_GetClassicOCSPEnabledHardFailurePolicy() |
michael@0 | 1882 | { |
michael@0 | 1883 | return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy; |
michael@0 | 1884 | } |
michael@0 | 1885 | |
michael@0 | 1886 | |
michael@0 | 1887 | static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = { |
michael@0 | 1888 | /* crl */ |
michael@0 | 1889 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1890 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1891 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1892 | /* ocsp */ |
michael@0 | 1893 | 0 |
michael@0 | 1894 | }; |
michael@0 | 1895 | |
michael@0 | 1896 | static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = { |
michael@0 | 1897 | /* crl */ |
michael@0 | 1898 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1899 | | CERT_REV_M_FORBID_NETWORK_FETCHING |
michael@0 | 1900 | | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO, |
michael@0 | 1901 | /* ocsp */ |
michael@0 | 1902 | 0 |
michael@0 | 1903 | }; |
michael@0 | 1904 | |
michael@0 | 1905 | static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = { |
michael@0 | 1906 | { |
michael@0 | 1907 | /* leafTests */ |
michael@0 | 1908 | 2, |
michael@0 | 1909 | certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags, |
michael@0 | 1910 | 0, |
michael@0 | 1911 | 0, |
michael@0 | 1912 | 0 |
michael@0 | 1913 | }, |
michael@0 | 1914 | { |
michael@0 | 1915 | /* chainTests */ |
michael@0 | 1916 | 2, |
michael@0 | 1917 | certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags, |
michael@0 | 1918 | 0, |
michael@0 | 1919 | 0, |
michael@0 | 1920 | 0 |
michael@0 | 1921 | } |
michael@0 | 1922 | }; |
michael@0 | 1923 | |
michael@0 | 1924 | extern const CERTRevocationFlags* |
michael@0 | 1925 | CERT_GetClassicOCSPDisabledPolicy() |
michael@0 | 1926 | { |
michael@0 | 1927 | return &certRev_NSS_3_11_Ocsp_Disabled_Policy; |
michael@0 | 1928 | } |
michael@0 | 1929 | |
michael@0 | 1930 | |
michael@0 | 1931 | static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = { |
michael@0 | 1932 | /* crl */ |
michael@0 | 1933 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1934 | | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
michael@0 | 1935 | | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE, |
michael@0 | 1936 | /* ocsp */ |
michael@0 | 1937 | 0 |
michael@0 | 1938 | }; |
michael@0 | 1939 | |
michael@0 | 1940 | static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = { |
michael@0 | 1941 | /* crl */ |
michael@0 | 1942 | CERT_REV_M_TEST_USING_THIS_METHOD |
michael@0 | 1943 | | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO |
michael@0 | 1944 | | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE, |
michael@0 | 1945 | /* ocsp */ |
michael@0 | 1946 | 0 |
michael@0 | 1947 | }; |
michael@0 | 1948 | |
michael@0 | 1949 | static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = { |
michael@0 | 1950 | { |
michael@0 | 1951 | /* leafTests */ |
michael@0 | 1952 | 2, |
michael@0 | 1953 | certRev_PKIX_Verify_Nist_Policy_LeafFlags, |
michael@0 | 1954 | 0, |
michael@0 | 1955 | 0, |
michael@0 | 1956 | 0 |
michael@0 | 1957 | }, |
michael@0 | 1958 | { |
michael@0 | 1959 | /* chainTests */ |
michael@0 | 1960 | 2, |
michael@0 | 1961 | certRev_PKIX_Verify_Nist_Policy_ChainFlags, |
michael@0 | 1962 | 0, |
michael@0 | 1963 | 0, |
michael@0 | 1964 | 0 |
michael@0 | 1965 | } |
michael@0 | 1966 | }; |
michael@0 | 1967 | |
michael@0 | 1968 | extern const CERTRevocationFlags* |
michael@0 | 1969 | CERT_GetPKIXVerifyNistRevocationPolicy() |
michael@0 | 1970 | { |
michael@0 | 1971 | return &certRev_PKIX_Verify_Nist_Policy; |
michael@0 | 1972 | } |
michael@0 | 1973 | |
michael@0 | 1974 | CERTRevocationFlags * |
michael@0 | 1975 | CERT_AllocCERTRevocationFlags( |
michael@0 | 1976 | PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods, |
michael@0 | 1977 | PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods) |
michael@0 | 1978 | { |
michael@0 | 1979 | CERTRevocationFlags *flags; |
michael@0 | 1980 | |
michael@0 | 1981 | flags = PORT_New(CERTRevocationFlags); |
michael@0 | 1982 | if (!flags) |
michael@0 | 1983 | return(NULL); |
michael@0 | 1984 | |
michael@0 | 1985 | flags->leafTests.number_of_defined_methods = number_leaf_methods; |
michael@0 | 1986 | flags->leafTests.cert_rev_flags_per_method = |
michael@0 | 1987 | PORT_NewArray(PRUint64, number_leaf_methods); |
michael@0 | 1988 | |
michael@0 | 1989 | flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods; |
michael@0 | 1990 | flags->leafTests.preferred_methods = |
michael@0 | 1991 | PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods); |
michael@0 | 1992 | |
michael@0 | 1993 | flags->chainTests.number_of_defined_methods = number_chain_methods; |
michael@0 | 1994 | flags->chainTests.cert_rev_flags_per_method = |
michael@0 | 1995 | PORT_NewArray(PRUint64, number_chain_methods); |
michael@0 | 1996 | |
michael@0 | 1997 | flags->chainTests.number_of_preferred_methods = number_chain_pref_methods; |
michael@0 | 1998 | flags->chainTests.preferred_methods = |
michael@0 | 1999 | PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods); |
michael@0 | 2000 | |
michael@0 | 2001 | if (!flags->leafTests.cert_rev_flags_per_method |
michael@0 | 2002 | || !flags->leafTests.preferred_methods |
michael@0 | 2003 | || !flags->chainTests.cert_rev_flags_per_method |
michael@0 | 2004 | || !flags->chainTests.preferred_methods) { |
michael@0 | 2005 | CERT_DestroyCERTRevocationFlags(flags); |
michael@0 | 2006 | return (NULL); |
michael@0 | 2007 | } |
michael@0 | 2008 | |
michael@0 | 2009 | return flags; |
michael@0 | 2010 | } |
michael@0 | 2011 | |
michael@0 | 2012 | void CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags) |
michael@0 | 2013 | { |
michael@0 | 2014 | if (!flags) |
michael@0 | 2015 | return; |
michael@0 | 2016 | |
michael@0 | 2017 | if (flags->leafTests.cert_rev_flags_per_method) |
michael@0 | 2018 | PORT_Free(flags->leafTests.cert_rev_flags_per_method); |
michael@0 | 2019 | |
michael@0 | 2020 | if (flags->leafTests.preferred_methods) |
michael@0 | 2021 | PORT_Free(flags->leafTests.preferred_methods); |
michael@0 | 2022 | |
michael@0 | 2023 | if (flags->chainTests.cert_rev_flags_per_method) |
michael@0 | 2024 | PORT_Free(flags->chainTests.cert_rev_flags_per_method); |
michael@0 | 2025 | |
michael@0 | 2026 | if (flags->chainTests.preferred_methods) |
michael@0 | 2027 | PORT_Free(flags->chainTests.preferred_methods); |
michael@0 | 2028 | |
michael@0 | 2029 | PORT_Free(flags); |
michael@0 | 2030 | } |
michael@0 | 2031 | |
michael@0 | 2032 | /* |
michael@0 | 2033 | * CERT_PKIXVerifyCert |
michael@0 | 2034 | * |
michael@0 | 2035 | * Verify a Certificate using the PKIX library. |
michael@0 | 2036 | * |
michael@0 | 2037 | * Parameters: |
michael@0 | 2038 | * cert - the target certificate to verify. Must be non-null |
michael@0 | 2039 | * params - an array of type/value parameters which can be |
michael@0 | 2040 | * used to modify the behavior of the validation |
michael@0 | 2041 | * algorithm, or supply additional constraints. |
michael@0 | 2042 | * |
michael@0 | 2043 | * outputTrustAnchor - the trust anchor which the certificate |
michael@0 | 2044 | * chains to. The caller is responsible |
michael@0 | 2045 | * for freeing this. |
michael@0 | 2046 | * |
michael@0 | 2047 | * Example Usage: |
michael@0 | 2048 | * CERTValParam args[3]; |
michael@0 | 2049 | * args[0].type = cvpt_policyOID; |
michael@0 | 2050 | * args[0].value.si = oid; |
michael@0 | 2051 | * args[1].type = revCheckRequired; |
michael@0 | 2052 | * args[1].value.b = PR_TRUE; |
michael@0 | 2053 | * args[2].type = cvpt_end; |
michael@0 | 2054 | * |
michael@0 | 2055 | * CERT_PKIXVerifyCert(cert, &output, args |
michael@0 | 2056 | */ |
michael@0 | 2057 | SECStatus CERT_PKIXVerifyCert( |
michael@0 | 2058 | CERTCertificate *cert, |
michael@0 | 2059 | SECCertificateUsage usages, |
michael@0 | 2060 | CERTValInParam *paramsIn, |
michael@0 | 2061 | CERTValOutParam *paramsOut, |
michael@0 | 2062 | void *wincx) |
michael@0 | 2063 | { |
michael@0 | 2064 | SECStatus r = SECFailure; |
michael@0 | 2065 | PKIX_Error * error = NULL; |
michael@0 | 2066 | PKIX_ProcessingParams *procParams = NULL; |
michael@0 | 2067 | PKIX_BuildResult * buildResult = NULL; |
michael@0 | 2068 | void * nbioContext = NULL; /* for non-blocking IO */ |
michael@0 | 2069 | void * buildState = NULL; /* for non-blocking IO */ |
michael@0 | 2070 | PKIX_CertSelector * certSelector = NULL; |
michael@0 | 2071 | PKIX_List * certStores = NULL; |
michael@0 | 2072 | PKIX_ValidateResult * valResult = NULL; |
michael@0 | 2073 | PKIX_VerifyNode * verifyNode = NULL; |
michael@0 | 2074 | PKIX_TrustAnchor * trustAnchor = NULL; |
michael@0 | 2075 | PKIX_PL_Cert * trustAnchorCert = NULL; |
michael@0 | 2076 | PKIX_List * builtCertList = NULL; |
michael@0 | 2077 | CERTValOutParam * oparam = NULL; |
michael@0 | 2078 | int i=0; |
michael@0 | 2079 | |
michael@0 | 2080 | void *plContext = NULL; |
michael@0 | 2081 | |
michael@0 | 2082 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 2083 | int leakedObjNum = 0; |
michael@0 | 2084 | int memLeakLoopCount = 0; |
michael@0 | 2085 | int objCountTable[PKIX_NUMTYPES]; |
michael@0 | 2086 | int fnInvLocalCount = 0; |
michael@0 | 2087 | PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine; |
michael@0 | 2088 | |
michael@0 | 2089 | if (usePKIXValidationEngine) { |
michael@0 | 2090 | /* current memory leak testing implementation does not allow |
michael@0 | 2091 | * to run simultaneous tests one the same or a different threads. |
michael@0 | 2092 | * Setting the variable to false, to make additional chain |
michael@0 | 2093 | * validations be handled by old nss. */ |
michael@0 | 2094 | usePKIXValidationEngine = PR_FALSE; |
michael@0 | 2095 | } |
michael@0 | 2096 | testStartFnStackPosition = 1; |
michael@0 | 2097 | fnStackNameArr[0] = "CERT_PKIXVerifyCert"; |
michael@0 | 2098 | fnStackInvCountArr[0] = 0; |
michael@0 | 2099 | PKIX_Boolean abortOnLeak = |
michael@0 | 2100 | (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ? |
michael@0 | 2101 | PKIX_FALSE : PKIX_TRUE; |
michael@0 | 2102 | runningLeakTest = PKIX_TRUE; |
michael@0 | 2103 | |
michael@0 | 2104 | /* Prevent multi-threaded run of object leak test */ |
michael@0 | 2105 | fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount); |
michael@0 | 2106 | PORT_Assert(fnInvLocalCount == 1); |
michael@0 | 2107 | |
michael@0 | 2108 | do { |
michael@0 | 2109 | r = SECFailure; |
michael@0 | 2110 | error = NULL; |
michael@0 | 2111 | procParams = NULL; |
michael@0 | 2112 | buildResult = NULL; |
michael@0 | 2113 | nbioContext = NULL; /* for non-blocking IO */ |
michael@0 | 2114 | buildState = NULL; /* for non-blocking IO */ |
michael@0 | 2115 | certSelector = NULL; |
michael@0 | 2116 | certStores = NULL; |
michael@0 | 2117 | valResult = NULL; |
michael@0 | 2118 | verifyNode = NULL; |
michael@0 | 2119 | trustAnchor = NULL; |
michael@0 | 2120 | trustAnchorCert = NULL; |
michael@0 | 2121 | builtCertList = NULL; |
michael@0 | 2122 | oparam = NULL; |
michael@0 | 2123 | i=0; |
michael@0 | 2124 | errorGenerated = PKIX_FALSE; |
michael@0 | 2125 | stackPosition = 0; |
michael@0 | 2126 | |
michael@0 | 2127 | if (leakedObjNum) { |
michael@0 | 2128 | pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); |
michael@0 | 2129 | } |
michael@0 | 2130 | memLeakLoopCount += 1; |
michael@0 | 2131 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 2132 | |
michael@0 | 2133 | error = PKIX_PL_NssContext_Create( |
michael@0 | 2134 | 0, PR_FALSE /*use arena*/, wincx, &plContext); |
michael@0 | 2135 | if (error != NULL) { /* need pkix->nss error map */ |
michael@0 | 2136 | PORT_SetError(SEC_ERROR_CERT_NOT_VALID); |
michael@0 | 2137 | goto cleanup; |
michael@0 | 2138 | } |
michael@0 | 2139 | |
michael@0 | 2140 | error = pkix_pl_NssContext_SetCertUsage(usages, plContext); |
michael@0 | 2141 | if (error != NULL) { |
michael@0 | 2142 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 2143 | goto cleanup; |
michael@0 | 2144 | } |
michael@0 | 2145 | |
michael@0 | 2146 | error = PKIX_ProcessingParams_Create(&procParams, plContext); |
michael@0 | 2147 | if (error != NULL) { /* need pkix->nss error map */ |
michael@0 | 2148 | PORT_SetError(SEC_ERROR_CERT_NOT_VALID); |
michael@0 | 2149 | goto cleanup; |
michael@0 | 2150 | } |
michael@0 | 2151 | |
michael@0 | 2152 | /* local cert store should be set into procParams before |
michael@0 | 2153 | * filling in revocation settings. */ |
michael@0 | 2154 | certStores = cert_GetCertStores(plContext); |
michael@0 | 2155 | if (certStores == NULL) { |
michael@0 | 2156 | goto cleanup; |
michael@0 | 2157 | } |
michael@0 | 2158 | error = PKIX_ProcessingParams_SetCertStores |
michael@0 | 2159 | (procParams, certStores, plContext); |
michael@0 | 2160 | if (error != NULL) { |
michael@0 | 2161 | goto cleanup; |
michael@0 | 2162 | } |
michael@0 | 2163 | |
michael@0 | 2164 | /* now process the extensible input parameters structure */ |
michael@0 | 2165 | if (paramsIn != NULL) { |
michael@0 | 2166 | i=0; |
michael@0 | 2167 | while (paramsIn[i].type != cert_pi_end) { |
michael@0 | 2168 | if (paramsIn[i].type >= cert_pi_max) { |
michael@0 | 2169 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 2170 | goto cleanup; |
michael@0 | 2171 | } |
michael@0 | 2172 | if (cert_pkixSetParam(procParams, |
michael@0 | 2173 | ¶msIn[i],plContext) != SECSuccess) { |
michael@0 | 2174 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 2175 | goto cleanup; |
michael@0 | 2176 | } |
michael@0 | 2177 | i++; |
michael@0 | 2178 | } |
michael@0 | 2179 | } |
michael@0 | 2180 | |
michael@0 | 2181 | certSelector = cert_GetTargetCertConstraints(cert, plContext); |
michael@0 | 2182 | if (certSelector == NULL) { |
michael@0 | 2183 | goto cleanup; |
michael@0 | 2184 | } |
michael@0 | 2185 | error = PKIX_ProcessingParams_SetTargetCertConstraints |
michael@0 | 2186 | (procParams, certSelector, plContext); |
michael@0 | 2187 | if (error != NULL) { |
michael@0 | 2188 | goto cleanup; |
michael@0 | 2189 | } |
michael@0 | 2190 | |
michael@0 | 2191 | error = PKIX_BuildChain( procParams, &nbioContext, |
michael@0 | 2192 | &buildState, &buildResult, &verifyNode, |
michael@0 | 2193 | plContext); |
michael@0 | 2194 | if (error != NULL) { |
michael@0 | 2195 | goto cleanup; |
michael@0 | 2196 | } |
michael@0 | 2197 | |
michael@0 | 2198 | error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult, |
michael@0 | 2199 | plContext); |
michael@0 | 2200 | if (error != NULL) { |
michael@0 | 2201 | goto cleanup; |
michael@0 | 2202 | } |
michael@0 | 2203 | |
michael@0 | 2204 | error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor, |
michael@0 | 2205 | plContext); |
michael@0 | 2206 | if (error != NULL) { |
michael@0 | 2207 | goto cleanup; |
michael@0 | 2208 | } |
michael@0 | 2209 | |
michael@0 | 2210 | if (trustAnchor != NULL) { |
michael@0 | 2211 | error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert, |
michael@0 | 2212 | plContext); |
michael@0 | 2213 | if (error != NULL) { |
michael@0 | 2214 | goto cleanup; |
michael@0 | 2215 | } |
michael@0 | 2216 | } |
michael@0 | 2217 | |
michael@0 | 2218 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 2219 | /* Can not continue if error was generated but not returned. |
michael@0 | 2220 | * Jumping to cleanup. */ |
michael@0 | 2221 | if (errorGenerated) goto cleanup; |
michael@0 | 2222 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 2223 | |
michael@0 | 2224 | oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor); |
michael@0 | 2225 | if (oparam != NULL) { |
michael@0 | 2226 | if (trustAnchorCert != NULL) { |
michael@0 | 2227 | oparam->value.pointer.cert = |
michael@0 | 2228 | cert_NSSCertFromPKIXCert(trustAnchorCert); |
michael@0 | 2229 | } else { |
michael@0 | 2230 | oparam->value.pointer.cert = NULL; |
michael@0 | 2231 | } |
michael@0 | 2232 | } |
michael@0 | 2233 | |
michael@0 | 2234 | error = PKIX_BuildResult_GetCertChain( buildResult, &builtCertList, |
michael@0 | 2235 | plContext); |
michael@0 | 2236 | if (error != NULL) { |
michael@0 | 2237 | goto cleanup; |
michael@0 | 2238 | } |
michael@0 | 2239 | |
michael@0 | 2240 | oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList); |
michael@0 | 2241 | if (oparam != NULL) { |
michael@0 | 2242 | error = cert_PkixToNssCertsChain(builtCertList, |
michael@0 | 2243 | &oparam->value.pointer.chain, |
michael@0 | 2244 | plContext); |
michael@0 | 2245 | if (error) goto cleanup; |
michael@0 | 2246 | } |
michael@0 | 2247 | |
michael@0 | 2248 | r = SECSuccess; |
michael@0 | 2249 | |
michael@0 | 2250 | cleanup: |
michael@0 | 2251 | if (verifyNode) { |
michael@0 | 2252 | /* Return validation log only upon error. */ |
michael@0 | 2253 | oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog); |
michael@0 | 2254 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 2255 | if (!errorGenerated) |
michael@0 | 2256 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 2257 | if (r && oparam != NULL) { |
michael@0 | 2258 | PKIX_Error *tmpError = |
michael@0 | 2259 | cert_GetLogFromVerifyNode(oparam->value.pointer.log, |
michael@0 | 2260 | verifyNode, plContext); |
michael@0 | 2261 | if (tmpError) { |
michael@0 | 2262 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext); |
michael@0 | 2263 | } |
michael@0 | 2264 | } |
michael@0 | 2265 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext); |
michael@0 | 2266 | } |
michael@0 | 2267 | |
michael@0 | 2268 | if (procParams != NULL) |
michael@0 | 2269 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext); |
michael@0 | 2270 | |
michael@0 | 2271 | if (trustAnchorCert != NULL) |
michael@0 | 2272 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext); |
michael@0 | 2273 | |
michael@0 | 2274 | if (trustAnchor != NULL) |
michael@0 | 2275 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext); |
michael@0 | 2276 | |
michael@0 | 2277 | if (valResult != NULL) |
michael@0 | 2278 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext); |
michael@0 | 2279 | |
michael@0 | 2280 | if (buildResult != NULL) |
michael@0 | 2281 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext); |
michael@0 | 2282 | |
michael@0 | 2283 | if (certStores != NULL) |
michael@0 | 2284 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext); |
michael@0 | 2285 | |
michael@0 | 2286 | if (certSelector != NULL) |
michael@0 | 2287 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext); |
michael@0 | 2288 | |
michael@0 | 2289 | if (builtCertList != NULL) |
michael@0 | 2290 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext); |
michael@0 | 2291 | |
michael@0 | 2292 | if (error != NULL) { |
michael@0 | 2293 | SECErrorCodes nssErrorCode = 0; |
michael@0 | 2294 | |
michael@0 | 2295 | cert_PkixErrorToNssCode(error, &nssErrorCode, plContext); |
michael@0 | 2296 | cert_pkixDestroyValOutParam(paramsOut); |
michael@0 | 2297 | PORT_SetError(nssErrorCode); |
michael@0 | 2298 | PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext); |
michael@0 | 2299 | } |
michael@0 | 2300 | |
michael@0 | 2301 | PKIX_PL_NssContext_Destroy(plContext); |
michael@0 | 2302 | |
michael@0 | 2303 | #ifdef PKIX_OBJECT_LEAK_TEST |
michael@0 | 2304 | leakedObjNum = |
michael@0 | 2305 | pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL); |
michael@0 | 2306 | |
michael@0 | 2307 | if (pkixLog && leakedObjNum) { |
michael@0 | 2308 | PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d." |
michael@0 | 2309 | "Stack %s\n", memLeakLoopCount, errorFnStackString)); |
michael@0 | 2310 | } |
michael@0 | 2311 | PR_Free(errorFnStackString); |
michael@0 | 2312 | errorFnStackString = NULL; |
michael@0 | 2313 | if (abortOnLeak) { |
michael@0 | 2314 | PORT_Assert(leakedObjNum == 0); |
michael@0 | 2315 | } |
michael@0 | 2316 | |
michael@0 | 2317 | } while (errorGenerated); |
michael@0 | 2318 | |
michael@0 | 2319 | runningLeakTest = PKIX_FALSE; |
michael@0 | 2320 | PR_ATOMIC_DECREMENT(¶llelFnInvocationCount); |
michael@0 | 2321 | usePKIXValidationEngine = savedUsePkixEngFlag; |
michael@0 | 2322 | #endif /* PKIX_OBJECT_LEAK_TEST */ |
michael@0 | 2323 | |
michael@0 | 2324 | return r; |
michael@0 | 2325 | } |