summaryrefslogtreecommitdiffstats
path: root/pki/base/native-tools/src/tkstool
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/native-tools/src/tkstool')
-rw-r--r--pki/base/native-tools/src/tkstool/CMakeLists.txt45
-rw-r--r--pki/base/native-tools/src/tkstool/NSPRerrs.h161
-rw-r--r--pki/base/native-tools/src/tkstool/SECerrs.h523
-rw-r--r--pki/base/native-tools/src/tkstool/SSLerrs.h393
-rw-r--r--pki/base/native-tools/src/tkstool/delete.c111
-rw-r--r--pki/base/native-tools/src/tkstool/file.c518
-rw-r--r--pki/base/native-tools/src/tkstool/find.c81
-rw-r--r--pki/base/native-tools/src/tkstool/help.c499
-rw-r--r--pki/base/native-tools/src/tkstool/key.c1350
-rw-r--r--pki/base/native-tools/src/tkstool/list.c181
-rw-r--r--pki/base/native-tools/src/tkstool/modules.c63
-rw-r--r--pki/base/native-tools/src/tkstool/pppolicy.c306
-rw-r--r--pki/base/native-tools/src/tkstool/random.c173
-rw-r--r--pki/base/native-tools/src/tkstool/retrieve.c114
-rw-r--r--pki/base/native-tools/src/tkstool/secerror.c118
-rw-r--r--pki/base/native-tools/src/tkstool/secpwd.c213
-rw-r--r--pki/base/native-tools/src/tkstool/secutil.c3662
-rw-r--r--pki/base/native-tools/src/tkstool/secutil.h430
-rw-r--r--pki/base/native-tools/src/tkstool/tkstool.c2660
-rw-r--r--pki/base/native-tools/src/tkstool/tkstool.h321
-rw-r--r--pki/base/native-tools/src/tkstool/util.c640
-rw-r--r--pki/base/native-tools/src/tkstool/version.c49
22 files changed, 12611 insertions, 0 deletions
diff --git a/pki/base/native-tools/src/tkstool/CMakeLists.txt b/pki/base/native-tools/src/tkstool/CMakeLists.txt
new file mode 100644
index 000000000..8b07950eb
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/CMakeLists.txt
@@ -0,0 +1,45 @@
+project(tkstool C)
+
+set(TKSTOOL_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(TKSTOOL_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(tkstool_SRCS
+ delete.c
+ file.c
+ find.c
+ help.c
+ key.c
+ list.c
+ modules.c
+ pppolicy.c
+ random.c
+ retrieve.c
+ secerror.c
+ secpwd.c
+ secutil.c
+ tkstool.c
+ util.c
+ version.c
+)
+
+include_directories(${TKSTOOL_PRIVATE_INCLUDE_DIRS})
+
+add_executable(tkstool ${tkstool_SRCS})
+
+target_link_libraries(tkstool ${TKSTOOL_LINK_LIBRARIES})
+
+install(
+ TARGETS tkstool
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/pki/base/native-tools/src/tkstool/NSPRerrs.h b/pki/base/native-tools/src/tkstool/NSPRerrs.h
new file mode 100644
index 000000000..f0bc8b77e
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/NSPRerrs.h
@@ -0,0 +1,161 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/NSPRerrs.h
+ */
+
+/* General NSPR 2.0 errors */
+/* Caller must #include "prerror.h" */
+
+ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." )
+ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." )
+ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." )
+ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." )
+ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." )
+ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." )
+ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." )
+ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." )
+ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." )
+ER2( PR_IO_ERROR, "I/O function error." )
+ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." )
+ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." )
+ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." )
+ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." )
+ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." )
+ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." )
+ER2( PR_IS_CONNECTED_ERROR, "Already connected." )
+ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." )
+ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." )
+ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." )
+ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." )
+ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." )
+ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." )
+ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." )
+ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." )
+ER2( PR_FIND_SYMBOL_ERROR,
+"Symbol not found in any of the loaded dynamic libraries." )
+ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." )
+ER2( PR_DIRECTORY_LOOKUP_ERROR,
+"A directory lookup on a network address has failed." )
+ER2( PR_TPD_RANGE_ERROR,
+"Attempt to access a TPD key that is out of range." )
+ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." )
+ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." )
+ER2( PR_NOT_SOCKET_ERROR,
+"Network operation attempted on non-network file descriptor." )
+ER2( PR_NOT_TCP_SOCKET_ERROR,
+"TCP-specific function attempted on a non-TCP file descriptor." )
+ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." )
+ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." )
+ER2( PR_OPERATION_NOT_SUPPORTED_ERROR,
+"The requested operation is not supported by the platform." )
+ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR,
+"The host operating system does not support the protocol requested." )
+ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." )
+ER2( PR_BUFFER_OVERFLOW_ERROR,
+"The value requested is too large to be stored in the data buffer provided." )
+ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." )
+ER2( PR_RANGE_ERROR, "Unused." )
+ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." )
+ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." )
+ER2( PR_FILE_TOO_BIG_ERROR,
+"Write would result in file larger than the system allows." )
+ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." )
+ER2( PR_PIPE_ERROR, "Unused." )
+ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." )
+ER2( PR_IS_DIRECTORY_ERROR,
+"Cannot perform a normal file operation on a directory." )
+ER2( PR_LOOP_ERROR, "Symbolic link loop." )
+ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." )
+ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." )
+ER2( PR_NOT_DIRECTORY_ERROR,
+"Cannot perform directory operation on a normal file." )
+ER2( PR_READ_ONLY_FILESYSTEM_ERROR,
+"Cannot write to a read-only file system." )
+ER2( PR_DIRECTORY_NOT_EMPTY_ERROR,
+"Cannot delete a directory that is not empty." )
+ER2( PR_FILESYSTEM_MOUNTED_ERROR,
+"Cannot delete or rename a file object while the file system is busy." )
+ER2( PR_NOT_SAME_DEVICE_ERROR,
+"Cannot rename a file to a file system on another device." )
+ER2( PR_DIRECTORY_CORRUPTED_ERROR,
+"The directory object in the file system is corrupted." )
+ER2( PR_FILE_EXISTS_ERROR,
+"Cannot create or rename a filename that already exists." )
+ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR,
+"Directory is full. No additional filenames may be added." )
+ER2( PR_INVALID_DEVICE_STATE_ERROR,
+"The required device was in an invalid state." )
+ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." )
+ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." )
+ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." )
+ER2( PR_FILE_SEEK_ERROR, "Seek error." )
+ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." )
+ER2( PR_IN_PROGRESS_ERROR,
+"Operation is still in progress (probably a non-blocking connect)." )
+ER2( PR_ALREADY_INITIATED_ERROR,
+"Operation has already been initiated (probably a non-blocking connect)." )
+
+#ifdef PR_GROUP_EMPTY_ERROR
+ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." )
+#endif
+
+#ifdef PR_INVALID_STATE_ERROR
+ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." )
+#endif
+
+#ifdef PR_NETWORK_DOWN_ERROR
+ER2( PR_NETWORK_DOWN_ERROR, "Network is down." )
+#endif
+
+#ifdef PR_SOCKET_SHUTDOWN_ERROR
+ER2( PR_SOCKET_SHUTDOWN_ERROR, "The socket was previously shut down." )
+#endif
+
+#ifdef PR_CONNECT_ABORTED_ERROR
+ER2( PR_CONNECT_ABORTED_ERROR, "TCP Connection aborted." )
+#endif
+
+#ifdef PR_HOST_UNREACHABLE_ERROR
+ER2( PR_HOST_UNREACHABLE_ERROR, "Host is unreachable." )
+#endif
+
+/* always last */
+ER2( PR_MAX_ERROR, "Placeholder for the end of the list" )
diff --git a/pki/base/native-tools/src/tkstool/SECerrs.h b/pki/base/native-tools/src/tkstool/SECerrs.h
new file mode 100644
index 000000000..55858b98f
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/SECerrs.h
@@ -0,0 +1,523 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/SECerrs.h
+ */
+
+/* General security error codes */
+/* Caller must #include "secerr.h" */
+
+ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
+"An I/O error occurred during security authorization.")
+
+ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
+"security library failure.")
+
+ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
+"security library: received bad data.")
+
+ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
+"security library: output length error.")
+
+ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
+"security library has experienced an input length error.")
+
+ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
+"security library: invalid arguments.")
+
+ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
+"security library: invalid algorithm.")
+
+ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
+"security library: invalid AVA.")
+
+ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
+"Improperly formatted time string.")
+
+ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9,
+"security library: improperly formatted DER-encoded message.")
+
+ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10,
+"Peer's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11,
+"Peer's Certificate has expired.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12,
+"Peer's Certificate has been revoked.")
+
+ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13,
+"Peer's Certificate issuer is not recognized.")
+
+ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14,
+"Peer's public key is invalid.")
+
+ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15,
+"The security password entered is incorrect.")
+
+ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16,
+"New password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17,
+"security library: no nodelock.")
+
+ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18,
+"security library: bad database.")
+
+ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19,
+"security library: memory allocation failure.")
+
+ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20,
+"Peer's certificate issuer has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21,
+"Peer's certificate has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22),
+"Certificate already exists in your database.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23),
+"Downloaded certificate's name duplicates one already in your database.")
+
+ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24),
+"Error adding certificate to database.")
+
+ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25),
+"Error refiling the key for this certificate.")
+
+ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26),
+"The private key for this certificate cannot be found in key database")
+
+ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27),
+"This certificate is valid.")
+
+ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28),
+"This certificate is not valid.")
+
+ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29),
+"Cert Library: No Response")
+
+ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30),
+"The certificate issuer's certificate has expired. Check your system date and time.")
+
+ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31),
+"The CRL for the certificate's issuer has expired. Update it or check your system data and time.")
+
+ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32),
+"The CRL for the certificate's issuer has an invalid signature.")
+
+ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33),
+"New CRL has an invalid format.")
+
+ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34),
+"Certificate extension value is invalid.")
+
+ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35),
+"Certificate extension not found.")
+
+ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36),
+"Issuer certificate is invalid.")
+
+ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37),
+"Certificate path length constraint is invalid.")
+
+ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38),
+"Certificate usages field is invalid.")
+
+ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39),
+"**Internal ONLY module**")
+
+ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40),
+"The key does not support the requested operation.")
+
+ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41),
+"Certificate contains unknown critical extension.")
+
+ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42),
+"New CRL is not later than the current one.")
+
+ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43),
+"Not encrypted or signed: you do not yet have an email certificate.")
+
+ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44),
+"Not encrypted: you do not have certificates for each of the recipients.")
+
+ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45),
+"Cannot decrypt: you are not a recipient, or matching certificate and \
+private key not found.")
+
+ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46),
+"Cannot decrypt: key encryption algorithm does not match your certificate.")
+
+ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47),
+"Signature verification failed: no signer found, too many signers found, \
+or improper or corrupted data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48),
+"Unsupported or unknown key algorithm.")
+
+ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49),
+"Cannot decrypt: encrypted using a disallowed algorithm or key size.")
+
+
+/* Fortezza Alerts */
+ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50),
+"Fortezza card has not been properly initialized. \
+Please remove it and return it to your issuer.")
+
+ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51),
+"No Fortezza cards Found")
+
+ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52),
+"No Fortezza card selected")
+
+ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53),
+"Please select a personality to get more info on")
+
+ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54),
+"Personality not found")
+
+ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55),
+"No more information on that Personality")
+
+ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56),
+"Invalid Pin")
+
+ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57),
+"Couldn't initialize Fortezza personalities.")
+/* end fortezza alerts. */
+
+ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58),
+"No KRL for this site's certificate has been found.")
+
+ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59),
+"The KRL for this site's certificate has expired.")
+
+ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60),
+"The KRL for this site's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61),
+"The key for this site's certificate has been revoked.")
+
+ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62),
+"New KRL has an invalid format.")
+
+ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63),
+"security library: need random data.")
+
+ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64),
+"security library: no security module can perform the requested operation.")
+
+ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65),
+"The security card or token does not exist, needs to be initialized, or has been removed.")
+
+ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66),
+"security library: read-only database.")
+
+ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67),
+"No slot or token was selected.")
+
+ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68),
+"A certificate with the same nickname already exists.")
+
+ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69),
+"A key with the same nickname already exists.")
+
+ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70),
+"error while creating safe object")
+
+ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71),
+"error while creating baggage object")
+
+ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72),
+"Couldn't remove the principal")
+
+ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73),
+"Couldn't delete the privilege")
+
+ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74),
+"This principal doesn't have a certificate")
+
+ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75),
+"Required algorithm is not allowed.")
+
+ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76),
+"Error attempting to export certificates.")
+
+ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77),
+"Error attempting to import certificates.")
+
+ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78),
+"Unable to import. Decoding error. File not valid.")
+
+ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79),
+"Unable to import. Invalid MAC. Incorrect password or corrupt file.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80),
+"Unable to import. MAC algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81),
+"Unable to import. Only password integrity and privacy modes supported.")
+
+ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82),
+"Unable to import. File structure is corrupt.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83),
+"Unable to import. Encryption algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84),
+"Unable to import. File version not supported.")
+
+ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85),
+"Unable to import. Incorrect privacy password.")
+
+ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86),
+"Unable to import. Same nickname already exists in database.")
+
+ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87),
+"The user pressed cancel.")
+
+ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88),
+"Not imported, already in database.")
+
+ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89),
+"Message not sent.")
+
+ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90),
+"Certificate key usage inadequate for attempted operation.")
+
+ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91),
+"Certificate type not approved for application.")
+
+ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92),
+"Address in signing certificate does not match address in message headers.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93),
+"Unable to import. Error attempting to import private key.")
+
+ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94),
+"Unable to import. Error attempting to import certificate chain.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95),
+"Unable to export. Unable to locate certificate or key by nickname.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96),
+"Unable to export. Private Key could not be located and exported.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97),
+"Unable to export. Unable to write the export file.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98),
+"Unable to import. Unable to read the import file.")
+
+ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99),
+"Unable to export. Key database corrupt or deleted.")
+
+ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100),
+"Unable to generate public/private key pair.")
+
+ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101),
+"Password entered is invalid. Please pick a different one.")
+
+ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102),
+"Old password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103),
+"Certificate nickname already in use.")
+
+ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104),
+"Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
+
+ER3(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, (SEC_ERROR_BASE + 105),
+"A sensitive key cannot be moved to the slot where it is needed.")
+
+ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106),
+"Invalid module name.")
+
+ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107),
+"Invalid module path/filename")
+
+ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108),
+"Unable to add module")
+
+ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109),
+"Unable to delete module")
+
+ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110),
+"New KRL is not later than the current one.")
+
+ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111),
+"New CKL has different issuer than current CKL. Delete current CKL.")
+
+ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
+"The Certifying Authority for this certificate is not permitted to issue a \
+certificate with this name.")
+
+ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113),
+"The key revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114),
+"The certificate revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115),
+"The requested certificate could not be found.")
+
+ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116),
+"The signer's certificate could not be found.")
+
+ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117),
+"The location for the certificate status server has invalid format.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118),
+"The OCSP response cannot be fully decoded; it is of an unknown type.")
+
+ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119),
+"The OCSP server returned unexpected/invalid HTTP data.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120),
+"The OCSP server found the request to be corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121),
+"The OCSP server experienced an internal error.")
+
+ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122),
+"The OCSP server suggests trying again later.")
+
+ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123),
+"The OCSP server requires a signature on this request.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124),
+"The OCSP server has refused this request as unauthorized.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125),
+"The OCSP server returned an unrecognizable status.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126),
+"The OCSP server has no status for the certificate.")
+
+ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127),
+"You must enable OCSP before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128),
+"You must set the OCSP default responder before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129),
+"The response from the OCSP server was corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130),
+"The signer of the OCSP response is not authorized to give status for \
+this certificate.")
+
+ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131),
+"The OCSP response is not yet valid (contains a date in the future).")
+
+ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132),
+"The OCSP response contains out-of-date information.")
+
+ER3(SEC_ERROR_DIGEST_NOT_FOUND, (SEC_ERROR_BASE + 133),
+"The CMS or PKCS #7 Digest was not found in signed message.")
+
+ER3(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, (SEC_ERROR_BASE + 134),
+"The CMS or PKCS #7 Message type is unsupported.")
+
+ER3(SEC_ERROR_MODULE_STUCK, (SEC_ERROR_BASE + 135),
+"PKCS #11 module could not be removed because it is still in use.")
+
+ER3(SEC_ERROR_BAD_TEMPLATE, (SEC_ERROR_BASE + 136),
+"Could not decode ASN.1 data. Specified template was invalid.")
+
+ER3(SEC_ERROR_CRL_NOT_FOUND, (SEC_ERROR_BASE + 137),
+"No matching CRL was found.")
+
+ER3(SEC_ERROR_REUSED_ISSUER_AND_SERIAL, (SEC_ERROR_BASE + 138),
+"You are attempting to import a cert with the same issuer/serial as \
+an existing cert, but that is not the same cert.")
+
+ER3(SEC_ERROR_BUSY, (SEC_ERROR_BASE + 139),
+"NSS could not shutdown. Objects are still in use.")
+
+ER3(SEC_ERROR_EXTRA_INPUT, (SEC_ERROR_BASE + 140),
+"DER-encoded message contained extra unused data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, (SEC_ERROR_BASE + 141),
+"Unsupported elliptic curve.")
+
+ER3(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, (SEC_ERROR_BASE + 142),
+"Unsupported elliptic curve point form.")
+
+ER3(SEC_ERROR_UNRECOGNIZED_OID, (SEC_ERROR_BASE + 143),
+"Unrecognized Object IDentifier.")
+
+ER3(SEC_ERROR_OCSP_INVALID_SIGNING_CERT, (SEC_ERROR_BASE + 144),
+"Invalid OCSP signing certificate in OCSP response.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE_CRL, (SEC_ERROR_BASE + 145),
+"Certificate is revoked in issuer's certificate revocation list.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE_OCSP, (SEC_ERROR_BASE + 146),
+"Issuer's OCSP responder reports certificate is revoked.")
+
+ER3(SEC_ERROR_CRL_INVALID_VERSION, (SEC_ERROR_BASE + 147),
+"Issuer's Certificate Revocation List has an unknown version number.")
+
+ER3(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 148),
+"Issuer's V1 Certificate Revocation List has a critical extension.")
+
+ER3(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 149),
+"Issuer's V2 Certificate Revocation List has an unknown critical extension.")
+
+ER3(SEC_ERROR_UNKNOWN_OBJECT_TYPE, (SEC_ERROR_BASE + 150),
+"Unknown object type specified.")
+
+ER3(SEC_ERROR_INCOMPATIBLE_PKCS11, (SEC_ERROR_BASE + 151),
+"PKCS #11 driver violates the spec in an incompatible way.")
+
+ER3(SEC_ERROR_NO_EVENT, (SEC_ERROR_BASE + 152),
+"No new slot event is available at this time.")
+
+ER3(SEC_ERROR_CRL_ALREADY_EXISTS, (SEC_ERROR_BASE + 153),
+"CRL already exists.")
+
+ER3(SEC_ERROR_NOT_INITIALIZED, (SEC_ERROR_BASE + 154),
+"NSS is not initialized.")
+
+ER3(SEC_ERROR_TOKEN_NOT_LOGGED_IN, (SEC_ERROR_BASE + 155),
+"The operation failed because the PKCS#11 token is not logged in.")
+
diff --git a/pki/base/native-tools/src/tkstool/SSLerrs.h b/pki/base/native-tools/src/tkstool/SSLerrs.h
new file mode 100644
index 000000000..d6ec13b47
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/SSLerrs.h
@@ -0,0 +1,393 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/SSLerrs.h
+ */
+
+/* SSL-specific security error codes */
+/* caller must include "sslerr.h" */
+
+ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
+"Unable to communicate securely. Peer does not support high-grade encryption.")
+
+ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
+"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
+
+ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
+"Cannot communicate securely with peer: no common encryption algorithm(s).")
+
+ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
+"Unable to find the certificate or key necessary for authentication.")
+
+ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
+"Unable to communicate securely with peer: peers's certificate was rejected.")
+
+/* unused (SSL_ERROR_BASE + 5),*/
+
+ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
+"The server has encountered bad data from the client.")
+
+ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
+"The client has encountered bad data from the server.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
+"Unsupported certificate type.")
+
+ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
+"Peer using unsupported version of security protocol.")
+
+/* unused (SSL_ERROR_BASE + 10),*/
+
+ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
+"Client authentication failed: private key in key database does not match public key in certificate database.")
+
+ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
+"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
+
+/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
+ defined in sslerr.h
+*/
+
+ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
+"Peer only supports SSL version 2, which is locally disabled.")
+
+
+ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
+"SSL received a record with an incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
+"SSL peer reports incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
+"SSL peer cannot verify your certificate.")
+
+ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
+"SSL peer rejected your certificate as revoked.")
+
+ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
+"SSL peer rejected your certificate as expired.")
+
+ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
+"Cannot connect: SSL is disabled.")
+
+ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
+"Cannot connect: SSL peer is in another FORTEZZA domain.")
+
+
+ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
+"An unknown SSL cipher suite has been requested.")
+
+ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
+"No cipher suites are present and enabled in this program.")
+
+ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
+"SSL received a record with bad block padding.")
+
+ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
+"SSL received a record that exceeded the maximum permissible length.")
+
+ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
+"SSL attempted to send a record that exceeded the maximum permissible length.")
+
+/*
+ * Received a malformed (too long or short or invalid content) SSL handshake.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
+"SSL received a malformed Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
+"SSL received a malformed Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
+"SSL received a malformed Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
+"SSL received a malformed Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
+"SSL received a malformed Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
+"SSL received a malformed Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
+"SSL received a malformed Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
+"SSL received a malformed Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
+"SSL received a malformed Client Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
+"SSL received a malformed Finished handshake message.")
+
+/*
+ * Received a malformed (too long or short) SSL record.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
+"SSL received a malformed Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
+"SSL received a malformed Alert record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
+"SSL received a malformed Handshake record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
+"SSL received a malformed Application Data record.")
+
+/*
+ * Received an SSL handshake that was inappropriate for the state we're in.
+ * E.g. Server received message from server, or wrong state in state machine.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
+"SSL received an unexpected Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
+"SSL received an unexpected Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
+"SSL received an unexpected Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
+"SSL received an unexpected Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
+"SSL received an unexpected Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
+"SSL received an unexpected Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
+"SSL received an unexpected Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
+"SSL received an unexpected Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
+"SSL received an unexpected Cllient Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
+"SSL received an unexpected Finished handshake message.")
+
+/*
+ * Received an SSL record that was inappropriate for the state we're in.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
+"SSL received an unexpected Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
+"SSL received an unexpected Alert record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
+"SSL received an unexpected Handshake record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
+"SSL received an unexpected Application Data record.")
+
+/*
+ * Received record/message with unknown discriminant.
+ */
+ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
+"SSL received a record with an unknown content type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
+"SSL received a handshake message with an unknown message type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
+"SSL received an alert record with an unknown alert description.")
+
+/*
+ * Received an alert reporting what we did wrong. (more alerts above)
+ */
+ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
+"SSL peer has closed this connection.")
+
+ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
+"SSL peer was not expecting a handshake message it received.")
+
+ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
+"SSL peer was unable to succesfully decompress an SSL record it received.")
+
+ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
+"SSL peer was unable to negotiate an acceptable set of security parameters.")
+
+ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
+"SSL peer rejected a handshake message for unacceptable content.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
+"SSL peer does not support certificates of the type it received.")
+
+ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
+"SSL peer had some unspecified issue with the certificate it received.")
+
+
+ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
+"SSL experienced a failure of its random number generator.")
+
+ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
+"Unable to digitally sign data required to verify your certificate.")
+
+ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
+"SSL was unable to extract the public key from the peer's certificate.")
+
+ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
+"Unspecified failure while processing SSL Server Key Exchange handshake.")
+
+ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
+"Unspecified failure while processing SSL Client Key Exchange handshake.")
+
+ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
+"Bulk data encryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
+"Bulk data decryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
+"Attempt to write encrypted data to underlying socket failed.")
+
+ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
+"MD5 digest function failed.")
+
+ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
+"SHA-1 digest function failed.")
+
+ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
+"MAC computation failed.")
+
+ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
+"Failure to create Symmetric Key context.")
+
+ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
+"Failure to unwrap the Symmetric key in Client Key Exchange message.")
+
+ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
+"SSL Server attempted to use domestic-grade public key with export cipher suite.")
+
+ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
+"PKCS11 code failed to translate an IV into a param.")
+
+ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
+"Failed to initialize the selected cipher suite.")
+
+ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
+"Client failed to generate session keys for SSL session.")
+
+ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
+"Server has no key for the attempted key exchange algorithm.")
+
+ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
+"PKCS#11 token was inserted or removed while operation was in progress.")
+
+ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
+"No PKCS#11 token could be found to do a required operation.")
+
+ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
+"Cannot communicate securely with peer: no common compression algorithm(s).")
+
+ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
+"Cannot initiate another SSL handshake until current handshake is complete.")
+
+ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
+"Received incorrect handshakes hash values from peer.")
+
+ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
+"The certificate provided cannot be used with the selected key exchange algorithm.")
+
+ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89),
+"No certificate authority is trusted for SSL client authentication.")
+
+ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90),
+"Client's SSL session ID not found in server's session cache.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91),
+"Peer was unable to decrypt an SSL record it received.")
+
+ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92),
+"Peer received an SSL record that was longer than is permitted.")
+
+ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93),
+"Peer does not recognize and trust the CA that issued your certificate.")
+
+ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94),
+"Peer received a valid certificate, but access was denied.")
+
+ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95),
+"Peer could not decode an SSL handshake message.")
+
+ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96),
+"Peer reports failure of signature verification or key exchange.")
+
+ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97),
+"Peer reports negotiation not in compliance with export regulations.")
+
+ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98),
+"Peer reports incompatible or unsupported protocol version.")
+
+ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99),
+"Server requires ciphers more secure than those supported by client.")
+
+ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100),
+"Peer reports it experienced an internal error.")
+
+ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101),
+"Peer user canceled handshake.")
+
+ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102),
+"Peer does not permit renegotiation of SSL security parameters.")
+
+ER3(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED , (SSL_ERROR_BASE + 103),
+"SSL server cache not configured and not disabled for this socket.")
+
+ER3(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT , (SSL_ERROR_BASE + 104),
+"SSL peer does not support requested TLS hello extension.")
+
+ER3(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT , (SSL_ERROR_BASE + 105),
+"SSL peer could not obtain your certificate from the supplied URL.")
+
+ER3(SSL_ERROR_UNRECOGNIZED_NAME_ALERT , (SSL_ERROR_BASE + 106),
+"SSL peer has no certificate for the requested DNS name.")
+
+ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT , (SSL_ERROR_BASE + 107),
+"SSL peer was unable to get an OCSP response for its certificate.")
+
+ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT , (SSL_ERROR_BASE + 108),
+"SSL peer reported bad certificate hash value.")
diff --git a/pki/base/native-tools/src/tkstool/delete.c b/pki/base/native-tools/src/tkstool/delete.c
new file mode 100644
index 000000000..f40e66d16
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/delete.c
@@ -0,0 +1,111 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+static SECStatus
+DeleteKey( char *keyname,
+ PK11SymKey *key )
+{
+ char *name = NULL;
+ SECStatus rv = SECFailure;
+
+ name = PK11_GetSymKeyNickname( /* symmetric key */ key );
+ if( name == NULL ) {
+ name = PORT_Strdup( "< orphaned >" );
+ }
+
+ /* Delete this key ONLY if its name is the specified keyname */
+ /* */
+ /* NOTE: If duplicate keys are allowed to be added to an */
+ /* individual token, this function will delete */
+ /* EVERY key named by the specified keyname; */
+ /* therefore, MORE than ONE key may be DELETED from */
+ /* the specified token!!! */
+ if( PL_strcmp( keyname, name ) == 0 ) {
+ rv = PK11_DeleteTokenSymKey( /* symmetric key */ key );
+ }
+
+ PORT_Free( name );
+
+ return rv;
+}
+
+
+SECStatus
+TKS_DeleteKeys( char *progName,
+ PK11SlotInfo *slot,
+ char *keyname,
+ secuPWData *pwdata )
+{
+ int count = 0;
+ int keys_deleted = 0;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ SECStatus rvDelete = SECFailure;
+ SECStatus rv;
+
+ if( PK11_NeedLogin( /* slot */ slot ) ) {
+ PK11_Authenticate(
+ /* slot */ slot,
+ /* load certs */ PR_TRUE,
+ /* wincx */ pwdata );
+ }
+
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot(
+ /* slot */ slot,
+ /* nickname */ NULL,
+ /* wincx */ ( void *) pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while( symKey != NULL ) {
+ rvDelete = DeleteKey( keyname,
+ symKey );
+ if( rvDelete != SECFailure ) {
+ keys_deleted++;
+ }
+
+ nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
+ PK11_FreeSymKey( /* symmetric key */ symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ if( keys_deleted == 0 ) {
+ PR_fprintf( PR_STDOUT,
+ "\t%s: no key(s) called \"%s\" could be deleted\n",
+ progName,
+ keyname );
+
+ rv = SECFailure;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "%s: %d key(s) called \"%s\" were deleted\n",
+ progName,
+ keys_deleted,
+ keyname );
+
+ rv = SECSuccess;
+ }
+
+ return rv;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/file.c b/pki/base/native-tools/src/tkstool/file.c
new file mode 100644
index 000000000..d757225fc
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/file.c
@@ -0,0 +1,518 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+SECStatus
+TKS_ReadInputFileIntoSECItem( char *input,
+ char *hexInternalKeyKCV,
+ int hexInternalKeyKCVLength,
+ char *wrappedKeyName,
+ SECItem *wrappedKey )
+{
+ char buf[1];
+ PRFileDesc *fd = NULL;
+ PRInt32 c = 0;
+ PRInt32 k = 0;
+ PRInt32 count = 0;
+ PRIntn firstCount = 0;
+ PRIntn secondCount = 0;
+ PRIntn thirdCount = 0;
+ PRIntn i = 0;
+ SECItem hexWrappedKey = { siBuffer,
+ NULL,
+ 0 };
+ SECStatus status = SECFailure;
+
+ /* Create a clean new hex display buffer for this wrapped key */
+ hexWrappedKey.type = ( SECItemType ) siBuffer;
+ hexWrappedKey.len = ( ( wrappedKey->len * 2 ) + 1 );
+ hexWrappedKey.data = ( unsigned char * )
+ PORT_ZAlloc( hexWrappedKey.len );
+ if( hexWrappedKey.data == NULL ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* open the input file read-only */
+ fd = PR_OpenFile( input, PR_RDONLY, 0666 );
+ if( !fd ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* read in the wrapped key */
+ while( c < HEX_WRAPPED_KEY_LENGTH ) {
+ /* read in the next byte */
+ count = PR_Read( fd, buf, 1 );
+
+ /* check for EOF */
+ if( count > 0 ) {
+ /* save acceptable hex characters */
+ /* silently throw anything else away */
+ switch( *buf ) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* acceptable character; save it as typed */
+ hexWrappedKey.data[c] = buf[0];
+ break;
+ case 'A':
+ case 'a':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'A';
+ break;
+ case 'B':
+ case 'b':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'B';
+ break;
+ case 'C':
+ case 'c':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'C';
+ break;
+ case 'D':
+ case 'd':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'D';
+ break;
+ case 'E':
+ case 'e':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'E';
+ break;
+ case 'F':
+ case 'f':
+ /* acceptable character; save uppercase version */
+ hexWrappedKey.data[c] = 'F';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+
+ /* increment the number of wrapped key bytes read */
+ c++;
+ }
+ }
+
+ /* insure that the wrapped key was completely obtained */
+ if( c != HEX_WRAPPED_KEY_LENGTH ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* Convert these wrapped key hex digits */
+ /* into the data portion of a SECItem */
+ TKS_ConvertStringOfHexCharactersIntoBitStream( ( char * ) hexWrappedKey.data,
+ ( hexWrappedKey.len - 1 ),
+ wrappedKey->data );
+
+ /* read in the wrapped key KCV */
+ while( k < HEX_WRAPPED_KEY_KCV_LENGTH ) {
+ count = PR_Read( fd, buf, 1 );
+
+ if( count > 0 ) {
+ /* save acceptable hex characters; silently */
+ /* throw anything else away */
+ switch( *buf ) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* acceptable character; save it as typed */
+ hexInternalKeyKCV[k] = buf[0];
+ break;
+ case 'A':
+ case 'a':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'A';
+ break;
+ case 'B':
+ case 'b':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'B';
+ break;
+ case 'C':
+ case 'c':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'C';
+ break;
+ case 'D':
+ case 'd':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'D';
+ break;
+ case 'E':
+ case 'e':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'E';
+ break;
+ case 'F':
+ case 'f':
+ /* acceptable character; save uppercase version */
+ hexInternalKeyKCV[k] = 'F';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+
+ /* increment the number of key KCV bytes read */
+ k++;
+ }
+ }
+
+ /* insure that the wrapped key KCV was completely obtained */
+ if( k != HEX_WRAPPED_KEY_KCV_LENGTH ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* For convenience, display the read-in wrapped key */
+ /* and its associated KCV to the user. */
+ if( hexWrappedKey.data != NULL ) {
+ /* Display this final wrapped key */
+ if( ( hexWrappedKey.len - 1 ) !=
+ HEX_WRAPPED_KEY_LENGTH ) {
+ /* invalid key length */
+ PR_fprintf( PR_STDERR,
+ "ERROR: Invalid data length of %d bytes!\n\n\n",
+ hexWrappedKey.len );
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ } else {
+ /* Print wrapped data blob */
+ PR_fprintf( PR_STDOUT,
+ "\n wrapped data: " );
+
+ /* Print first DES_LENGTH bytes */
+ if( wrappedKey->len == ( 3 * DES_LENGTH ) ) {
+ firstCount = ( ( hexWrappedKey.len - 1 ) / 3 );
+ } else {
+ firstCount = ( ( hexWrappedKey.len - 1 ) / 2 );
+ }
+ for( i = 0; i < firstCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+
+ /* Print appropriate padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+
+ /* Print second DES_LENGTH bytes */
+ secondCount = firstCount * 2;
+ for( i = firstCount; i < secondCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+
+ /* print out last 8 bytes of triple-DES keys */
+ if( wrappedKey->len == ( 3 * DES_LENGTH ) ) {
+ /* Print appropriate padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+
+ /* Print third DES_LENGTH bytes */
+ thirdCount = hexWrappedKey.len;
+ for( i = secondCount; i < thirdCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+ }
+
+ /* Print appropriate vertical spacing */
+ PR_fprintf( PR_STDOUT, "\n\n\n" );
+ }
+ }
+
+ if( hexInternalKeyKCV != NULL ) {
+ /* Display this final wrapped key's KCV */
+ if( ( hexInternalKeyKCVLength - 1 ) !=
+ HEX_WRAPPED_KEY_KCV_LENGTH ) {
+ /* invalid key length */
+ PR_fprintf( PR_STDERR,
+ "ERROR: Invalid key KCV length "
+ "of %d bytes!\n\n\n",
+ hexInternalKeyKCVLength );
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ " master key KCV: "
+ "%c%c%c%c %c%c%c%c\n (pre-computed KCV of the "
+ "master key residing inside the wrapped data)\n\n\n",
+ hexInternalKeyKCV[0],
+ hexInternalKeyKCV[1],
+ hexInternalKeyKCV[2],
+ hexInternalKeyKCV[3],
+ hexInternalKeyKCV[4],
+ hexInternalKeyKCV[5],
+ hexInternalKeyKCV[6],
+ hexInternalKeyKCV[7] );
+ }
+ }
+
+ /* close the input file */
+ PR_Close( fd );
+
+ status = SECSuccess;
+
+destroyHexWrappedKey:
+ /* Destroy the hex wrapped key */
+ if( hexWrappedKey.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexWrappedKey.data,
+ hexWrappedKey.len );
+ hexWrappedKey.data = NULL;
+ hexWrappedKey.len = 0;
+ }
+
+ return status;
+}
+
+
+SECStatus
+TKS_WriteSECItemIntoOutputFile( SECItem *wrappedKey,
+ char *wrappedKeyName,
+ char *hexInternalKeyKCV,
+ int hexInternalKeyKCVLength,
+ char *output )
+{
+ PRFileDesc *fd = NULL;
+ PRInt32 count = 0;
+ PRInt32 r = 0;
+ PRIntn firstCount = 0;
+ PRIntn secondCount = 0;
+ PRIntn thirdCount = 0;
+ PRIntn i = 0;
+ SECItem hexWrappedKey = { siBuffer,
+ NULL,
+ 0 };
+ SECStatus status = SECFailure;
+
+ /* Create a clean new hex display buffer for this wrapped key */
+ hexWrappedKey.type = ( SECItemType ) siBuffer;
+ hexWrappedKey.len = ( ( wrappedKey->len * 2 ) + 1 );
+ hexWrappedKey.data = ( unsigned char * )
+ PORT_ZAlloc( hexWrappedKey.len );
+ if( hexWrappedKey.data == NULL ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* Convert this wrapped key into hex digits */
+ TKS_StringToHex( ( PRUint8 * ) wrappedKey->data,
+ ( PRIntn ) wrappedKey->len,
+ ( PRUint8 * ) hexWrappedKey.data,
+ ( PRIntn ) hexWrappedKey.len );
+
+ /* For convenience, display this wrapped key to the user. */
+ if( hexWrappedKey.data != NULL ) {
+ /* Display this final wrapped key */
+ if( ( hexWrappedKey.len - 1 ) !=
+ HEX_WRAPPED_KEY_LENGTH ) {
+ /* invalid key length */
+ PR_fprintf( PR_STDERR,
+ "ERROR: Invalid data length of %d bytes!\n\n\n",
+ hexWrappedKey.len );
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ } else {
+ /* Print wrapped data blob */
+ PR_fprintf( PR_STDOUT,
+ " wrapped data: " );
+
+ /* Print first DES_LENGTH bytes */
+ if( wrappedKey->len == ( 3 * DES_LENGTH ) ) {
+ firstCount = ( ( hexWrappedKey.len - 1 ) / 3 );
+ } else {
+ firstCount = ( ( hexWrappedKey.len - 1 ) / 2 );
+ }
+ for( i = 0; i < firstCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+
+ /* Print appropriate padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+
+ /* Print second DES_LENGTH bytes */
+ secondCount = firstCount * 2;
+ for( i = firstCount; i < secondCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+
+ /* print out last 8 bytes of triple-DES keys */
+ if( wrappedKey->len == ( 3 * DES_LENGTH ) ) {
+ /* Print appropriate padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+
+ /* Print third DES_LENGTH bytes */
+ thirdCount = hexWrappedKey.len;
+ for( i = secondCount; i < thirdCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexWrappedKey.data[i],
+ hexWrappedKey.data[i + 1],
+ hexWrappedKey.data[i + 2],
+ hexWrappedKey.data[i + 3] );
+ }
+ }
+
+ /* Print appropriate vertical spacing */
+ PR_fprintf( PR_STDOUT, "\n\n\n" );
+ }
+ }
+
+ /* For convenience, display this wrapped key's */
+ /* master key KCV to the user. */
+ if( ( hexInternalKeyKCV != NULL ) &&
+ ( hexInternalKeyKCVLength == HEX_WRAPPED_KEY_KCV_LENGTH ) ) {
+ /* display this wrapped key's computed KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ " master key KCV: "
+ "%c%c%c%c %c%c%c%c\n (computed KCV of the "
+ "master key residing inside the wrapped data)\n\n\n",
+ hexInternalKeyKCV[0],
+ hexInternalKeyKCV[1],
+ hexInternalKeyKCV[2],
+ hexInternalKeyKCV[3],
+ hexInternalKeyKCV[4],
+ hexInternalKeyKCV[5],
+ hexInternalKeyKCV[6],
+ hexInternalKeyKCV[7] );
+ }
+
+ /* open the output file read-write */
+ fd = PR_OpenFile( output, ( PR_RDWR | PR_CREATE_FILE ), 0666 );
+ if( !fd ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* write out the wrapped key (in hex) to the output file */
+ while( count < HEX_WRAPPED_KEY_LENGTH ) {
+ /* write out 4 bytes */
+ r = PR_Write( fd, &( hexWrappedKey.data[count] ), 4 );
+ if( r != 4 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* increment the byte count by 4 */
+ count += 4;
+
+ if( count >= HEX_WRAPPED_KEY_LENGTH ) {
+ r = PR_Write( fd, "\n", 1 );
+ if( r != 1 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+ } else {
+ r = PR_Write( fd, " ", 1 );
+ if( r != 1 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+ }
+ }
+
+ /* reinitialize count */
+ count = 0;
+
+ /* write out the master key KCV (in hex) to the output file */
+ while( count < HEX_WRAPPED_KEY_KCV_LENGTH ) {
+ /* write out 4 bytes */
+ r = PR_Write( fd, &( hexInternalKeyKCV[count] ), 4 );
+ if( r != 4 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+
+ /* increment the byte count by 4 */
+ count += 4;
+
+ if( count >= HEX_WRAPPED_KEY_KCV_LENGTH ) {
+ r = PR_Write( fd, "\n", 1 );
+ if( r != 1 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+ } else {
+ r = PR_Write( fd, " ", 1 );
+ if( r != 1 ) {
+ status = SECFailure;
+ goto destroyHexWrappedKey;
+ }
+ }
+ }
+
+ /* close the output file */
+ PR_Close( fd );
+
+ status = SECSuccess;
+
+destroyHexWrappedKey:
+ /* Destroy the hex wrapped key */
+ if( hexWrappedKey.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexWrappedKey.data,
+ hexWrappedKey.len );
+ hexWrappedKey.data = NULL;
+ hexWrappedKey.len = 0;
+ }
+
+ return status;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/find.c b/pki/base/native-tools/src/tkstool/find.c
new file mode 100644
index 000000000..8926d5cbb
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/find.c
@@ -0,0 +1,81 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+SECStatus
+TKS_FindSymKey( PK11SlotInfo *slot,
+ char *keyname,
+ void *pwdata )
+{
+ char *name = NULL;
+ int count = 0;
+ int keys_found = 0;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ SECStatus rv = SECFailure;
+
+ if( PK11_NeedLogin( /* slot */ slot ) ) {
+ PK11_Authenticate(
+ /* slot */ slot,
+ /* load certs */ PR_TRUE,
+ /* wincx */ pwdata );
+ }
+
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot(
+ /* slot */ slot,
+ /* nickname */ NULL,
+ /* wincx */ ( void *) pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while( symKey != NULL ) {
+ name = PK11_GetSymKeyNickname( /* symmetric key */ symKey );
+ if( name != NULL ) {
+ if( keyname != NULL ) {
+ if( PL_strcmp( keyname, name ) == 0 ) {
+ keys_found++;
+ rv = SECSuccess;
+ }
+ }
+ }
+
+ nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
+ PK11_FreeSymKey( /* symmetric key */ symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ /* case 1: the token is empty */
+ if( count == 0 ) {
+ /* the specified token is empty */
+ rv = SECFailure;
+ }
+
+ /* case 2: the specified key is not on this token */
+ if( ( keyname != NULL ) &&
+ ( keys_found == 0 ) ) {
+ /* the key called "keyname" could not be found */
+ rv = SECFailure;
+ }
+
+ return rv;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/help.c b/pki/base/native-tools/src/tkstool/help.c
new file mode 100644
index 000000000..97c724459
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/help.c
@@ -0,0 +1,499 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+void
+TKS_Usage( char *progName )
+{
+ PR_fprintf( PR_STDERR,
+ "Usage: %s -D -n keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -H\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -I -n keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -K -n keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -L -d DBDir [-h all | -h token_name]\n"
+ "\t\t[-p DBPrefix] [-n keyname] [-f pwfile] [-x]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -M -n keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -N -d DBDir\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -P -d DBDir\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -R -n keyname -r new_keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -S -d DBDir\n"
+ "\t\t[-p DBPrefix] [-x]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -T -n keyname -d DBDir [-h token_name]\n"
+ "\t\t[-p DBPrefix] [-f pwfile] [-z noisefile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -U -n keyname -d DBDir -t transport_keyname -i infile\n"
+ "\t\t[-h token_name] [-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -V\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "\t%s -W -n keyname -d DBDir -t transport_keyname -o outfile\n"
+ "\t\t[-h token_name] [-p DBPrefix] [-f pwfile]\n\n",
+ progName );
+ PR_fprintf( PR_STDERR,
+ "Type \"%s -H\" for more detailed descriptions\n\n",
+ progName );
+}
+
+
+void
+TKS_PrintHelp( char *progName )
+{
+ /**********************/
+ /* -D command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Delete a key from the token\n",
+ "-D" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name of the key to delete\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token from which to remove key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -H command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Display this extended help for Usage\n",
+ "-H" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -I command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Input shares to generate a new transport key\n",
+ "-I" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name to assign to the generated transport key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to generate transport key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -K command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Display the KCV of the specified key\n",
+ "-K" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name of the key to perform a KCV on\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token on which the named key resides\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -L command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s List out a specified key, or all keys\n",
+ "-L" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Look on all tokens OR\n"
+ "%-24s Name of token in which to look for keys\n"
+ "\t\t [optional]\n",
+ " -h all |",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name of the key to list\n"
+ "\t\t [optional]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "%-24s force the database to open R/W (software only)\n"
+ "\t\t [optional]\n",
+ " -x" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -M command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Generate a new master key\n",
+ "-M" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name to assign to the generated master key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to generate master key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -N command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Create a new key database (software only)\n",
+ "-N" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Key database prefix (software only)\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -P command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Change the key database password (software only)\n",
+ "-P" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Key database prefix (software only)\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -R command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Rename a symmetric key\n",
+ "-R" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The original name assigned to a pre-existing\n"
+ "\t\t symmetric key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The new name assigned to the original pre-existing\n"
+ "\t\t symmetric key\n"
+ "\t\t [required]\n",
+ " -r new_keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to generate master key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -S command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s List all security modules\n",
+ /*, or print out a single named module\n",*/
+ "-S" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s force the database to open R/W (software only)\n"
+ "\t\t [optional]\n",
+ " -x" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -T command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Generate a new transport key\n",
+ "-T" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name to assign to the generated transport key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to generate transport key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the noise file to be used\n"
+ "\t\t [optional]\n",
+ " -z noisefile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -U command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Unwrap the wrapped master key\n",
+ "-U" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name to assign to the unwrapped master key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name of the transport key (e. g. - unwrapping key)\n"
+ "\t\t [required]\n",
+ " -t transport_keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The filename from which to input the wrapped master key\n"
+ "\t\t [required]\n",
+ " -i infile" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to store wrapped master key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -V command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Display the version number of this tool\n",
+ "-V" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+
+
+ /**********************/
+ /* -W command options */
+ /**********************/
+
+ PR_fprintf( PR_STDERR,
+ "%-15s Wrap a newly generated master key\n",
+ "-W" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name to assign to the generated master key\n"
+ "\t\t [required]\n",
+ " -n keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database directory (HSM);\n"
+ "\t\t Key database directory (software only)\n"
+ "\t\t [required]\n",
+ " -d DBDir" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The name of the transport key (e. g. - wrapping key)\n"
+ "\t\t [required]\n",
+ " -t transport_keyname" );
+ PR_fprintf( PR_STDERR,
+ "%-24s The filename in which to output the wrapped master key\n"
+ "\t\t [required]\n",
+ " -o outfile" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Name of token in which to generate master key\n"
+ "\t\t [optional]\n",
+ " -h token_name" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Security module database prefix\n"
+ "\t\t [optional]\n",
+ " -p DBPrefix" );
+ PR_fprintf( PR_STDERR,
+ "%-24s Specify the password file\n"
+ "\t\t [optional]\n",
+ " -f pwfile" );
+ PR_fprintf( PR_STDERR,
+ "\n" );
+}
+
diff --git a/pki/base/native-tools/src/tkstool/key.c b/pki/base/native-tools/src/tkstool/key.c
new file mode 100644
index 000000000..4fd37963b
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/key.c
@@ -0,0 +1,1350 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+/*******************************/
+/** local private functions **/
+/*******************************/
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+InputHexSessionKey( char *sessionKeyShareName,
+ SECItem *hexSessionKeyShare )
+{
+ int fd;
+ int i;
+ int count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+
+ PR_fprintf( PR_STDOUT,
+ "Type in the %s session key share (or ^C to break):\n\n",
+ sessionKeyShareName );
+ PR_fprintf( PR_STDOUT,
+ "[ ] [ ] [ ] [ ] "
+ "[ ] [ ] [ ] [ ]\r" );
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno( stdin );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ tcgetattr( fd, &tio );
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ /* Get user input from keyboard strokes */
+ count = 0;
+ while( count < HEX_SESSION_KEY_BUF_LENGTH ) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc( stdin );
+#else
+ c = getch();
+#endif
+ /* break on EOF */
+ if( c == EOF ) {
+ rv = -1;
+ break;
+ }
+
+ /* break on ^C */
+ if( c == CTRL_C ) {
+ rv = -1;
+ break;
+ }
+
+ /* save acceptable hex characters; silently throw anything else away */
+ switch( c ) {
+ case '\010': /* backspace */
+ /* acceptable character; save it as a NULL value */
+ hexSessionKeyShare->data[count] = '\0';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* acceptable character; save it as typed */
+ hexSessionKeyShare->data[count] = c;
+ break;
+ case 'A':
+ case 'a':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'A';
+ break;
+ case 'B':
+ case 'b':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'B';
+ break;
+ case 'C':
+ case 'c':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'C';
+ break;
+ case 'D':
+ case 'd':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'D';
+ break;
+ case 'E':
+ case 'e':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'E';
+ break;
+ case 'F':
+ case 'f':
+ /* acceptable character; save uppercase version */
+ hexSessionKeyShare->data[count] = 'F';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+
+ /* adjust the character count appropriately */
+ if( c != '\010' ) {
+ /* only increment the character count if everything is OK */
+ count++;
+ } else {
+ /* only decrement the character count if a backspace was entered */
+ if( count > 0 ) {
+ count--;
+ }
+ }
+
+ /* redisplay the left bracket */
+ PR_fprintf( PR_STDOUT,
+ "\r[" );
+
+ /* display the characters input so far */
+ for( i = 0 ; i < count ; i++ ) {
+ PR_fprintf( PR_STDOUT,
+ "%c",
+ hexSessionKeyShare->data[i] );
+ if( ( i > 0 ) &&
+ ( ( ( i + 1 ) % 4 ) == 0 ) ) {
+ PR_fprintf( PR_STDOUT, "] [" );
+ }
+ }
+
+ /* display a "cursor" pointing to the next character */
+ PR_fprintf( PR_STDOUT,
+ "/" );
+
+ /* display spaces to pad the remainder */
+ for( i = ( count + 1 );
+ i < HEX_SESSION_KEY_BUF_LENGTH;
+ i++ ) {
+ if( ( i % 4 ) != 0 ) {
+ PR_fprintf( PR_STDOUT, " " );
+ } else {
+ if( ( i > 0 ) &&
+ ( ( i + 1 ) < HEX_SESSION_KEY_BUF_LENGTH ) ) {
+ PR_fprintf( PR_STDOUT, "] [" );
+ PR_fprintf( PR_STDOUT, " " );
+ }
+ }
+ }
+
+ /* redisplay the right bracket */
+ PR_fprintf( PR_STDOUT,
+ "]" );
+ }
+
+ /* Null terminate the entered character sequence */
+ hexSessionKeyShare->data[count] = '\0';
+
+
+ /**************************************/
+ /* Print the final character sequence */
+ /**************************************/
+
+ /* Clear input line by outputting 78 blank */
+ /* spaces from the beginning of this line */
+ PR_fprintf( PR_STDOUT,
+ "\r"
+ " "
+ " " );
+
+ /* Print appropriate key share name */
+ PR_fprintf( PR_STDOUT,
+ "\r %s session key share: ",
+ sessionKeyShareName );
+
+ /* Print first DES_LENGTH bytes */
+ count = ( ( hexSessionKeyShare->len - 1 ) / 2 );
+ for( i = 0; i < count; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSessionKeyShare->data[i],
+ hexSessionKeyShare->data[i + 1],
+ hexSessionKeyShare->data[i + 2],
+ hexSessionKeyShare->data[i + 3] );
+ }
+
+ /* Print appropriate key share padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+ for( i = 0; i < PL_strlen( sessionKeyShareName ); i++ ) {
+ PR_fprintf( PR_STDOUT, " " );
+ }
+
+ /* Print second DES_LENGTH bytes */
+ for( i = count; i < hexSessionKeyShare->len; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSessionKeyShare->data[i],
+ hexSessionKeyShare->data[i + 1],
+ hexSessionKeyShare->data[i + 2],
+ hexSessionKeyShare->data[i + 3] );
+ }
+
+ /* Print appropriate vertical spacing */
+ PR_fprintf( PR_STDOUT, "\n\n\n" );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ return rv;
+}
+
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+InputHexKCV( char *sessionKeyShareName,
+ PRUint8 *hexKCV )
+{
+ int fd;
+ int i;
+ int count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+
+ PR_fprintf( PR_STDOUT,
+ "Type in the corresponding KCV for the "
+ "%s session key share (or ^C to break):\n\n",
+ sessionKeyShareName );
+ PR_fprintf( PR_STDOUT,
+ "[ ] [ ]\r" );
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno( stdin );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ tcgetattr( fd, &tio );
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ /* Get user input from keyboard strokes */
+ count = 0;
+ while( count < HEX_SESSION_KEY_KCV_BUF_LENGTH ) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc( stdin );
+#else
+ c = getch();
+#endif
+ /* break on EOF */
+ if( c == EOF ) {
+ rv = -1;
+ break;
+ }
+
+ /* break on ^C */
+ if( c == CTRL_C ) {
+ rv = -1;
+ break;
+ }
+
+ /* save acceptable hex characters; silently throw anything else away */
+ switch( c ) {
+ case '\010': /* backspace */
+ /* acceptable character; save it as a NULL value */
+ hexKCV[count] = '\0';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* acceptable character; save it as typed */
+ hexKCV[count] = c;
+ break;
+ case 'A':
+ case 'a':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'A';
+ break;
+ case 'B':
+ case 'b':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'B';
+ break;
+ case 'C':
+ case 'c':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'C';
+ break;
+ case 'D':
+ case 'd':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'D';
+ break;
+ case 'E':
+ case 'e':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'E';
+ break;
+ case 'F':
+ case 'f':
+ /* acceptable character; save uppercase version */
+ hexKCV[count] = 'F';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+
+ /* adjust the character count appropriately */
+ if( c != '\010' ) {
+ /* only increment the character count if everything is OK */
+ count++;
+ } else {
+ /* only decrement the character count if a backspace was entered */
+ if( count > 0 ) {
+ count--;
+ }
+ }
+
+ /* redisplay the left bracket */
+ PR_fprintf( PR_STDOUT,
+ "\r[" );
+
+ /* display the characters input so far */
+ for( i = 0 ; i < count ; i++ ) {
+ PR_fprintf( PR_STDOUT,
+ "%c",
+ hexKCV[i] );
+ if( ( i > 0 ) &&
+ ( ( ( i + 1 ) % 4 ) == 0 ) ) {
+ PR_fprintf( PR_STDOUT, "] [" );
+ }
+ }
+
+ /* display a "cursor" pointing to the next character */
+ PR_fprintf( PR_STDOUT,
+ "/" );
+
+ /* display spaces to pad the remainder */
+ for( i = ( count + 1 );
+ i < HEX_SESSION_KEY_KCV_BUF_LENGTH;
+ i++ ) {
+ if( ( i % 4 ) != 0 ) {
+ PR_fprintf( PR_STDOUT, " " );
+ } else {
+ if( ( i > 0 ) &&
+ ( ( i + 1 ) < HEX_SESSION_KEY_KCV_BUF_LENGTH ) ) {
+ PR_fprintf( PR_STDOUT, "] [" );
+ PR_fprintf( PR_STDOUT, " " );
+ }
+ }
+ }
+
+ /* redisplay the right bracket */
+ PR_fprintf( PR_STDOUT,
+ "]" );
+ }
+
+ /* Null terminate the entered character sequence */
+ hexKCV[count] = '\0';
+
+
+ /**************************************/
+ /* Print the final character sequence */
+ /**************************************/
+
+ /* Clear input line by outputting 78 blank */
+ /* spaces from the beginning of this line */
+ PR_fprintf( PR_STDOUT,
+ "\r"
+ " "
+ " " );
+
+ /* display this session key share's entered KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ "\r %s session key share KCV: "
+ "%c%c%c%c %c%c%c%c\n\n\n",
+ sessionKeyShareName,
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ return rv;
+}
+
+
+/************************************/
+/** public session key functions **/
+/************************************/
+
+SECStatus
+TKS_ComputeAndDisplayKCV( PRUint8 *newKey,
+ PRIntn newKeyLen,
+ PRUint8 *KCV,
+ PRIntn KCVLen,
+ PK11SymKey *symKey,
+ char *keyName,
+ char *keyType,
+ PRBool displayKCV,
+ PRUint8 *expectedHexKCV )
+{
+ int len;
+ unsigned char value[8];
+ PK11SymKey *key = NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11Context *context = NULL;
+ PRIntn hexKCVLen = ( 2 * KCVLen ) + 1;
+ PRUint8 *hexKCV = NULL;
+ PRUint8 *keyData = NULL;
+ SECItem keyItem = { siBuffer,
+ NULL,
+ 0 };
+ SECItem noParams = { siBuffer,
+ NULL,
+ 0 };
+ SECStatus s = SECFailure;
+ SECStatus status = SECFailure;
+
+ /* for all keys except keys that are resident/wrapped/unwrapped . . . */
+ if( ( PL_strcmp( keyType, RESIDENT_KEY ) != 0 ) &&
+ ( PL_strcmp( keyType, UNWRAPPED_KEY ) != 0 ) &&
+ ( PL_strcmp( keyType, WRAPPED_KEY ) != 0 ) ) {
+ slot = PK11_GetInternalKeySlot();
+
+ if( newKeyLen == ( 2 * DES_LENGTH ) ) {
+#if defined(PAD_DES2_KEY_LENGTH)
+ /* double-DES key */
+ keyData = ( PRUint8 * ) PORT_ZAlloc( newKeyLen + DES_LENGTH );
+
+ keyItem.type = ( SECItemType ) siBuffer;
+ keyItem.data = ( unsigned char * ) keyData;
+ keyItem.len = ( unsigned int ) ( newKeyLen + DES_LENGTH );
+
+ /* convert 16-byte double-DES key to 24-byte triple-DES key */
+ PORT_Memcpy( keyData, newKey, newKeyLen );
+ PORT_Memcpy( ( keyData + ( 2 * DES_LENGTH ) ),
+ newKey, DES_LENGTH );
+#else
+ /* double-DES key */
+ keyData = ( PRUint8 * ) PORT_ZAlloc( newKeyLen );
+
+ keyItem.type = ( SECItemType ) siBuffer;
+ keyItem.data = ( unsigned char * ) keyData;
+ keyItem.len = ( unsigned int ) newKeyLen;
+
+ PORT_Memcpy( keyData, newKey, newKeyLen );
+#endif
+ } else if( newKeyLen == ( 3 * DES_LENGTH ) ) {
+ /* triple-DES key */
+ keyData = ( PRUint8 * ) PORT_ZAlloc( newKeyLen );
+
+ keyItem.type = ( SECItemType ) siBuffer;
+ keyItem.data = ( unsigned char * ) keyData;
+ keyItem.len = ( unsigned int ) newKeyLen;
+
+ PORT_Memcpy( keyData, newKey, newKeyLen );
+ } else {
+ /* invalid key size */
+ PR_fprintf( PR_STDOUT,
+ "Attempting to perform KCV on invalid key length!\n\n\n" );
+ status = SECFailure;
+ goto done;
+ }
+
+ key = PK11_ImportSymKeyWithFlags(
+ /* slot */ slot,
+ /* mechanism type */ CKM_DES3_ECB,
+ /* origin */ PK11_OriginGenerated,
+ /* operation */ CKA_ENCRYPT,
+ /* key */ &keyItem,
+ /* flags */ CKF_ENCRYPT,
+ /* isPerm */ PR_FALSE,
+ /* wincx */ 0 );
+
+ if( ! key ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to import %s key!\n\n\n",
+ keyType );
+ status = SECFailure;
+ goto done;
+ }
+ } else {
+ /* since resident/wrapped/unwrapped keys are already present . . . */
+ key = symKey;
+ }
+
+ PORT_Memset( value, 0, sizeof( value ) );
+
+ context = PK11_CreateContextBySymKey(
+ /* mechanism type */ CKM_DES3_ECB,
+ /* operation */ CKA_ENCRYPT,
+ /* symmetric key */ key,
+ /* param */ &noParams );
+
+ if( ! context ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to create crypto context!\n\n\n" );
+ status = SECFailure;
+ goto done;
+ }
+
+ s = PK11_CipherOp(
+ /* context */ context,
+ /* output */ &value[0],
+ /* output length */ &len,
+ /* maximum output length */ DES_LENGTH,
+ /* input */ &value[0],
+ /* input length */ DES_LENGTH );
+ if( s != SECSuccess) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: CipherOp Failed!\n\n\n" );
+ status = SECFailure;
+ goto done;
+ }
+
+ KCV = ( PRUint8 * ) PORT_ZAlloc( KCVLen );
+
+ PORT_Memcpy( KCV, value, KCVLen );
+
+ /* Create a clean new display buffer for this */
+ /* symmetric key/session key share KCV */
+ hexKCV = ( PRUint8 * ) PORT_ZAlloc( hexKCVLen );
+ if( hexKCV == NULL ) {
+ status = SECFailure;
+ goto done;
+ }
+
+ /* Display the symmetric key/session key share KCV (in hex digits) */
+ TKS_StringToHex( ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ ( PRUint8 * ) hexKCV,
+ ( PRIntn ) hexKCVLen );
+
+ if( displayKCV != PR_FALSE ) {
+ /********************************************/
+ /* The following code is ONLY relevant to: */
+ /* */
+ /* (1) resident, */
+ /* (2) session, */
+ /* (3) symmetric, and */
+ /* (4) transport keys. */
+ /* */
+ /********************************************/
+
+ if( PL_strcmp( keyType, RESIDENT_KEY ) == 0 ) {
+ /* display this resident key's computed KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ " %s key KCV: "
+ "%c%c%c%c %c%c%c%c\n\n\n",
+ keyName,
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+ } else if( PL_strcmp( keyType, SESSION_KEY ) == 0 ) {
+ /* display this session key share's computed KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ " %s session key share KCV: "
+ "%c%c%c%c %c%c%c%c\n\n\n",
+ keyName,
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+ } else if( PL_strcmp( keyType, SYMMETRIC_KEY ) == 0 ) {
+ /* display this symmetric key's computed KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ " %s key KCV: "
+ "%c%c%c%c %c%c%c%c\n\n\n",
+ keyName,
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+ } else if( PL_strcmp( keyType, TRANSPORT_KEY ) == 0 ) {
+ /* display this transport key's computed KCV value (in hex) */
+ PR_fprintf( PR_STDOUT,
+ " %s key KCV: "
+ "%c%c%c%c %c%c%c%c\n\n\n",
+ keyName,
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+ }
+ } else {
+ /**********************************************/
+ /* The following code is ONLY relevant to: */
+ /* */
+ /* (1) session keys, */
+ /* (2) keys that have been unwrapped, and */
+ /* (3) keys that will be wrapped. */
+ /* */
+ /**********************************************/
+
+ if( PL_strcmp( keyType, SESSION_KEY ) == 0 ) {
+ /* compare this session key share's computed KCV value (in hex) */
+ /* with the expected KCV value (in hex) */
+ if( PL_strcmp( ( const char * ) hexKCV,
+ ( const char * ) expectedHexKCV ) == 0 ) {
+ PR_fprintf( PR_STDOUT,
+ "Congratulations, the %s session key share KCV "
+ "value entered CORRESPONDS\nto the %s session key "
+ "share value entered!\n",
+ keyName,
+ keyName );
+
+ /* Wait for the user to type "proceed" to continue */
+ TKS_TypeProceedToContinue();
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Unfortunately, a MISMATCH exists between the %s "
+ "session key share entered\nand the %s session key "
+ "share KCV entered. Please try again . . .\n",
+ keyName,
+ keyName );
+
+ /* Wait for the user to type "proceed" to continue */
+ TKS_TypeProceedToContinue();
+
+ status = SECFailure;
+ goto done;
+ }
+ } else if( PL_strcmp( keyType, UNWRAPPED_KEY ) == 0 ) {
+ PR_fprintf( PR_STDOUT,
+ " master key KCV: "
+ "%c%c%c%c %c%c%c%c\n (computed KCV of the "
+ "master key residing inside the wrapped data)\n\n\n",
+ hexKCV[0],
+ hexKCV[1],
+ hexKCV[2],
+ hexKCV[3],
+ hexKCV[4],
+ hexKCV[5],
+ hexKCV[6],
+ hexKCV[7] );
+
+ PR_fprintf( PR_STDOUT,
+ " master key KCV: "
+ "%c%c%c%c %c%c%c%c\n (pre-computed KCV of the "
+ "master key residing inside the wrapped data)\n\n\n",
+ expectedHexKCV[0],
+ expectedHexKCV[1],
+ expectedHexKCV[2],
+ expectedHexKCV[3],
+ expectedHexKCV[4],
+ expectedHexKCV[5],
+ expectedHexKCV[6],
+ expectedHexKCV[7] );
+
+ /* compare this wrapped key's computed KCV value (in hex) */
+ /* with the expected KCV value (in hex) -- silently */
+ if( PL_strcmp( ( const char * ) hexKCV,
+ ( const char * ) expectedHexKCV ) != 0 ) {
+ PR_fprintf( PR_STDOUT,
+ "Unfortunately, a MISMATCH exists between the "
+ "wrapped data read in\nfrom the input file "
+ "and the master key KCV that was recomputed.\n\n",
+ keyName,
+ keyName );
+ status = SECFailure;
+ goto done;
+ }
+ } else if( PL_strcmp( keyType, WRAPPED_KEY ) == 0 ) {
+ /* store this master key's computed KCV value (in hex) */
+ expectedHexKCV[0] = hexKCV[0];
+ expectedHexKCV[1] = hexKCV[1];
+ expectedHexKCV[2] = hexKCV[2];
+ expectedHexKCV[3] = hexKCV[3];
+ expectedHexKCV[4] = hexKCV[4];
+ expectedHexKCV[5] = hexKCV[5];
+ expectedHexKCV[6] = hexKCV[6];
+ expectedHexKCV[7] = hexKCV[7];
+ }
+ }
+
+ status = SECSuccess;
+
+done:
+ if( keyItem.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ keyItem.data,
+ keyItem.len );
+ keyItem.data = NULL;
+ keyItem.len = 0;
+ }
+
+ if( hexKCV != NULL ) {
+ PORT_ZFree( ( PRUint8 * )
+ hexKCV,
+ hexKCVLen );
+ }
+
+ if( context ) {
+ PK11_DestroyContext(
+ /* context */ context,
+ /* free it */ PR_TRUE );
+ }
+
+ if( slot ) {
+ PK11_FreeSlot( /* slot */ slot );
+ }
+
+ /* for all keys except keys that are resident/wrapped/unwrapped . . . */
+ if( ( PL_strcmp( keyType, RESIDENT_KEY ) != 0 ) &&
+ ( PL_strcmp( keyType, UNWRAPPED_KEY ) != 0 ) &&
+ ( PL_strcmp( keyType, WRAPPED_KEY ) != 0 ) ) {
+ if( key ) {
+ PK11_FreeSymKey( /* symmetric key */ key );
+ }
+ }
+
+ return status;
+}
+
+
+SECStatus
+TKS_GenerateSessionKeyShare( char *sessionKeyShareName,
+ SECItem *sessionKeyShare )
+{
+ PRIntn count = 0;
+ PRIntn i = 0;
+ PRIntn KCVLen = KCV_LENGTH;
+ PRUint8 *KCV = NULL;
+ SECItem hexSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+ SECStatus rvKCV = SECFailure;
+ SECStatus sessionKeyShareStatus = SECFailure;
+ SECStatus status = SECFailure;
+
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Generate a new session key share */
+ PR_fprintf( PR_STDOUT,
+ "\nGenerating the %s session key share . . .\n\n\n",
+ sessionKeyShareName );
+
+ sessionKeyShareStatus = PK11_GenerateRandom( ( unsigned char * )
+ /* data */ sessionKeyShare->data,
+ /* length */ sessionKeyShare->len );
+ if( sessionKeyShareStatus != SECSuccess ) {
+ goto destroyHexSessionKeyShare;
+ }
+
+ /* Create a clean new display buffer for this session key share */
+ hexSessionKeyShare.type = ( SECItemType ) siBuffer;
+ hexSessionKeyShare.len = ( ( sessionKeyShare->len * 2 ) + 1 );
+ hexSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( hexSessionKeyShare.len );
+ if( hexSessionKeyShare.data == NULL ) {
+ goto destroyHexSessionKeyShare;
+ }
+
+ /* Convert this session key share into hex digits */
+ TKS_StringToHex( ( PRUint8 * ) sessionKeyShare->data,
+ ( PRIntn ) sessionKeyShare->len,
+ ( PRUint8 * ) hexSessionKeyShare.data,
+ ( PRIntn ) hexSessionKeyShare.len );
+
+ /* Adjust the first DES-sized (8-byte) chunk */
+ TKS_AdjustOddParity( ( PRUint8 * ) sessionKeyShare->data );
+
+ /* Adjust the second DES-sized (8-byte) chunk */
+ TKS_AdjustOddParity( ( PRUint8 * ) ( sessionKeyShare->data + DES_LENGTH ) );
+
+ /* Finally, display this session key share */
+ /* (adjusted for odd parity in hex digits) */
+ TKS_StringToHex( ( PRUint8 * ) sessionKeyShare->data,
+ ( PRIntn ) sessionKeyShare->len,
+ ( PRUint8 * ) hexSessionKeyShare.data,
+ ( PRIntn ) hexSessionKeyShare.len );
+
+ if( ( ( hexSessionKeyShare.len - 1 ) % 4 ) != 0 ) {
+ /* invalid key length */
+ PR_fprintf( PR_STDERR,
+ "ERROR: Invalid session key share length "
+ "of %d bytes!\n\n\n",
+ hexSessionKeyShare.len );
+ goto destroyHexSessionKeyShare;
+ } else {
+ /* Print appropriate key share name */
+ PR_fprintf( PR_STDOUT,
+ " %s session key share: ",
+ sessionKeyShareName );
+
+ /* Print first DES_LENGTH bytes */
+ count = ( ( hexSessionKeyShare.len - 1 ) / 2 );
+ for( i = 0; i < count; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSessionKeyShare.data[i],
+ hexSessionKeyShare.data[i + 1],
+ hexSessionKeyShare.data[i + 2],
+ hexSessionKeyShare.data[i + 3] );
+ }
+
+ /* Print appropriate key share padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+ for( i = 0; i < PL_strlen( sessionKeyShareName ); i++ ) {
+ PR_fprintf( PR_STDOUT, " " );
+ }
+
+ /* Print second DES_LENGTH bytes */
+ for( i = count; i < hexSessionKeyShare.len; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSessionKeyShare.data[i],
+ hexSessionKeyShare.data[i + 1],
+ hexSessionKeyShare.data[i + 2],
+ hexSessionKeyShare.data[i + 3] );
+ }
+
+ /* Print appropriate vertical spacing */
+ PR_fprintf( PR_STDOUT, "\n\n\n" );
+ }
+
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) sessionKeyShare->data,
+ ( PRIntn ) sessionKeyShare->len,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ NULL,
+ sessionKeyShareName,
+ SESSION_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to compute KCV of "
+ "this %s session key share!\n\n",
+ sessionKeyShareName );
+ goto destroyHexSessionKeyShare;
+ }
+
+ PR_fprintf( PR_STDOUT,
+ "(1) Write down and save the value "
+ "for this %s session key share.\n\n",
+ sessionKeyShareName );
+
+ PR_fprintf( PR_STDOUT,
+ "(2) Write down and save the KCV value "
+ "for this %s session key share.\n",
+ sessionKeyShareName );
+
+ /* Wait for the user to type "proceed" to continue */
+ TKS_TypeProceedToContinue();
+
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Report success */
+ status = SECSuccess;
+
+destroyHexSessionKeyShare:
+ /* Destroy the hex session key share */
+ if( hexSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexSessionKeyShare.data,
+ hexSessionKeyShare.len );
+ hexSessionKeyShare.data = NULL;
+ hexSessionKeyShare.len = 0;
+ }
+
+ return status;
+}
+
+SECStatus
+TKS_InputSessionKeyShare( char *sessionKeyShareName,
+ SECItem *sessionKeyShare )
+{
+ int rv = 0;
+ PRIntn KCVLen = KCV_LENGTH;
+ PRUint8 *KCV = NULL;
+ SECItem hexSessionKeyShare;
+ PRIntn hexKCVLen = ( 2 * KCVLen ) + 1;
+ PRUint8 *hexKCV = NULL;
+ SECStatus rvKCV = SECFailure;
+ SECStatus status = SECFailure;
+
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Enter a new session key share */
+ PR_fprintf( PR_STDOUT,
+ "\nEnter the %s session key share . . .\n\n\n",
+ sessionKeyShareName );
+
+ /* Create a clean new display buffer for this session key share */
+ hexSessionKeyShare.type = ( SECItemType ) siBuffer;
+ hexSessionKeyShare.len = ( ( sessionKeyShare->len * 2 ) + 1 );
+ hexSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( hexSessionKeyShare.len );
+ if( hexSessionKeyShare.data == NULL ) {
+ goto destroyHexSessionKeyShare;
+ }
+
+ rv = InputHexSessionKey( sessionKeyShareName,
+ &hexSessionKeyShare );
+ if( rv ) {
+ PORT_SetError( PR_END_OF_FILE_ERROR );
+ return SECFailure;
+ }
+
+ /* Convert these hex digits into a session key share */
+ TKS_ConvertStringOfHexCharactersIntoBitStream( ( char * ) hexSessionKeyShare.data,
+ ( hexSessionKeyShare.len - 1 ),
+ sessionKeyShare->data );
+
+ /* Create a clean new display buffer for this session key share KCV */
+ hexKCV = ( PRUint8 * ) PORT_ZAlloc( hexKCVLen );
+ if( hexKCV == NULL ) {
+ goto destroyHexSessionKeyShare;
+ }
+
+ rv = InputHexKCV( sessionKeyShareName,
+ hexKCV );
+ if( rv ) {
+ PORT_SetError( PR_END_OF_FILE_ERROR );
+ return SECFailure;
+ }
+
+ /* Enter the corresponding KCV */
+ PR_fprintf( PR_STDOUT,
+ "Verifying that this session key share and KCV "
+ "correspond to each other . . .\n\n\n" );
+
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) sessionKeyShare->data,
+ ( PRIntn ) sessionKeyShare->len,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ NULL,
+ sessionKeyShareName,
+ SESSION_KEY,
+ PR_FALSE,
+ hexKCV );
+ if( rvKCV != SECSuccess ) {
+ goto destroyHexSessionKeyShare;
+ }
+
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Report success */
+ status = SECSuccess;
+
+destroyHexSessionKeyShare:
+ /* Destroy the hex session key share */
+ if( hexSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexSessionKeyShare.data,
+ hexSessionKeyShare.len );
+ hexSessionKeyShare.data = NULL;
+ hexSessionKeyShare.len = 0;
+ }
+
+ if( hexKCV != NULL ) {
+ PORT_ZFree( ( PRUint8 * )
+ hexKCV,
+ hexKCVLen );
+ }
+
+ return status;
+}
+
+
+/**************************************/
+/** public symmetric key functions **/
+/**************************************/
+
+PK11SymKey *
+TKS_ImportSymmetricKey( char *symmetricKeyName,
+ PK11SlotInfo *slot,
+ CK_MECHANISM_TYPE mechanism,
+ CK_ATTRIBUTE_TYPE operation,
+ SECItem *sessionKeyShare,
+ secuPWData *pwdata )
+{
+ PK11Origin origin = PK11_OriginGenerated;
+ PK11SymKey *symKey = NULL;
+
+ if( slot == NULL ) {
+ return NULL;
+ }
+
+ PR_fprintf( PR_STDOUT,
+ "\n" );
+ PR_fprintf( PR_STDOUT,
+ "Generating %s symmetric key . . .\n\n",
+ symmetricKeyName );
+
+ symKey = PK11_ImportSymKeyWithFlags(
+ /* slot */ slot,
+ /* mechanism type */ mechanism,
+ /* origin */ origin,
+ /* operation */ operation,
+ /* key */ sessionKeyShare,
+ /* flags */ 0,
+ /* isPerm */ PR_FALSE,
+ /* wincx */ pwdata );
+ return symKey;
+}
+
+
+PK11SymKey *
+TKS_DeriveSymmetricKey( char *symmetricKeyName,
+ PK11SymKey *symKey,
+ CK_MECHANISM_TYPE derive,
+ SECItem *sessionKeyShare,
+ CK_MECHANISM_TYPE target,
+ CK_ATTRIBUTE_TYPE operation,
+ int keysize )
+{
+ PK11SymKey *newSymKey = NULL;
+
+ if( symKey == NULL ) {
+ return NULL;
+ }
+
+ if( keysize <= 0 ) {
+ return NULL;
+ }
+
+ PR_fprintf( PR_STDOUT,
+ "Generating %s symmetric key . . .\n\n",
+ symmetricKeyName );
+
+ newSymKey = PK11_Derive(
+ /* base symmetric key */ symKey,
+ /* mechanism derive type */ derive,
+ /* param */ sessionKeyShare,
+ /* target */ target,
+ /* operation */ operation,
+ /* key size */ keysize );
+ return newSymKey;
+}
+
+
+SECStatus
+TKS_StoreSymmetricKeyAndNameIt( char *symmetricKeyName,
+ char *keyname,
+ PK11SlotInfo *slot,
+ CK_ATTRIBUTE_TYPE operation,
+ CK_FLAGS flags,
+ PK11SymKey *symKey )
+{
+ PK11SymKey *newSymKey = NULL;
+ PRIntn KCVLen = KCV_LENGTH;
+ PRUint8 *KCV = NULL;
+ SECItem *symmetricKey = NULL;
+ SECStatus rvExtractSymmetricKey = SECFailure;
+ SECStatus rvKCV = SECFailure;
+ SECStatus rvSymmetricKeyname = SECFailure;
+ SECStatus status = SECFailure;
+#if defined(DEBUG)
+ PRIntn firstCount = 0;
+ PRIntn secondCount = 0;
+ PRIntn thirdCount = 0;
+ PRIntn i = 0;
+ SECItem hexSymmetricKey;
+#endif
+
+ PR_fprintf( PR_STDOUT,
+ "Extracting %s key from operational token . . .\n\n",
+ symmetricKeyName );
+
+ rvExtractSymmetricKey = PK11_ExtractKeyValue( /* symmetric key */ symKey );
+ if( rvExtractSymmetricKey != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to extract the %s key!\n\n",
+ symmetricKeyName );
+ goto destroyHexSymmetricKey;
+ }
+
+ /* If present, retrieve the raw key data */
+ symmetricKey = PK11_GetKeyData( /* symmetric key */ symKey );
+
+#if defined(DEBUG)
+ /* For convenience, display the final symmetric key and */
+ /* its associated KCV to the user in DEBUG mode ONLY!!! */
+ if( symmetricKey != NULL ) {
+
+ /* Create a clean new display buffer for this symmetric key */
+ hexSymmetricKey.type = ( SECItemType ) siBuffer;
+ hexSymmetricKey.len = ( ( symmetricKey->len * 2 ) + 1 );
+ hexSymmetricKey.data = ( unsigned char * )
+ PORT_ZAlloc( hexSymmetricKey.len );
+ if( hexSymmetricKey.data == NULL ) {
+ goto destroyHexSymmetricKey;
+ }
+
+ /* Convert this symmetric key into hex digits */
+ TKS_StringToHex( ( PRUint8 * ) symmetricKey->data,
+ ( PRIntn ) symmetricKey->len,
+ ( PRUint8 * ) hexSymmetricKey.data,
+ ( PRIntn ) hexSymmetricKey.len );
+
+ /* Display this final symmetric key */
+ if( ( ( hexSymmetricKey.len - 1 ) % 4 ) != 0 ) {
+ /* invalid key length */
+ PR_fprintf( PR_STDERR,
+ "ERROR: Invalid symmetric key length "
+ "of %d bytes!\n\n\n",
+ hexSymmetricKey.len );
+ goto destroyHexSymmetricKey;
+ } else {
+ /* Print appropriate key name */
+ PR_fprintf( PR_STDOUT,
+ "\n %s key: ",
+ symmetricKeyName );
+
+ /* Print first DES_LENGTH bytes */
+ if( symmetricKey->len == ( 3 * DES_LENGTH ) ) {
+ firstCount = ( ( hexSymmetricKey.len - 1 ) / 3 );
+ } else {
+ firstCount = ( ( hexSymmetricKey.len - 1 ) / 2 );
+ }
+ for( i = 0; i < firstCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSymmetricKey.data[i],
+ hexSymmetricKey.data[i + 1],
+ hexSymmetricKey.data[i + 2],
+ hexSymmetricKey.data[i + 3] );
+ }
+
+ /* Print appropriate key padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+ for( i = 0; i < PL_strlen( symmetricKeyName ); i++ ) {
+ PR_fprintf( PR_STDOUT, " " );
+ }
+
+ /* Print second DES_LENGTH bytes */
+ secondCount = firstCount * 2;
+ for( i = firstCount; i < secondCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSymmetricKey.data[i],
+ hexSymmetricKey.data[i + 1],
+ hexSymmetricKey.data[i + 2],
+ hexSymmetricKey.data[i + 3] );
+ }
+
+ /* print out last 8 bytes of triple-DES keys */
+ if( symmetricKey->len == ( 3 * DES_LENGTH ) ) {
+ /* Print appropriate key padding length */
+ PR_fprintf( PR_STDOUT, "\n " );
+ for( i = 0; i < PL_strlen( symmetricKeyName ); i++ ) {
+ PR_fprintf( PR_STDOUT, " " );
+ }
+
+ /* Print third DES_LENGTH bytes */
+ thirdCount = hexSymmetricKey.len;
+ for( i = secondCount; i < thirdCount; i += 4 ) {
+ PR_fprintf( PR_STDOUT,
+ "%c%c%c%c ",
+ hexSymmetricKey.data[i],
+ hexSymmetricKey.data[i + 1],
+ hexSymmetricKey.data[i + 2],
+ hexSymmetricKey.data[i + 3] );
+ }
+ }
+
+ /* Print appropriate vertical spacing */
+ PR_fprintf( PR_STDOUT, "\n\n\n" );
+ }
+
+ /* Compute and display this final symmetric key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) symmetricKey->data,
+ ( PRIntn ) symmetricKey->len,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ NULL,
+ symmetricKeyName,
+ SYMMETRIC_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to compute KCV of this %s key!\n\n",
+ symmetricKeyName );
+ goto destroyHexSymmetricKey;
+ }
+ }
+#else
+ /* Display the final symmetric key's associated KCV to the user . . . */
+ if( symmetricKey != NULL ) {
+ /* . . . if and only if this is the transport key!!! */
+ if( PL_strcmp( symmetricKeyName, TRANSPORT_KEY ) == 0 ) {
+ /* Compute and display this transport key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) symmetricKey->data,
+ ( PRIntn ) symmetricKey->len,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ NULL,
+ symmetricKeyName,
+ TRANSPORT_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to compute KCV of this %s key!\n\n",
+ symmetricKeyName );
+ goto destroyHexSymmetricKey;
+ }
+ }
+ }
+#endif
+
+ PR_fprintf( PR_STDOUT,
+ "Storing %s key on final specified token . . .\n\n",
+ symmetricKeyName );
+
+ newSymKey = PK11_MoveSymKey(
+ /* slot */ slot,
+ /* operation */ operation,
+ /* flags */ flags,
+ /* permanence */ PR_TRUE,
+ /* symmetric key */ symKey );
+ if( newSymKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to store the %s key: %d!\n\n",
+ symmetricKeyName,
+ PR_GetError() );
+ goto destroyHexSymmetricKey;
+ }
+
+
+ PR_fprintf( PR_STDOUT,
+ "Naming %s key \"%s\" . . .\n\n",
+ symmetricKeyName,
+ keyname );
+
+ rvSymmetricKeyname = PK11_SetSymKeyNickname(
+ /* symmetric key */ newSymKey,
+ /* nickname */ keyname );
+ if( rvSymmetricKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to name the %s key!\n\n",
+ symmetricKeyName );
+ goto destroyHexSymmetricKey;
+ }
+
+ status = SECSuccess;
+
+
+destroyHexSymmetricKey:
+
+#if defined(DEBUG)
+ /* Destroy the hex symmetric key */
+ if( hexSymmetricKey.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexSymmetricKey.data,
+ hexSymmetricKey.len );
+ hexSymmetricKey.data = NULL;
+ hexSymmetricKey.len = 0;
+ }
+#endif
+
+ return status;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/list.c b/pki/base/native-tools/src/tkstool/list.c
new file mode 100644
index 000000000..44173fa36
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/list.c
@@ -0,0 +1,181 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+/* callback for listing keys through pkcs11 */
+static SECStatus
+PrintSymKey( struct PRFileDesc *out,
+ int count,
+ char *keyname,
+ PK11SymKey *key )
+{
+ char *name = NULL;
+ SECStatus rv = SECFailure;
+
+ name = PK11_GetSymKeyNickname( /* symmetric key */ key );
+ if( name == NULL ) {
+ name = PORT_Strdup( "\t< orphaned >" );
+ }
+
+ if( keyname != NULL ) {
+ /* ONLY print this name if it is the requested key */
+ if( PL_strcmp( keyname, name ) == 0 ) {
+ PR_fprintf( out,
+ "\t<%d> %s\n",
+ count,
+ name );
+
+ rv = SECSuccess;
+ }
+ } else {
+ PR_fprintf( out,
+ "\t<%d> %s\n",
+ count,
+ name );
+
+ rv = SECSuccess;
+ }
+
+ PORT_Free( name );
+
+ return rv;
+}
+
+
+static SECStatus
+listKeys( char *progName,
+ PK11SlotInfo *slot,
+ char *keyname,
+ void *pwdata )
+{
+ int count = 0;
+ int keys_found = 0;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ SECStatus rvPrint = SECFailure;
+
+ if( PK11_NeedLogin( /* slot */ slot ) ) {
+ PK11_Authenticate(
+ /* slot */ slot,
+ /* load certs */ PR_TRUE,
+ /* wincx */ pwdata );
+ }
+
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot(
+ /* slot */ slot,
+ /* nickname */ NULL,
+ /* wincx */ ( void *) pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while( symKey != NULL ) {
+ rvPrint = PrintSymKey( PR_STDOUT,
+ count,
+ keyname,
+ symKey );
+ if( rvPrint != SECFailure ) {
+ keys_found++;
+ }
+
+ nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
+ PK11_FreeSymKey( /* symmetric key */ symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ /* case 1: the token is empty */
+ if( count == 0 ) {
+ PR_fprintf( PR_STDOUT,
+ "\t%s: the specified token is empty\n",
+ progName );
+
+ return SECFailure;
+ }
+
+ /* case 2: the specified key is not on this token */
+ if( ( keyname != NULL ) &&
+ ( keys_found == 0 ) ) {
+ PR_fprintf( PR_STDOUT,
+ "\t%s: the key called \"%s\" could not be found\n",
+ progName,
+ keyname );
+
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+
+SECStatus
+TKS_ListKeys( char *progName,
+ PK11SlotInfo *slot,
+ char *keyname,
+ int index,
+ PRBool dopriv,
+ secuPWData *pwdata )
+{
+ SECStatus rv = SECSuccess;
+
+ if( slot == NULL ) {
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ list = PK11_GetAllTokens(
+ /* mechanism type */ CKM_INVALID_MECHANISM,
+ /* need R/W */ PR_FALSE,
+ /* load certs */ PR_FALSE,
+ /* wincx */ pwdata );
+
+ if( list ) {
+ for( le = list->head ; le ; le = le->next ) {
+ PR_fprintf( PR_STDOUT,
+ "\n slot: %s\n",
+ PK11_GetSlotName( /* slot */ le->slot ) );
+
+ PR_fprintf( PR_STDOUT,
+ "token: %s\n\n",
+ PK11_GetTokenName( /* slot */ le->slot ) );
+
+ rv = listKeys( progName,
+ le->slot,
+ keyname,
+ pwdata );
+ }
+ }
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "\n slot: %s\n",
+ PK11_GetSlotName( /* slot */ slot ) );
+
+ PR_fprintf( PR_STDOUT,
+ "token: %s\n\n",
+ PK11_GetTokenName( /* slot */ slot ) );
+
+ rv = listKeys( progName,
+ slot,
+ keyname,
+ pwdata );
+ }
+
+ return rv;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/modules.c b/pki/base/native-tools/src/tkstool/modules.c
new file mode 100644
index 000000000..0c4297251
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/modules.c
@@ -0,0 +1,63 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+/*
+ * L i s t S e c M o d u l e s
+ *
+ * Print a list of the PKCS11 security modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+SECStatus
+TKS_ListSecModules( void )
+{
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ /* get them all! */
+ list = PK11_GetAllTokens(
+ /* mechanism type */ CKM_INVALID_MECHANISM,
+ /* need R/W */ PR_FALSE,
+ /* load certs */ PR_FALSE,
+ /* wincx */ NULL );
+
+ if( list == NULL ) {
+ return SECFailure;
+ }
+
+ /* look at each slot */
+ for( le = list->head ; le ; le = le->next ) {
+ PR_fprintf ( PR_STDOUT,
+ "\n" );
+ PR_fprintf ( PR_STDOUT,
+ " slot: %s\n",
+ PK11_GetSlotName( /* slot */ le->slot ) );
+ PR_fprintf ( PR_STDOUT,
+ " token: %s\n",
+ PK11_GetTokenName( /* slot */ le->slot ) );
+ }
+
+ PK11_FreeSlotList( /* slot list */ list );
+
+ return SECSuccess;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/pppolicy.c b/pki/base/native-tools/src/tkstool/pppolicy.c
new file mode 100644
index 000000000..8b198ca52
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/pppolicy.c
@@ -0,0 +1,306 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/pppolicy.c
+ */
+
+/*
+ * Support for various policy related extensions
+ *
+ * $Id$
+ */
+
+#include "seccomon.h"
+#include "secport.h"
+#include "secder.h"
+#include "cert.h"
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
+** The chief difference is the addition of the OPTIONAL flag to many
+** parts. The idea is to be able to parse and print as much of the
+** policy extension as possible, even if some parts are invalid.
+**
+** If this approach still is unable to decode policy extensions that
+** contain invalid parts, then the next approach will be to parse
+** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
+** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
+** parse each of the PolicyQualifiers.
+*/
+
+static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyQualifier) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyQualifier, qualifierID) },
+ { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyQualifier, qualifierValue) },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyInfo, policyID) },
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyInfo, policyQualifiers),
+ secu_PolicyQualifierTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF,
+ offsetof(CERTCertificatePolicies, policyInfos),
+ secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
+};
+
+
+static CERTCertificatePolicies *
+secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
+{
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+ CERTCertificatePolicies *policies;
+ CERTPolicyInfo **policyInfos, *policyInfo;
+ CERTPolicyQualifier **policyQualifiers, *policyQualifier;
+ SECItem newExtnValue;
+
+ /* make a new arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+
+ /* allocate the certifiate policies structure */
+ policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
+ if ( policies == NULL ) {
+ goto loser;
+ }
+
+ policies->arena = arena;
+
+ /* copy the DER into the arena, since Quick DER returns data that points
+ into the DER input, which may get freed by the caller */
+ rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* decode the policy info */
+ rv = SEC_QuickDERDecodeItem(arena, policies,
+ secu_CertificatePoliciesTemplate,
+ &newExtnValue);
+
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* initialize the oid tags */
+ policyInfos = policies->policyInfos;
+ while (policyInfos != NULL && *policyInfos != NULL ) {
+ policyInfo = *policyInfos;
+ policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
+ policyQualifiers = policyInfo->policyQualifiers;
+ while ( policyQualifiers && *policyQualifiers != NULL ) {
+ policyQualifier = *policyQualifiers;
+ policyQualifier->oid =
+ SECOID_FindOIDTag(&policyQualifier->qualifierID);
+ policyQualifiers++;
+ }
+ policyInfos++;
+ }
+
+ return(policies);
+
+loser:
+ if ( arena != NULL ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+
+static char *
+itemToString(SECItem *item)
+{
+ char *string;
+
+ string = PORT_ZAlloc(item->len+1);
+ if (string == NULL) return NULL;
+ PORT_Memcpy(string,item->data,item->len);
+ string[item->len] = 0;
+ return string;
+}
+
+static SECStatus
+secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue,
+ char *msg, int level)
+{
+ CERTUserNotice *userNotice = NULL;
+ if (qualifierValue)
+ userNotice = CERT_DecodeUserNotice(qualifierValue);
+ if (userNotice) {
+ if (userNotice->noticeReference.organization.len != 0) {
+ char *string =
+ itemToString(&userNotice->noticeReference.organization);
+ SECItem **itemList = userNotice->noticeReference.noticeNumbers;
+
+ while (itemList && *itemList) {
+ SECU_PrintInteger(out,*itemList,string,level+1);
+ itemList++;
+ }
+ PORT_Free(string);
+ }
+ if (userNotice->displayText.len != 0) {
+ SECU_PrintString(out,&userNotice->displayText,
+ "Display Text", level+1);
+ }
+ CERT_DestroyUserNotice(userNotice);
+ return SECSuccess;
+ }
+ return SECFailure; /* caller will print this value */
+}
+
+static SECStatus
+secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,
+ char *msg,int level)
+{
+ SECStatus rv;
+ SECItem * qualifierValue = &policyQualifier->qualifierValue;
+
+ SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
+ "Policy Qualifier Name", level);
+ if (!qualifierValue->data) {
+ SECU_Indent(out, level);
+ fprintf(out,"Error: missing qualifier\n");
+ } else
+ switch (policyQualifier->oid) {
+ case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
+ rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
+ if (SECSuccess == rv)
+ break;
+ /* fall through on error */
+ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
+ default:
+ SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
+{
+ CERTPolicyQualifier **policyQualifiers;
+
+ policyQualifiers = policyInfo->policyQualifiers;
+ SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
+
+ while (policyQualifiers && *policyQualifiers != NULL) {
+ secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
+ policyQualifiers++;
+ }
+ return SECSuccess;
+}
+
+void
+SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCertificatePolicies *policies = NULL;
+ CERTPolicyInfo **policyInfos;
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out,"%s: \n",msg);
+ level++;
+ }
+ policies = secu_DecodeCertificatePoliciesExtension(value);
+ if (policies == NULL) {
+ SECU_PrintAny(out, value, "Invalid Policy Data", level);
+ return;
+ }
+
+ policyInfos = policies->policyInfos;
+ while (policyInfos && *policyInfos != NULL) {
+ secu_PrintPolicyInfo(out,*policyInfos,"",level);
+ policyInfos++;
+ }
+
+ CERT_DestroyCertificatePoliciesExtension(policies);
+}
+
+
+void
+SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level)
+{
+ CERTPrivKeyUsagePeriod * prd;
+ PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+ prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
+ if (!prd) {
+ goto loser;
+ }
+ if (prd->notBefore.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
+ }
+ if (prd->notAfter.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
+ }
+ if (!prd->notBefore.data && !prd->notAfter.data) {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
+loser:
+ SECU_PrintAny(out, value, msg, level);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+}
diff --git a/pki/base/native-tools/src/tkstool/random.c b/pki/base/native-tools/src/tkstool/random.c
new file mode 100644
index 000000000..49dfb525e
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/random.c
@@ -0,0 +1,173 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+UpdateRNG( void )
+{
+ char *randbuf;
+ int fd;
+ int i;
+ int count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+
+#define FPS PR_fprintf( PR_STDOUT,
+ FPS "\n");
+ FPS "A random seed must be generated that will be used in the\n");
+ FPS "creation of your key. One of the easiest ways to create a\n");
+ FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
+ FPS "\n");
+ FPS "To begin, type keys on the keyboard until this progress meter\n");
+ FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
+ FPS "\n");
+ FPS "\n");
+ FPS "Continue typing until the progress meter is full:\n\n");
+ FPS "| |\r|");
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno( stdin );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ tcgetattr( fd, &tio );
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ /* Get random noise from keyboard strokes */
+ randbuf = ( char * ) PORT_Alloc( RAND_BUF_LENGTH );
+ count = 0;
+ while( randbuf != NULL && count < NUM_KEYSTROKES+1 ) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc( stdin );
+#else
+ c = getch();
+#endif
+ if( c == EOF ) {
+ rv = -1;
+ break;
+ }
+
+ PK11_RandomUpdate(
+ /* data */ randbuf,
+ /* length in bytes */ RAND_BUF_LENGTH );
+
+ if( c != randbuf[0] ) {
+ randbuf[0] = c;
+
+ FPS "\r|");
+
+ for( i = 0 ;
+ i < count / ( NUM_KEYSTROKES / RAND_BUF_LENGTH ) ;
+ i++ ) {
+ FPS "*");
+ }
+
+ if( count % ( NUM_KEYSTROKES / RAND_BUF_LENGTH ) == 1 ) {
+ FPS "/");
+ }
+
+ count++;
+ }
+ }
+
+ if (randbuf != NULL) free (randbuf);
+
+ FPS "\n\n");
+ FPS "Finished.\n");
+
+ TKS_TypeProceedToContinue();
+
+ FPS "\n");
+
+#undef FPS
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ return rv;
+}
+
+
+void
+TKS_FileForRNG( char *noise )
+{
+ char buf[2048];
+ PRFileDesc *fd;
+ PRInt32 count;
+
+ fd = PR_OpenFile( noise, PR_RDONLY, 0666 );
+ if( !fd ) {
+ return;
+ }
+
+ do {
+ count = PR_Read( fd, buf, sizeof( buf ) );
+ if (count > 0) {
+ PK11_RandomUpdate(
+ /* data */ buf,
+ /* length in bytes */ count );
+ }
+ } while( count > 0 );
+
+ PR_Close( fd );
+}
+
+
+SECStatus
+TKS_SeedRNG( char *noise )
+{
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Seed the RNG */
+ if( noise ) {
+ TKS_FileForRNG( noise );
+ } else {
+ int rv = UpdateRNG();
+ if( rv ) {
+ PORT_SetError( PR_END_OF_FILE_ERROR );
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/retrieve.c b/pki/base/native-tools/src/tkstool/retrieve.c
new file mode 100644
index 000000000..44cf3c069
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/retrieve.c
@@ -0,0 +1,114 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+PK11SymKey *
+TKS_RetrieveSymKey( PK11SlotInfo *slot,
+ char *keyname,
+ void *pwdata )
+{
+ char *name = NULL;
+ int count = 0;
+ int keys_found = 0;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ PK11SymKey *rvSymKey = NULL;
+
+ if( PK11_NeedLogin( /* slot */ slot ) ) {
+ PK11_Authenticate(
+ /* slot */ slot,
+ /* load certs */ PR_TRUE,
+ /* wincx */ pwdata );
+ }
+
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot(
+ /* slot */ slot,
+ /* nickname */ NULL,
+ /* wincx */ ( void *) pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while( symKey != NULL ) {
+ name = PK11_GetSymKeyNickname( /* symmetric key */ symKey );
+ if( name != NULL ) {
+ if( keyname != NULL ) {
+ if( PL_strcmp( keyname, name ) == 0 ) {
+ keys_found++;
+ }
+ }
+ }
+
+ nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
+ PK11_FreeSymKey( /* symmetric key */ symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ /* case 1: the token is empty */
+ if( count == 0 ) {
+ /* the specified token is empty */
+ rvSymKey = NULL;
+ goto retrievedSymKey;
+ }
+
+ /* case 2: the specified key is not on this token */
+ if( ( keyname != NULL ) &&
+ ( keys_found == 0 ) ) {
+ /* the key called "keyname" could not be found */
+ rvSymKey = NULL;
+ goto retrievedSymKey;
+ }
+
+ /* case 3: the specified key exists more than once on this token */
+ if( keys_found != 1 ) {
+ /* more than one key called "keyname" was found on this token */
+ rvSymKey = NULL;
+ goto retrievedSymKey;
+ } else {
+ /* Re-initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot(
+ /* slot */ slot,
+ /* nickname */ NULL,
+ /* wincx */ ( void *) pwdata );
+
+ /* Reiterate through the symmetric key list once more, */
+ /* this time returning an actual reference to the key. */
+ while( symKey != NULL ) {
+ name = PK11_GetSymKeyNickname( /* symmetric key */ symKey );
+ if( name != NULL ) {
+ if( keyname != NULL ) {
+ if( PL_strcmp( keyname, name ) == 0 ) {
+ rvSymKey = symKey;
+ goto retrievedSymKey;
+ }
+ }
+ }
+
+ nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
+ PK11_FreeSymKey( /* symmetric key */ symKey );
+ symKey = nextSymKey;
+ }
+ }
+
+retrievedSymKey:
+ return rvSymKey;
+}
+
diff --git a/pki/base/native-tools/src/tkstool/secerror.c b/pki/base/native-tools/src/tkstool/secerror.c
new file mode 100644
index 000000000..6b0f40d70
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/secerror.c
@@ -0,0 +1,118 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/secerror.c
+ */
+
+#include "nspr.h"
+
+struct tuple_str {
+ PRErrorCode errNum;
+ const char * errString;
+};
+
+typedef struct tuple_str tuple_str;
+
+#define ER2(a,b) {a, b},
+#define ER3(a,b,c) {a, c},
+
+#include "secerr.h"
+#include "sslerr.h"
+
+const tuple_str errStrings[] = {
+
+/* keep this list in asceding order of error numbers */
+#include "SSLerrs.h"
+#include "SECerrs.h"
+#include "NSPRerrs.h"
+
+};
+
+const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str);
+
+/* Returns a UTF-8 encoded constant error string for "errNum".
+ * Returns NULL of errNum is unknown.
+ */
+const char *
+SECU_Strerror(PRErrorCode errNum) {
+ PRInt32 low = 0;
+ PRInt32 high = numStrings - 1;
+ PRInt32 i;
+ PRErrorCode num;
+ static int initDone;
+
+ /* make sure table is in ascending order.
+ * binary search depends on it.
+ */
+ if (!initDone) {
+ PRErrorCode lastNum = ((PRInt32)0x80000000);
+ for (i = low; i <= high; ++i) {
+ num = errStrings[i].errNum;
+ if (num <= lastNum) {
+ fprintf(stderr,
+"sequence error in error strings at item %d\n"
+"error %d (%s)\n"
+"should come after \n"
+"error %d (%s)\n",
+ i, lastNum, errStrings[i-1].errString,
+ num, errStrings[i].errString);
+ }
+ lastNum = num;
+ }
+ initDone = 1;
+ }
+
+ /* Do binary search of table. */
+ while (low + 1 < high) {
+ i = (low + high) / 2;
+ num = errStrings[i].errNum;
+ if (errNum == num)
+ return errStrings[i].errString;
+ if (errNum < num)
+ high = i;
+ else
+ low = i;
+ }
+ if (errNum == errStrings[low].errNum)
+ return errStrings[low].errString;
+ if (errNum == errStrings[high].errNum)
+ return errStrings[high].errString;
+ return NULL;
+}
diff --git a/pki/base/native-tools/src/tkstool/secpwd.c b/pki/base/native-tools/src/tkstool/secpwd.c
new file mode 100644
index 000000000..542885858
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/secpwd.c
@@ -0,0 +1,213 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/secpwd.c
+ */
+
+#include "secutil.h"
+
+/*
+ * NOTE: The contents of this file are NOT used by the client.
+ * (They are part of the security library as a whole, but they are
+ * NOT USED BY THE CLIENT.) Do not change things on behalf of the
+ * client (like localizing strings), or add things that are only
+ * for the client (put them elsewhere).
+ */
+
+
+#ifdef XP_UNIX
+#include <termios.h>
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#include <unistd.h> /* for isatty() */
+#endif
+
+#if( defined(_WINDOWS) && !defined(_WIN32_WCE)) || defined(XP_OS2_VACPP)
+#include <conio.h>
+#include <io.h>
+#define QUIET_FGETS quiet_fgets
+static char * quiet_fgets (char *buf, int length, FILE *input);
+#else
+#define QUIET_FGETS fgets
+#endif
+
+static void echoOff(int fd)
+{
+#if defined(XP_UNIX) && !defined(VMS)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+static void echoOn(int fd)
+{
+#if defined(XP_UNIX) && !defined(VMS)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag |= ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+char *SEC_GetPassword(FILE *input, FILE *output, char *prompt,
+ PRBool (*ok)(char *))
+{
+#if defined(_WINDOWS)
+ int isTTY = (input == stdin);
+#define echoOn(x)
+#define echoOff(x)
+#else
+ int infd = fileno(input);
+ int isTTY = isatty(infd);
+#endif
+ char phrase[200] = {'\0'}; /* ensure EOF doesn't return junk */
+
+ for (;;) {
+ /* Prompt for password */
+ if (isTTY) {
+ fprintf(output, "%s", prompt);
+ fflush (output);
+ echoOff(infd);
+ }
+
+ QUIET_FGETS ( phrase, sizeof(phrase), input);
+
+ if (isTTY) {
+ fprintf(output, "\n");
+ echoOn(infd);
+ }
+
+ /* stomp on newline */
+ phrase[PORT_Strlen(phrase)-1] = 0;
+
+ /* Validate password */
+ if (!(*ok)(phrase)) {
+ /* Not weird enough */
+ if (!isTTY) return 0;
+ fprintf(output, "Password must be at least 8 characters long with one or more\n");
+ fprintf(output, "non-alphabetic characters\n");
+ continue;
+ }
+ return (char*) PORT_Strdup(phrase);
+ }
+}
+
+
+
+PRBool SEC_CheckPassword(char *cp)
+{
+ int len;
+ char *end;
+
+ len = PORT_Strlen(cp);
+ if (len < 8) {
+ return PR_FALSE;
+ }
+ end = cp + len;
+ while (cp < end) {
+ unsigned char ch = *cp++;
+ if (!((ch >= 'A') && (ch <= 'Z')) &&
+ !((ch >= 'a') && (ch <= 'z'))) {
+ /* pass phrase has at least one non alphabetic in it */
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool SEC_BlindCheckPassword(char *cp)
+{
+ if (cp != NULL) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/* Get a password from the input terminal, without echoing */
+
+#if defined(_WINDOWS) || defined(XP_OS2_VACPP)
+static char * quiet_fgets (char *buf, int length, FILE *input)
+ {
+ int c;
+ char *end = buf;
+
+ /* fflush (input); */
+ memset (buf, 0, length);
+
+#ifndef XP_OS2_VACPP
+ if (input != stdin) {
+ return fgets(buf,length,input);
+ }
+#else
+ if (!isatty(fileno(input))) {
+ return fgets(buf,length,input);
+ }
+#endif
+
+ while (1)
+ {
+#if defined (_WIN32_WCE)
+ c = getchar(); /* gets a character from stdin */
+#else
+ c = getch(); /* getch gets a character from the console */
+#endif
+ if (c == '\b')
+ {
+ if (end > buf)
+ end--;
+ }
+
+ else if (--length > 0)
+ *end++ = c;
+
+ if (!c || c == '\n' || c == '\r')
+ break;
+ }
+
+ return buf;
+ }
+#endif
diff --git a/pki/base/native-tools/src/tkstool/secutil.c b/pki/base/native-tools/src/tkstool/secutil.c
new file mode 100644
index 000000000..9ece007fa
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/secutil.c
@@ -0,0 +1,3662 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/secutil.c
+ */
+
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+#include "prnetdb.h"
+
+#include "cryptohi.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include <stdarg.h>
+#if !defined(_WIN32_WCE)
+#include <sys/stat.h>
+#include <errno.h>
+#endif
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "certt.h"
+#include "certdb.h"
+
+/* #include "secmod.h" */
+#include "pk11func.h"
+#include "secoid.h"
+
+static char consoleName[] = {
+#ifdef XP_UNIX
+#ifdef VMS
+ "TT"
+#else
+ "/dev/tty"
+#endif
+#else
+#ifdef XP_OS2
+ "\\DEV\\CON"
+#else
+ "CON:"
+#endif
+#endif
+};
+
+
+char *
+SECU_GetString(int16 error_number)
+{
+
+ static char errString[80];
+ sprintf(errString, "Unknown error string (%d)", error_number);
+ return errString;
+}
+
+void
+SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errString = SECU_Strerror(err);
+
+ va_start(args, msg);
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", progName);
+ vfprintf(out, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(out, ": %s\n", errString);
+ else
+ fprintf(out, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
+SECU_PrintError(char *progName, char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errString = SECU_Strerror(err);
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(stderr, ": %s\n", errString);
+ else
+ fprintf(stderr, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
+SECU_PrintSystemError(char *progName, char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+#if defined(_WIN32_WCE)
+ fprintf(stderr, ": %d\n", PR_GetOSError());
+#else
+ fprintf(stderr, ": %s\n", strerror(errno));
+#endif
+ va_end(args);
+}
+
+static void
+secu_ClearPassword(char *p)
+{
+ if (p) {
+ PORT_Memset(p, 0, PORT_Strlen(p));
+ PORT_Free(p);
+ }
+}
+
+char *
+SECU_GetPasswordString(void *arg, char *prompt)
+{
+#ifndef _WINDOWS
+ char *p = NULL;
+ FILE *input, *output;
+
+ /* open terminal */
+ input = fopen(consoleName, "r");
+ if (input == NULL) {
+ fprintf(stderr, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ fprintf(stderr, "Error opening output terminal for write\n");
+ fclose(input);
+ return NULL;
+ }
+
+ p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
+
+
+ fclose(input);
+ fclose(output);
+
+ return p;
+
+#else
+ /* Win32 version of above. opening the console may fail
+ on windows95, and certainly isn't necessary.. */
+
+ char *p = NULL;
+
+ p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
+ return p;
+
+#endif
+}
+
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -f(pwfile) argument
+ * of the command line.
+ * After use once, null it out otherwise PKCS11 calls us forever.?
+ *
+ */
+char *
+SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ unsigned char phrase[200];
+ PRFileDesc *fd;
+ PRInt32 nb;
+ char *pwFile = arg;
+ int i;
+
+ if (!pwFile)
+ return 0;
+
+ if (retry) {
+ return 0; /* no good retrying - the files contents will be the same */
+ }
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrase, sizeof(phrase));
+
+ PR_Close(fd);
+ /* handle the Windows EOL case */
+ i = 0;
+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
+ phrase[i] = '\0';
+ if (nb == 0) {
+ fprintf(stderr,"password file contains no data\n");
+ return NULL;
+ }
+ return (char*) PORT_Strdup((char*)phrase);
+}
+
+char *
+SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char prompt[255];
+ secuPWData *pwdata = (secuPWData *)arg;
+ secuPWData pwnull = { PW_NONE, 0 };
+ secuPWData pwxtrn = { PW_EXTERNAL, "external" };
+ char *pw;
+
+ if (pwdata == NULL)
+ pwdata = &pwnull;
+
+ if (PK11_ProtectedAuthenticationPath(slot)) {
+ pwdata = &pwxtrn;
+ }
+ if (retry && pwdata->source != PW_NONE) {
+ PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
+ return NULL;
+ }
+
+ switch (pwdata->source) {
+ case PW_NONE:
+ sprintf(prompt, "Enter Password or Pin for \"%s\":",
+ PK11_GetTokenName(slot));
+ return SECU_GetPasswordString(NULL, prompt);
+ case PW_FROMFILE:
+ /* Instead of opening and closing the file every time, get the pw
+ * once, then keep it in memory (duh).
+ */
+ pw = SECU_FilePasswd(slot, retry, pwdata->data);
+ pwdata->source = PW_PLAINTEXT;
+ pwdata->data = PL_strdup(pw);
+ /* it's already been dup'ed */
+ return pw;
+ case PW_EXTERNAL:
+ sprintf(prompt,
+ "Press Enter, then enter PIN for \"%s\" on external device.\n",
+ PK11_GetTokenName(slot));
+ (void) SECU_GetPasswordString(NULL, prompt);
+ /* Fall Through */
+ case PW_PLAINTEXT:
+ return PL_strdup(pwdata->data);
+ default:
+ break;
+ }
+
+ PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
+ return NULL;
+}
+
+char *
+secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *p0 = NULL;
+ char *p1 = NULL;
+ FILE *input, *output;
+ secuPWData *pwdata = arg;
+
+ if (pwdata->source == PW_FROMFILE) {
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ }
+ if (pwdata->source == PW_PLAINTEXT) {
+ return PL_strdup(pwdata->data);
+ }
+
+ /* PW_NONE - get it from tty */
+ /* open terminal */
+#ifdef _WINDOWS
+ input = stdin;
+#else
+ input = fopen(consoleName, "r");
+#endif
+ if (input == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ /* we have no password, so initialize database with one */
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least 8 characters long,\n"
+ "and should contain at least one non-alphabetic character.\n\n");
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
+ fclose(input);
+ return NULL;
+ }
+
+
+ for (;;) {
+ if (p0)
+ PORT_Free(p0);
+ p0 = SEC_GetPassword(input, output, "Enter new password: ",
+ SEC_BlindCheckPassword);
+
+ if (p1)
+ PORT_Free(p1);
+ p1 = SEC_GetPassword(input, output, "Re-enter password: ",
+ SEC_BlindCheckPassword);
+ if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
+ break;
+ }
+ PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
+ }
+
+ /* clear out the duplicate password string */
+ secu_ClearPassword(p1);
+
+ fclose(input);
+ fclose(output);
+
+ return p0;
+}
+
+SECStatus
+SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
+{
+ SECStatus rv;
+ secuPWData pwdata, newpwdata;
+ char *oldpw = NULL, *newpw = NULL;
+
+ if (passwd) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = passwd;
+ } else if (pwFile) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwFile;
+ } else {
+ pwdata.source = PW_NONE;
+ pwdata.data = NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
+ rv = PK11_InitPin(slot, (char*)NULL, newpw);
+ goto done;
+ }
+
+ for (;;) {
+ oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
+
+ if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ if (pwdata.source == PW_NONE) {
+ PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
+ } else {
+ PR_fprintf(PR_STDERR, "Invalid password.\n");
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+ return SECFailure;
+ }
+ } else
+ break;
+
+ PORT_Free(oldpw);
+ }
+
+ newpwdata.source = PW_NONE;
+ newpwdata.data = NULL;
+
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
+
+ if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to change password.\n");
+ return SECFailure;
+ }
+
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+
+ PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
+
+done:
+ PORT_Memset(newpw, 0, PL_strlen(newpw));
+ PORT_Free(newpw);
+ return SECSuccess;
+}
+
+struct matchobj {
+ SECItem index;
+ char *nname;
+ PRBool found;
+};
+
+char *
+SECU_DefaultSSLDir(void)
+{
+ char *dir;
+ static char sslDir[1000];
+
+ dir = PR_GetEnv("SSL_DIR");
+ if (!dir)
+ return NULL;
+
+ sprintf(sslDir, "%s", dir);
+
+ if (sslDir[strlen(sslDir)-1] == '/')
+ sslDir[strlen(sslDir)-1] = 0;
+
+ return sslDir;
+}
+
+char *
+SECU_AppendFilenameToDir(char *dir, char *filename)
+{
+ static char path[1000];
+
+ if (dir[strlen(dir)-1] == '/')
+ sprintf(path, "%s%s", dir, filename);
+ else
+ sprintf(path, "%s/%s", dir, filename);
+ return path;
+}
+
+char *
+SECU_ConfigDirectory(const char* base)
+{
+ static PRBool initted = PR_FALSE;
+ const char *dir = ".netscape";
+ char *home;
+ static char buf[1000];
+
+ if (initted) return buf;
+
+
+ if (base == NULL || *base == 0) {
+ home = PR_GetEnv("HOME");
+ if (!home) home = "";
+
+ if (*home && home[strlen(home) - 1] == '/')
+ sprintf (buf, "%.900s%s", home, dir);
+ else
+ sprintf (buf, "%.900s/%s", home, dir);
+ } else {
+ sprintf(buf, "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+/*Turn off SSL for now */
+/* This gets called by SSL when server wants our cert & key */
+int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ int errsave;
+
+ if (arg == NULL) {
+ fprintf(stderr, "no key/cert name specified for client auth\n");
+ return -1;
+ }
+ cert = PK11_FindCertFromNickname(arg, NULL);
+ errsave = PORT_GetError();
+ if (!cert) {
+ if (errsave == SEC_ERROR_BAD_PASSWORD)
+ fprintf(stderr, "Bad password\n");
+ else if (errsave > 0)
+ fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
+ else if (errsave == SEC_ERROR_BAD_DATABASE)
+ fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
+ else
+ fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
+ return -1;
+ }
+
+ key = PK11_FindKeyByAnyCert(arg,NULL);
+ if (!key) {
+ fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
+ return -1;
+ }
+
+
+ *pRetCert = cert;
+ *pRetKey = key;
+
+ return 0;
+}
+
+SECStatus
+secu_StdinToItem(SECItem *dst)
+{
+ unsigned char buf[1000];
+ PRInt32 numBytes;
+ PRBool notDone = PR_TRUE;
+
+ dst->len = 0;
+ dst->data = NULL;
+
+ while (notDone) {
+ numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
+
+ if (numBytes < 0) {
+ return SECFailure;
+ }
+
+ if (numBytes == 0)
+ break;
+
+ if (dst->data) {
+ unsigned char * p = dst->data;
+ dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
+ if (!dst->data) {
+ PORT_Free(p);
+ }
+ } else {
+ dst->data = (unsigned char*)PORT_Alloc(numBytes);
+ }
+ if (!dst->data) {
+ return SECFailure;
+ }
+ PORT_Memcpy(dst->data + dst->len, buf, numBytes);
+ dst->len += numBytes;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECU_FileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, info.size))
+ goto loser;
+
+ numBytes = PR_Read(src, dst->data, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ return SECSuccess;
+loser:
+ SECITEM_FreeItem(dst, PR_FALSE);
+ return SECFailure;
+}
+
+SECStatus
+SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ unsigned char *buf;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ buf = (unsigned char*)PORT_Alloc(info.size);
+ if (!buf)
+ return SECFailure;
+
+ numBytes = PR_Read(src, buf, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ if (buf[numBytes-1] == '\n') numBytes--;
+#ifdef _WINDOWS
+ if (buf[numBytes-1] == '\r') numBytes--;
+#endif
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, numBytes))
+ goto loser;
+
+ memcpy(dst->data, buf, numBytes);
+
+ PORT_Free(buf);
+ return SECSuccess;
+loser:
+ PORT_Free(buf);
+ return SECFailure;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
+{
+ SECStatus rv;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+ char *asc, *body;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ asc = (char *)filedata.data;
+ if (!asc) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+
+ /* check for headers and trailers and remove them */
+ if ((body = strstr(asc, "-----BEGIN")) != NULL) {
+ char *trailer = NULL;
+ asc = body;
+ body = PORT_Strchr(body, '\n');
+ if (!body)
+ body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
+ if (body)
+ trailer = strstr(++body, "-----END");
+ if (trailer != NULL) {
+ *trailer = '\0';
+ } else {
+ fprintf(stderr, "input has header but no trailer\n");
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+ } else {
+ body = asc;
+ }
+
+ /* Convert to binary */
+ rv = ATOB_ConvertAsciiToItem(der, body);
+ if (rv) {
+ fprintf(stderr, "error converting ascii to binary (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+
+ PORT_Free(filedata.data);
+ } else {
+ /* Read in binary der */
+ rv = SECU_FileToItem(der, inFile);
+ if (rv) {
+ fprintf(stderr, "error converting der (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+#define INDENT_MULT 4
+void
+SECU_Indent(FILE *out, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++) {
+ fprintf(out, " ");
+ }
+}
+
+static void secu_Newline(FILE *out)
+{
+ fprintf(out, "\n");
+}
+
+void
+SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
+{
+ unsigned i;
+ int column;
+ PRBool isString = PR_TRUE;
+ PRBool isWhiteSpace = PR_TRUE;
+ PRBool printedHex = PR_FALSE;
+ unsigned int limit = 15;
+
+ if ( m ) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ level++;
+ }
+
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ if (!data->len) {
+ fprintf(out, "(empty)\n");
+ return;
+ }
+ /* take a pass to see if it's all printable. */
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+ if (!val || !isprint(val)) {
+ isString = PR_FALSE;
+ break;
+ }
+ if (isWhiteSpace && !isspace(val)) {
+ isWhiteSpace = PR_FALSE;
+ }
+ }
+
+ /* Short values, such as bit strings (which are printed with this
+ ** function) often look like strings, but we want to see the bits.
+ ** so this test assures that short values will be printed in hex,
+ ** perhaps in addition to being printed as strings.
+ ** The threshold size (4 bytes) is arbitrary.
+ */
+ if (!isString || data->len <= 4) {
+ for (i = 0; i < data->len; i++) {
+ if (i != data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ column += 3;
+ } else {
+ fprintf(out, "%02x", data->data[i]);
+ column += 2;
+ break;
+ }
+ if (column > 76 || (i % 16 == limit)) {
+ secu_Newline(out);
+ SECU_Indent(out, level);
+ column = level*INDENT_MULT;
+ limit = i % 16;
+ }
+ }
+ printedHex = PR_TRUE;
+ }
+ if (isString && !isWhiteSpace) {
+ if (printedHex != PR_FALSE) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+
+ if (val) {
+ fprintf(out,"%c",val);
+ column++;
+ } else {
+ column = 77;
+ }
+ if (column > 76) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ }
+ }
+
+ if (column != level*INDENT_MULT) {
+ secu_Newline(out);
+ }
+}
+
+static const char *hex = "0123456789abcdef";
+
+static const char printable[257] = {
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
+};
+
+void
+SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
+{
+ const unsigned char *cp = (const unsigned char *)vp;
+ char buf[80];
+ char *bp;
+ char *ap;
+
+ fprintf(out, "%s [Len: %d]\n", msg, len);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ while (--len >= 0) {
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
+ }
+ if (bp > buf) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ }
+}
+
+SECStatus
+SECU_StripTagAndLength(SECItem *i)
+{
+ unsigned int start;
+
+ if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ return SECFailure;
+ }
+ start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
+ if (i->len < start) {
+ return SECFailure;
+ }
+ i->data += start;
+ i->len -= start;
+ return SECSuccess;
+}
+
+
+/* This expents i->data[0] to be the MSB of the integer.
+** if you want to print a DER-encoded integer (with the tag and length)
+** call SECU_PrintEncodedInteger();
+*/
+void
+SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level)
+{
+ int iv;
+
+ if (!i || !i->len || !i->data) {
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: (null)\n", m);
+ } else {
+ fprintf(out, "(null)\n");
+ }
+ } else if (i->len > 4) {
+ SECU_PrintAsHex(out, i, m, level);
+ } else {
+ iv = DER_GetInteger(i);
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
+ } else {
+ fprintf(out, "%d (0x%x)\n", iv, iv);
+ }
+ }
+}
+
+static void
+secu_PrintRawString(FILE *out, SECItem *si, char *m, int level)
+{
+ int column;
+ unsigned int i;
+
+ if ( m ) {
+ SECU_Indent(out, level); fprintf(out, "%s: ", m);
+ column = (level * INDENT_MULT) + strlen(m) + 2;
+ level++;
+ } else {
+ SECU_Indent(out, level);
+ column = level*INDENT_MULT;
+ }
+ fprintf(out, "\""); column++;
+
+ for (i = 0; i < si->len; i++) {
+ unsigned char val = si->data[i];
+ if (column > 76) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+
+ fprintf(out,"%c", printable[val]); column++;
+ }
+
+ fprintf(out, "\""); column++;
+ if (column != level*INDENT_MULT || column > 76) {
+ secu_Newline(out);
+ }
+}
+
+void
+SECU_PrintString(FILE *out, SECItem *si, char *m, int level)
+{
+ SECItem my = *si;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
+ return;
+ secu_PrintRawString(out, &my, m, level);
+}
+
+/* print an unencoded boolean */
+static void
+secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
+{
+ int val = 0;
+
+ if ( i->data && i->len ) {
+ val = i->data[0];
+ }
+
+ if (!m) {
+ m = "Boolean";
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
+}
+
+/*
+ * Format and print "time". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+static void
+secu_PrintTime(FILE *out, int64 time, char *m, int level)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
+
+ timeString = PORT_Alloc(100);
+ if (timeString == NULL)
+ return;
+
+ if (m != NULL) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", m);
+ }
+
+ PR_FormatTime(timeString, 100, "%a %b %d %H:%M:%S %Y", &printableTime);
+ fprintf(out, timeString);
+
+ if (m != NULL)
+ fprintf(out, "\n");
+
+ PORT_Free(timeString);
+}
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level)
+{
+ int64 time;
+ SECStatus rv;
+
+ rv = DER_UTCTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, int level)
+{
+ int64 time;
+ SECStatus rv;
+
+
+ rv = DER_GeneralizedTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level)
+{
+ switch (t->type) {
+ case siUTCTime:
+ SECU_PrintUTCTime(out, t, m, level);
+ break;
+
+ case siGeneralizedTime:
+ SECU_PrintGeneralizedTime(out, t, m, level);
+ break;
+
+ default:
+ PORT_Assert(0);
+ break;
+ }
+}
+
+
+/* This prints a SET or SEQUENCE */
+void
+SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
+{
+ int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
+ const char * label;
+ SECItem my = *t;
+
+ if (!constructed) {
+ SECU_PrintAsHex(out, t, m, level);
+ return;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ return;
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+
+ if (type == SEC_ASN1_SET)
+ label = "Set ";
+ else if (type == SEC_ASN1_SEQUENCE)
+ label = "Sequence ";
+ else
+ label = "";
+ fprintf(out,"%s{\n", label); /* } */
+
+ while (my.len >= 2) {
+ SECItem tmp = my;
+
+ if (tmp.data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = tmp.data[1] & 0x7f;
+ if (lenlen > sizeof tmp.len)
+ break;
+ tmp.len = 0;
+ for (i=0; i < lenlen; i++) {
+ tmp.len = (tmp.len << 8) | tmp.data[2+i];
+ }
+ tmp.len += lenlen + 2;
+ } else {
+ tmp.len = tmp.data[1] + 2;
+ }
+ if (tmp.len > my.len) {
+ tmp.len = my.len;
+ }
+ my.data += tmp.len;
+ my.len -= tmp.len;
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
+}
+
+static void
+secu_PrintContextSpecific(FILE *out, SECItem *i, char *m, int level)
+{
+ int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
+ SECItem tmp;
+
+ if (constructed) {
+ char * m2;
+ if (!m)
+ m2 = PR_smprintf("[%d]", type);
+ else
+ m2 = PR_smprintf("%s: [%d]", m, type);
+ if (m2) {
+ SECU_PrintSet(out, i, m2, level);
+ PR_smprintf_free(m2);
+ }
+ return;
+ }
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+ fprintf(out,"[%d]\n", type);
+
+ tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level+1);
+}
+
+static void
+secu_PrintOctetString(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level);
+}
+
+static void
+secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
+ return;
+
+ unused_bits = *tmp.data++;
+ tmp.len--;
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+/* in a decoded bit string, the len member is a bit length. */
+static void
+secu_PrintDecodedBitString(FILE *out, SECItem *i, char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+
+ unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
+ DER_ConvertBitString(&tmp); /* convert length to byte length */
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+
+/* Print a DER encoded Boolean */
+void
+SECU_PrintEncodedBoolean(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ secu_PrintBoolean(out, &my, m, level);
+}
+
+/* Print a DER encoded integer */
+void
+SECU_PrintEncodedInteger(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintInteger(out, &my, m, level);
+}
+
+/* Print a DER encoded OID */
+void
+SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintObjectID(out, &my, m, level);
+}
+
+static void
+secu_PrintBMPString(FILE *out, SECItem *i, char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 2)
+ goto loser;
+ len = (int)(my.len / 2);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversalString(FILE *out, SECItem *i, char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 4)
+ goto loser;
+ len = (int)(my.len / 4);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+ s += 4;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
+{
+ switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_ENUMERATED:
+ case SEC_ASN1_INTEGER:
+ SECU_PrintEncodedInteger(out, i, m, level);
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ SECU_PrintEncodedObjectID(out, i, m, level);
+ break;
+ case SEC_ASN1_BOOLEAN:
+ SECU_PrintEncodedBoolean(out, i, m, level);
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_T61_STRING:
+ SECU_PrintString(out, i, m, level);
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ SECU_PrintGeneralizedTime(out, i, m, level);
+ break;
+ case SEC_ASN1_UTC_TIME:
+ SECU_PrintUTCTime(out, i, m, level);
+ break;
+ case SEC_ASN1_NULL:
+ SECU_Indent(out, level);
+ if (m && m[0])
+ fprintf(out, "%s: NULL\n", m);
+ else
+ fprintf(out, "NULL\n");
+ break;
+ case SEC_ASN1_SET:
+ case SEC_ASN1_SEQUENCE:
+ SECU_PrintSet(out, i, m, level);
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ secu_PrintOctetString(out, i, m, level);
+ break;
+ case SEC_ASN1_BIT_STRING:
+ secu_PrintBitString(out, i, m, level);
+ break;
+ case SEC_ASN1_BMP_STRING:
+ secu_PrintBMPString(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL_STRING:
+ secu_PrintUniversalString(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+}
+
+void
+SECU_PrintAny(FILE *out, SECItem *i, char *m, int level)
+{
+ if ( i && i->len && i->data ) {
+ switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ secu_PrintContextSpecific(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL:
+ secu_PrintUniversal(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+ }
+}
+
+static int
+secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level+1);
+ SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level+1);
+ return 0;
+}
+
+/* This function does NOT expect a DER type and length. */
+SECOidTag
+SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
+{
+ SECOidData *oiddata;
+ char * oidString = NULL;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata != NULL) {
+ const char *name = oiddata->desc;
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", name);
+ return oiddata->offset;
+ }
+ oidString = CERT_GetOidString(oid);
+ if (oidString) {
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", oidString);
+ PR_smprintf_free(oidString);
+ return SEC_OID_UNKNOWN;
+ }
+ SECU_PrintAsHex(out, oid, m, level);
+ return SEC_OID_UNKNOWN;
+}
+
+
+/* This function does NOT expect a DER type and length. */
+void
+SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
+{
+ SECU_PrintObjectID(out, &a->algorithm, m, level);
+
+ if (a->parameters.len == 0
+ || (a->parameters.len == 2
+ && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else {
+ /* Print args to algorithm */
+ SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
+ }
+}
+
+static void
+secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ if (m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ }
+
+ /*
+ * Should make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i++]) != NULL) {
+ sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ SECU_PrintAny(out, value, om, level+1);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ SECU_PrintAsHex(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ SECU_PrintObjectID(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ SECU_PrintTimeChoice(out, value, om, level+1);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
+ SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
+ if (pk->u.rsa.publicExponent.len == 1 &&
+ pk->u.rsa.publicExponent.data[0] == 1) {
+ SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
+ }
+}
+
+static void
+secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
+}
+
+#ifdef NSS_ENABLE_ECC
+static void
+secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECItem curveOID = { siBuffer, NULL, 0};
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1);
+ /* For named curves, the DEREncodedParams field contains an
+ * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
+ */
+ if ((pk->u.ec.DEREncodedParams.len > 2) &&
+ (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
+ curveOID.len = pk->u.ec.DEREncodedParams.data[1];
+ curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
+ SECU_PrintObjectID(out, &curveOID, "Curve", level +1);
+ }
+}
+#endif /* NSS_ENABLE_ECC */
+
+static void
+secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg, int level)
+{
+ SECKEYPublicKey *pk;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
+ SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
+
+ pk = SECKEY_ExtractPublicKey(i);
+ if (pk) {
+ switch (pk->keyType) {
+ case rsaKey:
+ secu_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
+ break;
+
+ case dsaKey:
+ secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
+ break;
+
+#ifdef NSS_ENABLE_ECC
+ case ecKey:
+ secu_PrintECPublicKey(out, pk, "EC Public Key", level +1);
+ break;
+#endif
+
+ case dhKey:
+ case fortezzaKey:
+ case keaKey:
+ SECU_Indent(out, level);
+ fprintf(out, "unable to format this SPKI algorithm type\n");
+ goto loser;
+ default:
+ SECU_Indent(out, level);
+ fprintf(out, "unknown SPKI algorithm type\n");
+ goto loser;
+ }
+ PORT_FreeArena(pk->arena, PR_FALSE);
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
+loser:
+ if (i->subjectPublicKey.data) {
+ SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
+ }
+ }
+}
+
+static SECStatus
+secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ int64 invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii
+ (invalidTime, "%a %b %d %H:%M:%S %Y");
+ SECU_Indent(out, level +1);
+ fprintf (out, "%s: %s\n", msg, formattedTime);
+ PORT_Free (formattedTime);
+ }
+ }
+ PORT_Free (decodedValue.data);
+ return (rv);
+}
+
+static SECStatus
+PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTOidSequence *os;
+ SECItem **op;
+
+ os = CERT_DecodeOidSequence(value);
+ if( (CERTOidSequence *)NULL == os ) {
+ return SECFailure;
+ }
+
+ for( op = os->oids; *op; op++ ) {
+ SECU_PrintObjectID(out, *op, msg, level + 1);
+ }
+ CERT_DestroyOidSequence(os);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
+ CERTBasicConstraints constraints;
+ SECStatus rv;
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out,"%s: ",msg);
+ }
+ rv = CERT_DecodeBasicConstraintValue(&constraints,value);
+ if (rv == SECSuccess && constraints.isCA) {
+ if (constraints.pathLenConstraint >= 0) {
+ fprintf(out,"Is a CA with a maximum path length of %d.\n",
+ constraints.pathLenConstraint);
+ } else {
+ fprintf(out,"Is a CA with no maximum path length.\n");
+ }
+ } else {
+ fprintf(out,"Is not a CA.\n");
+ }
+ return SECSuccess;
+}
+
+static const char * const nsTypeBits[] = {
+ "SSL Client",
+ "SSL Server",
+ "S/MIME",
+ "Object Signing",
+ "Reserved",
+ "SSL CA",
+ "S/MIME CA",
+ "ObjectSigning CA"
+};
+
+/* NSCertType is merely a bit string whose bits are displayed symbolically */
+static SECStatus
+secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int NS_Type;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return SECSuccess;
+ }
+
+ unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
+ NS_Type = my.data[1] & (0xff << unused);
+
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out,"%s: ",msg);
+ } else {
+ fprintf(out,"Netscape Certificate Type: ");
+ }
+ for (i=0; i < 8; i++) {
+ if ( (0x80 >> i) & NS_Type) {
+ fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
+ found = 1;
+ }
+ }
+ fprintf(out, (found ? ">\n" : "none\n"));
+ return SECSuccess;
+}
+
+static const char * const usageBits[] = {
+ "Digital Signature", /* 0x80 */
+ "Non-Repudiation", /* 0x40 */
+ "Key Encipherment", /* 0x20 */
+ "Data Encipherment", /* 0x10 */
+ "Key Agreement", /* 0x08 */
+ "Certificate Signing", /* 0x04 */
+ "CRL Signing", /* 0x02 */
+ "Encipher Only", /* 0x01 */
+ "Decipher Only", /* 0x0080 */
+ NULL
+};
+
+/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
+static void
+secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int usage;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return;
+ }
+
+ unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
+ usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
+ : (my.data[1] << 8) |
+ (my.data[2] & (0xff << unused));
+
+ SECU_Indent(out, level);
+ fprintf(out, "Usages: ");
+ for (i=0; usageBits[i]; i++) {
+ if ( (0x8000 >> i) & usage) {
+ if (found)
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s\n", usageBits[i]);
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(out, "(none)\n");
+ }
+}
+
+static void
+secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
+{
+ PRStatus st;
+ PRNetAddr addr;
+ char addrBuf[80];
+
+ memset(&addr, 0, sizeof addr);
+ if (value->len == 4) {
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, value->data, value->len);
+ } else if (value->len == 16) {
+ addr.ipv6.family = PR_AF_INET6;
+ memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
+ /* convert to IPv4. */
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
+ memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
+ }
+ } else {
+ goto loser;
+ }
+
+ st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
+ if (st == PR_SUCCESS) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", msg, addrBuf);
+ } else {
+loser:
+ SECU_PrintAsHex(out, value, msg, level);
+ }
+}
+
+
+static void
+secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ char label[40];
+ if (msg && msg[0]) {
+ SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
+ }
+ switch (gname->type) {
+ case certOtherName :
+ SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
+ SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
+ break;
+ case certDirectoryName :
+ SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
+ break;
+ case certRFC822Name :
+ secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
+ break;
+ case certDNSName :
+ secu_PrintRawString( out, &gname->name.other, "DNS name", level);
+ break;
+ case certURI :
+ secu_PrintRawString( out, &gname->name.other, "URI", level);
+ break;
+ case certIPAddress :
+ secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
+ break;
+ case certRegisterID :
+ SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
+ break;
+ case certX400Address :
+ SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
+ break;
+ case certEDIPartyName :
+ SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
+ break;
+ default:
+ PR_snprintf(label, sizeof label, "unknown type [%d]",
+ (int)gname->type - 1);
+ SECU_PrintAsHex(out, &gname->name.other, label, level);
+ break;
+ }
+}
+
+static void
+secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthKeyID *kid = NULL;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ kid = CERT_DecodeAuthKeyID(pool, value);
+ if (!kid) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ int keyIDPresent = (kid->keyID.data && kid->keyID.len);
+ int issuerPresent = kid->authCertIssuer != NULL;
+ int snPresent = (kid->authCertSerialNumber.data &&
+ kid->authCertSerialNumber.len);
+
+ if ((keyIDPresent && !issuerPresent && !snPresent) ||
+ (!keyIDPresent && issuerPresent && snPresent)) {
+ /* all is well */
+ } else {
+ SECU_Indent(out, level);
+ fprintf(out,
+ "Error: KeyID OR (Issuer AND Serial) must be present, not both.\n");
+ }
+ if (keyIDPresent)
+ SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
+ if (issuerPresent)
+ secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
+ if (snPresent)
+ SECU_PrintInteger(out, &kid->authCertSerialNumber,
+ "Serial Number", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTGeneralName * nameList;
+ CERTGeneralName * current;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ nameList = current = CERT_DecodeAltNameExtension(pool, value);
+ if (!current) {
+ if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
+ /* Decoder found empty sequence, which is invalid. */
+ PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
+ }
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ do {
+ secu_PrintGeneralName(out, current, msg, level);
+ current = CERT_GetNextGeneralName(current);
+ } while (current != nameList);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCrlDistributionPoints * dPoints;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
+ if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
+ CRLDistributionPoint ** pPoints = dPoints->distPoints;
+ CRLDistributionPoint * pPoint;
+ while (NULL != (pPoint = *pPoints++)) {
+ if (pPoint->distPointType == generalName &&
+ pPoint->distPoint.fullName != NULL) {
+ secu_PrintGeneralName(out, pPoint->distPoint.fullName, NULL,
+ level);
+#if defined(LATER)
+ } else if (pPoint->distPointType == relativeDistinguishedName) {
+ /* print the relative name */
+#endif
+ } else if (pPoint->derDistPoint.data) {
+ SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level);
+ }
+ if (pPoint->reasons.data) {
+ secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
+ level);
+ }
+ if (pPoint->crlIssuer) {
+ secu_PrintGeneralName(out, pPoint->crlIssuer, "Issuer", level);
+ }
+ }
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
+ char *msg, int level)
+{
+ CERTNameConstraint *head = value;
+ SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
+ level++;
+ do {
+ secu_PrintGeneralName(out, &value->name, NULL, level);
+ if (value->min.data)
+ SECU_PrintInteger(out, &value->min, "Minimum", level+1);
+ if (value->max.data)
+ SECU_PrintInteger(out, &value->max, "Maximum", level+1);
+ value = CERT_GetNextNameConstraint(value);
+ } while (value != head);
+}
+
+static void
+secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTNameConstraints * cnstrnts;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
+ if (!cnstrnts) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ if (cnstrnts->permited)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
+ "Permitted", level);
+ if (cnstrnts->excluded)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
+ "Excluded", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthInfoAccess **infos = NULL;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
+ if (!infos) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ CERTAuthInfoAccess *info;
+ while (NULL != (info = *infos++)) {
+ if (info->method.data) {
+ SECU_PrintObjectID(out, &info->method, "Method", level);
+ } else {
+ SECU_Indent(out,level);
+ fprintf(out, "Error: missing method\n");
+ }
+ if (info->location) {
+ secu_PrintGeneralName(out, info->location, "Location", level);
+ } else {
+ SECU_PrintAny(out, &info->derLocation, "Location", level);
+ }
+ }
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+void
+SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ SECOidTag oidTag;
+
+ if ( extensions ) {
+ if (msg && *msg) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", msg);
+ }
+
+ while ( *extensions ) {
+ SECItem *tmpitem;
+
+ tmpitem = &(*extensions)->id;
+ SECU_PrintObjectID(out, tmpitem, "Name", level);
+
+ tmpitem = &(*extensions)->critical;
+ if ( tmpitem->len ) {
+ secu_PrintBoolean(out, tmpitem, "Critical", level);
+ }
+
+ oidTag = SECOID_FindOIDTag (&((*extensions)->id));
+ tmpitem = &((*extensions)->value);
+
+ switch (oidTag) {
+ case SEC_OID_X509_INVALID_DATE:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
+ secu_PrintX509InvalidDate(out, tmpitem, "Date", level );
+ break;
+ case SEC_OID_X509_CERTIFICATE_POLICIES:
+ SECU_PrintPolicy(out, tmpitem, "Data", level );
+ break;
+ case SEC_OID_NS_CERT_EXT_BASE_URL:
+ case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
+ case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
+ case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
+ case SEC_OID_OCSP_RESPONDER:
+ SECU_PrintString(out,tmpitem, "URL", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_COMMENT:
+ SECU_PrintString(out,tmpitem, "Comment", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
+ SECU_PrintString(out,tmpitem, "ServerName", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ secu_PrintNSCertType(out,tmpitem,"Data",level);
+ break;
+ case SEC_OID_X509_BASIC_CONSTRAINTS:
+ secu_PrintBasicConstraints(out,tmpitem,"Data",level);
+ break;
+ case SEC_OID_X509_EXT_KEY_USAGE:
+ PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ secu_PrintX509KeyUsage(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_AUTH_KEY_ID:
+ secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_SUBJECT_ALT_NAME:
+ case SEC_OID_X509_ISSUER_ALT_NAME:
+ secu_PrintAltNameExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_CRL_DIST_POINTS:
+ secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
+ SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
+ level );
+ break;
+ case SEC_OID_X509_NAME_CONSTRAINTS:
+ secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_AUTH_INFO_ACCESS:
+ secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
+ break;
+
+ case SEC_OID_X509_CRL_NUMBER:
+ case SEC_OID_X509_REASON_CODE:
+
+ /* PKIX OIDs */
+ case SEC_OID_PKIX_OCSP:
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NONCE:
+ case SEC_OID_PKIX_OCSP_CRL:
+ case SEC_OID_PKIX_OCSP_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NO_CHECK:
+ case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
+ case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
+ case SEC_OID_PKIX_REGCTRL_REGTOKEN:
+ case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
+ case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
+ case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
+ case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
+ case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
+ case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
+ case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
+
+ /* Netscape extension OIDs. */
+ case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
+ case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
+ case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
+ case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
+ case SEC_OID_NS_CERT_EXT_USER_PICTURE:
+
+ /* x.509 v3 Extensions */
+ case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
+ case SEC_OID_X509_SUBJECT_KEY_ID:
+ case SEC_OID_X509_POLICY_MAPPINGS:
+ case SEC_OID_X509_POLICY_CONSTRAINTS:
+
+
+ default:
+ SECU_PrintAny(out, tmpitem, "Data", level);
+ break;
+ }
+
+ secu_Newline(out);
+ extensions++;
+ }
+ }
+}
+
+
+void
+SECU_PrintName(FILE *out, CERTName *name, char *msg, int level)
+{
+ char *nameStr;
+ char *str;
+ SECItem my;
+
+ str = nameStr = CERT_NameToAscii(name);
+ if (!str) {
+ str = "!Invalid AVA!";
+ }
+ my.data = (unsigned char *)str;
+ my.len = PORT_Strlen(str);
+#if 1
+ secu_PrintRawString(out, &my, msg, level);
+#else
+ SECU_Indent(out, level); fprintf(out, "%s: ", msg);
+ fprintf(out, str);
+ secu_Newline(out);
+#endif
+ PORT_Free(nameStr);
+}
+
+void
+printflags(char *trusts, unsigned int flags)
+{
+ if (flags & CERTDB_VALID_CA)
+ if (!(flags & CERTDB_TRUSTED_CA) &&
+ !(flags & CERTDB_TRUSTED_CLIENT_CA))
+ PORT_Strcat(trusts, "c");
+ if (flags & CERTDB_VALID_PEER)
+ if (!(flags & CERTDB_TRUSTED))
+ PORT_Strcat(trusts, "p");
+ if (flags & CERTDB_TRUSTED_CA)
+ PORT_Strcat(trusts, "C");
+ if (flags & CERTDB_TRUSTED_CLIENT_CA)
+ PORT_Strcat(trusts, "T");
+ if (flags & CERTDB_TRUSTED)
+ PORT_Strcat(trusts, "P");
+ if (flags & CERTDB_USER)
+ PORT_Strcat(trusts, "u");
+ if (flags & CERTDB_SEND_WARN)
+ PORT_Strcat(trusts, "w");
+ if (flags & CERTDB_INVISIBLE_CA)
+ PORT_Strcat(trusts, "I");
+ if (flags & CERTDB_GOVT_APPROVED_CA)
+ PORT_Strcat(trusts, "G");
+ return;
+}
+
+/* callback for listing certs through pkcs11 */
+SECStatus
+SECU_PrintCertNickname(CERTCertListNode *node, void *data)
+{
+ CERTCertTrust *trust;
+ CERTCertificate* cert;
+ FILE *out;
+ char trusts[30];
+ char *name;
+
+ cert = node->cert;
+
+ PORT_Memset (trusts, 0, sizeof (trusts));
+ out = (FILE *)data;
+
+ name = node->appData;
+ if (!name || !name[0]) {
+ name = cert->nickname;
+ }
+ if (!name || !name[0]) {
+ name = cert->emailAddr;
+ }
+ if (!name || !name[0]) {
+ name = "(NULL)";
+ }
+
+ trust = cert->trust;
+ if (trust) {
+ printflags(trusts, trust->sslFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust->emailFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust->objectSigningFlags);
+ } else {
+ PORT_Memcpy(trusts,",,",3);
+ }
+ fprintf(out, "%-60s %-5s\n", name, trusts);
+
+ return (SECSuccess);
+}
+
+int
+SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
+{
+ CERTCertExtension **extensions = NULL;
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ int rv = 0;
+
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_QuickDERDecodeItem(arena, &extensions,
+ SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
+ if (!rv)
+ SECU_PrintExtensions(out, extensions, m, level);
+ else
+ SECU_PrintAny(out, any, m, level);
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF Extensions */
+int
+SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF "ANY" */
+int
+SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ SECU_PrintAny(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
+{
+ int rv = 0;
+ SECOidTag tag;
+ tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
+ if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
+ rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
+ } else {
+ rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
+{
+ int rv = 0;
+ while (attrs[0]) {
+ rv |= SECU_PrintCertAttribute(out, attrs[0], m, level+1);
+ attrs++;
+ }
+ return rv;
+}
+
+int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificateRequest *cr;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate request */
+ cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
+ if (!cr)
+ goto loser;
+ cr->arena = arena;
+ rv = SEC_QuickDERDecodeItem(arena, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &cr->version, "Version", level+1);
+ SECU_PrintName(out, &cr->subject, "Subject", level+1);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (cr->attributes)
+ SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level+1);
+ rv = 0;
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ int iv;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
+ goto loser;
+ }
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
+ SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level+1);
+ secu_PrintValidity(out, &c->validity, "Validity", level+1);
+ SECU_PrintName(out, &c->subject, "Subject", level+1);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (c->issuerID.data)
+ secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
+ if (c->subjectID.data)
+ secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
+ SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintPublicKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYPublicKey key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), der);
+ if (!rv) {
+ /* Pretty print it out */
+ secu_PrintRSAPublicKey(out, &key, m, level);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+#ifdef HAVE_EPV_TEMPLATE
+int
+SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYEncryptedPrivateKeyInfo key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
+ level+1);
+ SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
+loser:
+ PORT_FreeArena(arena, PR_TRUE);
+ return rv;
+}
+#endif
+
+int
+SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
+{
+ unsigned char fingerprint[20];
+ char *fpStr = NULL;
+ int err = PORT_GetError();
+ SECStatus rv;
+ SECItem fpItem;
+
+ /* print MD5 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = MD5_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (MD5):\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fpStr = NULL;
+ if (rv != SECSuccess && !err)
+ err = PORT_GetError();
+
+ /* print SHA1 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA1_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (SHA1):\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fprintf(out, "\n");
+
+ if (err)
+ PORT_SetError(err);
+ if (err || rv != SECSuccess)
+ return SECFailure;
+
+ return 0;
+}
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm", level+1);
+ SECU_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ /* Parse and display encrypted key */
+ SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+static void
+secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
+ level + 1);
+
+ if (info->authAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Authenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->authAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%d)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+
+ /* Parse and display signature */
+ SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
+ "Digest Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
+
+ if (info->unAuthAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Unauthenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%x)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+
+void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ /* version is optional */
+ iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
+ SECU_Indent(out, level+1);
+ fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+ SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
+ level + 1);
+ SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
+ SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
+ if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
+ SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv++]) != NULL) {
+ sprintf(om, "Entry (%x):\n", iv);
+ SECU_Indent(out, level + 1); fprintf(out, om);
+ SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
+ level + 2);
+ SECU_PrintTimeChoice(out, &(entry->revocationDate),
+ "Revocation Date", level + 2);
+ SECU_PrintExtensions(out, entry->extensions,
+ "Entry Extensions", level + 2);
+ }
+ }
+ SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "Content Information", level + 1);
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ const char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+int
+SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCrl *c = NULL;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+ do {
+ /* Decode CRL */
+ c = PORT_ArenaZNew(arena, CERTCrl);
+ if (!c)
+ break;
+
+ rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
+ if (rv != SECSuccess)
+ break;
+ SECU_PrintCRLInfo (out, c, m, level);
+ } while (0);
+ PORT_FreeArena (arena, PR_FALSE);
+ return rv;
+}
+
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
+ level + 1);
+ secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ char *m, int level)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ level++;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ if (src->content.data == NULL) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
+ level++;
+ SECU_Indent(out, level); fprintf(out, "<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
+ break;
+
+ default:
+ SECU_PrintAsHex(out, src->content.data, desc, level);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+** SECU_PrintPKCS7ContentInfo
+** Decode and print any major PKCS7 data type (up to version 1).
+*/
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (cinfo != NULL) {
+ /* Send it to recursive parsing and printing module */
+ rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+/*
+** End of PKCS7 functions
+*/
+
+void
+printFlags(FILE *out, unsigned int flags, int level)
+{
+ if ( flags & CERTDB_VALID_PEER ) {
+ SECU_Indent(out, level); fprintf(out, "Valid Peer\n");
+ }
+ if ( flags & CERTDB_TRUSTED ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted\n");
+ }
+ if ( flags & CERTDB_SEND_WARN ) {
+ SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
+ }
+ if ( flags & CERTDB_VALID_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Valid CA\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
+ }
+ if ( flags & CERTDB_NS_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
+ }
+ if ( flags & CERTDB_USER ) {
+ SECU_Indent(out, level); fprintf(out, "User\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
+ }
+ if ( flags & CERTDB_GOVT_APPROVED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Step-up\n");
+ }
+}
+
+void
+SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
+ printFlags(out, trust->sslFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
+ printFlags(out, trust->emailFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
+ printFlags(out, trust->objectSigningFlags, level+2);
+}
+
+int SECU_PrintSignedData(FILE *out, SECItem *der, char *m,
+ int level, SECU_PPFunc inner)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTSignedData *sd;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Strip off the signature */
+ sd = PORT_ArenaZNew(arena, CERTSignedData);
+ if (!sd)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv)
+ goto loser;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ rv = (*inner)(out, &sd->data, "Data", level+1);
+
+ SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
+ level+1);
+ DER_ConvertBitString(&sd->signature);
+ SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
+ SECU_PrintFingerprints(out, der, "Fingerprint", level+1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+
+}
+
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName, secuCommand *cmd)
+{
+ PRBool found;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *optstring;
+ int i, j;
+
+ optstring = (char *)malloc(cmd->numCommands + 2*cmd->numOptions);
+ j = 0;
+
+ for (i=0; i<cmd->numCommands; i++) {
+ optstring[j++] = cmd->commands[i].flag;
+ }
+ for (i=0; i<cmd->numOptions; i++) {
+ optstring[j++] = cmd->options[i].flag;
+ if (cmd->options[i].needsArg)
+ optstring[j++] = ':';
+ }
+ optstring[j] = '\0';
+ optstate = PL_CreateOptState(argc, argv, optstring);
+
+ /* Parse command line arguments */
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+
+ /* Wasn't really an option, just standalone arg. */
+ if (optstate->option == '\0')
+ continue;
+
+ found = PR_FALSE;
+
+ for (i=0; i<cmd->numCommands; i++) {
+ if (cmd->commands[i].flag == optstate->option) {
+ cmd->commands[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->commands[i].arg = (char *)optstate->value;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ for (i=0; i<cmd->numOptions; i++) {
+ if (cmd->options[i].flag == optstate->option) {
+ cmd->options[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->options[i].arg = (char *)optstate->value;
+ } else if (cmd->options[i].needsArg) {
+ return SECFailure;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return SECFailure;
+ }
+ if (status == PL_OPT_BAD)
+ return SECFailure;
+ return SECSuccess;
+}
+
+char *
+SECU_GetOptionArg(secuCommand *cmd, int optionNum)
+{
+ if (optionNum < 0 || optionNum >= cmd->numOptions)
+ return NULL;
+ if (cmd->options[optionNum].activated)
+ return PL_strdup(cmd->options[optionNum].arg);
+ else
+ return NULL;
+}
+
+static char SECUErrorBuf[64];
+
+char *
+SECU_ErrorStringRaw(int16 err)
+{
+ if (err == 0)
+ SECUErrorBuf[0] = '\0';
+ else if (err == SEC_ERROR_BAD_DATA)
+ sprintf(SECUErrorBuf, "Bad data");
+ else if (err == SEC_ERROR_BAD_DATABASE)
+ sprintf(SECUErrorBuf, "Problem with database");
+ else if (err == SEC_ERROR_BAD_DER)
+ sprintf(SECUErrorBuf, "Problem with DER");
+ else if (err == SEC_ERROR_BAD_KEY)
+ sprintf(SECUErrorBuf, "Problem with key");
+ else if (err == SEC_ERROR_BAD_PASSWORD)
+ sprintf(SECUErrorBuf, "Incorrect password");
+ else if (err == SEC_ERROR_BAD_SIGNATURE)
+ sprintf(SECUErrorBuf, "Bad signature");
+ else if (err == SEC_ERROR_EXPIRED_CERTIFICATE)
+ sprintf(SECUErrorBuf, "Expired certificate");
+ else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
+ sprintf(SECUErrorBuf, "Invalid extension value");
+ else if (err == SEC_ERROR_INPUT_LEN)
+ sprintf(SECUErrorBuf, "Problem with input length");
+ else if (err == SEC_ERROR_INVALID_ALGORITHM)
+ sprintf(SECUErrorBuf, "Invalid algorithm");
+ else if (err == SEC_ERROR_INVALID_ARGS)
+ sprintf(SECUErrorBuf, "Invalid arguments");
+ else if (err == SEC_ERROR_INVALID_AVA)
+ sprintf(SECUErrorBuf, "Invalid AVA");
+ else if (err == SEC_ERROR_INVALID_TIME)
+ sprintf(SECUErrorBuf, "Invalid time");
+ else if (err == SEC_ERROR_IO)
+ sprintf(SECUErrorBuf, "Security I/O error");
+ else if (err == SEC_ERROR_LIBRARY_FAILURE)
+ sprintf(SECUErrorBuf, "Library failure");
+ else if (err == SEC_ERROR_NO_MEMORY)
+ sprintf(SECUErrorBuf, "Out of memory");
+ else if (err == SEC_ERROR_OLD_CRL)
+ sprintf(SECUErrorBuf, "CRL is older than the current one");
+ else if (err == SEC_ERROR_OUTPUT_LEN)
+ sprintf(SECUErrorBuf, "Problem with output length");
+ else if (err == SEC_ERROR_UNKNOWN_ISSUER)
+ sprintf(SECUErrorBuf, "Unknown issuer");
+ else if (err == SEC_ERROR_UNTRUSTED_CERT)
+ sprintf(SECUErrorBuf, "Untrusted certificate");
+ else if (err == SEC_ERROR_UNTRUSTED_ISSUER)
+ sprintf(SECUErrorBuf, "Untrusted issuer");
+ else if (err == SSL_ERROR_BAD_CERTIFICATE)
+ sprintf(SECUErrorBuf, "Bad certificate");
+ else if (err == SSL_ERROR_BAD_CLIENT)
+ sprintf(SECUErrorBuf, "Bad client");
+ else if (err == SSL_ERROR_BAD_SERVER)
+ sprintf(SECUErrorBuf, "Bad server");
+ else if (err == SSL_ERROR_EXPORT_ONLY_SERVER)
+ sprintf(SECUErrorBuf, "Export only server");
+ else if (err == SSL_ERROR_NO_CERTIFICATE)
+ sprintf(SECUErrorBuf, "No certificate");
+ else if (err == SSL_ERROR_NO_CYPHER_OVERLAP)
+ sprintf(SECUErrorBuf, "No cypher overlap");
+ else if (err == SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE)
+ sprintf(SECUErrorBuf, "Unsupported certificate type");
+ else if (err == SSL_ERROR_UNSUPPORTED_VERSION)
+ sprintf(SECUErrorBuf, "Unsupported version");
+ else if (err == SSL_ERROR_US_ONLY_SERVER)
+ sprintf(SECUErrorBuf, "U.S. only server");
+ else if (err == PR_IO_ERROR)
+ sprintf(SECUErrorBuf, "I/O error");
+
+ else if (err == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE)
+ sprintf (SECUErrorBuf, "Expired Issuer Certificate");
+ else if (err == SEC_ERROR_REVOKED_CERTIFICATE)
+ sprintf (SECUErrorBuf, "Revoked certificate");
+ else if (err == SEC_ERROR_NO_KEY)
+ sprintf (SECUErrorBuf, "No private key in database for this cert");
+ else if (err == SEC_ERROR_CERT_NOT_VALID)
+ sprintf (SECUErrorBuf, "Certificate is not valid");
+ else if (err == SEC_ERROR_EXTENSION_NOT_FOUND)
+ sprintf (SECUErrorBuf, "Certificate extension was not found");
+ else if (err == SEC_ERROR_CA_CERT_INVALID)
+ sprintf (SECUErrorBuf, "Issuer certificate is invalid");
+ else if (err == SEC_ERROR_CERT_USAGES_INVALID)
+ sprintf (SECUErrorBuf, "Certificate usages is invalid");
+ else if (err == SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION)
+ sprintf (SECUErrorBuf, "Certificate has unknown critical extension");
+ else if (err == SEC_ERROR_PKCS7_BAD_SIGNATURE)
+ sprintf (SECUErrorBuf, "Bad PKCS7 signature");
+ else if (err == SEC_ERROR_INADEQUATE_KEY_USAGE)
+ sprintf (SECUErrorBuf, "Certificate not approved for this operation");
+ else if (err == SEC_ERROR_INADEQUATE_CERT_TYPE)
+ sprintf (SECUErrorBuf, "Certificate not approved for this operation");
+
+ return SECUErrorBuf;
+}
+
+char *
+SECU_ErrorString(int16 err)
+{
+ char *error_string;
+
+ *SECUErrorBuf = 0;
+ SECU_ErrorStringRaw (err);
+
+ if (*SECUErrorBuf == 0) {
+ error_string = SECU_GetString(err);
+ if (error_string == NULL || *error_string == '\0')
+ sprintf(SECUErrorBuf, "No error string found for %d.", err);
+ else
+ return error_string;
+ }
+
+ return SECUErrorBuf;
+}
+
+
+void
+SECU_PrintPRandOSError(char *progName)
+{
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_GetErrorText(buffer);
+ }
+ SECU_PrintError(progName, "function failed");
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_fprintf(PR_STDERR, "\t%s\n", buffer);
+ }
+}
+
+
+static char *
+bestCertName(CERTCertificate *cert) {
+ if (cert->nickname) {
+ return cert->nickname;
+ }
+ if (cert->emailAddr && cert->emailAddr[0]) {
+ return cert->emailAddr;
+ }
+ return cert->subjectName;
+}
+
+void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
+{
+ CERTVerifyLog log;
+ CERTVerifyLogNode *node = NULL;
+ unsigned int depth = (unsigned int)-1;
+ unsigned int flags = 0;
+ char * errstr = NULL;
+ PRErrorCode err = PORT_GetError();
+
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+ CERT_VerifyCertificate(handle, cert, checksig, certUsage, PR_Now(), pinArg, &log, NULL);
+
+ if (log.count > 0) {
+ fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
+ for (node = log.head; node; node = node->next) {
+ if (depth != node->depth) {
+ depth = node->depth;
+ fprintf(outfile,"CERT %d. %s %s:\n", depth,
+ bestCertName(node->cert),
+ depth ? "[Certificate Authority]": "");
+ if (verbose) {
+ const char * emailAddr;
+ emailAddr = CERT_GetFirstEmailAddress(node->cert);
+ if (emailAddr) {
+ fprintf(outfile,"Email Address(es): ");
+ do {
+ fprintf(outfile, "%s\n", emailAddr);
+ emailAddr = CERT_GetNextEmailAddress(node->cert,
+ emailAddr);
+ } while (emailAddr);
+ }
+ }
+ }
+ fprintf(outfile," ERROR %ld: %s\n", node->error,
+ SECU_Strerror(node->error));
+ errstr = NULL;
+ switch (node->error) {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case KU_DIGITAL_SIGNATURE:
+ errstr = "Cert cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ errstr = "Cert cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ errstr = "Cert cannot sign other certs.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ errstr = "Cert cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ errstr = "Cert cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ errstr = "Cert cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ errstr = "Cert cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ errstr = "Cert cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ errstr = "Cert cannot be used as an object signing CA.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ errstr = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (errstr) {
+ fprintf(stderr," %s\n",errstr);
+ }
+ CERT_DestroyCertificate(node->cert);
+ }
+ }
+ PORT_SetError(err); /* restore original error code */
+}
+
+SECOidTag
+SECU_StringToSignatureAlgTag(const char *alg)
+{
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+
+ if (alg) {
+ if (!PL_strcmp(alg, "MD2")) {
+ hashAlgTag = SEC_OID_MD2;
+ } else if (!PL_strcmp(alg, "MD4")) {
+ hashAlgTag = SEC_OID_MD4;
+ } else if (!PL_strcmp(alg, "MD5")) {
+ hashAlgTag = SEC_OID_MD5;
+ } else if (!PL_strcmp(alg, "SHA1")) {
+ hashAlgTag = SEC_OID_SHA1;
+ } else if (!PL_strcmp(alg, "SHA256")) {
+ hashAlgTag = SEC_OID_SHA256;
+ } else if (!PL_strcmp(alg, "SHA384")) {
+ hashAlgTag = SEC_OID_SHA384;
+ } else if (!PL_strcmp(alg, "SHA512")) {
+ hashAlgTag = SEC_OID_SHA512;
+ }
+ }
+ return hashAlgTag;
+}
+
+
+SECStatus
+SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
+ const PRBool ascii, char *url)
+{
+ PORT_Assert(derCrl != NULL);
+ if (!derCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (outFile != NULL) {
+ if (ascii) {
+ PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
+ BTOA_DataToAscii(derCrl->data, derCrl->len),
+ NS_CRL_TRAILER);
+ } else {
+ if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
+ return SECFailure;
+ }
+ }
+ }
+ if (slot) {
+ CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
+ SEC_CRL_TYPE, NULL, 0, NULL, 0);
+ if (newCrl != NULL) {
+ SEC_DestroyCrl(newCrl);
+ return SECSuccess;
+ }
+ return SECFailure;
+ }
+ if (!outFile && !slot) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PRArenaPool *arena;
+ SECOidTag algID;
+ void *dummy;
+
+ PORT_Assert(issuer != NULL && signCrl != NULL);
+ if (!issuer || !signCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ arena = signCrl->arena;
+
+ caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
+ if (caPrivateKey == NULL) {
+ *resCode = noKeyFound;
+ return SECFailure;
+ }
+
+ algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ *resCode = noSignatureMatch;
+ rv = SECFailure;
+ goto done;
+ }
+
+ if (!signCrl->crl.signatureAlg.parameters.data) {
+ rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
+ if (rv != SECSuccess) {
+ *resCode = failToEncode;
+ goto done;
+ }
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
+ der.data, der.len, caPrivateKey, algID);
+ if (rv != SECSuccess) {
+ *resCode = failToSign;
+ goto done;
+ }
+
+ signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
+ if (signCrl->derCrl == NULL) {
+ *resCode = noMem;
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ rv = SECFailure;
+ goto done;
+ }
+
+ signCrl->derCrl->len = 0;
+ signCrl->derCrl->data = NULL;
+ dummy = SEC_ASN1EncodeItem (arena, signCrl->derCrl, signCrl,
+ SEC_ASN1_GET(CERT_SignedCrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+done:
+ if (caPrivateKey) {
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ }
+ return rv;
+}
+
+
+
+SECStatus
+SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
+{
+ void *dummy;
+ SECStatus rv = SECSuccess;
+ SECItem der;
+
+ PORT_Assert(destArena && srcCrl && destCrl);
+ if (!destArena || !srcCrl || !destCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem (destArena, &der, srcCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ return SECFailure;
+ }
+
+ rv = SEC_QuickDERDecodeItem(destArena, destCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate), &der);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ destCrl->arena = destArena;
+
+ return rv;
+}
+
+SECStatus
+SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len, SECKEYPrivateKey *pk,
+ SECOidTag algID)
+{
+ SECItem it;
+ SECStatus rv;
+
+ it.data = 0;
+
+ /* XXX We should probably have some asserts here to make sure the key type
+ * and algID match
+ */
+
+ /* Sign input buffer */
+ rv = SEC_SignData(&it, buf, len, pk, algID);
+ if (rv) goto loser;
+
+ /* Fill out SignedData object */
+ PORT_Memset(sd, 0, sizeof(*sd));
+ sd->data.data = buf;
+ sd->data.len = len;
+ sd->signature.data = it.data;
+ sd->signature.len = it.len << 3; /* convert to bit string */
+ rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
+ if (rv) goto loser;
+
+ return rv;
+
+ loser:
+ PORT_Free(it.data);
+ return rv;
+}
+
+#if 0
+
+/* we need access to the private function cert_FindExtension for this code to work */
+
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *scrl)
+{
+ SECItem encodedExtenValue;
+ SECStatus rv;
+ CERTAuthKeyID *ret;
+ CERTCrl* crl;
+
+ if (!scrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ crl = &scrl->crl;
+
+ encodedExtenValue.data = NULL;
+ encodedExtenValue.len = 0;
+
+ rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
+ &encodedExtenValue);
+ if ( rv != SECSuccess ) {
+ return (NULL);
+ }
+
+ ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
+
+ PORT_Free(encodedExtenValue.data);
+ encodedExtenValue.data = NULL;
+
+ return(ret);
+}
+
+#endif
+
+/*
+ * Find the issuer of a Crl. Use the authorityKeyID if it exists.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem* subject,
+ CERTAuthKeyID* authorityKeyID, PRTime validTime)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTCertList *certList = NULL;
+
+ if (!subject) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ certList =
+ CERT_CreateSubjectCertList(NULL, dbhandle, subject,
+ validTime, PR_TRUE);
+ if (certList) {
+ CERTCertListNode *node = CERT_LIST_HEAD(certList);
+
+ /* XXX and authoritykeyid in the future */
+ while ( ! CERT_LIST_END(node, certList) ) {
+ CERTCertificate *cert = node->cert;
+ /* check cert CERTCertTrust data is allocated, check cert
+ usage extension, check that cert has pkey in db. Select
+ the first (newest) user cert */
+ if (cert->trust &&
+ CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
+ CERT_IsUserCert(cert)) {
+
+ issuerCert = CERT_DupCertificate(cert);
+ break;
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+ CERT_DestroyCertList(certList);
+ }
+ return(issuerCert);
+}
+
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ do {
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess)
+ break;
+
+ rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
+ criticality, PR_TRUE);
+ if (rv != SECSuccess)
+ break;
+ } while (0);
+
+ return (rv);
+}
diff --git a/pki/base/native-tools/src/tkstool/secutil.h b/pki/base/native-tools/src/tkstool/secutil.h
new file mode 100644
index 000000000..a2f065067
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/secutil.h
@@ -0,0 +1,430 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/secutil.h
+ */
+
+#ifndef _SEC_UTIL_H_
+#define _SEC_UTIL_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "prerror.h"
+#include "base64.h"
+#include "key.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include <stdio.h>
+
+#define SEC_CT_PRIVATE_KEY "private-key"
+#define SEC_CT_PUBLIC_KEY "public-key"
+#define SEC_CT_CERTIFICATE "certificate"
+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
+#define SEC_CT_PKCS7 "pkcs7"
+#define SEC_CT_CRL "crl"
+
+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
+
+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
+#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
+
+#define NS_CRL_HEADER "-----BEGIN CRL-----"
+#define NS_CRL_TRAILER "-----END CRL-----"
+
+/* From libsec/pcertdb.c --- it's not declared in sec.h */
+extern SECStatus SEC_AddPermCertificate(CERTCertDBHandle *handle,
+ SECItem *derCert, char *nickname, CERTCertTrust *trust);
+
+
+#ifdef SECUTIL_NEW
+typedef int (*SECU_PPFunc)(PRFileDesc *out, SECItem *item,
+ char *msg, int level);
+#else
+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, char *msg, int level);
+#endif
+
+typedef struct {
+ enum {
+ PW_NONE = 0,
+ PW_FROMFILE = 1,
+ PW_PLAINTEXT = 2,
+ PW_EXTERNAL = 3
+ } source;
+ char *data;
+} secuPWData;
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** Use passwd to send the password in plaintext, pwFile to specify a
+** file containing the password, or NULL for both to prompt the user.
+*/
+SECStatus SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile);
+
+/* These were stolen from the old sec.h... */
+/*
+** Check a password for legitimacy. Passwords must be at least 8
+** characters long and contain one non-alphabetic. Return DSTrue if the
+** password is ok, DSFalse otherwise.
+*/
+extern PRBool SEC_CheckPassword(char *password);
+
+/*
+** Blind check of a password. Complement to SEC_CheckPassword which
+** ignores length and content type, just retuning DSTrue is the password
+** exists, DSFalse if NULL
+*/
+extern PRBool SEC_BlindCheckPassword(char *password);
+
+/*
+** Get a password.
+** First prompt with "msg" on "out", then read the password from "in".
+** The password is then checked using "chkpw".
+*/
+extern char *SEC_GetPassword(FILE *in, FILE *out, char *msg,
+ PRBool (*chkpw)(char *));
+
+char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+char *SECU_GetPasswordString(void *arg, char *prompt);
+
+/*
+** Write a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to encrypt a password "pw" into a file "fd".
+*/
+extern SECStatus SEC_WriteDongleFile(int fd, char *pw);
+
+/*
+** Get a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to decrypt and return a password from file "fd".
+*/
+extern char *SEC_ReadDongleFile(int fd);
+
+
+/* End stolen headers */
+
+/* Just sticks the two strings together with a / if needed */
+char *SECU_AppendFilenameToDir(char *dir, char *filename);
+
+/* Returns result of getenv("SSL_DIR") or NULL */
+extern char *SECU_DefaultSSLDir(void);
+
+/*
+** Should be called once during initialization to set the default
+** directory for looking for cert.db, key.db, and cert-nameidx.db files
+** Removes trailing '/' in 'base'
+** If 'base' is NULL, defaults to set to .netscape in home directory.
+*/
+extern char *SECU_ConfigDirectory(const char* base);
+
+/*
+** Basic callback function for SSL_GetClientAuthDataHook
+*/
+extern int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+/* print out an error message */
+extern void SECU_PrintError(char *progName, char *msg, ...);
+
+/* print out a system error message */
+extern void SECU_PrintSystemError(char *progName, char *msg, ...);
+
+/* Return informative error string */
+extern const char * SECU_Strerror(PRErrorCode errNum);
+
+/* print information about cert verification failure */
+extern void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose);
+
+/* Read the contents of a file into a SECItem */
+extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src);
+extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src);
+
+/* Read in a DER from a file, may be ascii */
+extern SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii);
+
+/* Indent based on "level" */
+extern void SECU_Indent(FILE *out, int level);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level);
+
+/* Print ObjectIdentifier symbolically */
+extern SECOidTag SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level);
+
+/* Print AlgorithmIdentifier symbolically */
+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m,
+ int level);
+
+/* Print SECItem as hex */
+extern void SECU_PrintAsHex(FILE *out, SECItem *i, const char *m, int level);
+
+/* dump a buffer in hex and ASCII */
+extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level);
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m,
+ int level);
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level);
+
+/* callback for listing certs through pkcs11 */
+extern SECStatus SECU_PrintCertNickname(CERTCertListNode* cert, void *data);
+
+/* Dump all certificate nicknames in a database */
+extern SECStatus
+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc* out,
+ PRBool sortByName, PRBool sortByTrust);
+
+/* See if nickname already in database. Return 1 true, 0 false, -1 error */
+int SECU_CheckCertNameExists(CERTCertDBHandle *handle, char *nickname);
+
+/* Dump contents of cert req */
+extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of certificate */
+extern int SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level);
+
+/* print trust flags on a cert */
+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level);
+
+/* Dump contents of public key */
+extern int SECU_PrintPublicKey(FILE *out, SECItem *der, char *m, int level);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Print the MD5 and SHA1 fingerprints of a cert */
+extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
+ int level);
+
+/* Pretty-print any PKCS7 thing */
+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, char *m, int level,
+ SECU_PPFunc inner);
+
+extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level);
+
+extern void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level);
+
+extern void SECU_PrintString(FILE *out, SECItem *si, char *m, int level);
+extern void SECU_PrintAny(FILE *out, SECItem *i, char *m, int level);
+
+extern void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level);
+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level);
+
+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level);
+
+extern void SECU_PrintName(FILE *out, CERTName *name, char *msg, int level);
+
+#ifdef SECU_GetPassword
+/* Convert a High public Key to a Low public Key */
+extern SECKEYLowPublicKey *SECU_ConvHighToLow(SECKEYPublicKey *pubHighKey);
+#endif
+
+extern char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+extern SECStatus DER_PrettyPrint(FILE *out, SECItem *it, PRBool raw);
+extern void SEC_Init(void);
+
+extern char *SECU_SECModDBName(void);
+
+extern void SECU_PrintPRandOSError(char *progName);
+
+extern SECStatus SECU_RegisterDynamicOids(void);
+
+/* Identifies hash algorithm tag by its string representation. */
+extern SECOidTag SECU_StringToSignatureAlgTag(const char *alg);
+
+/* Store CRL in output file or pk11 db. Also
+ * encodes with base64 and exports to file if ascii flag is set
+ * and file is not NULL. */
+extern SECStatus SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl,
+ PRFileDesc *outFile, int ascii, char *url);
+
+
+/*
+** DER sign a single block of data using private key encryption and the
+** MD5 hashing algorithm. This routine first computes a digital signature
+** using SEC_SignData, then wraps it with an CERTSignedData and then der
+** encodes the result.
+** "arena" is the memory arena to use to allocate data from
+** "sd" returned CERTSignedData
+** "result" the final der encoded data (memory is allocated)
+** "buf" the input data to sign
+** "len" the amount of data to sign
+** "pk" the private key to encrypt with
+*/
+extern SECStatus SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algID);
+
+typedef enum {
+ noKeyFound = 1,
+ noSignatureMatch = 2,
+ failToEncode = 3,
+ failToSign = 4,
+ noMem = 5
+} SignAndEncodeFuncExitStat;
+
+extern SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode);
+
+extern SECStatus
+SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl);
+
+/*
+** Finds the crl Authority Key Id extension. Returns NULL if no such extension
+** was found.
+*/
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *crl);
+
+/*
+ * Find the issuer of a crl. Cert usage should be checked before signing a crl.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbHandle, SECItem* subject,
+ CERTAuthKeyID* id, PRTime validTime);
+
+
+/* call back function used in encoding of an extension. Called from
+ * SECU_EncodeAndAddExtensionValue */
+typedef SECStatus (* EXTEN_EXT_VALUE_ENCODER) (PRArenaPool *extHandleArena,
+ void *value, SECItem *encodedValue);
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn);
+
+
+/*
+ *
+ * Utilities for parsing security tools command lines
+ *
+ */
+
+/* A single command flag */
+typedef struct {
+ char flag;
+ PRBool needsArg;
+ char *arg;
+ PRBool activated;
+} secuCommandFlag;
+
+/* A full array of command/option flags */
+typedef struct
+{
+ int numCommands;
+ int numOptions;
+
+ secuCommandFlag *commands;
+ secuCommandFlag *options;
+} secuCommand;
+
+/* fill the "arg" and "activated" fields for each flag */
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName, secuCommand *cmd);
+char *
+SECU_GetOptionArg(secuCommand *cmd, int optionNum);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+/* Return informative error string */
+char *SECU_ErrorString(int16 err);
+
+/* Return informative error string. Does not call XP_GetString */
+char *SECU_ErrorStringRaw(int16 err);
+
+void printflags(char *trusts, unsigned int flags);
+
+#ifndef XP_UNIX
+extern int ffs(unsigned int i);
+#endif
+
+#include "secerr.h"
+#include "sslerr.h"
+
+#endif /* _SEC_UTIL_H_ */
diff --git a/pki/base/native-tools/src/tkstool/tkstool.c b/pki/base/native-tools/src/tkstool/tkstool.c
new file mode 100644
index 000000000..5368b2e7b
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/tkstool.c
@@ -0,0 +1,2660 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+
+static char *progName;
+
+
+/* tkstool commands */
+enum {
+ cmd_DeleteKey = 0,
+ cmd_PrintHelp,
+ cmd_InputGenTransportKey,
+ cmd_DisplayKCV,
+ cmd_ListKeys,
+ cmd_GenMasterKey,
+ cmd_NewDBs,
+ cmd_ChangePassword,
+ cmd_RenameKey,
+ cmd_ListSecModules,
+ cmd_GenTransportKey,
+ cmd_UnWrapMasterKey,
+ cmd_Version,
+ cmd_WrapMasterKey
+};
+
+
+/* tkstool options */
+enum {
+ opt_DBDir = 0,
+ opt_PasswordFile,
+ opt_TokenName,
+ opt_InFile,
+ opt_Keyname,
+ opt_OutFile,
+ opt_DBPrefix,
+ opt_NewKeyname,
+ opt_TransportKeyname,
+ opt_RW,
+ opt_NoiseFile
+};
+
+
+static secuCommandFlag tkstool_commands[] = {
+ { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_InputGenTransportKey */ 'I', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DisplayKCV */ 'K', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_GenMasterKey */ 'M', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_NewDBs */ 'N', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ChangePassword */ 'P', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_RenameKey */ 'R', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListSecModules */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_GenTransportKey */ 'T', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_UnWrapMasterKey */ 'U', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Version */ 'V', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_WrapMasterKey */ 'W', PR_FALSE, 0, PR_FALSE }
+};
+
+
+static secuCommandFlag tkstool_options[] = {
+ { /* opt_DBDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Keyname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NewKeyname */ 'r', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TransportKeyname */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_RW */ 'x', PR_FALSE, 0, PR_FALSE },
+ { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
+};
+
+
+int
+main( int argc, char **argv )
+{
+ CK_KEY_DERIVATION_STRING_DATA secondDerivationData = { NULL,
+ 0 };
+ CK_KEY_DERIVATION_STRING_DATA thirdDerivationData = { NULL,
+ 0 };
+ PK11SlotInfo *internalSlot = NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symmetricKey = NULL;
+ PK11SymKey *masterKey = NULL;
+ PK11SymKey *temporaryMasterKey = NULL;
+ PK11SymKey *firstSymmetricKey = NULL;
+ PK11SymKey *secondSymmetricKey = NULL;
+ PK11SymKey *thirdSymmetricKey = NULL;
+ PK11SymKey *transportKey = NULL;
+ PRBool readOnly = PR_FALSE;
+ PRIntn KCVLen = KCV_LENGTH;
+ PRUint8 *KCV = NULL;
+ SECItem firstSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+ SECItem secondSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+ SECItem thirdSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+#if defined(PAD_DES2_KEY_LENGTH)
+ SECItem paddedFirstSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+ SECItem paddedSecondSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+ SECItem paddedThirdSessionKeyShare = { siBuffer,
+ NULL,
+ 0 };
+#endif
+ SECItem hexInternalKeyKCV = { siBuffer,
+ NULL,
+ 0 };
+ SECItem wrappedMasterKey = { siBuffer,
+ NULL,
+ 0 };
+ SECStatus rvKCV = SECFailure;
+ SECStatus rvParse = SECSuccess;
+ SECStatus rvNSSinit = SECSuccess;
+ SECStatus rvFindSymKey = SECSuccess;
+ SECStatus rvSeedRNG = SECSuccess;
+ SECStatus rvFirstSessionKeyShare = SECFailure;
+ SECStatus rvSecondSessionKeyShare = SECFailure;
+ SECStatus rvThirdSessionKeyShare = SECFailure;
+ SECStatus rvSaveWrappedMasterKey = SECSuccess;
+ SECStatus rvSymmetricKeyname = SECSuccess;
+ SECStatus rvWrappedMasterKey = SECSuccess;
+ SECStatus rvMasterKeyname = SECSuccess;
+ SECStatus rv = SECSuccess;
+ SECStatus status = PR_FALSE;
+ char commandToRun = '\0';
+ char *DBDir = NULL;
+ char *DBPrefix = "";
+ char *input = NULL;
+ char *keyname = NULL;
+ char *new_keyname = NULL;
+ char *output = NULL;
+ char *SeedNoise = NULL;
+ char *slotname = "internal";
+ char *transport_keyname = NULL;
+ int commandsEntered = 0;
+ int i = 0;
+ int optionsEntered = 0;
+ secuPWData pwdata = { PW_NONE,
+ 0 };
+
+
+ /**************************/
+ /* Parse the command line */
+ /**************************/
+
+ secuCommand tkstool;
+ tkstool.numCommands = sizeof( tkstool_commands ) /
+ sizeof( secuCommandFlag );
+ tkstool.numOptions = sizeof( tkstool_options ) /
+ sizeof( secuCommandFlag );
+ tkstool.commands = tkstool_commands;
+ tkstool.options = tkstool_options;
+
+ /* retrieve name of command */
+ progName = strrchr( argv[0], '/' );
+ progName = progName ? ( progName + 1 ) : argv[0];
+
+ /* parse command line (command(s) and options) from command line */
+ rvParse = SECU_ParseCommandLine( argc, argv, progName, &tkstool );
+ if( rvParse != SECSuccess ) {
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+
+ /*********************************************************/
+ /* Check the number of command line "command(s)" entered */
+ /*********************************************************/
+
+ commandsEntered = 0;
+ for( i = 0 ; i < tkstool.numCommands ; i++ ) {
+ if( tkstool.commands[i].activated ) {
+ commandToRun = tkstool.commands[i].flag;
+ commandsEntered++;
+ }
+
+ if( commandsEntered > 1 ) {
+ break;
+ }
+ }
+
+ if( commandsEntered > 1 ) {
+ PR_fprintf( PR_STDERR,
+ "%s: only one command at a time!\n",
+ progName );
+
+ PR_fprintf( PR_STDERR,
+ "You entered: " );
+
+ for( i = 0 ; i < tkstool.numCommands ; i++ ) {
+ if( tkstool.commands[i].activated ) {
+ PR_fprintf( PR_STDERR,
+ " -%c",
+ tkstool.commands[i].flag );
+ }
+ }
+
+ PR_fprintf( PR_STDERR,
+ "\n" );
+ return 255;
+ }
+
+ if( commandsEntered == 0 ) {
+ PR_fprintf( PR_STDERR,
+ "%s: you must enter one of the following commands:\n\n",
+ progName );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+
+ /********************************************************/
+ /* Check the number of command line "option(s)" entered */
+ /********************************************************/
+
+ optionsEntered = 0;
+ for( i = 0 ; i < tkstool.numOptions ; i++ ) {
+ if( tkstool.options[i].activated ) {
+ optionsEntered++;
+ }
+
+ if( optionsEntered > 1 ) {
+ break;
+ }
+ }
+
+ if( optionsEntered == 0 &&
+ ! ( tkstool.commands[cmd_PrintHelp].activated ||
+ tkstool.commands[cmd_Version].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: you must enter the following options "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+
+ /***************************************************/
+ /* Check that command line "options" correspond to */
+ /* one of their specified command line "commands" */
+ /***************************************************/
+
+ /* the "-d DBDir" command option may ONLY be used with */
+ /* the "-D", "-I", "-K", "-L", "-M", "-N", "-P", "-R", */
+ /* "-S", "-T", "-U", and "-W" commands */
+ if( tkstool.options[opt_DBDir].activated &&
+ ! ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_NewDBs].activated ||
+ tkstool.commands[cmd_ChangePassword].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_ListSecModules].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-d DBDir\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-f pwfile" command option may ONLY be used with */
+ /* the "-D", "-I", "-K", "-L", "-M", "-N", "-P", "-R", */
+ /* "-T", "-U", and "-W" commands */
+ if( tkstool.options[opt_PasswordFile].activated &&
+ ! ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_NewDBs].activated ||
+ tkstool.commands[cmd_ChangePassword].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-f pwfile\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-h token_name" command option may ONLY be used with */
+ /* the "-D", "-I", "-K", "-L", "-M", "-R", "-T", "-U", and */
+ /* "-W" commands */
+ if( tkstool.options[opt_TokenName].activated &&
+ ! ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-h token_name\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-i infile" command option may ONLY be used with */
+ /* the "-U" command */
+ if( tkstool.options[opt_InFile].activated &&
+ !tkstool.commands[cmd_UnWrapMasterKey].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-i infile\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-n keyname" command option may ONLY be used with the */
+ /* "-D", "-I", "-K", "-L", "-M", "-R", "-T", "-U", and "-W" */
+ /* commands */
+ if( tkstool.options[opt_Keyname].activated &&
+ ! ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-n keyname\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-o outfile" command option may ONLY be used with */
+ /* the "-W" command */
+ if( tkstool.options[opt_OutFile].activated &&
+ !tkstool.commands[cmd_WrapMasterKey].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-o outfile\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-p DBPrefix" command option may ONLY be used with */
+ /* the "-D", "-I", "-K", "-L", "-M", "-N", "-P", "-R", */
+ /* "-S", "-T", "-U", and "-W" commands */
+ if( tkstool.options[opt_DBPrefix].activated &&
+ ! ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_NewDBs].activated ||
+ tkstool.commands[cmd_ChangePassword].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_ListSecModules].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-p DBPrefix\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-r new_keyname" command option may */
+ /* ONLY be used with the "-R" command */
+ if( tkstool.options[opt_NewKeyname].activated &&
+ ! ( tkstool.commands[cmd_RenameKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-r new_keyname\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-t transport_keyname" command option may ONLY be used with */
+ /* the "-U", and "-W" commands */
+ if( tkstool.options[opt_TransportKeyname].activated &&
+ !( tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-t transport_keyname\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-x" command option may ONLY be used with */
+ /* the "-L", and "-S" commands */
+ if( tkstool.options[opt_RW].activated &&
+ ! ( tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_ListSecModules].activated ) ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-x\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* the "-z noisefile" command option may ONLY be used with */
+ /* the "-T" command */
+ if( tkstool.options[opt_NoiseFile].activated &&
+ !tkstool.commands[cmd_GenTransportKey].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-z noisefile\" option may only be "
+ "specified with one of the following command(s):\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+
+ /********************************************************/
+ /* Perform special processing on command line "options" */
+ /********************************************************/
+
+ /* "-d DBDir" command option */
+ if( tkstool.options[opt_DBDir].activated ) {
+ if( tkstool.options[opt_DBDir].arg ) {
+ DBDir = SECU_ConfigDirectory( tkstool.options[opt_DBDir].arg );
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-d\" option must contain a "
+ "\"DBDir\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-f pwfile" command option */
+ if( tkstool.options[opt_PasswordFile].activated ) {
+ pwdata.source = PW_FROMFILE;
+ if( tkstool.options[opt_PasswordFile].arg ) {
+ pwdata.data = tkstool.options[opt_PasswordFile].arg;
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-f\" option must contain a "
+ "\"pwfile\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-i infile" command option */
+ if( tkstool.options[opt_InFile].activated ) {
+ if( tkstool.options[opt_InFile].arg ) {
+ input = tkstool.options[opt_InFile].arg;
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-i\" option must contain an "
+ "\"infile\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-h token_name" command option */
+ if( tkstool.options[opt_TokenName].activated ) {
+ if( tkstool.options[opt_TokenName].arg ) {
+ if( PL_strcmp( tkstool.options[opt_TokenName].arg, "all" ) == 0 ) {
+ slotname = NULL;
+ } else {
+ slotname = PL_strdup( tkstool.options[opt_TokenName].arg );
+ }
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-h\" option must contain a "
+ "\"token_name\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-n keyname" command option */
+ if( tkstool.options[opt_Keyname].activated ) {
+ if( tkstool.options[opt_Keyname].arg ) {
+ keyname = SECU_GetOptionArg( &tkstool,
+ opt_Keyname );
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-n\" option must contain a "
+ "\"keyname\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-o outfile" command option */
+ if( tkstool.options[opt_OutFile].activated ) {
+ if( tkstool.options[opt_OutFile].arg ) {
+ output = tkstool.options[opt_OutFile].arg;
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-o\" option must contain an "
+ "\"outfile\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-p DBPrefix" command option */
+ if( tkstool.options[opt_DBPrefix].activated ) {
+ if( tkstool.options[opt_DBPrefix].arg ) {
+ DBPrefix = strdup( tkstool.options[opt_DBPrefix].arg );
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-p\" option must contain a "
+ "\"DBPrefix\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-r new_keyname" command option */
+ if( tkstool.options[opt_NewKeyname].activated ) {
+ if( tkstool.options[opt_NewKeyname].arg ) {
+ new_keyname = SECU_GetOptionArg( &tkstool,
+ opt_NewKeyname );
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-r\" option must contain a "
+ "\"new_keyname\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-t transport_keyname" command option */
+ if( tkstool.options[opt_TransportKeyname].activated ) {
+ if( tkstool.options[opt_TransportKeyname].arg ) {
+ transport_keyname = SECU_GetOptionArg( &tkstool,
+ opt_TransportKeyname );
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-t\" option must contain a "
+ "\"transport_keyname\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+ /* "-x" command option is processed below */
+ /* ONLY based upon specific commands */
+
+ /* "-z noisefile" command option */
+ if( tkstool.options[opt_NoiseFile].activated ) {
+ if( tkstool.options[opt_NoiseFile].arg ) {
+ SeedNoise = tkstool.options[opt_NoiseFile].arg;
+ } else {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-z\" option must contain a "
+ "\"noisefile\" argument:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+ }
+
+
+ /******************************************************************/
+ /* Perform special processing on specific command line "commands" */
+ /******************************************************************/
+
+ /* "-D", "-I", "-K", "-M", "-R", "-T", "-U" and "-W" */
+ /* commands require the "-n keyname" command line */
+ /* option to be specified */
+ if( ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) &&
+ !tkstool.options[opt_Keyname].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-n keyname\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-D", "-I", "-K", "-L", "-M", "-N", "-P", "-R", "-S", */
+ /* "-T", "-U", and "-W" commands require the "-d DBDir" */
+ /* command line option to be specified */
+ if( ( tkstool.commands[cmd_DeleteKey].activated ||
+ tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_DisplayKCV].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_GenMasterKey].activated ||
+ tkstool.commands[cmd_NewDBs].activated ||
+ tkstool.commands[cmd_ChangePassword].activated ||
+ tkstool.commands[cmd_RenameKey].activated ||
+ tkstool.commands[cmd_ListSecModules].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ||
+ tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) &&
+ !tkstool.options[opt_DBDir].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-d DBDir\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-H", "-L", "-S", and "-V" commands require the "-x" */
+ /* command line option to be silently turned off */
+ if( tkstool.commands[cmd_PrintHelp].activated ||
+ tkstool.commands[cmd_ListKeys].activated ||
+ tkstool.commands[cmd_ListSecModules].activated ||
+ tkstool.commands[cmd_Version].activated ) {
+ readOnly = !tkstool.options[opt_RW].activated;
+ }
+
+ /* "-L" command is the ONLY command that allows */
+ /* the "-h all" command line option to be used */
+ /* */
+ /* NOTE: ONLY use "slotname == NULL" to */
+ /* LIST keys on all slots */
+ if( !tkstool.commands[cmd_ListKeys].activated && slotname == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: cannot use \"-h all\" for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-R" commands require the "-r new_keyname" */
+ /* command line option to be specified */
+ if( ( tkstool.commands[cmd_RenameKey].activated ) &&
+ !tkstool.options[opt_NewKeyname].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-r new_keyname\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-U", and "-W" commands require the "-t transport_keyname" */
+ /* command line option to be specified */
+ if( ( tkstool.commands[cmd_UnWrapMasterKey].activated ||
+ tkstool.commands[cmd_WrapMasterKey].activated ) &&
+ !tkstool.options[opt_TransportKeyname].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-t transport_keyname\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-U" commands require the "-i infile" */
+ /* command line option to be specified */
+ if( tkstool.commands[cmd_UnWrapMasterKey].activated &&
+ !tkstool.options[opt_InFile].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-i infile\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+ /* "-W" commands require the "-o outfile" */
+ /* command line option to be specified */
+ if( tkstool.commands[cmd_WrapMasterKey].activated &&
+ !tkstool.options[opt_OutFile].activated ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: the \"-o outfile\" option is required "
+ "for this command:\n\n",
+ progName,
+ commandToRun );
+
+ TKS_Usage( progName );
+
+ return 255;
+ }
+
+
+ /*********************************/
+ /* Execute the "-H" help command */
+ /*********************************/
+
+ if( tkstool.commands[cmd_PrintHelp].activated ) {
+ TKS_PrintHelp( progName );
+
+ return 0;
+ }
+
+
+ /************************************/
+ /* Execute the "-V" version command */
+ /************************************/
+
+ /* "-V" version command */
+ if( tkstool.commands[cmd_Version].activated ) {
+ TKS_Version( progName );
+
+ return 0;
+ }
+
+
+ /************************************************/
+ /* Initialize PKCS #11 Security Module Password */
+ /************************************************/
+
+ PK11_SetPasswordFunc( /* password callback */ SECU_GetModulePassword );
+
+
+ /*******************/
+ /* Initialize NSPR */
+ /*******************/
+
+ PR_Init( PR_SYSTEM_THREAD,
+ PR_PRIORITY_NORMAL,
+ 1 );
+
+
+ /******************/
+ /* Initialize NSS */
+ /******************/
+
+ rvNSSinit = NSS_Initialize( DBDir,
+ DBPrefix,
+ DBPrefix,
+ "secmod.db",
+ readOnly ? NSS_INIT_READONLY : 0 );
+ if( rvNSSinit != SECSuccess ) {
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+
+ if( errLen > 0 && errLen < sizeof buffer ) {
+ PR_GetErrorText( buffer );
+ }
+
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s",
+ progName,
+ commandToRun,
+ "NSS_Initialize() failed" );
+
+ if( errLen > 0 && errLen < sizeof buffer ) {
+ PR_fprintf( PR_STDERR, "\t%s\n", buffer );
+ } else {
+ PR_fprintf( PR_STDERR, "\n" );
+ }
+
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************/
+ /* Initialize internal PKCS #11 software crypto slot */
+ /* as well as any specified PKCS #11 slot */
+ /*****************************************************/
+
+ /* Always initialize the internal software crypto slot */
+ internalSlot = PK11_GetInternalSlot();
+
+ /* If "slotname != NULL", initialize the slot based upon the slotname */
+ if( PL_strcmp( slotname, "internal" ) == 0 ) {
+ slot = PK11_GetInternalKeySlot();
+ } else if( slotname != NULL ) {
+ slot = PK11_FindSlotByName( /* slot name */ slotname );
+
+ /* Fixes Bugscape Bug #55178: tkstool dumps core if -h <token> */
+ /* specifies a nonexistent token */
+ if( slot == NULL ) {
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+
+ if( errLen > 0 && errLen < sizeof buffer ) {
+ PR_GetErrorText( buffer );
+ }
+
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s%s%s",
+ progName,
+ commandToRun,
+ "no token called \"",
+ slotname,
+ "\" exists!" );
+
+ if( errLen > 0 && errLen < sizeof buffer ) {
+ PR_fprintf( PR_STDERR, "\t%s\n", buffer );
+ } else {
+ PR_fprintf( PR_STDERR, "\n" );
+ }
+
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+
+
+ /****************************************/
+ /* Execute the "-D" delete keys command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /****************************************/
+
+ if( tkstool.commands[cmd_DeleteKey].activated ) {
+ rv = TKS_DeleteKeys( progName,
+ slot,
+ keyname,
+ &pwdata );
+ goto shutdown;
+ }
+
+
+ /*******************************************************************/
+ /* Execute the "-I" input shares to generate transport key command */
+ /* */
+ /* --- OR --- */
+ /* */
+ /* Execute the "-T" generate transport key command */
+ /* */
+ /* NOTE: Each of these commands is mutually */
+ /* exclusive from all others, including */
+ /* each other. */
+ /*******************************************************************/
+
+ if( tkstool.commands[cmd_InputGenTransportKey].activated ||
+ tkstool.commands[cmd_GenTransportKey].activated ) {
+
+ /**********************************************************/
+ /* Do not allow duplicate symmetric keys to be generated */
+ /* (i. e. - disallow symmetric keys specified */
+ /* by the same keyname) */
+ /* */
+ /* NOTE: The following code snippet effectively */
+ /* prohibits this tool from generating any */
+ /* symmetric key with a keyname that already */
+ /* resides in the specified token */
+ /**********************************************************/
+
+ rvFindSymKey = TKS_FindSymKey( slot,
+ keyname,
+ &pwdata );
+ if( rvFindSymKey == SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" keyname specified by "
+ "\n\t\t\"-n %s\"\n\t\talready exists in the "
+ "specified token.\n\t\tPlease specify a "
+ "different keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /**********************************************/
+ /* Seed the Random Number Generator (RNG). */
+ /* ("-T" generate transport key command ONLY) */
+ /**********************************************/
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ rvSeedRNG = TKS_SeedRNG( SeedNoise );
+ if( rvSeedRNG != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s",
+ progName,
+ commandToRun,
+ "unable to seed random number generator\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+
+
+ /***********************************/
+ /* Clear screen and wait for user. */
+ /***********************************/
+
+ TKS_ClearScreen();
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ PR_fprintf( PR_STDOUT,
+ "\nThe next screen generates the "
+ "first session key share . . .\n" );
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ PR_fprintf( PR_STDOUT,
+ "\nUse the next screen to input the "
+ "first session key share . . .\n" );
+ }
+
+ TKS_TypeProceedToContinue();
+
+
+ /******************************************************************/
+ /* Input ("-I"), or Generate ("-T"), the first session key share. */
+ /******************************************************************/
+
+ firstSessionKeyShare.len = FIRST_SESSION_KEY_SHARE_LENGTH;
+ firstSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( FIRST_SESSION_KEY_SHARE_LENGTH );
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ rvFirstSessionKeyShare = TKS_GenerateSessionKeyShare(
+ FIRST_SESSION_KEY_SHARE,
+ &firstSessionKeyShare );
+
+ if( rvFirstSessionKeyShare != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s",
+ progName,
+ commandToRun,
+ "unable to generate the ",
+ FIRST_SESSION_KEY_SHARE,
+ " session key share\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ while( rvFirstSessionKeyShare != SECSuccess ) {
+ rvFirstSessionKeyShare = TKS_InputSessionKeyShare(
+ FIRST_SESSION_KEY_SHARE,
+ &firstSessionKeyShare );
+ }
+ }
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /****************************************************************/
+ /* Since TKS uses double-DES keys instead of triple-DES keys, */
+ /* the final 8 bytes of this session key share must be padded */
+ /* in order to use the standard PKCS #11 triple-DES operations! */
+ /* */
+ /* Therefore, in order to perform this operation, the 16 bytes */
+ /* comprising the original buffer are first copied into the new */
+ /* buffer, and then the first 8 bytes of the original buffer */
+ /* are copied into the final 8 bytes of the new buffer. */
+ /****************************************************************/
+
+ paddedFirstSessionKeyShare.len = PADDED_FIRST_SESSION_KEY_SHARE_LENGTH;
+ paddedFirstSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( PADDED_FIRST_SESSION_KEY_SHARE_LENGTH );
+
+ PORT_Memcpy( paddedFirstSessionKeyShare.data,
+ firstSessionKeyShare.data,
+ FIRST_SESSION_KEY_SHARE_LENGTH );
+ PORT_Memcpy( ( paddedFirstSessionKeyShare.data +
+ FIRST_SESSION_KEY_SHARE_LENGTH ),
+ firstSessionKeyShare.data,
+ DES_LENGTH );
+#endif
+
+
+ /***********************************/
+ /* Clear screen and wait for user. */
+ /***********************************/
+
+ TKS_ClearScreen();
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ PR_fprintf( PR_STDOUT,
+ "\nThe next screen generates the "
+ "second session key share . . .\n" );
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ PR_fprintf( PR_STDOUT,
+ "\nUse the next screen to input the "
+ "second session key share . . .\n" );
+ }
+
+ TKS_TypeProceedToContinue();
+
+
+ /*******************************************************************/
+ /* Input ("-I"), or Generate ("-T"), the second session key share. */
+ /*******************************************************************/
+
+ secondSessionKeyShare.len = SECOND_SESSION_KEY_SHARE_LENGTH;
+ secondSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( SECOND_SESSION_KEY_SHARE_LENGTH );
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ rvSecondSessionKeyShare = TKS_GenerateSessionKeyShare(
+ SECOND_SESSION_KEY_SHARE,
+ &secondSessionKeyShare );
+
+ if( rvSecondSessionKeyShare != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s",
+ progName,
+ commandToRun,
+ "unable to generate the ",
+ SECOND_SESSION_KEY_SHARE,
+ " session key share\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ while( rvSecondSessionKeyShare != SECSuccess ) {
+ rvSecondSessionKeyShare = TKS_InputSessionKeyShare(
+ SECOND_SESSION_KEY_SHARE,
+ &secondSessionKeyShare );
+ }
+ }
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /****************************************************************/
+ /* Since TKS uses double-DES keys instead of triple-DES keys, */
+ /* the final 8 bytes of this session key share must be padded */
+ /* in order to use the standard PKCS #11 triple-DES operations! */
+ /* */
+ /* Therefore, in order to perform this operation, the 16 bytes */
+ /* comprising the original buffer are first copied into the new */
+ /* buffer, and then the first 8 bytes of the original buffer */
+ /* are copied into the final 8 bytes of the new buffer. */
+ /****************************************************************/
+
+ paddedSecondSessionKeyShare.len = PADDED_SECOND_SESSION_KEY_SHARE_LENGTH;
+ paddedSecondSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( PADDED_SECOND_SESSION_KEY_SHARE_LENGTH );
+
+ PORT_Memcpy( paddedSecondSessionKeyShare.data,
+ secondSessionKeyShare.data,
+ SECOND_SESSION_KEY_SHARE_LENGTH );
+ PORT_Memcpy( ( paddedSecondSessionKeyShare.data +
+ SECOND_SESSION_KEY_SHARE_LENGTH ),
+ secondSessionKeyShare.data,
+ DES_LENGTH );
+
+
+ /**********************************************/
+ /* Prepare this key share to be used with the */
+ /* TKS_DeriveSymmetricKey() function . . . */
+ /**********************************************/
+
+ /* store a copy of the "original" padded second session key share */
+ secondDerivationData.ulLen = paddedSecondSessionKeyShare.len;
+ secondDerivationData.pData = ( unsigned char * )
+ PORT_ZAlloc( paddedSecondSessionKeyShare.len );
+ PORT_Memcpy( secondDerivationData.pData,
+ paddedSecondSessionKeyShare.data,
+ paddedSecondSessionKeyShare.len );
+
+ /* destroy the "original" padded second session key share */
+ if( paddedSecondSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ paddedSecondSessionKeyShare.data,
+ paddedSecondSessionKeyShare.len );
+ paddedSecondSessionKeyShare.data = NULL;
+ paddedSecondSessionKeyShare.len = 0;
+ }
+
+ /* create a "new" container for the padded second session key share */
+ paddedSecondSessionKeyShare.len = sizeof( CK_KEY_DERIVATION_STRING_DATA );
+ paddedSecondSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( paddedSecondSessionKeyShare.len );
+
+ /* copy the "original" padded second session key share */
+ /* into the "new" container */
+ PORT_Memcpy( paddedSecondSessionKeyShare.data,
+ &secondDerivationData,
+ paddedSecondSessionKeyShare.len );
+#else
+ /**********************************************/
+ /* Prepare this key share to be used with the */
+ /* TKS_DeriveSymmetricKey() function . . . */
+ /**********************************************/
+
+ /* store a copy of the "original" second session key share */
+ secondDerivationData.ulLen = secondSessionKeyShare.len;
+ secondDerivationData.pData = ( unsigned char * )
+ PORT_ZAlloc( secondSessionKeyShare.len );
+ PORT_Memcpy( secondDerivationData.pData,
+ secondSessionKeyShare.data,
+ secondSessionKeyShare.len );
+
+ /* destroy the "original" second session key share */
+ if( secondSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ secondSessionKeyShare.data,
+ secondSessionKeyShare.len );
+ secondSessionKeyShare.data = NULL;
+ secondSessionKeyShare.len = 0;
+ }
+
+ /* create a "new" container for the second session key share */
+ secondSessionKeyShare.len = sizeof( CK_KEY_DERIVATION_STRING_DATA );
+ secondSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( secondSessionKeyShare.len );
+
+ /* copy the "original" second session key share */
+ /* into the "new" container */
+ PORT_Memcpy( secondSessionKeyShare.data,
+ &secondDerivationData,
+ secondSessionKeyShare.len );
+#endif
+
+
+ /***********************************/
+ /* Clear screen and wait for user. */
+ /***********************************/
+
+ TKS_ClearScreen();
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ PR_fprintf( PR_STDOUT,
+ "\nThe next screen generates the "
+ "third session key share . . .\n" );
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ PR_fprintf( PR_STDOUT,
+ "\nUse the next screen to input the "
+ "third session key share . . .\n" );
+ }
+
+ TKS_TypeProceedToContinue();
+
+
+ /******************************************************************/
+ /* Input ("-I"), or Generate ("-T"), the third session key share. */
+ /******************************************************************/
+
+ thirdSessionKeyShare.len = THIRD_SESSION_KEY_SHARE_LENGTH;
+ thirdSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( THIRD_SESSION_KEY_SHARE_LENGTH );
+
+ if( tkstool.commands[cmd_GenTransportKey].activated ) {
+ rvThirdSessionKeyShare = TKS_GenerateSessionKeyShare(
+ THIRD_SESSION_KEY_SHARE,
+ &thirdSessionKeyShare );
+
+ if( rvThirdSessionKeyShare != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s",
+ progName,
+ commandToRun,
+ "unable to generate the ",
+ THIRD_SESSION_KEY_SHARE,
+ " session key share\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else {
+ /* ( tkstool.commands[cmd_InputGenTransportKey].activated ) */
+ while( rvThirdSessionKeyShare != SECSuccess ) {
+ rvThirdSessionKeyShare = TKS_InputSessionKeyShare(
+ THIRD_SESSION_KEY_SHARE,
+ &thirdSessionKeyShare );
+ }
+ }
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /****************************************************************/
+ /* Since TKS uses double-DES keys instead of triple-DES keys, */
+ /* the final 8 bytes of this session key share must be padded */
+ /* in order to use the standard PKCS #11 triple-DES operations! */
+ /* */
+ /* Therefore, in order to perform this operation, the 16 bytes */
+ /* comprising the original buffer are first copied into the new */
+ /* buffer, and then the first 8 bytes of the original buffer */
+ /* are copied into the final 8 bytes of the new buffer. */
+ /****************************************************************/
+
+ paddedThirdSessionKeyShare.len = PADDED_THIRD_SESSION_KEY_SHARE_LENGTH;
+ paddedThirdSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( PADDED_THIRD_SESSION_KEY_SHARE_LENGTH );
+
+ PORT_Memcpy( paddedThirdSessionKeyShare.data,
+ thirdSessionKeyShare.data,
+ THIRD_SESSION_KEY_SHARE_LENGTH );
+ PORT_Memcpy( ( paddedThirdSessionKeyShare.data +
+ THIRD_SESSION_KEY_SHARE_LENGTH ),
+ thirdSessionKeyShare.data,
+ DES_LENGTH );
+
+
+ /**********************************************/
+ /* Prepare this key share to be used with the */
+ /* TKS_DeriveSymmetricKey() function . . . */
+ /**********************************************/
+
+ /* store a copy of the "original" padded third session key share */
+ thirdDerivationData.ulLen = paddedThirdSessionKeyShare.len;
+ thirdDerivationData.pData = ( unsigned char * )
+ PORT_ZAlloc( paddedThirdSessionKeyShare.len );
+ PORT_Memcpy( thirdDerivationData.pData,
+ paddedThirdSessionKeyShare.data,
+ paddedThirdSessionKeyShare.len );
+
+ /* destroy the "original" padded third session key share */
+ if( paddedThirdSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ paddedThirdSessionKeyShare.data,
+ paddedThirdSessionKeyShare.len );
+ paddedThirdSessionKeyShare.data = NULL;
+ paddedThirdSessionKeyShare.len = 0;
+ }
+
+ /* create a "new" container for the padded third session key share */
+ paddedThirdSessionKeyShare.len = sizeof( CK_KEY_DERIVATION_STRING_DATA );
+ paddedThirdSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( paddedThirdSessionKeyShare.len );
+
+ /* copy the "original" padded third session key share */
+ /* into the "new" container */
+ PORT_Memcpy( paddedThirdSessionKeyShare.data,
+ &thirdDerivationData,
+ paddedThirdSessionKeyShare.len );
+#else
+ /**********************************************/
+ /* Prepare this key share to be used with the */
+ /* TKS_DeriveSymmetricKey() function . . . */
+ /**********************************************/
+
+ /* store a copy of the "original" third session key share */
+ thirdDerivationData.ulLen = thirdSessionKeyShare.len;
+ thirdDerivationData.pData = ( unsigned char * )
+ PORT_ZAlloc( thirdSessionKeyShare.len );
+ PORT_Memcpy( thirdDerivationData.pData,
+ thirdSessionKeyShare.data,
+ thirdSessionKeyShare.len );
+
+ /* destroy the "original" third session key share */
+ if( thirdSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ thirdSessionKeyShare.data,
+ thirdSessionKeyShare.len );
+ thirdSessionKeyShare.data = NULL;
+ thirdSessionKeyShare.len = 0;
+ }
+
+ /* create a "new" container for the third session key share */
+ thirdSessionKeyShare.len = sizeof( CK_KEY_DERIVATION_STRING_DATA );
+ thirdSessionKeyShare.data = ( unsigned char * )
+ PORT_ZAlloc( thirdSessionKeyShare.len );
+
+ /* copy the "original" third session key share */
+ /* into the "new" container */
+ PORT_Memcpy( thirdSessionKeyShare.data,
+ &thirdDerivationData,
+ thirdSessionKeyShare.len );
+#endif
+
+
+ /***********************************/
+ /* Clear screen and wait for user. */
+ /***********************************/
+
+ TKS_ClearScreen();
+
+ PR_fprintf( PR_STDOUT,
+ "\nThe next screen uses the session key shares to "
+ "generate the transport key . . .\n" );
+
+ TKS_TypeProceedToContinue();
+
+ TKS_ClearScreen();
+
+
+ /**************************************/
+ /* Generate the first symmetric key */
+ /* using the first session key share. */
+ /**************************************/
+
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ firstSymmetricKey = TKS_ImportSymmetricKey( FIRST_SYMMETRIC_KEY,
+ internalSlot,
+ CKM_DES3_KEY_GEN,
+ CKA_ENCRYPT,
+ &paddedFirstSessionKeyShare,
+ &pwdata );
+#else
+ firstSymmetricKey = TKS_ImportSymmetricKey( FIRST_SYMMETRIC_KEY,
+ internalSlot,
+ CKM_DES2_KEY_GEN,
+ CKA_ENCRYPT,
+ &firstSessionKeyShare,
+ &pwdata );
+#endif
+ if( firstSymmetricKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate the first (or initial) "
+ "symmetric key",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*********************************************************/
+ /* Generate the second symmetric key using the */
+ /* first symmetric key and the second session key share. */
+ /*********************************************************/
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ secondSymmetricKey = TKS_DeriveSymmetricKey( SECOND_SYMMETRIC_KEY,
+ firstSymmetricKey,
+ CKM_XOR_BASE_AND_DATA,
+ &paddedSecondSessionKeyShare,
+ CKM_DES3_ECB,
+ ( CKA_DERIVE |
+ CKA_ENCRYPT ),
+ PADDED_SECOND_SESSION_KEY_SHARE_LENGTH );
+#else
+ secondSymmetricKey = TKS_DeriveSymmetricKey( SECOND_SYMMETRIC_KEY,
+ firstSymmetricKey,
+ CKM_XOR_BASE_AND_DATA,
+ &secondSessionKeyShare,
+ CKM_DES3_ECB,
+ ( CKA_DERIVE |
+ CKA_ENCRYPT ),
+ SECOND_SESSION_KEY_SHARE_LENGTH );
+#endif
+ if( secondSymmetricKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate the second (or intermediate) "
+ "symmetric key",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*********************************************************/
+ /* Generate the third symmetric key using the */
+ /* second symmetric key and the third session key share. */
+ /*********************************************************/
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ thirdSymmetricKey = TKS_DeriveSymmetricKey( THIRD_SYMMETRIC_KEY,
+ secondSymmetricKey,
+ CKM_XOR_BASE_AND_DATA,
+ &paddedThirdSessionKeyShare,
+ CKM_DES3_ECB,
+ ( CKA_DERIVE |
+ CKA_ENCRYPT ),
+ PADDED_THIRD_SESSION_KEY_SHARE_LENGTH );
+#else
+ thirdSymmetricKey = TKS_DeriveSymmetricKey( THIRD_SYMMETRIC_KEY,
+ secondSymmetricKey,
+ CKM_XOR_BASE_AND_DATA,
+ &thirdSessionKeyShare,
+ CKM_DES3_ECB,
+ ( CKA_DERIVE |
+ CKA_ENCRYPT ),
+ THIRD_SESSION_KEY_SHARE_LENGTH );
+#endif
+ if( thirdSymmetricKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate the third (or final) "
+ "symmetric key",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*******************************************************************/
+ /* Finally, store the third symmetric key (the transport key) into */
+ /* the specified slot, and provide a name for this transport key. */
+ /*******************************************************************/
+
+ rvSymmetricKeyname = TKS_StoreSymmetricKeyAndNameIt( TRANSPORT_KEY,
+ keyname,
+ slot,
+ ( CKA_ENCRYPT |
+ CKA_WRAP ),
+ ( CKF_ENCRYPT |
+ CKF_UNWRAP |
+ CKF_WRAP ),
+ thirdSymmetricKey );
+ if( rvSymmetricKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to save/name the transport key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Successfully generated, stored, and named the "
+ "transport key!\n\n" );
+ }
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+ /****************************************/
+ /* Execute the "-K" display KCV command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /****************************************/
+
+ if( tkstool.commands[cmd_DisplayKCV].activated ) {
+
+ /*****************************************************/
+ /* Retrieve a handle to the specified symmetric key. */
+ /* This insures that the specified symmetric key */
+ /* already resides on the specified token. */
+ /*****************************************************/
+
+ symmetricKey = TKS_RetrieveSymKey( slot,
+ keyname,
+ &pwdata );
+ if( symmetricKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" symmetric keyname specified by "
+ "\n\t\t\"-n %s\" does NOT exist on the specified "
+ "token.\n\t\tPlease specify a "
+ "different symmetric keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*************************************************/
+ /* Compute and display this symmetric key's KCV. */
+ /*************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "\nComputing and displaying KCV of the symmetric key "
+ "on the specified token . . .\n\n" );
+
+ /* Calculate this symmetric key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ symmetricKey,
+ keyname,
+ RESIDENT_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Unable to compute/display KCV of "
+ "this symmetric key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+ /**************************************/
+ /* Execute the "-L" list keys command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /**************************************/
+
+ if( tkstool.commands[cmd_ListKeys].activated ) {
+ rv = TKS_ListKeys( progName,
+ slot,
+ keyname,
+ 0 /*keyindex*/,
+ PR_FALSE /*dopriv*/,
+ &pwdata );
+ goto shutdown;
+ }
+
+
+ /************************************************/
+ /* Execute the "-M" generate master key command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /************************************************/
+
+ if( tkstool.commands[cmd_GenMasterKey].activated ) {
+
+ /**********************************************************/
+ /* Do not allow duplicate symmetric keys to be generated */
+ /* (i. e. - disallow symmetric keys specified */
+ /* by the same keyname) */
+ /* */
+ /* NOTE: The following code snippet effectively */
+ /* prohibits this tool from generating any */
+ /* symmetric key with a keyname that already */
+ /* resides in the specified token */
+ /**********************************************************/
+
+ rvFindSymKey = TKS_FindSymKey( slot,
+ keyname,
+ &pwdata );
+ if( rvFindSymKey == SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" keyname specified by "
+ "\n\t\t\"-n %s\"\n\t\talready exists in the "
+ "specified token.\n\t\tPlease specify a "
+ "different keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Generate the master key and store it on the designated token. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "\nGenerating and storing the master key "
+ "on the specified token . . .\n\n" );
+
+ if( MASTER_KEY_LENGTH == ( 2 * DES_LENGTH ) ) {
+ masterKey = PK11_TokenKeyGen(
+ /* slot */ slot,
+ /* mechanism */ CKM_DES2_KEY_GEN,
+ /* param */ 0,
+ /* keySize */ 0,
+ /* keyid */ 0,
+ /* isToken (i. e. - isPerm) */ PR_TRUE,
+ /* wincx */ &pwdata );
+ if( masterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate/store this DES2 master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else if( MASTER_KEY_LENGTH == ( 3 * DES_LENGTH ) ) {
+ masterKey = PK11_TokenKeyGen(
+ /* slot */ slot,
+ /* mechanism */ CKM_DES3_KEY_GEN,
+ /* param */ 0,
+ /* keySize */ 0,
+ /* keyid */ 0,
+ /* isToken (i. e. - isPerm) */ PR_TRUE,
+ /* wincx */ &pwdata );
+ if( masterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate/store this DES3 master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else {
+ /* invalid key size */
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s\n\n\n",
+ progName,
+ commandToRun,
+ "MASTER_KEY_LENGTH must be DES2 or DES3 length!" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Finally, name the master key with the specified name. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Naming the master key \"%s\" . . .\n\n",
+ keyname );
+
+ rvMasterKeyname = PK11_SetSymKeyNickname(
+ /* symmetric key */ masterKey,
+ /* nickname */ keyname );
+ if( rvMasterKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to name the master key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*********************************************/
+ /* Compute and display the master key's KCV. */
+ /*********************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Computing and displaying KCV of the master key "
+ "on the specified token . . .\n\n" );
+
+ /* Calculate the master key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ masterKey,
+ keyname,
+ RESIDENT_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Unable to compute/display KCV of "
+ "the master key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Successfully generated, stored, and named the "
+ "master key\nincluding computing and displaying "
+ "its KCV!\n\n" );
+ }
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+ /**************************************************************/
+ /* Execute the "-N" new software database creation command */
+ /* */
+ /* NOTE: This command is mutually exclusive from all others. */
+ /* Always initialize the password when creating a new */
+ /* set of software databases */
+ /**************************************************************/
+
+ if( tkstool.commands[cmd_NewDBs].activated ) {
+ rv = SECU_ChangePW( slot,
+ 0,
+ pwdata.data );
+ goto shutdown;
+ }
+
+
+ /****************************************************/
+ /* Execute the "-P" change key DB password command */
+ /* */
+ /* NOTE: This command is mutually exclusive from */
+ /* all others. (future - change pw to slot?) */
+ /****************************************************/
+
+ if( tkstool.commands[cmd_ChangePassword].activated ) {
+ rv = SECU_ChangePW( slot,
+ 0,
+ pwdata.data );
+ goto shutdown;
+ }
+
+
+ /***************************************/
+ /* Execute the "-R" rename key command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /***************************************/
+
+ if( tkstool.commands[cmd_RenameKey].activated ) {
+
+ /*****************************************************/
+ /* Check that specified keynames are not identical. */
+ /*****************************************************/
+ if( PL_strcmp( keyname, new_keyname ) == 0 ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe two keynames specified by "
+ "\n\t\t\"-n %s\" and \"-r %s\" are identical."
+ "\n\t\tPlease provide two non-identical keynames.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ new_keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ /*****************************************************/
+ /* Retrieve a handle to the specified symmetric key. */
+ /* This insures that the specified symmetric key */
+ /* already resides on the specified token. */
+ /*****************************************************/
+
+ symmetricKey = TKS_RetrieveSymKey( slot,
+ keyname,
+ &pwdata );
+ if( symmetricKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" symmetric keyname specified by "
+ "\n\t\t\"-n %s\" does NOT exist on the specified "
+ "token.\n\t\tPlease specify a "
+ "different symmetric keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /**********************************************************/
+ /* Do not allow the renamed key to overwrite a */
+ /* preexisting key of the same name */
+ /* */
+ /* NOTE: The following code snippet effectively */
+ /* prohibits this tool from renaming any */
+ /* symmetric key with a keyname that already */
+ /* resides in the specified token */
+ /**********************************************************/
+
+ rvFindSymKey = TKS_FindSymKey( slot,
+ new_keyname,
+ &pwdata );
+ if( rvFindSymKey == SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" keyname specified by "
+ "\n\t\t\"-r %s\"\n\t\talready exists in the "
+ "specified token.\n\t\tPlease specify a "
+ "different keyname for renaming purposes.\n\n",
+ progName,
+ commandToRun,
+ new_keyname,
+ new_keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+#if defined(DEBUG)
+ /*****************************************************************/
+ /* For convenience, compute and display the symmetric key's KCV. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Computing and displaying KCV of the symmetric key "
+ "on the specified token . . .\n\n" );
+
+ /* Calculate the symmetric key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ symmetricKey,
+ keyname,
+ RESIDENT_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Unable to compute/display KCV of "
+ "the symmetric key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+#endif
+
+
+ /********************************************************************/
+ /* Finally, rename the symmetric key with the newly specified name. */
+ /********************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Renaming the symmetric key named \"%s\" to \"%s\" . . .\n\n",
+ keyname,
+ new_keyname );
+
+ rvSymmetricKeyname = PK11_SetSymKeyNickname(
+ /* symmetric key */ symmetricKey,
+ /* nickname */ new_keyname );
+ if( rvSymmetricKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to rename the symmetric key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Successfully renamed the symmetric key named \"%s\" "
+ "to \"%s\"!\n\n",
+ keyname,
+ new_keyname );
+ }
+
+
+#if defined(DEBUG)
+ /********************************************************/
+ /* For convenience, compute and display the renamed */
+ /* symmetric key's KCV. */
+ /********************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Computing and displaying KCV of the renamed symmetric key "
+ "on the specified token . . .\n\n" );
+
+ /* Calculate the renamed symmetric key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ symmetricKey,
+ new_keyname,
+ RESIDENT_KEY,
+ PR_TRUE,
+ NULL );
+ if( rvKCV != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Unable to compute/display KCV of "
+ "the renamed symmetric key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+#endif
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+ /**************************************************/
+ /* Execute the "-S" list security modules command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /**************************************************/
+
+ if( tkstool.commands[cmd_ListSecModules].activated ) {
+ rv = TKS_ListSecModules();
+ goto shutdown;
+ }
+
+
+ /**********************************************/
+ /* Execute the "-U" unwrap master key command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /**********************************************/
+
+ if( tkstool.commands[cmd_UnWrapMasterKey].activated ) {
+
+ /**********************************************************/
+ /* Do not allow duplicate symmetric keys to be stored */
+ /* (i. e. - disallow symmetric keys specified */
+ /* by the same keyname) */
+ /* */
+ /* NOTE: The following code snippet effectively */
+ /* prohibits this tool from storing any */
+ /* symmetric key with a keyname that already */
+ /* resides in the specified token */
+ /**********************************************************/
+
+ rvFindSymKey = TKS_FindSymKey( slot,
+ keyname,
+ &pwdata );
+ if( rvFindSymKey == SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" keyname specified by "
+ "\n\t\t\"-n %s\"\n\t\talready exists in the "
+ "specified token.\n\t\tPlease specify a "
+ "different keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*******************************************************************/
+ /* Retrieve a handle to the specified unwrapping key. This insures */
+ /* that the specified unwrapping key (i. e. - transport key) */
+ /* already exists on the specified token. */
+ /* */
+ /* NOTE: Requiring that the transport key AND the master key */
+ /* reside on the same token is a FIPS 140-1 requirement! */
+ /*******************************************************************/
+
+ TKS_ClearScreen();
+
+ PR_fprintf( PR_STDOUT,
+ "\nRetrieving the transport key from the "
+ "specified token (for unwrapping) . . .\n\n" );
+
+ transportKey = TKS_RetrieveSymKey( slot,
+ transport_keyname,
+ &pwdata );
+ if( transportKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" transport keyname specified by "
+ "\"-t %s\"\n\t\tdoes NOT exist on the specified "
+ "token.\n\t\tPlease specify a "
+ "different transport keyname.\n\n",
+ progName,
+ commandToRun,
+ transport_keyname,
+ transport_keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Read in the wrapped master key from the specified input file. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Reading in the wrapped data (and resident master key KCV) "
+ "from the file called\n\"%s\" . . .\n\n",
+ input );
+
+ /* Create a clean new storage buffer for this wrapped key */
+ wrappedMasterKey.len = WRAPPED_KEY_LENGTH;
+ wrappedMasterKey.data = ( unsigned char * )
+ PORT_ZAlloc( WRAPPED_KEY_LENGTH );
+
+ /* Create a clean new hex storage buffer for this master key's KCV */
+ hexInternalKeyKCV.type = ( SECItemType ) siBuffer;
+ hexInternalKeyKCV.len = ( HEX_WRAPPED_KEY_KCV_LENGTH + 1 );
+ hexInternalKeyKCV.data = ( unsigned char * )
+ PORT_ZAlloc( hexInternalKeyKCV.len );
+ if( hexInternalKeyKCV.data == NULL ) {
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ rvWrappedMasterKey = TKS_ReadInputFileIntoSECItem( input,
+ ( char * ) hexInternalKeyKCV.data,
+ hexInternalKeyKCV.len,
+ keyname,
+ &wrappedMasterKey );
+ if( rvWrappedMasterKey != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tunable to read in wrapped master key "
+ "from file called \"%s\".\n",
+ progName,
+ commandToRun,
+ input );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*************************************************************/
+ /* Temporarily unwrap the master key to check its KCV value. */
+ /*************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Using the transport key to temporarily unwrap "
+ "the master key to recompute\nits KCV value to "
+ "check against its pre-computed KCV value . . .\n\n" );
+
+ temporaryMasterKey = PK11_UnwrapSymKeyWithFlagsPerm(
+ /* wrapping key */ transportKey,
+ /* wraptype */ CKM_DES3_ECB,
+ /* param */ 0,
+ /* wrapped key */ &wrappedMasterKey,
+ /* target */ CKM_DES3_ECB,
+ /* operation */ CKA_ENCRYPT,
+ /* target key length */ WRAPPED_KEY_LENGTH,
+ /* flags */ 0,
+ /* isPerm */ PR_FALSE );
+ if( temporaryMasterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to temporarily unwrap the master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ /* verify that the wrapped key and KCV read in from */
+ /* the input file correspond to each other . . . */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ temporaryMasterKey,
+ keyname,
+ UNWRAPPED_KEY,
+ PR_FALSE,
+ hexInternalKeyKCV.data );
+ if( rvKCV != SECSuccess ) {
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /***************************************************************/
+ /* Unwrap the master key and store it on the designated token. */
+ /***************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Using the transport key to unwrap and store "
+ "the master key\non the specified token . . .\n\n" );
+
+ masterKey = PK11_UnwrapSymKeyWithFlagsPerm(
+ /* wrapping key */ transportKey,
+ /* wraptype */ CKM_DES3_ECB,
+ /* param */ 0,
+ /* wrapped key */ &wrappedMasterKey,
+ /* target */ CKM_DES3_ECB,
+ /* operation */ CKA_ENCRYPT,
+ /* target key length */ WRAPPED_KEY_LENGTH,
+ /* flags */ 0,
+ /* isPerm */ PR_TRUE );
+ if( masterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to unwrap/store the master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Finally, name the master key with the specified name. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Naming the master key \"%s\" . . .\n\n",
+ keyname );
+
+ rvMasterKeyname = PK11_SetSymKeyNickname(
+ /* symmetric key */ masterKey,
+ /* nickname */ keyname );
+ if( rvMasterKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to name the master key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Successfully unwrapped, stored, and named the "
+ "master key!\n\n" );
+ }
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+ /******************************************************/
+ /* Execute the "-W" wrap generated master key command */
+ /* */
+ /* NOTE: This command is mutually */
+ /* exclusive from all others. */
+ /******************************************************/
+
+ if( tkstool.commands[cmd_WrapMasterKey].activated ) {
+
+ /**********************************************************/
+ /* Do not allow duplicate symmetric keys to be stored */
+ /* (i. e. - disallow symmetric keys specified */
+ /* by the same keyname) */
+ /* */
+ /* NOTE: The following code snippet effectively */
+ /* prohibits this tool from storing any */
+ /* symmetric key with a keyname that already */
+ /* resides in the specified token */
+ /**********************************************************/
+
+ rvFindSymKey = TKS_FindSymKey( slot,
+ keyname,
+ &pwdata );
+ if( rvFindSymKey == SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" keyname specified by "
+ "\n\t\t\"-n %s\"\n\t\talready exists in the "
+ "specified token.\n\t\tPlease specify a "
+ "different keyname.\n\n",
+ progName,
+ commandToRun,
+ keyname,
+ keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Retrieve a handle to the specified wrapping key. This insures */
+ /* that the specified wrapping key (i. e. - transport key) */
+ /* already exists on the specified token. */
+ /* */
+ /* NOTE: Requiring that the transport key AND the master key */
+ /* reside on the same token is a FIPS 140-1 requirement! */
+ /*****************************************************************/
+
+ TKS_ClearScreen();
+
+ PR_fprintf( PR_STDOUT,
+ "\nRetrieving the transport key (for wrapping) "
+ "from the specified token . . .\n\n" );
+
+ transportKey = TKS_RetrieveSymKey( slot,
+ transport_keyname,
+ &pwdata );
+ if( transportKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c:\tthe \"%s\" transport keyname specified by "
+ "\"-t %s\"\n\t\tdoes NOT exist on the specified "
+ "token.\n\t\tPlease specify a "
+ "different transport keyname.\n\n",
+ progName,
+ commandToRun,
+ transport_keyname,
+ transport_keyname );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*****************************************************************/
+ /* Generate the master key and store it on the designated token. */
+ /*****************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Generating and storing the master key "
+ "on the specified token . . .\n\n" );
+
+ if( WRAPPED_KEY_LENGTH == ( 2 * DES_LENGTH ) ) {
+ masterKey = PK11_TokenKeyGen(
+ /* slot */ slot,
+ /* mechanism */ CKM_DES2_KEY_GEN,
+ /* param */ 0,
+ /* keySize */ 0,
+ /* keyid */ 0,
+ /* isToken (i. e. - isPerm) */ PR_TRUE,
+ /* wincx */ &pwdata );
+ if( masterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate/store this DES2 master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else if( WRAPPED_KEY_LENGTH == ( 3 * DES_LENGTH ) ) {
+ masterKey = PK11_TokenKeyGen(
+ /* slot */ slot,
+ /* mechanism */ CKM_DES3_KEY_GEN,
+ /* param */ 0,
+ /* keySize */ 0,
+ /* keyid */ 0,
+ /* isToken (i. e. - isPerm) */ PR_TRUE,
+ /* wincx */ &pwdata );
+ if( masterKey == NULL ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to generate/store this DES3 master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+ } else {
+ /* invalid key size */
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s\n\n\n",
+ progName,
+ commandToRun,
+ "WRAPPED_KEY_LENGTH must be DES2 or DES3 length!" );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /************************************************/
+ /* Name the master key with the specified name. */
+ /************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Naming the master key \"%s\" . . .\n\n",
+ keyname );
+
+ rvMasterKeyname = PK11_SetSymKeyNickname(
+ /* symmetric key */ masterKey,
+ /* nickname */ keyname );
+ if( rvMasterKeyname != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "ERROR: Failed to name the master key!\n\n" );
+ rv = SECFailure;
+ goto shutdown;
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "Successfully generated, stored, and named the "
+ "master key!\n\n" );
+ }
+
+
+ /**********************************/
+ /* Compute this master key's KCV. */
+ /**********************************/
+
+ /* Create a clean new hex storage buffer for this master key's KCV */
+ hexInternalKeyKCV.type = ( SECItemType ) siBuffer;
+ hexInternalKeyKCV.len = ( HEX_WRAPPED_KEY_KCV_LENGTH + 1 );
+ hexInternalKeyKCV.data = ( unsigned char * )
+ PORT_ZAlloc( hexInternalKeyKCV.len );
+ if( hexInternalKeyKCV.data == NULL ) {
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+ /* Calculate this master key's KCV */
+ rvKCV = TKS_ComputeAndDisplayKCV( ( PRUint8 * ) NULL,
+ ( PRIntn ) 0,
+ ( PRUint8 * ) KCV,
+ ( PRIntn ) KCVLen,
+ masterKey,
+ keyname,
+ WRAPPED_KEY,
+ PR_FALSE,
+ hexInternalKeyKCV.data );
+ if( rvKCV != SECSuccess ) {
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /****************************************/
+ /* Wrap the newly generated master key. */
+ /****************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Using the transport key to wrap and store "
+ "the master key . . .\n\n" );
+
+ wrappedMasterKey.len = WRAPPED_KEY_LENGTH;
+ wrappedMasterKey.data = ( unsigned char * )
+ PORT_ZAlloc( WRAPPED_KEY_LENGTH );
+
+ rvWrappedMasterKey = PK11_WrapSymKey(
+ /* mechanism type */ CKM_DES3_ECB,
+ /* param */ 0,
+ /* wrapping key */ transportKey,
+ /* key to be wrapped */ masterKey,
+ /* wrapped key */ &wrappedMasterKey );
+ if( rvWrappedMasterKey != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to wrap the master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /**************************************************************/
+ /* Write the wrapped master key to the specified output file. */
+ /**************************************************************/
+
+ PR_fprintf( PR_STDOUT,
+ "Writing the wrapped data (and resident master key KCV) "
+ "into the file called\n\"%s\" . . .\n\n",
+ output );
+
+ rvSaveWrappedMasterKey = TKS_WriteSECItemIntoOutputFile( &wrappedMasterKey,
+ keyname,
+ ( char * ) hexInternalKeyKCV.data,
+ ( hexInternalKeyKCV.len - 1 ),
+ output );
+ if( rvSaveWrappedMasterKey != SECSuccess ) {
+ PR_fprintf( PR_STDERR,
+ "%s -%c: %s:%d\n",
+ progName,
+ commandToRun,
+ "unable to save the wrapped master key ",
+ PR_GetError() );
+ rv = SECFailure;
+ goto shutdown;
+ }
+
+
+ /*********************************/
+ /* Cleanup and exit with success */
+ /*********************************/
+
+ rv = SECSuccess;
+ goto shutdown;
+ }
+
+
+shutdown:
+ /* free internal slot */
+ if( slot ) {
+ PK11_FreeSlot( /* slot */ internalSlot );
+ }
+
+
+ /* free slot */
+ if( slot ) {
+ PK11_FreeSlot( /* slot */ slot );
+ }
+
+
+ /* destroy the pwdata */
+ if( pwdata.data != NULL ) {
+ pwdata.source = PW_NONE;
+ i = 0;
+ do {
+ if( pwdata.data[i] != 0 ) {
+ pwdata.data[i] = 0;
+ i++;
+ } else {
+ status = PR_TRUE;
+ }
+ } while( status == PR_FALSE );
+ }
+
+
+ /* destroy the first session key share */
+ if( firstSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ firstSessionKeyShare.data,
+ firstSessionKeyShare.len );
+ firstSessionKeyShare.data = NULL;
+ firstSessionKeyShare.len = 0;
+ }
+
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /* destroy the first padded session key share */
+ if( paddedFirstSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ paddedFirstSessionKeyShare.data,
+ paddedFirstSessionKeyShare.len );
+ paddedFirstSessionKeyShare.data = NULL;
+ paddedFirstSessionKeyShare.len = 0;
+ }
+#endif
+
+
+ /* destroy the "original" second session key share */
+ if( secondDerivationData.pData != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ secondDerivationData.pData,
+ secondDerivationData.ulLen );
+ secondDerivationData.pData = NULL;
+ secondDerivationData.ulLen = 0;
+ }
+
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /* destroy the second padded session key share */
+ if( paddedSecondSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ paddedSecondSessionKeyShare.data,
+ paddedSecondSessionKeyShare.len );
+ paddedSecondSessionKeyShare.data = NULL;
+ paddedSecondSessionKeyShare.len = 0;
+ }
+#endif
+
+
+ /* destroy the second session key share container */
+ if( secondSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ secondSessionKeyShare.data,
+ secondSessionKeyShare.len );
+ secondSessionKeyShare.data = NULL;
+ secondSessionKeyShare.len = 0;
+ }
+
+
+ /* destroy the "original" third session key share */
+ if( thirdDerivationData.pData != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ thirdDerivationData.pData,
+ thirdDerivationData.ulLen );
+ thirdDerivationData.pData = NULL;
+ thirdDerivationData.ulLen = 0;
+ }
+
+
+#if defined(PAD_DES2_KEY_LENGTH)
+ /* destroy the third padded session key share */
+ if( paddedThirdSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ paddedThirdSessionKeyShare.data,
+ paddedThirdSessionKeyShare.len );
+ paddedThirdSessionKeyShare.data = NULL;
+ paddedThirdSessionKeyShare.len = 0;
+ }
+#endif
+
+
+ /* destroy the third session key share container */
+ if( thirdSessionKeyShare.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ thirdSessionKeyShare.data,
+ thirdSessionKeyShare.len );
+ thirdSessionKeyShare.data = NULL;
+ thirdSessionKeyShare.len = 0;
+ }
+
+
+ /* destroy the first symmetric key */
+ if( firstSymmetricKey ) {
+ PK11_FreeSymKey( /* symmetric key */ firstSymmetricKey );
+ }
+
+
+ /* destroy the second symmetric key */
+ if( secondSymmetricKey ) {
+ PK11_FreeSymKey( /* symmetric key */ secondSymmetricKey );
+ }
+
+
+ /* destroy the third symmetric key (transport key) */
+ if( thirdSymmetricKey ) {
+ PK11_FreeSymKey( /* symmetric key */ thirdSymmetricKey );
+ }
+
+
+ /* destroy the hexInternalKeyKCV */
+ if( hexInternalKeyKCV.data != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ hexInternalKeyKCV.data,
+ hexInternalKeyKCV.len );
+ hexInternalKeyKCV.data = NULL;
+ hexInternalKeyKCV.len = 0;
+ }
+
+
+ /* destroy the KCV */
+ if( KCV != NULL ) {
+ PORT_ZFree( ( unsigned char * )
+ KCV,
+ KCVLen );
+ KCV = NULL;
+ KCVLen = 0;
+ }
+
+
+ /* destroy the temporary master key */
+ if( temporaryMasterKey ) {
+ PK11_FreeSymKey( /* symmetric key */ temporaryMasterKey );
+ }
+
+
+ /* destroy the master key */
+ if( masterKey ) {
+ PK11_FreeSymKey( /* symmetric key */ masterKey );
+ }
+
+
+ /* destroy the transport key */
+ if( transportKey ) {
+ PK11_FreeSymKey( /* symmetric key */ transportKey );
+ }
+
+
+ /* shutdown NSS */
+ if( NSS_Shutdown() != SECSuccess ) {
+ return 255;
+ }
+
+
+ /* exit with an appropriate return value */
+ if( rv == SECSuccess ) {
+ return 0;
+ } else {
+ return 255;
+ }
+}
+
diff --git a/pki/base/native-tools/src/tkstool/tkstool.h b/pki/base/native-tools/src/tkstool/tkstool.h
new file mode 100644
index 000000000..3b0407227
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/tkstool.h
@@ -0,0 +1,321 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+/************************/
+/** #include headers **/
+/************************/
+
+#ifdef HAVE_CONFIG_H
+#ifndef AUTOTOOLS_CONFIG_H
+#define AUTOTOOLS_CONFIG_H
+
+/* Eliminate warnings when using Autotools */
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
+#include <config.h>
+#endif /* AUTOTOOLS_CONFIG_H */
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#include <sys/time.h>
+#include <termios.h>
+#endif
+
+#if defined(XP_WIN) || defined (XP_PC)
+#include <time.h>
+#include <conio.h>
+#endif
+
+#include "secutil.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+
+/****************/
+/** #defines **/
+/****************/
+
+#define TKSTOOL_MAJOR_VERSION_NUMBER 1
+#define TKSTOOL_MINOR_VERSION_NUMBER 0
+#define TKSTOOL_VERSION_SUFFIX ""
+
+#define DEFAULT_KEY_BITS 1024
+#define NUM_KEYSTROKES 120
+#define RAND_BUF_LENGTH 60
+#define DES_LENGTH 8
+#define KEYSTROKES_TO_PROCEED 8
+#define KCV_LENGTH 4
+#define CTRL_C 3
+
+#define FIRST_SESSION_KEY_SHARE "first"
+#define FIRST_SESSION_KEY_SHARE_LENGTH 16
+#define SECOND_SESSION_KEY_SHARE "second"
+#define SECOND_SESSION_KEY_SHARE_LENGTH 16
+#define THIRD_SESSION_KEY_SHARE "third"
+#define THIRD_SESSION_KEY_SHARE_LENGTH 16
+#define HEX_SESSION_KEY_BUF_LENGTH 32
+#define HEX_SESSION_KEY_KCV_BUF_LENGTH 8
+
+#define MASTER_KEY_LENGTH 16
+
+#define WRAPPED_KEY_LENGTH 16
+#define HEX_WRAPPED_KEY_LENGTH 32
+#define HEX_WRAPPED_KEY_KCV_LENGTH 8
+
+#if defined(PAD_DES2_KEY_LENGTH)
+#define PADDED_FIRST_SESSION_KEY_SHARE_LENGTH 24
+#define PADDED_SECOND_SESSION_KEY_SHARE_LENGTH 24
+#define PADDED_THIRD_SESSION_KEY_SHARE_LENGTH 24
+#endif
+
+#define FIRST_SYMMETRIC_KEY "first"
+#define SECOND_SYMMETRIC_KEY "second"
+#define THIRD_SYMMETRIC_KEY "third"
+#define MASTER_KEY "master"
+#define RESIDENT_KEY "resident"
+#define SESSION_KEY "session"
+#define SYMMETRIC_KEY "symmetric"
+#define TRANSPORT_KEY "transport"
+#define UNWRAPPED_KEY "unwrapped"
+#define WRAPPED_KEY "wrapped"
+
+#define CONTINUATION_MESSAGE "Press enter to continue " \
+ "(or ^C to break): "
+
+#define PROCEED_MESSAGE "Type the word \"proceed\" " \
+ "and press enter to continue " \
+ "(or ^C to break): "
+
+
+/**************************************/
+/** external function declarations **/
+/**************************************/
+
+#if defined(__sun) && !defined(SVR4)
+extern int fclose( FILE* );
+extern int fprintf( FILE *, char *, ... );
+extern int isatty( int );
+extern char *sys_errlist[];
+#define strerror( errno ) sys_errlist[errno]
+#endif
+
+
+/***************************/
+/** function prototypes **/
+/***************************/
+
+/************/
+/* delete.c */
+/************/
+
+SECStatus
+TKS_DeleteKeys( char *progName,
+ PK11SlotInfo *slot,
+ char *keyname,
+ secuPWData *pwdata );
+
+
+/**********/
+/* file.c */
+/**********/
+
+SECStatus
+TKS_ReadInputFileIntoSECItem( char *input,
+ char *hexInternalKeyKCV,
+ int hexInternalKeyKCVLength,
+ char *keyname,
+ SECItem *wrappedKey );
+
+SECStatus
+TKS_WriteSECItemIntoOutputFile( SECItem *wrappedKey,
+ char *keyname,
+ char *hexInternalKeyKCV,
+ int hexInternalKeyKCVLength,
+ char *output );
+
+
+/**********/
+/* find.c */
+/**********/
+
+SECStatus
+TKS_FindSymKey( PK11SlotInfo *slot,
+ char *keyname,
+ void *pwdata );
+
+
+/**********/
+/* help.c */
+/**********/
+
+void
+TKS_Usage( char *progName );
+
+void
+TKS_PrintHelp( char *progName );
+
+
+/*********/
+/* key.c */
+/*********/
+
+SECStatus
+TKS_ComputeAndDisplayKCV( PRUint8 *newKey,
+ PRIntn newKeyLen,
+ PRUint8 *KCV,
+ PRIntn KCVLen,
+ PK11SymKey *symKey,
+ char *keyName,
+ char *keyType,
+ PRBool displayKCV,
+ PRUint8 *expectedHexKCV );
+
+SECStatus
+TKS_GenerateSessionKeyShare( char *sessionKeyShareName,
+ SECItem *sessionKeyShare );
+
+SECStatus
+TKS_InputSessionKeyShare( char *sessionKeyShareName,
+ SECItem *sessionKeyShare );
+
+PK11SymKey *
+TKS_ImportSymmetricKey( char *symmetricKeyName,
+ PK11SlotInfo *slot,
+ CK_MECHANISM_TYPE mechanism,
+ CK_ATTRIBUTE_TYPE operation,
+ SECItem *sessionKeyShare,
+ secuPWData *pwdata );
+
+PK11SymKey *
+TKS_DeriveSymmetricKey( char *symmetricKeyName,
+ PK11SymKey *symKey,
+ CK_MECHANISM_TYPE derive,
+ SECItem *sessionKeyShare,
+ CK_MECHANISM_TYPE target,
+ CK_ATTRIBUTE_TYPE operation,
+ int keysize );
+
+SECStatus
+TKS_StoreSymmetricKeyAndNameIt( char *symmetricKeyName,
+ char *keyname,
+ PK11SlotInfo *slot,
+ CK_ATTRIBUTE_TYPE operation,
+ CK_FLAGS flags,
+ PK11SymKey *symKey );
+
+
+/**********/
+/* list.c */
+/**********/
+
+SECStatus
+TKS_ListKeys( char *progName,
+ PK11SlotInfo *slot,
+ char *keyname,
+ int index,
+ PRBool dopriv,
+ secuPWData *pwdata );
+
+
+/*************/
+/* modules.c */
+/*************/
+
+SECStatus
+TKS_ListSecModules( void );
+
+
+/************/
+/* random.c */
+/************/
+
+void
+TKS_FileForRNG( char *noise );
+
+SECStatus
+TKS_SeedRNG( char *noise );
+
+
+/**************/
+/* retrieve.c */
+/**************/
+
+PK11SymKey *
+TKS_RetrieveSymKey( PK11SlotInfo *slot,
+ char *keyname,
+ void *pwdata );
+
+
+/**********/
+/* util.c */
+/**********/
+
+PR_IMPLEMENT( void )
+TKS_ClearScreen();
+
+PR_IMPLEMENT( void )
+TKS_WaitForUser();
+
+PR_IMPLEMENT( void )
+TKS_TypeProceedToContinue();
+
+PR_IMPLEMENT( void )
+TKS_AdjustOddParity( PRUint8 *key );
+
+PR_IMPLEMENT( void )
+TKS_StringToHex( PRUint8 *key,
+ PRIntn len,
+ PRUint8 *hex_key,
+ PRIntn hex_len );
+
+PR_IMPLEMENT( PRBool )
+TKS_ConvertStringOfHexCharactersIntoBitStream( char* input,
+ PRIntn input_bytes,
+ PRUint8* output );
+
+
+/*************/
+/* version.c */
+/*************/
+
+void
+TKS_Version( char *progName );
+
diff --git a/pki/base/native-tools/src/tkstool/util.c b/pki/base/native-tools/src/tkstool/util.c
new file mode 100644
index 000000000..5fda75f8e
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/util.c
@@ -0,0 +1,640 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+static PRBool
+IsValidHexCharacter( char byte )
+{
+ switch( byte )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'C':
+ case 'd':
+ case 'D':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ {
+ /* Character may be converted into a hexadecimal number. */
+ return PR_TRUE;
+ }
+ default:
+ {
+ return PR_FALSE;
+ }
+ }
+}
+
+
+static void
+InsertUpperFourBits( char* byte, char bits )
+{
+ switch( bits )
+ {
+ case '0':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case '1':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case '2':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case '3':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case '4':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case '5':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case '6':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case '7':
+ {
+ *byte &= ~( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case '8':
+ {
+ *byte |= ( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case '9':
+ {
+ *byte |= ( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ *byte |= ( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case 'b':
+ case 'B':
+ {
+ *byte |= ( 1 << 7 );
+ *byte &= ~( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case 'c':
+ case 'C':
+ {
+ *byte |= ( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case 'd':
+ case 'D':
+ {
+ *byte |= ( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte &= ~( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ case 'e':
+ case 'E':
+ {
+ *byte |= ( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte &= ~( 1 << 4 );
+ break;
+ }
+ case 'f':
+ case 'F':
+ {
+ *byte |= ( 1 << 7 );
+ *byte |= ( 1 << 6 );
+ *byte |= ( 1 << 5 );
+ *byte |= ( 1 << 4 );
+ break;
+ }
+ }
+}
+
+
+static void
+InsertLowerFourBits( char* byte, char bits )
+{
+ switch( bits )
+ {
+ case '0':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case '1':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case '2':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case '3':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case '4':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case '5':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case '6':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case '7':
+ {
+ *byte &= ~( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case '8':
+ {
+ *byte |= ( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case '9':
+ {
+ *byte |= ( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ *byte |= ( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case 'b':
+ case 'B':
+ {
+ *byte |= ( 1 << 3 );
+ *byte &= ~( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case 'c':
+ case 'C':
+ {
+ *byte |= ( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case 'd':
+ case 'D':
+ {
+ *byte |= ( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte &= ~( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ case 'e':
+ case 'E':
+ {
+ *byte |= ( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte &= ~( 1 << 0 );
+ break;
+ }
+ case 'f':
+ case 'F':
+ {
+ *byte |= ( 1 << 3 );
+ *byte |= ( 1 << 2 );
+ *byte |= ( 1 << 1 );
+ *byte |= ( 1 << 0 );
+ break;
+ }
+ }
+}
+
+
+PR_IMPLEMENT( void )
+TKS_ClearScreen()
+{
+#if defined(XP_UNIX) && !defined(VMS)
+ system( "tput clear" );
+#else
+ system( "cls" );
+#endif
+}
+
+
+PR_IMPLEMENT( void )
+TKS_WaitForUser()
+{
+ int c;
+
+ PR_fprintf( PR_STDOUT, "\n\n" );
+ PR_fprintf( PR_STDOUT, "%s", CONTINUATION_MESSAGE );
+#if defined(VMS)
+ while((c = GENERIC_GETCHAR_NO_ECHO()) != '\r' && c != EOF && c != CTRL_C )
+ ;
+#else
+ while ((c = getc(stdin)) != '\n' && c != EOF && c != CTRL_C )
+ ;
+#endif
+ PR_fprintf( PR_STDOUT, "\n" );
+}
+
+
+PR_IMPLEMENT( void )
+TKS_TypeProceedToContinue()
+{
+ int fd;
+ int i;
+ int count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+ char keystrokes[KEYSTROKES_TO_PROCEED + 1] = "\0\0\0\0\0\0\0\0\0";
+
+ /* display the continuation message */
+ PR_fprintf( PR_STDOUT, "\n\n" );
+ PR_fprintf( PR_STDOUT, "%s", PROCEED_MESSAGE );
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno( stdin );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ tcgetattr( fd, &tio );
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ /* Get user input from keyboard strokes */
+ count = 0;
+ while( count < KEYSTROKES_TO_PROCEED ) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc( stdin );
+#else
+ c = getch();
+#endif
+ /* break on EOF */
+ if( c == EOF ) {
+ rv = -1;
+ break;
+ }
+
+ /* break on ^C */
+ if( c == CTRL_C ) {
+ rv = -1;
+ break;
+ }
+
+ /* save acceptable characters; silently throw anything else away */
+ switch( count ) {
+ case 0:
+ switch( c ) {
+ case 'P':
+ case 'p':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'p';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 1:
+ switch( c ) {
+ case 'R':
+ case 'r':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'r';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 2:
+ switch( c ) {
+ case 'O':
+ case 'o':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'o';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 3:
+ switch( c ) {
+ case 'C':
+ case 'c':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'c';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 4:
+ switch( c ) {
+ case 'E':
+ case 'e':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'e';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 5:
+ switch( c ) {
+ case 'E':
+ case 'e':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'e';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 6:
+ switch( c ) {
+ case 'D':
+ case 'd':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = 'd';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ case 7:
+ switch( c ) {
+ case '\n':
+ case '\r':
+ /* acceptable character; save lowercase version */
+ keystrokes[count] = '\n';
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+ break;
+ default:
+ /* unacceptable character; don't save it */
+ continue;
+ }
+
+ /* adjust the character count appropriately */
+ count++;
+
+ /* redisplay the message */
+ PR_fprintf( PR_STDOUT, "\r%s", PROCEED_MESSAGE );
+
+ /* display the characters input so far */
+ for( i = 0 ; i < count ; i++ ) {
+ PR_fprintf( PR_STDOUT,
+ "%c",
+ keystrokes[i] );
+ }
+ }
+}
+
+
+PR_IMPLEMENT( void )
+TKS_AdjustOddParity( PRUint8 *key )
+{
+ PRIntn i;
+ PRIntn j;
+ PRIntn one;
+
+ /* this must be performed for each DES-sized (8-byte) chunk */
+ for( j = 0 ; j < DES_LENGTH ; j++ ) {
+ for( one = 0, i = key[j] ; i ; i >>= 1 ) {
+ if( i & 1 ) {
+ one++;
+ }
+ }
+
+ key[j] ^= !( one & 1 );
+ }
+}
+
+
+PR_IMPLEMENT( void )
+TKS_StringToHex( PRUint8 *key,
+ PRIntn len,
+ PRUint8 *hex_key,
+ PRIntn hex_len )
+{
+ PRIntn i;
+
+ for( i = 0 ; i < len ; i++ ) {
+ ( void ) PR_snprintf( ( char * ) &( hex_key[ ( 2 * i ) ] ),
+ hex_len,
+ "%X",
+ ( key[i] >> 4 ) & 0x0F );
+ ( void ) PR_snprintf( ( char * ) &( hex_key[ ( 2 * i ) + 1 ] ),
+ hex_len,
+ "%X",
+ key[i] & 0x0F );
+ }
+
+ hex_key[ ( hex_len - 1 ) ] = '\0';
+
+ return;
+}
+
+
+/* Convert a signed character string such as "de43a58f. . ." into an */
+/* unsigned character string which is one/half the size of the input */
+PR_IMPLEMENT( PRBool )
+TKS_ConvertStringOfHexCharactersIntoBitStream( char* input,
+ PRIntn input_bytes,
+ PRUint8* output )
+{
+ PRIntn i;
+ PRIntn output_bytes;
+
+ /* Check to be sure that the input string contains an */
+ /* "even" number of bytes so that it may be converted. */
+ if( input_bytes % 2 ) {
+ ( void ) PR_fprintf( PR_STDERR,
+ "ERROR: "
+ "ConvertStringOfHexCharactersIntoBitStream() "
+ "contained an illegal "
+ "input byte length of %d bytes!\r\n",
+ input_bytes );
+ return PR_FALSE;
+ }
+
+ output_bytes = ( input_bytes / 2 );
+
+ for( i = 0; i < output_bytes; i++ ) {
+ if( IsValidHexCharacter( input[ ( 2 * i ) ] ) &&
+ IsValidHexCharacter( input[ ( 2 * i ) + 1 ] ) ) {
+ InsertUpperFourBits( ( char* ) &( output[i] ), input[ ( 2 * i ) ] );
+ InsertLowerFourBits( ( char* ) &( output[i] ), input[ ( 2 * i ) + 1 ] );
+ } else {
+ ( void ) PR_fprintf( PR_STDERR,
+ "ERROR: "
+ "ConvertStringOfHexCharactersIntoBitStream() "
+ "contained a "
+ "byte in the input string which can not be "
+ "converted!\r\n" );
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+
diff --git a/pki/base/native-tools/src/tkstool/version.c b/pki/base/native-tools/src/tkstool/version.c
new file mode 100644
index 000000000..b8d4c5fbb
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/version.c
@@ -0,0 +1,49 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+void
+TKS_Version( char *progName )
+{
+#if defined(TKSTOOL_VERSION_SUFFIX)
+ if( TKSTOOL_VERSION_SUFFIX != NULL &&
+ PL_strcmp( TKSTOOL_VERSION_SUFFIX, "" ) != 0 ) {
+ PR_fprintf( PR_STDOUT,
+ "%s: Version %d.%d %s\n",
+ progName,
+ TKSTOOL_MAJOR_VERSION_NUMBER,
+ TKSTOOL_MINOR_VERSION_NUMBER,
+ TKSTOOL_VERSION_SUFFIX );
+ } else {
+ PR_fprintf( PR_STDOUT,
+ "%s: Version %d.%d\n",
+ progName,
+ TKSTOOL_MAJOR_VERSION_NUMBER,
+ TKSTOOL_MINOR_VERSION_NUMBER );
+ }
+#else
+ PR_fprintf( PR_STDOUT,
+ "%s: Version %d.%d\n",
+ progName,
+ TKSTOOL_MAJOR_VERSION_NUMBER,
+ TKSTOOL_MINOR_VERSION_NUMBER );
+#endif
+}
+