security/nss/cmd/signtool/certgen.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 #include "signtool.h"
michael@0 6
michael@0 7 #include "secoid.h"
michael@0 8 #include "cryptohi.h"
michael@0 9 #include "certdb.h"
michael@0 10
michael@0 11 static char *GetSubjectFromUser(unsigned long serial);
michael@0 12 static CERTCertificate*GenerateSelfSignedObjectSigningCert(char *nickname,
michael@0 13 CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
michael@0 14 char *token);
michael@0 15 static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
michael@0 16 CERTCertificate *cert, char *trusts);
michael@0 17 static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
michael@0 18 static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
michael@0 19 static CERTCertificate*install_cert(CERTCertDBHandle *db, SECItem *derCert,
michael@0 20 char *nickname);
michael@0 21 static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
michael@0 22 SECKEYPrivateKey **privk, int keysize);
michael@0 23 static CERTCertificateRequest*make_cert_request(char *subject,
michael@0 24 SECKEYPublicKey *pubk);
michael@0 25 static CERTCertificate *make_cert(CERTCertificateRequest *req,
michael@0 26 unsigned long serial, CERTName *ca_subject);
michael@0 27 static void output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db);
michael@0 28
michael@0 29
michael@0 30 /***********************************************************************
michael@0 31 *
michael@0 32 * G e n e r a t e C e r t
michael@0 33 *
michael@0 34 * Runs the whole process of creating a new cert, getting info from the
michael@0 35 * user, etc.
michael@0 36 */
michael@0 37 int
michael@0 38 GenerateCert(char *nickname, int keysize, char *token)
michael@0 39 {
michael@0 40 CERTCertDBHandle * db;
michael@0 41 CERTCertificate * cert;
michael@0 42 char *subject;
michael@0 43 unsigned long serial;
michael@0 44 char stdinbuf[160];
michael@0 45
michael@0 46 /* Print warning about having the browser open */
michael@0 47 PR_fprintf(PR_STDOUT /*always go to console*/,
michael@0 48 "\nWARNING: Performing this operation while the browser is running could cause"
michael@0 49 "\ncorruption of your security databases. If the browser is currently running,"
michael@0 50 "\nyou should exit the browser before continuing this operation. Enter "
michael@0 51 "\n\"y\" to continue, or anything else to abort: ");
michael@0 52 pr_fgets(stdinbuf, 160, PR_STDIN);
michael@0 53 PR_fprintf(PR_STDOUT, "\n");
michael@0 54 if (tolower(stdinbuf[0]) != 'y') {
michael@0 55 PR_fprintf(errorFD, "Operation aborted at user's request.\n");
michael@0 56 errorCount++;
michael@0 57 return - 1;
michael@0 58 }
michael@0 59
michael@0 60 db = CERT_GetDefaultCertDB();
michael@0 61 if (!db) {
michael@0 62 FatalError("Unable to open certificate database");
michael@0 63 }
michael@0 64
michael@0 65 if (PK11_FindCertFromNickname(nickname, &pwdata)) {
michael@0 66 PR_fprintf(errorFD,
michael@0 67 "ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
michael@0 68 "must choose a different nickname.\n", nickname);
michael@0 69 errorCount++;
michael@0 70 exit(ERRX);
michael@0 71 }
michael@0 72
michael@0 73 LL_L2UI(serial, PR_Now());
michael@0 74
michael@0 75 subject = GetSubjectFromUser(serial);
michael@0 76
michael@0 77 cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
michael@0 78 serial, keysize, token);
michael@0 79
michael@0 80 if (cert) {
michael@0 81 output_ca_cert(cert, db);
michael@0 82 CERT_DestroyCertificate(cert);
michael@0 83 }
michael@0 84
michael@0 85 PORT_Free(subject);
michael@0 86 return 0;
michael@0 87 }
michael@0 88
michael@0 89
michael@0 90 #undef VERBOSE_PROMPTS
michael@0 91
michael@0 92 /*********************************************************************8
michael@0 93 * G e t S u b j e c t F r o m U s e r
michael@0 94 *
michael@0 95 * Construct the subject information line for a certificate by querying
michael@0 96 * the user on stdin.
michael@0 97 */
michael@0 98 static char *
michael@0 99 GetSubjectFromUser(unsigned long serial)
michael@0 100 {
michael@0 101 char buf[STDIN_BUF_SIZE];
michael@0 102 char common_name_buf[STDIN_BUF_SIZE];
michael@0 103 char *common_name, *state, *orgunit, *country, *org, *locality;
michael@0 104 char *email, *uid;
michael@0 105 char *subject;
michael@0 106 char *cp;
michael@0 107 int subjectlen = 0;
michael@0 108
michael@0 109 common_name = state = orgunit = country = org = locality = email =
michael@0 110 uid = subject = NULL;
michael@0 111
michael@0 112 /* Get subject information */
michael@0 113 PR_fprintf(PR_STDOUT,
michael@0 114 "\nEnter certificate information. All fields are optional. Acceptable\n"
michael@0 115 "characters are numbers, letters, spaces, and apostrophes.\n");
michael@0 116
michael@0 117 #ifdef VERBOSE_PROMPTS
michael@0 118 PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
michael@0 119 "Enter the full name you want to give your certificate. (Example: Test-Only\n"
michael@0 120 "Object Signing Certificate)\n"
michael@0 121 "-->");
michael@0 122 #else
michael@0 123 PR_fprintf(PR_STDOUT, "certificate common name: ");
michael@0 124 #endif
michael@0 125 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 126 cp = chop(buf);
michael@0 127 if (*cp == '\0') {
michael@0 128 sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME,
michael@0 129 serial);
michael@0 130 cp = common_name_buf;
michael@0 131 }
michael@0 132 common_name = PORT_ZAlloc(strlen(cp) + 6);
michael@0 133 if (!common_name) {
michael@0 134 out_of_memory();
michael@0 135 }
michael@0 136 sprintf(common_name, "CN=%s, ", cp);
michael@0 137 subjectlen += strlen(common_name);
michael@0 138
michael@0 139 #ifdef VERBOSE_PROMPTS
michael@0 140 PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
michael@0 141 "Enter the name of your organization. For example, this could be the name\n"
michael@0 142 "of your company.\n"
michael@0 143 "-->");
michael@0 144 #else
michael@0 145 PR_fprintf(PR_STDOUT, "organization: ");
michael@0 146 #endif
michael@0 147 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 148 cp = chop(buf);
michael@0 149 if (*cp != '\0') {
michael@0 150 org = PORT_ZAlloc(strlen(cp) + 5);
michael@0 151 if (!org) {
michael@0 152 out_of_memory();
michael@0 153 }
michael@0 154 sprintf(org, "O=%s, ", cp);
michael@0 155 subjectlen += strlen(org);
michael@0 156 }
michael@0 157
michael@0 158 #ifdef VERBOSE_PROMPTS
michael@0 159 PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
michael@0 160 "Enter the name of your organization unit. For example, this could be the\n"
michael@0 161 "name of your department.\n"
michael@0 162 "-->");
michael@0 163 #else
michael@0 164 PR_fprintf(PR_STDOUT, "organization unit: ");
michael@0 165 #endif
michael@0 166 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 167 cp = chop(buf);
michael@0 168 if (*cp != '\0') {
michael@0 169 orgunit = PORT_ZAlloc(strlen(cp) + 6);
michael@0 170 if (!orgunit) {
michael@0 171 out_of_memory();
michael@0 172 }
michael@0 173 sprintf(orgunit, "OU=%s, ", cp);
michael@0 174 subjectlen += strlen(orgunit);
michael@0 175 }
michael@0 176
michael@0 177 #ifdef VERBOSE_PROMPTS
michael@0 178 PR_fprintf(PR_STDOUT, "\nSTATE\n"
michael@0 179 "Enter the name of your state or province.\n"
michael@0 180 "-->");
michael@0 181 #else
michael@0 182 PR_fprintf(PR_STDOUT, "state or province: ");
michael@0 183 #endif
michael@0 184 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 185 cp = chop(buf);
michael@0 186 if (*cp != '\0') {
michael@0 187 state = PORT_ZAlloc(strlen(cp) + 6);
michael@0 188 if (!state) {
michael@0 189 out_of_memory();
michael@0 190 }
michael@0 191 sprintf(state, "ST=%s, ", cp);
michael@0 192 subjectlen += strlen(state);
michael@0 193 }
michael@0 194
michael@0 195 #ifdef VERBOSE_PROMPTS
michael@0 196 PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
michael@0 197 "Enter the 2-character abbreviation for the name of your country.\n"
michael@0 198 "-->");
michael@0 199 #else
michael@0 200 PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
michael@0 201 #endif
michael@0 202 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 203 cp = chop(cp);
michael@0 204 if (strlen(cp) != 2) {
michael@0 205 *cp = '\0'; /* country code must be 2 chars */
michael@0 206 }
michael@0 207 if (*cp != '\0') {
michael@0 208 country = PORT_ZAlloc(strlen(cp) + 5);
michael@0 209 if (!country) {
michael@0 210 out_of_memory();
michael@0 211 }
michael@0 212 sprintf(country, "C=%s, ", cp);
michael@0 213 subjectlen += strlen(country);
michael@0 214 }
michael@0 215
michael@0 216 #ifdef VERBOSE_PROMPTS
michael@0 217 PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
michael@0 218 "Enter your system username or UID\n"
michael@0 219 "-->");
michael@0 220 #else
michael@0 221 PR_fprintf(PR_STDOUT, "username: ");
michael@0 222 #endif
michael@0 223 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 224 cp = chop(buf);
michael@0 225 if (*cp != '\0') {
michael@0 226 uid = PORT_ZAlloc(strlen(cp) + 7);
michael@0 227 if (!uid) {
michael@0 228 out_of_memory();
michael@0 229 }
michael@0 230 sprintf(uid, "UID=%s, ", cp);
michael@0 231 subjectlen += strlen(uid);
michael@0 232 }
michael@0 233
michael@0 234 #ifdef VERBOSE_PROMPTS
michael@0 235 PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
michael@0 236 "Enter your email address.\n"
michael@0 237 "-->");
michael@0 238 #else
michael@0 239 PR_fprintf(PR_STDOUT, "email address: ");
michael@0 240 #endif
michael@0 241 fgets(buf, STDIN_BUF_SIZE, stdin);
michael@0 242 cp = chop(buf);
michael@0 243 if (*cp != '\0') {
michael@0 244 email = PORT_ZAlloc(strlen(cp) + 5);
michael@0 245 if (!email) {
michael@0 246 out_of_memory();
michael@0 247 }
michael@0 248 sprintf(email, "E=%s,", cp);
michael@0 249 subjectlen += strlen(email);
michael@0 250 }
michael@0 251
michael@0 252 subjectlen++;
michael@0 253
michael@0 254 subject = PORT_ZAlloc(subjectlen);
michael@0 255 if (!subject) {
michael@0 256 out_of_memory();
michael@0 257 }
michael@0 258
michael@0 259 sprintf(subject, "%s%s%s%s%s%s%s",
michael@0 260 common_name ? common_name : "",
michael@0 261 org ? org : "",
michael@0 262 orgunit ? orgunit : "",
michael@0 263 state ? state : "",
michael@0 264 country ? country : "",
michael@0 265 uid ? uid : "",
michael@0 266 email ? email : ""
michael@0 267 );
michael@0 268 if ( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) {
michael@0 269 subject[strlen(subject)-2] = '\0';
michael@0 270 }
michael@0 271
michael@0 272 PORT_Free(common_name);
michael@0 273 PORT_Free(org);
michael@0 274 PORT_Free(orgunit);
michael@0 275 PORT_Free(state);
michael@0 276 PORT_Free(country);
michael@0 277 PORT_Free(uid);
michael@0 278 PORT_Free(email);
michael@0 279
michael@0 280 return subject;
michael@0 281 }
michael@0 282
michael@0 283
michael@0 284 /**************************************************************************
michael@0 285 *
michael@0 286 * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
michael@0 287 * *phew*^
michael@0 288 *
michael@0 289 */
michael@0 290 static CERTCertificate*
michael@0 291 GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
michael@0 292 char *subject, unsigned long serial, int keysize, char *token)
michael@0 293 {
michael@0 294 CERTCertificate * cert, *temp_cert;
michael@0 295 SECItem * derCert;
michael@0 296 CERTCertificateRequest * req;
michael@0 297
michael@0 298 PK11SlotInfo * slot = NULL;
michael@0 299 SECKEYPrivateKey * privk = NULL;
michael@0 300 SECKEYPublicKey * pubk = NULL;
michael@0 301
michael@0 302 if ( token ) {
michael@0 303 slot = PK11_FindSlotByName(token);
michael@0 304 } else {
michael@0 305 slot = PK11_GetInternalKeySlot();
michael@0 306 }
michael@0 307
michael@0 308 if (slot == NULL) {
michael@0 309 PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
michael@0 310 token ? token : "");
michael@0 311 errorCount++;
michael@0 312 exit (ERRX);
michael@0 313 }
michael@0 314
michael@0 315 if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
michael@0 316 FatalError("Error generating keypair.");
michael@0 317 }
michael@0 318 req = make_cert_request (subject, pubk);
michael@0 319 temp_cert = make_cert (req, serial, &req->subject);
michael@0 320 if (set_cert_type(temp_cert,
michael@0 321 NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
michael@0 322 != SECSuccess) {
michael@0 323 FatalError("Unable to set cert type");
michael@0 324 }
michael@0 325
michael@0 326 derCert = sign_cert (temp_cert, privk);
michael@0 327 cert = install_cert(db, derCert, nickname);
michael@0 328 if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
michael@0 329 FatalError("Unable to change trust on generated certificate");
michael@0 330 }
michael@0 331
michael@0 332 /* !!! Free memory ? !!! */
michael@0 333 PK11_FreeSlot(slot);
michael@0 334 SECKEY_DestroyPrivateKey(privk);
michael@0 335 SECKEY_DestroyPublicKey(pubk);
michael@0 336
michael@0 337 return cert;
michael@0 338 }
michael@0 339
michael@0 340
michael@0 341 /**************************************************************************
michael@0 342 *
michael@0 343 * C h a n g e T r u s t A t t r i b u t e s
michael@0 344 */
michael@0 345 static SECStatus
michael@0 346 ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
michael@0 347 {
michael@0 348
michael@0 349 CERTCertTrust * trust;
michael@0 350
michael@0 351 if (!db || !cert || !trusts) {
michael@0 352 PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n");
michael@0 353 errorCount++;
michael@0 354 return SECFailure;
michael@0 355 }
michael@0 356
michael@0 357 trust = (CERTCertTrust * ) PORT_ZAlloc(sizeof(CERTCertTrust));
michael@0 358 if (!trust) {
michael@0 359 PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
michael@0 360 "CERTCertTrust\n");
michael@0 361 errorCount++;
michael@0 362 return SECFailure;
michael@0 363 }
michael@0 364
michael@0 365 if ( CERT_DecodeTrustString(trust, trusts) ) {
michael@0 366 return SECFailure;
michael@0 367 }
michael@0 368
michael@0 369 if ( CERT_ChangeCertTrust(db, cert, trust) ) {
michael@0 370 PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
michael@0 371 cert->nickname ? cert->nickname : "");
michael@0 372 errorCount++;
michael@0 373 return SECFailure;
michael@0 374 }
michael@0 375
michael@0 376 return SECSuccess;
michael@0 377 }
michael@0 378
michael@0 379
michael@0 380 /*************************************************************************
michael@0 381 *
michael@0 382 * s e t _ c e r t _ t y p e
michael@0 383 */
michael@0 384 static SECStatus
michael@0 385 set_cert_type(CERTCertificate *cert, unsigned int type)
michael@0 386 {
michael@0 387 void *context;
michael@0 388 SECStatus status = SECSuccess;
michael@0 389 SECItem certType;
michael@0 390 char ctype;
michael@0 391
michael@0 392 context = CERT_StartCertExtensions(cert);
michael@0 393
michael@0 394 certType.type = siBuffer;
michael@0 395 certType.data = (unsigned char * ) &ctype;
michael@0 396 certType.len = 1;
michael@0 397 ctype = (unsigned char)type;
michael@0 398 if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
michael@0 399 &certType, PR_TRUE /*critical*/) != SECSuccess) {
michael@0 400 status = SECFailure;
michael@0 401 }
michael@0 402
michael@0 403 if (CERT_FinishExtensions(context) != SECSuccess) {
michael@0 404 status = SECFailure;
michael@0 405 }
michael@0 406
michael@0 407 return status;
michael@0 408 }
michael@0 409
michael@0 410
michael@0 411 /********************************************************************
michael@0 412 *
michael@0 413 * s i g n _ c e r t
michael@0 414 */
michael@0 415 static SECItem *
michael@0 416 sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
michael@0 417 {
michael@0 418 SECStatus rv;
michael@0 419
michael@0 420 SECItem der2;
michael@0 421 SECItem * result2;
michael@0 422
michael@0 423 void *dummy;
michael@0 424 SECOidTag alg = SEC_OID_UNKNOWN;
michael@0 425
michael@0 426 alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
michael@0 427 if (alg == SEC_OID_UNKNOWN) {
michael@0 428 FatalError("Unknown key type");
michael@0 429 }
michael@0 430
michael@0 431 rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
michael@0 432
michael@0 433 if (rv != SECSuccess) {
michael@0 434 PR_fprintf(errorFD, "%s: unable to set signature alg id\n",
michael@0 435 PROGRAM_NAME);
michael@0 436 errorCount++;
michael@0 437 exit (ERRX);
michael@0 438 }
michael@0 439
michael@0 440 der2.len = 0;
michael@0 441 der2.data = NULL;
michael@0 442
michael@0 443 dummy = SEC_ASN1EncodeItem
michael@0 444 (cert->arena, &der2, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
michael@0 445
michael@0 446 if (rv != SECSuccess) {
michael@0 447 PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
michael@0 448 errorCount++;
michael@0 449 exit (ERRX);
michael@0 450 }
michael@0 451
michael@0 452 result2 = (SECItem * ) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem));
michael@0 453 if (result2 == NULL)
michael@0 454 out_of_memory();
michael@0 455
michael@0 456 rv = SEC_DerSignData
michael@0 457 (cert->arena, result2, der2.data, der2.len, privk, alg);
michael@0 458
michael@0 459 if (rv != SECSuccess) {
michael@0 460 PR_fprintf(errorFD, "can't sign encoded certificate data\n");
michael@0 461 errorCount++;
michael@0 462 exit (ERRX);
michael@0 463 } else if (verbosity >= 0) {
michael@0 464 PR_fprintf(outputFD, "certificate has been signed\n");
michael@0 465 }
michael@0 466
michael@0 467 cert->derCert = *result2;
michael@0 468
michael@0 469 return result2;
michael@0 470 }
michael@0 471
michael@0 472
michael@0 473 /*********************************************************************
michael@0 474 *
michael@0 475 * i n s t a l l _ c e r t
michael@0 476 *
michael@0 477 * Installs the cert in the permanent database.
michael@0 478 */
michael@0 479 static CERTCertificate*
michael@0 480 install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
michael@0 481 {
michael@0 482 CERTCertificate * newcert;
michael@0 483 PK11SlotInfo * newSlot;
michael@0 484
michael@0 485
michael@0 486 newSlot = PK11_ImportDERCertForKey(derCert, nickname, &pwdata);
michael@0 487 if ( newSlot == NULL ) {
michael@0 488 PR_fprintf(errorFD, "Unable to install certificate\n");
michael@0 489 errorCount++;
michael@0 490 exit(ERRX);
michael@0 491 }
michael@0 492
michael@0 493 newcert = PK11_FindCertFromDERCertItem(newSlot, derCert, &pwdata);
michael@0 494 PK11_FreeSlot(newSlot);
michael@0 495 if (newcert == NULL) {
michael@0 496 PR_fprintf(errorFD, "%s: can't find new certificate\n",
michael@0 497 PROGRAM_NAME);
michael@0 498 errorCount++;
michael@0 499 exit (ERRX);
michael@0 500 }
michael@0 501
michael@0 502 if (verbosity >= 0) {
michael@0 503 PR_fprintf(outputFD, "certificate \"%s\" added to database\n",
michael@0 504 nickname);
michael@0 505 }
michael@0 506
michael@0 507 return newcert;
michael@0 508 }
michael@0 509
michael@0 510
michael@0 511 /******************************************************************
michael@0 512 *
michael@0 513 * G e n e r a t e K e y P a i r
michael@0 514 */
michael@0 515 static SECStatus
michael@0 516 GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
michael@0 517 SECKEYPrivateKey **privk, int keysize)
michael@0 518 {
michael@0 519
michael@0 520 PK11RSAGenParams rsaParams;
michael@0 521
michael@0 522 if ( keysize == -1 ) {
michael@0 523 rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
michael@0 524 } else {
michael@0 525 rsaParams.keySizeInBits = keysize;
michael@0 526 }
michael@0 527 rsaParams.pe = 0x10001;
michael@0 528
michael@0 529 if (PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, &pwdata)
michael@0 530 != SECSuccess) {
michael@0 531 SECU_PrintError(progName, "failure authenticating to key database.\n");
michael@0 532 exit(ERRX);
michael@0 533 }
michael@0 534
michael@0 535 *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
michael@0 536
michael@0 537 pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, &pwdata);
michael@0 538
michael@0 539 if (*privk != NULL && *pubk != NULL) {
michael@0 540 if (verbosity >= 0) {
michael@0 541 PR_fprintf(outputFD, "generated public/private key pair\n");
michael@0 542 }
michael@0 543 } else {
michael@0 544 SECU_PrintError(progName, "failure generating key pair\n");
michael@0 545 exit (ERRX);
michael@0 546 }
michael@0 547
michael@0 548 return SECSuccess;
michael@0 549 }
michael@0 550
michael@0 551
michael@0 552
michael@0 553 /******************************************************************
michael@0 554 *
michael@0 555 * m a k e _ c e r t _ r e q u e s t
michael@0 556 */
michael@0 557 static CERTCertificateRequest*
michael@0 558 make_cert_request(char *subject, SECKEYPublicKey *pubk)
michael@0 559 {
michael@0 560 CERTName * subj;
michael@0 561 CERTSubjectPublicKeyInfo * spki;
michael@0 562
michael@0 563 CERTCertificateRequest * req;
michael@0 564
michael@0 565 /* Create info about public key */
michael@0 566 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
michael@0 567 if (!spki) {
michael@0 568 SECU_PrintError(progName, "unable to create subject public key");
michael@0 569 exit (ERRX);
michael@0 570 }
michael@0 571
michael@0 572 subj = CERT_AsciiToName (subject);
michael@0 573 if (subj == NULL) {
michael@0 574 FatalError("Invalid data in certificate description");
michael@0 575 }
michael@0 576
michael@0 577 /* Generate certificate request */
michael@0 578 req = CERT_CreateCertificateRequest(subj, spki, 0);
michael@0 579 if (!req) {
michael@0 580 SECU_PrintError(progName, "unable to make certificate request");
michael@0 581 exit (ERRX);
michael@0 582 }
michael@0 583
michael@0 584 SECKEY_DestroySubjectPublicKeyInfo(spki);
michael@0 585 CERT_DestroyName(subj);
michael@0 586
michael@0 587 if (verbosity >= 0) {
michael@0 588 PR_fprintf(outputFD, "certificate request generated\n");
michael@0 589 }
michael@0 590
michael@0 591 return req;
michael@0 592 }
michael@0 593
michael@0 594
michael@0 595 /******************************************************************
michael@0 596 *
michael@0 597 * m a k e _ c e r t
michael@0 598 */
michael@0 599 static CERTCertificate *
michael@0 600 make_cert(CERTCertificateRequest *req, unsigned long serial,
michael@0 601 CERTName *ca_subject)
michael@0 602 {
michael@0 603 CERTCertificate * cert;
michael@0 604
michael@0 605 CERTValidity * validity = NULL;
michael@0 606
michael@0 607 PRTime now, after;
michael@0 608 PRExplodedTime printableTime;
michael@0 609
michael@0 610 now = PR_Now();
michael@0 611 PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
michael@0 612
michael@0 613 printableTime.tm_month += 3;
michael@0 614 after = PR_ImplodeTime (&printableTime);
michael@0 615
michael@0 616 validity = CERT_CreateValidity (now, after);
michael@0 617
michael@0 618 if (validity == NULL) {
michael@0 619 PR_fprintf(errorFD, "%s: error creating certificate validity\n",
michael@0 620 PROGRAM_NAME);
michael@0 621 errorCount++;
michael@0 622 exit (ERRX);
michael@0 623 }
michael@0 624
michael@0 625 cert = CERT_CreateCertificate
michael@0 626 (serial, ca_subject, validity, req);
michael@0 627
michael@0 628 if (cert == NULL) {
michael@0 629 /* should probably be more precise here */
michael@0 630 PR_fprintf(errorFD, "%s: error while generating certificate\n",
michael@0 631 PROGRAM_NAME);
michael@0 632 errorCount++;
michael@0 633 exit (ERRX);
michael@0 634 }
michael@0 635
michael@0 636 return cert;
michael@0 637 }
michael@0 638
michael@0 639
michael@0 640 /*************************************************************************
michael@0 641 *
michael@0 642 * o u t p u t _ c a _ c e r t
michael@0 643 */
michael@0 644 static void
michael@0 645 output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db)
michael@0 646 {
michael@0 647 FILE * out;
michael@0 648
michael@0 649 SECItem * encodedCertChain;
michael@0 650 SEC_PKCS7ContentInfo * certChain;
michael@0 651 char *filename;
michael@0 652
michael@0 653 /* the raw */
michael@0 654
michael@0 655 filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8);
michael@0 656 if (!filename)
michael@0 657 out_of_memory();
michael@0 658
michael@0 659 sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
michael@0 660 if ((out = fopen (filename, "wb")) == NULL) {
michael@0 661 PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
michael@0 662 filename);
michael@0 663 errorCount++;
michael@0 664 exit(ERRX);
michael@0 665 }
michael@0 666
michael@0 667 certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db);
michael@0 668 encodedCertChain
michael@0 669 = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL);
michael@0 670 SEC_PKCS7DestroyContentInfo (certChain);
michael@0 671
michael@0 672 if (encodedCertChain) {
michael@0 673 fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
michael@0 674 fwrite (encodedCertChain->data, 1, encodedCertChain->len,
michael@0 675 out);
michael@0 676 SECITEM_FreeItem(encodedCertChain, PR_TRUE);
michael@0 677 } else {
michael@0 678 PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n",
michael@0 679 PROGRAM_NAME);
michael@0 680 errorCount++;
michael@0 681 exit(ERRX);
michael@0 682 }
michael@0 683
michael@0 684 fclose (out);
michael@0 685
michael@0 686 /* and the cooked */
michael@0 687
michael@0 688 sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
michael@0 689 if ((out = fopen (filename, "wb")) == NULL) {
michael@0 690 PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
michael@0 691 filename);
michael@0 692 errorCount++;
michael@0 693 return;
michael@0 694 }
michael@0 695
michael@0 696 fprintf (out, "%s\n%s\n%s\n",
michael@0 697 NS_CERT_HEADER,
michael@0 698 BTOA_DataToAscii (cert->derCert.data, cert->derCert.len),
michael@0 699 NS_CERT_TRAILER);
michael@0 700
michael@0 701 fclose (out);
michael@0 702
michael@0 703 if (verbosity >= 0) {
michael@0 704 PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
michael@0 705 DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
michael@0 706 }
michael@0 707 }
michael@0 708
michael@0 709

mercurial