xcrldist.c (7572B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * Code for dealing with x.509 v3 CRL Distribution Point extension. 7 */ 8 #include "genname.h" 9 #include "certt.h" 10 #include "secerr.h" 11 12 SEC_ASN1_MKSUB(SEC_AnyTemplate) 13 SEC_ASN1_MKSUB(SEC_BitStringTemplate) 14 15 extern void PrepareBitStringForEncoding(SECItem *bitMap, SECItem *value); 16 17 static const SEC_ASN1Template FullNameTemplate[] = { 18 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, 19 offsetof(CRLDistributionPoint, derFullName), 20 CERT_GeneralNamesTemplate } 21 }; 22 23 static const SEC_ASN1Template RelativeNameTemplate[] = { 24 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, 25 offsetof(CRLDistributionPoint, distPoint.relativeName), 26 CERT_RDNTemplate } 27 }; 28 29 static const SEC_ASN1Template DistributionPointNameTemplate[] = { 30 { SEC_ASN1_CHOICE, 31 offsetof(CRLDistributionPoint, distPointType), NULL, 32 sizeof(CRLDistributionPoint) }, 33 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, 34 offsetof(CRLDistributionPoint, derFullName), 35 CERT_GeneralNamesTemplate, generalName }, 36 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, 37 offsetof(CRLDistributionPoint, distPoint.relativeName), 38 CERT_RDNTemplate, relativeDistinguishedName }, 39 { 0 } 40 }; 41 42 static const SEC_ASN1Template CRLDistributionPointTemplate[] = { 43 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CRLDistributionPoint) }, 44 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 45 SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0, 46 offsetof(CRLDistributionPoint, derDistPoint), 47 SEC_ASN1_SUB(SEC_AnyTemplate) }, 48 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 49 offsetof(CRLDistributionPoint, bitsmap), 50 SEC_ASN1_SUB(SEC_BitStringTemplate) }, 51 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 52 SEC_ASN1_CONSTRUCTED | 2, 53 offsetof(CRLDistributionPoint, derCrlIssuer), 54 CERT_GeneralNamesTemplate }, 55 { 0 } 56 }; 57 58 const SEC_ASN1Template CERTCRLDistributionPointsTemplate[] = { 59 { SEC_ASN1_SEQUENCE_OF, 0, CRLDistributionPointTemplate } 60 }; 61 62 SECStatus 63 CERT_EncodeCRLDistributionPoints(PLArenaPool *arena, 64 CERTCrlDistributionPoints *value, 65 SECItem *derValue) 66 { 67 CRLDistributionPoint **pointList, *point; 68 PLArenaPool *ourPool = NULL; 69 SECStatus rv = SECSuccess; 70 71 PORT_Assert(derValue); 72 PORT_Assert(value && value->distPoints); 73 74 do { 75 ourPool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 76 if (ourPool == NULL) { 77 rv = SECFailure; 78 break; 79 } 80 81 pointList = value->distPoints; 82 while (*pointList) { 83 point = *pointList; 84 point->derFullName = NULL; 85 point->derDistPoint.data = NULL; 86 87 switch (point->distPointType) { 88 case generalName: 89 point->derFullName = cert_EncodeGeneralNames(ourPool, point->distPoint.fullName); 90 91 if (!point->derFullName || 92 !SEC_ASN1EncodeItem(ourPool, &point->derDistPoint, 93 point, FullNameTemplate)) 94 rv = SECFailure; 95 break; 96 97 case relativeDistinguishedName: 98 if (!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint, 99 point, RelativeNameTemplate)) 100 rv = SECFailure; 101 break; 102 103 default: 104 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); 105 rv = SECFailure; 106 break; 107 } 108 109 if (rv != SECSuccess) 110 break; 111 112 if (point->reasons.data) 113 PrepareBitStringForEncoding(&point->bitsmap, &point->reasons); 114 115 if (point->crlIssuer) { 116 point->derCrlIssuer = cert_EncodeGeneralNames(ourPool, point->crlIssuer); 117 if (!point->derCrlIssuer) { 118 rv = SECFailure; 119 break; 120 } 121 } 122 ++pointList; 123 } 124 if (rv != SECSuccess) 125 break; 126 if (!SEC_ASN1EncodeItem(arena, derValue, value, 127 CERTCRLDistributionPointsTemplate)) { 128 rv = SECFailure; 129 break; 130 } 131 } while (0); 132 PORT_FreeArena(ourPool, PR_FALSE); 133 return rv; 134 } 135 136 CERTCrlDistributionPoints * 137 CERT_DecodeCRLDistributionPoints(PLArenaPool *arena, SECItem *encodedValue) 138 { 139 CERTCrlDistributionPoints *value = NULL; 140 CRLDistributionPoint **pointList, *point; 141 SECStatus rv = SECSuccess; 142 SECItem newEncodedValue; 143 144 PORT_Assert(arena); 145 do { 146 value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints); 147 if (value == NULL) { 148 rv = SECFailure; 149 break; 150 } 151 152 /* copy the DER into the arena, since Quick DER returns data that points 153 into the DER input, which may get freed by the caller */ 154 rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue); 155 if (rv != SECSuccess) 156 break; 157 158 rv = SEC_QuickDERDecodeItem(arena, &value->distPoints, 159 CERTCRLDistributionPointsTemplate, &newEncodedValue); 160 if (rv != SECSuccess) 161 break; 162 163 pointList = value->distPoints; 164 while (NULL != (point = *pointList)) { 165 166 /* get the data if the distributionPointName is not omitted */ 167 if (point->derDistPoint.data != NULL) { 168 rv = SEC_QuickDERDecodeItem(arena, point, 169 DistributionPointNameTemplate, &(point->derDistPoint)); 170 if (rv != SECSuccess) 171 break; 172 173 switch (point->distPointType) { 174 case generalName: 175 point->distPoint.fullName = 176 cert_DecodeGeneralNames(arena, point->derFullName); 177 rv = point->distPoint.fullName ? SECSuccess : SECFailure; 178 break; 179 180 case relativeDistinguishedName: 181 break; 182 183 default: 184 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); 185 rv = SECFailure; 186 break; 187 } /* end switch */ 188 if (rv != SECSuccess) 189 break; 190 } /* end if */ 191 192 /* Get the reason code if it's not omitted in the encoding */ 193 if (point->bitsmap.data != NULL) { 194 SECItem bitsmap = point->bitsmap; 195 DER_ConvertBitString(&bitsmap); 196 rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap); 197 if (rv != SECSuccess) 198 break; 199 } 200 201 /* Get the crl issuer name if it's not omitted in the encoding */ 202 if (point->derCrlIssuer != NULL) { 203 point->crlIssuer = cert_DecodeGeneralNames(arena, 204 point->derCrlIssuer); 205 if (!point->crlIssuer) 206 break; 207 } 208 ++pointList; 209 } /* end while points remain */ 210 } while (0); 211 return (rv == SECSuccess ? value : NULL); 212 }