| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | |
| 5 /* | |
| 6 * X.509 Extension Encoding | |
| 7 */ | |
| 8 | |
| 9 #include "prtypes.h" | |
| 10 #include "seccomon.h" | |
| 11 #include "secdert.h" | |
| 12 #include "secoidt.h" | |
| 13 #include "secasn1t.h" | |
| 14 #include "secasn1.h" | |
| 15 #include "cert.h" | |
| 16 #include "secder.h" | |
| 17 #include "prprf.h" | |
| 18 #include "xconst.h" | |
| 19 #include "genname.h" | |
| 20 #include "secasn1.h" | |
| 21 #include "secerr.h" | |
| 22 | |
| 23 static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = { | |
| 24 { SEC_ASN1_OCTET_STRING } | |
| 25 }; | |
| 26 | |
| 27 static const SEC_ASN1Template CERTIA5TypeTemplate[] = { | |
| 28 { SEC_ASN1_IA5_STRING } | |
| 29 }; | |
| 30 | |
| 31 SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate) | |
| 32 | |
| 33 static const SEC_ASN1Template CERTPrivateKeyUsagePeriodTemplate[] = { | |
| 34 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPrivKeyUsagePeriod) }, | |
| 35 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | |
| 36 offsetof(CERTPrivKeyUsagePeriod, notBefore), | |
| 37 SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) }, | |
| 38 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, | |
| 39 offsetof(CERTPrivKeyUsagePeriod, notAfter), | |
| 40 SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) }, | |
| 41 { 0 } | |
| 42 }; | |
| 43 | |
| 44 const SEC_ASN1Template CERTAltNameTemplate[] = { | |
| 45 { SEC_ASN1_CONSTRUCTED, offsetof(CERTAltNameEncodedContext, encodedGenName), | |
| 46 CERT_GeneralNamesTemplate } | |
| 47 }; | |
| 48 | |
| 49 const SEC_ASN1Template CERTAuthInfoAccessItemTemplate[] = { | |
| 50 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthInfoAccess) }, | |
| 51 { SEC_ASN1_OBJECT_ID, offsetof(CERTAuthInfoAccess, method) }, | |
| 52 { SEC_ASN1_ANY, offsetof(CERTAuthInfoAccess, derLocation) }, | |
| 53 { 0 } | |
| 54 }; | |
| 55 | |
| 56 const SEC_ASN1Template CERTAuthInfoAccessTemplate[] = { | |
| 57 { SEC_ASN1_SEQUENCE_OF, 0, CERTAuthInfoAccessItemTemplate } | |
| 58 }; | |
| 59 | |
| 60 SECStatus | |
| 61 CERT_EncodeSubjectKeyID(PLArenaPool *arena, const SECItem *srcString, | |
| 62 SECItem *encodedValue) | |
| 63 { | |
| 64 SECStatus rv = SECSuccess; | |
| 65 | |
| 66 if (!srcString) { | |
| 67 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 68 return SECFailure; | |
| 69 } | |
| 70 if (SEC_ASN1EncodeItem(arena, encodedValue, srcString, | |
| 71 CERTSubjectKeyIDTemplate) == NULL) { | |
| 72 rv = SECFailure; | |
| 73 } | |
| 74 | |
| 75 return (rv); | |
| 76 } | |
| 77 | |
| 78 SECStatus | |
| 79 CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena, | |
| 80 CERTPrivKeyUsagePeriod *pkup, | |
| 81 SECItem *encodedValue) | |
| 82 { | |
| 83 SECStatus rv = SECSuccess; | |
| 84 | |
| 85 if (SEC_ASN1EncodeItem(arena, encodedValue, pkup, | |
| 86 CERTPrivateKeyUsagePeriodTemplate) == NULL) { | |
| 87 rv = SECFailure; | |
| 88 } | |
| 89 return (rv); | |
| 90 } | |
| 91 | |
| 92 CERTPrivKeyUsagePeriod * | |
| 93 CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue) | |
| 94 { | |
| 95 SECStatus rv; | |
| 96 CERTPrivKeyUsagePeriod *pPeriod; | |
| 97 SECItem newExtnValue; | |
| 98 | |
| 99 /* allocate the certificate policies structure */ | |
| 100 pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod); | |
| 101 if (pPeriod == NULL) { | |
| 102 goto loser; | |
| 103 } | |
| 104 | |
| 105 pPeriod->arena = arena; | |
| 106 | |
| 107 /* copy the DER into the arena, since Quick DER returns data that points | |
| 108 into the DER input, which may get freed by the caller */ | |
| 109 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); | |
| 110 if (rv != SECSuccess) { | |
| 111 goto loser; | |
| 112 } | |
| 113 | |
| 114 rv = SEC_QuickDERDecodeItem( | |
| 115 arena, pPeriod, CERTPrivateKeyUsagePeriodTemplate, &newExtnValue); | |
| 116 if (rv != SECSuccess) { | |
| 117 goto loser; | |
| 118 } | |
| 119 return pPeriod; | |
| 120 | |
| 121 loser: | |
| 122 return NULL; | |
| 123 } | |
| 124 | |
| 125 SECStatus | |
| 126 CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value, | |
| 127 SECItem *encodedValue) | |
| 128 { | |
| 129 SECItem encodeContext; | |
| 130 SECStatus rv = SECSuccess; | |
| 131 | |
| 132 PORT_Memset(&encodeContext, 0, sizeof(encodeContext)); | |
| 133 | |
| 134 if (value != NULL) { | |
| 135 encodeContext.data = (unsigned char *)value; | |
| 136 encodeContext.len = strlen(value); | |
| 137 } | |
| 138 if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext, | |
| 139 CERTIA5TypeTemplate) == NULL) { | |
| 140 rv = SECFailure; | |
| 141 } | |
| 142 | |
| 143 return (rv); | |
| 144 } | |
| 145 | |
| 146 SECStatus | |
| 147 CERT_EncodeAltNameExtension(PLArenaPool *arena, CERTGeneralName *value, | |
| 148 SECItem *encodedValue) | |
| 149 { | |
| 150 SECItem **encodedGenName; | |
| 151 SECStatus rv = SECSuccess; | |
| 152 | |
| 153 encodedGenName = cert_EncodeGeneralNames(arena, value); | |
| 154 if (SEC_ASN1EncodeItem(arena, encodedValue, &encodedGenName, | |
| 155 CERT_GeneralNamesTemplate) == NULL) { | |
| 156 rv = SECFailure; | |
| 157 } | |
| 158 | |
| 159 return rv; | |
| 160 } | |
| 161 | |
| 162 CERTGeneralName * | |
| 163 CERT_DecodeAltNameExtension(PLArenaPool *reqArena, SECItem *EncodedAltName) | |
| 164 { | |
| 165 SECStatus rv = SECSuccess; | |
| 166 CERTAltNameEncodedContext encodedContext; | |
| 167 SECItem *newEncodedAltName; | |
| 168 | |
| 169 if (!reqArena) { | |
| 170 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 171 return NULL; | |
| 172 } | |
| 173 | |
| 174 newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName); | |
| 175 if (!newEncodedAltName) { | |
| 176 return NULL; | |
| 177 } | |
| 178 | |
| 179 encodedContext.encodedGenName = NULL; | |
| 180 PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext)); | |
| 181 rv = SEC_QuickDERDecodeItem(reqArena, &encodedContext, | |
| 182 CERT_GeneralNamesTemplate, newEncodedAltName); | |
| 183 if (rv == SECFailure) { | |
| 184 goto loser; | |
| 185 } | |
| 186 if (encodedContext.encodedGenName && encodedContext.encodedGenName[0]) | |
| 187 return cert_DecodeGeneralNames(reqArena, encodedContext.encodedGenName); | |
| 188 /* Extension contained an empty GeneralNames sequence */ | |
| 189 /* Treat as extension not found */ | |
| 190 PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); | |
| 191 loser: | |
| 192 return NULL; | |
| 193 } | |
| 194 | |
| 195 SECStatus | |
| 196 CERT_EncodeNameConstraintsExtension(PLArenaPool *arena, | |
| 197 CERTNameConstraints *value, | |
| 198 SECItem *encodedValue) | |
| 199 { | |
| 200 SECStatus rv = SECSuccess; | |
| 201 | |
| 202 rv = cert_EncodeNameConstraints(value, arena, encodedValue); | |
| 203 return rv; | |
| 204 } | |
| 205 | |
| 206 CERTNameConstraints * | |
| 207 CERT_DecodeNameConstraintsExtension(PLArenaPool *arena, | |
| 208 const SECItem *encodedConstraints) | |
| 209 { | |
| 210 return cert_DecodeNameConstraints(arena, encodedConstraints); | |
| 211 } | |
| 212 | |
| 213 CERTAuthInfoAccess ** | |
| 214 CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena, | |
| 215 const SECItem *encodedExtension) | |
| 216 { | |
| 217 CERTAuthInfoAccess **info = NULL; | |
| 218 SECStatus rv; | |
| 219 int i; | |
| 220 SECItem *newEncodedExtension; | |
| 221 | |
| 222 if (!reqArena) { | |
| 223 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 224 return NULL; | |
| 225 } | |
| 226 | |
| 227 newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension); | |
| 228 if (!newEncodedExtension) { | |
| 229 return NULL; | |
| 230 } | |
| 231 | |
| 232 rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate, | |
| 233 newEncodedExtension); | |
| 234 if (rv != SECSuccess || info == NULL) { | |
| 235 return NULL; | |
| 236 } | |
| 237 | |
| 238 for (i = 0; info[i] != NULL; i++) { | |
| 239 info[i]->location = | |
| 240 CERT_DecodeGeneralName(reqArena, &(info[i]->derLocation), NULL); | |
| 241 } | |
| 242 return info; | |
| 243 } | |
| 244 | |
| 245 SECStatus | |
| 246 CERT_EncodeInfoAccessExtension(PLArenaPool *arena, CERTAuthInfoAccess **info, | |
| 247 SECItem *dest) | |
| 248 { | |
| 249 SECItem *dummy; | |
| 250 int i; | |
| 251 | |
| 252 PORT_Assert(info != NULL); | |
| 253 PORT_Assert(dest != NULL); | |
| 254 if (info == NULL || dest == NULL) { | |
| 255 return SECFailure; | |
| 256 } | |
| 257 | |
| 258 for (i = 0; info[i] != NULL; i++) { | |
| 259 if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation), | |
| 260 arena) == NULL) | |
| 261 /* Note that this may leave some of the locations filled in. */ | |
| 262 return SECFailure; | |
| 263 } | |
| 264 dummy = SEC_ASN1EncodeItem(arena, dest, &info, CERTAuthInfoAccessTemplate); | |
| 265 if (dummy == NULL) { | |
| 266 return SECFailure; | |
| 267 } | |
| 268 return SECSuccess; | |
| 269 } | |
| OLD | NEW |