xconst.c (7671B)
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 }