summaryrefslogtreecommitdiff
path: root/security/nss/cmd/signtool/certgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/cmd/signtool/certgen.c')
-rw-r--r--security/nss/cmd/signtool/certgen.c713
1 files changed, 0 insertions, 713 deletions
diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c
deleted file mode 100644
index 4687a7841..000000000
--- a/security/nss/cmd/signtool/certgen.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-#include "signtool.h"
-
-#include "secoid.h"
-#include "cryptohi.h"
-#include "certdb.h"
-
-static char* GetSubjectFromUser(unsigned long serial);
-static CERTCertificate* GenerateSelfSignedObjectSigningCert(char *nickname,
- CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
- char *token);
-static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
- CERTCertificate *cert, char *trusts);
-static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
-static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
-static CERTCertificate* install_cert(CERTCertDBHandle *db, SECItem *derCert,
- char *nickname);
-static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
- SECKEYPrivateKey **privk, int keysize);
-static CERTCertificateRequest* make_cert_request(char *subject,
- SECKEYPublicKey *pubk);
-static CERTCertificate * make_cert(CERTCertificateRequest *req,
- unsigned long serial, CERTName *ca_subject);
-static void output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db);
-
-
-/***********************************************************************
- *
- * G e n e r a t e C e r t
- *
- * Runs the whole process of creating a new cert, getting info from the
- * user, etc.
- */
-int
-GenerateCert(char *nickname, int keysize, char *token)
-{
- CERTCertDBHandle *db;
- CERTCertificate *cert;
- char *subject;
- unsigned long serial;
- char stdinbuf[160];
-
- /* Print warning about having the browser open */
- PR_fprintf(PR_STDOUT /*always go to console*/,
-"\nWARNING: Performing this operation while the browser is running could cause"
-"\ncorruption of your security databases. If the browser is currently running,"
-"\nyou should exit the browser before continuing this operation. Enter "
-"\n\"y\" to continue, or anything else to abort: ");
- pr_fgets(stdinbuf, 160, PR_STDIN);
- PR_fprintf(PR_STDOUT, "\n");
- if(tolower(stdinbuf[0]) != 'y') {
- PR_fprintf(errorFD, "Operation aborted at user's request.\n");
- errorCount++;
- return -1;
- }
-
- db = CERT_GetDefaultCertDB();
- if(!db) {
- FatalError("Unable to open certificate database");
- }
-
- if(PK11_FindCertFromNickname(nickname, NULL)) {
- PR_fprintf(errorFD,
-"ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
-"must choose a different nickname.\n", nickname);
- errorCount++;
- exit(ERRX);
- }
-
- LL_L2UI(serial, PR_Now());
-
- subject = GetSubjectFromUser(serial);
-
- cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
- serial, keysize, token);
-
- if(cert) {
- output_ca_cert(cert, db);
- CERT_DestroyCertificate(cert);
- }
-
- PORT_Free(subject);
- return 0;
-}
-
-#undef VERBOSE_PROMPTS
-
-/*********************************************************************8
- * G e t S u b j e c t F r o m U s e r
- *
- * Construct the subject information line for a certificate by querying
- * the user on stdin.
- */
-static char*
-GetSubjectFromUser(unsigned long serial)
-{
- char buf[STDIN_BUF_SIZE];
- char common_name_buf[STDIN_BUF_SIZE];
- char *common_name, *state, *orgunit, *country, *org, *locality;
- char *email, *uid;
- char *subject;
- char *cp;
- int subjectlen=0;
-
- common_name = state = orgunit = country = org = locality = email =
- uid = subject = NULL;
-
- /* Get subject information */
- PR_fprintf(PR_STDOUT,
-"\nEnter certificate information. All fields are optional. Acceptable\n"
-"characters are numbers, letters, spaces, and apostrophes.\n");
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
-"Enter the full name you want to give your certificate. (Example: Test-Only\n"
-"Object Signing Certificate)\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "certificate common name: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp == '\0') {
- sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME, serial);
- cp = common_name_buf;
- }
- common_name = PORT_ZAlloc(strlen(cp) + 6);
- if(!common_name) {out_of_memory();}
- sprintf(common_name, "CN=%s, ", cp);
- subjectlen += strlen(common_name);
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
-"Enter the name of your organization. For example, this could be the name\n"
-"of your company.\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "organization: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp != '\0') {
- org = PORT_ZAlloc(strlen(cp) + 5);
- if(!org) {out_of_memory();}
- sprintf(org, "O=%s, ", cp);
- subjectlen += strlen(org);
- }
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
-"Enter the name of your organization unit. For example, this could be the\n"
-"name of your department.\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "organization unit: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp != '\0') {
- orgunit = PORT_ZAlloc(strlen(cp)+6);
- if(!orgunit) {out_of_memory();}
- sprintf(orgunit, "OU=%s, ", cp);
- subjectlen += strlen(orgunit);
- }
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nSTATE\n"
-"Enter the name of your state or province.\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "state or province: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp != '\0') {
- state = PORT_ZAlloc(strlen(cp)+6);
- if(!state) {out_of_memory();}
- sprintf(state, "ST=%s, ", cp);
- subjectlen += strlen(state);
- }
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
-"Enter the 2-character abbreviation for the name of your country.\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(cp);
- if(strlen(cp) != 2) {
- *cp = '\0'; /* country code must be 2 chars */
- }
- if(*cp != '\0') {
- country = PORT_ZAlloc(strlen(cp)+5);
- if(!country) {out_of_memory();}
- sprintf(country, "C=%s, ", cp);
- subjectlen += strlen(country);
- }
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
-"Enter your system username or UID\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "username: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp != '\0') {
- uid = PORT_ZAlloc(strlen(cp)+7);
- if(!uid) {out_of_memory();}
- sprintf(uid, "UID=%s, ", cp);
- subjectlen += strlen(uid);
- }
-
-#ifdef VERBOSE_PROMPTS
- PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
-"Enter your email address.\n"
-"-->");
-#else
- PR_fprintf(PR_STDOUT, "email address: ");
-#endif
- fgets(buf, STDIN_BUF_SIZE, stdin);
- cp = chop(buf);
- if(*cp != '\0') {
- email = PORT_ZAlloc(strlen(cp)+5);
- if(!email) {out_of_memory();}
- sprintf(email, "E=%s,", cp);
- subjectlen += strlen(email);
- }
-
- subjectlen++;
-
- subject = PORT_ZAlloc(subjectlen);
- if(!subject) {out_of_memory();}
-
- sprintf(subject, "%s%s%s%s%s%s%s",
- common_name ? common_name : "",
- org ? org : "",
- orgunit ? orgunit : "",
- state ? state : "",
- country ? country : "",
- uid ? uid : "",
- email ? email : ""
- );
- if( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) {
- subject[strlen(subject)-2] = '\0';
- }
-
- PORT_Free(common_name);
- PORT_Free(org);
- PORT_Free(orgunit);
- PORT_Free(state);
- PORT_Free(country);
- PORT_Free(uid);
- PORT_Free(email);
-
- return subject;
-}
-
-/**************************************************************************
- *
- * 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
- * *phew*^
- *
- */
-static CERTCertificate*
-GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
- char *subject, unsigned long serial, int keysize, char *token)
-{
- CERTCertificate *cert, *temp_cert;
- SECItem *derCert;
- CERTCertificateRequest *req;
-
- PK11SlotInfo *slot = NULL;
- SECKEYPrivateKey *privk = NULL;
- SECKEYPublicKey *pubk = NULL;
-
- if( token ) {
- slot = PK11_FindSlotByName(token);
- } else {
- slot = PK11_GetInternalKeySlot();
- }
-
- if (slot == NULL) {
- PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
- token ? token : "");
- errorCount++;
- exit (ERRX);
- }
-
- if( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
- FatalError("Error generating keypair.");
- }
- req = make_cert_request (subject, pubk);
- temp_cert = make_cert (req, serial, &req->subject);
- if(set_cert_type(temp_cert,
- NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
- != SECSuccess) {
- FatalError("Unable to set cert type");
- }
-
- derCert = sign_cert (temp_cert, privk);
- cert = install_cert(db, derCert, nickname);
- if(ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
- FatalError("Unable to change trust on generated certificate");
- }
-
- /* !!! Free memory ? !!! */
- PK11_FreeSlot(slot);
- SECKEY_DestroyPrivateKey(privk);
- SECKEY_DestroyPublicKey(pubk);
-
- return cert;
-}
-
-/**************************************************************************
- *
- * C h a n g e T r u s t A t t r i b u t e s
- */
-static SECStatus
-ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
-{
-
- CERTCertTrust *trust;
-
- if(!db || !cert || !trusts) {
- PR_fprintf(errorFD,"ChangeTrustAttributes got incomplete arguments.\n");
- errorCount++;
- return SECFailure;
- }
-
- trust = (CERTCertTrust*) PORT_ZAlloc(sizeof(CERTCertTrust));
- if(!trust) {
- PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
- "CERTCertTrust\n");
- errorCount++;
- return SECFailure;
- }
-
- if( CERT_DecodeTrustString(trust, trusts) ) {
- return SECFailure;
- }
-
- if( CERT_ChangeCertTrust(db, cert, trust) ) {
- PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
- cert->nickname ? cert->nickname : "");
- errorCount++;
- return SECFailure;
- }
-
- return SECSuccess;
-}
-
-/*************************************************************************
- *
- * s e t _ c e r t _ t y p e
- */
-static SECStatus
-set_cert_type(CERTCertificate *cert, unsigned int type)
-{
- void *context;
- SECStatus status = SECSuccess;
- SECItem certType;
- char ctype;
-
- context = CERT_StartCertExtensions(cert);
-
- certType.type = siBuffer;
- certType.data = (unsigned char*) &ctype;
- certType.len = 1;
- ctype = (unsigned char)type;
- if(CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
- &certType, PR_TRUE /*critical*/) != SECSuccess) {
- status = SECFailure;
- }
-
- if(CERT_FinishExtensions(context) != SECSuccess) {
- status = SECFailure;
- }
-
- return status;
-}
-
-/********************************************************************
- *
- * s i g n _ c e r t
- */
-static SECItem *
-sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
-{
- SECStatus rv;
-
- SECItem der2;
- SECItem *result2;
-
- void *dummy;
- SECOidTag alg = SEC_OID_UNKNOWN;
-
- switch (privk->keyType)
- {
- case rsaKey:
- alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
- break;
-
- case dsaKey:
- alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
- break;
- default:
- FatalError("Unknown key type");
- }
- PORT_Assert(alg != SEC_OID_UNKNOWN);
-
- rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
-
- if (rv != SECSuccess)
- {
- PR_fprintf(errorFD, "%s: unable to set signature alg id\n", PROGRAM_NAME);
- errorCount++;
- exit (ERRX);
- }
-
- der2.len = 0;
- der2.data = NULL;
-
- dummy = SEC_ASN1EncodeItem
- (cert->arena, &der2, cert, CERT_CertificateTemplate);
-
- if (rv != SECSuccess)
- {
- PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
- errorCount++;
- exit (ERRX);
- }
-
- result2 = (SECItem *) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem));
- if (result2 == NULL)
- out_of_memory();
-
- rv = SEC_DerSignData
- (cert->arena, result2, der2.data, der2.len, privk, alg);
-
- if (rv != SECSuccess)
- {
- PR_fprintf(errorFD, "can't sign encoded certificate data\n");
- errorCount++;
- exit (ERRX);
- }
- else if(verbosity >= 0) {
- PR_fprintf(outputFD, "certificate has been signed\n");
- }
-
- cert->derCert = *result2;
-
- return result2;
-}
-
-/*********************************************************************
- *
- * i n s t a l l _ c e r t
- *
- * Installs the cert in the permanent database.
- */
-static CERTCertificate*
-install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
-{
- CERTCertificate *newcert;
- PK11SlotInfo *newSlot;
-
- newcert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL);
-
- if (newcert == NULL) {
- PR_fprintf(errorFD, "%s: can't create new certificate\n", PROGRAM_NAME);
- errorCount++;
- exit (ERRX);
- }
-
- newSlot = PK11_ImportCertForKey(newcert, nickname, NULL /*wincx*/);
- if( newSlot == NULL ) {
- PR_fprintf(errorFD, "Unable to install certificate\n");
- errorCount++;
- exit(ERRX);
- }
- PK11_FreeSlot(newSlot);
-
- if(verbosity >= 0){
- PR_fprintf(outputFD, "certificate \"%s\" added to database\n", nickname);
- }
-
- return newcert;
-}
-
-/******************************************************************
- *
- * G e n e r a t e K e y P a i r
- */
-static SECStatus
-GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
- SECKEYPrivateKey **privk, int keysize)
-{
-
- PK11RSAGenParams rsaParams;
-
- if( keysize == -1 ) {
- rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
- } else {
- rsaParams.keySizeInBits = keysize;
- }
- rsaParams.pe = 0x10001;
-
- if(PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, NULL /*wincx*/)
- != SECSuccess) {
- SECU_PrintError(progName, "failure authenticating to key database.\n");
- exit(ERRX);
- }
-
- *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
- pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, NULL /*wincx*/ );
-
- if (*privk != NULL && *pubk != NULL) {
- if(verbosity >= 0) {
- PR_fprintf(outputFD, "generated public/private key pair\n");
- }
- } else {
- SECU_PrintError(progName, "failure generating key pair\n");
- exit (ERRX);
- }
-
- return SECSuccess;
-}
-
-/******************************************************************
- *
- * m a k e _ c e r t _ r e q u e s t
- */
-static CERTCertificateRequest*
-make_cert_request(char *subject, SECKEYPublicKey *pubk)
-{
- CERTName *subj;
- CERTSubjectPublicKeyInfo *spki;
-
- CERTCertificateRequest *req;
-
- /* Create info about public key */
- spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
- if (!spki) {
- SECU_PrintError(progName, "unable to create subject public key");
- exit (ERRX);
- }
-
- subj = CERT_AsciiToName (subject);
- if(subj == NULL) {
- FatalError("Invalid data in certificate description");
- }
-
- /* Generate certificate request */
- req = CERT_CreateCertificateRequest(subj, spki, 0);
- if (!req) {
- SECU_PrintError(progName, "unable to make certificate request");
- exit (ERRX);
- }
-
- if(verbosity >= 0) {
- PR_fprintf(outputFD, "certificate request generated\n");
- }
-
- return req;
-}
-
-/******************************************************************
- *
- * m a k e _ c e r t
- */
-static CERTCertificate *
-make_cert(CERTCertificateRequest *req, unsigned long serial,
- CERTName *ca_subject)
-{
- CERTCertificate *cert;
-
- CERTValidity *validity = NULL;
-
- PRTime now, after;
- PRExplodedTime printableTime;
-
- now = PR_Now();
- PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
-
- printableTime.tm_month += 3;
- after = PR_ImplodeTime (&printableTime);
-
- validity = CERT_CreateValidity (now, after);
-
- if (validity == NULL)
- {
- PR_fprintf(errorFD, "%s: error creating certificate validity\n", PROGRAM_NAME);
- errorCount++;
- exit (ERRX);
- }
-
- cert = CERT_CreateCertificate
- (serial, ca_subject, validity, req);
-
- if (cert == NULL)
- {
- /* should probably be more precise here */
- PR_fprintf(errorFD, "%s: error while generating certificate\n", PROGRAM_NAME);
- errorCount++;
- exit (ERRX);
- }
-
- return cert;
- }
-
-/*************************************************************************
- *
- * o u t p u t _ c a _ c e r t
- */
-static void
-output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db)
- {
- FILE *out;
-
- SECItem *encodedCertChain;
- SEC_PKCS7ContentInfo *certChain;
- char *filename;
-
- /* the raw */
-
- filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME)+8);
- if(!filename) out_of_memory();
-
- sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
- if ((out = fopen (filename, "wb")) == NULL)
- {
- PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename);
- errorCount++;
- exit(ERRX);
- }
-
- certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db);
- encodedCertChain
- = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL);
- SEC_PKCS7DestroyContentInfo (certChain);
-
- if (encodedCertChain)
- {
- fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
- fwrite (encodedCertChain->data, 1, encodedCertChain->len, out);
- SECITEM_FreeItem(encodedCertChain, PR_TRUE);
- }
- else {
- PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n", PROGRAM_NAME);
- errorCount++;
- exit(ERRX);
- }
-
- fclose (out);
-
- /* and the cooked */
-
- sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
- if ((out = fopen (filename, "wb")) == NULL)
- {
- PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename);
- errorCount++;
- return;
- }
-
- fprintf (out, "%s\n%s\n%s\n",
- NS_CERT_HEADER,
- BTOA_DataToAscii (cert->derCert.data, cert->derCert.len),
- NS_CERT_TRAILER);
-
- fclose (out);
-
- if(verbosity >= 0) {
- PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
- DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
- }
-}