security/nss/cmd/crlutil/crlgen.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 ** crlgen.c
michael@0 7 **
michael@0 8 ** utility for managing certificates revocation lists generation
michael@0 9 **
michael@0 10 */
michael@0 11
michael@0 12
michael@0 13 #include <stdio.h>
michael@0 14 #include <math.h>
michael@0 15
michael@0 16 #include "nspr.h"
michael@0 17 #include "plgetopt.h"
michael@0 18 #include "nss.h"
michael@0 19 #include "secutil.h"
michael@0 20 #include "cert.h"
michael@0 21 #include "certi.h"
michael@0 22 #include "certdb.h"
michael@0 23 #include "pk11func.h"
michael@0 24 #include "crlgen.h"
michael@0 25
michael@0 26
michael@0 27 /* Destroys extHandle and data. data was create on heap.
michael@0 28 * extHandle creaded by CERT_StartCRLEntryExtensions. entry
michael@0 29 * was allocated on arena.*/
michael@0 30 static void
michael@0 31 destroyEntryData(CRLGENEntryData *data)
michael@0 32 {
michael@0 33 if (!data)
michael@0 34 return;
michael@0 35 PORT_Assert(data->entry);
michael@0 36 if (data->extHandle)
michael@0 37 CERT_FinishExtensions(data->extHandle);
michael@0 38 PORT_Free(data);
michael@0 39 }
michael@0 40
michael@0 41
michael@0 42 /* Prints error messages along with line number */
michael@0 43 void
michael@0 44 crlgen_PrintError(int line, char *msg, ...)
michael@0 45 {
michael@0 46 va_list args;
michael@0 47
michael@0 48 va_start(args, msg);
michael@0 49
michael@0 50 fprintf(stderr, "crlgen: (line: %d) ", line);
michael@0 51 vfprintf(stderr, msg, args);
michael@0 52
michael@0 53 va_end(args);
michael@0 54 }
michael@0 55 /* Finds CRLGENEntryData in hashtable according PRUint64 value
michael@0 56 * - certId : cert serial number*/
michael@0 57 static CRLGENEntryData*
michael@0 58 crlgen_FindEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
michael@0 59 {
michael@0 60 if (!crlGenData->entryDataHashTable || !certId)
michael@0 61 return NULL;
michael@0 62 return (CRLGENEntryData*)
michael@0 63 PL_HashTableLookup(crlGenData->entryDataHashTable,
michael@0 64 certId);
michael@0 65 }
michael@0 66
michael@0 67
michael@0 68 /* Removes CRLGENEntryData from hashtable according to certId
michael@0 69 * - certId : cert serial number*/
michael@0 70 static SECStatus
michael@0 71 crlgen_RmEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
michael@0 72 {
michael@0 73 CRLGENEntryData *data = NULL;
michael@0 74
michael@0 75 if (!crlGenData->entryDataHashTable)
michael@0 76 return SECSuccess;
michael@0 77 data = crlgen_FindEntry(crlGenData, certId);
michael@0 78 if (!data)
michael@0 79 return SECSuccess;
michael@0 80 if (PL_HashTableRemove(crlGenData->entryDataHashTable, certId))
michael@0 81 return SECSuccess;
michael@0 82 destroyEntryData(data);
michael@0 83 return SECFailure;
michael@0 84 }
michael@0 85
michael@0 86
michael@0 87 /* Stores CRLGENEntryData in hashtable according to certId
michael@0 88 * - certId : cert serial number*/
michael@0 89 static CRLGENEntryData*
michael@0 90 crlgen_PlaceAnEntry(CRLGENGeneratorData *crlGenData,
michael@0 91 CERTCrlEntry *entry, SECItem *certId)
michael@0 92 {
michael@0 93 CRLGENEntryData *newData = NULL;
michael@0 94
michael@0 95 PORT_Assert(crlGenData && crlGenData->entryDataHashTable &&
michael@0 96 entry);
michael@0 97 if (!crlGenData || !crlGenData->entryDataHashTable || !entry) {
michael@0 98 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 99 return NULL;
michael@0 100 }
michael@0 101
michael@0 102 newData = PORT_ZNew(CRLGENEntryData);
michael@0 103 if (!newData) {
michael@0 104 return NULL;
michael@0 105 }
michael@0 106 newData->entry = entry;
michael@0 107 newData->certId = certId;
michael@0 108 if (!PL_HashTableAdd(crlGenData->entryDataHashTable,
michael@0 109 newData->certId, newData)) {
michael@0 110 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 111 "Can not add entryData structure\n");
michael@0 112 return NULL;
michael@0 113 }
michael@0 114 return newData;
michael@0 115 }
michael@0 116
michael@0 117 /* Use this structure to keep pointer when commiting entries extensions */
michael@0 118 struct commitData {
michael@0 119 int pos;
michael@0 120 CERTCrlEntry **entries;
michael@0 121 };
michael@0 122
michael@0 123 /* HT PL_HashTableEnumerateEntries callback. Sorts hashtable entries of the
michael@0 124 * table he. Returns value through arg parameter*/
michael@0 125 static PRIntn PR_CALLBACK
michael@0 126 crlgen_CommitEntryData(PLHashEntry *he, PRIntn i, void *arg)
michael@0 127 {
michael@0 128 CRLGENEntryData *data = NULL;
michael@0 129
michael@0 130 PORT_Assert(he);
michael@0 131 if (!he) {
michael@0 132 return HT_ENUMERATE_NEXT;
michael@0 133 }
michael@0 134 data = (CRLGENEntryData*)he->value;
michael@0 135
michael@0 136 PORT_Assert(data);
michael@0 137 PORT_Assert(arg);
michael@0 138
michael@0 139 if (data) {
michael@0 140 struct commitData *dt = (struct commitData*)arg;
michael@0 141 dt->entries[dt->pos++] = data->entry;
michael@0 142 destroyEntryData(data);
michael@0 143 }
michael@0 144 return HT_ENUMERATE_NEXT;
michael@0 145 }
michael@0 146
michael@0 147
michael@0 148
michael@0 149 /* Copy char * datainto allocated in arena SECItem */
michael@0 150 static SECStatus
michael@0 151 crlgen_SetString(PLArenaPool *arena, const char *dataIn, SECItem *value)
michael@0 152 {
michael@0 153 SECItem item;
michael@0 154
michael@0 155 PORT_Assert(arena && dataIn);
michael@0 156 if (!arena || !dataIn) {
michael@0 157 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 158 return SECFailure;
michael@0 159 }
michael@0 160
michael@0 161 item.data = (void*)dataIn;
michael@0 162 item.len = PORT_Strlen(dataIn);
michael@0 163
michael@0 164 return SECITEM_CopyItem(arena, value, &item);
michael@0 165 }
michael@0 166
michael@0 167 /* Creates CERTGeneralName from parsed data for the Authority Key Extension */
michael@0 168 static CERTGeneralName *
michael@0 169 crlgen_GetGeneralName (PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
michael@0 170 const char *data)
michael@0 171 {
michael@0 172 CERTGeneralName *namesList = NULL;
michael@0 173 CERTGeneralName *current;
michael@0 174 CERTGeneralName *tail = NULL;
michael@0 175 SECStatus rv = SECSuccess;
michael@0 176 const char *nextChunk = NULL;
michael@0 177 const char *currData = NULL;
michael@0 178 int intValue;
michael@0 179 char buffer[512];
michael@0 180 void *mark;
michael@0 181
michael@0 182 if (!data)
michael@0 183 return NULL;
michael@0 184 PORT_Assert (arena);
michael@0 185 if (!arena) {
michael@0 186 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 187 return NULL;
michael@0 188 }
michael@0 189
michael@0 190 mark = PORT_ArenaMark (arena);
michael@0 191
michael@0 192 nextChunk = data;
michael@0 193 currData = data;
michael@0 194 do {
michael@0 195 int nameLen = 0;
michael@0 196 char name[128];
michael@0 197 const char *sepPrt = NULL;
michael@0 198 nextChunk = PORT_Strchr(currData, '|');
michael@0 199 if (!nextChunk)
michael@0 200 nextChunk = data + strlen(data);
michael@0 201 sepPrt = PORT_Strchr(currData, ':');
michael@0 202 if (sepPrt == NULL || sepPrt >= nextChunk) {
michael@0 203 *buffer = '\0';
michael@0 204 sepPrt = nextChunk;
michael@0 205 } else {
michael@0 206 PORT_Memcpy(buffer, sepPrt + 1,
michael@0 207 (nextChunk - sepPrt - 1));
michael@0 208 buffer[nextChunk - sepPrt - 1] = '\0';
michael@0 209 }
michael@0 210 nameLen = PR_MIN(sepPrt - currData, sizeof(name) - 1 );
michael@0 211 PORT_Memcpy(name, currData, nameLen);
michael@0 212 name[nameLen] = '\0';
michael@0 213 currData = nextChunk + 1;
michael@0 214
michael@0 215 if (!PORT_Strcmp(name, "otherName"))
michael@0 216 intValue = certOtherName;
michael@0 217 else if (!PORT_Strcmp(name, "rfc822Name"))
michael@0 218 intValue = certRFC822Name;
michael@0 219 else if (!PORT_Strcmp(name, "dnsName"))
michael@0 220 intValue = certDNSName;
michael@0 221 else if (!PORT_Strcmp(name, "x400Address"))
michael@0 222 intValue = certX400Address;
michael@0 223 else if (!PORT_Strcmp(name, "directoryName"))
michael@0 224 intValue = certDirectoryName;
michael@0 225 else if (!PORT_Strcmp(name, "ediPartyName"))
michael@0 226 intValue = certEDIPartyName;
michael@0 227 else if (!PORT_Strcmp(name, "URI"))
michael@0 228 intValue = certURI;
michael@0 229 else if (!PORT_Strcmp(name, "ipAddress"))
michael@0 230 intValue = certIPAddress;
michael@0 231 else if (!PORT_Strcmp(name, "registerID"))
michael@0 232 intValue = certRegisterID;
michael@0 233 else intValue = -1;
michael@0 234
michael@0 235 if (intValue >= certOtherName && intValue <= certRegisterID) {
michael@0 236 if (namesList == NULL) {
michael@0 237 namesList = current = tail = PORT_ArenaZNew(arena,
michael@0 238 CERTGeneralName);
michael@0 239 } else {
michael@0 240 current = PORT_ArenaZNew(arena, CERTGeneralName);
michael@0 241 }
michael@0 242 if (current == NULL) {
michael@0 243 rv = SECFailure;
michael@0 244 break;
michael@0 245 }
michael@0 246 } else {
michael@0 247 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 248 break;
michael@0 249 }
michael@0 250 current->type = intValue;
michael@0 251 switch (current->type) {
michael@0 252 case certURI:
michael@0 253 case certDNSName:
michael@0 254 case certRFC822Name:
michael@0 255 current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer));
michael@0 256 if (current->name.other.data == NULL) {
michael@0 257 rv = SECFailure;
michael@0 258 break;
michael@0 259 }
michael@0 260 PORT_Memcpy(current->name.other.data, buffer,
michael@0 261 current->name.other.len = strlen(buffer));
michael@0 262 break;
michael@0 263
michael@0 264 case certEDIPartyName:
michael@0 265 case certIPAddress:
michael@0 266 case certOtherName:
michael@0 267 case certRegisterID:
michael@0 268 case certX400Address: {
michael@0 269
michael@0 270 current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer) + 2);
michael@0 271 if (current->name.other.data == NULL) {
michael@0 272 rv = SECFailure;
michael@0 273 break;
michael@0 274 }
michael@0 275
michael@0 276 PORT_Memcpy (current->name.other.data + 2, buffer, strlen (buffer));
michael@0 277 /* This may not be accurate for all cases.For now, use this tag type */
michael@0 278 current->name.other.data[0] = (char)(((current->type - 1) & 0x1f)| 0x80);
michael@0 279 current->name.other.data[1] = (char)strlen (buffer);
michael@0 280 current->name.other.len = strlen (buffer) + 2;
michael@0 281 break;
michael@0 282 }
michael@0 283
michael@0 284 case certDirectoryName: {
michael@0 285 CERTName *directoryName = NULL;
michael@0 286
michael@0 287 directoryName = CERT_AsciiToName (buffer);
michael@0 288 if (!directoryName) {
michael@0 289 rv = SECFailure;
michael@0 290 break;
michael@0 291 }
michael@0 292
michael@0 293 rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
michael@0 294 CERT_DestroyName (directoryName);
michael@0 295
michael@0 296 break;
michael@0 297 }
michael@0 298 }
michael@0 299 if (rv != SECSuccess)
michael@0 300 break;
michael@0 301 current->l.next = &(namesList->l);
michael@0 302 current->l.prev = &(tail->l);
michael@0 303 tail->l.next = &(current->l);
michael@0 304 tail = current;
michael@0 305
michael@0 306 } while(nextChunk != data + strlen(data));
michael@0 307
michael@0 308 if (rv != SECSuccess) {
michael@0 309 PORT_ArenaRelease (arena, mark);
michael@0 310 namesList = NULL;
michael@0 311 }
michael@0 312 return (namesList);
michael@0 313 }
michael@0 314
michael@0 315 /* Creates CERTGeneralName from parsed data for the Authority Key Extension */
michael@0 316 static CERTGeneralName *
michael@0 317 crlgen_DistinguishedName (PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
michael@0 318 const char *data)
michael@0 319 {
michael@0 320 CERTName *directoryName = NULL;
michael@0 321 CERTGeneralName *current;
michael@0 322 SECStatus rv = SECFailure;
michael@0 323 void *mark;
michael@0 324
michael@0 325 if (!data)
michael@0 326 return NULL;
michael@0 327 PORT_Assert (arena);
michael@0 328 if (!arena) {
michael@0 329 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 330 return NULL;
michael@0 331 }
michael@0 332
michael@0 333 mark = PORT_ArenaMark (arena);
michael@0 334
michael@0 335 current = PORT_ArenaZNew(arena, CERTGeneralName);
michael@0 336 if (current == NULL) {
michael@0 337 goto loser;
michael@0 338 }
michael@0 339 current->type = certDirectoryName;
michael@0 340 current->l.next = &current->l;
michael@0 341 current->l.prev = &current->l;
michael@0 342
michael@0 343 directoryName = CERT_AsciiToName ((char*)data);
michael@0 344 if (!directoryName) {
michael@0 345 goto loser;
michael@0 346 }
michael@0 347
michael@0 348 rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
michael@0 349 CERT_DestroyName (directoryName);
michael@0 350
michael@0 351 loser:
michael@0 352 if (rv != SECSuccess) {
michael@0 353 PORT_SetError (rv);
michael@0 354 PORT_ArenaRelease (arena, mark);
michael@0 355 current = NULL;
michael@0 356 }
michael@0 357 return (current);
michael@0 358 }
michael@0 359
michael@0 360
michael@0 361 /* Adding Authority Key ID extension to extension handle. */
michael@0 362 static SECStatus
michael@0 363 crlgen_AddAuthKeyID (CRLGENGeneratorData *crlGenData,
michael@0 364 const char **dataArr)
michael@0 365 {
michael@0 366 void *extHandle = NULL;
michael@0 367 CERTAuthKeyID *authKeyID = NULL;
michael@0 368 PLArenaPool *arena = NULL;
michael@0 369 SECStatus rv = SECSuccess;
michael@0 370
michael@0 371 PORT_Assert(dataArr && crlGenData);
michael@0 372 if (!crlGenData || !dataArr) {
michael@0 373 return SECFailure;
michael@0 374 }
michael@0 375
michael@0 376 extHandle = crlGenData->crlExtHandle;
michael@0 377
michael@0 378 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
michael@0 379 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 380 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 381 "insufficient number of parameters.\n");
michael@0 382 return SECFailure;
michael@0 383 }
michael@0 384
michael@0 385 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 386 if (!arena) {
michael@0 387 return SECFailure;
michael@0 388 }
michael@0 389
michael@0 390 authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
michael@0 391 if (authKeyID == NULL) {
michael@0 392 rv = SECFailure;
michael@0 393 goto loser;
michael@0 394 }
michael@0 395
michael@0 396 if (dataArr[3] == NULL) {
michael@0 397 rv = crlgen_SetString (arena, dataArr[2], &authKeyID->keyID);
michael@0 398 if (rv != SECSuccess)
michael@0 399 goto loser;
michael@0 400 } else {
michael@0 401 rv = crlgen_SetString (arena, dataArr[3],
michael@0 402 &authKeyID->authCertSerialNumber);
michael@0 403 if (rv != SECSuccess)
michael@0 404 goto loser;
michael@0 405
michael@0 406 authKeyID->authCertIssuer =
michael@0 407 crlgen_DistinguishedName (arena, crlGenData, dataArr[2]);
michael@0 408 if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError ()){
michael@0 409 crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
michael@0 410 rv = SECFailure;
michael@0 411 goto loser;
michael@0 412 }
michael@0 413 }
michael@0 414
michael@0 415 rv =
michael@0 416 SECU_EncodeAndAddExtensionValue(arena, extHandle, authKeyID,
michael@0 417 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
michael@0 418 SEC_OID_X509_AUTH_KEY_ID,
michael@0 419 (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
michael@0 420 loser:
michael@0 421 if (arena)
michael@0 422 PORT_FreeArena (arena, PR_FALSE);
michael@0 423 return rv;
michael@0 424 }
michael@0 425
michael@0 426 /* Creates and add Subject Alternative Names extension */
michael@0 427 static SECStatus
michael@0 428 crlgen_AddIssuerAltNames(CRLGENGeneratorData *crlGenData,
michael@0 429 const char **dataArr)
michael@0 430 {
michael@0 431 CERTGeneralName *nameList = NULL;
michael@0 432 PLArenaPool *arena = NULL;
michael@0 433 void *extHandle = NULL;
michael@0 434 SECStatus rv = SECSuccess;
michael@0 435
michael@0 436
michael@0 437 PORT_Assert(dataArr && crlGenData);
michael@0 438 if (!crlGenData || !dataArr) {
michael@0 439 return SECFailure;
michael@0 440 }
michael@0 441
michael@0 442 if (!dataArr || !dataArr[0] || !dataArr[1] || !dataArr[2]) {
michael@0 443 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 444 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 445 "insufficient number of arguments.\n");
michael@0 446 return SECFailure;
michael@0 447 }
michael@0 448
michael@0 449 PORT_Assert(dataArr && crlGenData);
michael@0 450 if (!crlGenData || !dataArr) {
michael@0 451 return SECFailure;
michael@0 452 }
michael@0 453
michael@0 454 extHandle = crlGenData->crlExtHandle;
michael@0 455
michael@0 456 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
michael@0 457 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 458 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 459 "insufficient number of parameters.\n");
michael@0 460 return SECFailure;
michael@0 461 }
michael@0 462
michael@0 463 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 464 if (!arena) {
michael@0 465 return SECFailure;
michael@0 466 }
michael@0 467
michael@0 468 nameList = crlgen_GetGeneralName(arena, crlGenData, dataArr[2]);
michael@0 469 if (nameList == NULL) {
michael@0 470 crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
michael@0 471 rv = SECFailure;
michael@0 472 goto loser;
michael@0 473 }
michael@0 474
michael@0 475 rv =
michael@0 476 SECU_EncodeAndAddExtensionValue(arena, extHandle, nameList,
michael@0 477 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
michael@0 478 SEC_OID_X509_ISSUER_ALT_NAME,
michael@0 479 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeAltNameExtension);
michael@0 480 loser:
michael@0 481 if (arena)
michael@0 482 PORT_FreeArena (arena, PR_FALSE);
michael@0 483 return rv;
michael@0 484 }
michael@0 485
michael@0 486 /* Creates and adds CRLNumber extension to extension handle.
michael@0 487 * Since, this is CRL extension, extension handle is the one
michael@0 488 * related to CRL extensions */
michael@0 489 static SECStatus
michael@0 490 crlgen_AddCrlNumber(CRLGENGeneratorData *crlGenData, const char **dataArr)
michael@0 491 {
michael@0 492 PLArenaPool *arena = NULL;
michael@0 493 SECItem encodedItem;
michael@0 494 void *extHandle = crlGenData->crlExtHandle;
michael@0 495 void *dummy;
michael@0 496 SECStatus rv = SECFailure;
michael@0 497 int code = 0;
michael@0 498
michael@0 499 PORT_Assert(dataArr && crlGenData);
michael@0 500 if (!crlGenData || !dataArr) {
michael@0 501 goto loser;
michael@0 502 }
michael@0 503
michael@0 504 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
michael@0 505 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 506 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 507 "insufficient number of arguments.\n");
michael@0 508 goto loser;
michael@0 509 }
michael@0 510
michael@0 511 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 512 if (arena == NULL) {
michael@0 513 goto loser;
michael@0 514 }
michael@0 515
michael@0 516 code = atoi(dataArr[2]);
michael@0 517 if (code == 0 && *dataArr[2] != '0') {
michael@0 518 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 519 goto loser;
michael@0 520 }
michael@0 521
michael@0 522 dummy = SEC_ASN1EncodeInteger(arena, &encodedItem, code);
michael@0 523 if (!dummy) {
michael@0 524 rv = SECFailure;
michael@0 525 goto loser;
michael@0 526 }
michael@0 527
michael@0 528 rv = CERT_AddExtension (extHandle, SEC_OID_X509_CRL_NUMBER, &encodedItem,
michael@0 529 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
michael@0 530 PR_TRUE);
michael@0 531
michael@0 532 loser:
michael@0 533 if (arena)
michael@0 534 PORT_FreeArena(arena, PR_FALSE);
michael@0 535 return rv;
michael@0 536
michael@0 537 }
michael@0 538
michael@0 539
michael@0 540 /* Creates Cert Revocation Reason code extension. Encodes it and
michael@0 541 * returns as SECItem structure */
michael@0 542 static SECItem*
michael@0 543 crlgen_CreateReasonCode(PLArenaPool *arena, const char **dataArr,
michael@0 544 int *extCode)
michael@0 545 {
michael@0 546 SECItem *encodedItem;
michael@0 547 void *dummy;
michael@0 548 void *mark;
michael@0 549 int code = 0;
michael@0 550
michael@0 551 PORT_Assert(arena && dataArr);
michael@0 552 if (!arena || !dataArr) {
michael@0 553 goto loser;
michael@0 554 }
michael@0 555
michael@0 556 mark = PORT_ArenaMark(arena);
michael@0 557
michael@0 558 encodedItem = PORT_ArenaZNew (arena, SECItem);
michael@0 559 if (encodedItem == NULL) {
michael@0 560 goto loser;
michael@0 561 }
michael@0 562
michael@0 563 if (dataArr[2] == NULL) {
michael@0 564 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 565 goto loser;
michael@0 566 }
michael@0 567
michael@0 568 code = atoi(dataArr[2]);
michael@0 569 /* aACompromise(10) is the last possible of the values
michael@0 570 * for the Reason Core Extension */
michael@0 571 if ((code == 0 && *dataArr[2] != '0') || code > 10) {
michael@0 572
michael@0 573 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 574 goto loser;
michael@0 575 }
michael@0 576
michael@0 577 dummy = SEC_ASN1EncodeInteger(arena, encodedItem, code);
michael@0 578 if (!dummy) {
michael@0 579 goto loser;
michael@0 580 }
michael@0 581
michael@0 582 *extCode = SEC_OID_X509_REASON_CODE;
michael@0 583 return encodedItem;
michael@0 584
michael@0 585 loser:
michael@0 586 PORT_ArenaRelease (arena, mark);
michael@0 587 return NULL;
michael@0 588 }
michael@0 589
michael@0 590 /* Creates Cert Invalidity Date extension. Encodes it and
michael@0 591 * returns as SECItem structure */
michael@0 592 static SECItem*
michael@0 593 crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr,
michael@0 594 int *extCode)
michael@0 595 {
michael@0 596 SECItem *encodedItem;
michael@0 597 int length = 0;
michael@0 598 void *mark;
michael@0 599
michael@0 600 PORT_Assert(arena && dataArr);
michael@0 601 if (!arena || !dataArr) {
michael@0 602 goto loser;
michael@0 603 }
michael@0 604
michael@0 605 mark = PORT_ArenaMark(arena);
michael@0 606
michael@0 607 encodedItem = PORT_ArenaZNew(arena, SECItem);
michael@0 608 if (encodedItem == NULL) {
michael@0 609 goto loser;
michael@0 610 }
michael@0 611
michael@0 612 length = PORT_Strlen(dataArr[2]);
michael@0 613
michael@0 614 encodedItem->type = siGeneralizedTime;
michael@0 615 encodedItem->data = PORT_ArenaAlloc(arena, length);
michael@0 616 if (!encodedItem->data) {
michael@0 617 goto loser;
michael@0 618 }
michael@0 619
michael@0 620 PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) *
michael@0 621 sizeof(char));
michael@0 622
michael@0 623 *extCode = SEC_OID_X509_INVALID_DATE;
michael@0 624 return encodedItem;
michael@0 625
michael@0 626 loser:
michael@0 627 PORT_ArenaRelease(arena, mark);
michael@0 628 return NULL;
michael@0 629 }
michael@0 630
michael@0 631 /* Creates(by calling extCreator function) and adds extension to a set
michael@0 632 * of already added certs. Uses values of rangeFrom and rangeTo from
michael@0 633 * CRLGENCrlGenCtl structure for identifying the inclusive set of certs */
michael@0 634 static SECStatus
michael@0 635 crlgen_AddEntryExtension(CRLGENGeneratorData *crlGenData,
michael@0 636 const char **dataArr, char *extName,
michael@0 637 SECItem* (*extCreator)(PLArenaPool *arena,
michael@0 638 const char **dataArr,
michael@0 639 int *extCode))
michael@0 640 {
michael@0 641 PRUint64 i = 0;
michael@0 642 SECStatus rv = SECFailure;
michael@0 643 int extCode = 0;
michael@0 644 PRUint64 lastRange ;
michael@0 645 SECItem *ext = NULL;
michael@0 646 PLArenaPool *arena = NULL;
michael@0 647
michael@0 648
michael@0 649 PORT_Assert(crlGenData && dataArr);
michael@0 650 if (!crlGenData || !dataArr) {
michael@0 651 goto loser;
michael@0 652 }
michael@0 653
michael@0 654 if (!dataArr[0] || !dataArr[1]) {
michael@0 655 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 656 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 657 "insufficient number of arguments.\n");
michael@0 658 }
michael@0 659
michael@0 660 lastRange = crlGenData->rangeTo - crlGenData->rangeFrom + 1;
michael@0 661
michael@0 662 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 663 if (arena == NULL) {
michael@0 664 goto loser;
michael@0 665 }
michael@0 666
michael@0 667 ext = extCreator(arena, dataArr, &extCode);
michael@0 668 if (ext == NULL) {
michael@0 669 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 670 "got error while creating extension: %s\n",
michael@0 671 extName);
michael@0 672 goto loser;
michael@0 673 }
michael@0 674
michael@0 675 for (i = 0;i < lastRange;i++) {
michael@0 676 CRLGENEntryData * extData = NULL;
michael@0 677 void *extHandle = NULL;
michael@0 678 SECItem * certIdItem =
michael@0 679 SEC_ASN1EncodeInteger(arena, NULL,
michael@0 680 crlGenData->rangeFrom + i);
michael@0 681 if (!certIdItem) {
michael@0 682 rv = SECFailure;
michael@0 683 goto loser;
michael@0 684 }
michael@0 685
michael@0 686 extData = crlgen_FindEntry(crlGenData, certIdItem);
michael@0 687 if (!extData) {
michael@0 688 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 689 "can not add extension: crl entry "
michael@0 690 "(serial number: %d) is not in the list yet.\n",
michael@0 691 crlGenData->rangeFrom + i);
michael@0 692 continue;
michael@0 693 }
michael@0 694
michael@0 695 extHandle = extData->extHandle;
michael@0 696 if (extHandle == NULL) {
michael@0 697 extHandle = extData->extHandle =
michael@0 698 CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
michael@0 699 (CERTCrlEntry*)extData->entry);
michael@0 700 }
michael@0 701 rv = CERT_AddExtension (extHandle, extCode, ext,
michael@0 702 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
michael@0 703 PR_TRUE);
michael@0 704 if (rv == SECFailure) {
michael@0 705 goto loser;
michael@0 706 }
michael@0 707 }
michael@0 708
michael@0 709 loser:
michael@0 710 if (arena)
michael@0 711 PORT_FreeArena(arena, PR_FALSE);
michael@0 712 return rv;
michael@0 713 }
michael@0 714
michael@0 715
michael@0 716 /* Commits all added entries and their's extensions into CRL. */
michael@0 717 SECStatus
michael@0 718 CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData)
michael@0 719 {
michael@0 720 int size = 0;
michael@0 721 CERTCrl *crl;
michael@0 722 PLArenaPool *arena;
michael@0 723 SECStatus rv = SECSuccess;
michael@0 724 void *mark;
michael@0 725
michael@0 726 PORT_Assert(crlGenData && crlGenData->signCrl && crlGenData->signCrl->arena);
michael@0 727 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
michael@0 728 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 729 return SECFailure;
michael@0 730 }
michael@0 731
michael@0 732 arena = crlGenData->signCrl->arena;
michael@0 733 crl = &crlGenData->signCrl->crl;
michael@0 734
michael@0 735 mark = PORT_ArenaMark(arena);
michael@0 736
michael@0 737 if (crlGenData->crlExtHandle)
michael@0 738 CERT_FinishExtensions(crlGenData->crlExtHandle);
michael@0 739
michael@0 740 size = crlGenData->entryDataHashTable->nentries;
michael@0 741 crl->entries = NULL;
michael@0 742 if (size) {
michael@0 743 crl->entries = PORT_ArenaZNewArray(arena, CERTCrlEntry*, size + 1);
michael@0 744 if (!crl->entries) {
michael@0 745 rv = SECFailure;
michael@0 746 } else {
michael@0 747 struct commitData dt;
michael@0 748 dt.entries = crl->entries;
michael@0 749 dt.pos = 0;
michael@0 750 PL_HashTableEnumerateEntries(crlGenData->entryDataHashTable,
michael@0 751 &crlgen_CommitEntryData, &dt);
michael@0 752 /* Last should be NULL */
michael@0 753 crl->entries[size] = NULL;
michael@0 754 }
michael@0 755 }
michael@0 756
michael@0 757 if (rv != SECSuccess)
michael@0 758 PORT_ArenaRelease(arena, mark);
michael@0 759 return rv;
michael@0 760 }
michael@0 761
michael@0 762 /* Initializes extHandle with data from extensions array */
michael@0 763 static SECStatus
michael@0 764 crlgen_InitExtensionHandle(void *extHandle,
michael@0 765 CERTCertExtension **extensions)
michael@0 766 {
michael@0 767 CERTCertExtension *extension = NULL;
michael@0 768
michael@0 769 if (!extensions)
michael@0 770 return SECSuccess;
michael@0 771
michael@0 772 PORT_Assert(extHandle != NULL);
michael@0 773 if (!extHandle) {
michael@0 774 return SECFailure;
michael@0 775 }
michael@0 776
michael@0 777 extension = *extensions;
michael@0 778 while (extension) {
michael@0 779 SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
michael@0 780 /* shell we skip unknown extensions? */
michael@0 781 CERT_AddExtension (extHandle, oidTag, &extension->value,
michael@0 782 (extension->critical.len != 0) ? PR_TRUE : PR_FALSE,
michael@0 783 PR_FALSE);
michael@0 784 extension = *(++extensions);
michael@0 785 }
michael@0 786 return SECSuccess;
michael@0 787 }
michael@0 788
michael@0 789 /* Used for initialization of extension handles for crl and certs
michael@0 790 * extensions from existing CRL data then modifying existing CRL.*/
michael@0 791 SECStatus
michael@0 792 CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData)
michael@0 793 {
michael@0 794 CERTCrl *crl = NULL;
michael@0 795 PRUint64 maxSN = 0;
michael@0 796
michael@0 797 PORT_Assert(crlGenData && crlGenData->signCrl &&
michael@0 798 crlGenData->entryDataHashTable);
michael@0 799 if (!crlGenData || !crlGenData->signCrl ||
michael@0 800 !crlGenData->entryDataHashTable) {
michael@0 801 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 802 return SECFailure;
michael@0 803 }
michael@0 804
michael@0 805 crl = &crlGenData->signCrl->crl;
michael@0 806 crlGenData->crlExtHandle = CERT_StartCRLExtensions(crl);
michael@0 807 crlgen_InitExtensionHandle(crlGenData->crlExtHandle,
michael@0 808 crl->extensions);
michael@0 809 crl->extensions = NULL;
michael@0 810
michael@0 811 if (crl->entries) {
michael@0 812 CERTCrlEntry **entry = crl->entries;
michael@0 813 while (*entry) {
michael@0 814 PRUint64 sn = DER_GetInteger(&(*entry)->serialNumber);
michael@0 815 CRLGENEntryData *extData =
michael@0 816 crlgen_PlaceAnEntry(crlGenData, *entry, &(*entry)->serialNumber);
michael@0 817 if ((*entry)->extensions) {
michael@0 818 extData->extHandle =
michael@0 819 CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
michael@0 820 (CERTCrlEntry*)extData->entry);
michael@0 821 if (crlgen_InitExtensionHandle(extData->extHandle,
michael@0 822 (*entry)->extensions) == SECFailure)
michael@0 823 return SECFailure;
michael@0 824 }
michael@0 825 (*entry)->extensions = NULL;
michael@0 826 entry++;
michael@0 827 maxSN = PR_MAX(maxSN, sn);
michael@0 828 }
michael@0 829 }
michael@0 830
michael@0 831 crlGenData->rangeFrom = crlGenData->rangeTo = maxSN + 1;
michael@0 832 return SECSuccess;
michael@0 833 }
michael@0 834
michael@0 835 /*****************************************************************************
michael@0 836 * Parser trigger functions start here
michael@0 837 */
michael@0 838
michael@0 839 /* Sets new internal range value for add/rm certs.*/
michael@0 840 static SECStatus
michael@0 841 crlgen_SetNewRangeField(CRLGENGeneratorData *crlGenData, char *value)
michael@0 842 {
michael@0 843 long rangeFrom = 0, rangeTo = 0;
michael@0 844 char *dashPos = NULL;
michael@0 845
michael@0 846 PORT_Assert(crlGenData);
michael@0 847 if (!crlGenData) {
michael@0 848 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 849 return SECFailure;
michael@0 850 }
michael@0 851
michael@0 852 if (value == NULL) {
michael@0 853 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 854 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 855 "insufficient number of arguments.\n");
michael@0 856 return SECFailure;
michael@0 857 }
michael@0 858
michael@0 859 if ((dashPos = strchr(value, '-')) != NULL) {
michael@0 860 char *rangeToS, *rangeFromS = value;
michael@0 861 *dashPos = '\0';
michael@0 862 rangeFrom = atoi(rangeFromS);
michael@0 863 *dashPos = '-';
michael@0 864
michael@0 865 rangeToS = (char*)(dashPos + 1);
michael@0 866 rangeTo = atol(rangeToS);
michael@0 867 } else {
michael@0 868 rangeFrom = atol(value);
michael@0 869 rangeTo = rangeFrom;
michael@0 870 }
michael@0 871
michael@0 872 if (rangeFrom < 1 || rangeTo<rangeFrom) {
michael@0 873 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 874 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 875 "bad cert id range: %s.\n", value);
michael@0 876 return SECFailure;
michael@0 877 }
michael@0 878
michael@0 879 crlGenData->rangeFrom = rangeFrom;
michael@0 880 crlGenData->rangeTo = rangeTo;
michael@0 881
michael@0 882 return SECSuccess;
michael@0 883 }
michael@0 884
michael@0 885 /* Changes issuer subject field in CRL. By default this data is taken from
michael@0 886 * issuer cert subject field.Not yet implemented */
michael@0 887 static SECStatus
michael@0 888 crlgen_SetIssuerField(CRLGENGeneratorData *crlGenData, char *value)
michael@0 889 {
michael@0 890 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 891 "Can not change CRL issuer field.\n");
michael@0 892 return SECFailure;
michael@0 893 }
michael@0 894
michael@0 895 /* Encode and sets CRL thisUpdate and nextUpdate time fields*/
michael@0 896 static SECStatus
michael@0 897 crlgen_SetTimeField(CRLGENGeneratorData *crlGenData, char *value,
michael@0 898 PRBool setThisUpdate)
michael@0 899 {
michael@0 900 CERTSignedCrl *signCrl;
michael@0 901 PLArenaPool *arena;
michael@0 902 CERTCrl *crl;
michael@0 903 int length = 0;
michael@0 904 SECItem *timeDest = NULL;
michael@0 905
michael@0 906 PORT_Assert(crlGenData && crlGenData->signCrl &&
michael@0 907 crlGenData->signCrl->arena);
michael@0 908 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
michael@0 909 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 910 return SECFailure;
michael@0 911 }
michael@0 912
michael@0 913 signCrl = crlGenData->signCrl;
michael@0 914 arena = signCrl->arena;
michael@0 915 crl = &signCrl->crl;
michael@0 916
michael@0 917 if (value == NULL) {
michael@0 918 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 919 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 920 "insufficient number of arguments.\n");
michael@0 921 return SECFailure;
michael@0 922 }
michael@0 923 length = PORT_Strlen(value);
michael@0 924
michael@0 925 if (setThisUpdate == PR_TRUE) {
michael@0 926 timeDest = &crl->lastUpdate;
michael@0 927 } else {
michael@0 928 timeDest = &crl->nextUpdate;
michael@0 929 }
michael@0 930
michael@0 931 timeDest->type = siGeneralizedTime;
michael@0 932 timeDest->data = PORT_ArenaAlloc(arena, length);
michael@0 933 if (!timeDest->data) {
michael@0 934 return SECFailure;
michael@0 935 }
michael@0 936 PORT_Memcpy(timeDest->data, value, length);
michael@0 937 timeDest->len = length;
michael@0 938
michael@0 939 return SECSuccess;
michael@0 940 }
michael@0 941
michael@0 942
michael@0 943 /* Adds new extension into CRL or added cert handles */
michael@0 944 static SECStatus
michael@0 945 crlgen_AddExtension(CRLGENGeneratorData *crlGenData, const char **extData)
michael@0 946 {
michael@0 947 PORT_Assert(crlGenData && crlGenData->crlExtHandle);
michael@0 948 if (!crlGenData || !crlGenData->crlExtHandle) {
michael@0 949 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 950 return SECFailure;
michael@0 951 }
michael@0 952
michael@0 953 if (extData == NULL || *extData == NULL) {
michael@0 954 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 955 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 956 "insufficient number of arguments.\n");
michael@0 957 return SECFailure;
michael@0 958 }
michael@0 959 if (!PORT_Strcmp(*extData, "authKeyId"))
michael@0 960 return crlgen_AddAuthKeyID(crlGenData, extData);
michael@0 961 else if (!PORT_Strcmp(*extData, "issuerAltNames"))
michael@0 962 return crlgen_AddIssuerAltNames(crlGenData, extData);
michael@0 963 else if (!PORT_Strcmp(*extData, "crlNumber"))
michael@0 964 return crlgen_AddCrlNumber(crlGenData, extData);
michael@0 965 else if (!PORT_Strcmp(*extData, "reasonCode"))
michael@0 966 return crlgen_AddEntryExtension(crlGenData, extData, "reasonCode",
michael@0 967 crlgen_CreateReasonCode);
michael@0 968 else if (!PORT_Strcmp(*extData, "invalidityDate"))
michael@0 969 return crlgen_AddEntryExtension(crlGenData, extData, "invalidityDate",
michael@0 970 crlgen_CreateInvalidityDate);
michael@0 971 else {
michael@0 972 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 973 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 974 "insufficient number of arguments.\n");
michael@0 975 return SECFailure;
michael@0 976 }
michael@0 977 }
michael@0 978
michael@0 979
michael@0 980
michael@0 981 /* Created CRLGENEntryData for cert with serial number certId and
michael@0 982 * adds it to entryDataHashTable. certId can be a single cert serial
michael@0 983 * number or an inclusive rage of certs */
michael@0 984 static SECStatus
michael@0 985 crlgen_AddCert(CRLGENGeneratorData *crlGenData,
michael@0 986 char *certId, char *revocationDate)
michael@0 987 {
michael@0 988 CERTSignedCrl *signCrl;
michael@0 989 SECItem *certIdItem;
michael@0 990 PLArenaPool *arena;
michael@0 991 PRUint64 rangeFrom = 0, rangeTo = 0, i = 0;
michael@0 992 int timeValLength = -1;
michael@0 993 SECStatus rv = SECFailure;
michael@0 994 void *mark;
michael@0 995
michael@0 996
michael@0 997 PORT_Assert(crlGenData && crlGenData->signCrl &&
michael@0 998 crlGenData->signCrl->arena);
michael@0 999 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
michael@0 1000 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1001 return SECFailure;
michael@0 1002 }
michael@0 1003
michael@0 1004 signCrl = crlGenData->signCrl;
michael@0 1005 arena = signCrl->arena;
michael@0 1006
michael@0 1007 if (!certId || !revocationDate) {
michael@0 1008 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1009 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1010 "insufficient number of arguments.\n");
michael@0 1011 return SECFailure;
michael@0 1012 }
michael@0 1013
michael@0 1014 timeValLength = strlen(revocationDate);
michael@0 1015
michael@0 1016 if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
michael@0 1017 certId) {
michael@0 1018 return SECFailure;
michael@0 1019 }
michael@0 1020 rangeFrom = crlGenData->rangeFrom;
michael@0 1021 rangeTo = crlGenData->rangeTo;
michael@0 1022
michael@0 1023 for (i = 0;i < rangeTo - rangeFrom + 1;i++) {
michael@0 1024 CERTCrlEntry *entry;
michael@0 1025 mark = PORT_ArenaMark(arena);
michael@0 1026 entry = PORT_ArenaZNew(arena, CERTCrlEntry);
michael@0 1027 if (entry == NULL) {
michael@0 1028 goto loser;
michael@0 1029 }
michael@0 1030
michael@0 1031 certIdItem = SEC_ASN1EncodeInteger(arena, &entry->serialNumber,
michael@0 1032 rangeFrom + i);
michael@0 1033 if (!certIdItem) {
michael@0 1034 goto loser;
michael@0 1035 }
michael@0 1036
michael@0 1037 if (crlgen_FindEntry(crlGenData, certIdItem)) {
michael@0 1038 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1039 "entry already exists. Use \"range\" "
michael@0 1040 "and \"rmcert\" before adding a new one with the "
michael@0 1041 "same serial number %ld\n", rangeFrom + i);
michael@0 1042 goto loser;
michael@0 1043 }
michael@0 1044
michael@0 1045 entry->serialNumber.type = siBuffer;
michael@0 1046
michael@0 1047 entry->revocationDate.type = siGeneralizedTime;
michael@0 1048
michael@0 1049 entry->revocationDate.data =
michael@0 1050 PORT_ArenaAlloc(arena, timeValLength);
michael@0 1051 if (entry->revocationDate.data == NULL) {
michael@0 1052 goto loser;
michael@0 1053 }
michael@0 1054
michael@0 1055 PORT_Memcpy(entry->revocationDate.data, revocationDate,
michael@0 1056 timeValLength * sizeof(char));
michael@0 1057 entry->revocationDate.len = timeValLength;
michael@0 1058
michael@0 1059
michael@0 1060 entry->extensions = NULL;
michael@0 1061 if (!crlgen_PlaceAnEntry(crlGenData, entry, certIdItem)) {
michael@0 1062 goto loser;
michael@0 1063 }
michael@0 1064 mark = NULL;
michael@0 1065 }
michael@0 1066
michael@0 1067 rv = SECSuccess;
michael@0 1068 loser:
michael@0 1069 if (mark) {
michael@0 1070 PORT_ArenaRelease(arena, mark);
michael@0 1071 }
michael@0 1072 return rv;
michael@0 1073 }
michael@0 1074
michael@0 1075
michael@0 1076 /* Removes certs from entryDataHashTable which have certId serial number.
michael@0 1077 * certId can have value of a range of certs */
michael@0 1078 static SECStatus
michael@0 1079 crlgen_RmCert(CRLGENGeneratorData *crlGenData, char *certId)
michael@0 1080 {
michael@0 1081 PRUint64 i = 0;
michael@0 1082 PLArenaPool *arena;
michael@0 1083
michael@0 1084 PORT_Assert(crlGenData && certId);
michael@0 1085 if (!crlGenData || !certId) {
michael@0 1086 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1087 return SECFailure;
michael@0 1088 }
michael@0 1089
michael@0 1090 arena = crlGenData->signCrl->arena;
michael@0 1091
michael@0 1092 if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
michael@0 1093 certId) {
michael@0 1094 return SECFailure;
michael@0 1095 }
michael@0 1096
michael@0 1097 for (i = 0;i < crlGenData->rangeTo - crlGenData->rangeFrom + 1;i++) {
michael@0 1098 SECItem* certIdItem = SEC_ASN1EncodeInteger(NULL, NULL,
michael@0 1099 crlGenData->rangeFrom + i);
michael@0 1100 if (certIdItem) {
michael@0 1101 CRLGENEntryData *extData =
michael@0 1102 crlgen_FindEntry(crlGenData, certIdItem);
michael@0 1103 if (!extData) {
michael@0 1104 printf("Cert with id %s is not in the list\n", certId);
michael@0 1105 } else {
michael@0 1106 crlgen_RmEntry(crlGenData, certIdItem);
michael@0 1107 }
michael@0 1108 SECITEM_FreeItem(certIdItem, PR_TRUE);
michael@0 1109 }
michael@0 1110 }
michael@0 1111
michael@0 1112 return SECSuccess;
michael@0 1113 }
michael@0 1114
michael@0 1115 /*************************************************************************
michael@0 1116 * Lex Parser Helper functions are used to store parsed information
michael@0 1117 * in context related structures. Context(or state) is identified base on
michael@0 1118 * a type of a instruction parser currently is going through. New context
michael@0 1119 * is identified by first token in a line. It can be addcert context,
michael@0 1120 * addext context, etc. */
michael@0 1121
michael@0 1122 /* Updates CRL field depending on current context */
michael@0 1123 static SECStatus
michael@0 1124 crlgen_updateCrlFn_field(CRLGENGeneratorData *crlGenData, void *str)
michael@0 1125 {
michael@0 1126 CRLGENCrlField *fieldStr = (CRLGENCrlField*)str;
michael@0 1127
michael@0 1128 PORT_Assert(crlGenData);
michael@0 1129 if (!crlGenData) {
michael@0 1130 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1131 return SECFailure;
michael@0 1132 }
michael@0 1133
michael@0 1134 switch(crlGenData->contextId) {
michael@0 1135 case CRLGEN_ISSUER_CONTEXT:
michael@0 1136 crlgen_SetIssuerField(crlGenData, fieldStr->value);
michael@0 1137 break;
michael@0 1138 case CRLGEN_UPDATE_CONTEXT:
michael@0 1139 return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_TRUE);
michael@0 1140 break;
michael@0 1141 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1142 return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_FALSE);
michael@0 1143 break;
michael@0 1144 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1145 return crlgen_SetNewRangeField(crlGenData, fieldStr->value);
michael@0 1146 break;
michael@0 1147 default:
michael@0 1148 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1149 "syntax error (unknow token type: %d)\n",
michael@0 1150 crlGenData->contextId);
michael@0 1151 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1152 return SECFailure;
michael@0 1153 }
michael@0 1154 return SECSuccess;
michael@0 1155 }
michael@0 1156
michael@0 1157 /* Sets parsed data for CRL field update into temporary structure */
michael@0 1158 static SECStatus
michael@0 1159 crlgen_setNextDataFn_field(CRLGENGeneratorData *crlGenData, void *str,
michael@0 1160 void *data, unsigned short dtype)
michael@0 1161 {
michael@0 1162 CRLGENCrlField *fieldStr = (CRLGENCrlField*)str;
michael@0 1163
michael@0 1164 PORT_Assert(crlGenData);
michael@0 1165 if (!crlGenData) {
michael@0 1166 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1167 return SECFailure;
michael@0 1168 }
michael@0 1169
michael@0 1170 switch (crlGenData->contextId) {
michael@0 1171 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1172 if (dtype != CRLGEN_TYPE_DIGIT || dtype != CRLGEN_TYPE_DIGIT_RANGE) {
michael@0 1173 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1174 "range value should have "
michael@0 1175 "numeric or numeric range values.\n");
michael@0 1176 return SECFailure;
michael@0 1177 }
michael@0 1178 break;
michael@0 1179 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1180 case CRLGEN_UPDATE_CONTEXT:
michael@0 1181 if (dtype != CRLGEN_TYPE_ZDATE){
michael@0 1182 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1183 "bad formated date. Should be "
michael@0 1184 "YYYYMMDDHHMMSSZ.\n");
michael@0 1185 return SECFailure;
michael@0 1186 }
michael@0 1187 break;
michael@0 1188 default:
michael@0 1189 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1190 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1191 "syntax error (unknow token type: %d).\n",
michael@0 1192 crlGenData->contextId, data);
michael@0 1193 return SECFailure;
michael@0 1194 }
michael@0 1195 fieldStr->value = PORT_Strdup(data);
michael@0 1196 if (!fieldStr->value) {
michael@0 1197 return SECFailure;
michael@0 1198 }
michael@0 1199 return SECSuccess;
michael@0 1200 }
michael@0 1201
michael@0 1202 /* Triggers cert entries update depending on current context */
michael@0 1203 static SECStatus
michael@0 1204 crlgen_updateCrlFn_cert(CRLGENGeneratorData *crlGenData, void *str)
michael@0 1205 {
michael@0 1206 CRLGENCertEntry *certStr = (CRLGENCertEntry*)str;
michael@0 1207
michael@0 1208 PORT_Assert(crlGenData);
michael@0 1209 if (!crlGenData) {
michael@0 1210 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1211 return SECFailure;
michael@0 1212 }
michael@0 1213
michael@0 1214 switch(crlGenData->contextId) {
michael@0 1215 case CRLGEN_ADD_CERT_CONTEXT:
michael@0 1216 return crlgen_AddCert(crlGenData, certStr->certId,
michael@0 1217 certStr->revocationTime);
michael@0 1218 case CRLGEN_RM_CERT_CONTEXT:
michael@0 1219 return crlgen_RmCert(crlGenData, certStr->certId);
michael@0 1220 default:
michael@0 1221 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1222 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1223 "syntax error (unknow token type: %d).\n",
michael@0 1224 crlGenData->contextId);
michael@0 1225 return SECFailure;
michael@0 1226 }
michael@0 1227 }
michael@0 1228
michael@0 1229
michael@0 1230 /* Sets parsed data for CRL entries update into temporary structure */
michael@0 1231 static SECStatus
michael@0 1232 crlgen_setNextDataFn_cert(CRLGENGeneratorData *crlGenData, void *str,
michael@0 1233 void *data, unsigned short dtype)
michael@0 1234 {
michael@0 1235 CRLGENCertEntry *certStr = (CRLGENCertEntry*)str;
michael@0 1236
michael@0 1237 PORT_Assert(crlGenData);
michael@0 1238 if (!crlGenData) {
michael@0 1239 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1240 return SECFailure;
michael@0 1241 }
michael@0 1242
michael@0 1243 switch(dtype) {
michael@0 1244 case CRLGEN_TYPE_DIGIT:
michael@0 1245 case CRLGEN_TYPE_DIGIT_RANGE:
michael@0 1246 certStr->certId = PORT_Strdup(data);
michael@0 1247 if (!certStr->certId) {
michael@0 1248 return SECFailure;
michael@0 1249 }
michael@0 1250 break;
michael@0 1251 case CRLGEN_TYPE_DATE:
michael@0 1252 case CRLGEN_TYPE_ZDATE:
michael@0 1253 certStr->revocationTime = PORT_Strdup(data);
michael@0 1254 if (!certStr->revocationTime) {
michael@0 1255 return SECFailure;
michael@0 1256 }
michael@0 1257 break;
michael@0 1258 default:
michael@0 1259 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1260 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1261 "syntax error (unknow token type: %d).\n",
michael@0 1262 crlGenData->contextId);
michael@0 1263 return SECFailure;
michael@0 1264 }
michael@0 1265 return SECSuccess;
michael@0 1266 }
michael@0 1267
michael@0 1268 /* Triggers cert entries/crl extension update */
michael@0 1269 static SECStatus
michael@0 1270 crlgen_updateCrlFn_extension(CRLGENGeneratorData *crlGenData, void *str)
michael@0 1271 {
michael@0 1272 CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry*)str;
michael@0 1273
michael@0 1274 return crlgen_AddExtension(crlGenData, (const char**)extStr->extData);
michael@0 1275 }
michael@0 1276
michael@0 1277 /* Defines maximum number of fields extension may have */
michael@0 1278 #define MAX_EXT_DATA_LENGTH 10
michael@0 1279
michael@0 1280 /* Sets parsed extension data for CRL entries/CRL extensions update
michael@0 1281 * into temporary structure */
michael@0 1282 static SECStatus
michael@0 1283 crlgen_setNextDataFn_extension(CRLGENGeneratorData *crlGenData, void *str,
michael@0 1284 void *data, unsigned short dtype)
michael@0 1285 {
michael@0 1286 CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry*)str;
michael@0 1287
michael@0 1288 PORT_Assert(crlGenData);
michael@0 1289 if (!crlGenData) {
michael@0 1290 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1291 return SECFailure;
michael@0 1292 }
michael@0 1293
michael@0 1294 if (extStr->extData == NULL) {
michael@0 1295 extStr->extData = PORT_ZNewArray(char *, MAX_EXT_DATA_LENGTH);
michael@0 1296 if (!extStr->extData) {
michael@0 1297 return SECFailure;
michael@0 1298 }
michael@0 1299 }
michael@0 1300 if (extStr->nextUpdatedData >= MAX_EXT_DATA_LENGTH) {
michael@0 1301 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1302 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1303 "number of fields in extension "
michael@0 1304 "exceeded maximum allowed data length: %d.\n",
michael@0 1305 MAX_EXT_DATA_LENGTH);
michael@0 1306 return SECFailure;
michael@0 1307 }
michael@0 1308 extStr->extData[extStr->nextUpdatedData] = PORT_Strdup(data);
michael@0 1309 if (!extStr->extData[extStr->nextUpdatedData]) {
michael@0 1310 return SECFailure;
michael@0 1311 }
michael@0 1312 extStr->nextUpdatedData += 1;
michael@0 1313
michael@0 1314 return SECSuccess;
michael@0 1315 }
michael@0 1316
michael@0 1317
michael@0 1318 /****************************************************************************************
michael@0 1319 * Top level functions are triggered directly by parser.
michael@0 1320 */
michael@0 1321
michael@0 1322 /*
michael@0 1323 * crl generation script parser recreates a temporary data staructure
michael@0 1324 * for each line it is going through. This function cleans temp structure.
michael@0 1325 */
michael@0 1326 void
michael@0 1327 crlgen_destroyTempData(CRLGENGeneratorData *crlGenData)
michael@0 1328 {
michael@0 1329 if (crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
michael@0 1330 switch(crlGenData->contextId) {
michael@0 1331 case CRLGEN_ISSUER_CONTEXT:
michael@0 1332 case CRLGEN_UPDATE_CONTEXT:
michael@0 1333 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1334 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1335 if (crlGenData->crlField->value)
michael@0 1336 PORT_Free(crlGenData->crlField->value);
michael@0 1337 PORT_Free(crlGenData->crlField);
michael@0 1338 break;
michael@0 1339 case CRLGEN_ADD_CERT_CONTEXT:
michael@0 1340 case CRLGEN_RM_CERT_CONTEXT:
michael@0 1341 if (crlGenData->certEntry->certId)
michael@0 1342 PORT_Free(crlGenData->certEntry->certId);
michael@0 1343 if (crlGenData->certEntry->revocationTime)
michael@0 1344 PORT_Free(crlGenData->certEntry->revocationTime);
michael@0 1345 PORT_Free(crlGenData->certEntry);
michael@0 1346 break;
michael@0 1347 case CRLGEN_ADD_EXTENSION_CONTEXT:
michael@0 1348 if (crlGenData->extensionEntry->extData) {
michael@0 1349 int i = 0;
michael@0 1350 for (;i < crlGenData->extensionEntry->nextUpdatedData;i++)
michael@0 1351 PORT_Free(*(crlGenData->extensionEntry->extData + i));
michael@0 1352 PORT_Free(crlGenData->extensionEntry->extData);
michael@0 1353 }
michael@0 1354 PORT_Free(crlGenData->extensionEntry);
michael@0 1355 break;
michael@0 1356 }
michael@0 1357 crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
michael@0 1358 }
michael@0 1359 }
michael@0 1360
michael@0 1361 SECStatus
michael@0 1362 crlgen_updateCrl(CRLGENGeneratorData *crlGenData)
michael@0 1363 {
michael@0 1364 SECStatus rv = SECSuccess;
michael@0 1365
michael@0 1366 PORT_Assert(crlGenData);
michael@0 1367 if (!crlGenData) {
michael@0 1368 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1369 return SECFailure;
michael@0 1370 }
michael@0 1371
michael@0 1372 switch(crlGenData->contextId) {
michael@0 1373 case CRLGEN_ISSUER_CONTEXT:
michael@0 1374 case CRLGEN_UPDATE_CONTEXT:
michael@0 1375 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1376 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1377 rv = crlGenData->crlField->updateCrlFn(crlGenData, crlGenData->crlField);
michael@0 1378 break;
michael@0 1379 case CRLGEN_RM_CERT_CONTEXT:
michael@0 1380 case CRLGEN_ADD_CERT_CONTEXT:
michael@0 1381 rv = crlGenData->certEntry->updateCrlFn(crlGenData, crlGenData->certEntry);
michael@0 1382 break;
michael@0 1383 case CRLGEN_ADD_EXTENSION_CONTEXT:
michael@0 1384 rv = crlGenData->extensionEntry->
michael@0 1385 updateCrlFn(crlGenData, crlGenData->extensionEntry);
michael@0 1386 break;
michael@0 1387 case CRLGEN_UNKNOWN_CONTEXT:
michael@0 1388 break;
michael@0 1389 default:
michael@0 1390 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1391 "unknown lang context type code: %d.\n",
michael@0 1392 crlGenData->contextId);
michael@0 1393 PORT_Assert(0);
michael@0 1394 return SECFailure;
michael@0 1395 }
michael@0 1396 /* Clrean structures after crl update */
michael@0 1397 crlgen_destroyTempData(crlGenData);
michael@0 1398
michael@0 1399 crlGenData->parsedLineNum += 1;
michael@0 1400
michael@0 1401 return rv;
michael@0 1402 }
michael@0 1403
michael@0 1404 SECStatus
michael@0 1405 crlgen_setNextData(CRLGENGeneratorData *crlGenData, void *data,
michael@0 1406 unsigned short dtype)
michael@0 1407 {
michael@0 1408 SECStatus rv = SECSuccess;
michael@0 1409
michael@0 1410 PORT_Assert(crlGenData);
michael@0 1411 if (!crlGenData) {
michael@0 1412 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1413 return SECFailure;
michael@0 1414 }
michael@0 1415
michael@0 1416 switch(crlGenData->contextId) {
michael@0 1417 case CRLGEN_ISSUER_CONTEXT:
michael@0 1418 case CRLGEN_UPDATE_CONTEXT:
michael@0 1419 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1420 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1421 rv = crlGenData->crlField->setNextDataFn(crlGenData, crlGenData->crlField,
michael@0 1422 data, dtype);
michael@0 1423 break;
michael@0 1424 case CRLGEN_ADD_CERT_CONTEXT:
michael@0 1425 case CRLGEN_RM_CERT_CONTEXT:
michael@0 1426 rv = crlGenData->certEntry->setNextDataFn(crlGenData, crlGenData->certEntry,
michael@0 1427 data, dtype);
michael@0 1428 break;
michael@0 1429 case CRLGEN_ADD_EXTENSION_CONTEXT:
michael@0 1430 rv =
michael@0 1431 crlGenData->extensionEntry->
michael@0 1432 setNextDataFn(crlGenData, crlGenData->extensionEntry, data, dtype);
michael@0 1433 break;
michael@0 1434 case CRLGEN_UNKNOWN_CONTEXT:
michael@0 1435 break;
michael@0 1436 default:
michael@0 1437 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1438 "unknown context type: %d.\n",
michael@0 1439 crlGenData->contextId);
michael@0 1440 PORT_Assert(0);
michael@0 1441 return SECFailure;
michael@0 1442 }
michael@0 1443 return rv;
michael@0 1444 }
michael@0 1445
michael@0 1446 SECStatus
michael@0 1447 crlgen_createNewLangStruct(CRLGENGeneratorData *crlGenData,
michael@0 1448 unsigned structType)
michael@0 1449 {
michael@0 1450 PORT_Assert(crlGenData &&
michael@0 1451 crlGenData->contextId == CRLGEN_UNKNOWN_CONTEXT);
michael@0 1452 if (!crlGenData ||
michael@0 1453 crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
michael@0 1454 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1455 return SECFailure;
michael@0 1456 }
michael@0 1457
michael@0 1458 switch(structType) {
michael@0 1459 case CRLGEN_ISSUER_CONTEXT:
michael@0 1460 case CRLGEN_UPDATE_CONTEXT:
michael@0 1461 case CRLGEN_NEXT_UPDATE_CONTEXT:
michael@0 1462 case CRLGEN_CHANGE_RANGE_CONTEXT:
michael@0 1463 crlGenData->crlField = PORT_New(CRLGENCrlField);
michael@0 1464 if (!crlGenData->crlField) {
michael@0 1465 return SECFailure;
michael@0 1466 }
michael@0 1467 crlGenData->contextId = structType;
michael@0 1468 crlGenData->crlField->value = NULL;
michael@0 1469 crlGenData->crlField->updateCrlFn = &crlgen_updateCrlFn_field;
michael@0 1470 crlGenData->crlField->setNextDataFn = &crlgen_setNextDataFn_field;
michael@0 1471 break;
michael@0 1472 case CRLGEN_RM_CERT_CONTEXT:
michael@0 1473 case CRLGEN_ADD_CERT_CONTEXT:
michael@0 1474 crlGenData->certEntry = PORT_New(CRLGENCertEntry);
michael@0 1475 if (!crlGenData->certEntry) {
michael@0 1476 return SECFailure;
michael@0 1477 }
michael@0 1478 crlGenData->contextId = structType;
michael@0 1479 crlGenData->certEntry->certId = 0;
michael@0 1480 crlGenData->certEntry->revocationTime = NULL;
michael@0 1481 crlGenData->certEntry->updateCrlFn = &crlgen_updateCrlFn_cert;
michael@0 1482 crlGenData->certEntry->setNextDataFn = &crlgen_setNextDataFn_cert;
michael@0 1483 break;
michael@0 1484 case CRLGEN_ADD_EXTENSION_CONTEXT:
michael@0 1485 crlGenData->extensionEntry = PORT_New(CRLGENExtensionEntry);
michael@0 1486 if (!crlGenData->extensionEntry) {
michael@0 1487 return SECFailure;
michael@0 1488 }
michael@0 1489 crlGenData->contextId = structType;
michael@0 1490 crlGenData->extensionEntry->extData = NULL;
michael@0 1491 crlGenData->extensionEntry->nextUpdatedData = 0;
michael@0 1492 crlGenData->extensionEntry->updateCrlFn =
michael@0 1493 &crlgen_updateCrlFn_extension;
michael@0 1494 crlGenData->extensionEntry->setNextDataFn =
michael@0 1495 &crlgen_setNextDataFn_extension;
michael@0 1496 break;
michael@0 1497 case CRLGEN_UNKNOWN_CONTEXT:
michael@0 1498 break;
michael@0 1499 default:
michael@0 1500 crlgen_PrintError(crlGenData->parsedLineNum,
michael@0 1501 "unknown context type: %d.\n", structType);
michael@0 1502 PORT_Assert(0);
michael@0 1503 return SECFailure;
michael@0 1504 }
michael@0 1505 return SECSuccess;
michael@0 1506 }
michael@0 1507
michael@0 1508
michael@0 1509 /* Parser initialization function */
michael@0 1510 CRLGENGeneratorData*
michael@0 1511 CRLGEN_InitCrlGeneration(CERTSignedCrl *signCrl, PRFileDesc *src)
michael@0 1512 {
michael@0 1513 CRLGENGeneratorData *crlGenData = NULL;
michael@0 1514
michael@0 1515 PORT_Assert(signCrl && src);
michael@0 1516 if (!signCrl || !src) {
michael@0 1517 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 1518 return NULL;
michael@0 1519 }
michael@0 1520
michael@0 1521 crlGenData = PORT_ZNew(CRLGENGeneratorData);
michael@0 1522 if (!crlGenData) {
michael@0 1523 return NULL;
michael@0 1524 }
michael@0 1525
michael@0 1526 crlGenData->entryDataHashTable =
michael@0 1527 PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
michael@0 1528 PL_CompareValues, NULL, NULL);
michael@0 1529 if (!crlGenData->entryDataHashTable) {
michael@0 1530 PORT_Free(crlGenData);
michael@0 1531 return NULL;
michael@0 1532 }
michael@0 1533
michael@0 1534 crlGenData->src = src;
michael@0 1535 crlGenData->parsedLineNum = 1;
michael@0 1536 crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
michael@0 1537 crlGenData->signCrl = signCrl;
michael@0 1538 crlGenData->rangeFrom = 0;
michael@0 1539 crlGenData->rangeTo = 0;
michael@0 1540 crlGenData->crlExtHandle = NULL;
michael@0 1541
michael@0 1542 PORT_SetError(0);
michael@0 1543
michael@0 1544 return crlGenData;
michael@0 1545 }
michael@0 1546
michael@0 1547 void
michael@0 1548 CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData)
michael@0 1549 {
michael@0 1550 if (!crlGenData)
michael@0 1551 return;
michael@0 1552 if (crlGenData->src)
michael@0 1553 PR_Close(crlGenData->src);
michael@0 1554 PL_HashTableDestroy(crlGenData->entryDataHashTable);
michael@0 1555 PORT_Free(crlGenData);
michael@0 1556 }
michael@0 1557

mercurial