summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorogiorgis <olivier.giorgis@logilab.fr>2023-03-13 11:25:14 +0000
committerogiorgis <olivier.giorgis@logilab.fr>2023-03-13 11:25:14 +0000
commitc82b6088755b47b3e9b1a7e5a5723e4a1f41234d (patch)
treea07da06af659fee013907654619888fb9eb7f4ac
parent273447d07498d300b5b22ddaccd1ba8e93ad0699 (diff)
downloadnss-hg-c82b6088755b47b3e9b1a7e5a5723e4a1f41234d.tar.gz
Bug 1821997 - Fix incorrect pygment style r=nss-reviewers,bbeurdouche
Differential Revision: https://phabricator.services.mozilla.com/D172398
-rw-r--r--doc/rst/legacy/encrypt_decrypt_mac_keys_as_session_objects/index.rst2
-rw-r--r--doc/rst/legacy/encrypt_decrypt_mac_using_token/index.rst2
-rw-r--r--doc/rst/legacy/new_nss_samples/index.rst2
-rw-r--r--doc/rst/legacy/nss_developer_tutorial/index.rst20
-rw-r--r--doc/rst/legacy/nss_sample_code/enc_dec_mac_output_plblic_key_as_csr/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/enc_dec_mac_using_key_wrap_certreq_pkcs10_csr/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/nss_sample_code_sample_1_hashing/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/nss_sample_code_sample_2_initialization_of_nss/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/nss_sample_code_sample_3_basic_encryption_and_maci/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/sample1/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/sample1_-_hashing/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/sample2/index.rst4
-rw-r--r--doc/rst/legacy/nss_sample_code/sample2_-_initialize_nss_database/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/sample3_-_encdecmac_using_token_object/index.rst2
-rw-r--r--doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst4
-rw-r--r--doc/rst/legacy/nss_sources_building_testing/index.rst2
-rw-r--r--doc/rst/legacy/reference/fc_initialize/index.rst11
19 files changed, 30 insertions, 39 deletions
diff --git a/doc/rst/legacy/encrypt_decrypt_mac_keys_as_session_objects/index.rst b/doc/rst/legacy/encrypt_decrypt_mac_keys_as_session_objects/index.rst
index b932fad62..4d6d09bcf 100644
--- a/doc/rst/legacy/encrypt_decrypt_mac_keys_as_session_objects/index.rst
+++ b/doc/rst/legacy/encrypt_decrypt_mac_keys_as_session_objects/index.rst
@@ -12,7 +12,7 @@ Encrypt Decrypt MAC Keys As Session Objects
Generates encryption/mac keys and uses session objects.
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/encrypt_decrypt_mac_using_token/index.rst b/doc/rst/legacy/encrypt_decrypt_mac_using_token/index.rst
index f112fa1eb..e2f399166 100644
--- a/doc/rst/legacy/encrypt_decrypt_mac_using_token/index.rst
+++ b/doc/rst/legacy/encrypt_decrypt_mac_using_token/index.rst
@@ -12,7 +12,7 @@ Encrypt and decrypt MAC using token
Generates encryption/mac keys and uses token for storing.
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/new_nss_samples/index.rst b/doc/rst/legacy/new_nss_samples/index.rst
index 6a34f503e..9a9b0c10a 100644
--- a/doc/rst/legacy/new_nss_samples/index.rst
+++ b/doc/rst/legacy/new_nss_samples/index.rst
@@ -20,7 +20,7 @@ New NSS Samples
How to download the samples:
- .. code:: bz_comment_text
+ .. code:: sh
hg clone https://hg.mozilla.org/projects/nss; cd nss; hg update SAMPLES_BRANCH
diff --git a/doc/rst/legacy/nss_developer_tutorial/index.rst b/doc/rst/legacy/nss_developer_tutorial/index.rst
index 22252997b..a891d968d 100644
--- a/doc/rst/legacy/nss_developer_tutorial/index.rst
+++ b/doc/rst/legacy/nss_developer_tutorial/index.rst
@@ -25,7 +25,7 @@ NSS Developer Tutorial
**Curly braces**: both of the following styles are allowed:
- .. code:: brush:
+ .. code::
if (condition) {
action1();
@@ -35,7 +35,7 @@ NSS Developer Tutorial
Or:
- .. code:: brush:
+ .. code::
if (condition)
{
@@ -52,7 +52,7 @@ NSS Developer Tutorial
When a block of code consists of a single statement, NSS doesn’t require curly braces, so both of
these examples are fine:
- .. code:: brush:
+ .. code::
if (condition) {
action();
@@ -60,7 +60,7 @@ NSS Developer Tutorial
Or:
- .. code:: brush:
+ .. code::
if (condition)
action();
@@ -69,7 +69,7 @@ NSS Developer Tutorial
**Multiple-line comments** should be formatted as follows:
- .. code:: brush:
+ .. code::
/*
* Line1
@@ -78,7 +78,7 @@ NSS Developer Tutorial
or
- .. code:: brush:
+ .. code::
/*
** Line 1
@@ -87,7 +87,7 @@ NSS Developer Tutorial
The following styles are also common, because they conserve vertical space:
- .. code:: brush:
+ .. code::
/* Line1
* Line2
@@ -95,7 +95,7 @@ NSS Developer Tutorial
or
- .. code:: brush:
+ .. code::
/* Line1
** Line2
@@ -103,7 +103,7 @@ NSS Developer Tutorial
or
- .. code:: brush:
+ .. code::
/* Line1
* Line2 */
@@ -129,7 +129,7 @@ NSS Developer Tutorial
A data buffer is usually represented as:
- .. code:: brush:
+ .. code:: c
unsigned char *data;
unsigned int len;
diff --git a/doc/rst/legacy/nss_sample_code/enc_dec_mac_output_plblic_key_as_csr/index.rst b/doc/rst/legacy/nss_sample_code/enc_dec_mac_output_plblic_key_as_csr/index.rst
index 294466a50..dfa740a91 100644
--- a/doc/rst/legacy/nss_sample_code/enc_dec_mac_output_plblic_key_as_csr/index.rst
+++ b/doc/rst/legacy/nss_sample_code/enc_dec_mac_output_plblic_key_as_csr/index.rst
@@ -12,7 +12,7 @@ Enc Dec MAC Output Public Key as CSR
Generates encryption/mac keys and outputs public key as certificate signing request
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/nss_sample_code/enc_dec_mac_using_key_wrap_certreq_pkcs10_csr/index.rst b/doc/rst/legacy/nss_sample_code/enc_dec_mac_using_key_wrap_certreq_pkcs10_csr/index.rst
index ccc7b4bed..793555ce5 100644
--- a/doc/rst/legacy/nss_sample_code/enc_dec_mac_using_key_wrap_certreq_pkcs10_csr/index.rst
+++ b/doc/rst/legacy/nss_sample_code/enc_dec_mac_using_key_wrap_certreq_pkcs10_csr/index.rst
@@ -12,7 +12,7 @@ Enc Dec MAC Using Key Wrap CertReq PKCS10 CSR
Generates encryption/mac keys and outputs public key as pkcs11 certificate signing request
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.rst b/doc/rst/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.rst
index 26b3efb1b..712823698 100644
--- a/doc/rst/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.rst
+++ b/doc/rst/legacy/nss_sample_code/encrypt_decrypt_mac_using_token/index.rst
@@ -12,7 +12,7 @@ Encrypt Decrypt_MAC_Using Token
Generates encryption/mac keys and uses token for storing.
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/nss_sample_code/index.rst b/doc/rst/legacy/nss_sample_code/index.rst
index c5f326740..88f1e7bda 100644
--- a/doc/rst/legacy/nss_sample_code/index.rst
+++ b/doc/rst/legacy/nss_sample_code/index.rst
@@ -24,7 +24,7 @@ NSS Sample Code
You are welcome to download the new samples via:
- .. code:: bz_comment_text
+ .. code:: sh
hg clone https://hg.mozilla.org/projects/nss; cd nss; hg update SAMPLES_BRANCH
diff --git a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_1_hashing/index.rst b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_1_hashing/index.rst
index fa0c820b4..5ea9c8cad 100644
--- a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_1_hashing/index.rst
+++ b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_1_hashing/index.rst
@@ -20,7 +20,7 @@ NSS Sample Code Sample_1_Hashing
.. container::
- .. code:: brush:
+ .. code:: c
/* NSPR Headers */
#include <prprf.h>
diff --git a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_2_initialization_of_nss/index.rst b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_2_initialization_of_nss/index.rst
index 52aa4ecf7..a8ad843b4 100644
--- a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_2_initialization_of_nss/index.rst
+++ b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_2_initialization_of_nss/index.rst
@@ -20,7 +20,7 @@ NSS Sample Code Sample_2_Initialization of NSS
.. container::
- .. code:: brush:
+ .. code:: c
/* NSPR Headers */
#include <prthread.h>
diff --git a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_3_basic_encryption_and_maci/index.rst b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_3_basic_encryption_and_maci/index.rst
index 89247620d..059c6861b 100644
--- a/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_3_basic_encryption_and_maci/index.rst
+++ b/doc/rst/legacy/nss_sample_code/nss_sample_code_sample_3_basic_encryption_and_maci/index.rst
@@ -19,7 +19,7 @@ NSS Sample Code Sample_3_Basic Encryption and MACing
.. container::
- .. code:: brush:
+ .. code:: c
/* NSPR Headers */
#include <prthread.h>
diff --git a/doc/rst/legacy/nss_sample_code/sample1/index.rst b/doc/rst/legacy/nss_sample_code/sample1/index.rst
index 5c2436a88..ee1bb2dcf 100644
--- a/doc/rst/legacy/nss_sample_code/sample1/index.rst
+++ b/doc/rst/legacy/nss_sample_code/sample1/index.rst
@@ -7,7 +7,7 @@ sample1
1. A program to compute the hash of a file and save it to another file.
- .. code:: brush:
+ .. code:: c
/* NSPR Headers */
#include <prprf.h>
diff --git a/doc/rst/legacy/nss_sample_code/sample1_-_hashing/index.rst b/doc/rst/legacy/nss_sample_code/sample1_-_hashing/index.rst
index 4971ae599..3fe6f2fb1 100644
--- a/doc/rst/legacy/nss_sample_code/sample1_-_hashing/index.rst
+++ b/doc/rst/legacy/nss_sample_code/sample1_-_hashing/index.rst
@@ -13,7 +13,7 @@ Hashing - sample 1
The NSS same code below computes the hash of a file and saves it to another file, this
illustrates the use of NSS message APIs.
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/nss_sample_code/sample2/index.rst b/doc/rst/legacy/nss_sample_code/sample2/index.rst
index 6827e88bc..5243b05e4 100644
--- a/doc/rst/legacy/nss_sample_code/sample2/index.rst
+++ b/doc/rst/legacy/nss_sample_code/sample2/index.rst
@@ -7,6 +7,6 @@ sample2
.. container:: summary
- .. code:: brush:
+ .. code:: c
- /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* NSPR Headers */ #include <prthread.h> #include <plgetopt.h> #include <prerror.h> #include <prinit.h> #include <prlog.h> #include <prtypes.h> #include <plstr.h> /* NSS headers */ #include <cryptohi.h> #include <keyhi.h> #include <pk11priv.h> #include <cert.h> #include <base64.h> #include <secerr.h> #include <secport.h> #include <secoid.h> #include <secmodt.h> #include <secoidt.h> #include <sechash.h> /* our samples utilities */ #include "util.h" /* Constants */ #define BLOCKSIZE 32 #define MODBLOCKSIZE 128 #define DEFAULT_KEY_BITS 1024 /* Header file Constants */ #define ENCKEY_HEADER "-----BEGIN WRAPPED ENCKEY-----" #define ENCKEY_TRAILER "-----END WRAPPED ENCKEY-----" #define MACKEY_HEADER "-----BEGIN WRAPPED MACKEY-----" #define MACKEY_TRAILER "-----END WRAPPED MACKEY-----" #define IV_HEADER "-----BEGIN IV-----" #define IV_TRAILER "-----END IV-----" #define MAC_HEADER "-----BEGIN MAC-----" #define MAC_TRAILER "-----END MAC-----" #define PAD_HEADER "-----BEGIN PAD-----" #define PAD_TRAILER "-----END PAD-----" #define LAB_HEADER "-----BEGIN KEY LABEL-----" #define LAB_TRAILER "-----END KEY LABEL-----" #define PUBKEY_HEADER "-----BEGIN PUB KEY -----" #define PUBKEY_TRAILER "-----END PUB KEY -----" #define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----" #define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----" #define NS_CERT_ENC_HEADER "-----BEGIN CERTIFICATE FOR ENCRYPTION-----" #define NS_CERT_ENC_TRAILER "-----END CERTIFICATE FOR ENCRYPTION-----" #define NS_CERT_VFY_HEADER "-----BEGIN CERTIFICATE FOR SIGNATURE VERIFICATION-----" #define NS_CERT_VFY_TRAILER "-----END CERTIFICATE FOR SIGNATURE VERIFICATION-----" #define NS_SIG_HEADER "-----BEGIN SIGNATURE-----" #define NS_SIG_TRAILER "-----END SIGNATURE-----" #define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" #define NS_CERT_TRAILER "-----END CERTIFICATE-----" /* Missing publically from nss versions earlier than 3.13 */ #ifndef SEC_ERROR_BASE #define SEC_ERROR_BASE (-0x2000) typedef enum { SEC_ERROR_IO = SEC_ERROR_BASE + 0, SEC_ERROR_TOKEN_NOT_LOGGED_IN = (SEC_ERROR_BASE + 155), SEC_ERROR_END_OF_LIST } SECErrorCodes; #endif /* PORT_ErrorToString introduced in nss 3.13. On earlier versions of nss that * don't support error tables, PR_ErrorToString will return "Unknown code". */ #ifndef PORT_ErrorToString #define PORT_ErrorToString(err) PR_ErrorToString((err), PR_LANGUAGE_I_DEFAULT) #endif /* sample 6 commands */ typedef enum { GENERATE_CSR, ADD_CERT_TO_DB, SAVE_CERT_TO_HEADER, ENCRYPT, DECRYPT, SIGN, VERIFY, UNKNOWN } CommandType; typedef enum { SYMKEY = 0, MACKEY = 1, IV = 2, MAC = 3, PAD = 4, PUBKEY = 5, LAB = 6, CERTENC= 7, CERTVFY= 8, SIG = 9 } HeaderType; /* * Print usage message and exit */ static void Usage(const char *progName) { fprintf(stderr, "\nUsage: %s %s %s %s %s %s %s %s %s %s\n\n", progName, " -<g|a|h|e|ds|v> -d <dbdirpath> ", "[-p <dbpwd> | -f <dbpwdfile>] [-z <noisefilename>] [-a <\"\">]", "-s <subject> -r <csr> | ", "-n <nickname> -t <trust> -c <cert> [ -r <csr> -u <issuernickname> [-x <\"\">] -m <serialnumber> ] | ", "-n <nickname> -b <headerfilename> | ", "-b <headerfilename> -i <ipfilename> -e <encryptfilename> | ", "-b <headerfilename> -i <ipfilename> | ", "-b <headerfilename> -i <ipfilename> | ", "-b <headerfilename> -e <encryptfilename> -o <opfilename> \n"); fprintf(stderr, "commands:\n\n"); fprintf(stderr, "%s %s\n --for generating cert request (for CA also)\n\n", progName, "-G -s <subject> -r <csr>"); fprintf(stderr, "%s %s\n --to input and store cert (for CA also)\n\n", progName, "-A -n <nickname> -t <trust> -c <cert> [ -r <csr> -u <issuernickname> [-x <\"\">] -m <serialnumber> ]"); fprintf(stderr, "%s %s\n --to put cert in header\n\n", progName, "-H -n <nickname> -b <headerfilename> [-v <\"\">]"); fprintf(stderr, "%s %s\n --to find public key from cert in header and encrypt\n\n", progName, "-E -b <headerfilename> -i <ipfilename> -e <encryptfilename> "); fprintf(stderr, "%s %s\n --decrypt using corresponding private key \n\n", progName, "-D -b <headerfilename> -e <encryptfilename> -o <opfilename>"); fprintf(stderr, "%s %s\n --Sign using private key \n\n", progName, "-S -b <headerfilename> -i <infilename> "); fprintf(stderr, "%s %s\n --Verify using public key \n\n", progName, "-V -b <headerfilename> -i <ipfilename> "); fprintf(stderr, "options:\n\n"); fprintf(stderr, "%-30s - db directory path\n\n", "-d <dbdirpath>"); fprintf(stderr, "%-30s - db password [optional]\n\n", "-p <dbpwd>"); fprintf(stderr, "%-30s - db password file [optional]\n\n", "-f <dbpwdfile>"); fprintf(stderr, "%-30s - noise file name [optional]\n\n", "-z <noisefilename>"); fprintf(stderr, "%-30s - input file name\n\n", "-i <ipfilename>"); fprintf(stderr, "%-30s - header file name\n\n", "-b <headerfilename>"); fprintf(stderr, "%-30s - encrypt file name\n\n", "-e <encryptfilename>"); fprintf(stderr, "%-30s - output file name\n\n", "-o <opfilename>"); fprintf(stderr, "%-30s - certificate serial number\n\n", "-m <serialnumber>"); fprintf(stderr, "%-30s - certificate nickname\n\n", "-n <nickname>"); fprintf(stderr, "%-30s - certificate trust\n\n", "-t <trustargs>"); fprintf(stderr, "%-30s - certificate issuer nickname\n\n", "-u <issuernickname>"); fprintf(stderr, "%-30s - certificate signing request \n\n", "-r <csr>"); fprintf(stderr, "%-30s - generate a self-signed cert [optional]\n\n", "-x"); fprintf(stderr, "%-30s - to enable ascii [optional]\n\n", "-a"); fprintf(stderr, "%-30s - to save certificate to header file as sig verification [optional]\n\n", "-v"); exit(-1); } /* * Validate the options used for Generate CSR command */ static void ValidateGenerateCSRCommand(const char *progName, const char *dbdir, CERTName *subject, const char *subjectStr, const char *certReqFileName) { PRBool validationFailed = PR_FALSE; if (!subject) { PR_fprintf(PR_STDERR, "%s -G -d %s -s: improperly formatted name: \"%s\"\n", progName, dbdir, subjectStr); validationFailed = PR_TRUE; } if (!certReqFileName) { PR_fprintf(PR_STDERR, "%s -G -d %s -s %s -r: certificate request file name not found\n", progName, dbdir, subjectStr); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-G -d <dbdirpath> -s <subject> -r <csr> \n"); exit(-1); } } /* * Validate the options used for Add Cert to DB command */ static void ValidateAddCertToDBCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *trustStr, const char *certFileName, const char *certReqFileName, const char *issuerNameStr, const char *serialNumberStr, PRBool selfsign) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!trustStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t: trust flag is missing\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!certFileName) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c: certificate file name not found\n", progName, dbdir, nickNameStr, trustStr, serialNumberStr, certReqFileName); validationFailed = PR_TRUE; } if (PR_Access(certFileName, PR_ACCESS_EXISTS) == PR_FAILURE) { if (!certReqFileName) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r: certificate file or certificate request file is not found\n", progName, dbdir, nickNameStr, trustStr, certFileName); validationFailed = PR_TRUE; } if (!selfsign && !issuerNameStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r %s -u : issuer name is missing\n", progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName); validationFailed = PR_TRUE; } if (!serialNumberStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r %s -u %s -m : serial number is missing\n", progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName, issuerNameStr); validationFailed = PR_TRUE; } } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, " -A -d <dbdirpath> -n <nickname> -t <trust> -c <cert> \n"); fprintf(stderr, " OR\n"); fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-A -d <dbdirpath> -n <nickname> -t <trust> -c <cert> -r <csr> -u <issuernickname> -m <serialnumber> [-x <\"\">] \n"); exit(-1); } } /* * Validate the options used for Save Cert To Header command */ static void ValidateSaveCertToHeaderCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -S -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -S -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-S -d <dbdirpath> -n <nickname> -b <headerfilename> [-v <\"\">]\n"); exit(-1); } } /* * Validate the options used for Encrypt command */ static void ValidateEncryptCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName, const char *inFileName, const char *encryptedFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -E -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b %s -i : input file name is not found\n", progName, dbdir, nickNameStr, headerFileName); validationFailed = PR_TRUE; } if (!encryptedFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b %s -i %s -e : encrypt file name is not found\n", progName, dbdir, nickNameStr, headerFileName, inFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-E -d <dbdirpath> -b <headerfilename> -i <ipfilename> -e <encryptfilename> -n <nickname> \n"); exit(-1); } } /* * Validate the options used for Sign command */ static void ValidateSignCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName, const char *inFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -I -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -n %s -b %s -i : input file name is not found\n", progName, dbdir, nickNameStr, headerFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-I -d <dbdirpath> -b <headerfilename> -i <ipfilename> -n <nickname> \n"); exit(-1); } } /* * Validate the options used for verify command */ static void ValidateVerifyCommand(const char *progName, const char *dbdir, const char *headerFileName, const char *inFileName) { PRBool validationFailed = PR_FALSE; if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -V -d %s -b : header file name is not found\n", progName, dbdir); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -b %s -i : input file name is not found\n", progName, dbdir, headerFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-I -d <dbdirpath> -b <headerfilename> -i <ipfilename> \n"); exit(-1); } } /* * Validate the options used for Decrypt command */ static void ValidateDecryptCommand(const char *progName, const char *dbdir, const char *headerFileName, const char *encryptedFileName, const char *outFileName) { PRBool validationFailed = PR_FALSE; if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b : header file name is not found\n", progName, dbdir); validationFailed = PR_TRUE; } if (!encryptedFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b %s -e : encrypt file name is not found\n", progName, dbdir, headerFileName); validationFailed = PR_TRUE; } if (!outFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b %s -e %s -o : output file name is not found\n", progName, dbdir, headerFileName, encryptedFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-D -d <dbdirpath> -b <headerfilename> -e <encryptfilename> -o <opfilename>\n"); exit(-1); } } /* * Sign the contents of input file using private key and * return result as SECItem */ SECStatus SignData(const char *inFileName, SECKEYPrivateKey *pk, SECItem *res) { SECStatus rv = SECFailure; unsigned int nb; unsigned char ibuf[4096]; PRFileDesc *inFile = NULL; SGNContext *sgn = NULL; /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Sign using private key */ sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, pk); if (!sgn) { PR_fprintf(PR_STDERR, "unable to create context for signing\n"); rv = SECFailure; goto cleanup; } rv = SGN_Begin(sgn); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_Begin\n"); goto cleanup; } while ((nb = PR_Read(inFile, ibuf, sizeof(ibuf))) > 0) { rv = SGN_Update(sgn, ibuf, nb); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_Update\n"); goto cleanup; } } rv = SGN_End(sgn, res); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_End\n"); goto cleanup; } cleanup: if (inFile) { PR_Close(inFile); } if (sgn) { SGN_DestroyContext(sgn, PR_TRUE); } return rv; } /* * Verify the signature using public key */ SECStatus VerifyData(const char *inFileName, SECKEYPublicKey *pk, SECItem *sigItem, secuPWData *pwdata) { unsigned int nb; unsigned char ibuf[4096]; SECStatus rv = SECFailure; VFYContext *vfy = NULL; PRFileDesc *inFile = NULL; /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } vfy = VFY_CreateContext(pk, sigItem, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, pwdata); if (!vfy) { PR_fprintf(PR_STDERR, "unable to create context for verifying signature\n"); rv = SECFailure; goto cleanup; } rv = VFY_Begin(vfy); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_Begin\n"); goto cleanup; } while ((nb = PR_Read(inFile, ibuf, sizeof(ibuf))) > 0) { rv = VFY_Update(vfy, ibuf, nb); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_Update\n"); goto cleanup; } } rv = VFY_End(vfy); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_End\n"); goto cleanup; } cleanup: if (inFile) { PR_Close(inFile); } if (vfy) { VFY_DestroyContext(vfy, PR_TRUE); } return rv; } /* * Write Cryptographic parameters to header file */ SECStatus WriteToHeaderFile(const char *buf, unsigned int len, HeaderType type, PRFileDesc *outFile) { SECStatus rv; const char *header; const char *trailer; switch (type) { case SYMKEY: header = ENCKEY_HEADER; trailer = ENCKEY_TRAILER; break; case MACKEY: header = MACKEY_HEADER; trailer = MACKEY_TRAILER; break; case IV: header = IV_HEADER; trailer = IV_TRAILER; break; case MAC: header = MAC_HEADER; trailer = MAC_TRAILER; break; case PAD: header = PAD_HEADER; trailer = PAD_TRAILER; break; case PUBKEY: header = PUBKEY_HEADER; trailer = PUBKEY_TRAILER; break; case CERTENC: header = NS_CERT_ENC_HEADER; trailer = NS_CERT_ENC_TRAILER; break; case CERTVFY: header = NS_CERT_VFY_HEADER; trailer = NS_CERT_VFY_TRAILER; break; case SIG: header = NS_SIG_HEADER; trailer = NS_SIG_TRAILER; break; case LAB: header = LAB_HEADER; trailer = LAB_TRAILER; PR_fprintf(outFile, "%s\n", header); PR_fprintf(outFile, "%s\n", buf); PR_fprintf(outFile, "%s\n\n", trailer); return SECSuccess; break; default: return SECFailure; } PR_fprintf(outFile, "%s\n", header); PrintAsHex(outFile, buf, len); PR_fprintf(outFile, "%s\n\n", trailer); return SECSuccess; } /* * Read cryptographic parameters from the header file */ SECStatus ReadFromHeaderFile(const char *fileName, HeaderType type, SECItem *item, PRBool isHexData) { SECStatus rv = SECSuccess; PRFileDesc* file = NULL; SECItem filedata; SECItem outbuf; unsigned char *nonbody; unsigned char *body; char *header; char *trailer; outbuf.type = siBuffer; file = PR_Open(fileName, PR_RDONLY, 0); if (!file) { PR_fprintf(PR_STDERR, "Failed to open %s\n", fileName); rv = SECFailure; goto cleanup; } switch (type) { case PUBKEY: header = PUBKEY_HEADER; trailer = PUBKEY_TRAILER; break; case SYMKEY: header = ENCKEY_HEADER; trailer = ENCKEY_TRAILER; break; case MACKEY: header = MACKEY_HEADER; trailer = MACKEY_TRAILER; break; case IV: header = IV_HEADER; trailer = IV_TRAILER; break; case MAC: header = MAC_HEADER; trailer = MAC_TRAILER; break; case PAD: header = PAD_HEADER; trailer = PAD_TRAILER; break; case LAB: header = LAB_HEADER; trailer = LAB_TRAILER; break; case CERTENC: header = NS_CERT_ENC_HEADER; trailer = NS_CERT_ENC_TRAILER; break; case CERTVFY: header = NS_CERT_VFY_HEADER; trailer = NS_CERT_VFY_TRAILER; break; case SIG: header = NS_SIG_HEADER; trailer = NS_SIG_TRAILER; break; default: rv = SECFailure; goto cleanup; } rv = FileToItem(&filedata, file); nonbody = (char *)filedata.data; if (!nonbody) { PR_fprintf(PR_STDERR, "unable to read data from input file\n"); rv = SECFailure; goto cleanup; } /* check for headers and trailers and remove them */ if ((body = strstr(nonbody, header)) != NULL) { char *trail = NULL; nonbody = body; body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(nonbody, '\r'); /* maybe this is a MAC file */ if (body) trail = strstr(++body, trailer); if (trail != NULL) { *trail = '\0'; } else { PR_fprintf(PR_STDERR, "input has header but no trailer\n"); PORT_Free(filedata.data); rv = SECFailure; goto cleanup; } } else { /* headers didn't exist */ char *trail = NULL; body = nonbody; if (body) { trail = strstr(++body, trailer); if (trail != NULL) { PR_fprintf(PR_STDERR, "input has no header but has trailer\n"); PORT_Free(filedata.data); rv = SECFailure; goto cleanup; } } } HexToBuf(body, item, isHexData); cleanup: if (file) { PR_Close(file); } return rv; } /* * Generate the private key */ SECKEYPrivateKey * GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, int publicExponent, const char *noise, SECKEYPublicKey **pubkeyp, const char *pqgFile, secuPWData *pwdata) { CK_MECHANISM_TYPE mechanism; SECOidTag algtag; PK11RSAGenParams rsaparams; void *params; SECKEYPrivateKey *privKey = NULL; SECStatus rv; unsigned char randbuf[BLOCKSIZE + 1]; rv = GenerateRandom(randbuf, BLOCKSIZE); if (rv != SECSuccess) { fprintf(stderr, "Error while generating the random numbers : %s\n", PORT_ErrorToString(rv)); goto cleanup; } PK11_RandomUpdate(randbuf, BLOCKSIZE); switch (keytype) { case rsaKey: rsaparams.keySizeInBits = size; rsaparams.pe = publicExponent; mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; params = &rsaparams; break; default: goto cleanup; } fprintf(stderr, "\n\n"); fprintf(stderr, "Generating key. This may take a few moments...\n\n"); privKey = PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, pwdata); cleanup: return privKey; } /* * Get the certificate request from CSR */ static CERTCertificateRequest * GetCertRequest(char *inFileName, PRBool ascii) { CERTSignedData signedData; SECItem reqDER; CERTCertificateRequest *certReq = NULL; SECStatus rv = SECSuccess; PRArenaPool *arena = NULL; reqDER.data = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { rv = SECFailure; goto cleanup; } rv = ReadDERFromFile(&reqDER, inFileName, ascii); if (rv) { rv = SECFailure; goto cleanup; } certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc (arena, sizeof(CERTCertificateRequest)); if (!certReq) { rv = SECFailure; goto cleanup; } certReq->arena = arena; /* Since cert request is a signed data, must decode to get the inner data */ PORT_Memset(&signedData, 0, sizeof(signedData)); rv = SEC_ASN1DecodeItem(arena, &signedData, SEC_ASN1_GET(CERT_SignedDataTemplate), &reqDER); if (rv) { rv = SECFailure; goto cleanup; } rv = SEC_ASN1DecodeItem(arena, certReq, SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data); if (rv) { rv = SECFailure; goto cleanup; } rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, &certReq->subjectPublicKeyInfo, NULL /* wincx */); if (reqDER.data) { SECITEM_FreeItem(&reqDER, PR_FALSE); } cleanup: if (rv) { PR_fprintf(PR_STDERR, "bad certificate request\n"); if (arena) { PORT_FreeArena(arena, PR_FALSE); } certReq = NULL; } return certReq; } /* * Sign Cert */ static SECItem * SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, SECOidTag hashAlgTag, SECKEYPrivateKey *privKey, char *issuerNickName, void *pwarg) { SECItem der; SECStatus rv; SECOidTag algID; void *dummy; PRArenaPool *arena = NULL; SECItem *result = NULL; SECKEYPrivateKey *caPrivateKey = NULL; if (!selfsign) { CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg); if ((CERTCertificate *)NULL == issuer) { PR_fprintf(PR_STDERR, "unable to find issuer with nickname %s\n", issuerNickName); goto cleanup; } privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); CERT_DestroyCertificate(issuer); if (caPrivateKey == NULL) { PR_fprintf(PR_STDERR, "unable to retrieve key %s\n", issuerNickName); goto cleanup; } } arena = cert->arena; algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag); if (algID == SEC_OID_UNKNOWN) { PR_fprintf(PR_STDERR, "Unknown key or hash type for issuer.\n"); goto cleanup; } rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not set signature algorithm id.\n%s\n", PORT_ErrorToString(rv)); goto cleanup; } /* we only deal with cert v3 here */ *(cert->version.data) = 2; cert->version.len = 1; der.len = 0; der.data = NULL; dummy = SEC_ASN1EncodeItem (arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); if (!dummy) { PR_fprintf(PR_STDERR, "Could not encode certificate.\n"); goto cleanup; } result = (SECItem *) PORT_ArenaZAlloc (arena, sizeof (SECItem)); if (result == NULL) { PR_fprintf(PR_STDERR, "Could not allocate item for certificate data.\n"); goto cleanup; } rv = SEC_DerSignData(arena, result, der.data, der.len, privKey, algID); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not sign encoded certificate data : %s\n", PORT_ErrorToString(rv)); /* result allocated out of the arena, it will be freed * when the arena is freed */ result = NULL; goto cleanup; } cert->derCert = *result; cleanup: if (caPrivateKey) { SECKEY_DestroyPrivateKey(caPrivateKey); } return result; } /* * MakeV1Cert */ static CERTCertificate * MakeV1Cert(CERTCertDBHandle *handle, CERTCertificateRequest *req, char * issuerNickName, PRBool selfsign, unsigned int serialNumber, int warpmonths, int validityMonths) { PRExplodedTime printableTime; PRTime now; PRTime after; CERTValidity *validity = NULL; CERTCertificate *issuerCert = NULL; CERTCertificate *cert = NULL; if ( !selfsign ) { issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName); if (!issuerCert) { PR_fprintf(PR_STDERR, "could not find certificate named %s\n", issuerNickName); goto cleanup; } } now = PR_Now(); PR_ExplodeTime (now, PR_GMTParameters, &printableTime); if ( warpmonths ) { printableTime.tm_month += warpmonths; now = PR_ImplodeTime (&printableTime); PR_ExplodeTime (now, PR_GMTParameters, &printableTime); } printableTime.tm_month += validityMonths; after = PR_ImplodeTime (&printableTime); /* note that the time is now in micro-second unit */ validity = CERT_CreateValidity (now, after); if (validity) { cert = CERT_CreateCertificate(serialNumber, (selfsign ? &req->subject : &issuerCert->subject), validity, req); CERT_DestroyValidity(validity); } cleanup: if ( issuerCert ) { CERT_DestroyCertificate (issuerCert); } return cert; } /* * Add a certificate to the nss database */ SECStatus AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, const char *name, char *trusts, char *inFileName, PRBool ascii, PRBool emailcert, void *pwdata) { SECItem certDER; SECStatus rv; CERTCertTrust *trust = NULL; CERTCertificate *cert = NULL; certDER.data = NULL; /* Read in the entire file specified with the -i argument */ rv = ReadDERFromFile(&certDER, inFileName, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "unable to read input file %s : %s\n", inFileName, PORT_ErrorToString(rv)); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)certDER.data, certDER.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Create a cert trust */ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); if (!trust) { PR_fprintf(PR_STDERR, "unable to allocate cert trust\n"); rv = SECFailure; goto cleanup; } rv = CERT_DecodeTrustString(trust, trusts); if (rv) { PR_fprintf(PR_STDERR, "unable to decode trust string\n"); rv = SECFailure; goto cleanup; } rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); if (rv != SECSuccess) { /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have * been coded to take a password arg. */ if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not authenticate to token %s : %s\n", PK11_GetTokenName(slot), PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); } if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not add certificate to token or database : %s\n", PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } } rv = CERT_ChangeCertTrust(handle, cert, trust); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not authenticate to token %s : %s\n", PK11_GetTokenName(slot), PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } rv = CERT_ChangeCertTrust(handle, cert, trust); } if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not change trust on certificate : %s\n", PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } } if (emailcert) { CERT_SaveSMimeProfile(cert, NULL, pwdata); } cleanup: if (cert) { CERT_DestroyCertificate (cert); } if (trust) { PORT_Free(trust); } if (certDER.data) { PORT_Free(certDER.data); } return rv; } /* * Create a certificate */ static SECStatus CreateCert( CERTCertDBHandle *handle, PK11SlotInfo *slot, char * issuerNickName, char *inFileName, char *outFileName, SECKEYPrivateKey **selfsignprivkey, void *pwarg, SECOidTag hashAlgTag, unsigned int serialNumber, int warpmonths, int validityMonths, const char *dnsNames, PRBool ascii, PRBool selfsign) { void *extHandle; SECItem reqDER; CERTCertExtension **CRexts; SECStatus rv = SECSuccess; CERTCertificate *subjectCert = NULL; CERTCertificateRequest *certReq = NULL; PRFileDesc *outFile = NULL; SECItem *certDER = NULL; reqDER.data = NULL; outFile = PR_Open(outFileName, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00660); /* Create a cert request object from the input cert request der */ certReq = GetCertRequest(inFileName, ascii); if (certReq == NULL) { rv = SECFailure; goto cleanup; } subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign, serialNumber, warpmonths, validityMonths); if (subjectCert == NULL) { rv = SECFailure; goto cleanup; } extHandle = CERT_StartCertExtensions (subjectCert); if (extHandle == NULL) { rv = SECFailure; goto cleanup; } if (certReq->attributes != NULL && certReq->attributes[0] != NULL && certReq->attributes[0]->attrType.data != NULL && certReq->attributes[0]->attrType.len > 0 && SECOID_FindOIDTag(&certReq->attributes[0]->attrType) == SEC_OID_PKCS9_EXTENSION_REQUEST) { rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", PORT_ErrorToString(rv)); goto cleanup; } rv = CERT_MergeExtensions(extHandle, CRexts); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", PORT_ErrorToString(rv)); goto cleanup; } } CERT_FinishExtensions(extHandle); /* self-signing a cert request, find the private key */ if (*selfsignprivkey == NULL) { *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg); if (!*selfsignprivkey) { PR_fprintf(PR_STDERR, "Failed to locate private key.\n"); rv = SECFailure; goto cleanup; } } certDER = SignCert(handle, subjectCert, selfsign, hashAlgTag, *selfsignprivkey, issuerNickName,pwarg); if (certDER) { if (ascii) { PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CERT_HEADER, BTOA_DataToAscii(certDER->data, certDER->len), NS_CERT_TRAILER); } else { PR_Write(outFile, certDER->data, certDER->len); } } if (rv != SECSuccess) { PRErrorCode perr = PR_GetError(); PR_fprintf(PR_STDERR, "unable to create cert %s\n", perr); } cleanup: if (outFile) { PR_Close(outFile); } if (*selfsignprivkey) { SECKEY_DestroyPrivateKey(*selfsignprivkey); } if (certReq) { CERT_DestroyCertificateRequest(certReq); } if (subjectCert) { CERT_DestroyCertificate(subjectCert); } return rv; } /* * Generate the certificate request with subject */ static SECStatus CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, SECOidTag hashAlgTag, CERTName *subject, PRBool ascii, const char *certReqFileName) { SECOidTag signAlgTag; SECItem result; PRInt32 numBytes; SECStatus rv = SECSuccess; PRArenaPool *arena = NULL; void *extHandle = NULL; PRFileDesc *outFile = NULL; CERTSubjectPublicKeyInfo *spki = NULL; CERTCertificateRequest *cr = NULL; SECItem *encoding = NULL; /* If the certificate request file already exists, delete it */ if (PR_Access(certReqFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(certReqFileName); } /* Open the certificate request file to write */ outFile = PR_Open(certReqFileName, PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); if (!outFile) { PR_fprintf(PR_STDERR, "unable to open \"%s\" for writing (%ld, %ld).\n", certReqFileName, PR_GetError(), PR_GetOSError()); goto cleanup; } /* Create info about public key */ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); if (!spki) { PR_fprintf(PR_STDERR, "unable to create subject public key\n"); rv = SECFailure; goto cleanup; } /* Generate certificate request */ cr = CERT_CreateCertificateRequest(subject, spki, NULL); if (!cr) { PR_fprintf(PR_STDERR, "unable to make certificate request\n"); rv = SECFailure; goto cleanup; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { fprintf(stderr, "out of memory"); rv = SECFailure; goto cleanup; } extHandle = CERT_StartCertificateRequestAttributes(cr); if (extHandle == NULL) { PORT_FreeArena (arena, PR_FALSE); rv = SECFailure; goto cleanup; } CERT_FinishExtensions(extHandle); CERT_FinishCertificateRequestAttributes(cr); /* Der encode the request */ encoding = SEC_ASN1EncodeItem(arena, NULL, cr, SEC_ASN1_GET(CERT_CertificateRequestTemplate)); if (encoding == NULL) { PR_fprintf(PR_STDERR, "der encoding of request failed\n"); rv = SECFailure; goto cleanup; } /* Sign the request */ signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag); if (signAlgTag == SEC_OID_UNKNOWN) { PR_fprintf(PR_STDERR, "unknown Key or Hash type\n"); rv = SECFailure; goto cleanup; } rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len, privk, signAlgTag); if (rv) { PR_fprintf(PR_STDERR, "signing of data failed\n"); rv = SECFailure; goto cleanup; } /* Encode request in specified format */ if (ascii) { char *obuf; char *name, *email, *org, *state, *country; SECItem *it; int total; it = &result; obuf = BTOA_ConvertItemToAscii(it); total = PL_strlen(obuf); name = CERT_GetCommonName(subject); if (!name) { name = strdup("(not specified)"); } email = CERT_GetCertEmailAddress(subject); if (!email) email = strdup("(not specified)"); org = CERT_GetOrgName(subject); if (!org) org = strdup("(not specified)"); state = CERT_GetStateName(subject); if (!state) state = strdup("(not specified)"); country = CERT_GetCountryName(subject); if (!country) country = strdup("(not specified)"); PR_fprintf(outFile, "\nCertificate request generated by Netscape certutil\n"); PR_fprintf(outFile, "Common Name: %s\n", name); PR_fprintf(outFile, "Email: %s\n", email); PR_fprintf(outFile, "Organization: %s\n", org); PR_fprintf(outFile, "State: %s\n", state); PR_fprintf(outFile, "Country: %s\n\n", country); PR_fprintf(outFile, "%s\n", NS_CERTREQ_HEADER); numBytes = PR_Write(outFile, obuf, total); if (numBytes != total) { PR_fprintf(PR_STDERR, "write error\n"); return SECFailure; } PR_fprintf(outFile, "\n%s\n", NS_CERTREQ_TRAILER); } else { numBytes = PR_Write(outFile, result.data, result.len); if (numBytes != (int)result.len) { PR_fprintf(PR_STDERR, "write error\n"); rv = SECFailure; goto cleanup; } } cleanup: if (outFile) { PR_Close(outFile); } if (privk) { SECKEY_DestroyPrivateKey(privk); } if (pubk) { SECKEY_DestroyPublicKey(pubk); } return rv; } /* * Create certificate request with subject */ SECStatus CreateCertRequest(PK11SlotInfo *slot, secuPWData *pwdata, CERTName *subject, char *certReqFileName, PRBool ascii) { SECStatus rv; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; KeyType keytype = rsaKey; int keysize = DEFAULT_KEY_BITS; int publicExponent = 0x010001; SECOidTag hashAlgTag = SEC_OID_UNKNOWN; privkey = GeneratePrivateKey(keytype, slot, keysize, publicExponent, NULL, &pubkey, NULL, pwdata); if (privkey == NULL) { PR_fprintf(PR_STDERR, "unable to generate key(s)\n"); rv = SECFailure; goto cleanup; } privkey->wincx = pwdata; PORT_Assert(pubkey != NULL); rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject, ascii, certReqFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to create Certificate Request\n"); } cleanup: return rv; } /* * Creates the certificate using CSR and adds the certificate to DB */ SECStatus AddCertificateToDB(PK11SlotInfo *slot, secuPWData *pwdata, char *certReqFileName, char *certFileName, char *issuerNameStr, CERTCertDBHandle *certHandle, const char *nickNameStr, char *trustStr, unsigned int serialNumber, PRBool selfsign, PRBool ascii) { SECStatus rv; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; SECOidTag hashAlgTag = SEC_OID_UNKNOWN; if (PR_Access(certFileName, PR_ACCESS_EXISTS) == PR_FAILURE) { rv = CreateCert(certHandle, slot, issuerNameStr, certReqFileName, certFileName, &privkey, &pwdata, hashAlgTag, serialNumber, 0, 3, NULL, ascii, selfsign); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to create Certificate\n"); goto cleanup; } } rv = AddCert(slot, certHandle, nickNameStr, trustStr, certFileName, ascii, 0, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to add Certificate\n"); } cleanup: return rv; } /* * Finds the certificate using nickname and saves it to the header file */ SECStatus AddCertificateToHeader(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, CERTCertDBHandle *certHandle, const char *nickNameStr, PRBool sigVerify) { SECStatus rv = SECSuccess; PRFileDesc *headerFile = NULL; CERTCertificate *cert = NULL; HeaderType hType = CERTENC; /* If the intermediate header file already exists, delete it */ if (PR_Access(headerFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(headerFileName); } headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "unable to open \"%s\" for writing (%ld, %ld).\n", headerFileName, PR_GetError(), PR_GetOSError()); rv = SECFailure; goto cleanup; } cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickNameStr); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } if (sigVerify) { hType = CERTVFY; } WriteToHeaderFile(cert->derCert.data, cert->derCert.len, hType, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the public key from the certificate saved in the header file * and encrypts with it the contents of inFileName to encryptedFileName. */ SECStatus FindKeyAndEncrypt(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, const char *encryptedFileName, const char *inFileName) { SECStatus rv; PRFileDesc *headerFile = NULL; PRFileDesc *encFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; SECItem data; unsigned char ptext[MODBLOCKSIZE]; unsigned char encBuf[MODBLOCKSIZE]; unsigned int ptextLen; int index; unsigned int nWritten; unsigned int pad[1]; SECItem padItem; unsigned int paddingLength = 0; SECKEYPublicKey *pubkey = NULL; /* If the intermediate encrypted file already exists, delete it*/ if (PR_Access(encryptedFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(encryptedFileName); } /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTENC, &data, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)data.data, data.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Extract the public key from certificate */ pubkey = CERT_ExtractPublicKey(cert); if (!pubkey) { PR_fprintf(PR_STDERR, "could not get key from certificate\n"); rv = SECFailure; goto cleanup; } /* Open the encrypted file for writing */ encFile = PR_Open(encryptedFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!encFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", encryptedFileName); rv = SECFailure; goto cleanup; } /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Open the header file to write padding */ headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_APPEND, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Read input file */ while ((ptextLen = PR_Read(inFile, ptext, sizeof(ptext))) > 0) { if (ptextLen != MODBLOCKSIZE) { paddingLength = MODBLOCKSIZE - ptextLen; for ( index=0; index < paddingLength; index++) { ptext[ptextLen+index] = (unsigned char)paddingLength; } ptextLen = MODBLOCKSIZE; } rv = PK11_PubEncryptRaw(pubkey, encBuf, ptext, ptextLen, NULL); nWritten = PR_Write(encFile, encBuf, ptextLen); } /* Write the padding to header file */ pad[0] = paddingLength; padItem.type = siBuffer; padItem.data = (unsigned char *)pad; padItem.len = sizeof(pad[0]); WriteToHeaderFile(padItem.data, padItem.len, PAD, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (encFile) { PR_Close(encFile); } if (inFile) { PR_Close(inFile); } if (pubkey) { SECKEY_DestroyPublicKey(pubkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the private key from db and signs the contents * of inFileName and writes to signatureFileName */ SECStatus FindKeyAndSign(PK11SlotInfo *slot, CERTCertDBHandle* certHandle, secuPWData *pwdata, const char *nickNameStr, const char *headerFileName, const char *inFileName) { SECStatus rv; PRFileDesc *headerFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; unsigned int signatureLen = 0; SECKEYPrivateKey *privkey = NULL; SECItem sigItem; SECOidTag hashOIDTag; /* Open the header file to write padding */ headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_APPEND, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Get the certificate by nick name and write to header file */ cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickNameStr); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate by name - %s\n", nickNameStr); rv = SECFailure; goto cleanup; } WriteToHeaderFile(cert->derCert.data, cert->derCert.len, CERTVFY, headerFile); /* Find private key from certificate */ privkey = PK11_FindKeyByAnyCert(cert, NULL); if (privkey == NULL) { fprintf(stderr, "Couldn't find private key for cert\n"); rv = SECFailure; goto cleanup; } /* Sign the contents of the input file */ rv = SignData(inFileName, privkey, &sigItem); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not sign the contents from file - %s \n", inFileName); goto cleanup; } /* write signature to header file */ WriteToHeaderFile(sigItem.data, sigItem.len, SIG, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (privkey) { SECKEY_DestroyPrivateKey(privkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the public key from certificate and verifies signature */ SECStatus FindKeyAndVerify(PK11SlotInfo *slot, CERTCertDBHandle* certHandle, secuPWData *pwdata, const char *headerFileName, const char *inFileName) { SECStatus rv = SECFailure; PRFileDesc *headerFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; SECKEYPublicKey *pubkey = NULL; SECItem sigItem; SECItem certData; /* Open the input file */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Open the header file to read the certificate and signature */ headerFile = PR_Open(headerFileName, PR_RDONLY, 0); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTVFY, &certData, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)certData.data, certData.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Extract the public key from certificate */ pubkey = CERT_ExtractPublicKey(cert); if (!pubkey) { PR_fprintf(PR_STDERR, "Could not get key from certificate\n"); rv = SECFailure; goto cleanup; } /* Read signature from header file */ rv = ReadFromHeaderFile(headerFileName, SIG, &sigItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read signature from header file\n"); goto cleanup; } /* Verify with the public key */ rv = VerifyData(inFileName, pubkey, &sigItem, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Couldn't verify the signature for file - %s\n", inFileName); goto cleanup; } cleanup: if (headerFile) { PR_Close(headerFile); } if (pubkey) { SECKEY_DestroyPublicKey(pubkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the private key corresponding to the certificate saved in the header file * and decrypts with it the contents of encryptedFileName to outFileName. */ SECStatus FindKeyAndDecrypt(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, const char *encryptedFileName, const char *outFileName) { SECStatus rv; PRFileDesc *encFile = NULL; PRFileDesc *outFile = NULL; SECKEYPrivateKey *pvtkey = NULL; unsigned int inFileLength = 0; unsigned int paddingLength = 0; unsigned int count = 0; unsigned int temp = 0; unsigned char ctext[MODBLOCKSIZE]; unsigned char decBuf[MODBLOCKSIZE]; unsigned int ctextLen; unsigned int decBufLen; SECItem padItem; SECItem data; SECItem signature; CERTCertificate *cert = NULL; /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTENC, &data, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read padding from header file */ rv = ReadFromHeaderFile(headerFileName, PAD, &padItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve PAD detail from header file\n"); goto cleanup; } paddingLength = (unsigned int)padItem.data[0]; inFileLength = FileSize(encryptedFileName); /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)data.data, data.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Find private key from certificate */ pvtkey = PK11_FindKeyByAnyCert(cert, NULL); if (pvtkey == NULL) { fprintf(stderr, "Couldn't find private key for cert\n"); rv = SECFailure; goto cleanup; } /* Open the out file to write */ outFile = PR_Open(outFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!outFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", outFileName); rv = SECFailure; goto cleanup; } /* Open the encrypted file for reading */ encFile = PR_Open(encryptedFileName, PR_RDONLY, 0); if (!encFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", encryptedFileName); rv = SECFailure; goto cleanup; } /* Read the encrypt file, decrypt and write to out file */ while ((ctextLen = PR_Read(encFile, ctext, sizeof(ctext))) > 0) { count += ctextLen; rv = PK11_PubDecryptRaw(pvtkey, decBuf, &decBufLen, sizeof(decBuf), ctext, ctextLen); if (rv != SECSuccess) { fprintf(stderr, "Couldn't decrypt\n"); goto cleanup; } if (decBufLen == 0) { break; } if (count == inFileLength) { decBufLen = decBufLen - paddingLength; } /* write the plain text to out file */ temp = PR_Write(outFile, decBuf, decBufLen); if (temp != decBufLen) { PR_fprintf(PR_STDERR, "write error\n"); rv = SECFailure; break; } } cleanup: if (encFile) { PR_Close(encFile); } if (outFile) { PR_Close(outFile); } if (pvtkey) { SECKEY_DestroyPrivateKey(pvtkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* Map option letter to command */ static CommandType option2Command(char c) { switch (c) { case 'G': return GENERATE_CSR; case 'A': return ADD_CERT_TO_DB; case 'H': return SAVE_CERT_TO_HEADER; case 'E': return ENCRYPT; case 'D': return DECRYPT; case 'S': return SIGN; case 'V': return VERIFY; default: return UNKNOWN; } } /* * This example illustrates basic encryption/decryption and MACing * Generates the RSA key pair as token object and outputs public key as cert request. * Reads cert request file and stores certificate in DB. * Input, store and trust CA certificate. * Write certificate to intermediate header file * Extract public key from certificate, encrypts the input file and write to external file. * Finds the matching private key, decrypts and write to external file * * How this sample is different from sample 5 ? * * 1. As in sample 5, output is a PKCS#10 CSR * 2. Input and store a cert in cert DB and also used to input, store and trust CA cert. * 3. Like sample 5, but puts cert in header * 4. Like sample 5, but finds key matching cert in header */ int main(int argc, char **argv) { SECStatus rv; PLOptState *optstate; PLOptStatus status; PRBool initialized = PR_FALSE; CommandType cmd = UNKNOWN; const char *dbdir = NULL; secuPWData pwdata = { PW_NONE, 0 }; char *subjectStr = NULL; CERTName *subject = 0; unsigned int serialNumber = 0; char *serialNumberStr = NULL; char *trustStr = NULL; CERTCertDBHandle *certHandle; const char *nickNameStr = NULL; char *issuerNameStr = NULL; PRBool selfsign = PR_FALSE; PRBool ascii = PR_FALSE; PRBool sigVerify = PR_FALSE; const char *headerFileName = NULL; const char *encryptedFileName = NULL; const char *inFileName = NULL; const char *outFileName = NULL; char *certReqFileName = NULL; char *certFileName = NULL; const char *noiseFileName = NULL; PK11SlotInfo *slot = NULL; char * progName = strrchr(argv[0], '/'); progName = progName ? progName + 1 : argv[0]; /* Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, "GAHEDSVad:i:o:f:p:z:s:r:n:x:m:t:c:u:e:b:v:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'a': ascii = PR_TRUE; break; case 'G': /* Generate a CSR */ case 'A': /* Add cert to database */ case 'H': /* Save cert to the header file */ case 'E': /* Encrypt with public key from cert in header file */ case 'S': /* Sign with private key */ case 'D': /* Decrypt with the matching private key */ case 'V': /* Verify with the matching public key */ cmd = option2Command(optstate->option); break; case 'd': dbdir = strdup(optstate->value); break; case 'f': pwdata.source = PW_FROMFILE; pwdata.data = strdup(optstate->value); break; case 'p': pwdata.source = PW_PLAINTEXT; pwdata.data = strdup(optstate->value); break; case 'i': inFileName = strdup(optstate->value); break; case 'b': headerFileName = strdup(optstate->value); break; case 'e': encryptedFileName = strdup(optstate->value); break; case 'o': outFileName = strdup(optstate->value); break; case 'z': noiseFileName = strdup(optstate->value); break; case 's': subjectStr = strdup(optstate->value); subject = CERT_AsciiToName(subjectStr); break; case 'r': certReqFileName = strdup(optstate->value); break; case 'c': certFileName = strdup(optstate->value); break; case 'u': issuerNameStr = strdup(optstate->value); break; case 'n': nickNameStr = strdup(optstate->value); break; case 'x': selfsign = PR_TRUE; break; case 'm': serialNumberStr = strdup(optstate->value); serialNumber = atoi(serialNumberStr); break; case 't': trustStr = strdup(optstate->value); break; case 'v': sigVerify = PR_TRUE; break; default: Usage(progName); break; } } PL_DestroyOptState(optstate); if (cmd == UNKNOWN || !dbdir) Usage(progName); /* Open DB for read/write and authenticate to it */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); initialized = PR_TRUE; rv = NSS_InitReadWrite(dbdir); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "NSS_InitReadWrite Failed\n"); goto cleanup; } PK11_SetPasswordFunc(GetModulePassword); slot = PK11_GetInternalKeySlot(); if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); goto cleanup; } } switch (cmd) { case GENERATE_CSR: ValidateGenerateCSRCommand(progName, dbdir, subject, subjectStr, certReqFileName); /* Generate a CSR */ rv = CreateCertRequest(slot, &pwdata, subject, certReqFileName, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Create Certificate Request: Failed\n"); goto cleanup; } break; case ADD_CERT_TO_DB: ValidateAddCertToDBCommand(progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName, issuerNameStr, serialNumberStr, selfsign); /* Add cert to database */ rv = AddCertificateToDB(slot, &pwdata, certReqFileName, certFileName, issuerNameStr, certHandle, nickNameStr, trustStr, serialNumber, selfsign, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Add Certificate to DB: Failed\n"); goto cleanup; } break; case SAVE_CERT_TO_HEADER: ValidateSaveCertToHeaderCommand(progName, dbdir, nickNameStr, headerFileName); /* Save cert to the header file */ rv = AddCertificateToHeader(slot, &pwdata, headerFileName, certHandle, nickNameStr, sigVerify); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Saving Certificate to header: Failed\n"); goto cleanup; } break; case ENCRYPT: ValidateEncryptCommand(progName, dbdir, nickNameStr, headerFileName, inFileName, encryptedFileName); /* Encrypt with public key from cert in header file */ rv = FindKeyAndEncrypt(slot, &pwdata, headerFileName, encryptedFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find public key and Encrypt : Failed\n"); goto cleanup; } break; case SIGN: ValidateSignCommand(progName, dbdir, nickNameStr, headerFileName, inFileName); /* Sign with private key */ rv = FindKeyAndSign(slot, certHandle, &pwdata, nickNameStr, headerFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find private key and sign : Failed\n"); goto cleanup; } break; case DECRYPT: ValidateDecryptCommand(progName, dbdir, headerFileName, encryptedFileName, outFileName); /* Decrypt with the matching private key */ rv = FindKeyAndDecrypt(slot, &pwdata, headerFileName, encryptedFileName, outFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find private key and Decrypt : Failed\n"); } break; case VERIFY: ValidateVerifyCommand(progName, dbdir, headerFileName, inFileName); /* Verify with the matching public key */ rv = FindKeyAndVerify(slot, certHandle, &pwdata, headerFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find public key and verify signature : Failed\n"); goto cleanup; } } cleanup: if (slot) { PK11_FreeSlot(slot); } if (initialized) { SECStatus rvShutdown = NSS_Shutdown(); if (rvShutdown != SECSuccess) { PR_fprintf(PR_STDERR, "Failed : NSS_Shutdown() - %s", PORT_ErrorToString(rvShutdown)); rv = SECFailure; } PR_Cleanup(); } return rv; }</opfilename></encryptfilename></headerfilename></dbdirpath></ipfilename></headerfilename></dbdirpath></nickname></ipfilename></headerfilename></dbdirpath></nickname></encryptfilename></ipfilename></headerfilename></dbdirpath></headerfilename></nickname></dbdirpath></serialnumber></issuernickname></csr></cert></trust></nickname></dbdirpath></cert></trust></nickname></dbdirpath></csr></subject></dbdirpath></csr></issuernickname></trustargs></nickname></serialnumber></opfilename></encryptfilename></headerfilename></ipfilename></noisefilename></dbpwdfile></dbpwd></dbdirpath></ipfilename></headerfilename></infilename></headerfilename></opfilename></encryptfilename></headerfilename></encryptfilename></ipfilename></headerfilename></headerfilename></nickname></serialnumber></issuernickname></csr></cert></trust></nickname></csr></subject></opfilename></encryptfilename></headerfilename></ipfilename></headerfilename></ipfilename></headerfilename></encryptfilename></ipfilename></headerfilename></headerfilename></nickname></serialnumber></issuernickname></csr></cert></trust></nickname></csr></subject></noisefilename></dbpwdfile></dbpwd></dbdirpath></g|a|h|e|ds|v></sechash.h></secoidt.h></secmodt.h></secoid.h></secport.h></secerr.h></base64.h></cert.h></pk11priv.h></keyhi.h></cryptohi.h></plstr.h></prtypes.h></prlog.h></prinit.h></prerror.h></plgetopt.h></prthread.h> \ No newline at end of file
+ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* NSPR Headers */ #include <prthread.h> #include <plgetopt.h> #include <prerror.h> #include <prinit.h> #include <prlog.h> #include <prtypes.h> #include <plstr.h> /* NSS headers */ #include <cryptohi.h> #include <keyhi.h> #include <pk11priv.h> #include <cert.h> #include <base64.h> #include <secerr.h> #include <secport.h> #include <secoid.h> #include <secmodt.h> #include <secoidt.h> #include <sechash.h> /* our samples utilities */ #include "util.h" /* Constants */ #define BLOCKSIZE 32 #define MODBLOCKSIZE 128 #define DEFAULT_KEY_BITS 1024 /* Header file Constants */ #define ENCKEY_HEADER "-----BEGIN WRAPPED ENCKEY-----" #define ENCKEY_TRAILER "-----END WRAPPED ENCKEY-----" #define MACKEY_HEADER "-----BEGIN WRAPPED MACKEY-----" #define MACKEY_TRAILER "-----END WRAPPED MACKEY-----" #define IV_HEADER "-----BEGIN IV-----" #define IV_TRAILER "-----END IV-----" #define MAC_HEADER "-----BEGIN MAC-----" #define MAC_TRAILER "-----END MAC-----" #define PAD_HEADER "-----BEGIN PAD-----" #define PAD_TRAILER "-----END PAD-----" #define LAB_HEADER "-----BEGIN KEY LABEL-----" #define LAB_TRAILER "-----END KEY LABEL-----" #define PUBKEY_HEADER "-----BEGIN PUB KEY -----" #define PUBKEY_TRAILER "-----END PUB KEY -----" #define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----" #define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----" #define NS_CERT_ENC_HEADER "-----BEGIN CERTIFICATE FOR ENCRYPTION-----" #define NS_CERT_ENC_TRAILER "-----END CERTIFICATE FOR ENCRYPTION-----" #define NS_CERT_VFY_HEADER "-----BEGIN CERTIFICATE FOR SIGNATURE VERIFICATION-----" #define NS_CERT_VFY_TRAILER "-----END CERTIFICATE FOR SIGNATURE VERIFICATION-----" #define NS_SIG_HEADER "-----BEGIN SIGNATURE-----" #define NS_SIG_TRAILER "-----END SIGNATURE-----" #define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" #define NS_CERT_TRAILER "-----END CERTIFICATE-----" /* Missing publically from nss versions earlier than 3.13 */ #ifndef SEC_ERROR_BASE #define SEC_ERROR_BASE (-0x2000) typedef enum { SEC_ERROR_IO = SEC_ERROR_BASE + 0, SEC_ERROR_TOKEN_NOT_LOGGED_IN = (SEC_ERROR_BASE + 155), SEC_ERROR_END_OF_LIST } SECErrorCodes; #endif /* PORT_ErrorToString introduced in nss 3.13. On earlier versions of nss that * don't support error tables, PR_ErrorToString will return "Unknown code". */ #ifndef PORT_ErrorToString #define PORT_ErrorToString(err) PR_ErrorToString((err), PR_LANGUAGE_I_DEFAULT) #endif /* sample 6 commands */ typedef enum { GENERATE_CSR, ADD_CERT_TO_DB, SAVE_CERT_TO_HEADER, ENCRYPT, DECRYPT, SIGN, VERIFY, UNKNOWN } CommandType; typedef enum { SYMKEY = 0, MACKEY = 1, IV = 2, MAC = 3, PAD = 4, PUBKEY = 5, LAB = 6, CERTENC= 7, CERTVFY= 8, SIG = 9 } HeaderType; /* * Print usage message and exit */ static void Usage(const char *progName) { fprintf(stderr, "\nUsage: %s %s %s %s %s %s %s %s %s %s\n\n", progName, " -<g|a|h|e|ds|v> -d <dbdirpath> ", "[-p <dbpwd> | -f <dbpwdfile>] [-z <noisefilename>] [-a <\"\">]", "-s <subject> -r <csr> | ", "-n <nickname> -t <trust> -c <cert> [ -r <csr> -u <issuernickname> [-x <\"\">] -m <serialnumber> ] | ", "-n <nickname> -b <headerfilename> | ", "-b <headerfilename> -i <ipfilename> -e <encryptfilename> | ", "-b <headerfilename> -i <ipfilename> | ", "-b <headerfilename> -i <ipfilename> | ", "-b <headerfilename> -e <encryptfilename> -o <opfilename> \n"); fprintf(stderr, "commands:\n\n"); fprintf(stderr, "%s %s\n --for generating cert request (for CA also)\n\n", progName, "-G -s <subject> -r <csr>"); fprintf(stderr, "%s %s\n --to input and store cert (for CA also)\n\n", progName, "-A -n <nickname> -t <trust> -c <cert> [ -r <csr> -u <issuernickname> [-x <\"\">] -m <serialnumber> ]"); fprintf(stderr, "%s %s\n --to put cert in header\n\n", progName, "-H -n <nickname> -b <headerfilename> [-v <\"\">]"); fprintf(stderr, "%s %s\n --to find public key from cert in header and encrypt\n\n", progName, "-E -b <headerfilename> -i <ipfilename> -e <encryptfilename> "); fprintf(stderr, "%s %s\n --decrypt using corresponding private key \n\n", progName, "-D -b <headerfilename> -e <encryptfilename> -o <opfilename>"); fprintf(stderr, "%s %s\n --Sign using private key \n\n", progName, "-S -b <headerfilename> -i <infilename> "); fprintf(stderr, "%s %s\n --Verify using public key \n\n", progName, "-V -b <headerfilename> -i <ipfilename> "); fprintf(stderr, "options:\n\n"); fprintf(stderr, "%-30s - db directory path\n\n", "-d <dbdirpath>"); fprintf(stderr, "%-30s - db password [optional]\n\n", "-p <dbpwd>"); fprintf(stderr, "%-30s - db password file [optional]\n\n", "-f <dbpwdfile>"); fprintf(stderr, "%-30s - noise file name [optional]\n\n", "-z <noisefilename>"); fprintf(stderr, "%-30s - input file name\n\n", "-i <ipfilename>"); fprintf(stderr, "%-30s - header file name\n\n", "-b <headerfilename>"); fprintf(stderr, "%-30s - encrypt file name\n\n", "-e <encryptfilename>"); fprintf(stderr, "%-30s - output file name\n\n", "-o <opfilename>"); fprintf(stderr, "%-30s - certificate serial number\n\n", "-m <serialnumber>"); fprintf(stderr, "%-30s - certificate nickname\n\n", "-n <nickname>"); fprintf(stderr, "%-30s - certificate trust\n\n", "-t <trustargs>"); fprintf(stderr, "%-30s - certificate issuer nickname\n\n", "-u <issuernickname>"); fprintf(stderr, "%-30s - certificate signing request \n\n", "-r <csr>"); fprintf(stderr, "%-30s - generate a self-signed cert [optional]\n\n", "-x"); fprintf(stderr, "%-30s - to enable ascii [optional]\n\n", "-a"); fprintf(stderr, "%-30s - to save certificate to header file as sig verification [optional]\n\n", "-v"); exit(-1); } /* * Validate the options used for Generate CSR command */ static void ValidateGenerateCSRCommand(const char *progName, const char *dbdir, CERTName *subject, const char *subjectStr, const char *certReqFileName) { PRBool validationFailed = PR_FALSE; if (!subject) { PR_fprintf(PR_STDERR, "%s -G -d %s -s: improperly formatted name: \"%s\"\n", progName, dbdir, subjectStr); validationFailed = PR_TRUE; } if (!certReqFileName) { PR_fprintf(PR_STDERR, "%s -G -d %s -s %s -r: certificate request file name not found\n", progName, dbdir, subjectStr); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-G -d <dbdirpath> -s <subject> -r <csr> \n"); exit(-1); } } /* * Validate the options used for Add Cert to DB command */ static void ValidateAddCertToDBCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *trustStr, const char *certFileName, const char *certReqFileName, const char *issuerNameStr, const char *serialNumberStr, PRBool selfsign) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!trustStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t: trust flag is missing\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!certFileName) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c: certificate file name not found\n", progName, dbdir, nickNameStr, trustStr, serialNumberStr, certReqFileName); validationFailed = PR_TRUE; } if (PR_Access(certFileName, PR_ACCESS_EXISTS) == PR_FAILURE) { if (!certReqFileName) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r: certificate file or certificate request file is not found\n", progName, dbdir, nickNameStr, trustStr, certFileName); validationFailed = PR_TRUE; } if (!selfsign && !issuerNameStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r %s -u : issuer name is missing\n", progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName); validationFailed = PR_TRUE; } if (!serialNumberStr) { PR_fprintf(PR_STDERR, "%s -A -d %s -n %s -t %s -c %s -r %s -u %s -m : serial number is missing\n", progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName, issuerNameStr); validationFailed = PR_TRUE; } } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, " -A -d <dbdirpath> -n <nickname> -t <trust> -c <cert> \n"); fprintf(stderr, " OR\n"); fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-A -d <dbdirpath> -n <nickname> -t <trust> -c <cert> -r <csr> -u <issuernickname> -m <serialnumber> [-x <\"\">] \n"); exit(-1); } } /* * Validate the options used for Save Cert To Header command */ static void ValidateSaveCertToHeaderCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -S -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -S -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-S -d <dbdirpath> -n <nickname> -b <headerfilename> [-v <\"\">]\n"); exit(-1); } } /* * Validate the options used for Encrypt command */ static void ValidateEncryptCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName, const char *inFileName, const char *encryptedFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -E -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b %s -i : input file name is not found\n", progName, dbdir, nickNameStr, headerFileName); validationFailed = PR_TRUE; } if (!encryptedFileName) { PR_fprintf(PR_STDERR, "%s -E -d %s -n %s -b %s -i %s -e : encrypt file name is not found\n", progName, dbdir, nickNameStr, headerFileName, inFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-E -d <dbdirpath> -b <headerfilename> -i <ipfilename> -e <encryptfilename> -n <nickname> \n"); exit(-1); } } /* * Validate the options used for Sign command */ static void ValidateSignCommand(const char *progName, const char *dbdir, const char *nickNameStr, const char *headerFileName, const char *inFileName) { PRBool validationFailed = PR_FALSE; if (!nickNameStr) { PR_fprintf(PR_STDERR, "%s -I -d %s -n : nick name is missing\n", progName, dbdir); validationFailed = PR_TRUE; } if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -n %s -b : header file name is not found\n", progName, dbdir, nickNameStr); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -n %s -b %s -i : input file name is not found\n", progName, dbdir, nickNameStr, headerFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-I -d <dbdirpath> -b <headerfilename> -i <ipfilename> -n <nickname> \n"); exit(-1); } } /* * Validate the options used for verify command */ static void ValidateVerifyCommand(const char *progName, const char *dbdir, const char *headerFileName, const char *inFileName) { PRBool validationFailed = PR_FALSE; if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -V -d %s -b : header file name is not found\n", progName, dbdir); validationFailed = PR_TRUE; } if (!inFileName) { PR_fprintf(PR_STDERR, "%s -I -d %s -b %s -i : input file name is not found\n", progName, dbdir, headerFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-I -d <dbdirpath> -b <headerfilename> -i <ipfilename> \n"); exit(-1); } } /* * Validate the options used for Decrypt command */ static void ValidateDecryptCommand(const char *progName, const char *dbdir, const char *headerFileName, const char *encryptedFileName, const char *outFileName) { PRBool validationFailed = PR_FALSE; if (!headerFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b : header file name is not found\n", progName, dbdir); validationFailed = PR_TRUE; } if (!encryptedFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b %s -e : encrypt file name is not found\n", progName, dbdir, headerFileName); validationFailed = PR_TRUE; } if (!outFileName) { PR_fprintf(PR_STDERR, "%s -D -d %s -b %s -e %s -o : output file name is not found\n", progName, dbdir, headerFileName, encryptedFileName); validationFailed = PR_TRUE; } if (validationFailed) { fprintf(stderr, "\nUsage: %s %s \n\n", progName, "-D -d <dbdirpath> -b <headerfilename> -e <encryptfilename> -o <opfilename>\n"); exit(-1); } } /* * Sign the contents of input file using private key and * return result as SECItem */ SECStatus SignData(const char *inFileName, SECKEYPrivateKey *pk, SECItem *res) { SECStatus rv = SECFailure; unsigned int nb; unsigned char ibuf[4096]; PRFileDesc *inFile = NULL; SGNContext *sgn = NULL; /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Sign using private key */ sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, pk); if (!sgn) { PR_fprintf(PR_STDERR, "unable to create context for signing\n"); rv = SECFailure; goto cleanup; } rv = SGN_Begin(sgn); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_Begin\n"); goto cleanup; } while ((nb = PR_Read(inFile, ibuf, sizeof(ibuf))) > 0) { rv = SGN_Update(sgn, ibuf, nb); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_Update\n"); goto cleanup; } } rv = SGN_End(sgn, res); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while SGN_End\n"); goto cleanup; } cleanup: if (inFile) { PR_Close(inFile); } if (sgn) { SGN_DestroyContext(sgn, PR_TRUE); } return rv; } /* * Verify the signature using public key */ SECStatus VerifyData(const char *inFileName, SECKEYPublicKey *pk, SECItem *sigItem, secuPWData *pwdata) { unsigned int nb; unsigned char ibuf[4096]; SECStatus rv = SECFailure; VFYContext *vfy = NULL; PRFileDesc *inFile = NULL; /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } vfy = VFY_CreateContext(pk, sigItem, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, pwdata); if (!vfy) { PR_fprintf(PR_STDERR, "unable to create context for verifying signature\n"); rv = SECFailure; goto cleanup; } rv = VFY_Begin(vfy); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_Begin\n"); goto cleanup; } while ((nb = PR_Read(inFile, ibuf, sizeof(ibuf))) > 0) { rv = VFY_Update(vfy, ibuf, nb); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_Update\n"); goto cleanup; } } rv = VFY_End(vfy); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "problem while VFY_End\n"); goto cleanup; } cleanup: if (inFile) { PR_Close(inFile); } if (vfy) { VFY_DestroyContext(vfy, PR_TRUE); } return rv; } /* * Write Cryptographic parameters to header file */ SECStatus WriteToHeaderFile(const char *buf, unsigned int len, HeaderType type, PRFileDesc *outFile) { SECStatus rv; const char *header; const char *trailer; switch (type) { case SYMKEY: header = ENCKEY_HEADER; trailer = ENCKEY_TRAILER; break; case MACKEY: header = MACKEY_HEADER; trailer = MACKEY_TRAILER; break; case IV: header = IV_HEADER; trailer = IV_TRAILER; break; case MAC: header = MAC_HEADER; trailer = MAC_TRAILER; break; case PAD: header = PAD_HEADER; trailer = PAD_TRAILER; break; case PUBKEY: header = PUBKEY_HEADER; trailer = PUBKEY_TRAILER; break; case CERTENC: header = NS_CERT_ENC_HEADER; trailer = NS_CERT_ENC_TRAILER; break; case CERTVFY: header = NS_CERT_VFY_HEADER; trailer = NS_CERT_VFY_TRAILER; break; case SIG: header = NS_SIG_HEADER; trailer = NS_SIG_TRAILER; break; case LAB: header = LAB_HEADER; trailer = LAB_TRAILER; PR_fprintf(outFile, "%s\n", header); PR_fprintf(outFile, "%s\n", buf); PR_fprintf(outFile, "%s\n\n", trailer); return SECSuccess; break; default: return SECFailure; } PR_fprintf(outFile, "%s\n", header); PrintAsHex(outFile, buf, len); PR_fprintf(outFile, "%s\n\n", trailer); return SECSuccess; } /* * Read cryptographic parameters from the header file */ SECStatus ReadFromHeaderFile(const char *fileName, HeaderType type, SECItem *item, PRBool isHexData) { SECStatus rv = SECSuccess; PRFileDesc* file = NULL; SECItem filedata; SECItem outbuf; unsigned char *nonbody; unsigned char *body; char *header; char *trailer; outbuf.type = siBuffer; file = PR_Open(fileName, PR_RDONLY, 0); if (!file) { PR_fprintf(PR_STDERR, "Failed to open %s\n", fileName); rv = SECFailure; goto cleanup; } switch (type) { case PUBKEY: header = PUBKEY_HEADER; trailer = PUBKEY_TRAILER; break; case SYMKEY: header = ENCKEY_HEADER; trailer = ENCKEY_TRAILER; break; case MACKEY: header = MACKEY_HEADER; trailer = MACKEY_TRAILER; break; case IV: header = IV_HEADER; trailer = IV_TRAILER; break; case MAC: header = MAC_HEADER; trailer = MAC_TRAILER; break; case PAD: header = PAD_HEADER; trailer = PAD_TRAILER; break; case LAB: header = LAB_HEADER; trailer = LAB_TRAILER; break; case CERTENC: header = NS_CERT_ENC_HEADER; trailer = NS_CERT_ENC_TRAILER; break; case CERTVFY: header = NS_CERT_VFY_HEADER; trailer = NS_CERT_VFY_TRAILER; break; case SIG: header = NS_SIG_HEADER; trailer = NS_SIG_TRAILER; break; default: rv = SECFailure; goto cleanup; } rv = FileToItem(&filedata, file); nonbody = (char *)filedata.data; if (!nonbody) { PR_fprintf(PR_STDERR, "unable to read data from input file\n"); rv = SECFailure; goto cleanup; } /* check for headers and trailers and remove them */ if ((body = strstr(nonbody, header)) != NULL) { char *trail = NULL; nonbody = body; body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(nonbody, '\r'); /* maybe this is a MAC file */ if (body) trail = strstr(++body, trailer); if (trail != NULL) { *trail = '\0'; } else { PR_fprintf(PR_STDERR, "input has header but no trailer\n"); PORT_Free(filedata.data); rv = SECFailure; goto cleanup; } } else { /* headers didn't exist */ char *trail = NULL; body = nonbody; if (body) { trail = strstr(++body, trailer); if (trail != NULL) { PR_fprintf(PR_STDERR, "input has no header but has trailer\n"); PORT_Free(filedata.data); rv = SECFailure; goto cleanup; } } } HexToBuf(body, item, isHexData); cleanup: if (file) { PR_Close(file); } return rv; } /* * Generate the private key */ SECKEYPrivateKey * GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, int publicExponent, const char *noise, SECKEYPublicKey **pubkeyp, const char *pqgFile, secuPWData *pwdata) { CK_MECHANISM_TYPE mechanism; SECOidTag algtag; PK11RSAGenParams rsaparams; void *params; SECKEYPrivateKey *privKey = NULL; SECStatus rv; unsigned char randbuf[BLOCKSIZE + 1]; rv = GenerateRandom(randbuf, BLOCKSIZE); if (rv != SECSuccess) { fprintf(stderr, "Error while generating the random numbers : %s\n", PORT_ErrorToString(rv)); goto cleanup; } PK11_RandomUpdate(randbuf, BLOCKSIZE); switch (keytype) { case rsaKey: rsaparams.keySizeInBits = size; rsaparams.pe = publicExponent; mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; params = &rsaparams; break; default: goto cleanup; } fprintf(stderr, "\n\n"); fprintf(stderr, "Generating key. This may take a few moments...\n\n"); privKey = PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, pwdata); cleanup: return privKey; } /* * Get the certificate request from CSR */ static CERTCertificateRequest * GetCertRequest(char *inFileName, PRBool ascii) { CERTSignedData signedData; SECItem reqDER; CERTCertificateRequest *certReq = NULL; SECStatus rv = SECSuccess; PRArenaPool *arena = NULL; reqDER.data = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { rv = SECFailure; goto cleanup; } rv = ReadDERFromFile(&reqDER, inFileName, ascii); if (rv) { rv = SECFailure; goto cleanup; } certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc (arena, sizeof(CERTCertificateRequest)); if (!certReq) { rv = SECFailure; goto cleanup; } certReq->arena = arena; /* Since cert request is a signed data, must decode to get the inner data */ PORT_Memset(&signedData, 0, sizeof(signedData)); rv = SEC_ASN1DecodeItem(arena, &signedData, SEC_ASN1_GET(CERT_SignedDataTemplate), &reqDER); if (rv) { rv = SECFailure; goto cleanup; } rv = SEC_ASN1DecodeItem(arena, certReq, SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data); if (rv) { rv = SECFailure; goto cleanup; } rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, &certReq->subjectPublicKeyInfo, NULL /* wincx */); if (reqDER.data) { SECITEM_FreeItem(&reqDER, PR_FALSE); } cleanup: if (rv) { PR_fprintf(PR_STDERR, "bad certificate request\n"); if (arena) { PORT_FreeArena(arena, PR_FALSE); } certReq = NULL; } return certReq; } /* * Sign Cert */ static SECItem * SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, SECOidTag hashAlgTag, SECKEYPrivateKey *privKey, char *issuerNickName, void *pwarg) { SECItem der; SECStatus rv; SECOidTag algID; void *dummy; PRArenaPool *arena = NULL; SECItem *result = NULL; SECKEYPrivateKey *caPrivateKey = NULL; if (!selfsign) { CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg); if ((CERTCertificate *)NULL == issuer) { PR_fprintf(PR_STDERR, "unable to find issuer with nickname %s\n", issuerNickName); goto cleanup; } privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); CERT_DestroyCertificate(issuer); if (caPrivateKey == NULL) { PR_fprintf(PR_STDERR, "unable to retrieve key %s\n", issuerNickName); goto cleanup; } } arena = cert->arena; algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag); if (algID == SEC_OID_UNKNOWN) { PR_fprintf(PR_STDERR, "Unknown key or hash type for issuer.\n"); goto cleanup; } rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not set signature algorithm id.\n%s\n", PORT_ErrorToString(rv)); goto cleanup; } /* we only deal with cert v3 here */ *(cert->version.data) = 2; cert->version.len = 1; der.len = 0; der.data = NULL; dummy = SEC_ASN1EncodeItem (arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); if (!dummy) { PR_fprintf(PR_STDERR, "Could not encode certificate.\n"); goto cleanup; } result = (SECItem *) PORT_ArenaZAlloc (arena, sizeof (SECItem)); if (result == NULL) { PR_fprintf(PR_STDERR, "Could not allocate item for certificate data.\n"); goto cleanup; } rv = SEC_DerSignData(arena, result, der.data, der.len, privKey, algID); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not sign encoded certificate data : %s\n", PORT_ErrorToString(rv)); /* result allocated out of the arena, it will be freed * when the arena is freed */ result = NULL; goto cleanup; } cert->derCert = *result; cleanup: if (caPrivateKey) { SECKEY_DestroyPrivateKey(caPrivateKey); } return result; } /* * MakeV1Cert */ static CERTCertificate * MakeV1Cert(CERTCertDBHandle *handle, CERTCertificateRequest *req, char * issuerNickName, PRBool selfsign, unsigned int serialNumber, int warpmonths, int validityMonths) { PRExplodedTime printableTime; PRTime now; PRTime after; CERTValidity *validity = NULL; CERTCertificate *issuerCert = NULL; CERTCertificate *cert = NULL; if ( !selfsign ) { issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName); if (!issuerCert) { PR_fprintf(PR_STDERR, "could not find certificate named %s\n", issuerNickName); goto cleanup; } } now = PR_Now(); PR_ExplodeTime (now, PR_GMTParameters, &printableTime); if ( warpmonths ) { printableTime.tm_month += warpmonths; now = PR_ImplodeTime (&printableTime); PR_ExplodeTime (now, PR_GMTParameters, &printableTime); } printableTime.tm_month += validityMonths; after = PR_ImplodeTime (&printableTime); /* note that the time is now in micro-second unit */ validity = CERT_CreateValidity (now, after); if (validity) { cert = CERT_CreateCertificate(serialNumber, (selfsign ? &req->subject : &issuerCert->subject), validity, req); CERT_DestroyValidity(validity); } cleanup: if ( issuerCert ) { CERT_DestroyCertificate (issuerCert); } return cert; } /* * Add a certificate to the nss database */ SECStatus AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, const char *name, char *trusts, char *inFileName, PRBool ascii, PRBool emailcert, void *pwdata) { SECItem certDER; SECStatus rv; CERTCertTrust *trust = NULL; CERTCertificate *cert = NULL; certDER.data = NULL; /* Read in the entire file specified with the -i argument */ rv = ReadDERFromFile(&certDER, inFileName, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "unable to read input file %s : %s\n", inFileName, PORT_ErrorToString(rv)); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)certDER.data, certDER.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Create a cert trust */ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); if (!trust) { PR_fprintf(PR_STDERR, "unable to allocate cert trust\n"); rv = SECFailure; goto cleanup; } rv = CERT_DecodeTrustString(trust, trusts); if (rv) { PR_fprintf(PR_STDERR, "unable to decode trust string\n"); rv = SECFailure; goto cleanup; } rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); if (rv != SECSuccess) { /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have * been coded to take a password arg. */ if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not authenticate to token %s : %s\n", PK11_GetTokenName(slot), PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); } if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not add certificate to token or database : %s\n", PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } } rv = CERT_ChangeCertTrust(handle, cert, trust); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not authenticate to token %s : %s\n", PK11_GetTokenName(slot), PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } rv = CERT_ChangeCertTrust(handle, cert, trust); } if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not change trust on certificate : %s\n", PORT_ErrorToString(rv)); rv = SECFailure; goto cleanup; } } if (emailcert) { CERT_SaveSMimeProfile(cert, NULL, pwdata); } cleanup: if (cert) { CERT_DestroyCertificate (cert); } if (trust) { PORT_Free(trust); } if (certDER.data) { PORT_Free(certDER.data); } return rv; } /* * Create a certificate */ static SECStatus CreateCert( CERTCertDBHandle *handle, PK11SlotInfo *slot, char * issuerNickName, char *inFileName, char *outFileName, SECKEYPrivateKey **selfsignprivkey, void *pwarg, SECOidTag hashAlgTag, unsigned int serialNumber, int warpmonths, int validityMonths, const char *dnsNames, PRBool ascii, PRBool selfsign) { void *extHandle; SECItem reqDER; CERTCertExtension **CRexts; SECStatus rv = SECSuccess; CERTCertificate *subjectCert = NULL; CERTCertificateRequest *certReq = NULL; PRFileDesc *outFile = NULL; SECItem *certDER = NULL; reqDER.data = NULL; outFile = PR_Open(outFileName, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00660); /* Create a cert request object from the input cert request der */ certReq = GetCertRequest(inFileName, ascii); if (certReq == NULL) { rv = SECFailure; goto cleanup; } subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign, serialNumber, warpmonths, validityMonths); if (subjectCert == NULL) { rv = SECFailure; goto cleanup; } extHandle = CERT_StartCertExtensions (subjectCert); if (extHandle == NULL) { rv = SECFailure; goto cleanup; } if (certReq->attributes != NULL && certReq->attributes[0] != NULL && certReq->attributes[0]->attrType.data != NULL && certReq->attributes[0]->attrType.len > 0 && SECOID_FindOIDTag(&certReq->attributes[0]->attrType) == SEC_OID_PKCS9_EXTENSION_REQUEST) { rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", PORT_ErrorToString(rv)); goto cleanup; } rv = CERT_MergeExtensions(extHandle, CRexts); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", PORT_ErrorToString(rv)); goto cleanup; } } CERT_FinishExtensions(extHandle); /* self-signing a cert request, find the private key */ if (*selfsignprivkey == NULL) { *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg); if (!*selfsignprivkey) { PR_fprintf(PR_STDERR, "Failed to locate private key.\n"); rv = SECFailure; goto cleanup; } } certDER = SignCert(handle, subjectCert, selfsign, hashAlgTag, *selfsignprivkey, issuerNickName,pwarg); if (certDER) { if (ascii) { PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CERT_HEADER, BTOA_DataToAscii(certDER->data, certDER->len), NS_CERT_TRAILER); } else { PR_Write(outFile, certDER->data, certDER->len); } } if (rv != SECSuccess) { PRErrorCode perr = PR_GetError(); PR_fprintf(PR_STDERR, "unable to create cert %s\n", perr); } cleanup: if (outFile) { PR_Close(outFile); } if (*selfsignprivkey) { SECKEY_DestroyPrivateKey(*selfsignprivkey); } if (certReq) { CERT_DestroyCertificateRequest(certReq); } if (subjectCert) { CERT_DestroyCertificate(subjectCert); } return rv; } /* * Generate the certificate request with subject */ static SECStatus CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, SECOidTag hashAlgTag, CERTName *subject, PRBool ascii, const char *certReqFileName) { SECOidTag signAlgTag; SECItem result; PRInt32 numBytes; SECStatus rv = SECSuccess; PRArenaPool *arena = NULL; void *extHandle = NULL; PRFileDesc *outFile = NULL; CERTSubjectPublicKeyInfo *spki = NULL; CERTCertificateRequest *cr = NULL; SECItem *encoding = NULL; /* If the certificate request file already exists, delete it */ if (PR_Access(certReqFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(certReqFileName); } /* Open the certificate request file to write */ outFile = PR_Open(certReqFileName, PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); if (!outFile) { PR_fprintf(PR_STDERR, "unable to open \"%s\" for writing (%ld, %ld).\n", certReqFileName, PR_GetError(), PR_GetOSError()); goto cleanup; } /* Create info about public key */ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); if (!spki) { PR_fprintf(PR_STDERR, "unable to create subject public key\n"); rv = SECFailure; goto cleanup; } /* Generate certificate request */ cr = CERT_CreateCertificateRequest(subject, spki, NULL); if (!cr) { PR_fprintf(PR_STDERR, "unable to make certificate request\n"); rv = SECFailure; goto cleanup; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { fprintf(stderr, "out of memory"); rv = SECFailure; goto cleanup; } extHandle = CERT_StartCertificateRequestAttributes(cr); if (extHandle == NULL) { PORT_FreeArena (arena, PR_FALSE); rv = SECFailure; goto cleanup; } CERT_FinishExtensions(extHandle); CERT_FinishCertificateRequestAttributes(cr); /* Der encode the request */ encoding = SEC_ASN1EncodeItem(arena, NULL, cr, SEC_ASN1_GET(CERT_CertificateRequestTemplate)); if (encoding == NULL) { PR_fprintf(PR_STDERR, "der encoding of request failed\n"); rv = SECFailure; goto cleanup; } /* Sign the request */ signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag); if (signAlgTag == SEC_OID_UNKNOWN) { PR_fprintf(PR_STDERR, "unknown Key or Hash type\n"); rv = SECFailure; goto cleanup; } rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len, privk, signAlgTag); if (rv) { PR_fprintf(PR_STDERR, "signing of data failed\n"); rv = SECFailure; goto cleanup; } /* Encode request in specified format */ if (ascii) { char *obuf; char *name, *email, *org, *state, *country; SECItem *it; int total; it = &result; obuf = BTOA_ConvertItemToAscii(it); total = PL_strlen(obuf); name = CERT_GetCommonName(subject); if (!name) { name = strdup("(not specified)"); } email = CERT_GetCertEmailAddress(subject); if (!email) email = strdup("(not specified)"); org = CERT_GetOrgName(subject); if (!org) org = strdup("(not specified)"); state = CERT_GetStateName(subject); if (!state) state = strdup("(not specified)"); country = CERT_GetCountryName(subject); if (!country) country = strdup("(not specified)"); PR_fprintf(outFile, "\nCertificate request generated by Netscape certutil\n"); PR_fprintf(outFile, "Common Name: %s\n", name); PR_fprintf(outFile, "Email: %s\n", email); PR_fprintf(outFile, "Organization: %s\n", org); PR_fprintf(outFile, "State: %s\n", state); PR_fprintf(outFile, "Country: %s\n\n", country); PR_fprintf(outFile, "%s\n", NS_CERTREQ_HEADER); numBytes = PR_Write(outFile, obuf, total); if (numBytes != total) { PR_fprintf(PR_STDERR, "write error\n"); return SECFailure; } PR_fprintf(outFile, "\n%s\n", NS_CERTREQ_TRAILER); } else { numBytes = PR_Write(outFile, result.data, result.len); if (numBytes != (int)result.len) { PR_fprintf(PR_STDERR, "write error\n"); rv = SECFailure; goto cleanup; } } cleanup: if (outFile) { PR_Close(outFile); } if (privk) { SECKEY_DestroyPrivateKey(privk); } if (pubk) { SECKEY_DestroyPublicKey(pubk); } return rv; } /* * Create certificate request with subject */ SECStatus CreateCertRequest(PK11SlotInfo *slot, secuPWData *pwdata, CERTName *subject, char *certReqFileName, PRBool ascii) { SECStatus rv; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; KeyType keytype = rsaKey; int keysize = DEFAULT_KEY_BITS; int publicExponent = 0x010001; SECOidTag hashAlgTag = SEC_OID_UNKNOWN; privkey = GeneratePrivateKey(keytype, slot, keysize, publicExponent, NULL, &pubkey, NULL, pwdata); if (privkey == NULL) { PR_fprintf(PR_STDERR, "unable to generate key(s)\n"); rv = SECFailure; goto cleanup; } privkey->wincx = pwdata; PORT_Assert(pubkey != NULL); rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject, ascii, certReqFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to create Certificate Request\n"); } cleanup: return rv; } /* * Creates the certificate using CSR and adds the certificate to DB */ SECStatus AddCertificateToDB(PK11SlotInfo *slot, secuPWData *pwdata, char *certReqFileName, char *certFileName, char *issuerNameStr, CERTCertDBHandle *certHandle, const char *nickNameStr, char *trustStr, unsigned int serialNumber, PRBool selfsign, PRBool ascii) { SECStatus rv; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; SECOidTag hashAlgTag = SEC_OID_UNKNOWN; if (PR_Access(certFileName, PR_ACCESS_EXISTS) == PR_FAILURE) { rv = CreateCert(certHandle, slot, issuerNameStr, certReqFileName, certFileName, &privkey, &pwdata, hashAlgTag, serialNumber, 0, 3, NULL, ascii, selfsign); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to create Certificate\n"); goto cleanup; } } rv = AddCert(slot, certHandle, nickNameStr, trustStr, certFileName, ascii, 0, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to add Certificate\n"); } cleanup: return rv; } /* * Finds the certificate using nickname and saves it to the header file */ SECStatus AddCertificateToHeader(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, CERTCertDBHandle *certHandle, const char *nickNameStr, PRBool sigVerify) { SECStatus rv = SECSuccess; PRFileDesc *headerFile = NULL; CERTCertificate *cert = NULL; HeaderType hType = CERTENC; /* If the intermediate header file already exists, delete it */ if (PR_Access(headerFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(headerFileName); } headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "unable to open \"%s\" for writing (%ld, %ld).\n", headerFileName, PR_GetError(), PR_GetOSError()); rv = SECFailure; goto cleanup; } cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickNameStr); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } if (sigVerify) { hType = CERTVFY; } WriteToHeaderFile(cert->derCert.data, cert->derCert.len, hType, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the public key from the certificate saved in the header file * and encrypts with it the contents of inFileName to encryptedFileName. */ SECStatus FindKeyAndEncrypt(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, const char *encryptedFileName, const char *inFileName) { SECStatus rv; PRFileDesc *headerFile = NULL; PRFileDesc *encFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; SECItem data; unsigned char ptext[MODBLOCKSIZE]; unsigned char encBuf[MODBLOCKSIZE]; unsigned int ptextLen; int index; unsigned int nWritten; unsigned int pad[1]; SECItem padItem; unsigned int paddingLength = 0; SECKEYPublicKey *pubkey = NULL; /* If the intermediate encrypted file already exists, delete it*/ if (PR_Access(encryptedFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(encryptedFileName); } /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTENC, &data, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)data.data, data.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Extract the public key from certificate */ pubkey = CERT_ExtractPublicKey(cert); if (!pubkey) { PR_fprintf(PR_STDERR, "could not get key from certificate\n"); rv = SECFailure; goto cleanup; } /* Open the encrypted file for writing */ encFile = PR_Open(encryptedFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!encFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", encryptedFileName); rv = SECFailure; goto cleanup; } /* Open the input file for reading */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Open the header file to write padding */ headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_APPEND, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Read input file */ while ((ptextLen = PR_Read(inFile, ptext, sizeof(ptext))) > 0) { if (ptextLen != MODBLOCKSIZE) { paddingLength = MODBLOCKSIZE - ptextLen; for ( index=0; index < paddingLength; index++) { ptext[ptextLen+index] = (unsigned char)paddingLength; } ptextLen = MODBLOCKSIZE; } rv = PK11_PubEncryptRaw(pubkey, encBuf, ptext, ptextLen, NULL); nWritten = PR_Write(encFile, encBuf, ptextLen); } /* Write the padding to header file */ pad[0] = paddingLength; padItem.type = siBuffer; padItem.data = (unsigned char *)pad; padItem.len = sizeof(pad[0]); WriteToHeaderFile(padItem.data, padItem.len, PAD, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (encFile) { PR_Close(encFile); } if (inFile) { PR_Close(inFile); } if (pubkey) { SECKEY_DestroyPublicKey(pubkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the private key from db and signs the contents * of inFileName and writes to signatureFileName */ SECStatus FindKeyAndSign(PK11SlotInfo *slot, CERTCertDBHandle* certHandle, secuPWData *pwdata, const char *nickNameStr, const char *headerFileName, const char *inFileName) { SECStatus rv; PRFileDesc *headerFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; unsigned int signatureLen = 0; SECKEYPrivateKey *privkey = NULL; SECItem sigItem; SECOidTag hashOIDTag; /* Open the header file to write padding */ headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_RDWR | PR_APPEND, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Get the certificate by nick name and write to header file */ cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickNameStr); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate by name - %s\n", nickNameStr); rv = SECFailure; goto cleanup; } WriteToHeaderFile(cert->derCert.data, cert->derCert.len, CERTVFY, headerFile); /* Find private key from certificate */ privkey = PK11_FindKeyByAnyCert(cert, NULL); if (privkey == NULL) { fprintf(stderr, "Couldn't find private key for cert\n"); rv = SECFailure; goto cleanup; } /* Sign the contents of the input file */ rv = SignData(inFileName, privkey, &sigItem); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "could not sign the contents from file - %s \n", inFileName); goto cleanup; } /* write signature to header file */ WriteToHeaderFile(sigItem.data, sigItem.len, SIG, headerFile); cleanup: if (headerFile) { PR_Close(headerFile); } if (privkey) { SECKEY_DestroyPrivateKey(privkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the public key from certificate and verifies signature */ SECStatus FindKeyAndVerify(PK11SlotInfo *slot, CERTCertDBHandle* certHandle, secuPWData *pwdata, const char *headerFileName, const char *inFileName) { SECStatus rv = SECFailure; PRFileDesc *headerFile = NULL; PRFileDesc *inFile = NULL; CERTCertificate *cert = NULL; SECKEYPublicKey *pubkey = NULL; SECItem sigItem; SECItem certData; /* Open the input file */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); rv = SECFailure; goto cleanup; } /* Open the header file to read the certificate and signature */ headerFile = PR_Open(headerFileName, PR_RDONLY, 0); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); rv = SECFailure; goto cleanup; } /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTVFY, &certData, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)certData.data, certData.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Extract the public key from certificate */ pubkey = CERT_ExtractPublicKey(cert); if (!pubkey) { PR_fprintf(PR_STDERR, "Could not get key from certificate\n"); rv = SECFailure; goto cleanup; } /* Read signature from header file */ rv = ReadFromHeaderFile(headerFileName, SIG, &sigItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read signature from header file\n"); goto cleanup; } /* Verify with the public key */ rv = VerifyData(inFileName, pubkey, &sigItem, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Couldn't verify the signature for file - %s\n", inFileName); goto cleanup; } cleanup: if (headerFile) { PR_Close(headerFile); } if (pubkey) { SECKEY_DestroyPublicKey(pubkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* * Finds the private key corresponding to the certificate saved in the header file * and decrypts with it the contents of encryptedFileName to outFileName. */ SECStatus FindKeyAndDecrypt(PK11SlotInfo *slot, secuPWData *pwdata, const char *headerFileName, const char *encryptedFileName, const char *outFileName) { SECStatus rv; PRFileDesc *encFile = NULL; PRFileDesc *outFile = NULL; SECKEYPrivateKey *pvtkey = NULL; unsigned int inFileLength = 0; unsigned int paddingLength = 0; unsigned int count = 0; unsigned int temp = 0; unsigned char ctext[MODBLOCKSIZE]; unsigned char decBuf[MODBLOCKSIZE]; unsigned int ctextLen; unsigned int decBufLen; SECItem padItem; SECItem data; SECItem signature; CERTCertificate *cert = NULL; /* Read certificate from header file */ rv = ReadFromHeaderFile(headerFileName, CERTENC, &data, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not read certificate from header file\n"); goto cleanup; } /* Read padding from header file */ rv = ReadFromHeaderFile(headerFileName, PAD, &padItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve PAD detail from header file\n"); goto cleanup; } paddingLength = (unsigned int)padItem.data[0]; inFileLength = FileSize(encryptedFileName); /* Read in an ASCII cert and return a CERTCertificate */ cert = CERT_DecodeCertFromPackage((char *)data.data, data.len); if (!cert) { PR_fprintf(PR_STDERR, "could not obtain certificate from file\n"); rv = SECFailure; goto cleanup; } /* Find private key from certificate */ pvtkey = PK11_FindKeyByAnyCert(cert, NULL); if (pvtkey == NULL) { fprintf(stderr, "Couldn't find private key for cert\n"); rv = SECFailure; goto cleanup; } /* Open the out file to write */ outFile = PR_Open(outFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!outFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", outFileName); rv = SECFailure; goto cleanup; } /* Open the encrypted file for reading */ encFile = PR_Open(encryptedFileName, PR_RDONLY, 0); if (!encFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", encryptedFileName); rv = SECFailure; goto cleanup; } /* Read the encrypt file, decrypt and write to out file */ while ((ctextLen = PR_Read(encFile, ctext, sizeof(ctext))) > 0) { count += ctextLen; rv = PK11_PubDecryptRaw(pvtkey, decBuf, &decBufLen, sizeof(decBuf), ctext, ctextLen); if (rv != SECSuccess) { fprintf(stderr, "Couldn't decrypt\n"); goto cleanup; } if (decBufLen == 0) { break; } if (count == inFileLength) { decBufLen = decBufLen - paddingLength; } /* write the plain text to out file */ temp = PR_Write(outFile, decBuf, decBufLen); if (temp != decBufLen) { PR_fprintf(PR_STDERR, "write error\n"); rv = SECFailure; break; } } cleanup: if (encFile) { PR_Close(encFile); } if (outFile) { PR_Close(outFile); } if (pvtkey) { SECKEY_DestroyPrivateKey(pvtkey); } if (cert) { CERT_DestroyCertificate(cert); } return rv; } /* Map option letter to command */ static CommandType option2Command(char c) { switch (c) { case 'G': return GENERATE_CSR; case 'A': return ADD_CERT_TO_DB; case 'H': return SAVE_CERT_TO_HEADER; case 'E': return ENCRYPT; case 'D': return DECRYPT; case 'S': return SIGN; case 'V': return VERIFY; default: return UNKNOWN; } } /* * This example illustrates basic encryption/decryption and MACing * Generates the RSA key pair as token object and outputs public key as cert request. * Reads cert request file and stores certificate in DB. * Input, store and trust CA certificate. * Write certificate to intermediate header file * Extract public key from certificate, encrypts the input file and write to external file. * Finds the matching private key, decrypts and write to external file * * How this sample is different from sample 5 ? * * 1. As in sample 5, output is a PKCS#10 CSR * 2. Input and store a cert in cert DB and also used to input, store and trust CA cert. * 3. Like sample 5, but puts cert in header * 4. Like sample 5, but finds key matching cert in header */ int main(int argc, char **argv) { SECStatus rv; PLOptState *optstate; PLOptStatus status; PRBool initialized = PR_FALSE; CommandType cmd = UNKNOWN; const char *dbdir = NULL; secuPWData pwdata = { PW_NONE, 0 }; char *subjectStr = NULL; CERTName *subject = 0; unsigned int serialNumber = 0; char *serialNumberStr = NULL; char *trustStr = NULL; CERTCertDBHandle *certHandle; const char *nickNameStr = NULL; char *issuerNameStr = NULL; PRBool selfsign = PR_FALSE; PRBool ascii = PR_FALSE; PRBool sigVerify = PR_FALSE; const char *headerFileName = NULL; const char *encryptedFileName = NULL; const char *inFileName = NULL; const char *outFileName = NULL; char *certReqFileName = NULL; char *certFileName = NULL; const char *noiseFileName = NULL; PK11SlotInfo *slot = NULL; char * progName = strrchr(argv[0], '/'); progName = progName ? progName + 1 : argv[0]; /* Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, "GAHEDSVad:i:o:f:p:z:s:r:n:x:m:t:c:u:e:b:v:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'a': ascii = PR_TRUE; break; case 'G': /* Generate a CSR */ case 'A': /* Add cert to database */ case 'H': /* Save cert to the header file */ case 'E': /* Encrypt with public key from cert in header file */ case 'S': /* Sign with private key */ case 'D': /* Decrypt with the matching private key */ case 'V': /* Verify with the matching public key */ cmd = option2Command(optstate->option); break; case 'd': dbdir = strdup(optstate->value); break; case 'f': pwdata.source = PW_FROMFILE; pwdata.data = strdup(optstate->value); break; case 'p': pwdata.source = PW_PLAINTEXT; pwdata.data = strdup(optstate->value); break; case 'i': inFileName = strdup(optstate->value); break; case 'b': headerFileName = strdup(optstate->value); break; case 'e': encryptedFileName = strdup(optstate->value); break; case 'o': outFileName = strdup(optstate->value); break; case 'z': noiseFileName = strdup(optstate->value); break; case 's': subjectStr = strdup(optstate->value); subject = CERT_AsciiToName(subjectStr); break; case 'r': certReqFileName = strdup(optstate->value); break; case 'c': certFileName = strdup(optstate->value); break; case 'u': issuerNameStr = strdup(optstate->value); break; case 'n': nickNameStr = strdup(optstate->value); break; case 'x': selfsign = PR_TRUE; break; case 'm': serialNumberStr = strdup(optstate->value); serialNumber = atoi(serialNumberStr); break; case 't': trustStr = strdup(optstate->value); break; case 'v': sigVerify = PR_TRUE; break; default: Usage(progName); break; } } PL_DestroyOptState(optstate); if (cmd == UNKNOWN || !dbdir) Usage(progName); /* Open DB for read/write and authenticate to it */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); initialized = PR_TRUE; rv = NSS_InitReadWrite(dbdir); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "NSS_InitReadWrite Failed\n"); goto cleanup; } PK11_SetPasswordFunc(GetModulePassword); slot = PK11_GetInternalKeySlot(); if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); goto cleanup; } } switch (cmd) { case GENERATE_CSR: ValidateGenerateCSRCommand(progName, dbdir, subject, subjectStr, certReqFileName); /* Generate a CSR */ rv = CreateCertRequest(slot, &pwdata, subject, certReqFileName, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Create Certificate Request: Failed\n"); goto cleanup; } break; case ADD_CERT_TO_DB: ValidateAddCertToDBCommand(progName, dbdir, nickNameStr, trustStr, certFileName, certReqFileName, issuerNameStr, serialNumberStr, selfsign); /* Add cert to database */ rv = AddCertificateToDB(slot, &pwdata, certReqFileName, certFileName, issuerNameStr, certHandle, nickNameStr, trustStr, serialNumber, selfsign, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Add Certificate to DB: Failed\n"); goto cleanup; } break; case SAVE_CERT_TO_HEADER: ValidateSaveCertToHeaderCommand(progName, dbdir, nickNameStr, headerFileName); /* Save cert to the header file */ rv = AddCertificateToHeader(slot, &pwdata, headerFileName, certHandle, nickNameStr, sigVerify); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Saving Certificate to header: Failed\n"); goto cleanup; } break; case ENCRYPT: ValidateEncryptCommand(progName, dbdir, nickNameStr, headerFileName, inFileName, encryptedFileName); /* Encrypt with public key from cert in header file */ rv = FindKeyAndEncrypt(slot, &pwdata, headerFileName, encryptedFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find public key and Encrypt : Failed\n"); goto cleanup; } break; case SIGN: ValidateSignCommand(progName, dbdir, nickNameStr, headerFileName, inFileName); /* Sign with private key */ rv = FindKeyAndSign(slot, certHandle, &pwdata, nickNameStr, headerFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find private key and sign : Failed\n"); goto cleanup; } break; case DECRYPT: ValidateDecryptCommand(progName, dbdir, headerFileName, encryptedFileName, outFileName); /* Decrypt with the matching private key */ rv = FindKeyAndDecrypt(slot, &pwdata, headerFileName, encryptedFileName, outFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find private key and Decrypt : Failed\n"); } break; case VERIFY: ValidateVerifyCommand(progName, dbdir, headerFileName, inFileName); /* Verify with the matching public key */ rv = FindKeyAndVerify(slot, certHandle, &pwdata, headerFileName, inFileName); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Find public key and verify signature : Failed\n"); goto cleanup; } } cleanup: if (slot) { PK11_FreeSlot(slot); } if (initialized) { SECStatus rvShutdown = NSS_Shutdown(); if (rvShutdown != SECSuccess) { PR_fprintf(PR_STDERR, "Failed : NSS_Shutdown() - %s", PORT_ErrorToString(rvShutdown)); rv = SECFailure; } PR_Cleanup(); } return rv; }</opfilename></encryptfilename></headerfilename></dbdirpath></ipfilename></headerfilename></dbdirpath></nickname></ipfilename></headerfilename></dbdirpath></nickname></encryptfilename></ipfilename></headerfilename></dbdirpath></headerfilename></nickname></dbdirpath></serialnumber></issuernickname></csr></cert></trust></nickname></dbdirpath></cert></trust></nickname></dbdirpath></csr></subject></dbdirpath></csr></issuernickname></trustargs></nickname></serialnumber></opfilename></encryptfilename></headerfilename></ipfilename></noisefilename></dbpwdfile></dbpwd></dbdirpath></ipfilename></headerfilename></infilename></headerfilename></opfilename></encryptfilename></headerfilename></encryptfilename></ipfilename></headerfilename></headerfilename></nickname></serialnumber></issuernickname></csr></cert></trust></nickname></csr></subject></opfilename></encryptfilename></headerfilename></ipfilename></headerfilename></ipfilename></headerfilename></encryptfilename></ipfilename></headerfilename></headerfilename></nickname></serialnumber></issuernickname></csr></cert></trust></nickname></csr></subject></noisefilename></dbpwdfile></dbpwd></dbdirpath></g|a|h|e|ds|v></sechash.h></secoidt.h></secmodt.h></secoid.h></secport.h></secerr.h></base64.h></cert.h></pk11priv.h></keyhi.h></cryptohi.h></plstr.h></prtypes.h></prlog.h></prinit.h></prerror.h></plgetopt.h></prthread.h>
diff --git a/doc/rst/legacy/nss_sample_code/sample2_-_initialize_nss_database/index.rst b/doc/rst/legacy/nss_sample_code/sample2_-_initialize_nss_database/index.rst
index 43a401815..fe1d83fc6 100644
--- a/doc/rst/legacy/nss_sample_code/sample2_-_initialize_nss_database/index.rst
+++ b/doc/rst/legacy/nss_sample_code/sample2_-_initialize_nss_database/index.rst
@@ -12,7 +12,7 @@ Initialize NSS database - sample 2
The NSS sample code below demonstrates how to initialize the NSS database.
- .. code:: brush:
+ .. code:: c
/*
* Print a usage message and exit
diff --git a/doc/rst/legacy/nss_sample_code/sample3_-_encdecmac_using_token_object/index.rst b/doc/rst/legacy/nss_sample_code/sample3_-_encdecmac_using_token_object/index.rst
index 0fa9e49df..ec6ff208f 100644
--- a/doc/rst/legacy/nss_sample_code/sample3_-_encdecmac_using_token_object/index.rst
+++ b/doc/rst/legacy/nss_sample_code/sample3_-_encdecmac_using_token_object/index.rst
@@ -25,6 +25,6 @@ EncDecMAC using token object - sample 3
Computes the hash of a file and saves it to another file, illustrates the use of NSS message
APIs.
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* NSPR Headers */ #include #include #include #include #include #include #include /* NSS headers */ #include #include /* our samples utilities */ #include "util.h" #define BUFFERSIZE 80 #define DIGESTSIZE 16 #define PTEXT_MAC_BUFFER_SIZE 96 #define CIPHERSIZE 96 #define BLOCKSIZE 32 #define CIPHER_HEADER "-----BEGIN CIPHER-----" #define CIPHER_TRAILER "-----END CIPHER-----" #define ENCKEY_HEADER "-----BEGIN AESKEY CKAID-----" #define ENCKEY_TRAILER "-----END AESKEY CKAID-----" #define MACKEY_HEADER "-----BEGIN MACKEY CKAID-----" #define MACKEY_TRAILER "-----END MACKEY CKAID-----" #define IV_HEADER "-----BEGIN IV-----" #define IV_TRAILER "-----END IV-----" #define MAC_HEADER "-----BEGIN MAC-----" #define MAC_TRAILER "-----END MAC-----" #define PAD_HEADER "-----BEGIN PAD-----" #define PAD_TRAILER "-----END PAD-----" typedef enum { ENCRYPT, DECRYPT, UNKNOWN } CommandType; typedef enum { SYMKEY = 0, MACKEY = 1, IV = 2, MAC = 3, PAD = 4 } HeaderType; /* * Print usage message and exit */ static void Usage(const char *progName) { fprintf(stderr, "\nUsage: %s -c -d [-z ] " "[-p | -f ] -i -o \n\n", progName); fprintf(stderr, "%-20s Specify 'a' for encrypt operation\n\n", "-c "); fprintf(stderr, "%-20s Specify 'b' for decrypt operation\n\n", " "); fprintf(stderr, "%-20s Specify db directory path\n\n", "-d "); fprintf(stderr, "%-20s Specify db password [optional]\n\n", "-p "); fprintf(stderr, "%-20s Specify db password file [optional]\n\n", "-f "); fprintf(stderr, "%-20s Specify noise file name [optional]\n\n", "-z "); fprintf(stderr, "%-21s Specify an input file name\n\n", "-i "); fprintf(stderr, "%-21s Specify an output file name\n\n", "-o "); fprintf(stderr, "%-7s For encrypt, it takes as an input file and produces\n", "Note :"); fprintf(stderr, "%-7s .enc and .header as intermediate output files.\n\n", ""); fprintf(stderr, "%-7s For decrypt, it takes .enc and .header\n", ""); fprintf(stderr, "%-7s as input files and produces as a final output file.\n\n", ""); exit(-1); } /* * Gather a CKA_ID */ SECStatus GatherCKA_ID(PK11SymKey* key, SECItem* buf) { SECStatus rv = PK11_ReadRawAttribute(PK11_TypeSymKey, key, CKA_ID, buf); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "PK11_ReadRawAttribute returned (%d)\n", rv); PR_fprintf(PR_STDERR, "Could not read SymKey CKA_ID attribute\n"); return rv; } return rv; } /* * Generate a Symmetric Key */ PK11SymKey * GenerateSYMKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism, int keySize, SECItem *keyID, secuPWData *pwdata) { SECStatus rv; PK11SymKey *key; if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); return NULL; } } /* Generate the symmetric key */ key = PK11_TokenKeyGen(slot, mechanism, NULL, keySize, keyID, PR_TRUE, pwdata); if (!key) { PR_fprintf(PR_STDERR, "Symmetric Key Generation Failed \n"); } return key; } /* * MacInit */ SECStatus MacInit(PK11Context *ctx) { SECStatus rv = PK11_DigestBegin(ctx); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Compute MAC Failed : PK11_DigestBegin()\n"); } return rv; } /* * MacUpdate */ SECStatus MacUpdate(PK11Context *ctx, unsigned char *msg, unsigned int msgLen) { SECStatus rv = PK11_DigestOp(ctx, msg, msgLen); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Compute MAC Failed : DigestOp()\n"); } return rv; } /* * Finalize MACing */ SECStatus MacFinal(PK11Context *ctx, unsigned char *mac, unsigned int *macLen, unsigned int maxLen) { SECStatus rv = PK11_DigestFinal(ctx, mac, macLen, maxLen); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Compute MAC Failed : PK11_DigestFinal()\n"); } return SECSuccess; } /* * Compute Mac */ SECStatus ComputeMac(PK11Context *ctxmac, unsigned char *ptext, unsigned int ptextLen, unsigned char *mac, unsigned int *macLen, unsigned int maxLen) { SECStatus rv = MacInit(ctxmac); if (rv != SECSuccess) return rv; rv = MacUpdate(ctxmac, ptext, ptextLen); if (rv != SECSuccess) return rv; rv = MacFinal(ctxmac, mac, macLen, maxLen); return rv; } /* * WriteToHeaderFile */ SECStatus WriteToHeaderFile(const char *buf, unsigned int len, HeaderType type, PRFileDesc *outFile) { SECStatus rv; char header[40]; char trailer[40]; char *outString = NULL; switch (type) { case SYMKEY: strcpy(header, ENCKEY_HEADER); strcpy(trailer, ENCKEY_TRAILER); break; case MACKEY: strcpy(header, MACKEY_HEADER); strcpy(trailer, MACKEY_TRAILER); break; case IV: strcpy(header, IV_HEADER); strcpy(trailer, IV_TRAILER); break; case MAC: strcpy(header, MAC_HEADER); strcpy(trailer, MAC_TRAILER); break; case PAD: strcpy(header, PAD_HEADER); strcpy(trailer, PAD_TRAILER); break; } PR_fprintf(outFile, "%s\n", header); PrintAsHex(outFile, buf, len); PR_fprintf(outFile, "%s\n\n", trailer); return SECSuccess; } /* * Initialize for encryption or decryption - common code */ PK11Context * CryptInit(PK11SymKey *key, unsigned char *iv, unsigned int ivLen, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation) { SECItem ivItem = { siBuffer, iv, ivLen }; PK11Context *ctx = NULL; SECItem *secParam = PK11_ParamFromIV(CKM_AES_CBC, &ivItem); if (secParam == NULL) { PR_fprintf(PR_STDERR, "Crypt Failed : secParam NULL\n"); return NULL; } ctx = PK11_CreateContextBySymKey(CKM_AES_CBC, operation, key, secParam); if (ctx == NULL) { PR_fprintf(PR_STDERR, "Crypt Failed : can't create a context\n"); goto cleanup; } cleanup: if (secParam) { SECITEM_FreeItem(secParam, PR_TRUE); } return ctx; } /* * Common encryption and decryption code */ SECStatus Crypt(PK11Context *ctx, unsigned char *out, unsigned int *outLen, unsigned int maxOut, unsigned char *in, unsigned int inLen) { SECStatus rv; rv = PK11_CipherOp(ctx, out, outLen, maxOut, in, inLen); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Crypt Failed : PK11_CipherOp returned %d\n", rv); goto cleanup; } cleanup: if (rv != SECSuccess) { return rv; } return SECSuccess; } /* * Decrypt */ SECStatus Decrypt(PK11Context *ctx, unsigned char *out, unsigned int *outLen, unsigned int maxout, unsigned char *in, unsigned int inLen) { return Crypt(ctx, out, outLen, maxout, in, inLen); } /* * Encrypt */ SECStatus Encrypt(PK11Context* ctx, unsigned char *out, unsigned int *outLen, unsigned int maxout, unsigned char *in, unsigned int inLen) { return Crypt(ctx, out, outLen, maxout, in, inLen); } /* * EncryptInit */ PK11Context * EncryptInit(PK11SymKey *ek, unsigned char *iv, unsigned int ivLen, CK_MECHANISM_TYPE type) { return CryptInit(ek, iv, ivLen, type, CKA_ENCRYPT); } /* * DecryptInit */ PK11Context * DecryptInit(PK11SymKey *dk, unsigned char *iv, unsigned int ivLen, CK_MECHANISM_TYPE type) { return CryptInit(dk, iv, ivLen, type, CKA_DECRYPT); } /* * Read cryptographic parameters from the header file */ SECStatus ReadFromHeaderFile(const char *fileName, HeaderType type, SECItem *item, PRBool isHexData) { SECStatus rv; PRFileDesc* file; SECItem filedata; SECItem outbuf; unsigned char *nonbody; unsigned char *body; char header[40]; char trailer[40]; outbuf.type = siBuffer; file = PR_Open(fileName, PR_RDONLY, 0); if (!file) { PR_fprintf(PR_STDERR, "Failed to open %s\n", fileName); return SECFailure; } switch (type) { case SYMKEY: strcpy(header, ENCKEY_HEADER); strcpy(trailer, ENCKEY_TRAILER); break; case MACKEY: strcpy(header, MACKEY_HEADER); strcpy(trailer, MACKEY_TRAILER); break; case IV: strcpy(header, IV_HEADER); strcpy(trailer, IV_TRAILER); break; case MAC: strcpy(header, MAC_HEADER); strcpy(trailer, MAC_TRAILER); break; case PAD: strcpy(header, PAD_HEADER); strcpy(trailer, PAD_TRAILER); break; } rv = FileToItem(&filedata, file); nonbody = (char *)filedata.data; if (!nonbody) { PR_fprintf(PR_STDERR, "unable to read data from input file\n"); rv = SECFailure; goto cleanup; } /* check for headers and trailers and remove them */ if ((body = strstr(nonbody, header)) != NULL) { char *trail = NULL; nonbody = body; body = PORT_Strchr(body, '\n'); if (!body) body = PORT_Strchr(nonbody, '\r'); /* maybe this is a MAC file */ if (body) trail = strstr(++body, trailer); if (trail != NULL) { *trail = '\0'; } else { PR_fprintf(PR_STDERR, "input has header but no trailer\n"); PORT_Free(filedata.data); return SECFailure; } } else { body = nonbody; } cleanup: PR_Close(file); HexToBuf(body, item, isHexData); return SECSuccess; } /* * EncryptAndMac */ SECStatus EncryptAndMac(PRFileDesc *inFile, PRFileDesc *headerFile, PRFileDesc *encFile, PK11SymKey *ek, PK11SymKey *mk, unsigned char *iv, unsigned int ivLen, PRBool ascii) { SECStatus rv; unsigned char ptext[BLOCKSIZE]; unsigned int ptextLen; unsigned char mac[DIGESTSIZE]; unsigned int macLen; unsigned int nwritten; unsigned char encbuf[BLOCKSIZE]; unsigned int encbufLen; SECItem noParams = { siBuffer, NULL, 0 }; PK11Context *ctxmac = NULL; PK11Context *ctxenc = NULL; unsigned int pad[1]; SECItem padItem; unsigned int paddingLength; static unsigned int firstTime = 1; int j; ctxmac = PK11_CreateContextBySymKey(CKM_MD5_HMAC, CKA_SIGN, mk, &noParams); if (ctxmac == NULL) { PR_fprintf(PR_STDERR, "Can't create MAC context\n"); rv = SECFailure; goto cleanup; } rv = MacInit(ctxmac); if (rv != SECSuccess) { goto cleanup; } ctxenc = EncryptInit(ek, iv, ivLen, CKM_AES_CBC); /* read a buffer of plaintext from input file */ while ((ptextLen = PR_Read(inFile, ptext, sizeof(ptext))) > 0) { /* Encrypt using it using CBC, using previously created IV */ if (ptextLen != BLOCKSIZE) { paddingLength = BLOCKSIZE - ptextLen; for ( j=0; j < paddingLength; j++) { ptext[ptextLen+j] = (unsigned char)paddingLength; } ptextLen = BLOCKSIZE; } rv = Encrypt(ctxenc, encbuf, &encbufLen, sizeof(encbuf), ptext, ptextLen); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Encrypt Failure\n"); goto cleanup; } /* save the last block of ciphertext as the next IV */ iv = encbuf; ivLen = encbufLen; /* write the cipher text to intermediate file */ nwritten = PR_Write(encFile, encbuf, encbufLen); /*PR_Assert(nwritten == encbufLen);*/ rv = MacUpdate(ctxmac, ptext, ptextLen); } rv = MacFinal(ctxmac, mac, &macLen, DIGESTSIZE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "MacFinal Failure\n"); goto cleanup; } if (macLen == 0) { PR_fprintf(PR_STDERR, "Bad MAC length\n"); rv = SECFailure; goto cleanup; } WriteToHeaderFile(mac, macLen, MAC, headerFile); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Write MAC Failure\n"); goto cleanup; } pad[0] = paddingLength; padItem.type = siBuffer; padItem.data = (unsigned char *)pad; padItem.len = sizeof(pad[0]); WriteToHeaderFile(padItem.data, padItem.len, PAD, headerFile); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Write PAD Failure\n"); goto cleanup; } rv = SECSuccess; cleanup: if (ctxmac != NULL) { PK11_DestroyContext(ctxmac, PR_TRUE); } if (ctxenc != NULL) { PK11_DestroyContext(ctxenc, PR_TRUE); } return rv; } /* * Find the Key for the given mechanism */ PK11SymKey* FindKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism, SECItem *keyBuf, secuPWData *pwdata) { SECStatus rv; PK11SymKey *key; if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); if (slot) { PK11_FreeSlot(slot); } return NULL; } } key = PK11_FindFixedKey(slot, mechanism, keyBuf, 0); if (!key) { PR_fprintf(PR_STDERR, "PK11_FindFixedKey failed (err %d)\n", PR_GetError()); PK11_FreeSlot(slot); return NULL; } return key; } /* * Decrypt and Verify MAC */ SECStatus DecryptAndVerifyMac(const char* outFileName, char *encryptedFileName, SECItem *cItem, SECItem *macItem, PK11SymKey* ek, PK11SymKey* mk, SECItem *ivItem, SECItem *padItem) { SECStatus rv; PRFileDesc* inFile; PRFileDesc* outFile; unsigned char decbuf[64]; unsigned int decbufLen; unsigned char ptext[BLOCKSIZE]; unsigned int ptextLen = 0; unsigned char ctext[64]; unsigned int ctextLen; unsigned char newmac[DIGESTSIZE]; unsigned int newmacLen = 0; unsigned int newptextLen = 0; unsigned int count = 0; unsigned int temp = 0; unsigned int blockNumber = 0; SECItem noParams = { siBuffer, NULL, 0 }; PK11Context *ctxmac = NULL; PK11Context *ctxenc = NULL; unsigned char iv[BLOCKSIZE]; unsigned int ivLen = ivItem->len; unsigned int fileLength; unsigned int paddingLength; int j; memcpy(iv, ivItem->data, ivItem->len); paddingLength = (unsigned int)padItem->data[0]; ctxmac = PK11_CreateContextBySymKey(CKM_MD5_HMAC, CKA_SIGN, mk, &noParams); if (ctxmac == NULL) { PR_fprintf(PR_STDERR, "Can't create MAC context\n"); rv = SECFailure; goto cleanup; } /* Open the input file. */ inFile = PR_Open(encryptedFileName, PR_RDONLY , 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", encryptedFileName); return SECFailure; } /* Open the output file. */ outFile = PR_Open(outFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR , 00660); if (!outFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", outFileName); return SECFailure; } rv = MacInit(ctxmac); if (rv != SECSuccess) goto cleanup; ctxenc = DecryptInit(ek, iv, ivLen, CKM_AES_CBC); fileLength = FileSize(encryptedFileName); while ((ctextLen = PR_Read(inFile, ctext, sizeof(ctext))) > 0) { count += ctextLen; /* decrypt cipher text buffer using CBC and IV */ rv = Decrypt(ctxenc, decbuf, &decbufLen, sizeof(decbuf), ctext, ctextLen); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Decrypt Failure\n"); goto cleanup; } if (decbufLen == 0) break; rv = MacUpdate(ctxmac, decbuf, decbufLen); if (rv != SECSuccess) { goto cleanup; } if (count == fileLength) { decbufLen = decbufLen-paddingLength; } /* write the plain text to out file */ temp = PR_Write(outFile, decbuf, decbufLen); if (temp != decbufLen) { PR_fprintf(PR_STDERR, "write error\n"); rv = SECFailure; break; } /* save last block of ciphertext */ memcpy(iv, decbuf, decbufLen); ivLen = decbufLen; blockNumber++; } if (rv != SECSuccess) { goto cleanup; } rv = MacFinal(ctxmac, newmac, &newmacLen, sizeof(newmac)); if (rv != SECSuccess) { goto cleanup; } if (PORT_Memcmp(macItem->data, newmac, newmacLen) == 0) { rv = SECSuccess; } else { PR_fprintf(PR_STDERR, "Check MAC : Failure\n"); PR_fprintf(PR_STDERR, "Extracted : "); PrintAsHex(PR_STDERR, macItem->data, macItem->len); PR_fprintf(PR_STDERR, "Computed : "); PrintAsHex(PR_STDERR, newmac, newmacLen); rv = SECFailure; } cleanup: if (ctxmac) { PK11_DestroyContext(ctxmac, PR_TRUE); } if (ctxenc) { PK11_DestroyContext(ctxenc, PR_TRUE); } if (outFile) { PR_Close(outFile); } return rv; } /* * Gets IV and CKAIDS From Header File */ SECStatus GetIVandCKAIDSFromHeader(const char *cipherFileName, SECItem *ivItem, SECItem *encKeyItem, SECItem *macKeyItem) { SECStatus rv; /* open intermediate file, read in header, get IV and CKA_IDs of two keys * from it */ rv = ReadFromHeaderFile(cipherFileName, IV, ivItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve IV from cipher file\n"); goto cleanup; } rv = ReadFromHeaderFile(cipherFileName, SYMKEY, encKeyItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve AES CKA_ID from cipher file\n"); goto cleanup; } rv = ReadFromHeaderFile(cipherFileName, MACKEY, macKeyItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve MAC CKA_ID from cipher file\n"); goto cleanup; } cleanup: return rv; } /* * DecryptFile */ SECStatus DecryptFile(PK11SlotInfo *slot, const char *dbdir, const char *outFileName, const char *headerFileName, char *encryptedFileName, secuPWData *pwdata, PRBool ascii) { /* * The DB is open read only and we have authenticated to it * open input file, read in header, get IV and CKA_IDs of two keys from it * find those keys in the DB token * Open output file * loop until EOF(input): * read a buffer of ciphertext from input file, * Save last block of ciphertext * decrypt ciphertext buffer using CBC and IV, * compute and check MAC, then remove MAC from plaintext * replace IV with saved last block of ciphertext * write the plain text to output file * close files * report success */ SECStatus rv; SECItem ivItem; SECItem encKeyItem; SECItem macKeyItem; SECItem cipherItem; SECItem macItem; SECItem padItem; PK11SymKey *encKey = NULL; PK11SymKey *macKey = NULL; /* open intermediate file, read in header, get IV and CKA_IDs of two keys * from it */ rv = GetIVandCKAIDSFromHeader(headerFileName, &ivItem, &encKeyItem, &macKeyItem); if (rv != SECSuccess) { goto cleanup; } /* find those keys in the DB token */ encKey = FindKey(slot, CKM_AES_CBC, &encKeyItem, pwdata); if (encKey == NULL) { PR_fprintf(PR_STDERR, "Can't find the encryption key\n"); rv = SECFailure; goto cleanup; } /* CKM_MD5_HMAC or CKM_EXTRACT_KEY_FROM_KEY */ macKey = FindKey(slot, CKM_MD5_HMAC, &macKeyItem, pwdata); if (macKey == NULL) { rv = SECFailure; goto cleanup; } /* Read in the Mac into item from the intermediate file */ rv = ReadFromHeaderFile(headerFileName, MAC, &macItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve MAC from cipher file\n"); goto cleanup; } if (macItem.data == NULL) { PR_fprintf(PR_STDERR, "MAC has NULL data\n"); rv = SECFailure; goto cleanup; } if (macItem.len == 0) { PR_fprintf(PR_STDERR, "MAC has data has 0 length\n"); /*rv = SECFailure; goto cleanup;*/ } rv = ReadFromHeaderFile(headerFileName, PAD, &padItem, PR_TRUE); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not retrieve PAD detail from header file\n"); goto cleanup; } if (rv == SECSuccess) { /* Decrypt and Remove Mac */ rv = DecryptAndVerifyMac(outFileName, encryptedFileName, &cipherItem, &macItem, encKey, macKey, &ivItem, &padItem); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed while decrypting and removing MAC\n"); } } cleanup: if (slot) { PK11_FreeSlot(slot); } if (encKey) { PK11_FreeSymKey(encKey); } if (macKey) { PK11_FreeSymKey(macKey); } return rv; } /* * EncryptFile */ SECStatus EncryptFile(PK11SlotInfo *slot, const char *dbdir, const char *inFileName, const char *headerFileName, const char *encryptedFileName, const char *noiseFileName, secuPWData *pwdata, PRBool ascii) { /* * The DB is open for read/write and we have authenticated to it. * generate a symmetric AES key as a token object. * generate a second key to use for MACing, also a token object. * get their CKA_IDs * generate a random value to use as IV for AES CBC * open an input file and an output file, * write a header to the output that identifies the two keys by * their CKA_IDs, May include original file name and length. * loop until EOF(input) * read a buffer of plaintext from input file, * MAC it, append the MAC to the plaintext * encrypt it using CBC, using previously created IV, * store the last block of ciphertext as the new IV, * write the cipher text to intermediate file * close files * report success */ SECStatus rv; PRFileDesc *inFile; PRFileDesc *headerFile; PRFileDesc *encFile; unsigned char *encKeyId = (unsigned char *) "Encrypt Key"; unsigned char *macKeyId = (unsigned char *) "MAC Key"; SECItem encKeyID = { siAsciiString, encKeyId, PL_strlen(encKeyId) }; SECItem macKeyID = { siAsciiString, macKeyId, PL_strlen(macKeyId) }; SECItem encCKAID; SECItem macCKAID; unsigned char iv[BLOCKSIZE]; SECItem ivItem; PK11SymKey *encKey = NULL; PK11SymKey *macKey = NULL; SECItem temp; unsigned char c; /* generate a symmetric AES key as a token object. */ encKey = GenerateSYMKey(slot, CKM_AES_KEY_GEN, 128/8, &encKeyID, pwdata); if (encKey == NULL) { PR_fprintf(PR_STDERR, "GenerateSYMKey for AES returned NULL.\n"); rv = SECFailure; goto cleanup; } /* generate a second key to use for MACing, also a token object. */ macKey = GenerateSYMKey(slot, CKM_GENERIC_SECRET_KEY_GEN, 160/8, &macKeyID, pwdata); if (macKey == NULL) { PR_fprintf(PR_STDERR, "GenerateSYMKey for MACing returned NULL.\n"); rv = SECFailure; goto cleanup; } /* get the encrypt key CKA_ID */ rv = GatherCKA_ID(encKey, &encCKAID); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Error while wrapping encrypt key\n"); goto cleanup; } /* get the MAC key CKA_ID */ rv = GatherCKA_ID(macKey, &macCKAID); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Can't get the MAC key CKA_ID.\n"); goto cleanup; } if (noiseFileName) { rv = SeedFromNoiseFile(noiseFileName); if (rv != SECSuccess) { PORT_SetError(PR_END_OF_FILE_ERROR); return SECFailure; } rv = PK11_GenerateRandom(iv, BLOCKSIZE); if (rv != SECSuccess) { goto cleanup; } } else { /* generate a random value to use as IV for AES CBC */ GenerateRandom(iv, BLOCKSIZE); } headerFile = PR_Open(headerFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!headerFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", headerFileName); return SECFailure; } encFile = PR_Open(encryptedFileName, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 00660); if (!encFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for writing.\n", encryptedFileName); return SECFailure; } /* write to a header file the IV and the CKA_IDs * identifying the two keys */ ivItem.type = siBuffer; ivItem.data = iv; ivItem.len = BLOCKSIZE; rv = WriteToHeaderFile(iv, BLOCKSIZE, IV, headerFile); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Error writing IV to cipher file - %s\n", headerFileName); goto cleanup; } rv = WriteToHeaderFile(encCKAID.data, encCKAID.len, SYMKEY, headerFile); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Error writing AES CKA_ID to cipher file - %s\n", encryptedFileName); goto cleanup; } rv = WriteToHeaderFile(macCKAID.data, macCKAID.len, MACKEY, headerFile); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Error writing MAC CKA_ID to cipher file - %s\n", headerFileName); goto cleanup; } /* Open the input file. */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); return SECFailure; } /* Macing and Encryption */ if (rv == SECSuccess) { rv = EncryptAndMac(inFile, headerFile, encFile, encKey, macKey, ivItem.data, ivItem.len, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Failed : Macing and Encryption\n"); goto cleanup; } } cleanup: if (inFile) { PR_Close(inFile); } if (headerFile) { PR_Close(headerFile); } if (encFile) { PR_Close(encFile); } if (slot) { PK11_FreeSlot(slot); } if (encKey) { PK11_FreeSymKey(encKey); } if (macKey) { PK11_FreeSymKey(macKey); } return rv; } /* * This example illustrates basic encryption/decryption and MACing * Generates the encryption/mac keys and uses token for storing. * Encrypts the input file and appends MAC before storing in intermediate * header file. * Writes the CKA_IDs of the encryption keys into intermediate header file. * Reads the intermediate headerfile for CKA_IDs and encrypted * contents and decrypts into output file. */ int main(int argc, char **argv) { SECStatus rv; SECStatus rvShutdown; PK11SlotInfo *slot = NULL; PLOptState *optstate; PLOptStatus status; char headerFileName[50]; char encryptedFileName[50]; PRFileDesc *inFile; PRFileDesc *outFile; PRBool ascii = PR_FALSE; CommandType cmd = UNKNOWN; const char *command = NULL; const char *dbdir = NULL; const char *inFileName = NULL; const char *outFileName = NULL; const char *noiseFileName = NULL; secuPWData pwdata = { PW_NONE, 0 }; char * progName = strrchr(argv[0], '/'); progName = progName ? progName + 1 : argv[0]; /* Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, "c:d:i:o:f:p:z:a"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'a': ascii = PR_TRUE; break; case 'c': command = strdup(optstate->value); break; case 'd': dbdir = strdup(optstate->value); break; case 'f': pwdata.source = PW_FROMFILE; pwdata.data = strdup(optstate->value); break; case 'p': pwdata.source = PW_PLAINTEXT; pwdata.data = strdup(optstate->value); break; case 'i': inFileName = strdup(optstate->value); break; case 'o': outFileName = strdup(optstate->value); break; case 'z': noiseFileName = strdup(optstate->value); break; default: Usage(progName); break; } } PL_DestroyOptState(optstate); if (!command || !dbdir || !inFileName || !outFileName) Usage(progName); if (PL_strlen(command)==0) Usage(progName); cmd = command[0] == 'a' ? ENCRYPT : command[0] == 'b' ? DECRYPT : UNKNOWN; /* Open the input file. */ inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { PR_fprintf(PR_STDERR, "Unable to open \"%s\" for reading.\n", inFileName); return SECFailure; } PR_Close(inFile); /* For intermediate header file, choose filename as inputfile name with extension ".header" */ strcpy(headerFileName, inFileName); strcat(headerFileName, ".header"); /* For intermediate encrypted file, choose filename as inputfile name with extension ".enc" */ strcpy(encryptedFileName, inFileName); strcat(encryptedFileName, ".enc"); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); switch (cmd) { case ENCRYPT: /* If the intermediate header file already exists, delete it */ if (PR_Access(headerFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(headerFileName); } /* If the intermediate encrypted already exists, delete it */ if (PR_Access(encryptedFileName, PR_ACCESS_EXISTS) == PR_SUCCESS) { PR_Delete(encryptedFileName); } /* Open DB for read/write and authenticate to it. */ rv = NSS_InitReadWrite(dbdir); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "NSS_InitReadWrite Failed\n"); goto cleanup; } PK11_SetPasswordFunc(GetModulePassword); slot = PK11_GetInternalKeySlot(); if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); goto cleanup; } } rv = EncryptFile(slot, dbdir, inFileName, headerFileName, encryptedFileName, noiseFileName, &pwdata, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "EncryptFile : Failed\n"); return SECFailure; } break; case DECRYPT: /* Open DB read only, authenticate to it */ PK11_SetPasswordFunc(GetModulePassword); rv = NSS_Init(dbdir); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "NSS_Init Failed\n"); return SECFailure; } slot = PK11_GetInternalKeySlot(); if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "Could not authenticate to token %s.\n", PK11_GetTokenName(slot)); goto cleanup; } } rv = DecryptFile(slot, dbdir, outFileName, headerFileName, encryptedFileName, &pwdata, ascii); if (rv != SECSuccess) { PR_fprintf(PR_STDERR, "DecryptFile : Failed\n"); return SECFailure; } break; } cleanup: rvShutdown = NSS_Shutdown(); if (rvShutdown != SECSuccess) { PR_fprintf(PR_STDERR, "Failed : NSS_Shutdown()\n"); rv = SECFailure; } PR_Cleanup(); return rv; } \ No newline at end of file
diff --git a/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst b/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst
index 84ba6ed40..a1df68437 100644
--- a/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst
+++ b/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst
@@ -28,7 +28,7 @@ Utilities for nss samples
.. container::
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -179,7 +179,7 @@ Utilities for nss samples
.. container::
- .. code:: brush:
+ .. code:: c
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/doc/rst/legacy/nss_sources_building_testing/index.rst b/doc/rst/legacy/nss_sources_building_testing/index.rst
index bf342e4ce..bb92d9039 100644
--- a/doc/rst/legacy/nss_sources_building_testing/index.rst
+++ b/doc/rst/legacy/nss_sources_building_testing/index.rst
@@ -27,7 +27,7 @@ NSS sources building testing
read-only access is sufficient. Create a new directory on your computer that you will use as your
local work area, and run the following commands.
- .. code:: language-html
+ .. code:: sh
hg clone https://hg.mozilla.org/projects/nspr
hg clone https://hg.mozilla.org/projects/nss
diff --git a/doc/rst/legacy/reference/fc_initialize/index.rst b/doc/rst/legacy/reference/fc_initialize/index.rst
index c9a1a2ac0..5cc8d2f3f 100644
--- a/doc/rst/legacy/reference/fc_initialize/index.rst
+++ b/doc/rst/legacy/reference/fc_initialize/index.rst
@@ -17,7 +17,7 @@ FC_Initialize
.. container::
- .. code:: brush:
+ .. code::
CK_RV FC_Initialize(CK_VOID_PTR pInitArgs);
@@ -129,12 +129,3 @@ FC_Initialize
/* invoke FC_Initialize as pFunctionList->C_Initialize */
crv = pFunctionList->C_Initialize(&initArgs);
-
-.. _see_also:
-
-`See also <#see_also>`__
-------------------------
-
-.. container::
-
- - `FC_Finalize <https://developer.mozilla.org/en-US/docs/FC_Finalize>`__ \ No newline at end of file