1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/certdb/polcyxtn.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,829 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * Support for various policy related extensions 1.10 + */ 1.11 + 1.12 +#include "seccomon.h" 1.13 +#include "secport.h" 1.14 +#include "secder.h" 1.15 +#include "cert.h" 1.16 +#include "secoid.h" 1.17 +#include "secasn1.h" 1.18 +#include "secerr.h" 1.19 +#include "nspr.h" 1.20 + 1.21 +SEC_ASN1_MKSUB(SEC_IntegerTemplate) 1.22 +SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) 1.23 + 1.24 +const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = { 1.25 + { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) }, 1.26 + { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString}, 1.27 + { SEC_ASN1_VISIBLE_STRING , 0, 0, siVisibleString}, 1.28 + { SEC_ASN1_BMP_STRING , 0, 0, siBMPString }, 1.29 + { SEC_ASN1_UTF8_STRING , 0, 0, siUTF8String }, 1.30 + { 0 } 1.31 +}; 1.32 + 1.33 +const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = { 1.34 + { SEC_ASN1_SEQUENCE, 1.35 + 0, NULL, sizeof(CERTNoticeReference) }, 1.36 + { SEC_ASN1_INLINE, 1.37 + offsetof(CERTNoticeReference, organization), 1.38 + CERT_DisplayTextTypeTemplate, 0 }, 1.39 + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 1.40 + offsetof(CERTNoticeReference, noticeNumbers), 1.41 + SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1.42 + { 0 } 1.43 +}; 1.44 + 1.45 +const SEC_ASN1Template CERT_UserNoticeTemplate[] = { 1.46 + { SEC_ASN1_SEQUENCE, 1.47 + 0, NULL, sizeof(CERTUserNotice) }, 1.48 + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, 1.49 + offsetof(CERTUserNotice, noticeReference), 1.50 + CERT_NoticeReferenceTemplate, 0 }, 1.51 + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, 1.52 + offsetof(CERTUserNotice, displayText), 1.53 + CERT_DisplayTextTypeTemplate, 0 }, 1.54 + { 0 } 1.55 +}; 1.56 + 1.57 +const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = { 1.58 + { SEC_ASN1_SEQUENCE, 1.59 + 0, NULL, sizeof(CERTPolicyQualifier) }, 1.60 + { SEC_ASN1_OBJECT_ID, 1.61 + offsetof(CERTPolicyQualifier, qualifierID) }, 1.62 + { SEC_ASN1_ANY, 1.63 + offsetof(CERTPolicyQualifier, qualifierValue) }, 1.64 + { 0 } 1.65 +}; 1.66 + 1.67 +const SEC_ASN1Template CERT_PolicyInfoTemplate[] = { 1.68 + { SEC_ASN1_SEQUENCE, 1.69 + 0, NULL, sizeof(CERTPolicyInfo) }, 1.70 + { SEC_ASN1_OBJECT_ID, 1.71 + offsetof(CERTPolicyInfo, policyID) }, 1.72 + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL, 1.73 + offsetof(CERTPolicyInfo, policyQualifiers), 1.74 + CERT_PolicyQualifierTemplate }, 1.75 + { 0 } 1.76 +}; 1.77 + 1.78 +const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = { 1.79 + { SEC_ASN1_SEQUENCE_OF, 1.80 + offsetof(CERTCertificatePolicies, policyInfos), 1.81 + CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) } 1.82 +}; 1.83 + 1.84 +const SEC_ASN1Template CERT_PolicyMapTemplate[] = { 1.85 + { SEC_ASN1_SEQUENCE, 1.86 + 0, NULL, sizeof(CERTPolicyMap) }, 1.87 + { SEC_ASN1_OBJECT_ID, 1.88 + offsetof(CERTPolicyMap, issuerDomainPolicy) }, 1.89 + { SEC_ASN1_OBJECT_ID, 1.90 + offsetof(CERTPolicyMap, subjectDomainPolicy) }, 1.91 + { 0 } 1.92 +}; 1.93 + 1.94 +const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = { 1.95 + { SEC_ASN1_SEQUENCE_OF, 1.96 + offsetof(CERTCertificatePolicyMappings, policyMaps), 1.97 + CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) } 1.98 +}; 1.99 + 1.100 +const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = { 1.101 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) }, 1.102 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1.103 + offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts), 1.104 + SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1.105 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 1.106 + offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts), 1.107 + SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1.108 + { 0 } 1.109 +}; 1.110 + 1.111 +const SEC_ASN1Template CERT_InhibitAnyTemplate[] = { 1.112 + { SEC_ASN1_INTEGER, 1.113 + offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), 1.114 + NULL, sizeof(CERTCertificateInhibitAny) } 1.115 +}; 1.116 + 1.117 +static void 1.118 +breakLines(char *string) 1.119 +{ 1.120 + char *tmpstr; 1.121 + char *lastspace = NULL; 1.122 + int curlen = 0; 1.123 + int c; 1.124 + 1.125 + tmpstr = string; 1.126 + 1.127 + while ( ( c = *tmpstr ) != '\0' ) { 1.128 + switch ( c ) { 1.129 + case ' ': 1.130 + lastspace = tmpstr; 1.131 + break; 1.132 + case '\n': 1.133 + lastspace = NULL; 1.134 + curlen = 0; 1.135 + break; 1.136 + } 1.137 + 1.138 + if ( ( curlen >= 55 ) && ( lastspace != NULL ) ) { 1.139 + *lastspace = '\n'; 1.140 + curlen = ( tmpstr - lastspace ); 1.141 + lastspace = NULL; 1.142 + } 1.143 + 1.144 + curlen++; 1.145 + tmpstr++; 1.146 + } 1.147 + 1.148 + return; 1.149 +} 1.150 + 1.151 +CERTCertificatePolicies * 1.152 +CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue) 1.153 +{ 1.154 + PLArenaPool *arena = NULL; 1.155 + SECStatus rv; 1.156 + CERTCertificatePolicies *policies; 1.157 + CERTPolicyInfo **policyInfos, *policyInfo; 1.158 + CERTPolicyQualifier **policyQualifiers, *policyQualifier; 1.159 + SECItem newExtnValue; 1.160 + 1.161 + /* make a new arena */ 1.162 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.163 + 1.164 + if ( !arena ) { 1.165 + goto loser; 1.166 + } 1.167 + 1.168 + /* allocate the certificate policies structure */ 1.169 + policies = (CERTCertificatePolicies *) 1.170 + PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicies)); 1.171 + 1.172 + if ( policies == NULL ) { 1.173 + goto loser; 1.174 + } 1.175 + 1.176 + policies->arena = arena; 1.177 + 1.178 + /* copy the DER into the arena, since Quick DER returns data that points 1.179 + into the DER input, which may get freed by the caller */ 1.180 + rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); 1.181 + if ( rv != SECSuccess ) { 1.182 + goto loser; 1.183 + } 1.184 + 1.185 + /* decode the policy info */ 1.186 + rv = SEC_QuickDERDecodeItem(arena, policies, CERT_CertificatePoliciesTemplate, 1.187 + &newExtnValue); 1.188 + 1.189 + if ( rv != SECSuccess ) { 1.190 + goto loser; 1.191 + } 1.192 + 1.193 + /* initialize the oid tags */ 1.194 + policyInfos = policies->policyInfos; 1.195 + while (*policyInfos != NULL ) { 1.196 + policyInfo = *policyInfos; 1.197 + policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); 1.198 + policyQualifiers = policyInfo->policyQualifiers; 1.199 + while ( policyQualifiers != NULL && *policyQualifiers != NULL ) { 1.200 + policyQualifier = *policyQualifiers; 1.201 + policyQualifier->oid = 1.202 + SECOID_FindOIDTag(&policyQualifier->qualifierID); 1.203 + policyQualifiers++; 1.204 + } 1.205 + policyInfos++; 1.206 + } 1.207 + 1.208 + return(policies); 1.209 + 1.210 +loser: 1.211 + if ( arena != NULL ) { 1.212 + PORT_FreeArena(arena, PR_FALSE); 1.213 + } 1.214 + 1.215 + return(NULL); 1.216 +} 1.217 + 1.218 +void 1.219 +CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies) 1.220 +{ 1.221 + if ( policies != NULL ) { 1.222 + PORT_FreeArena(policies->arena, PR_FALSE); 1.223 + } 1.224 + return; 1.225 +} 1.226 + 1.227 +CERTCertificatePolicyMappings * 1.228 +CERT_DecodePolicyMappingsExtension(SECItem *extnValue) 1.229 +{ 1.230 + PLArenaPool *arena = NULL; 1.231 + SECStatus rv; 1.232 + CERTCertificatePolicyMappings *mappings; 1.233 + SECItem newExtnValue; 1.234 + 1.235 + /* make a new arena */ 1.236 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.237 + if ( !arena ) { 1.238 + goto loser; 1.239 + } 1.240 + 1.241 + /* allocate the policy mappings structure */ 1.242 + mappings = (CERTCertificatePolicyMappings *) 1.243 + PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicyMappings)); 1.244 + if ( mappings == NULL ) { 1.245 + goto loser; 1.246 + } 1.247 + mappings->arena = arena; 1.248 + 1.249 + /* copy the DER into the arena, since Quick DER returns data that points 1.250 + into the DER input, which may get freed by the caller */ 1.251 + rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); 1.252 + if ( rv != SECSuccess ) { 1.253 + goto loser; 1.254 + } 1.255 + 1.256 + /* decode the policy mappings */ 1.257 + rv = SEC_QuickDERDecodeItem 1.258 + (arena, mappings, CERT_PolicyMappingsTemplate, &newExtnValue); 1.259 + if ( rv != SECSuccess ) { 1.260 + goto loser; 1.261 + } 1.262 + 1.263 + return(mappings); 1.264 + 1.265 +loser: 1.266 + if ( arena != NULL ) { 1.267 + PORT_FreeArena(arena, PR_FALSE); 1.268 + } 1.269 + 1.270 + return(NULL); 1.271 +} 1.272 + 1.273 +SECStatus 1.274 +CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings) 1.275 +{ 1.276 + if ( mappings != NULL ) { 1.277 + PORT_FreeArena(mappings->arena, PR_FALSE); 1.278 + } 1.279 + return SECSuccess; 1.280 +} 1.281 + 1.282 +SECStatus 1.283 +CERT_DecodePolicyConstraintsExtension 1.284 + (CERTCertificatePolicyConstraints *decodedValue, 1.285 + const SECItem *encodedValue) 1.286 +{ 1.287 + CERTCertificatePolicyConstraints decodeContext; 1.288 + PLArenaPool *arena = NULL; 1.289 + SECStatus rv = SECSuccess; 1.290 + 1.291 + /* initialize so we can tell when an optional component is omitted */ 1.292 + PORT_Memset(&decodeContext, 0, sizeof(decodeContext)); 1.293 + 1.294 + /* make a new arena */ 1.295 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.296 + if (!arena) { 1.297 + return SECFailure; 1.298 + } 1.299 + 1.300 + do { 1.301 + /* decode the policy constraints */ 1.302 + rv = SEC_QuickDERDecodeItem(arena, 1.303 + &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue); 1.304 + 1.305 + if ( rv != SECSuccess ) { 1.306 + break; 1.307 + } 1.308 + 1.309 + if (decodeContext.explicitPolicySkipCerts.len == 0) { 1.310 + *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1; 1.311 + } else { 1.312 + *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = 1.313 + DER_GetInteger(&decodeContext.explicitPolicySkipCerts); 1.314 + } 1.315 + 1.316 + if (decodeContext.inhibitMappingSkipCerts.len == 0) { 1.317 + *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1; 1.318 + } else { 1.319 + *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = 1.320 + DER_GetInteger(&decodeContext.inhibitMappingSkipCerts); 1.321 + } 1.322 + 1.323 + if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == 1.324 + PR_INT32_MIN) || 1.325 + (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == 1.326 + PR_INT32_MAX) || 1.327 + (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == 1.328 + PR_INT32_MIN) || 1.329 + (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == 1.330 + PR_INT32_MAX)) { 1.331 + rv = SECFailure; 1.332 + } 1.333 + 1.334 + } while (0); 1.335 + 1.336 + PORT_FreeArena(arena, PR_FALSE); 1.337 + return(rv); 1.338 +} 1.339 + 1.340 +SECStatus CERT_DecodeInhibitAnyExtension 1.341 + (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue) 1.342 +{ 1.343 + CERTCertificateInhibitAny decodeContext; 1.344 + PLArenaPool *arena = NULL; 1.345 + SECStatus rv = SECSuccess; 1.346 + 1.347 + /* make a new arena */ 1.348 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.349 + if ( !arena ) { 1.350 + return SECFailure; 1.351 + } 1.352 + 1.353 + do { 1.354 + 1.355 + /* decode the policy mappings */ 1.356 + decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger; 1.357 + rv = SEC_QuickDERDecodeItem(arena, 1.358 + &decodeContext, CERT_InhibitAnyTemplate, encodedValue); 1.359 + 1.360 + if ( rv != SECSuccess ) { 1.361 + break; 1.362 + } 1.363 + 1.364 + *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data = 1.365 + DER_GetInteger(&decodeContext.inhibitAnySkipCerts); 1.366 + 1.367 + } while (0); 1.368 + 1.369 + PORT_FreeArena(arena, PR_FALSE); 1.370 + return(rv); 1.371 +} 1.372 + 1.373 +CERTUserNotice * 1.374 +CERT_DecodeUserNotice(SECItem *noticeItem) 1.375 +{ 1.376 + PLArenaPool *arena = NULL; 1.377 + SECStatus rv; 1.378 + CERTUserNotice *userNotice; 1.379 + SECItem newNoticeItem; 1.380 + 1.381 + /* make a new arena */ 1.382 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.383 + 1.384 + if ( !arena ) { 1.385 + goto loser; 1.386 + } 1.387 + 1.388 + /* allocate the userNotice structure */ 1.389 + userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena, 1.390 + sizeof(CERTUserNotice)); 1.391 + 1.392 + if ( userNotice == NULL ) { 1.393 + goto loser; 1.394 + } 1.395 + 1.396 + userNotice->arena = arena; 1.397 + 1.398 + /* copy the DER into the arena, since Quick DER returns data that points 1.399 + into the DER input, which may get freed by the caller */ 1.400 + rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem); 1.401 + if ( rv != SECSuccess ) { 1.402 + goto loser; 1.403 + } 1.404 + 1.405 + /* decode the user notice */ 1.406 + rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate, 1.407 + &newNoticeItem); 1.408 + 1.409 + if ( rv != SECSuccess ) { 1.410 + goto loser; 1.411 + } 1.412 + 1.413 + if (userNotice->derNoticeReference.data != NULL) { 1.414 + 1.415 + rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference, 1.416 + CERT_NoticeReferenceTemplate, 1.417 + &userNotice->derNoticeReference); 1.418 + if (rv == SECFailure) { 1.419 + goto loser; 1.420 + } 1.421 + } 1.422 + 1.423 + return(userNotice); 1.424 + 1.425 +loser: 1.426 + if ( arena != NULL ) { 1.427 + PORT_FreeArena(arena, PR_FALSE); 1.428 + } 1.429 + 1.430 + return(NULL); 1.431 +} 1.432 + 1.433 +void 1.434 +CERT_DestroyUserNotice(CERTUserNotice *userNotice) 1.435 +{ 1.436 + if ( userNotice != NULL ) { 1.437 + PORT_FreeArena(userNotice->arena, PR_FALSE); 1.438 + } 1.439 + return; 1.440 +} 1.441 + 1.442 +static CERTPolicyStringCallback policyStringCB = NULL; 1.443 +static void *policyStringCBArg = NULL; 1.444 + 1.445 +void 1.446 +CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg) 1.447 +{ 1.448 + policyStringCB = cb; 1.449 + policyStringCBArg = cbarg; 1.450 + return; 1.451 +} 1.452 + 1.453 +char * 1.454 +stringFromUserNotice(SECItem *noticeItem) 1.455 +{ 1.456 + SECItem *org; 1.457 + unsigned int len, headerlen; 1.458 + char *stringbuf; 1.459 + CERTUserNotice *userNotice; 1.460 + char *policystr; 1.461 + char *retstr = NULL; 1.462 + SECItem *displayText; 1.463 + SECItem **noticeNumbers; 1.464 + unsigned int strnum; 1.465 + 1.466 + /* decode the user notice */ 1.467 + userNotice = CERT_DecodeUserNotice(noticeItem); 1.468 + if ( userNotice == NULL ) { 1.469 + return(NULL); 1.470 + } 1.471 + 1.472 + org = &userNotice->noticeReference.organization; 1.473 + if ( (org->len != 0 ) && ( policyStringCB != NULL ) ) { 1.474 + /* has a noticeReference */ 1.475 + 1.476 + /* extract the org string */ 1.477 + len = org->len; 1.478 + stringbuf = (char*)PORT_Alloc(len + 1); 1.479 + if ( stringbuf != NULL ) { 1.480 + PORT_Memcpy(stringbuf, org->data, len); 1.481 + stringbuf[len] = '\0'; 1.482 + 1.483 + noticeNumbers = userNotice->noticeReference.noticeNumbers; 1.484 + while ( *noticeNumbers != NULL ) { 1.485 + /* XXX - only one byte integers right now*/ 1.486 + strnum = (*noticeNumbers)->data[0]; 1.487 + policystr = (* policyStringCB)(stringbuf, 1.488 + strnum, 1.489 + policyStringCBArg); 1.490 + if ( policystr != NULL ) { 1.491 + if ( retstr != NULL ) { 1.492 + retstr = PR_sprintf_append(retstr, "\n%s", policystr); 1.493 + } else { 1.494 + retstr = PR_sprintf_append(retstr, "%s", policystr); 1.495 + } 1.496 + 1.497 + PORT_Free(policystr); 1.498 + } 1.499 + 1.500 + noticeNumbers++; 1.501 + } 1.502 + 1.503 + PORT_Free(stringbuf); 1.504 + } 1.505 + } 1.506 + 1.507 + if ( retstr == NULL ) { 1.508 + if ( userNotice->displayText.len != 0 ) { 1.509 + displayText = &userNotice->displayText; 1.510 + 1.511 + if ( displayText->len > 2 ) { 1.512 + if ( displayText->data[0] == SEC_ASN1_VISIBLE_STRING ) { 1.513 + headerlen = 2; 1.514 + if ( displayText->data[1] & 0x80 ) { 1.515 + /* multibyte length */ 1.516 + headerlen += ( displayText->data[1] & 0x7f ); 1.517 + } 1.518 + 1.519 + len = displayText->len - headerlen; 1.520 + retstr = (char*)PORT_Alloc(len + 1); 1.521 + if ( retstr != NULL ) { 1.522 + PORT_Memcpy(retstr, &displayText->data[headerlen],len); 1.523 + retstr[len] = '\0'; 1.524 + } 1.525 + } 1.526 + } 1.527 + } 1.528 + } 1.529 + 1.530 + CERT_DestroyUserNotice(userNotice); 1.531 + 1.532 + return(retstr); 1.533 +} 1.534 + 1.535 +char * 1.536 +CERT_GetCertCommentString(CERTCertificate *cert) 1.537 +{ 1.538 + char *retstring = NULL; 1.539 + SECStatus rv; 1.540 + SECItem policyItem; 1.541 + CERTCertificatePolicies *policies = NULL; 1.542 + CERTPolicyInfo **policyInfos; 1.543 + CERTPolicyQualifier **policyQualifiers, *qualifier; 1.544 + 1.545 + policyItem.data = NULL; 1.546 + 1.547 + rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES, 1.548 + &policyItem); 1.549 + if ( rv != SECSuccess ) { 1.550 + goto nopolicy; 1.551 + } 1.552 + 1.553 + policies = CERT_DecodeCertificatePoliciesExtension(&policyItem); 1.554 + if ( policies == NULL ) { 1.555 + goto nopolicy; 1.556 + } 1.557 + 1.558 + policyInfos = policies->policyInfos; 1.559 + /* search through policyInfos looking for the verisign policy */ 1.560 + while (*policyInfos != NULL ) { 1.561 + if ( (*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES ) { 1.562 + policyQualifiers = (*policyInfos)->policyQualifiers; 1.563 + /* search through the policy qualifiers looking for user notice */ 1.564 + while ( policyQualifiers != NULL && *policyQualifiers != NULL ) { 1.565 + qualifier = *policyQualifiers; 1.566 + if ( qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER ) { 1.567 + retstring = 1.568 + stringFromUserNotice(&qualifier->qualifierValue); 1.569 + break; 1.570 + } 1.571 + 1.572 + policyQualifiers++; 1.573 + } 1.574 + break; 1.575 + } 1.576 + policyInfos++; 1.577 + } 1.578 + 1.579 +nopolicy: 1.580 + if ( policyItem.data != NULL ) { 1.581 + PORT_Free(policyItem.data); 1.582 + } 1.583 + 1.584 + if ( policies != NULL ) { 1.585 + CERT_DestroyCertificatePoliciesExtension(policies); 1.586 + } 1.587 + 1.588 + if ( retstring == NULL ) { 1.589 + retstring = CERT_FindNSStringExtension(cert, 1.590 + SEC_OID_NS_CERT_EXT_COMMENT); 1.591 + } 1.592 + 1.593 + if ( retstring != NULL ) { 1.594 + breakLines(retstring); 1.595 + } 1.596 + 1.597 + return(retstring); 1.598 +} 1.599 + 1.600 + 1.601 +const SEC_ASN1Template CERT_OidSeqTemplate[] = { 1.602 + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 1.603 + offsetof(CERTOidSequence, oids), 1.604 + SEC_ASN1_SUB(SEC_ObjectIDTemplate) } 1.605 +}; 1.606 + 1.607 +CERTOidSequence * 1.608 +CERT_DecodeOidSequence(const SECItem *seqItem) 1.609 +{ 1.610 + PLArenaPool *arena = NULL; 1.611 + SECStatus rv; 1.612 + CERTOidSequence *oidSeq; 1.613 + SECItem newSeqItem; 1.614 + 1.615 + /* make a new arena */ 1.616 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.617 + 1.618 + if ( !arena ) { 1.619 + goto loser; 1.620 + } 1.621 + 1.622 + /* allocate the userNotice structure */ 1.623 + oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena, 1.624 + sizeof(CERTOidSequence)); 1.625 + 1.626 + if ( oidSeq == NULL ) { 1.627 + goto loser; 1.628 + } 1.629 + 1.630 + oidSeq->arena = arena; 1.631 + 1.632 + /* copy the DER into the arena, since Quick DER returns data that points 1.633 + into the DER input, which may get freed by the caller */ 1.634 + rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem); 1.635 + if ( rv != SECSuccess ) { 1.636 + goto loser; 1.637 + } 1.638 + 1.639 + /* decode the user notice */ 1.640 + rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem); 1.641 + 1.642 + if ( rv != SECSuccess ) { 1.643 + goto loser; 1.644 + } 1.645 + 1.646 + return(oidSeq); 1.647 + 1.648 +loser: 1.649 + if (arena) { 1.650 + PORT_FreeArena(arena, PR_FALSE); 1.651 + } 1.652 + return(NULL); 1.653 +} 1.654 + 1.655 + 1.656 +void 1.657 +CERT_DestroyOidSequence(CERTOidSequence *oidSeq) 1.658 +{ 1.659 + if ( oidSeq != NULL ) { 1.660 + PORT_FreeArena(oidSeq->arena, PR_FALSE); 1.661 + } 1.662 + return; 1.663 +} 1.664 + 1.665 +PRBool 1.666 +CERT_GovtApprovedBitSet(CERTCertificate *cert) 1.667 +{ 1.668 + SECStatus rv; 1.669 + SECItem extItem; 1.670 + CERTOidSequence *oidSeq = NULL; 1.671 + PRBool ret; 1.672 + SECItem **oids; 1.673 + SECItem *oid; 1.674 + SECOidTag oidTag; 1.675 + 1.676 + extItem.data = NULL; 1.677 + rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); 1.678 + if ( rv != SECSuccess ) { 1.679 + goto loser; 1.680 + } 1.681 + 1.682 + oidSeq = CERT_DecodeOidSequence(&extItem); 1.683 + if ( oidSeq == NULL ) { 1.684 + goto loser; 1.685 + } 1.686 + 1.687 + oids = oidSeq->oids; 1.688 + while ( oids != NULL && *oids != NULL ) { 1.689 + oid = *oids; 1.690 + 1.691 + oidTag = SECOID_FindOIDTag(oid); 1.692 + 1.693 + if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) { 1.694 + goto success; 1.695 + } 1.696 + 1.697 + oids++; 1.698 + } 1.699 + 1.700 +loser: 1.701 + ret = PR_FALSE; 1.702 + goto done; 1.703 +success: 1.704 + ret = PR_TRUE; 1.705 +done: 1.706 + if ( oidSeq != NULL ) { 1.707 + CERT_DestroyOidSequence(oidSeq); 1.708 + } 1.709 + if (extItem.data != NULL) { 1.710 + PORT_Free(extItem.data); 1.711 + } 1.712 + return(ret); 1.713 +} 1.714 + 1.715 + 1.716 +SECStatus 1.717 +CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena, 1.718 + CERTCertificatePolicyConstraints *constr, 1.719 + SECItem *dest) 1.720 +{ 1.721 + SECStatus rv = SECSuccess; 1.722 + 1.723 + PORT_Assert(constr != NULL && dest != NULL); 1.724 + if (constr == NULL || dest == NULL) { 1.725 + return SECFailure; 1.726 + } 1.727 + 1.728 + if (SEC_ASN1EncodeItem (arena, dest, constr, 1.729 + CERT_PolicyConstraintsTemplate) == NULL) { 1.730 + rv = SECFailure; 1.731 + } 1.732 + return(rv); 1.733 +} 1.734 + 1.735 +SECStatus 1.736 +CERT_EncodePolicyMappingExtension(PLArenaPool *arena, 1.737 + CERTCertificatePolicyMappings *mapping, 1.738 + SECItem *dest) 1.739 +{ 1.740 + SECStatus rv = SECSuccess; 1.741 + 1.742 + PORT_Assert(mapping != NULL && dest != NULL); 1.743 + if (mapping == NULL || dest == NULL) { 1.744 + return SECFailure; 1.745 + } 1.746 + 1.747 + if (SEC_ASN1EncodeItem (arena, dest, mapping, 1.748 + CERT_PolicyMappingsTemplate) == NULL) { 1.749 + rv = SECFailure; 1.750 + } 1.751 + return(rv); 1.752 +} 1.753 + 1.754 + 1.755 + 1.756 +SECStatus 1.757 +CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, 1.758 + CERTPolicyInfo **info, 1.759 + SECItem *dest) 1.760 +{ 1.761 + SECStatus rv = SECSuccess; 1.762 + 1.763 + PORT_Assert(info != NULL && dest != NULL); 1.764 + if (info == NULL || dest == NULL) { 1.765 + return SECFailure; 1.766 + } 1.767 + 1.768 + if (SEC_ASN1EncodeItem (arena, dest, info, 1.769 + CERT_CertificatePoliciesTemplate) == NULL) { 1.770 + rv = SECFailure; 1.771 + } 1.772 + return(rv); 1.773 +} 1.774 + 1.775 +SECStatus 1.776 +CERT_EncodeUserNotice(PLArenaPool *arena, 1.777 + CERTUserNotice *notice, 1.778 + SECItem *dest) 1.779 +{ 1.780 + SECStatus rv = SECSuccess; 1.781 + 1.782 + PORT_Assert(notice != NULL && dest != NULL); 1.783 + if (notice == NULL || dest == NULL) { 1.784 + return SECFailure; 1.785 + } 1.786 + 1.787 + if (SEC_ASN1EncodeItem(arena, dest, 1.788 + notice, CERT_UserNoticeTemplate) == NULL) { 1.789 + rv = SECFailure; 1.790 + } 1.791 + 1.792 + return(rv); 1.793 +} 1.794 + 1.795 +SECStatus 1.796 +CERT_EncodeNoticeReference(PLArenaPool *arena, 1.797 + CERTNoticeReference *reference, 1.798 + SECItem *dest) 1.799 +{ 1.800 + SECStatus rv = SECSuccess; 1.801 + 1.802 + PORT_Assert(reference != NULL && dest != NULL); 1.803 + if (reference == NULL || dest == NULL) { 1.804 + return SECFailure; 1.805 + } 1.806 + 1.807 + if (SEC_ASN1EncodeItem (arena, dest, reference, 1.808 + CERT_NoticeReferenceTemplate) == NULL) { 1.809 + rv = SECFailure; 1.810 + } 1.811 + 1.812 + return(rv); 1.813 +} 1.814 + 1.815 +SECStatus 1.816 +CERT_EncodeInhibitAnyExtension(PLArenaPool *arena, 1.817 + CERTCertificateInhibitAny *certInhibitAny, 1.818 + SECItem *dest) 1.819 +{ 1.820 + SECStatus rv = SECSuccess; 1.821 + 1.822 + PORT_Assert(certInhibitAny != NULL && dest != NULL); 1.823 + if (certInhibitAny == NULL || dest == NULL) { 1.824 + return SECFailure; 1.825 + } 1.826 + 1.827 + if (SEC_ASN1EncodeItem (arena, dest, certInhibitAny, 1.828 + CERT_InhibitAnyTemplate) == NULL) { 1.829 + rv = SECFailure; 1.830 + } 1.831 + return(rv); 1.832 +}