security/nss/cmd/signtool/certgen.c

changeset 0
6474c204b198
     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 +

mercurial