1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/signtool/certgen.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,709 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "signtool.h" 1.9 + 1.10 +#include "secoid.h" 1.11 +#include "cryptohi.h" 1.12 +#include "certdb.h" 1.13 + 1.14 +static char *GetSubjectFromUser(unsigned long serial); 1.15 +static CERTCertificate*GenerateSelfSignedObjectSigningCert(char *nickname, 1.16 + CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize, 1.17 + char *token); 1.18 +static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db, 1.19 + CERTCertificate *cert, char *trusts); 1.20 +static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type); 1.21 +static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk); 1.22 +static CERTCertificate*install_cert(CERTCertDBHandle *db, SECItem *derCert, 1.23 + char *nickname); 1.24 +static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk, 1.25 + SECKEYPrivateKey **privk, int keysize); 1.26 +static CERTCertificateRequest*make_cert_request(char *subject, 1.27 + SECKEYPublicKey *pubk); 1.28 +static CERTCertificate *make_cert(CERTCertificateRequest *req, 1.29 + unsigned long serial, CERTName *ca_subject); 1.30 +static void output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db); 1.31 + 1.32 + 1.33 +/*********************************************************************** 1.34 + * 1.35 + * G e n e r a t e C e r t 1.36 + * 1.37 + * Runs the whole process of creating a new cert, getting info from the 1.38 + * user, etc. 1.39 + */ 1.40 +int 1.41 +GenerateCert(char *nickname, int keysize, char *token) 1.42 +{ 1.43 + CERTCertDBHandle * db; 1.44 + CERTCertificate * cert; 1.45 + char *subject; 1.46 + unsigned long serial; 1.47 + char stdinbuf[160]; 1.48 + 1.49 + /* Print warning about having the browser open */ 1.50 + PR_fprintf(PR_STDOUT /*always go to console*/, 1.51 + "\nWARNING: Performing this operation while the browser is running could cause" 1.52 + "\ncorruption of your security databases. If the browser is currently running," 1.53 + "\nyou should exit the browser before continuing this operation. Enter " 1.54 + "\n\"y\" to continue, or anything else to abort: "); 1.55 + pr_fgets(stdinbuf, 160, PR_STDIN); 1.56 + PR_fprintf(PR_STDOUT, "\n"); 1.57 + if (tolower(stdinbuf[0]) != 'y') { 1.58 + PR_fprintf(errorFD, "Operation aborted at user's request.\n"); 1.59 + errorCount++; 1.60 + return - 1; 1.61 + } 1.62 + 1.63 + db = CERT_GetDefaultCertDB(); 1.64 + if (!db) { 1.65 + FatalError("Unable to open certificate database"); 1.66 + } 1.67 + 1.68 + if (PK11_FindCertFromNickname(nickname, &pwdata)) { 1.69 + PR_fprintf(errorFD, 1.70 + "ERROR: Certificate with nickname \"%s\" already exists in database. You\n" 1.71 + "must choose a different nickname.\n", nickname); 1.72 + errorCount++; 1.73 + exit(ERRX); 1.74 + } 1.75 + 1.76 + LL_L2UI(serial, PR_Now()); 1.77 + 1.78 + subject = GetSubjectFromUser(serial); 1.79 + 1.80 + cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject, 1.81 + serial, keysize, token); 1.82 + 1.83 + if (cert) { 1.84 + output_ca_cert(cert, db); 1.85 + CERT_DestroyCertificate(cert); 1.86 + } 1.87 + 1.88 + PORT_Free(subject); 1.89 + return 0; 1.90 +} 1.91 + 1.92 + 1.93 +#undef VERBOSE_PROMPTS 1.94 + 1.95 +/*********************************************************************8 1.96 + * G e t S u b j e c t F r o m U s e r 1.97 + * 1.98 + * Construct the subject information line for a certificate by querying 1.99 + * the user on stdin. 1.100 + */ 1.101 +static char * 1.102 +GetSubjectFromUser(unsigned long serial) 1.103 +{ 1.104 + char buf[STDIN_BUF_SIZE]; 1.105 + char common_name_buf[STDIN_BUF_SIZE]; 1.106 + char *common_name, *state, *orgunit, *country, *org, *locality; 1.107 + char *email, *uid; 1.108 + char *subject; 1.109 + char *cp; 1.110 + int subjectlen = 0; 1.111 + 1.112 + common_name = state = orgunit = country = org = locality = email = 1.113 + uid = subject = NULL; 1.114 + 1.115 + /* Get subject information */ 1.116 + PR_fprintf(PR_STDOUT, 1.117 + "\nEnter certificate information. All fields are optional. Acceptable\n" 1.118 + "characters are numbers, letters, spaces, and apostrophes.\n"); 1.119 + 1.120 +#ifdef VERBOSE_PROMPTS 1.121 + PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n" 1.122 + "Enter the full name you want to give your certificate. (Example: Test-Only\n" 1.123 + "Object Signing Certificate)\n" 1.124 + "-->"); 1.125 +#else 1.126 + PR_fprintf(PR_STDOUT, "certificate common name: "); 1.127 +#endif 1.128 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.129 + cp = chop(buf); 1.130 + if (*cp == '\0') { 1.131 + sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME, 1.132 + serial); 1.133 + cp = common_name_buf; 1.134 + } 1.135 + common_name = PORT_ZAlloc(strlen(cp) + 6); 1.136 + if (!common_name) { 1.137 + out_of_memory(); 1.138 + } 1.139 + sprintf(common_name, "CN=%s, ", cp); 1.140 + subjectlen += strlen(common_name); 1.141 + 1.142 +#ifdef VERBOSE_PROMPTS 1.143 + PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n" 1.144 + "Enter the name of your organization. For example, this could be the name\n" 1.145 + "of your company.\n" 1.146 + "-->"); 1.147 +#else 1.148 + PR_fprintf(PR_STDOUT, "organization: "); 1.149 +#endif 1.150 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.151 + cp = chop(buf); 1.152 + if (*cp != '\0') { 1.153 + org = PORT_ZAlloc(strlen(cp) + 5); 1.154 + if (!org) { 1.155 + out_of_memory(); 1.156 + } 1.157 + sprintf(org, "O=%s, ", cp); 1.158 + subjectlen += strlen(org); 1.159 + } 1.160 + 1.161 +#ifdef VERBOSE_PROMPTS 1.162 + PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n" 1.163 + "Enter the name of your organization unit. For example, this could be the\n" 1.164 + "name of your department.\n" 1.165 + "-->"); 1.166 +#else 1.167 + PR_fprintf(PR_STDOUT, "organization unit: "); 1.168 +#endif 1.169 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.170 + cp = chop(buf); 1.171 + if (*cp != '\0') { 1.172 + orgunit = PORT_ZAlloc(strlen(cp) + 6); 1.173 + if (!orgunit) { 1.174 + out_of_memory(); 1.175 + } 1.176 + sprintf(orgunit, "OU=%s, ", cp); 1.177 + subjectlen += strlen(orgunit); 1.178 + } 1.179 + 1.180 +#ifdef VERBOSE_PROMPTS 1.181 + PR_fprintf(PR_STDOUT, "\nSTATE\n" 1.182 + "Enter the name of your state or province.\n" 1.183 + "-->"); 1.184 +#else 1.185 + PR_fprintf(PR_STDOUT, "state or province: "); 1.186 +#endif 1.187 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.188 + cp = chop(buf); 1.189 + if (*cp != '\0') { 1.190 + state = PORT_ZAlloc(strlen(cp) + 6); 1.191 + if (!state) { 1.192 + out_of_memory(); 1.193 + } 1.194 + sprintf(state, "ST=%s, ", cp); 1.195 + subjectlen += strlen(state); 1.196 + } 1.197 + 1.198 +#ifdef VERBOSE_PROMPTS 1.199 + PR_fprintf(PR_STDOUT, "\nCOUNTRY\n" 1.200 + "Enter the 2-character abbreviation for the name of your country.\n" 1.201 + "-->"); 1.202 +#else 1.203 + PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): "); 1.204 +#endif 1.205 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.206 + cp = chop(cp); 1.207 + if (strlen(cp) != 2) { 1.208 + *cp = '\0'; /* country code must be 2 chars */ 1.209 + } 1.210 + if (*cp != '\0') { 1.211 + country = PORT_ZAlloc(strlen(cp) + 5); 1.212 + if (!country) { 1.213 + out_of_memory(); 1.214 + } 1.215 + sprintf(country, "C=%s, ", cp); 1.216 + subjectlen += strlen(country); 1.217 + } 1.218 + 1.219 +#ifdef VERBOSE_PROMPTS 1.220 + PR_fprintf(PR_STDOUT, "\nUSERNAME\n" 1.221 + "Enter your system username or UID\n" 1.222 + "-->"); 1.223 +#else 1.224 + PR_fprintf(PR_STDOUT, "username: "); 1.225 +#endif 1.226 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.227 + cp = chop(buf); 1.228 + if (*cp != '\0') { 1.229 + uid = PORT_ZAlloc(strlen(cp) + 7); 1.230 + if (!uid) { 1.231 + out_of_memory(); 1.232 + } 1.233 + sprintf(uid, "UID=%s, ", cp); 1.234 + subjectlen += strlen(uid); 1.235 + } 1.236 + 1.237 +#ifdef VERBOSE_PROMPTS 1.238 + PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n" 1.239 + "Enter your email address.\n" 1.240 + "-->"); 1.241 +#else 1.242 + PR_fprintf(PR_STDOUT, "email address: "); 1.243 +#endif 1.244 + fgets(buf, STDIN_BUF_SIZE, stdin); 1.245 + cp = chop(buf); 1.246 + if (*cp != '\0') { 1.247 + email = PORT_ZAlloc(strlen(cp) + 5); 1.248 + if (!email) { 1.249 + out_of_memory(); 1.250 + } 1.251 + sprintf(email, "E=%s,", cp); 1.252 + subjectlen += strlen(email); 1.253 + } 1.254 + 1.255 + subjectlen++; 1.256 + 1.257 + subject = PORT_ZAlloc(subjectlen); 1.258 + if (!subject) { 1.259 + out_of_memory(); 1.260 + } 1.261 + 1.262 + sprintf(subject, "%s%s%s%s%s%s%s", 1.263 + common_name ? common_name : "", 1.264 + org ? org : "", 1.265 + orgunit ? orgunit : "", 1.266 + state ? state : "", 1.267 + country ? country : "", 1.268 + uid ? uid : "", 1.269 + email ? email : "" 1.270 + ); 1.271 + if ( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) { 1.272 + subject[strlen(subject)-2] = '\0'; 1.273 + } 1.274 + 1.275 + PORT_Free(common_name); 1.276 + PORT_Free(org); 1.277 + PORT_Free(orgunit); 1.278 + PORT_Free(state); 1.279 + PORT_Free(country); 1.280 + PORT_Free(uid); 1.281 + PORT_Free(email); 1.282 + 1.283 + return subject; 1.284 +} 1.285 + 1.286 + 1.287 +/************************************************************************** 1.288 + * 1.289 + * 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 1.290 + * *phew*^ 1.291 + * 1.292 + */ 1.293 +static CERTCertificate* 1.294 +GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db, 1.295 + char *subject, unsigned long serial, int keysize, char *token) 1.296 +{ 1.297 + CERTCertificate * cert, *temp_cert; 1.298 + SECItem * derCert; 1.299 + CERTCertificateRequest * req; 1.300 + 1.301 + PK11SlotInfo * slot = NULL; 1.302 + SECKEYPrivateKey * privk = NULL; 1.303 + SECKEYPublicKey * pubk = NULL; 1.304 + 1.305 + if ( token ) { 1.306 + slot = PK11_FindSlotByName(token); 1.307 + } else { 1.308 + slot = PK11_GetInternalKeySlot(); 1.309 + } 1.310 + 1.311 + if (slot == NULL) { 1.312 + PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n", 1.313 + token ? token : ""); 1.314 + errorCount++; 1.315 + exit (ERRX); 1.316 + } 1.317 + 1.318 + if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) { 1.319 + FatalError("Error generating keypair."); 1.320 + } 1.321 + req = make_cert_request (subject, pubk); 1.322 + temp_cert = make_cert (req, serial, &req->subject); 1.323 + if (set_cert_type(temp_cert, 1.324 + NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA) 1.325 + != SECSuccess) { 1.326 + FatalError("Unable to set cert type"); 1.327 + } 1.328 + 1.329 + derCert = sign_cert (temp_cert, privk); 1.330 + cert = install_cert(db, derCert, nickname); 1.331 + if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) { 1.332 + FatalError("Unable to change trust on generated certificate"); 1.333 + } 1.334 + 1.335 + /* !!! Free memory ? !!! */ 1.336 + PK11_FreeSlot(slot); 1.337 + SECKEY_DestroyPrivateKey(privk); 1.338 + SECKEY_DestroyPublicKey(pubk); 1.339 + 1.340 + return cert; 1.341 +} 1.342 + 1.343 + 1.344 +/************************************************************************** 1.345 + * 1.346 + * C h a n g e T r u s t A t t r i b u t e s 1.347 + */ 1.348 +static SECStatus 1.349 +ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts) 1.350 +{ 1.351 + 1.352 + CERTCertTrust * trust; 1.353 + 1.354 + if (!db || !cert || !trusts) { 1.355 + PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n"); 1.356 + errorCount++; 1.357 + return SECFailure; 1.358 + } 1.359 + 1.360 + trust = (CERTCertTrust * ) PORT_ZAlloc(sizeof(CERTCertTrust)); 1.361 + if (!trust) { 1.362 + PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate " 1.363 + "CERTCertTrust\n"); 1.364 + errorCount++; 1.365 + return SECFailure; 1.366 + } 1.367 + 1.368 + if ( CERT_DecodeTrustString(trust, trusts) ) { 1.369 + return SECFailure; 1.370 + } 1.371 + 1.372 + if ( CERT_ChangeCertTrust(db, cert, trust) ) { 1.373 + PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n", 1.374 + cert->nickname ? cert->nickname : ""); 1.375 + errorCount++; 1.376 + return SECFailure; 1.377 + } 1.378 + 1.379 + return SECSuccess; 1.380 +} 1.381 + 1.382 + 1.383 +/************************************************************************* 1.384 + * 1.385 + * s e t _ c e r t _ t y p e 1.386 + */ 1.387 +static SECStatus 1.388 +set_cert_type(CERTCertificate *cert, unsigned int type) 1.389 +{ 1.390 + void *context; 1.391 + SECStatus status = SECSuccess; 1.392 + SECItem certType; 1.393 + char ctype; 1.394 + 1.395 + context = CERT_StartCertExtensions(cert); 1.396 + 1.397 + certType.type = siBuffer; 1.398 + certType.data = (unsigned char * ) &ctype; 1.399 + certType.len = 1; 1.400 + ctype = (unsigned char)type; 1.401 + if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE, 1.402 + &certType, PR_TRUE /*critical*/) != SECSuccess) { 1.403 + status = SECFailure; 1.404 + } 1.405 + 1.406 + if (CERT_FinishExtensions(context) != SECSuccess) { 1.407 + status = SECFailure; 1.408 + } 1.409 + 1.410 + return status; 1.411 +} 1.412 + 1.413 + 1.414 +/******************************************************************** 1.415 + * 1.416 + * s i g n _ c e r t 1.417 + */ 1.418 +static SECItem * 1.419 +sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk) 1.420 +{ 1.421 + SECStatus rv; 1.422 + 1.423 + SECItem der2; 1.424 + SECItem * result2; 1.425 + 1.426 + void *dummy; 1.427 + SECOidTag alg = SEC_OID_UNKNOWN; 1.428 + 1.429 + alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN); 1.430 + if (alg == SEC_OID_UNKNOWN) { 1.431 + FatalError("Unknown key type"); 1.432 + } 1.433 + 1.434 + rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0); 1.435 + 1.436 + if (rv != SECSuccess) { 1.437 + PR_fprintf(errorFD, "%s: unable to set signature alg id\n", 1.438 + PROGRAM_NAME); 1.439 + errorCount++; 1.440 + exit (ERRX); 1.441 + } 1.442 + 1.443 + der2.len = 0; 1.444 + der2.data = NULL; 1.445 + 1.446 + dummy = SEC_ASN1EncodeItem 1.447 + (cert->arena, &der2, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); 1.448 + 1.449 + if (rv != SECSuccess) { 1.450 + PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME); 1.451 + errorCount++; 1.452 + exit (ERRX); 1.453 + } 1.454 + 1.455 + result2 = (SECItem * ) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem)); 1.456 + if (result2 == NULL) 1.457 + out_of_memory(); 1.458 + 1.459 + rv = SEC_DerSignData 1.460 + (cert->arena, result2, der2.data, der2.len, privk, alg); 1.461 + 1.462 + if (rv != SECSuccess) { 1.463 + PR_fprintf(errorFD, "can't sign encoded certificate data\n"); 1.464 + errorCount++; 1.465 + exit (ERRX); 1.466 + } else if (verbosity >= 0) { 1.467 + PR_fprintf(outputFD, "certificate has been signed\n"); 1.468 + } 1.469 + 1.470 + cert->derCert = *result2; 1.471 + 1.472 + return result2; 1.473 +} 1.474 + 1.475 + 1.476 +/********************************************************************* 1.477 + * 1.478 + * i n s t a l l _ c e r t 1.479 + * 1.480 + * Installs the cert in the permanent database. 1.481 + */ 1.482 +static CERTCertificate* 1.483 +install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname) 1.484 +{ 1.485 + CERTCertificate * newcert; 1.486 + PK11SlotInfo * newSlot; 1.487 + 1.488 + 1.489 + newSlot = PK11_ImportDERCertForKey(derCert, nickname, &pwdata); 1.490 + if ( newSlot == NULL ) { 1.491 + PR_fprintf(errorFD, "Unable to install certificate\n"); 1.492 + errorCount++; 1.493 + exit(ERRX); 1.494 + } 1.495 + 1.496 + newcert = PK11_FindCertFromDERCertItem(newSlot, derCert, &pwdata); 1.497 + PK11_FreeSlot(newSlot); 1.498 + if (newcert == NULL) { 1.499 + PR_fprintf(errorFD, "%s: can't find new certificate\n", 1.500 + PROGRAM_NAME); 1.501 + errorCount++; 1.502 + exit (ERRX); 1.503 + } 1.504 + 1.505 + if (verbosity >= 0) { 1.506 + PR_fprintf(outputFD, "certificate \"%s\" added to database\n", 1.507 + nickname); 1.508 + } 1.509 + 1.510 + return newcert; 1.511 +} 1.512 + 1.513 + 1.514 +/****************************************************************** 1.515 + * 1.516 + * G e n e r a t e K e y P a i r 1.517 + */ 1.518 +static SECStatus 1.519 +GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk, 1.520 +SECKEYPrivateKey **privk, int keysize) 1.521 +{ 1.522 + 1.523 + PK11RSAGenParams rsaParams; 1.524 + 1.525 + if ( keysize == -1 ) { 1.526 + rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE; 1.527 + } else { 1.528 + rsaParams.keySizeInBits = keysize; 1.529 + } 1.530 + rsaParams.pe = 0x10001; 1.531 + 1.532 + if (PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, &pwdata) 1.533 + != SECSuccess) { 1.534 + SECU_PrintError(progName, "failure authenticating to key database.\n"); 1.535 + exit(ERRX); 1.536 + } 1.537 + 1.538 + *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, 1.539 + 1.540 + pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, &pwdata); 1.541 + 1.542 + if (*privk != NULL && *pubk != NULL) { 1.543 + if (verbosity >= 0) { 1.544 + PR_fprintf(outputFD, "generated public/private key pair\n"); 1.545 + } 1.546 + } else { 1.547 + SECU_PrintError(progName, "failure generating key pair\n"); 1.548 + exit (ERRX); 1.549 + } 1.550 + 1.551 + return SECSuccess; 1.552 +} 1.553 + 1.554 + 1.555 + 1.556 +/****************************************************************** 1.557 + * 1.558 + * m a k e _ c e r t _ r e q u e s t 1.559 + */ 1.560 +static CERTCertificateRequest* 1.561 +make_cert_request(char *subject, SECKEYPublicKey *pubk) 1.562 +{ 1.563 + CERTName * subj; 1.564 + CERTSubjectPublicKeyInfo * spki; 1.565 + 1.566 + CERTCertificateRequest * req; 1.567 + 1.568 + /* Create info about public key */ 1.569 + spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); 1.570 + if (!spki) { 1.571 + SECU_PrintError(progName, "unable to create subject public key"); 1.572 + exit (ERRX); 1.573 + } 1.574 + 1.575 + subj = CERT_AsciiToName (subject); 1.576 + if (subj == NULL) { 1.577 + FatalError("Invalid data in certificate description"); 1.578 + } 1.579 + 1.580 + /* Generate certificate request */ 1.581 + req = CERT_CreateCertificateRequest(subj, spki, 0); 1.582 + if (!req) { 1.583 + SECU_PrintError(progName, "unable to make certificate request"); 1.584 + exit (ERRX); 1.585 + } 1.586 + 1.587 + SECKEY_DestroySubjectPublicKeyInfo(spki); 1.588 + CERT_DestroyName(subj); 1.589 + 1.590 + if (verbosity >= 0) { 1.591 + PR_fprintf(outputFD, "certificate request generated\n"); 1.592 + } 1.593 + 1.594 + return req; 1.595 +} 1.596 + 1.597 + 1.598 +/****************************************************************** 1.599 + * 1.600 + * m a k e _ c e r t 1.601 + */ 1.602 +static CERTCertificate * 1.603 +make_cert(CERTCertificateRequest *req, unsigned long serial, 1.604 +CERTName *ca_subject) 1.605 +{ 1.606 + CERTCertificate * cert; 1.607 + 1.608 + CERTValidity * validity = NULL; 1.609 + 1.610 + PRTime now, after; 1.611 + PRExplodedTime printableTime; 1.612 + 1.613 + now = PR_Now(); 1.614 + PR_ExplodeTime (now, PR_GMTParameters, &printableTime); 1.615 + 1.616 + printableTime.tm_month += 3; 1.617 + after = PR_ImplodeTime (&printableTime); 1.618 + 1.619 + validity = CERT_CreateValidity (now, after); 1.620 + 1.621 + if (validity == NULL) { 1.622 + PR_fprintf(errorFD, "%s: error creating certificate validity\n", 1.623 + PROGRAM_NAME); 1.624 + errorCount++; 1.625 + exit (ERRX); 1.626 + } 1.627 + 1.628 + cert = CERT_CreateCertificate 1.629 + (serial, ca_subject, validity, req); 1.630 + 1.631 + if (cert == NULL) { 1.632 + /* should probably be more precise here */ 1.633 + PR_fprintf(errorFD, "%s: error while generating certificate\n", 1.634 + PROGRAM_NAME); 1.635 + errorCount++; 1.636 + exit (ERRX); 1.637 + } 1.638 + 1.639 + return cert; 1.640 +} 1.641 + 1.642 + 1.643 +/************************************************************************* 1.644 + * 1.645 + * o u t p u t _ c a _ c e r t 1.646 + */ 1.647 +static void 1.648 +output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db) 1.649 +{ 1.650 + FILE * out; 1.651 + 1.652 + SECItem * encodedCertChain; 1.653 + SEC_PKCS7ContentInfo * certChain; 1.654 + char *filename; 1.655 + 1.656 + /* the raw */ 1.657 + 1.658 + filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8); 1.659 + if (!filename) 1.660 + out_of_memory(); 1.661 + 1.662 + sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME); 1.663 + if ((out = fopen (filename, "wb")) == NULL) { 1.664 + PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, 1.665 + filename); 1.666 + errorCount++; 1.667 + exit(ERRX); 1.668 + } 1.669 + 1.670 + certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db); 1.671 + encodedCertChain 1.672 + = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL); 1.673 + SEC_PKCS7DestroyContentInfo (certChain); 1.674 + 1.675 + if (encodedCertChain) { 1.676 + fprintf(out, "Content-type: application/x-x509-ca-cert\n\n"); 1.677 + fwrite (encodedCertChain->data, 1, encodedCertChain->len, 1.678 + out); 1.679 + SECITEM_FreeItem(encodedCertChain, PR_TRUE); 1.680 + } else { 1.681 + PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n", 1.682 + PROGRAM_NAME); 1.683 + errorCount++; 1.684 + exit(ERRX); 1.685 + } 1.686 + 1.687 + fclose (out); 1.688 + 1.689 + /* and the cooked */ 1.690 + 1.691 + sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME); 1.692 + if ((out = fopen (filename, "wb")) == NULL) { 1.693 + PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, 1.694 + filename); 1.695 + errorCount++; 1.696 + return; 1.697 + } 1.698 + 1.699 + fprintf (out, "%s\n%s\n%s\n", 1.700 + NS_CERT_HEADER, 1.701 + BTOA_DataToAscii (cert->derCert.data, cert->derCert.len), 1.702 + NS_CERT_TRAILER); 1.703 + 1.704 + fclose (out); 1.705 + 1.706 + if (verbosity >= 0) { 1.707 + PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n", 1.708 + DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME); 1.709 + } 1.710 +} 1.711 + 1.712 +