1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/certhigh/xcrldist.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 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 + * Code for dealing with x.509 v3 CRL Distribution Point extension. 1.10 + */ 1.11 +#include "genname.h" 1.12 +#include "certt.h" 1.13 +#include "secerr.h" 1.14 + 1.15 +SEC_ASN1_MKSUB(SEC_AnyTemplate) 1.16 +SEC_ASN1_MKSUB(SEC_BitStringTemplate) 1.17 + 1.18 +extern void PrepareBitStringForEncoding (SECItem *bitMap, SECItem *value); 1.19 + 1.20 +static const SEC_ASN1Template FullNameTemplate[] = { 1.21 + {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, 1.22 + offsetof (CRLDistributionPoint,derFullName), 1.23 + CERT_GeneralNamesTemplate} 1.24 +}; 1.25 + 1.26 +static const SEC_ASN1Template RelativeNameTemplate[] = { 1.27 + {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, 1.28 + offsetof (CRLDistributionPoint,distPoint.relativeName), 1.29 + CERT_RDNTemplate} 1.30 +}; 1.31 + 1.32 +static const SEC_ASN1Template DistributionPointNameTemplate[] = { 1.33 + { SEC_ASN1_CHOICE, 1.34 + offsetof(CRLDistributionPoint, distPointType), NULL, 1.35 + sizeof(CRLDistributionPoint) }, 1.36 + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, 1.37 + offsetof (CRLDistributionPoint, derFullName), 1.38 + CERT_GeneralNamesTemplate, generalName }, 1.39 + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, 1.40 + offsetof (CRLDistributionPoint, distPoint.relativeName), 1.41 + CERT_RDNTemplate, relativeDistinguishedName }, 1.42 + { 0 } 1.43 +}; 1.44 + 1.45 +static const SEC_ASN1Template CRLDistributionPointTemplate[] = { 1.46 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CRLDistributionPoint) }, 1.47 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1.48 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0, 1.49 + offsetof(CRLDistributionPoint,derDistPoint), 1.50 + SEC_ASN1_SUB(SEC_AnyTemplate)}, 1.51 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 1.52 + offsetof(CRLDistributionPoint,bitsmap), 1.53 + SEC_ASN1_SUB(SEC_BitStringTemplate) }, 1.54 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1.55 + SEC_ASN1_CONSTRUCTED | 2, 1.56 + offsetof(CRLDistributionPoint, derCrlIssuer), 1.57 + CERT_GeneralNamesTemplate}, 1.58 + { 0 } 1.59 +}; 1.60 + 1.61 +const SEC_ASN1Template CERTCRLDistributionPointsTemplate[] = { 1.62 + {SEC_ASN1_SEQUENCE_OF, 0, CRLDistributionPointTemplate} 1.63 +}; 1.64 + 1.65 +SECStatus 1.66 +CERT_EncodeCRLDistributionPoints (PLArenaPool *arena, 1.67 + CERTCrlDistributionPoints *value, 1.68 + SECItem *derValue) 1.69 +{ 1.70 + CRLDistributionPoint **pointList, *point; 1.71 + PLArenaPool *ourPool = NULL; 1.72 + SECStatus rv = SECSuccess; 1.73 + 1.74 + PORT_Assert (derValue); 1.75 + PORT_Assert (value && value->distPoints); 1.76 + 1.77 + do { 1.78 + ourPool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); 1.79 + if (ourPool == NULL) { 1.80 + rv = SECFailure; 1.81 + break; 1.82 + } 1.83 + 1.84 + pointList = value->distPoints; 1.85 + while (*pointList) { 1.86 + point = *pointList; 1.87 + point->derFullName = NULL; 1.88 + point->derDistPoint.data = NULL; 1.89 + 1.90 + switch (point->distPointType) { 1.91 + case generalName: 1.92 + point->derFullName = cert_EncodeGeneralNames 1.93 + (ourPool, point->distPoint.fullName); 1.94 + 1.95 + if (!point->derFullName || 1.96 + !SEC_ASN1EncodeItem (ourPool, &point->derDistPoint, 1.97 + point, FullNameTemplate)) 1.98 + rv = SECFailure; 1.99 + break; 1.100 + 1.101 + case relativeDistinguishedName: 1.102 + if (!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint, 1.103 + point, RelativeNameTemplate)) 1.104 + rv = SECFailure; 1.105 + break; 1.106 + 1.107 + /* distributionPointName is omitted */ 1.108 + case 0: break; 1.109 + 1.110 + default: 1.111 + PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); 1.112 + rv = SECFailure; 1.113 + break; 1.114 + } 1.115 + 1.116 + if (rv != SECSuccess) 1.117 + break; 1.118 + 1.119 + if (point->reasons.data) 1.120 + PrepareBitStringForEncoding (&point->bitsmap, &point->reasons); 1.121 + 1.122 + if (point->crlIssuer) { 1.123 + point->derCrlIssuer = cert_EncodeGeneralNames 1.124 + (ourPool, point->crlIssuer); 1.125 + if (!point->derCrlIssuer) { 1.126 + rv = SECFailure; 1.127 + break; 1.128 + } 1.129 + } 1.130 + ++pointList; 1.131 + } 1.132 + if (rv != SECSuccess) 1.133 + break; 1.134 + if (!SEC_ASN1EncodeItem(arena, derValue, value, 1.135 + CERTCRLDistributionPointsTemplate)) { 1.136 + rv = SECFailure; 1.137 + break; 1.138 + } 1.139 + } while (0); 1.140 + PORT_FreeArena (ourPool, PR_FALSE); 1.141 + return rv; 1.142 +} 1.143 + 1.144 +CERTCrlDistributionPoints * 1.145 +CERT_DecodeCRLDistributionPoints (PLArenaPool *arena, SECItem *encodedValue) 1.146 +{ 1.147 + CERTCrlDistributionPoints *value = NULL; 1.148 + CRLDistributionPoint **pointList, *point; 1.149 + SECStatus rv = SECSuccess; 1.150 + SECItem newEncodedValue; 1.151 + 1.152 + PORT_Assert (arena); 1.153 + do { 1.154 + value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints); 1.155 + if (value == NULL) { 1.156 + rv = SECFailure; 1.157 + break; 1.158 + } 1.159 + 1.160 + /* copy the DER into the arena, since Quick DER returns data that points 1.161 + into the DER input, which may get freed by the caller */ 1.162 + rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue); 1.163 + if (rv != SECSuccess) 1.164 + break; 1.165 + 1.166 + rv = SEC_QuickDERDecodeItem(arena, &value->distPoints, 1.167 + CERTCRLDistributionPointsTemplate, &newEncodedValue); 1.168 + if (rv != SECSuccess) 1.169 + break; 1.170 + 1.171 + pointList = value->distPoints; 1.172 + while (NULL != (point = *pointList)) { 1.173 + 1.174 + /* get the data if the distributionPointName is not omitted */ 1.175 + if (point->derDistPoint.data != NULL) { 1.176 + rv = SEC_QuickDERDecodeItem(arena, point, 1.177 + DistributionPointNameTemplate, &(point->derDistPoint)); 1.178 + if (rv != SECSuccess) 1.179 + break; 1.180 + 1.181 + switch (point->distPointType) { 1.182 + case generalName: 1.183 + point->distPoint.fullName = 1.184 + cert_DecodeGeneralNames(arena, point->derFullName); 1.185 + rv = point->distPoint.fullName ? SECSuccess : SECFailure; 1.186 + break; 1.187 + 1.188 + case relativeDistinguishedName: 1.189 + break; 1.190 + 1.191 + default: 1.192 + PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); 1.193 + rv = SECFailure; 1.194 + break; 1.195 + } /* end switch */ 1.196 + if (rv != SECSuccess) 1.197 + break; 1.198 + } /* end if */ 1.199 + 1.200 + /* Get the reason code if it's not omitted in the encoding */ 1.201 + if (point->bitsmap.data != NULL) { 1.202 + SECItem bitsmap = point->bitsmap; 1.203 + DER_ConvertBitString(&bitsmap); 1.204 + rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap); 1.205 + if (rv != SECSuccess) 1.206 + break; 1.207 + } 1.208 + 1.209 + /* Get the crl issuer name if it's not omitted in the encoding */ 1.210 + if (point->derCrlIssuer != NULL) { 1.211 + point->crlIssuer = cert_DecodeGeneralNames(arena, 1.212 + point->derCrlIssuer); 1.213 + if (!point->crlIssuer) 1.214 + break; 1.215 + } 1.216 + ++pointList; 1.217 + } /* end while points remain */ 1.218 + } while (0); 1.219 + return (rv == SECSuccess ? value : NULL); 1.220 +}