| OLD | NEW |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | 4 |
| 5 /* | 5 /* |
| 6 * Certificate Extensions handling code | 6 * Certificate Extensions handling code |
| 7 * | 7 * |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #include "cert.h" | 10 #include "cert.h" |
| 11 #include "secitem.h" | 11 #include "secitem.h" |
| 12 #include "secoid.h" | 12 #include "secoid.h" |
| 13 #include "secder.h" | 13 #include "secder.h" |
| 14 #include "secasn1.h" | 14 #include "secasn1.h" |
| 15 #include "certxutl.h" | 15 #include "certxutl.h" |
| 16 #include "secerr.h" | 16 #include "secerr.h" |
| 17 | 17 |
| 18 #ifdef OLD | 18 #ifdef OLD |
| 19 #include "ocspti.h"» /* XXX a better extensions interface would not | 19 #include "ocspti.h" /* XXX a better extensions interface would not |
| 20 * require knowledge of data structures of callers */ | 20 * require knowledge of data structures of callers */ |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 static CERTCertExtension * | 23 static CERTCertExtension * |
| 24 GetExtension (CERTCertExtension **extensions, SECItem *oid) | 24 GetExtension(CERTCertExtension **extensions, SECItem *oid) |
| 25 { | 25 { |
| 26 CERTCertExtension **exts; | 26 CERTCertExtension **exts; |
| 27 CERTCertExtension *ext = NULL; | 27 CERTCertExtension *ext = NULL; |
| 28 SECComparison comp; | 28 SECComparison comp; |
| 29 | 29 |
| 30 exts = extensions; | 30 exts = extensions; |
| 31 | 31 |
| 32 if (exts) { | 32 if (exts) { |
| 33 » while ( *exts ) { | 33 while (*exts) { |
| 34 » ext = *exts; | 34 ext = *exts; |
| 35 » comp = SECITEM_CompareItem(oid, &ext->id); | 35 comp = SECITEM_CompareItem(oid, &ext->id); |
| 36 » if ( comp == SECEqual ) | 36 if (comp == SECEqual) |
| 37 » » break; | 37 break; |
| 38 | 38 |
| 39 » exts++; | 39 exts++; |
| 40 » } | 40 } |
| 41 » return (*exts ? ext : NULL); | 41 return (*exts ? ext : NULL); |
| 42 } | 42 } |
| 43 return (NULL); | 43 return (NULL); |
| 44 } | 44 } |
| 45 | 45 |
| 46 SECStatus | 46 SECStatus |
| 47 cert_FindExtensionByOID (CERTCertExtension **extensions, SECItem *oid, SECItem *
value) | 47 cert_FindExtensionByOID(CERTCertExtension **extensions, SECItem *oid, |
| 48 SECItem *value) |
| 48 { | 49 { |
| 49 CERTCertExtension *ext; | 50 CERTCertExtension *ext; |
| 50 SECStatus rv = SECSuccess; | 51 SECStatus rv = SECSuccess; |
| 51 | 52 |
| 52 ext = GetExtension (extensions, oid); | 53 ext = GetExtension(extensions, oid); |
| 53 if (ext == NULL) { | 54 if (ext == NULL) { |
| 54 » PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND); | 55 PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); |
| 55 » return (SECFailure); | 56 return (SECFailure); |
| 56 } | 57 } |
| 57 if (value) | 58 if (value) |
| 58 » rv = SECITEM_CopyItem(NULL, value, &ext->value); | 59 rv = SECITEM_CopyItem(NULL, value, &ext->value); |
| 59 return (rv); | 60 return (rv); |
| 60 } | 61 } |
| 61 | |
| 62 | 62 |
| 63 SECStatus | 63 SECStatus |
| 64 CERT_GetExtenCriticality (CERTCertExtension **extensions, int tag, PRBool *isCri
tical) | 64 CERT_GetExtenCriticality(CERTCertExtension **extensions, int tag, |
| 65 PRBool *isCritical) |
| 65 { | 66 { |
| 66 CERTCertExtension *ext; | 67 CERTCertExtension *ext; |
| 67 SECOidData *oid; | 68 SECOidData *oid; |
| 68 | 69 |
| 69 if (!isCritical) | 70 if (!isCritical) |
| 70 » return (SECSuccess); | 71 return (SECSuccess); |
| 71 | 72 |
| 72 /* find the extension in the extensions list */ | 73 /* find the extension in the extensions list */ |
| 73 oid = SECOID_FindOIDByTag((SECOidTag)tag); | 74 oid = SECOID_FindOIDByTag((SECOidTag)tag); |
| 74 if ( !oid ) { | 75 if (!oid) { |
| 75 » return(SECFailure); | 76 return (SECFailure); |
| 76 } | 77 } |
| 77 ext = GetExtension (extensions, &oid->oid); | 78 ext = GetExtension(extensions, &oid->oid); |
| 78 if (ext == NULL) { | 79 if (ext == NULL) { |
| 79 » PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND); | 80 PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); |
| 80 » return (SECFailure); | 81 return (SECFailure); |
| 81 } | 82 } |
| 82 | 83 |
| 83 /* If the criticality is omitted, then it is false by default. | 84 /* If the criticality is omitted, then it is false by default. |
| 84 ex->critical.data is NULL */ | 85 ex->critical.data is NULL */ |
| 85 if (ext->critical.data == NULL) | 86 if (ext->critical.data == NULL) |
| 86 » *isCritical = PR_FALSE; | 87 *isCritical = PR_FALSE; |
| 87 else | 88 else |
| 88 » *isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE; | 89 *isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE; |
| 89 return (SECSuccess); | 90 return (SECSuccess); |
| 90 } | 91 } |
| 91 | 92 |
| 92 SECStatus | 93 SECStatus |
| 93 cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value) | 94 cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value) |
| 94 { | 95 { |
| 95 SECOidData *oid; | 96 SECOidData *oid; |
| 96 | 97 |
| 97 oid = SECOID_FindOIDByTag((SECOidTag)tag); | 98 oid = SECOID_FindOIDByTag((SECOidTag)tag); |
| 98 if ( !oid ) { | 99 if (!oid) { |
| 99 » return(SECFailure); | 100 return (SECFailure); |
| 100 } | 101 } |
| 101 | 102 |
| 102 return(cert_FindExtensionByOID(extensions, &oid->oid, value)); | 103 return (cert_FindExtensionByOID(extensions, &oid->oid, value)); |
| 103 } | 104 } |
| 104 | 105 |
| 105 | |
| 106 typedef struct _extNode { | 106 typedef struct _extNode { |
| 107 struct _extNode *next; | 107 struct _extNode *next; |
| 108 CERTCertExtension *ext; | 108 CERTCertExtension *ext; |
| 109 } extNode; | 109 } extNode; |
| 110 | 110 |
| 111 typedef struct { | 111 typedef struct { |
| 112 void (*setExts)(void *object, CERTCertExtension **exts); | 112 void (*setExts)(void *object, CERTCertExtension **exts); |
| 113 void *object; | 113 void *object; |
| 114 PLArenaPool *ownerArena; | 114 PLArenaPool *ownerArena; |
| 115 PLArenaPool *arena; | 115 PLArenaPool *arena; |
| 116 extNode *head; | 116 extNode *head; |
| 117 int count; | 117 int count; |
| 118 }extRec; | 118 } extRec; |
| 119 | 119 |
| 120 /* | 120 /* |
| 121 * cert_StartExtensions | 121 * cert_StartExtensions |
| 122 * | 122 * |
| 123 * NOTE: This interface changed significantly to remove knowledge | 123 * NOTE: This interface changed significantly to remove knowledge |
| 124 * about callers data structures (owner objects) | 124 * about callers data structures (owner objects) |
| 125 */ | 125 */ |
| 126 void * | 126 void * |
| 127 cert_StartExtensions(void *owner, PLArenaPool *ownerArena, | 127 cert_StartExtensions(void *owner, PLArenaPool *ownerArena, |
| 128 void (*setExts)(void *object, CERTCertExtension **exts)) | 128 void (*setExts)(void *object, CERTCertExtension **exts)) |
| 129 { | 129 { |
| 130 PLArenaPool *arena; | 130 PLArenaPool *arena; |
| 131 extRec *handle; | 131 extRec *handle; |
| 132 | 132 |
| 133 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 133 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 134 if ( !arena ) { | 134 if (!arena) { |
| 135 » return(0); | 135 return (0); |
| 136 } | 136 } |
| 137 | 137 |
| 138 handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec)); | 138 handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec)); |
| 139 if ( !handle ) { | 139 if (!handle) { |
| 140 » PORT_FreeArena(arena, PR_FALSE); | 140 PORT_FreeArena(arena, PR_FALSE); |
| 141 » return(0); | 141 return (0); |
| 142 } | 142 } |
| 143 | 143 |
| 144 handle->object = owner; | 144 handle->object = owner; |
| 145 handle->ownerArena = ownerArena; | 145 handle->ownerArena = ownerArena; |
| 146 handle->setExts = setExts; | 146 handle->setExts = setExts; |
| 147 | 147 |
| 148 handle->arena = arena; | 148 handle->arena = arena; |
| 149 handle->head = 0; | 149 handle->head = 0; |
| 150 handle->count = 0; | 150 handle->count = 0; |
| 151 | 151 |
| 152 return(handle); | 152 return (handle); |
| 153 } | 153 } |
| 154 | 154 |
| 155 static unsigned char hextrue = 0xff; | 155 static unsigned char hextrue = 0xff; |
| 156 | 156 |
| 157 /* | 157 /* |
| 158 * Note - assumes that data pointed to by oid->data will not move | 158 * Note - assumes that data pointed to by oid->data will not move |
| 159 */ | 159 */ |
| 160 SECStatus | 160 SECStatus |
| 161 CERT_AddExtensionByOID (void *exthandle, SECItem *oid, SECItem *value, | 161 CERT_AddExtensionByOID(void *exthandle, SECItem *oid, SECItem *value, |
| 162 » » » PRBool critical, PRBool copyData) | 162 PRBool critical, PRBool copyData) |
| 163 { | 163 { |
| 164 CERTCertExtension *ext; | 164 CERTCertExtension *ext; |
| 165 SECStatus rv; | 165 SECStatus rv; |
| 166 extNode *node; | 166 extNode *node; |
| 167 extRec *handle; | 167 extRec *handle; |
| 168 | 168 |
| 169 handle = (extRec *)exthandle; | 169 handle = (extRec *)exthandle; |
| 170 | 170 |
| 171 /* allocate space for extension and list node */ | 171 /* allocate space for extension and list node */ |
| 172 ext = (CERTCertExtension*)PORT_ArenaZAlloc(handle->ownerArena, | 172 ext = (CERTCertExtension *)PORT_ArenaZAlloc(handle->ownerArena, |
| 173 sizeof(CERTCertExtension)); | 173 sizeof(CERTCertExtension)); |
| 174 if ( !ext ) { | 174 if (!ext) { |
| 175 » return(SECFailure); | 175 return (SECFailure); |
| 176 } | 176 } |
| 177 | 177 |
| 178 node = (extNode*)PORT_ArenaAlloc(handle->arena, sizeof(extNode)); | 178 node = (extNode *)PORT_ArenaAlloc(handle->arena, sizeof(extNode)); |
| 179 if ( !node ) { | 179 if (!node) { |
| 180 » return(SECFailure); | 180 return (SECFailure); |
| 181 } | 181 } |
| 182 | 182 |
| 183 /* add to list */ | 183 /* add to list */ |
| 184 node->next = handle->head; | 184 node->next = handle->head; |
| 185 handle->head = node; | 185 handle->head = node; |
| 186 | 186 |
| 187 /* point to ext struct */ | 187 /* point to ext struct */ |
| 188 node->ext = ext; | 188 node->ext = ext; |
| 189 | 189 |
| 190 /* the object ID of the extension */ | 190 /* the object ID of the extension */ |
| 191 ext->id = *oid; | 191 ext->id = *oid; |
| 192 | 192 |
| 193 /* set critical field */ | 193 /* set critical field */ |
| 194 if ( critical ) { | 194 if (critical) { |
| 195 » ext->critical.data = (unsigned char*)&hextrue; | 195 ext->critical.data = (unsigned char *)&hextrue; |
| 196 » ext->critical.len = 1; | 196 ext->critical.len = 1; |
| 197 } | 197 } |
| 198 | 198 |
| 199 /* set the value */ | 199 /* set the value */ |
| 200 if ( copyData ) { | 200 if (copyData) { |
| 201 » rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value); | 201 rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value); |
| 202 » if ( rv ) { | 202 if (rv) { |
| 203 » return(SECFailure); | 203 return (SECFailure); |
| 204 » } | 204 } |
| 205 } else { | 205 } else { |
| 206 » ext->value = *value; | 206 ext->value = *value; |
| 207 } | 207 } |
| 208 | 208 |
| 209 handle->count++; | 209 handle->count++; |
| 210 | |
| 211 return(SECSuccess); | |
| 212 | 210 |
| 211 return (SECSuccess); |
| 213 } | 212 } |
| 214 | 213 |
| 215 SECStatus | 214 SECStatus |
| 216 CERT_AddExtension(void *exthandle, int idtag, SECItem *value, | 215 CERT_AddExtension(void *exthandle, int idtag, SECItem *value, PRBool critical, |
| 217 » » PRBool critical, PRBool copyData) | 216 PRBool copyData) |
| 218 { | 217 { |
| 219 SECOidData *oid; | 218 SECOidData *oid; |
| 220 | 219 |
| 221 oid = SECOID_FindOIDByTag((SECOidTag)idtag); | 220 oid = SECOID_FindOIDByTag((SECOidTag)idtag); |
| 222 if ( !oid ) { | 221 if (!oid) { |
| 223 » return(SECFailure); | 222 return (SECFailure); |
| 224 } | 223 } |
| 225 | 224 |
| 226 return(CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical, copyDat
a)); | 225 return (CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical, |
| 226 copyData)); |
| 227 } | 227 } |
| 228 | 228 |
| 229 SECStatus | 229 SECStatus |
| 230 CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value, | 230 CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value, |
| 231 » » » PRBool critical, const SEC_ASN1Template *atemplate) | 231 PRBool critical, const SEC_ASN1Template *atemplate) |
| 232 { | 232 { |
| 233 extRec *handle; | 233 extRec *handle; |
| 234 SECItem *encitem; | 234 SECItem *encitem; |
| 235 | 235 |
| 236 handle = (extRec *)exthandle; | 236 handle = (extRec *)exthandle; |
| 237 | 237 |
| 238 encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate); | 238 encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate); |
| 239 if ( encitem == NULL ) { | 239 if (encitem == NULL) { |
| 240 » return(SECFailure); | 240 return (SECFailure); |
| 241 } | 241 } |
| 242 | 242 |
| 243 return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE); | 243 return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE); |
| 244 } | 244 } |
| 245 | 245 |
| 246 void | 246 void |
| 247 PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value) | 247 PrepareBitStringForEncoding(SECItem *bitsmap, SECItem *value) |
| 248 { | 248 { |
| 249 unsigned char onebyte; | 249 unsigned char onebyte; |
| 250 unsigned int i, len = 0; | 250 unsigned int i, len = 0; |
| 251 | 251 |
| 252 /* to prevent warning on some platform at compile time */ | 252 /* to prevent warning on some platform at compile time */ |
| 253 onebyte = '\0'; | 253 onebyte = '\0'; |
| 254 /* Get the position of the right-most turn-on bit */ | 254 /* Get the position of the right-most turn-on bit */ |
| 255 for (i = 0; i < (value->len ) * 8; ++i) { | 255 for (i = 0; i < (value->len) * 8; ++i) { |
| 256 if (i % 8 == 0) | 256 if (i % 8 == 0) |
| 257 » onebyte = value->data[i/8]; | 257 onebyte = value->data[i / 8]; |
| 258 if (onebyte & 0x80) | 258 if (onebyte & 0x80) |
| 259 » len = i; | 259 len = i; |
| 260 onebyte <<= 1; | 260 onebyte <<= 1; |
| 261 | 261 } |
| 262 } | 262 bitsmap->data = value->data; |
| 263 bitsmap->data = value->data; | 263 /* Add one here since we work with base 1 */ |
| 264 /* Add one here since we work with base 1 */ | 264 bitsmap->len = len + 1; |
| 265 bitsmap->len = len + 1; | |
| 266 } | 265 } |
| 267 | 266 |
| 268 SECStatus | 267 SECStatus |
| 269 CERT_EncodeAndAddBitStrExtension (void *exthandle, int idtag, | 268 CERT_EncodeAndAddBitStrExtension(void *exthandle, int idtag, SECItem *value, |
| 270 » » » » SECItem *value, PRBool critical) | 269 PRBool critical) |
| 271 { | 270 { |
| 272 SECItem bitsmap; | 271 SECItem bitsmap; |
| 273 | 272 |
| 274 PrepareBitStringForEncoding (&bitsmap, value); | 273 PrepareBitStringForEncoding(&bitsmap, value); |
| 275 return (CERT_EncodeAndAddExtension | 274 return (CERT_EncodeAndAddExtension(exthandle, idtag, &bitsmap, critical, |
| 276 » (exthandle, idtag, &bitsmap, critical, | 275 SEC_ASN1_GET(SEC_BitStringTemplate))); |
| 277 SEC_ASN1_GET(SEC_BitStringTemplate))); | |
| 278 } | 276 } |
| 279 | 277 |
| 280 SECStatus | 278 SECStatus |
| 281 CERT_FinishExtensions(void *exthandle) | 279 CERT_FinishExtensions(void *exthandle) |
| 282 { | 280 { |
| 283 extRec *handle; | 281 extRec *handle; |
| 284 extNode *node; | 282 extNode *node; |
| 285 CERTCertExtension **exts; | 283 CERTCertExtension **exts; |
| 286 SECStatus rv = SECFailure; | 284 SECStatus rv = SECFailure; |
| 287 | 285 |
| 288 handle = (extRec *)exthandle; | 286 handle = (extRec *)exthandle; |
| 289 | 287 |
| 290 /* allocate space for extensions array */ | 288 /* allocate space for extensions array */ |
| 291 exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *, | 289 exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *, |
| 292 » » » handle->count + 1); | 290 handle->count + 1); |
| 293 if (exts == NULL) { | 291 if (exts == NULL) { |
| 294 » goto loser; | 292 goto loser; |
| 295 } | 293 } |
| 296 | 294 |
| 297 /* put extensions in owner object and update its version number */ | 295 /* put extensions in owner object and update its version number */ |
| 298 | 296 |
| 299 #ifdef OLD | 297 #ifdef OLD |
| 300 switch (handle->type) { | 298 switch (handle->type) { |
| 301 case CertificateExtensions: | 299 case CertificateExtensions: |
| 302 » handle->owner.cert->extensions = exts; | 300 handle->owner.cert->extensions = exts; |
| 303 » DER_SetUInteger (ownerArena, &(handle->owner.cert->version), | 301 DER_SetUInteger(ownerArena, &(handle->owner.cert->version), |
| 304 » » » SEC_CERTIFICATE_VERSION_3); | 302 SEC_CERTIFICATE_VERSION_3); |
| 305 » break; | 303 break; |
| 306 case CrlExtensions: | 304 case CrlExtensions: |
| 307 » handle->owner.crl->extensions = exts; | 305 handle->owner.crl->extensions = exts; |
| 308 » DER_SetUInteger (ownerArena, &(handle->owner.crl->version), | 306 DER_SetUInteger(ownerArena, &(handle->owner.crl->version), |
| 309 » » » SEC_CRL_VERSION_2); | 307 SEC_CRL_VERSION_2); |
| 310 » break; | 308 break; |
| 311 case OCSPRequestExtensions: | 309 case OCSPRequestExtensions: |
| 312 » handle->owner.request->tbsRequest->requestExtensions = exts; | 310 handle->owner.request->tbsRequest->requestExtensions = exts; |
| 313 » break; | 311 break; |
| 314 case OCSPSingleRequestExtensions: | 312 case OCSPSingleRequestExtensions: |
| 315 » handle->owner.singleRequest->singleRequestExtensions = exts;» | 313 handle->owner.singleRequest->singleRequestExtensions = exts; |
| 316 » break; | 314 break; |
| 317 case OCSPResponseSingleExtensions: | 315 case OCSPResponseSingleExtensions: |
| 318 » handle->owner.singleResponse->singleExtensions = exts;» | 316 handle->owner.singleResponse->singleExtensions = exts; |
| 319 » break; | 317 break; |
| 320 } | 318 } |
| 321 #endif | 319 #endif |
| 322 | 320 |
| 323 handle->setExts(handle->object, exts); | 321 handle->setExts(handle->object, exts); |
| 324 » | 322 |
| 325 /* update the version number */ | 323 /* update the version number */ |
| 326 | 324 |
| 327 /* copy each extension pointer */ | 325 /* copy each extension pointer */ |
| 328 node = handle->head; | 326 node = handle->head; |
| 329 while ( node ) { | 327 while (node) { |
| 330 » *exts = node->ext; | 328 *exts = node->ext; |
| 331 » | 329 |
| 332 » node = node->next; | 330 node = node->next; |
| 333 » exts++; | 331 exts++; |
| 334 } | 332 } |
| 335 | 333 |
| 336 /* terminate the array of extensions */ | 334 /* terminate the array of extensions */ |
| 337 *exts = 0; | 335 *exts = 0; |
| 338 | 336 |
| 339 rv = SECSuccess; | 337 rv = SECSuccess; |
| 340 | 338 |
| 341 loser: | 339 loser: |
| 342 /* free working arena */ | 340 /* free working arena */ |
| 343 PORT_FreeArena(handle->arena, PR_FALSE); | 341 PORT_FreeArena(handle->arena, PR_FALSE); |
| 344 return rv; | 342 return rv; |
| 345 } | 343 } |
| 346 | 344 |
| 347 SECStatus | 345 SECStatus |
| 348 CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions) | 346 CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions) |
| 349 { | 347 { |
| 350 CERTCertExtension *ext; | 348 CERTCertExtension *ext; |
| 351 SECStatus rv = SECSuccess; | 349 SECStatus rv = SECSuccess; |
| 352 SECOidTag tag; | 350 SECOidTag tag; |
| 353 extNode *node; | 351 extNode *node; |
| 354 extRec *handle = exthandle; | 352 extRec *handle = exthandle; |
| 355 | 353 |
| 356 if (!exthandle || !extensions) { | 354 if (!exthandle || !extensions) { |
| 357 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 355 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 358 return SECFailure; | 356 return SECFailure; |
| 359 } | 357 } |
| 360 while ((ext = *extensions++) != NULL) { | 358 while ((ext = *extensions++) != NULL) { |
| 361 tag = SECOID_FindOIDTag(&ext->id); | 359 tag = SECOID_FindOIDTag(&ext->id); |
| 362 for (node=handle->head; node != NULL; node=node->next) { | 360 for (node = handle->head; node != NULL; node = node->next) { |
| 363 if (tag == 0) { | 361 if (tag == 0) { |
| 364 if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id)) | 362 if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id)) |
| 365 break; | 363 break; |
| 366 } | 364 } else { |
| 367 else { | |
| 368 if (SECOID_FindOIDTag(&node->ext->id) == tag) { | 365 if (SECOID_FindOIDTag(&node->ext->id) == tag) { |
| 369 break; | 366 break; |
| 370 } | 367 } |
| 371 } | 368 } |
| 372 } | 369 } |
| 373 if (node == NULL) { | 370 if (node == NULL) { |
| 374 PRBool critical = (ext->critical.len != 0 && | 371 PRBool critical = (ext->critical.len != 0 && |
| 375 ext->critical.data[ext->critical.len - 1] != 0); | 372 ext->critical.data[ext->critical.len - 1] != 0); |
| 376 if (critical && tag == SEC_OID_UNKNOWN) { | 373 if (critical && tag == SEC_OID_UNKNOWN) { |
| 377 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); | 374 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); |
| 378 rv = SECFailure; | 375 rv = SECFailure; |
| 379 break; | 376 break; |
| 380 } | 377 } |
| 381 /* add to list */ | 378 /* add to list */ |
| 382 rv = CERT_AddExtensionByOID (exthandle, &ext->id, &ext->value, | 379 rv = CERT_AddExtensionByOID(exthandle, &ext->id, &ext->value, |
| 383 critical, PR_TRUE); | 380 critical, PR_TRUE); |
| 384 if (rv != SECSuccess) | 381 if (rv != SECSuccess) |
| 385 break; | 382 break; |
| 386 } | 383 } |
| 387 } | 384 } |
| 388 return rv; | 385 return rv; |
| 389 } | 386 } |
| 390 | 387 |
| 391 /* | 388 /* |
| 392 * get the value of the Netscape Certificate Type Extension | 389 * get the value of the Netscape Certificate Type Extension |
| 393 */ | 390 */ |
| 394 SECStatus | 391 SECStatus |
| 395 CERT_FindBitStringExtension (CERTCertExtension **extensions, int tag, | 392 CERT_FindBitStringExtension(CERTCertExtension **extensions, int tag, |
| 396 » » » SECItem *retItem) | 393 SECItem *retItem) |
| 397 { | 394 { |
| 398 SECItem wrapperItem, tmpItem = {siBuffer,0}; | 395 SECItem wrapperItem, tmpItem = { siBuffer, 0 }; |
| 399 SECStatus rv; | 396 SECStatus rv; |
| 400 PLArenaPool *arena = NULL; | 397 PLArenaPool *arena = NULL; |
| 401 | 398 |
| 402 wrapperItem.data = NULL; | 399 wrapperItem.data = NULL; |
| 403 tmpItem.data = NULL; | 400 tmpItem.data = NULL; |
| 404 | 401 |
| 405 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 402 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 406 | 403 |
| 407 if ( ! arena ) { | 404 if (!arena) { |
| 408 » return(SECFailure); | 405 return (SECFailure); |
| 409 } | |
| 410 | |
| 411 rv = cert_FindExtension(extensions, tag, &wrapperItem); | |
| 412 if ( rv != SECSuccess ) { | |
| 413 » goto loser; | |
| 414 } | 406 } |
| 415 | 407 |
| 416 rv = SEC_QuickDERDecodeItem(arena, &tmpItem, | 408 rv = cert_FindExtension(extensions, tag, &wrapperItem); |
| 417 SEC_ASN1_GET(SEC_BitStringTemplate), | 409 if (rv != SECSuccess) { |
| 418 &wrapperItem); | 410 goto loser; |
| 419 | |
| 420 if ( rv != SECSuccess ) { | |
| 421 » goto loser; | |
| 422 } | 411 } |
| 423 | 412 |
| 424 retItem->data = (unsigned char *)PORT_Alloc( ( tmpItem.len + 7 ) >> 3 ); | 413 rv = SEC_QuickDERDecodeItem( |
| 425 if ( retItem->data == NULL ) { | 414 arena, &tmpItem, SEC_ASN1_GET(SEC_BitStringTemplate), &wrapperItem); |
| 426 » goto loser; | 415 |
| 416 if (rv != SECSuccess) { |
| 417 goto loser; |
| 427 } | 418 } |
| 428 | 419 |
| 429 PORT_Memcpy(retItem->data, tmpItem.data, ( tmpItem.len + 7 ) >> 3); | 420 retItem->data = (unsigned char *)PORT_Alloc((tmpItem.len + 7) >> 3); |
| 421 if (retItem->data == NULL) { |
| 422 goto loser; |
| 423 } |
| 424 |
| 425 PORT_Memcpy(retItem->data, tmpItem.data, (tmpItem.len + 7) >> 3); |
| 430 retItem->len = tmpItem.len; | 426 retItem->len = tmpItem.len; |
| 431 | 427 |
| 432 rv = SECSuccess; | 428 rv = SECSuccess; |
| 433 goto done; | 429 goto done; |
| 434 | 430 |
| 435 loser: | 431 loser: |
| 436 rv = SECFailure; | 432 rv = SECFailure; |
| 437 | 433 |
| 438 done: | 434 done: |
| 439 if ( arena ) { | 435 if (arena) { |
| 440 » PORT_FreeArena(arena, PR_FALSE); | 436 PORT_FreeArena(arena, PR_FALSE); |
| 441 } | |
| 442 | |
| 443 if ( wrapperItem.data ) { | |
| 444 » PORT_Free(wrapperItem.data); | |
| 445 } | 437 } |
| 446 | 438 |
| 447 return(rv); | 439 if (wrapperItem.data) { |
| 440 PORT_Free(wrapperItem.data); |
| 441 } |
| 442 |
| 443 return (rv); |
| 448 } | 444 } |
| 449 | 445 |
| 450 PRBool | 446 PRBool |
| 451 cert_HasCriticalExtension (CERTCertExtension **extensions) | 447 cert_HasCriticalExtension(CERTCertExtension **extensions) |
| 452 { | 448 { |
| 453 CERTCertExtension **exts; | 449 CERTCertExtension **exts; |
| 454 CERTCertExtension *ext = NULL; | 450 CERTCertExtension *ext = NULL; |
| 455 PRBool hasCriticalExten = PR_FALSE; | 451 PRBool hasCriticalExten = PR_FALSE; |
| 456 | 452 |
| 457 exts = extensions; | 453 exts = extensions; |
| 458 | 454 |
| 459 if (exts) { | 455 if (exts) { |
| 460 » while ( *exts ) { | 456 while (*exts) { |
| 461 » ext = *exts; | 457 ext = *exts; |
| 462 » /* If the criticality is omitted, it's non-critical */ | 458 /* If the criticality is omitted, it's non-critical */ |
| 463 » if (ext->critical.data && ext->critical.data[0] == 0xff) { | 459 if (ext->critical.data && ext->critical.data[0] == 0xff) { |
| 464 » » hasCriticalExten = PR_TRUE; | 460 hasCriticalExten = PR_TRUE; |
| 465 » » break; | 461 break; |
| 466 » } | 462 } |
| 467 » exts++; | 463 exts++; |
| 468 » } | 464 } |
| 469 } | 465 } |
| 470 return (hasCriticalExten); | 466 return (hasCriticalExten); |
| 471 } | 467 } |
| 472 | 468 |
| 473 PRBool | 469 PRBool |
| 474 cert_HasUnknownCriticalExten (CERTCertExtension **extensions) | 470 cert_HasUnknownCriticalExten(CERTCertExtension **extensions) |
| 475 { | 471 { |
| 476 CERTCertExtension **exts; | 472 CERTCertExtension **exts; |
| 477 CERTCertExtension *ext = NULL; | 473 CERTCertExtension *ext = NULL; |
| 478 PRBool hasUnknownCriticalExten = PR_FALSE; | 474 PRBool hasUnknownCriticalExten = PR_FALSE; |
| 479 | 475 |
| 480 exts = extensions; | 476 exts = extensions; |
| 481 | 477 |
| 482 if (exts) { | 478 if (exts) { |
| 483 » while ( *exts ) { | 479 while (*exts) { |
| 484 » ext = *exts; | 480 ext = *exts; |
| 485 » /* If the criticality is omitted, it's non-critical. | 481 /* If the criticality is omitted, it's non-critical. |
| 486 » If an extension is critical, make sure that we know | 482 If an extension is critical, make sure that we know |
| 487 » how to process the extension. | 483 how to process the extension. |
| 488 */ | 484 */ |
| 489 » if (ext->critical.data && ext->critical.data[0] == 0xff) { | 485 if (ext->critical.data && ext->critical.data[0] == 0xff) { |
| 490 » » if (SECOID_KnownCertExtenOID (&ext->id) == PR_FALSE) { | 486 if (SECOID_KnownCertExtenOID(&ext->id) == PR_FALSE) { |
| 491 » » hasUnknownCriticalExten = PR_TRUE; | 487 hasUnknownCriticalExten = PR_TRUE; |
| 492 » » break; | 488 break; |
| 493 » » } | 489 } |
| 494 » } | 490 } |
| 495 » exts++; | 491 exts++; |
| 496 » } | 492 } |
| 497 } | 493 } |
| 498 return (hasUnknownCriticalExten); | 494 return (hasUnknownCriticalExten); |
| 499 } | 495 } |
| OLD | NEW |