summaryrefslogtreecommitdiffstats
path: root/base/native-tools
diff options
context:
space:
mode:
authorEndi Sukma Dewata <edewata@redhat.com>2012-03-24 02:27:47 -0500
committerEndi Sukma Dewata <edewata@redhat.com>2012-03-26 11:43:54 -0500
commit621d9e5c413e561293d7484b93882d985b3fe15f (patch)
tree638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/native-tools
parent40d3643b8d91886bf210aa27f711731c81a11e49 (diff)
downloadpki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131
Diffstat (limited to 'base/native-tools')
-rw-r--r--base/native-tools/CMakeLists.txt3
-rw-r--r--base/native-tools/LICENSE291
-rw-r--r--base/native-tools/doc/README55
-rw-r--r--base/native-tools/src/CMakeLists.txt5
-rw-r--r--base/native-tools/src/bulkissuance/CMakeLists.txt37
-rw-r--r--base/native-tools/src/bulkissuance/bulkissuance.c807
-rw-r--r--base/native-tools/src/bulkissuance/bulkissuance.data1
-rw-r--r--base/native-tools/src/bulkissuance/getopt.c126
-rw-r--r--base/native-tools/src/p7tool/CMakeLists.txt33
-rw-r--r--base/native-tools/src/p7tool/NSPRerrs.h161
-rw-r--r--base/native-tools/src/p7tool/SECerrs.h523
-rw-r--r--base/native-tools/src/p7tool/SSLerrs.h393
-rw-r--r--base/native-tools/src/p7tool/p7tool.c375
-rw-r--r--base/native-tools/src/p7tool/pppolicy.c309
-rw-r--r--base/native-tools/src/p7tool/secerror.c119
-rw-r--r--base/native-tools/src/p7tool/secerror.h44
-rw-r--r--base/native-tools/src/p7tool/secpwd.c213
-rw-r--r--base/native-tools/src/p7tool/secutil.c3665
-rw-r--r--base/native-tools/src/p7tool/secutil.h430
-rw-r--r--base/native-tools/src/revoker/CMakeLists.txt30
-rw-r--r--base/native-tools/src/revoker/getopt.c126
-rw-r--r--base/native-tools/src/revoker/revoker.c882
-rw-r--r--base/native-tools/src/setpin/CMakeLists.txt43
-rw-r--r--base/native-tools/src/setpin/b64.c102
-rw-r--r--base/native-tools/src/setpin/options.c184
-rw-r--r--base/native-tools/src/setpin/options.h83
-rw-r--r--base/native-tools/src/setpin/setpin.c1237
-rw-r--r--base/native-tools/src/setpin/setpin.conf83
-rw-r--r--base/native-tools/src/setpin/setpin_options.c290
-rw-r--r--base/native-tools/src/setpin/setpin_options.h56
-rw-r--r--base/native-tools/src/sslget/CMakeLists.txt30
-rw-r--r--base/native-tools/src/sslget/getopt.c126
-rw-r--r--base/native-tools/src/sslget/sslget.c836
-rw-r--r--base/native-tools/src/tkstool/CMakeLists.txt45
-rw-r--r--base/native-tools/src/tkstool/NSPRerrs.h161
-rw-r--r--base/native-tools/src/tkstool/SECerrs.h523
-rw-r--r--base/native-tools/src/tkstool/SSLerrs.h393
-rw-r--r--base/native-tools/src/tkstool/delete.c111
-rw-r--r--base/native-tools/src/tkstool/file.c518
-rw-r--r--base/native-tools/src/tkstool/find.c81
-rw-r--r--base/native-tools/src/tkstool/help.c499
-rw-r--r--base/native-tools/src/tkstool/key.c1350
-rw-r--r--base/native-tools/src/tkstool/list.c181
-rw-r--r--base/native-tools/src/tkstool/modules.c63
-rw-r--r--base/native-tools/src/tkstool/pppolicy.c306
-rw-r--r--base/native-tools/src/tkstool/random.c173
-rw-r--r--base/native-tools/src/tkstool/retrieve.c114
-rw-r--r--base/native-tools/src/tkstool/secerror.c118
-rw-r--r--base/native-tools/src/tkstool/secpwd.c213
-rw-r--r--base/native-tools/src/tkstool/secutil.c3662
-rw-r--r--base/native-tools/src/tkstool/secutil.h430
-rw-r--r--base/native-tools/src/tkstool/tkstool.c2660
-rw-r--r--base/native-tools/src/tkstool/tkstool.h321
-rw-r--r--base/native-tools/src/tkstool/util.c640
-rw-r--r--base/native-tools/src/tkstool/version.c49
55 files changed, 24309 insertions, 0 deletions
diff --git a/base/native-tools/CMakeLists.txt b/base/native-tools/CMakeLists.txt
new file mode 100644
index 000000000..0ccebe578
--- /dev/null
+++ b/base/native-tools/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(native-tools)
+
+add_subdirectory(src)
diff --git a/base/native-tools/LICENSE b/base/native-tools/LICENSE
new file mode 100644
index 000000000..e281f4362
--- /dev/null
+++ b/base/native-tools/LICENSE
@@ -0,0 +1,291 @@
+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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/base/native-tools/doc/README b/base/native-tools/doc/README
new file mode 100644
index 000000000..01b11a7a3
--- /dev/null
+++ b/base/native-tools/doc/README
@@ -0,0 +1,55 @@
+# --- 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 ---
+#
+ Certificate System
+ Native Command Line Utilities
+
+
+Command Line Utility Purpose
+==============================================================================
+bulkissuance A command line utility utilized
+ to send either a KEYGEN or CRMF
+ enrollment request to the bulk
+ issuance interface for the
+ automatic creation of
+ certificates.
+
+bulkissuance.data An example data file for use
+ with the bulkissuance tool.
+
+revoker A command line tool which may be
+ conveniently utilized to
+ automate user management scripts
+ used to revoke certificates.
+
+setpin A command line tool utilized
+ to enable Certificate
+ System to utilize PIN-based
+ authentication.
+
+setpin.conf The configuration file utilized
+ by the setpin command line
+ utility.
+
+tkstool A command line tool utilized
+ to construct DES 2 symmetric
+ keys utilized in conjunction
+ with the Certificate
+ System Token Key Service
+ subsystem.
+
diff --git a/base/native-tools/src/CMakeLists.txt b/base/native-tools/src/CMakeLists.txt
new file mode 100644
index 000000000..c727a9a49
--- /dev/null
+++ b/base/native-tools/src/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_subdirectory(p7tool)
+add_subdirectory(revoker)
+add_subdirectory(setpin)
+add_subdirectory(sslget)
+add_subdirectory(tkstool)
diff --git a/base/native-tools/src/bulkissuance/CMakeLists.txt b/base/native-tools/src/bulkissuance/CMakeLists.txt
new file mode 100644
index 000000000..31df27306
--- /dev/null
+++ b/base/native-tools/src/bulkissuance/CMakeLists.txt
@@ -0,0 +1,37 @@
+project(bulkissuance C)
+
+set(BULKISSUANCE_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(BULKISSUANCE_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(bulkissuance_SRCS
+ bulkissuance.c
+ getopt.c
+)
+
+include_directories(${BULKISSUANCE_PRIVATE_INCLUDE_DIRS})
+
+add_executable(bulkissuance ${bulkissuance_SRCS})
+
+target_link_libraries(bulkissuance ${BULKISSUANCE_LINK_LIBRARIES})
+
+install(
+ TARGETS bulkissuance
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
+
+install(
+ FILES
+ bulkissuance.data
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/pki/native-tools/
+)
diff --git a/base/native-tools/src/bulkissuance/bulkissuance.c b/base/native-tools/src/bulkissuance/bulkissuance.c
new file mode 100644
index 000000000..ec33e8a7a
--- /dev/null
+++ b/base/native-tools/src/bulkissuance/bulkissuance.c
@@ -0,0 +1,807 @@
+/* --- 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 ---
+ */
+
+/* vi: set ts=4 sw=4 : */
+#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>
+#include <time.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "ssl.h"
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+
+/*from nss2.8.4 secopt.h*/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+
+#ifdef _WIN32
+static void do_opterr(const char *s, int c, char * const av[]);
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int getopt(int ac, char * const av[], const char * opts);
+#else
+#if defined(LINUX)
+#include <getopt.h>
+#endif
+#endif /* XP_PC */
+/*end secopt.h*/
+
+#define VERSIONSTRING "$Revision$ ($Date$)"
+#define MAXLEN 50000
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define RD_BUF_SIZE (60 * 1024)
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+#define FPUTS if (verbose) fputs
+
+#define MAX_SERIAL_LEN 8192
+
+int MakeCertOK=1;
+
+int verbose;
+SECItem bigBuf;
+
+
+static char *ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+static void
+Usage(const char *progName)
+{
+ fprintf( stderr,
+ "\n" );
+ fprintf( stderr,
+ "Description: A command-line utility used to send either a KEYGEN or a\n"
+ " Certificate Request Message Format (CRMF) enrollment\n"
+ " request to the bulk issuance interface of a\n"
+ " Certificate Authority (CA) for the automatic\n"
+ " creation of certificates.\n\n\n" );
+ fprintf( stderr,
+ "Usage:\n\n"
+ " %s -n rsa_nickname [-p password | -w pwfile ]\n"
+ " [-d dbdir] [-v] [-V] [-f inputFile] hostname[:port]\n\n"
+ " where:\n\n"
+ " -n rsa_nickname nickname of the Agent Certificate\n"
+ " [-p password | -w pwfile] password OR file containing password\n"
+ " [-d dbdir] database directory\n"
+ " [-v] verbose mode\n"
+ " [-V] version of %s\n"
+ " [-f inputFile] file containing an http request\n"
+ " which gets sent to the hostname[:port]\n"
+ " hostname[:port] machine name with optional port address\n\n\n",
+ progName, progName );
+ fprintf( stderr,
+ "Example (using the example inputFile called \"bulkissuance.data\"):\n\n" );
+ fprintf( stderr,
+ " (1) cd <server-root>/bin/cert/tools\n" );
+ fprintf( stderr,
+ " (2) cp <client-database>/cert8.db .\n" );
+ fprintf( stderr,
+ " (3) cp <client-database>/key3.db .\n" );
+ fprintf( stderr,
+ " (4) Ensure that the agent certificate is\n"
+ " inside these cert8.db/key3.db databases.\n"
+ " (for this example, call it \"CS Agent\'s CS ID\")\n" );
+ fprintf( stderr,
+ " (5) ./bulkissuance.sh -n \"CS Agent\'s CS ID\" -p password\n"
+ " -d . -f bulkissuance.data example.com:8100\n\n" );
+ exit( 1 );
+}
+
+
+static void
+errWarn(const char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+
+ FPRINTF(stderr, "exit after %s with error %d:\n", funcString,perr );
+}
+
+static void
+errExit(const char * funcString)
+{
+ errWarn(funcString);
+ exit(1);
+}
+
+/* This invokes the "default" AuthCert handler in libssl.
+** The only reason to use this one is that it prints out info as it goes.
+*/
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate * peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("Subject: %s\nIssuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ /* invoke the "default" AuthCert handler. */
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ if (rv == SECSuccess) {
+ FPUTS("-- SSL3: Server Certificate Validated.\n", stderr);
+ }
+ /* error, if any, will be displayed by the Bad Cert Handler. */
+ return rv;
+}
+
+static SECStatus
+myBadCertHandler( void *arg, PRFileDesc *fd)
+{
+ /* int err = PR_GetError(); */
+ /* fprintf(stderr, "-- SSL: Server Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err)); */
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+
+static SECStatus
+my_GetClientAuthData(void * arg,
+ PRFileDesc * sock,
+ struct CERTDistNamesStr * caNames,
+ struct CERTCertificateStr ** pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ CERTCertificate * cert = NULL;
+ SECKEYPrivateKey * privkey = NULL;
+ char * chosenNickName = (char *)arg; /* CONST */
+ void * proto_win = NULL;
+ SECStatus rv = SECFailure;
+
+ FPRINTF(stderr,"Called mygetclientauthdata - nickname = %s\n",chosenNickName);
+
+ proto_win = SSL_RevealPinArg(sock);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - cert = %p\n", cert);
+ if ( cert ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - privkey = %p\n", privkey);
+ if ( privkey ) {
+ rv = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no name given, automatically find the right cert. */
+ CERTCertNicknames * names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+ cert = PK11_FindCertFromNickname(names->nicknames[i],proto_win);
+ if ( !cert )
+ continue;
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
+ secCertTimeValid ) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+ rv = NSS_CmpCertChainWCANames(cert, caNames);
+ if ( rv == SECSuccess ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if ( privkey )
+ break;
+ }
+ rv = SECFailure;
+ CERT_DestroyCertificate(cert);
+ }
+ CERT_FreeNicknames(names);
+ }
+ }
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privkey;
+ }
+ return rv;
+}
+
+
+
+
+static void
+printSecurityInfo(PRFileDesc *fd)
+{
+ char * cp; /* bulk cipher name */
+ char * ip; /* cert issuer DN */
+ char * sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+
+ static int only_once;
+
+ if (! only_once++ && fd) {
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+#if 0
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ "subject DN: %s\n"
+ "issuer DN: %s\n", cp, kp1, kp0, op, sp, ip);
+#else
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n",
+ cp, kp1, kp0, op);
+#endif
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+ }
+
+}
+
+
+PRBool useModelSocket = PR_TRUE;
+
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Netscape-Enterprise/2.0a\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+
+static PRInt32
+do_writes(
+ void * a
+)
+{
+ PRFileDesc * ssl_sock = (PRFileDesc *)a;
+ PRUint32 sent = 0;
+ PRInt32 count = 0;
+
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ exit(4);
+ break;
+ }
+ FPRINTF(stderr, "PR_Write wrote %d bytes from bigBuf\n", count );
+ FPRINTF(stderr, "bytes: [%*s]\n",count,bigBuf.data);
+
+ sent += (PRUint32)count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ FPRINTF(stderr, "do_writes shutting down send socket\n");
+ /* PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); */
+ }
+
+ FPRINTF(stderr, "do_writes exiting with (failure = %d)\n",
+ (sent < bigBuf.len) == SECFailure);
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+
+
+
+static SECStatus
+do_io( PRFileDesc *ssl_sock, int connection)
+{
+ int countRead = 0;
+ PRInt32 rv;
+ char *buf;
+ int first=1;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+ if (!buf) exit(5);
+
+
+ /* send the http request here. */
+
+ rv = do_writes(ssl_sock);
+
+ if (rv == SECFailure) {
+ errWarn("returning from after calling do_writes");
+ PR_Free(buf);
+ buf = 0;
+ exit(6);
+ }
+ printSecurityInfo(ssl_sock);
+
+ /* read until EOF */
+ while (1) {
+ rv = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
+ if (rv == 0) {
+ break; /* EOF */
+ }
+ if (rv < 0) {
+ errWarn("PR_Read");
+ exit(1);
+ }
+
+ countRead += rv;
+ FPRINTF(stderr, "connection %d read %d bytes (%d total).\n",
+ connection, rv, countRead );
+ FPRINTF(stderr, "these bytes read: ");
+ if (verbose) {
+ PR_Write(PR_STDERR,buf,rv);
+ }
+
+ if (first) {
+ first=0;
+ if (rv < 13) {
+ errWarn("not enough bytes read in first read");
+ exit(2);
+ } else {
+ if ( ! PL_strnstr(buf,"200",13)) {
+ exit(3);
+ }
+ }
+ }
+ }
+ PR_Free(buf);
+ buf = 0;
+
+ /* Caller closes the socket. */
+
+ FPRINTF(stderr,
+ "connection %d read %d bytes total. -----------------------------\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+static int
+do_connect(
+ PRNetAddr *addr,
+ PRFileDesc *model_sock,
+ int connection)
+{
+ PRFileDesc * ssl_sock;
+ PRFileDesc * tcp_sock;
+ PRStatus prStatus;
+ SECStatus result;
+ int rv = SECSuccess;
+ PRSocketOptionData opt;
+
+ int family = PR_NetAddrFamily( addr );
+
+ tcp_sock = PR_OpenTCPSocket( family );
+ if (tcp_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ /* Don't return SECFailure? */
+ return SECSuccess;
+ }
+
+ prStatus = PR_Connect(tcp_sock, addr, PR_SecondsToInterval(3));
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(6);
+ }
+
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ /* XXX if this import fails, close tcp_sock and return. */
+ if (!ssl_sock) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(7);
+ }
+
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ exit(8);
+ }
+
+ result = do_io( ssl_sock, connection);
+
+ if( ssl_sock != NULL ) {
+ PR_Close(ssl_sock);
+ ssl_sock = NULL;
+ }
+ return SECSuccess;
+}
+
+#if 0
+/* Returns IP address for hostname as PRUint32 in Host Byte Order.
+** Since the value returned is an integer (not a string of bytes),
+** it is inherently in Host Byte Order.
+*/
+static PRUint32
+getIPAddress(const char * hostName)
+{
+ const unsigned char *p;
+ PRStatus prStatus;
+ PRUint32 rv;
+ PRHostEnt prHostEnt;
+ char scratch[PR_NETDB_BUF_SIZE];
+
+ prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_GetHostByName");
+
+#undef h_addr
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+
+ p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
+ FPRINTF(stderr, "%s -> %d.%d.%d.%d\n", hostName, p[0], p[1], p[2], p[3]);
+ rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return rv;
+}
+#endif
+
+static void
+client_main(
+ unsigned short port,
+ int connections,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert,
+ const char * hostName,
+ char * nickName)
+{
+ PRFileDesc *model_sock = NULL;
+ int rv;
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+ int family = PR_AF_INET;
+
+
+
+ FPRINTF(stderr, "port: %d\n", port);
+
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ /* SSL_CipherPrefSetDefault(0xC005 */
+ /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */
+ /*, PR_TRUE); */
+
+ /*
+ * Rifle through the values for the host
+ */
+
+ ai = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (ai) {
+ FPRINTF( stderr, "addr='%s'\n", PR_GetCanonNameFromAddrInfo( ai ) );
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ family = PR_NetAddrFamily(&addr);
+ FPRINTF( stderr, "family='%d'\n", family );
+ break;
+ }
+ PR_FreeAddrInfo(ai);
+ }
+
+ PR_SetNetAddr( PR_IpAddrNull, family, port, &addr );
+
+ model_sock = PR_OpenTCPSocket( family );
+ if (model_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ /* Should we really be re-using the same socket? */
+ model_sock = SSL_ImportFD(NULL, model_sock);
+
+
+ /* check on success of call to SSL_ImportFD() */
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+
+ /* enable ECC cipher also */
+
+ /* do SSL configuration. */
+
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ if (rv < 0) {
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ SSL_GetClientAuthDataHook(model_sock,
+ (SSLGetClientAuthData)my_GetClientAuthData,
+ nickName);
+
+ /* I'm not going to set the HandshakeCallback function. */
+
+ /* end of ssl configuration. */
+
+ rv = do_connect(&addr, model_sock, 1);
+
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+}
+
+
+static SECStatus
+createRequest(char *progName, char *path)
+{
+ char *temp;
+ char * newstr;
+ FILE *fp;
+
+ temp = (char *)malloc(MAXLEN);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ fputs("Input file must be provided on command line in this version"
+ " of bulk issuance client.\n", stderr);
+ Usage(progName);
+ } else {
+ temp = fgets(temp, MAXLEN, fp);
+ if (temp == NULL) {
+ fclose(fp);
+ fputs("File is empty\n", stderr);
+ exit(1);
+ }
+
+ fclose(fp);
+ }
+
+ newstr = PR_smprintf("%s\r\n\r\n", temp);
+/*
+ "GET /ca/bulkissuance?csrRequestorName=++&CN=a&UID=a&E=a&OU=&O=&C=US&email=true&ssl_client=true&digital_signature=true&non_repudiation=true&key_encipherment=true&challengePassword=&confirmChallengePassword=&csrRequestorEmail=a&csrRequestorPhone=&csrRequestorComments=&CRMFRequest=MIICTDCB%2BzCB8wICJ4EwgbWAAQKlQDA%2BMQswCQYDVQQGEwJVUzERMA8GCgmSJomT%0D%0A8ixkAQETAWExCjAIBgNVBAMTAWExEDAOBgkqhkiG9w0BCQEWAWGmXDANBgkqhkiG%0D%0A9w0BAQEFAANLADBIAkEA3R3vkvw3%2F4f5eDJZszB2%2B8BhWtNgwX97KV%2FydZ1kPlei%0D%0AcJwIcHfLbp6tRYs2iKAxbTuw01H1P9gdUIx1nY7R0QIDAQABqRAwDgYDVR0PAQH%2F%0D%0ABAQDAgUgMDUwGwYJKwYBBQUHBQECDA5hdXRoZW50aWNhdG9yADAWBgkrBgEFBQcF%0D%0AAQEMCXJlZ1Rva2VuAKIDgQEBMIIBSjCB8wICRGswgbWAAQKlQDA%2BMQswCQYDVQQG%0D%0AEwJVUzERMA8GCgmSJomT8ixkAQETAWExCjAIBgNVBAMTAWExEDAOBgkqhkiG9w0B%0D%0ACQEWAWGmXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuf9KVCouLB6rKI290XpSghLe%0D%0APtYxSBdGv5gnzYVyokz9DPSSTeRBCUQDGWCVMIgMrUMABK0tkXPlVrD8lylVWQID%0D%0AAQABqRAwDgYDVR0PAQH%2FBAQDAgeAMDUwGwYJKwYBBQUHBQECDA5hdXRoZW50aWNh%0D%0AdG9yADAWBgkrBgEFBQcFAQEMCXJlZ1Rva2VuAKFSMA0GCSqGSIb3DQEBBQUAA0EA%0D%0Aq0tNDOzqcDI%2BwQ6gZMsCbYLh7MBBAzJo8Z67ddx%2BOS%2FZjCAtAbdabeazQnu0UOfN%0D%0A0HwLPDcNuurcvw4y604ang%3D%3D&cmmfResponse=true&certNickname=E%3Da%2C+CN%3Da%2C+UID%3Da%2C+C%3DUS&subject=E%3Da%2C+CN%3Da%2C+UID%3Da%2C+C%3DUS&requestFormat=keygen&certType=client HTTP/1.0\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "\r\n");
+*/
+
+ bigBuf.data = (unsigned char *)newstr;
+
+ FPUTS((char *)bigBuf.data, stderr);
+
+ bigBuf.len = PORT_Strlen((char *)bigBuf.data);
+
+ free(temp);
+
+ return SECSuccess;
+}
+
+int
+main(int argc, char **argv)
+{
+ const char * dir = ".";
+ char * hostName = NULL;
+ char * nickName = NULL;
+ char * progName = NULL;
+ char * tmp = NULL;
+ CERTCertificate * cert [kt_kea_size] = { NULL };
+ SECKEYPrivateKey * privKey[kt_kea_size] = { NULL };
+ int optchar;
+ int connections = 1;
+ int tmpI;
+ unsigned short port = 443;
+ SECStatus rv;
+ char * passwd = NULL;
+ char * passwdfile = NULL;
+ char path[1000];
+ FILE *fp;
+ char pwbuf[256];
+ int co;
+ char *crlf;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+
+ while ((optchar = getopt(argc, argv, "Vd:n:p:f:v")) != -1) {
+ switch(optchar) {
+
+ case 'V':
+ PRINTF("%s\n",VERSIONSTRING);
+ break;
+
+ case 'd':
+ dir = optarg;
+ break;
+
+ case 'n':
+ nickName = optarg;
+ break;
+
+ case 'p':
+ passwd = optarg;
+ break;
+
+ case 'w':
+ passwdfile = optarg;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'f':
+ strcpy(path, optarg);
+ break;
+
+ default:
+ case '?':
+ Usage(progName);
+ break;
+
+ }
+ }
+ if (optind != argc - 1)
+ Usage(progName);
+
+ hostName = argv[optind];
+ tmp = strchr(hostName, ':');
+ if (tmp) {
+ *tmp++ = 0;
+ tmpI = atoi(tmp);
+ if (tmpI <= 0)
+ Usage(progName);
+ port = (unsigned short)tmpI;
+ }
+
+ if (!nickName)
+ Usage(progName);
+
+ createRequest(progName, path);
+
+ if (passwdfile) {
+ fp = fopen(passwdfile,"r");
+ if (!fp) { fprintf(stderr, "Couldn't open password file\n"); exit(7); }
+ co = fread(pwbuf,1,256,fp);
+ pwbuf[co] = '\0';
+ crlf = PL_strchr(pwbuf,'\n');
+ if (crlf) {
+ *crlf = '\0';
+ }
+ passwd = pwbuf;
+ }
+
+ /* set our password function */
+ if (passwd == NULL) {
+ PRINTF("Password must be provided on command line in this version of revoker.\n");
+ Usage(progName);
+ }
+ PK11_SetPasswordFunc(ownPasswd);
+
+ /* Call the libsec initialization routines */
+ rv = NSS_Init(dir);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(1);
+ }
+
+ cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
+ if (cert[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find certificate %s\n", nickName);
+ exit(1);
+ }
+
+ privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
+ if (privKey[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find Private Key for cert %s (possibly incorrect password)\n", nickName);
+ exit(1);
+ }
+
+
+ client_main(port, connections, privKey, cert, hostName, nickName);
+
+ NSS_Shutdown();
+ PR_Cleanup();
+ return 0;
+}
+
diff --git a/base/native-tools/src/bulkissuance/bulkissuance.data b/base/native-tools/src/bulkissuance/bulkissuance.data
new file mode 100644
index 000000000..1d68c26a1
--- /dev/null
+++ b/base/native-tools/src/bulkissuance/bulkissuance.data
@@ -0,0 +1 @@
+GET /ca/agent/ca/bulkissuance?csrRequestorName=++&CN=a&UID=a&E=a&OU=&O=&C=US&email=true&ssl_client=true&digital_signature=true&non_repudiation=true&key_encipherment=true&challengePassword=&confirmChallengePassword=&csrRequestorEmail=a&csrRequestorPhone=&csrRequestorComments=&CRMFRequest=MIICTDCB%2BzCB8wICJ4EwgbWAAQKlQDA%2BMQswCQYDVQQGEwJVUzERMA8GCgmSJomT%0D%0A8ixkAQETAWExCjAIBgNVBAMTAWExEDAOBgkqhkiG9w0BCQEWAWGmXDANBgkqhkiG%0D%0A9w0BAQEFAANLADBIAkEA3R3vkvw3%2F4f5eDJZszB2%2B8BhWtNgwX97KV%2FydZ1kPlei%0D%0AcJwIcHfLbp6tRYs2iKAxbTuw01H1P9gdUIx1nY7R0QIDAQABqRAwDgYDVR0PAQH%2F%0D%0ABAQDAgUgMDUwGwYJKwYBBQUHBQECDA5hdXRoZW50aWNhdG9yADAWBgkrBgEFBQcF%0D%0AAQEMCXJlZ1Rva2VuAKIDgQEBMIIBSjCB8wICRGswgbWAAQKlQDA%2BMQswCQYDVQQG%0D%0AEwJVUzERMA8GCgmSJomT8ixkAQETAWExCjAIBgNVBAMTAWExEDAOBgkqhkiG9w0B%0D%0ACQEWAWGmXDANBgkqhkiG9w0BAQEFAANLADBIAkEAuf9KVCouLB6rKI290XpSghLe%0D%0APtYxSBdGv5gnzYVyokz9DPSSTeRBCUQDGWCVMIgMrUMABK0tkXPlVrD8lylVWQID%0D%0AAQABqRAwDgYDVR0PAQH%2FBAQDAgeAMDUwGwYJKwYBBQUHBQECDA5hdXRoZW50aWNh%0D%0AdG9yADAWBgkrBgEFBQcFAQEMCXJlZ1Rva2VuAKFSMA0GCSqGSIb3DQEBBQUAA0EA%0D%0Aq0tNDOzqcDI%2BwQ6gZMsCbYLh7MBBAzJo8Z67ddx%2BOS%2FZjCAtAbdabeazQnu0UOfN%0D%0A0HwLPDcNuurcvw4y604ang%3D%3D&cmmfResponse=true&certNickname=E%3Da%2C+CN%3Da%2C+UID%3Da%2C+C%3DUS&subject=E%3Da%2C+CN%3Da%2C+UID%3Da%2C+C%3DUS&requestFormat=CRMF&certType=client HTTP/1.0
diff --git a/base/native-tools/src/bulkissuance/getopt.c b/base/native-tools/src/bulkissuance/getopt.c
new file mode 100644
index 000000000..7554e1a14
--- /dev/null
+++ b/base/native-tools/src/bulkissuance/getopt.c
@@ -0,0 +1,126 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * END COPYRIGHT BLOCK **/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+#include <stdio.h>
+#include <string.h> /* for str*() */
+#include <io.h> /* for write() */
+
+int opterr = 1; /* boolean flag, says "report error on stderr." */
+int optind = 1; /* index to element of argv from which options are
+ ** being parsed. */
+int optopt = 0; /* option character */
+char *optarg; /* ptr to option's parameter arg. */
+
+#ifdef _WIN32
+static void
+do_opterr(const char *s, int c, char * const av[])
+{
+ if (opterr) {
+ char buff[2];
+ int fd = _fileno(stderr);
+
+ buff[0] = (char)c;
+ buff[1] = '\n';
+ (void)write(fd, av[0], strlen(av[0]));
+ (void)write(fd, s, strlen(s));
+ (void)write(fd, buff, 2);
+ }
+}
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int
+getopt(int ac, char * const av[], const char * opts)
+{
+ static int i = 1; /* offset of current option char in current arg. */
+ char *p; /* opt char in opts that matched. */
+
+ /* Move to next value from argv? */
+ if (i == 1) {
+ if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
+ return EOF;
+ if (strcmp(av[optind], "--") == 0) {
+ optind++;
+ return EOF;
+ }
+ }
+
+ /* Get next option character. */
+ if ((optopt = av[optind][i]) == ':' ||
+ (p = strchr(opts, optopt)) == NULL) {
+ ERR(": illegal option -- ", optopt);
+ if (av[optind][++i] == '\0') {
+ optind++;
+ i = 1;
+ }
+ return '?';
+ }
+
+ /* Snarf argument? */
+ if (*++p == ':') {
+ if (av[optind][i + 1] != '\0')
+ optarg = &av[optind++][i + 1];
+ else {
+ if (++optind >= ac) {
+ ERR(": option requires an argument -- ", optopt);
+ i = 1;
+ return '?';
+ }
+ optarg = av[optind++];
+ }
+ i = 1;
+ } else {
+ if (av[optind][++i] == '\0') {
+ i = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+
+ return optopt;
+}
+
+#endif /* XP_PC */
diff --git a/base/native-tools/src/p7tool/CMakeLists.txt b/base/native-tools/src/p7tool/CMakeLists.txt
new file mode 100644
index 000000000..6adfbedb7
--- /dev/null
+++ b/base/native-tools/src/p7tool/CMakeLists.txt
@@ -0,0 +1,33 @@
+project(p7tool C)
+
+set(P7TOOL_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(P7TOOL_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(p7tool_SRCS
+ secerror.c
+ secpwd.c
+ secutil.c
+ pppolicy.c
+ p7tool.c
+)
+
+include_directories(${P7TOOL_PRIVATE_INCLUDE_DIRS})
+
+add_executable(p7tool ${p7tool_SRCS})
+
+target_link_libraries(p7tool ${P7TOOL_LINK_LIBRARIES})
+
+install(
+ TARGETS p7tool
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/base/native-tools/src/p7tool/NSPRerrs.h b/base/native-tools/src/p7tool/NSPRerrs.h
new file mode 100644
index 000000000..f0bc8b77e
--- /dev/null
+++ b/base/native-tools/src/p7tool/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/base/native-tools/src/p7tool/SECerrs.h b/base/native-tools/src/p7tool/SECerrs.h
new file mode 100644
index 000000000..55858b98f
--- /dev/null
+++ b/base/native-tools/src/p7tool/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/base/native-tools/src/p7tool/SSLerrs.h b/base/native-tools/src/p7tool/SSLerrs.h
new file mode 100644
index 000000000..d6ec13b47
--- /dev/null
+++ b/base/native-tools/src/p7tool/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/base/native-tools/src/p7tool/p7tool.c b/base/native-tools/src/p7tool/p7tool.c
new file mode 100644
index 000000000..9ab6023ff
--- /dev/null
+++ b/base/native-tools/src/p7tool/p7tool.c
@@ -0,0 +1,375 @@
+/** 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.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+/* This file is based upon the file originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N
+ * mozilla/security/nss/cmd/p7content/p7content.c
+ */
+
+/*
+ * p7tool -- A command to display/process pkcs7 content.
+ *
+ */
+
+#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 "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-d dbdir] [-p chainFilePrefix] [-a] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr,
+ "%-20s Key/Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define the cert chain file name prefix(default is chaincert)\n",
+ "-p chainFilePrefix");
+ fprintf(stderr, "%-20s Input is in ascii encoded form (RFC1113)\n",
+ "-a");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static PRBool saw_content;
+
+static void
+PrintBytes(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = arg;
+ fwrite (buf, len, 1, out);
+
+ saw_content = PR_TRUE;
+}
+
+/*
+ * XXX Someday we may want to do real policy stuff here. This allows
+ * anything to be decrypted, which is okay for a test program but does
+ * not set an example of how a real client with a real policy would
+ * need to do it.
+ */
+static PRBool
+decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key)
+{
+ return PR_TRUE;
+}
+
+int
+DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName, int ascii,
+ char *prefix)
+{
+ SECItem derdata;
+ SEC_PKCS7ContentInfo *cinfo = NULL;
+ SEC_PKCS7DecoderContext *dcx;
+ int rv;
+
+ if (SECU_ReadDERFromFile(&derdata, in, ascii)) {
+ SECU_PrintError(progName, "error converting der");
+ return -1;
+ }
+
+ fprintf(out, "Pretty Print of PKCS#7 content:\n");
+ rv = SECU_PrintPKCS7ContentInfo(out, &derdata,
+ "PKCS #7 Content Info", 0);
+/*
+ fprintf(out,
+ "Content printed between bars (newline added before second bar):");
+ fprintf(out, "\n---------------------------------------------\n");
+*/
+ if (rv) {
+ fprintf(stderr, "%s: problem converting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ return -1;
+ }
+
+ saw_content = PR_FALSE;
+ dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, NULL,
+ NULL, NULL, decryption_allowed);
+ if (dcx != NULL) {
+#if 0 /* Test that decoder works when data is really streaming in. */
+ {
+ unsigned long i;
+ for (i = 0; i < derdata.len; i++)
+ SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1);
+ }
+#else
+ SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len);
+#endif
+ cinfo = SEC_PKCS7DecoderFinish(dcx);
+ }
+/*
+ fprintf(out, "\n---------------------------------------------\n");
+*/
+ if (cinfo == NULL)
+ return -1;
+/*
+ fprintf(out, "Content was%s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
+*/
+
+ if (SEC_PKCS7ContentIsSigned(cinfo)) {
+ char *signer_cname, *signer_ename;
+ SECItem *signing_time;
+
+ if (saw_content) {
+ fprintf(out, "Signature is ");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE))
+ fprintf(out, "valid.\n");
+ else
+ fprintf(out, "invalid (Reason: %s).\n",
+ SECU_Strerror(PORT_GetError()));
+ } else {
+ fprintf(out,
+ "Content is detached; signature cannot be verified.\n");
+ }
+
+ signer_cname = SEC_PKCS7GetSignerCommonName(cinfo);
+ if (signer_cname != NULL) {
+ fprintf(out, "The signer's common name is %s\n", signer_cname);
+ PORT_Free(signer_cname);
+ } else {
+ fprintf(out, "No signer common name.\n");
+ }
+
+ signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo);
+ if (signer_ename != NULL) {
+ fprintf(out, "The signer's email address is %s\n", signer_ename);
+ PORT_Free(signer_ename);
+ } else {
+ fprintf(out, "No signer email address.\n");
+ }
+
+ signing_time = SEC_PKCS7GetSigningTime(cinfo);
+ if (signing_time != NULL) {
+ SECU_PrintTimeChoice(out, signing_time, "Signing time", 0);
+ } else {
+ fprintf(out, "No signing time included.\n");
+ }
+ } else {
+/* fprintf(out, "Content was not signed.\n");*/
+ }
+/*
+ fprintf(out, "There were%s certs or crls included.\n",
+ SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no");
+*/
+
+ /* write out certs */
+ SECItem **items = NULL;
+ SECOidTag kind;
+
+ kind = SEC_PKCS7ContentType (cinfo);
+ if (kind == SEC_OID_PKCS7_SIGNED_DATA) {
+/* fprintf(out, "content is SEC_OID_PKCS7_SIGNED_DATA\n");*/
+ SEC_PKCS7SignedData *sdp;
+
+ sdp = cinfo->content.signedData;
+ if (sdp != NULL) {
+ items = sdp->rawCerts;
+ }
+ } else {
+/* fprintf(out, "content is not SEC_OID_PKCS7_SIGNED_DATA\n");*/
+
+ }
+
+ int i= 0;
+ if (items != NULL) {
+ CERTCertificate *cert;
+ if (prefix == NULL) {
+ prefix = "chaincert";
+ }
+ while ((items[i]) != NULL) {
+ cert = (CERTCertificate*) items[i]->data;
+ FILE *outFile;
+ char filename[256];
+ int nb = 0;
+
+ sprintf(filename, "%s%d.der", prefix, i);
+
+ outFile = fopen(filename, "wb");
+ if (outFile == NULL) {
+ fprintf(out, "Couldn't open '%s' file for writing\n", filename);
+ i = -1;
+ break;
+ }
+ nb = fwrite((char *) cert, 1, items[i]->len, outFile);
+ fclose(outFile);
+
+ i++;
+ }
+ } else {
+ fprintf(out, "certs is NULL\n");
+ }
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return i;
+}
+
+
+/*
+ * Print the contents of a PKCS7 message, indicating signatures, etc.
+ */
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+ int ascii = 0;
+ char *prefix = NULL;
+ int exitStatus = 0;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "ad:i:o:p:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'a':
+ ascii = 1;
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'p':
+ prefix = optstate->value;
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ exitStatus = DecodeAndPrintFile(outFile, inFile, progName, ascii, prefix);
+ if (exitStatus < 0) {
+ SECU_PrintError(progName, "problem decoding data");
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return exitStatus;
+/* return 0;*/
+}
diff --git a/base/native-tools/src/p7tool/pppolicy.c b/base/native-tools/src/p7tool/pppolicy.c
new file mode 100644
index 000000000..76ec6e8c6
--- /dev/null
+++ b/base/native-tools/src/p7tool/pppolicy.c
@@ -0,0 +1,309 @@
+/** 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),
+ NULL, 0},
+ { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyQualifier, qualifierValue),
+ NULL, 0},
+ { 0, 0, NULL, 0 }
+};
+
+static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyInfo, policyID),
+ NULL, 0},
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyInfo, policyQualifiers),
+ secu_PolicyQualifierTemplate, 0 },
+ { 0, 0, NULL, 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,
+ const 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,
+ const 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, const 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, const 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,
+ const 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/base/native-tools/src/p7tool/secerror.c b/base/native-tools/src/p7tool/secerror.c
new file mode 100644
index 000000000..07e6bac8e
--- /dev/null
+++ b/base/native-tools/src/p7tool/secerror.c
@@ -0,0 +1,119 @@
+/** 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"
+#include "secerror.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/base/native-tools/src/p7tool/secerror.h b/base/native-tools/src/p7tool/secerror.h
new file mode 100644
index 000000000..dce63728f
--- /dev/null
+++ b/base/native-tools/src/p7tool/secerror.h
@@ -0,0 +1,44 @@
+/** 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 **/
+
+#ifndef _SEC_ERROR_H_
+#define _SEC_ERROR_H_
+
+const char *
+SECU_Strerror(PRErrorCode errNum);
+
+#endif /* _SEC_ERROR_H_ */
diff --git a/base/native-tools/src/p7tool/secpwd.c b/base/native-tools/src/p7tool/secpwd.c
new file mode 100644
index 000000000..c0cb9b3d5
--- /dev/null
+++ b/base/native-tools/src/p7tool/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, const 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/base/native-tools/src/p7tool/secutil.c b/base/native-tools/src/p7tool/secutil.c
new file mode 100644
index 000000000..abdfd216f
--- /dev/null
+++ b/base/native-tools/src/p7tool/secutil.c
@@ -0,0 +1,3665 @@
+/** 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 "secerror.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
+};
+
+
+static char *
+SECU_GetString(int16 error_number)
+{
+
+ static char errString[80];
+ sprintf(errString, "Unknown error string (%d)", error_number);
+ return errString;
+}
+
+static void
+SECU_PrintErrMsg(FILE *out, int level, const char *progName, const 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(const char *progName, const 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(const char *progName, const 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];
+ char external[] = "external";
+ 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;
+}
+
+static 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";
+ const 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;
+}
+
+static 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);
+ }
+}
+
+static 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, const 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, const 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, const 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_val". 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_val, const char *m, int level)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time_val, 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, "%s", 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, const char *m, int level)
+{
+ int64 time_val;
+ SECStatus rv;
+
+ rv = DER_UTCTimeToTime(&time_val, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time_val, 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, const char *m, int level)
+{
+ int64 time_val;
+ SECStatus rv;
+
+
+ rv = DER_GeneralizedTimeToTime(&time_val, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time_val, 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, const 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 */
+static void
+SECU_PrintSet(FILE *out, SECItem *t, const 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, const 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, const 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, const 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, const 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 */
+static void
+SECU_PrintEncodedBoolean(FILE *out, SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ secu_PrintBoolean(out, &my, m, level);
+}
+
+/* Print a DER encoded integer */
+static void
+SECU_PrintEncodedInteger(FILE *out, SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintInteger(out, &my, m, level);
+}
+
+/* Print a DER encoded OID */
+static void
+SECU_PrintEncodedObjectID(FILE *out, SECItem *i, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, (char *) "%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, const 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, const 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, const 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, const 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,
+ const 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, const 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,
+ const 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, const char *msg, int level)
+{
+ char *nameStr;
+ const 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];
+ const 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);
+}
+
+static int
+SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, const 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 */
+static int
+SECU_PrintSetOfExtensions(FILE *out, SECItem **any, const 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" */
+static int
+SECU_PrintSetOfAny(FILE *out, SECItem **any, const 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;
+}
+
+static int
+SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, const 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;
+}
+
+static int
+SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, const 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, const 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, const 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, const 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, const 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 *, const char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ const 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, const 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, "%s", 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, const 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,
+ const 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, const 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
+*/
+
+static 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, const 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, const 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(const char *progName)
+{
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+ if ((errLen > 0) && ((size_t) errLen < sizeof(buffer))) {
+ PR_GetErrorText(buffer);
+ }
+ SECU_PrintError(progName, "function failed");
+ if ((errLen > 0) && ((size_t) 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;
+ const 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/base/native-tools/src/p7tool/secutil.h b/base/native-tools/src/p7tool/secutil.h
new file mode 100644
index 000000000..10c8f9ae6
--- /dev/null
+++ b/base/native-tools/src/p7tool/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,
+ const char *msg, int level);
+#else
+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, const 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, const 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(const char *progName, const char *msg, ...);
+
+/* print out a system error message */
+extern void SECU_PrintSystemError(const char *progName, const 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, const char *m, int level);
+
+/* Print ObjectIdentifier symbolically */
+extern SECOidTag SECU_PrintObjectID(FILE *out, SECItem *oid, const char *m, int level);
+
+/* Print AlgorithmIdentifier symbolically */
+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, const char *m,
+ int level);
+
+/* Print SECItem as hex */
+extern void SECU_PrintAsHex(FILE *out, SECItem *i, const 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, const 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, const 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, const 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, const char *m,
+ int level);
+
+/* Dump contents of certificate */
+extern int SECU_PrintCertificate(FILE *out, SECItem *der, const char *m, int level);
+
+/* print trust flags on a cert */
+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, const char *m, int level);
+
+/* Dump contents of public key */
+extern int SECU_PrintPublicKey(FILE *out, SECItem *der, const 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, const char *m,
+ int level);
+
+/* Pretty-print any PKCS7 thing */
+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, const 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, const char *m, int level,
+ SECU_PPFunc inner);
+
+extern int SECU_PrintCrl(FILE *out, SECItem *der, const char *m, int level);
+
+extern void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, const char *m, int level);
+
+extern void SECU_PrintString(FILE *out, SECItem *si, const char *m, int level);
+extern void SECU_PrintAny(FILE *out, SECItem *i, const char *m, int level);
+
+extern void SECU_PrintPolicy(FILE *out, SECItem *value, const char *msg, int level);
+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ const char *msg, int level);
+
+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ const char *msg, int level);
+
+extern void SECU_PrintName(FILE *out, CERTName *name, const 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(const 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/base/native-tools/src/revoker/CMakeLists.txt b/base/native-tools/src/revoker/CMakeLists.txt
new file mode 100644
index 000000000..5aa5ddff3
--- /dev/null
+++ b/base/native-tools/src/revoker/CMakeLists.txt
@@ -0,0 +1,30 @@
+project(revoker C)
+
+set(REVOKER_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(REVOKER_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(revoker_SRCS
+ revoker.c
+ getopt.c
+)
+
+include_directories(${REVOKER_PRIVATE_INCLUDE_DIRS})
+
+add_executable(revoker ${revoker_SRCS})
+
+target_link_libraries(revoker ${REVOKER_LINK_LIBRARIES})
+
+install(
+ TARGETS revoker
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/base/native-tools/src/revoker/getopt.c b/base/native-tools/src/revoker/getopt.c
new file mode 100644
index 000000000..7554e1a14
--- /dev/null
+++ b/base/native-tools/src/revoker/getopt.c
@@ -0,0 +1,126 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * END COPYRIGHT BLOCK **/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+#include <stdio.h>
+#include <string.h> /* for str*() */
+#include <io.h> /* for write() */
+
+int opterr = 1; /* boolean flag, says "report error on stderr." */
+int optind = 1; /* index to element of argv from which options are
+ ** being parsed. */
+int optopt = 0; /* option character */
+char *optarg; /* ptr to option's parameter arg. */
+
+#ifdef _WIN32
+static void
+do_opterr(const char *s, int c, char * const av[])
+{
+ if (opterr) {
+ char buff[2];
+ int fd = _fileno(stderr);
+
+ buff[0] = (char)c;
+ buff[1] = '\n';
+ (void)write(fd, av[0], strlen(av[0]));
+ (void)write(fd, s, strlen(s));
+ (void)write(fd, buff, 2);
+ }
+}
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int
+getopt(int ac, char * const av[], const char * opts)
+{
+ static int i = 1; /* offset of current option char in current arg. */
+ char *p; /* opt char in opts that matched. */
+
+ /* Move to next value from argv? */
+ if (i == 1) {
+ if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
+ return EOF;
+ if (strcmp(av[optind], "--") == 0) {
+ optind++;
+ return EOF;
+ }
+ }
+
+ /* Get next option character. */
+ if ((optopt = av[optind][i]) == ':' ||
+ (p = strchr(opts, optopt)) == NULL) {
+ ERR(": illegal option -- ", optopt);
+ if (av[optind][++i] == '\0') {
+ optind++;
+ i = 1;
+ }
+ return '?';
+ }
+
+ /* Snarf argument? */
+ if (*++p == ':') {
+ if (av[optind][i + 1] != '\0')
+ optarg = &av[optind++][i + 1];
+ else {
+ if (++optind >= ac) {
+ ERR(": option requires an argument -- ", optopt);
+ i = 1;
+ return '?';
+ }
+ optarg = av[optind++];
+ }
+ i = 1;
+ } else {
+ if (av[optind][++i] == '\0') {
+ i = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+
+ return optopt;
+}
+
+#endif /* XP_PC */
diff --git a/base/native-tools/src/revoker/revoker.c b/base/native-tools/src/revoker/revoker.c
new file mode 100644
index 000000000..c7fc76294
--- /dev/null
+++ b/base/native-tools/src/revoker/revoker.c
@@ -0,0 +1,882 @@
+/* --- 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 ---
+ */
+
+/* vi: set ts=4 sw=4 : */
+#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>
+#include <time.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "ssl.h"
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+
+
+/* set Tabs to 8 */
+
+
+/*from nss2.8.4 secopt.h*/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+
+#ifdef _WIN32
+static void do_opterr(const char *s, int c, char * const av[]);
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int getopt(int ac, char * const av[], const char * opts);
+#else
+#if defined(LINUX)
+#include <getopt.h>
+#endif
+#endif /* XP_PC */
+/*end secopt.h*/
+
+#define VERSIONSTRING "$Revision$ ($Date$)"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define RD_BUF_SIZE (60 * 1024)
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+#define FPUTS if (verbose) fputs
+
+#define MAX_SERIAL_LEN 8192
+
+int MakeCertOK=1;
+
+int verbose;
+SECItem bigBuf;
+
+
+char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -s serialNum -n rsa_nickname [-p password | -w pwfile ] [-d dbdir] \n"
+ " [-v] [-V] [-u] [-r reasoncode] [-i numberOfHours] hostname[:port]\n"
+ " serialNum: List of serial numbers to revoke, in hex, e.g. '0x31' or '0x44,0x643,0x22'\n"
+ " reasoncode: integer from 0 to 6, as follows\n"
+ " 0 = Unspecified (default)\n"
+ " 1 = Key compromised\n"
+ " 2 = CA key compromised\n"
+ " 3 = Affiliation changed\n"
+ " 4 = Certificate superseded\n"
+ " 5 = Cessation of operation\n"
+ " 6 = Certificate is on hold\n"
+ " -u : unrevoke (take off hold)\n"
+ " -v : verbose\n"
+ " -V : report version information\n",
+ progName);
+ exit(1);
+}
+
+
+static void
+errWarn(char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+
+ FPRINTF(stderr, "exit after %s with error %d:\n", funcString,perr );
+}
+
+static void
+errExit(char * funcString)
+{
+ errWarn(funcString);
+ exit(1);
+}
+
+/* This invokes the "default" AuthCert handler in libssl.
+** The only reason to use this one is that it prints out info as it goes.
+*/
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate * peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("Subject: %s\nIssuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ /* invoke the "default" AuthCert handler. */
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ if (rv == SECSuccess) {
+ FPUTS("-- SSL3: Server Certificate Validated.\n", stderr);
+ }
+ /* error, if any, will be displayed by the Bad Cert Handler. */
+ return rv;
+}
+
+static SECStatus
+myBadCertHandler( void *arg, PRFileDesc *fd)
+{
+ /* int err = PR_GetError(); */
+ /* fprintf(stderr, "-- SSL: Server Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err)); */
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+
+SECStatus
+my_GetClientAuthData(void * arg,
+ PRFileDesc * socket,
+ struct CERTDistNamesStr * caNames,
+ struct CERTCertificateStr ** pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ CERTCertificate * cert = NULL;
+ SECKEYPrivateKey * privkey = NULL;
+ char * chosenNickName = (char *)arg; /* CONST */
+ void * proto_win = NULL;
+ SECStatus rv = SECFailure;
+
+ FPRINTF(stderr,"Called mygetclientauthdata - nickname = %s\n",chosenNickName);
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - cert = %x\n",(unsigned int)cert);
+ if ( cert ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - privkey = %x\n",(unsigned int)privkey);
+ if ( privkey ) {
+ rv = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no name given, automatically find the right cert. */
+ CERTCertNicknames * names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+ cert = PK11_FindCertFromNickname(names->nicknames[i],proto_win);
+ if ( !cert )
+ continue;
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
+ secCertTimeValid ) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+ rv = NSS_CmpCertChainWCANames(cert, caNames);
+ if ( rv == SECSuccess ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if ( privkey )
+ break;
+ }
+ rv = SECFailure;
+ CERT_DestroyCertificate(cert);
+ }
+ CERT_FreeNicknames(names);
+ }
+ }
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privkey;
+ }
+ return rv;
+}
+
+
+
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ char * cp; /* bulk cipher name */
+ char * ip; /* cert issuer DN */
+ char * sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+
+ static int only_once;
+
+ if (! only_once++ && fd) {
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+#if 0
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ "subject DN: %s\n"
+ "issuer DN: %s\n", cp, kp1, kp0, op, sp, ip);
+#else
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n",
+ cp, kp1, kp0, op);
+#endif
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+ }
+
+}
+
+
+PRBool useModelSocket = PR_TRUE;
+
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Netscape-Enterprise/2.0a\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+
+PRInt32
+do_writes(
+ void * a
+)
+{
+ PRFileDesc * ssl_sock = (PRFileDesc *)a;
+ PRUint32 sent = 0;
+ PRInt32 count = 0;
+
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ exit(4);
+ break;
+ }
+ FPRINTF(stderr, "PR_Write wrote %d bytes from bigBuf\n", count );
+ FPRINTF(stderr, "bytes: [%*s]\n",count,bigBuf.data);
+
+ sent += (PRUint32)count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ FPRINTF(stderr, "do_writes shutting down send socket\n");
+ /* PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); */
+ }
+
+ FPRINTF(stderr, "do_writes exiting with (failure = %d)\n",sent<bigBuf.len == SECFailure);
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+
+
+
+SECStatus
+do_io( PRFileDesc *ssl_sock, int connection)
+{
+ int countRead = 0;
+ PRInt32 rv;
+ char *buf;
+ int first=1;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+ if (!buf) exit(5);
+
+
+ /* send the http request here. */
+
+ rv = do_writes(ssl_sock);
+
+ if (rv == SECFailure) {
+ errWarn("returning from after calling do_writes");
+ PR_Free(buf);
+ buf = 0;
+ exit(6);
+ }
+ printSecurityInfo(ssl_sock);
+
+ /* read until EOF */
+ while (1) {
+ rv = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
+ if (rv == 0) {
+ break; /* EOF */
+ }
+ if (rv < 0) {
+ errWarn("PR_Read");
+ exit(1);
+ }
+
+ countRead += rv;
+ FPRINTF(stderr, "connection %d read %d bytes (%d total).\n",
+ connection, rv, countRead );
+ FPRINTF(stderr, "these bytes read:\n");
+ if (verbose) {
+ PR_Write(PR_STDERR,buf,rv);
+ PR_fprintf(PR_STDERR, "\n");
+ }
+
+ if (first) {
+ first=0;
+ if (rv < 13) {
+ errWarn("not enough bytes read in first read");
+ exit(2);
+ } else {
+ if ( ! PL_strnstr(buf,"200",13)) {
+ exit(3);
+ }
+ }
+ }
+ }
+ PR_Free(buf);
+ buf = 0;
+
+ /* Caller closes the socket. */
+
+ FPRINTF(stderr,
+ "connection %d read %d bytes total. -----------------------------\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+int
+do_connect(
+ PRNetAddr *addr,
+ PRFileDesc *model_sock,
+ int connection)
+{
+ PRFileDesc * ssl_sock;
+ PRFileDesc * tcp_sock;
+ PRStatus prStatus;
+ SECStatus result;
+ int rv = SECSuccess;
+ PRSocketOptionData opt;
+
+ int family = PR_NetAddrFamily( addr );
+
+ tcp_sock = PR_OpenTCPSocket( family );
+ if (tcp_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ /* Don't return SECFailure? */
+ return SECSuccess;
+ }
+
+ prStatus = PR_Connect(tcp_sock, addr, PR_SecondsToInterval(3));
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(6);
+ }
+
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ /* XXX if this import fails, close tcp_sock and return. */
+ if (!ssl_sock) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(7);
+ }
+
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ exit(8);
+ }
+
+ result = do_io( ssl_sock, connection);
+
+ if( ssl_sock != NULL ) {
+ PR_Close(ssl_sock);
+ ssl_sock = NULL;
+ }
+ return SECSuccess;
+}
+
+/* Returns IP address for hostname as PRUint32 in Host Byte Order.
+** Since the value returned is an integer (not a string of bytes),
+** it is inherently in Host Byte Order.
+*/
+PRUint32
+getIPAddress(const char * hostName)
+{
+ const unsigned char *p;
+ PRStatus prStatus;
+ PRUint32 rv;
+ PRHostEnt prHostEnt;
+ char scratch[PR_NETDB_BUF_SIZE];
+
+ prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_GetHostByName");
+
+#undef h_addr
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+
+ p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
+ FPRINTF(stderr, "%s -> %d.%d.%d.%d\n", hostName, p[0], p[1], p[2], p[3]);
+ rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return rv;
+}
+
+void
+client_main(
+ unsigned short port,
+ int connections,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert,
+ const char * hostName,
+ char * nickName)
+{
+ PRFileDesc *model_sock = NULL;
+ int rv;
+
+
+ FPRINTF(stderr, "port: %d\n", port);
+
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ /* SSL_CipherPrefSetDefault(0xC005 */
+ /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */
+ /*, PR_TRUE); */
+
+ /*
+ * Rifle through the values for the host
+ */
+
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+ int family = PR_AF_INET;
+
+ ai = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (ai) {
+ FPRINTF( stderr, "addr='%s'\n", PR_GetCanonNameFromAddrInfo( ai ) );
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ family = PR_NetAddrFamily(&addr);
+ FPRINTF( stderr, "family='%d'\n", family );
+ break;
+ }
+ PR_FreeAddrInfo(ai);
+ }
+
+ PR_SetNetAddr( PR_IpAddrNull, family, port, &addr );
+
+ model_sock = PR_OpenTCPSocket( family );
+ if (model_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ /* Should we really be re-using the same socket? */
+ model_sock = SSL_ImportFD(NULL, model_sock);
+
+
+ /* check on success of call to SSL_ImportFD() */
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+
+ /* enable ECC cipher also */
+
+ /* do SSL configuration. */
+
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ if (rv < 0) {
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ SSL_GetClientAuthDataHook(model_sock,
+ (SSLGetClientAuthData)my_GetClientAuthData,
+ nickName);
+
+ /* I'm not going to set the HandshakeCallback function. */
+
+ /* end of ssl configuration. */
+
+ rv = do_connect(&addr, model_sock, 1);
+
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+}
+
+
+SECStatus
+createRequest(char * serials, char *reason, char *invalidity, int take_off_hold)
+{
+ int tmpI;
+ char *s;
+ char **strs=NULL;
+ char *filter = NULL;
+ int count = 0;
+ int range = 0;
+ int i;
+ char *old;
+ char * newstr;
+ char * iDate;
+ time_t ltime;
+ time_t itime;
+ long l;
+
+ tmpI = strlen(serials);
+ if (tmpI >= MAX_SERIAL_LEN) {
+ fputs("Serial number length invalid.\n", stderr);
+ exit(1);
+ }
+
+ strs = PR_Malloc((sizeof (char*)) * strlen(serials));
+ if (strs == NULL) exit(1);
+
+ /* example serials:
+ 23-25
+ 0x34523
+ 0x1010,0x10101
+ 0x94,0x2202,0x10101,0202
+ */
+
+ s = serials;
+ s = strchr(serials,'-');
+ if (s != NULL) {
+ strs[count++] = serials;
+ *s = '\0';
+ s++;
+ strs[count++] = s;
+ range = 1;
+ } else {
+ s = serials;
+ while (1) {
+ strs[count++] = s;
+ s = strchr(s,',');
+ if (s == NULL) {break;}
+ *s = '\0';
+ s++;
+ }
+ }
+
+ if (range == 0) {
+ old = "";
+ for (i=0; i<count; i++) {
+ filter = PR_smprintf("%s(certRecordId%%3D%s)",old,strs[i]);
+ if (i>0) PR_smprintf_free(old);
+ old = filter;
+ }
+ } else {
+ filter = PR_smprintf("(%%26(certRecordId>%%3D%s)(certRecordId<%%3D%s))",strs[0],strs[1]);
+ }
+
+ iDate = "";
+ if (invalidity != NULL) {
+ time( &ltime );
+ l = atol(invalidity);
+ l *= 3600;
+ itime = (time_t)l;
+ ltime -= itime;
+ iDate = PR_smprintf("invalidityDate=%ld000&", ltime);
+ }
+
+ if (take_off_hold > 0) {
+ newstr = PR_smprintf(
+ "GET /ca/doUnrevoke?serialNumber=%s HTTP/1.0\r\n\r\n",
+ strs[0]);
+ } else {
+ newstr = PR_smprintf(
+ "GET /ca/doRevoke?op=doRevoke&"
+ "revocationReason=%s&%s"
+ "revokeAll=(|%s)&totalRecordCount=1 HTTP/1.0\r\n\r\n",
+ reason,iDate,
+ filter);
+ }
+
+ if (strlen(iDate) > 0) PR_smprintf_free(iDate);
+ if (filter != NULL) PR_smprintf_free(filter);
+ if (strs != NULL) PR_Free(strs);
+
+ bigBuf.data = (unsigned char *)newstr;
+
+ FPUTS((char *)bigBuf.data, stderr);
+
+ bigBuf.len = PORT_Strlen((char *)bigBuf.data);
+
+ return SECSuccess;
+}
+
+int
+main(int argc, char **argv)
+{
+ char * dir = ".";
+ char * hostName = NULL;
+ char * nickName = NULL;
+ char * progName = NULL;
+ char * serial = NULL;
+ char * tmp = NULL;
+ CERTCertificate * cert [kt_kea_size] = { NULL };
+ SECKEYPrivateKey * privKey[kt_kea_size] = { NULL };
+ int optchar;
+ int connections = 1;
+ int tmpI;
+ unsigned short port = 443;
+ SECStatus rv;
+ char * passwd = NULL;
+ char * passwdfile = NULL;
+ char * revocation_reason = NULL;
+ char * invalidity_date = NULL;
+ int take_off_hold = 0;
+ FILE *fp;
+ char pwbuf[256];
+ int co;
+ char *crlf;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+
+ while ((optchar = getopt(argc, argv, "Vd:n:p:s:r:i:w:uv")) != -1) {
+ switch(optchar) {
+
+/* Version */
+ case 'V':
+ printf("%s\n",VERSIONSTRING);
+ PR_Cleanup();
+ return 0;
+
+/* Directory which holds cert8.db and key3.db */
+ case 'd':
+ dir = optarg;
+ break;
+
+/* Nickname of certificate to use */
+ case 'n':
+ nickName = optarg;
+ break;
+
+/* password to open key3.db */
+ case 'p':
+ passwd = optarg;
+ break;
+
+/* name of file holding password for key3.db */
+ case 'w':
+ passwdfile = optarg;
+ break;
+
+/* revocation reason */
+ case 'r':
+ revocation_reason = optarg;
+ break;
+
+/* invalidity date */
+ case 'i':
+ invalidity_date = optarg;
+ break;
+
+/* unrevoke - take off hold */
+ case 'u':
+ take_off_hold++;
+ break;
+
+/* serial number */
+ case 's':
+ serial = optarg;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ default:
+ case '?':
+ fprintf( stderr, "ERROR: Invalid option!\n" );
+ Usage(progName);
+ break;
+
+ }
+ }
+
+ if (optind != argc - 1) {
+ fprintf( stderr, "ERROR: Invalid number of arguments!\n" );
+ Usage(progName);
+ }
+
+ hostName = argv[optind];
+ tmp = strchr(hostName, ':');
+ if (tmp) {
+ *tmp++ = 0;
+ tmpI = atoi(tmp);
+ if (tmpI <= 0) {
+ fprintf( stderr, "ERROR: Invalid port!\n" );
+ Usage(progName);
+ }
+ port = (unsigned short)tmpI;
+ }
+
+ if (revocation_reason == NULL) {
+ revocation_reason = "0";
+ }
+
+ if (!nickName || !serial) {
+ fprintf( stderr, "ERROR: Invalid nickname or serial number!\n" );
+ Usage(progName);
+ }
+
+ createRequest(serial,revocation_reason,invalidity_date,take_off_hold);
+
+ if (passwdfile) {
+ fp = fopen(passwdfile,"r");
+ if (!fp) { fprintf(stderr, "Couldn't open password file\n"); exit(7); }
+ co = fread(pwbuf,1,256,fp);
+ pwbuf[co] = '\0';
+ crlf = PL_strchr(pwbuf,'\n');
+ if (crlf) {
+ *crlf = '\0';
+ }
+ passwd = pwbuf;
+ }
+
+ /* set our password function */
+ if (passwd == NULL) {
+ fprintf( stderr, "ERROR: Invalid password!\n" );
+ PRINTF("Password must be provided on command line in this version of revoker.\n");
+ Usage(progName);
+ }
+ PK11_SetPasswordFunc(ownPasswd);
+
+ /* Call the libsec initialization routines */
+ rv = NSS_Init(dir);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(1);
+ }
+
+ cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
+ if (cert[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find certificate %s\n", nickName);
+ exit(1);
+ }
+
+ privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
+ if (privKey[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find Private Key for cert %s (possibly incorrect password)\n", nickName);
+ exit(1);
+ }
+
+
+ client_main(port, connections, privKey, cert, hostName, nickName);
+
+ NSS_Shutdown();
+ PR_Cleanup();
+ return 0;
+}
+
diff --git a/base/native-tools/src/setpin/CMakeLists.txt b/base/native-tools/src/setpin/CMakeLists.txt
new file mode 100644
index 000000000..b32e12b22
--- /dev/null
+++ b/base/native-tools/src/setpin/CMakeLists.txt
@@ -0,0 +1,43 @@
+project(setpin C)
+
+find_package(Ldap REQUIRED)
+
+set(SETPIN_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+ ${LDAP_INCLUDE_DIRS}
+)
+
+set(SETPIN_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+ ${LDAP_LIBRARIES}
+)
+
+set(setpin_SRCS
+ b64.c
+ options.c
+ setpin.c
+ setpin_options.c
+)
+
+include_directories(${SETPIN_PRIVATE_INCLUDE_DIRS})
+
+add_executable(setpin ${setpin_SRCS})
+
+target_link_libraries(setpin ${SETPIN_LINK_LIBRARIES})
+
+install(
+ TARGETS setpin
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
+
+install(
+ FILES
+ setpin.conf
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/pki/native-tools/
+)
diff --git a/base/native-tools/src/setpin/b64.c b/base/native-tools/src/setpin/b64.c
new file mode 100644
index 000000000..1c20f3792
--- /dev/null
+++ b/base/native-tools/src/setpin/b64.c
@@ -0,0 +1,102 @@
+/* --- 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 ---
+ */
+
+
+
+
+
+
+
+static char nib2b64[0x40f] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+
+static int
+ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, int lenused, int wraplen )
+{
+ unsigned char *byte, *stop;
+ unsigned char buf[3];
+ char *out;
+ unsigned long bits;
+ int i, pad, len;
+
+ len = 0;
+ out = dst;
+ stop = src + srclen;
+
+ /* convert to base 64 (3 bytes => 4 base 64 digits) */
+ for ( byte = src; byte < stop - 2; byte += 3 ) {
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, bits <<= 6 ) {
+ if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) {
+ *out++ = '\n';
+ *out++ = ' ';
+ lenused = 2;
+ }
+
+ /* get b64 digit from high order 6 bits */
+ *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
+ }
+ }
+ /* add padding if necessary */
+ if ( byte < stop ) {
+ for ( i = 0; byte + i < stop; i++ ) {
+ buf[i] = byte[i];
+ }
+ for ( pad = 0; i < 3; i++, pad++ ) {
+ buf[i] = '\0';
+ }
+ byte = buf;
+ bits = (byte[0] & 0xff) << 16;
+ bits |= (byte[1] & 0xff) << 8;
+ bits |= (byte[2] & 0xff);
+
+ for ( i = 0; i < 4; i++, bits <<= 6 ) {
+ if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) {
+ *out++ = '\n';
+ *out++ = ' ';
+ lenused = 2;
+ }
+
+ if (( i == 3 && pad > 0 ) || ( i == 2 && pad == 2 )) {
+ /* Pad as appropriate */
+ *out++ = '=';
+ } else {
+ /* get b64 digit from low order 6 bits */
+ *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
+ }
+ }
+ }
+
+ *out = '\0';
+
+ return( out - dst );
+}
+
+
+int
+ldif_base64_encode( unsigned char *src, char *dst, int srclen, int lenused )
+{
+ return ldif_base64_encode_internal( src, dst, srclen, lenused, 200);
+}
+
diff --git a/base/native-tools/src/setpin/options.c b/base/native-tools/src/setpin/options.c
new file mode 100644
index 000000000..9e2dab129
--- /dev/null
+++ b/base/native-tools/src/setpin/options.c
@@ -0,0 +1,184 @@
+/* --- 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 "options.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+/*
+ * (C) 1998 Netscape Communications Corporation
+ * All rights reserved
+ * Intellectual property rulez!
+ *
+ */
+
+
+
+/* this file maintains a static linked list of the
+ options it knows about
+*/
+
+static OPTION *option_list = NULL;
+static OPTION *last_option = NULL;
+
+static char* OPT_parseArgument(char *arg,char**valid);
+
+
+/* OPT_getValue(char *option, char** output)
+
+ returns 1 if the specified option exists,
+ - value is put into 'output'
+ returns 0 if the specified option doesn't exist
+ - output is unchanged
+
+*/
+
+
+int OPT_getValue(char *option, char **output) {
+ OPTION *opt = option_list;
+
+ while (opt) {
+ if (! strcmp(opt->name,option)) {
+ *output = opt->value;
+ return 1;
+ }
+ opt = opt->next;
+ }
+ return 0;
+}
+
+
+static char* OPT_parseOptFile(char *filename, char*validlist[])
+{
+ FILE *fp;
+ char buffer[1024];
+
+ if (filename == NULL || filename[0] == '\0') {
+ return ("Bad syntax for 'optfile'\n");
+ }
+ fp = fopen(filename,"r");
+ if (fp == NULL) {
+ return ("Options file could not be opened for reading\n");
+ }
+ while (fgets(buffer,1024,fp)) {
+ if (buffer[strlen(buffer)-1] == '\n') buffer[strlen(buffer)-1] = '\0';
+ if (buffer[strlen(buffer)-1] == '\r') buffer[strlen(buffer)-1] = '\0';
+
+ OPT_parseArgument(strdup(buffer),validlist);
+ }
+ fclose(fp);
+ return NULL;
+}
+
+
+
+static char *OPT_parseArgument(char *arg, char* validlist[]) {
+ char *error;
+ char *INV_ARG = "invalid argument: %s";
+ char *eq;
+
+ OPTION *new_opt;
+
+ if (!strncmp(arg,"optfile=",8)) {
+ return OPT_parseOptFile(&arg[8],validlist);
+ }
+
+ new_opt = (OPTION*)malloc(sizeof(OPTION));
+
+ new_opt->next = NULL;
+ new_opt->name = strdup(arg);
+ eq = strchr(new_opt->name,'=');
+ if (eq) {
+ *eq = 0;
+ }
+ new_opt->value = strchr(arg,'=');
+
+
+ if (new_opt->value != NULL) {
+ new_opt->value++;
+ }
+
+ if (option_list == NULL) {
+ option_list = new_opt;
+ last_option = new_opt;
+ }
+ else {
+ last_option->next = new_opt;
+ last_option= new_opt;
+ }
+ if (!validlist) {
+ return NULL;
+ }
+ else {
+ int i=0;
+ while (validlist[i]) {
+ if (! strcmp(validlist[i],new_opt->name)) {
+ return NULL;
+ }
+ i+=2;
+ }
+ }
+
+ error = (char *)malloc(strlen(INV_ARG)+strlen(new_opt->name)+5);
+ sprintf(error,INV_ARG,new_opt->name);
+
+ return error;
+}
+
+
+
+
+/* char *OPT_parseOptions(int ac, char **av)
+
+ constructs the linked list of options
+ ac: number of arguments
+ av: array of arguments
+ valid: array of valid arguments (can be null)
+
+ returns:
+ NULL if no error
+ char* with error text if error. caller is responsible for
+ freeing this memory
+
+*/
+
+char * OPT_parseOptions(int ac, char **av, char *valid[]) {
+ int i=0;
+ char *r=NULL;
+
+ assert(option_list == NULL);
+ assert(last_option == NULL);
+ assert(av != NULL);
+
+ if (ac == 1) return NULL;
+
+ for (i=0; i<ac-1; i++) {
+ r = OPT_parseArgument(av[1+i],valid);
+ if (r) return r;
+ }
+ return r;
+}
+
+
+
+
diff --git a/base/native-tools/src/setpin/options.h b/base/native-tools/src/setpin/options.h
new file mode 100644
index 000000000..80ccae478
--- /dev/null
+++ b/base/native-tools/src/setpin/options.h
@@ -0,0 +1,83 @@
+/* --- 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 ---
+ */
+
+
+
+#ifndef OPT_INCLUDE_H
+#define OPT_INCLUDE_H
+
+#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 */
+
+struct option {
+ struct option *next;
+ char *name;
+ char *value;
+};
+
+typedef struct option OPTION;
+
+/* OPT_getValue(char *option, char** output)
+
+ returns 1 if the specified option exists,
+ - value is put into 'output'
+ returns 0 if the specified option doesn't exist
+ - output is unchanged
+
+ 'value' will be everything after the '='
+ If no '=' is present in the argument, 'output' will be
+ set to null.
+ If '=' is present, but no value is given (e.g. "file="),
+ output will be a pointer to a string of zero length.
+
+*/
+
+extern int OPT_getValue(char *option, char **output);
+
+/* void OPT_parseOptions(int ac, char **av)
+
+ initializes the global store with the options supplied
+ in av (typically used for parsing arguments passed on the
+ command line. Arguments are of the form 'arg=value'.
+ valid: array of valid arguments (can be null)
+
+ returns:
+ NULL if no error
+ char* with error text if error. caller is responsible for
+ freeing this memory
+
+
+
+*/
+
+extern char * OPT_parseOptions(int ac, char **av, char**valid);
+
+#endif
diff --git a/base/native-tools/src/setpin/setpin.c b/base/native-tools/src/setpin/setpin.c
new file mode 100644
index 000000000..f1bf6a8c7
--- /dev/null
+++ b/base/native-tools/src/setpin/setpin.c
@@ -0,0 +1,1237 @@
+/* --- 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 ---
+ */
+
+
+/* Set-pin tool */
+
+
+/* This will modify the specified attribute in the directory
+ You must add the pin objectclass to the schema
+ e.g in config/slapd.oc.conf
+
+ attribute pin bin
+ objectclass pinPerson
+ superior organizationalPerson
+ allows
+ pin
+*/
+
+/*
+ History:
+ version 1.2 - upgraded to NSS 3.3.1
+ */
+
+#define SETPIN_VERSION "1.2"
+
+#include "options.h"
+#include "setpin_options.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <ldap.h>
+
+#define USE_NSS_RANDOM
+
+#ifdef USE_NSS_RANDOM
+/* removed #include <secrng.h> as of NSS 3.9 */
+/* removed from nss3_3_1 secrngt.h*/
+typedef struct RNGContextStr RNGContext;
+#endif
+
+#include <sechash.h>
+
+#include <plhash.h>
+#include <prerror.h>
+#include <ctype.h>
+
+#include <secoidt.h>
+#include <nss.h>
+
+extern int equals(char *s, char *t);
+extern SECStatus PK11_HashBuf(SECOidTag hashAlg,
+ unsigned char *out,
+ unsigned char *in,
+ int32 len);
+extern SECStatus PK11_GenerateRandom(unsigned char *data,
+ int len);
+
+/* use NSS's new generic hash api */
+#define USE_NSS_GEN_HASH
+
+void exitError(char *errstring);
+void exitLDAPError(char *errstring);
+void doLDAPBind();
+void doLDAPSearch(LDAPMessage **result);
+void doLDAPUnbind();
+void processSearchResults(LDAPMessage *r);
+char *newPassword();
+void initrandom();
+void testpingen();
+void do_setup();
+
+
+char *sha1_pw_enc( char *pwd );
+
+int errcode=0;
+
+LDAP *ld=NULL;
+char *programName = NULL;
+
+FILE *output;
+FILE *input;
+
+
+PLHashTable *pinHashTable=NULL;
+
+#ifdef USE_NSS_RANDOM
+RNGContext *rngc = NULL;
+#endif
+
+/* this tool should really be changed to use NSPR */
+#ifdef _WIN32
+#define strcasecmp stricmp
+#endif
+
+void exitError(char *errstring) {
+ char *errbuf;
+
+ errbuf = malloc(strlen(errstring)+strlen(programName)+10);
+
+ sprintf(errbuf,"%s error : %s\n",programName,errstring);
+ fputs(errbuf,stderr);
+ exit(errcode);
+}
+
+
+void exitLDAPError(char *errstring) {
+ char *ldaperr;
+ char *newerror;
+ int err;
+
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
+ ldaperr = ldap_err2string(err);
+ newerror = (char*) malloc((errstring?strlen(errstring):0) + (ldaperr?strlen(ldaperr):0) +5);
+ sprintf(newerror,"%s (%s)",errstring?errstring:"",ldaperr?ldaperr:"");
+ exitError(newerror);
+}
+
+
+/* This returns an allocated string, like strdup does, except that
+ the duplicate string begins with the first non-whitespace character */
+
+char * trim_strdup(char *s)
+{
+ while (*s == ' ' || *s == '\t') {
+ s++;
+ }
+ if (*s == '\0') return NULL;
+ return strdup(s);
+}
+
+void readInputFile() {
+ int more_to_read=1;
+ char *thedn = NULL;
+ char *thepin = NULL;
+ int linenum=0;
+
+ pinHashTable = PL_NewHashTable(256,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ NULL, /* allocOps */
+ NULL);
+ if (pinHashTable == NULL) {
+ errcode=9;
+ exitError("Couldn't create dn->pin hashtable");
+ }
+
+ if (o_input) {
+
+ do {
+ char line[4096];
+ char *n;
+ char *checkdn;
+
+ do {
+ n = fgets(line,4096,input);
+ linenum++;
+ if (! n) {
+ more_to_read = 0;
+ break;
+ }
+
+ /* replace newline with null byte */
+
+ line[strlen(line)-1] = 0;
+
+ if (! strncmp("dn:",line,3)) {
+ thedn = trim_strdup(&line[3]);
+ if (thedn == NULL) {
+ fprintf(stderr,"warning: empty line not allowed at line: %d\n",linenum);
+ }
+ }
+
+ if (! strncmp("pin:",line,4)) {
+ thepin = trim_strdup(&line[4]);
+ }
+
+ } while (strlen(line));
+
+ /* first check to see if that dn is already in the hashtable */
+
+ if (thepin == NULL) {
+ thepin = strdup("");
+ }
+
+ if (thedn && thepin) {
+
+ checkdn = (char*) PL_HashTableLookup(pinHashTable, thedn);
+ if (checkdn) {
+ char msg[256];
+ errcode = 10;
+ strcpy(msg,"Duplicate entry in input file for dn=");
+ strcat(msg,thedn);
+ exitError(msg);
+ }
+
+ PL_HashTableAdd(pinHashTable,
+ thedn,
+ thepin);
+ fprintf(stderr, "Reading dn/pin ( %s, %s )\n", thedn, thepin);
+ if (o_debug) {
+ fprintf(stderr, "Reading dn/pin ( %s, %s )\n", thedn, thepin);
+ }
+
+ } else {
+ if (o_debug) {
+ fprintf(stderr," ...ignoring\n");
+ }
+ }
+ if (thedn != NULL) {
+ free(thedn);
+ thedn = NULL;
+ }
+ if (thepin != NULL) {
+ free(thepin);
+ thepin = NULL;
+ }
+ } while (more_to_read);
+ }
+}
+
+
+int main(int ac, char **av) {
+ char *error;
+ LDAPMessage *search_results;
+
+ programName = av[0];
+ if (strlen(av[0]) == 0) {
+ strcpy(programName, "setpin");
+ }
+ else {
+ strcpy(programName, av[0]);
+ }
+
+ if (ac == 1) {
+ int i=0;
+ fprintf(stderr,"Setpin utility. Version " SETPIN_VERSION "\n"
+ "(C) 2005 Fedora Project.\n\n");
+ fprintf(stderr,"To set up directory for pin usage, modify setpin.conf, "
+ "then run:\n %s optfile=<svr_root>/bin/cert/tools/setpin.conf\n", programName);
+ fprintf(stderr,"\nUsage: %s option=value ... option=value\n\n", programName);
+
+ for (i = 0; i < valid_args_len; i += 2) {
+ if (valid_args[i]) {
+ fprintf(stderr,"%13s : %s\n",valid_args[i],valid_args[i+1]);
+ } else {
+ errcode=0;
+ fprintf(stderr,"\n");
+ exit(errcode);
+ }
+ }
+ }
+
+ error = OPT_parseOptions(ac, av, valid_args);
+ if (error) {
+ errcode=7;
+ exitError(error);
+ }
+
+ setDefaultOptions();
+
+ getOptions();
+ fprintf(stderr,"\n");
+ if (o_debug) {
+ fprintf(stderr,"about to validateOptions\n");
+ }
+
+ validateOptions();
+
+ /* Initialize random number generator */
+ initrandom();
+
+ if (o_debug) {
+ fprintf(stderr,"about to doLDAPBind\n");
+ }
+
+ if (! o_testpingen) {
+ doLDAPBind();
+ }
+
+ if (o_setup) {
+ do_setup();
+ }
+
+ if (o_output) {
+ output = fopen(o_output,"w");
+ if (!output) {
+ errcode=5;
+ exitError("Couldn't open output file");
+ }
+ } else {
+ output = stdout;
+ }
+
+ if (o_testpingen) {
+ testpingen();
+ exit(0);
+ }
+
+ if (o_input) {
+ input = fopen(o_input,"r");
+ if (!input) {
+ errcode=8;
+ exitError("Couldn't open input file");
+ }
+ }
+
+ readInputFile();
+
+ if (o_debug) {
+ fprintf(stderr,"about to doLDAPSearch\n");
+ }
+
+ doLDAPSearch(&search_results);
+
+ if (o_debug) {
+ fprintf(stderr,"about to processSearchResults\n");
+ }
+
+ processSearchResults(search_results);
+
+ if (output != stdout) {
+ fclose(output);
+ }
+
+ return 0;
+}
+
+
+
+/* This function implements the 'setup' procedure, invoked when the user
+ specified 'setup' as one of the arguments. The point is that in this
+ mode, schema modifications are performed to add these things to the
+ directory schema:
+ if (schemachange argument is specified)
+ - 'pin' attribute as specified by the 'attribute' argument (default 'pin')
+ - 'pinPerson' objectclass as specified by the 'objectclass argument (dfl: pinperson)
+ if ('pinmanager' argument specified)
+ - pin manager user, with permission to remove the pin for the basedn specified
+
+*/
+
+void do_setup() {
+ int i;
+
+ char *x_values[]={NULL,NULL,NULL};
+ char *a1_values[]={NULL,NULL};
+ char *a2_values[]={NULL,NULL};
+ char *a3_values[]={NULL,NULL};
+ char *a4_values[]={NULL,NULL};
+ LDAPMod x,a1,a2,a3,a4;
+ LDAPMod *mods[10];
+ char* password=NULL;
+ int err;
+
+ x_values[0] = malloc(1024);
+
+ doLDAPBind();
+
+ if (o_schemachange) {
+ sprintf(x_values[0],"( %s-oid NAME '%s' DESC 'User Defined Attribute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.5' SINGLE-VALUE )",
+ o_attribute,
+ o_attribute);
+
+ fprintf(stderr,"Adding attribute: %s\n",x_values[0]);
+ x_values[1] = NULL;
+ x.mod_op = LDAP_MOD_ADD;
+ x.mod_type = "attributetypes";
+ x.mod_values = x_values;
+ mods[0] = &x;
+ mods[1] = NULL;
+
+ i = ldap_modify_ext_s(ld, "cn=schema", mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
+ if (err != LDAP_TYPE_OR_VALUE_EXISTS) {
+ exitLDAPError("couldn't modify schema when creating pin attribute");
+ } else {
+ fprintf(stderr," .. successful\n\n");
+ }
+ }
+
+ sprintf(x_values[0],"( %s-oid NAME '%s' DESC 'User Defined ObjectClass' SUP 'top' MUST ( objectclass ) MAY ( aci $ %s )",
+ o_objectclass,o_objectclass,
+ o_attribute);
+
+ fprintf(stderr,"Adding objectclass: %s\n",x_values[0]);
+
+ x_values[1] = NULL;
+ x.mod_op = LDAP_MOD_ADD;
+ x.mod_type = "objectclasses";
+ x.mod_values = x_values;
+ mods[0] = &x;
+ mods[1] = NULL;
+
+
+ i = ldap_modify_ext_s(ld, "cn=schema", mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
+ if (err != LDAP_TYPE_OR_VALUE_EXISTS) {
+ exitLDAPError("couldn't modify schema when creating objectclass");
+ } else {
+ fprintf(stderr," .. successful\n\n");
+ }
+ }
+ }
+
+ if (o_pinmanager) {
+
+ if (o_pinmanagerpwd == NULL) {
+ exitError("missing pinmanagerpwd argument");
+ }
+ if (o_basedn == NULL) {
+ exitError("missing basedn argument");
+ }
+
+ password = sha1_pw_enc( o_pinmanagerpwd );
+
+ fprintf(stderr,"Adding user: %s\n",o_pinmanager);
+
+ a1_values[0] = "pinmanager";
+ a1_values[1] = NULL;
+ a1.mod_op = 0;
+ a1.mod_type = "sn";
+ a1.mod_values = a1_values;
+
+ a2_values[0] = "pinmanager";
+ a2_values[1] = NULL;
+ a2.mod_op = 0;
+ a2.mod_type = "cn";
+ a2.mod_values = a2_values;
+
+ a3_values[0] = password;
+ a3_values[1] = NULL;
+ a3.mod_op = 0;
+ a3.mod_type = "userPassword";
+ a3.mod_values = a3_values;
+
+ a4_values[0] = "person";
+ a4_values[1] = NULL;
+ a4.mod_op = 0;
+ a4.mod_type = "objectclass";
+ a4.mod_values = a4_values;
+
+ mods[0] = &a1;
+ mods[1] = &a2;
+ mods[2] = &a3;
+ mods[3] = &a4;
+ mods[4] = NULL;
+
+
+ i = ldap_add_ext_s(ld, o_pinmanager, mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
+ if (!( err == LDAP_TYPE_OR_VALUE_EXISTS || err == LDAP_ALREADY_EXISTS)) {
+ exitLDAPError("couldn't create new user");
+ } else {
+ fprintf(stderr," .. successful\n\n");
+ }
+ }
+
+
+ /* modify aci on basedn to allow pinmanager to modify pin attr */
+
+ fprintf(stderr,"modifying ACI for: %s\n",o_basedn);
+
+ sprintf(x_values[0],"(target=\"ldap:///%s\")"
+ "(targetattr=\"pin\")"
+ "(version 3.0; acl \"Pin attribute\"; "
+ "allow (all) userdn = \"ldap:///%s\"; "
+ "deny(proxy,selfwrite,compare,add,write,delete,search) "
+ "userdn = \"ldap:///self\"; ) ",
+ o_basedn,
+ o_pinmanager);
+
+ x_values[1] = malloc(1024);
+
+ sprintf(x_values[1],"(target=\"ldap:///%s\")"
+ "(targetattr=\"objectclass\")"
+ "(version 3.0; acl \"Pin Objectclass\"; "
+ "allow (all) userdn = \"ldap:///%s\"; "
+ " ) ",
+ o_basedn,
+ o_pinmanager);
+
+ x_values[2] = NULL;
+ x.mod_op = LDAP_MOD_ADD;
+ x.mod_type = "aci";
+ x.mod_values = x_values;
+
+ mods[0] = &x;
+ mods[1] = NULL;
+
+ i = ldap_modify_ext_s(ld, o_basedn, mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
+ if (!( err == LDAP_TYPE_OR_VALUE_EXISTS || err == LDAP_ALREADY_EXISTS)) {
+ exitLDAPError("couldn't modify aci on basedn");
+ } else {
+ fprintf(stderr," .. successful\n\n");
+ }
+ }
+ }
+ exit(0);
+}
+
+int ldif_base64_encode(
+ unsigned char *src, char *dst, int srclen, int lenused );
+
+/* do password hashing */
+
+/*
+ * Number of bytes each hash algorithm produces
+ */
+#define SHA1_LENGTH 20
+
+
+char *
+sha1_pw_enc( char *pwd )
+{
+ unsigned char hash[ SHA1_LENGTH ];
+ char *enc;
+
+ /* SHA1 hash the user's key */
+ PK11_HashBuf(SEC_OID_SHA1,hash,pwd,strlen(pwd));
+ enc = malloc(256);
+
+ sprintf( enc, "{SHA}");
+
+ (void)ldif_base64_encode( hash, enc + 5,
+ SHA1_LENGTH, -1 );
+
+ return( enc );
+}
+
+/* check the first 8 characters to see if this is a string */
+
+int isstring(char *s) {
+ int i=0;
+
+ for (i=0;i<8;i++) {
+ if (*s == 0) return 1;
+ if (! isprint(*s)) return 0;
+ s++;
+ }
+ return 1;
+}
+
+
+void doLDAPBind() {
+ char errbuf[1024];
+ char ldapuri[1024];
+ int port=389;
+ int r;
+ int status;
+
+ if (o_port == NULL) {
+ if (o_ssl) {
+ port = 636;
+ /* fprintf(stderr,"o_ssl = %0x, o_certdb = %0x, o_nickname= %0x\n",o_ssl,o_certdb,o_nickname); */
+ } else {
+ port = 389;
+ }
+ } else {
+ port = atoi(o_port);
+ }
+
+ if (o_debug) {
+ fprintf(stderr,"# connecting to %s:%d\n",o_host,port);
+ }
+
+ if (o_ssl) {
+ printf("SSL not currently supported.\n");
+ exit(0);
+ /* ld = ldapssl_init(o_host,port,LDAPSSL_AUTH_CNCHECK); */
+ } else {
+ snprintf(ldapuri, 1024, "ldap://%s:%i", o_host, port);
+ status = ldap_initialize(&ld, ldapuri);
+ }
+
+ if ((status != LDAP_SUCCESS) || (ld == NULL)) {
+ errcode=4;
+ exitError("could not connect to directory server");
+ }
+
+ if (o_debug) {
+ fprintf(stderr,"# ldap_init completed\n");
+ }
+
+ struct berval credential;
+ credential.bv_val = o_bindpw;
+ credential.bv_len= strlen(o_bindpw);
+
+ r = ldap_sasl_bind_s(ld, o_binddn, LDAP_SASL_SIMPLE, &credential, NULL, NULL, NULL);
+ if (r != LDAP_SUCCESS) {
+ sprintf(errbuf,"could not bind to %s:%d as %s",o_host,port,o_binddn);
+ if (strstr(o_binddn,"=") == NULL) {
+ strcat(errbuf,". Perhaps you missed the 'CN=' part of the bin DN?");
+ }
+ exitLDAPError(errbuf);
+ }
+
+ if (o_debug) {
+ fprintf(stderr,"# ldap_simple_bind_s completed\n");
+ }
+}
+
+
+void doLDAPSearch(LDAPMessage **result ) {
+ int r;
+ char errbuf[1024];
+
+ r = ldap_search_ext_s( ld, o_basedn, LDAP_SCOPE_SUBTREE,
+ o_filter, NULL, 0, NULL, NULL, NULL, 0, result );
+
+ if (r != LDAP_SUCCESS ) {
+ sprintf(errbuf,"could not complete search with that filter. Check filter and basedn");
+ exitLDAPError(errbuf);
+ }
+
+ if (o_debug) {
+ fprintf(stderr,"# ldap_search_s completed\n");
+ }
+}
+
+void doLDAPUnbind(){
+ ldap_unbind_ext_s(ld, NULL, NULL);
+}
+
+
+void processSearchResults(LDAPMessage *r) {
+ LDAPMessage *e;
+ char *dn;
+ char *a;
+ struct berval **vals;
+#ifdef USE_NSS_GEN_HASH
+ /* HASHContext *hcx;
+ HASH_HashType ht; */
+#else
+#endif
+ int i;
+ BerElement *ber;
+ char *objectclass_values[]={NULL,NULL};
+ int change=0;
+ int pin_objectclass_exists=0;
+ LDAPMod objectclass, pinattribute;
+ LDAPMod *mods[3];
+ SECStatus status = SECFailure;
+
+ char *saltval;
+ int action;
+ char *hashbuf_source = NULL;
+ char hashbuf_dest[256];
+ char errbuf[1024];
+ int pindatasize= 0;
+ char *pindata = NULL;
+ char *generatedPassword = NULL;
+ struct berval *bvals[2];
+ struct berval bval;
+
+ bvals[0] = &bval;
+ bvals[1] = NULL;
+
+ /* Check whether any results were found. */
+ i = ldap_count_entries( ld, r );
+
+ fprintf(stderr,"filter %s found %d matching results.\n", o_filter,i);
+
+ /* for each entry print out name + all attrs and values */
+ for ( e = ldap_first_entry( ld, r ); e != NULL;
+ e = ldap_next_entry( ld, e ) ) {
+
+ generatedPassword = NULL;
+
+ if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
+ fprintf(stderr, "Processing: %s\n", dn );
+ if (o_input) {
+ generatedPassword = (char*) PL_HashTableLookup(pinHashTable,dn);
+ if (generatedPassword) {
+ fprintf(stderr, " found user from input file\n");
+ }
+ if (! generatedPassword) {
+ fprintf(stderr, " Skipping (not in input file)\n");
+ continue;
+ }
+ }
+ }
+
+
+ /* what we do here is go through all the entries looking for
+ 'objectclass'.
+ */
+
+ pin_objectclass_exists = 0;
+ change = 0;
+
+#define ACTION_NONE 0
+#define ACTION_REPLACE 1
+#define ACTION_ADD 2
+
+ action = ACTION_ADD;
+
+ saltval = NULL;
+ /* loop through the entries */
+ for ( a = ldap_first_attribute( ld, e, &ber );
+ a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
+
+ if ((vals = ldap_get_values_len( ld, e, a)) != NULL ) {
+
+ if (o_debug && (! strcasecmp(o_debug,"attrs"))) {
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ char *bin;
+ bin = "<binary>";
+ if (isstring(vals[i]->bv_val)) {
+ bin = vals[i]->bv_val;
+ }
+
+ fprintf(stderr, " %s: %s\n",a,bin);
+ }
+ }
+
+ if (o_debug) {
+ fprintf(stderr," examining attribute: %s\n",a);
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ fprintf(stderr," val[%d]: %s\n",i,vals[i]->bv_val);
+ }
+ }
+
+ if (o_saltattribute != NULL) {
+ if (!strcasecmp(a,o_saltattribute)) {
+ saltval = vals[0]->bv_val;
+ if (o_debug) {
+ fprintf(stderr," setting salt value to: %s\n",saltval);
+ }
+ }
+ }
+
+ if (!strcasecmp(a,"objectclass")) {
+ /* check if we have a pin objectclass already */
+ /* Cycle through all the values for this
+ entry, looking for the one which matches the
+ objectclass we specified */
+
+ /* if user specified objectclass= on the commandline,
+ without any value, then the objectclass is assumed to
+ exist already */
+ if (strlen(o_objectclass) == 0) {
+ if (o_debug) { fprintf(stderr, " user objectclass assumed to already exist\n"); }
+ pin_objectclass_exists=1;
+ } else {
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ if (o_debug) {
+ fprintf(stderr, " checking vals[%d]=%s == objectclass=%s -> %d \n",
+ i,vals[i]->bv_val, o_objectclass, strcasecmp(vals[i]->bv_val,o_objectclass));
+ }
+ if (!strcasecmp(vals[i]->bv_val,o_objectclass)) {
+ if (o_debug) {
+ fprintf(stderr, " %s: %s found\n", a, vals[i]->bv_val );
+ }
+ pin_objectclass_exists = 1;
+ }
+ }
+ }
+ } else if (!strcasecmp(a,o_attribute)) {
+ if (o_clobber) {
+ action = ACTION_REPLACE;
+ } else {
+ action = ACTION_NONE;
+ }
+ }
+
+ /* use ldap_value_free_len */
+ ldap_value_free_len( vals );
+ }
+ ldap_memfree( a );
+ }
+
+ if (o_debug) { fprintf(stderr, " Did the objectclass exist? %d\n", pin_objectclass_exists); }
+
+ /* add the objectclass attribute if it doesn't already exist */
+
+ if (! pin_objectclass_exists) {
+ if (o_debug) {
+ fprintf(stderr,"objectclass: %s doesn't exist, adding\n",o_objectclass);
+ }
+ objectclass_values[0] = o_objectclass;
+ objectclass_values[1] = NULL;
+ objectclass.mod_op = LDAP_MOD_ADD;
+ objectclass.mod_type = "objectclass";
+ objectclass.mod_values = objectclass_values;
+ mods[0] = &objectclass;
+ mods[1] = NULL;
+
+ if (o_write) {
+ i = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ exitLDAPError("couldn't modify attribute");
+ }
+ }
+ }
+
+ pinattribute.mod_type = o_attribute;
+
+ /* password could have been set from input file. If not, set it now */
+ if (generatedPassword == NULL || (strlen(generatedPassword) == 0)) {
+ generatedPassword = newPassword();
+ }
+ if (generatedPassword == NULL || (strlen(generatedPassword) == 0)) {
+ errcode=13;
+ exitError("Couldn't generate password.");
+ }
+
+ /* should we hash the password? */
+ if (o_hash) {
+
+ /* we hash the DN of the user and the PIN together */
+
+ if (o_debug) {
+ fprintf(stderr,"checking salt attribute...\n");
+ }
+ if (saltval == NULL) {
+ if (o_saltattribute != NULL) {
+ errcode = 11;
+ exitError("specified salt attribute not found for this user");
+ }
+ if (o_debug) {
+ fprintf(stderr,"setting salt attribute to dn...\n");
+ }
+ saltval = dn;
+ }
+
+ hashbuf_source =
+ malloc(strlen(saltval) + strlen(generatedPassword) + 10);
+ if (hashbuf_source == NULL) {
+ errcode=12;
+ exitError("Couldn't allocate 'hashbuf_source'.");
+ }
+ strcpy(hashbuf_source,saltval);
+ strcat(hashbuf_source,generatedPassword);
+
+ if (o_debug) {
+ fprintf(stderr,"hashing this: %s\n",hashbuf_source);
+ }
+
+ saltval = NULL;
+
+ /* We leave one byte at the beginning of the hash
+ buffer, to support the hash type */
+
+#define SENTINEL_SHA1 0
+#define SENTINEL_MD5 1
+#define SENTINEL_NONE '-'
+
+ if ((!strcmp(o_hash,"SHA1")) || (!strcmp(o_hash,"sha1")) ) {
+ status = PK11_HashBuf(SEC_OID_SHA1,
+ (unsigned char *)hashbuf_dest+1,
+ (unsigned char *)hashbuf_source,
+ strlen(hashbuf_source)
+ );
+ hashbuf_dest[0] = SENTINEL_SHA1;
+ pindatasize = SHA1_LENGTH + 1;
+ } else if ((!strcmp(o_hash,"MD5")) || (!strcmp(o_hash,"md5")) ) {
+ status = PK11_HashBuf(SEC_OID_MD5,
+ (unsigned char *)hashbuf_dest+1,
+ (unsigned char *)hashbuf_source,
+ strlen(hashbuf_source)
+ );
+ hashbuf_dest[0] = SENTINEL_MD5;
+ pindatasize = MD5_LENGTH + 1;
+ } else if ((!strcmp(o_hash,"NONE")) || (!strcmp(o_hash,"none")) ) {
+ hashbuf_dest[0] = SENTINEL_NONE;
+ status = SECSuccess;
+ memcpy(hashbuf_dest+1,
+ hashbuf_source,
+ strlen(hashbuf_source)
+ );
+ } else {
+ sprintf(errbuf,"Unsupported hash type '%s'. Must be one of 'sha1', 'md5' or 'none",o_hash);
+ errcode = 7;
+ exitError(errbuf);
+ }
+
+ if (status != SECSuccess) {
+ sprintf(errbuf,"Error hashing pin (%d)",PR_GetError());
+ errcode = 9;
+ exitError(errbuf);
+ }
+
+ pindata = hashbuf_dest;
+
+ if (hashbuf_source != NULL) {
+ free(hashbuf_source);
+ hashbuf_source = NULL;
+ }
+ } else {
+ pindata = generatedPassword;
+ pindatasize = strlen(generatedPassword);
+ }
+
+ bval.bv_len = pindatasize;
+ bval.bv_val = pindata;
+
+ fprintf(stderr," Adding new %s\n",o_attribute);
+
+ if (! o_write) {
+ fprintf(stderr, " [NOTE: 'write' was not specified, so no changes will be made to the directory]\n");
+ }
+
+ pinattribute.mod_bvalues = bvals;
+ if (action == ACTION_REPLACE) {
+ pinattribute.mod_op = LDAP_MOD_REPLACE|LDAP_MOD_BVALUES;
+ if (o_debug) {
+ fprintf(stderr," %s exists, replacing\n",o_attribute);
+ }
+ } else if (action == ACTION_ADD) {
+ if (o_debug) {
+ fprintf(stderr," %s doesn't exist, adding\n",o_attribute);
+ }
+ pinattribute.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES;
+ } else if (action == ACTION_NONE) {
+ if (o_debug) {
+ fprintf(stderr," %s exists. not replacing\n",o_attribute);
+ }
+ goto skip_write;
+ }
+ mods[0] = &pinattribute;
+ mods[1] = NULL;
+
+ if (o_write) {
+ i = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
+
+ if (i != LDAP_SUCCESS) {
+ exitLDAPError("couldn't modify attribute");
+ }
+ }
+
+ skip_write:
+
+ fprintf(output,"dn:%s\n",dn);
+ fprintf(output,"%s:%s\n",o_attribute,generatedPassword);
+ if (o_debug) {
+ fprintf(stderr,"o_write = %0x\n",(unsigned int)o_write);
+ }
+ if (! o_write) {
+ fprintf(output,"status:notwritten\n");
+ } else {
+ if (action == ACTION_NONE) {
+ fprintf(output,"status:notreplaced\n");
+ } else {
+ if (i != LDAP_SUCCESS) {
+ fprintf(output,"status:writefailed\n");
+ } else {
+ if (action == ACTION_ADD) {
+ fprintf(output,"status:added\n");
+ } else if (action == ACTION_REPLACE) {
+ fprintf(output,"status:replaced\n");
+ }
+ }
+ }
+ }
+
+ fprintf(output,"\n");
+
+ if (dn) {
+ ldap_memfree( dn );
+ dn = NULL;
+ }
+
+ if ( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ fprintf(stderr, "\n" );
+ }
+ ldap_msgfree( r );
+}
+
+
+/* this function uses i_minlength and i_maxlength to determine the
+ size of the password to generate */
+
+static char *UCalpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+
+static char *LCalpha = "abcdefghijklmnopqrstuvwxyz";
+static char *numbers = "0123456789";
+static char *punc = "!#$%&*+,-./:;<=>?@[]^{|}";
+
+static char *charpool = NULL; /* carpool, geddit? */
+static int charpoolsize;
+
+static char *RNG_ALPHA = "RNG-alpha";
+static char *RNG_PRINTABLEASCII = "RNG-printableascii";
+static char *RNG_ALPHANUM = "RNG-alphanum";
+
+
+/* build the pool of characters we can use for the password */
+
+void buildCharpool() {
+ char err_buf[1024];
+ charpool = (char*) malloc(256);
+
+ charpool[0] = '\0';
+
+ if ( o_case == NULL) {
+ strcat(charpool,LCalpha); /* then add the lowercase */
+ } else {
+ if (strcmp(o_case,"upperonly")) {
+ errcode = 7;
+ exitError("Illegal value for case=");
+ }
+ }
+
+
+ if ( !strcmp(o_gen,RNG_ALPHA) ||
+ !strcmp(o_gen,RNG_ALPHANUM) ||
+ !strcmp(o_gen,RNG_PRINTABLEASCII) ) {
+ strcat(charpool,UCalpha); /* add uppercase chars */
+ } else {
+ sprintf(err_buf,"invalid value '%s' for gen= option",o_gen);
+ errcode = 7;
+ exitError(err_buf);
+ }
+
+ if ( strcmp(o_gen,"RNG-alpha")) { /* not alpha-only */
+ strcat(charpool,numbers);
+ }
+ if (! strcmp(o_gen,"RNG-printableascii")) {
+ strcat(charpool, punc);
+ }
+ if (o_debug) {
+ fprintf(stderr,"Character pool: %s\n",charpool);
+ }
+ charpoolsize = strlen(charpool);
+}
+
+
+/* initialize random number generator */
+
+void initrandom() {
+ char err_buf[1024];
+#ifdef USE_NSS_RANDOM
+ if( NSS_Initialize( "",
+ "",
+ "",
+ "",
+ NSS_INIT_NOCERTDB |
+ NSS_INIT_NOMODDB |
+ NSS_INIT_FORCEOPEN ) != SECSuccess ) {
+ sprintf(err_buf,"Couldn't initialize NSS (error code %d)\n",PR_GetError());
+ errcode = 9;
+ exitError(err_buf);
+ }
+#else
+ srand(time(NULL));
+#endif
+
+}
+
+
+unsigned short getRandomShort() {
+ unsigned short r;
+#ifdef USE_NSS_RANDOM
+ PK11_GenerateRandom( ( unsigned char * ) &r, sizeof( r ) );
+ if (o_debug) {
+ /* fprintf(stderr,"Random: %d\n",r); */
+ }
+ return r;
+#else
+ return (unsigned short) rand();
+#endif
+}
+
+
+/*
+ * this function is important. It needs review.
+ *
+ * returns a random number in the range (0 .. max-1)
+ */
+
+/* We have a short, rno, and we want to convert this to a number
+ in the required range by just using (rno % max). However,
+ this may result in some of the numbers at the end of 'rno's
+ range being selected more frequently. So, if random number
+ select is in this range, we will pick another.
+
+ As an example, assume:
+ a short is 4 bits (0..15)
+ max is 6
+
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ a a a a a a b b b b b b X X X X
+
+ we want to reject everything more than 11
+
+ we take 16 (that largest number which can be in a short+1)
+ divide by 'max', which is 6. This gives us 2. Multiply by
+ max, gives us 12. Subtract 1, which is 11, our highest
+ allowable range. Now we do the modulus.
+
+*/
+
+unsigned short getRandomInRange(unsigned short max) {
+ unsigned short rno;
+ unsigned short result;
+
+ unsigned short max_allowed_rno =
+ ((65536 / max) * max) -1;
+
+ do {
+ rno = getRandomShort();
+ } while (rno >max_allowed_rno);
+
+ result = rno % max;
+
+ assert(result < max);
+
+ return result;
+}
+
+
+char * newPassword() {
+ static char *pw_buf=NULL;
+ unsigned short l;
+ unsigned short r;
+ int i;
+
+ if (pw_buf == NULL) {
+ pw_buf = (char *) malloc(i_maxlength+5);
+ }
+
+ if (charpool == NULL) {
+ buildCharpool();
+ }
+
+ /* decide how long the password should be */
+ /* It must be between i_minlength and i_maxlength */
+
+ if (i_minlength == i_maxlength) {
+ l = i_minlength;
+ } else {
+ l = getRandomInRange((unsigned short)(1 + i_maxlength - i_minlength));
+ l += i_minlength;
+ }
+
+ for (i=0; i<l; i++) {
+ r = getRandomInRange((unsigned short)(charpoolsize));
+ pw_buf[i] = charpool[r];
+ }
+ pw_buf[l] = '\0';
+ return pw_buf;
+}
+
+
+void testpingen() {
+ int count=25;
+ int i,j;
+ int pwlen;
+ char *pw;
+ unsigned int index[256];
+ unsigned int *totals;
+ char c;
+
+ if (! equals(o_testpingen,"")) {
+ count = atoi(o_testpingen);
+ }
+
+ if (charpool == NULL) {
+ buildCharpool();
+ }
+
+ /* last spot is used to hold invalid chars */
+ totals = malloc(sizeof(int)*(charpoolsize+1));
+ if (totals != NULL) {
+ for (i=0;i<(charpoolsize);i++) {
+ totals[i] = 0;
+ }
+ totals[charpoolsize]=0;
+ for (i=0;i<256;i++) {
+ index[i] = 255; /* indicates->invalid */
+ }
+ for (i=0;i<charpoolsize;i++) {
+ index[(int)(charpool[i])] = i;
+ }
+
+ for (i=0;i<count;i++) {
+ pw = newPassword();
+ if (pw != NULL) {
+ if (o_debug) {
+ fprintf(output,"%d:%s\n",i+1,pw);
+ }
+ pwlen = strlen(pw);
+ for (j=0;j<pwlen;j++) {
+ c = pw[j];
+ if (index[(int)c] == 255) {
+ printf("\ninvalid char found: %02x %c\n",c,c);
+ totals[charpoolsize]++;
+ }
+ else {
+ totals[index[(int)c]]++;
+ }
+ }
+ free(pw);
+ }
+ }
+
+ for (i=0;i<charpoolsize;i++) {
+ fprintf(output,"%c: %10d\n",charpool[i],totals[i]);
+ }
+ fprintf(output,"invalid: %10d\n",totals[charpoolsize]);
+ free(totals);
+ }
+}
+
+
+
diff --git a/base/native-tools/src/setpin/setpin.conf b/base/native-tools/src/setpin/setpin.conf
new file mode 100644
index 000000000..4e5851858
--- /dev/null
+++ b/base/native-tools/src/setpin/setpin.conf
@@ -0,0 +1,83 @@
+# --- 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 ---
+#
+#
+# Setpin has a special setup mode which allows you to
+# automate the following two tasks.
+#
+# * To enable setpin to operate, the directory schema must be
+# changed to add the pin attribute and pinPerson objectclass.
+#
+# * To enable pin removal to work well, you can create a new
+# pin user with an ACI which lets the user remove the pin
+#
+# This configuration file is used as an input for setpin.
+# After modifying the options in this file, invoke setpin
+# with this config file:
+#
+# setpin optfile=setpin.conf
+
+
+########## GENERAL INFO ABOUT YOUR DIRECTORY #####
+
+
+#------- Enter the hostname of the LDAP server
+host=localhost
+
+#------- Enter the port number of the LDAP server
+port=389
+
+#------- Enter the DN of the Directory Manager user
+binddn=CN=Directory Manager
+
+#------- Enter the password for the Directory manager user
+bindpw=
+
+
+
+################ SCHEMA MODIFICATIONS #######
+#
+# Comment-out to turn off schema modification
+schemachange=yes
+
+# Enter the pin attribute name
+attribute=pin
+
+# Enter the pin objectclass
+objectclass=pinPerson
+
+
+############### PIN REMOVAL ##########
+#
+# To enable pin removal, it is advisable to create a new
+# user who has the power to remove pins, and nothing else.
+#
+# Enter the DN and password for the new pin manager user
+pinmanager=cn=pinmanager,o=mcom.com
+pinmanagerpwd=
+
+# Enter the base over which this user has the power
+# to remove pins
+basedn=ou=people,o=mcom.com
+
+
+
+## This line switches setpin into setup mode.
+## Please do not change it.
+setup=yes
+
diff --git a/base/native-tools/src/setpin/setpin_options.c b/base/native-tools/src/setpin/setpin_options.c
new file mode 100644
index 000000000..d8ee83a8c
--- /dev/null
+++ b/base/native-tools/src/setpin/setpin_options.c
@@ -0,0 +1,290 @@
+/* --- 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 ---
+ */
+
+
+/* Set-pin tool */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+extern int OPT_getValue(char *option, char **output);
+extern void exitError(char *errstring);
+extern int errcode;
+
+#define PW_DEFAULT_LENGTH 6
+#define ERR_BUF_LENGTH 512
+
+char *valid_args[] = {
+ "host", "LDAP host [required]",
+ "port", "LDAP port (default 389)",
+ "binddn", "DN to bind to directory as [required]",
+ "bindpw", "Password associated with above DN ",
+ "filter", "Ldap search filter e.g. filter=(uid=*) [required]",
+/* "ssl", "Use SSL LDAP connection?", */
+/* "certdb", "Path to SSL Client certificate database directory (not yet implemented)",
+ "nickname", "Nickname of cert to use for SSL client auth (not yet implemented)",
+ */
+ "basedn", "Base DN used for LDAP search",
+ "length", "Length of generated pins (default 6)",
+ "minlength","Minimum length of generated pins (not to be used with 'length')",
+ "maxlength","Maximum length of generated pins (not to be used with 'length')",
+ "gen", "Permitted chars for pin. Type 'setpin gen' for more info",
+ "case", "Restrict case of pins 'case=upperonly'",
+ "objectclass", "Objectclass of LDAP entry to operate on (default pinPerson)",
+ "attribute","Which LDAP attribute to write to (default pin)",
+ "hash", "Hash algorithm used to store pin: 'none', 'md5' or 'sha1' (default)",
+ "saltattribute", "Which attribute to use for salt (default: dn)",
+ "input", "File to use for restricting DN's, or providing your own pins",
+ "output", "Redirect stdout to a file",
+ "write", "Turn on writing to directory (otherwise, pins will not get written)",
+ "clobber", "Overwrite old pins in the directory",
+ "testpingen", "Test pin generation mode. testpingen=count",
+ "debug", "Turn on debugging, or use debug=attrs for even more",
+ "optfile", "Read in options (one per line) from specified file",
+ "setup", "Switch to setup mode",
+ "pinmanager","Pin Manager user to create in setup mode",
+ "pinmanagerpwd","password of pin manager user in setup mode",
+ "schemachange","make schema changes in setup mode",
+ NULL
+};
+
+int valid_args_len = sizeof(valid_args)/sizeof(char *);
+
+int i_length, i_minlength, i_maxlength;
+
+char *attribute=NULL;
+
+char *o_certdb,*o_nickname,*o_binddn,*o_bindpw,*o_filter,*o_ssl,
+ *o_basedn,*o_input,*o_host,*o_port,*o_length,*o_minlength,*o_hash,
+ *o_maxlength,*o_gen,*o_case,*o_attribute,*o_objectclass,*o_output,
+ *o_retry,*o_debug, *o_write, *o_clobber, *o_saltattribute, *o_testpingen,
+ *o_setup,*o_pinmanager,*o_pinmanagerpwd,*o_schemachange;
+
+void setDefaultOptions() {
+ o_certdb= ".";
+ o_nickname= NULL;
+ o_binddn= NULL;
+ o_bindpw= NULL;
+ o_filter= NULL;
+ o_ssl= NULL;
+ o_basedn= NULL;
+ o_input= NULL;
+ o_host= NULL;
+ o_port= NULL;
+ o_length= NULL; /* default set later */
+ o_minlength=NULL;
+ o_maxlength=NULL;
+ o_gen= "RNG-alphanum";
+ o_case= NULL;
+ o_attribute="pin";
+ o_hash= "sha1";
+ o_objectclass="pinPerson";
+ o_output= NULL;
+ o_retry= "5";
+ o_debug= NULL;
+ o_write= NULL;
+ o_clobber= NULL;
+ o_saltattribute = NULL;
+ o_testpingen = NULL;
+ o_setup= NULL;
+ o_pinmanager= NULL;
+ o_pinmanagerpwd= NULL;
+ o_schemachange= NULL;
+}
+
+void getOptions() {
+ int i;
+ char *c;
+
+ i_length = 0;
+ i_minlength =0;
+ i_maxlength =0;
+
+ OPT_getValue("certdb", &o_certdb);
+ OPT_getValue("nickname", &o_nickname);
+ OPT_getValue("binddn", &o_binddn);
+ OPT_getValue("bindpw", &o_bindpw);
+ OPT_getValue("filter", &o_filter);
+ i = OPT_getValue("ssl", &o_ssl);
+ if (i) o_ssl = "yes";
+ OPT_getValue("basedn", &o_basedn);
+ OPT_getValue("input", &o_input);
+ OPT_getValue("host", &o_host);
+ OPT_getValue("port", &o_port);
+ OPT_getValue("length", &o_length);
+ if (o_length) i_length = atoi(o_length);
+ OPT_getValue("minlength",&o_minlength);
+ if (o_minlength) i_minlength = atoi(o_minlength);
+ OPT_getValue("maxlength",&o_maxlength);
+ if (o_maxlength) i_maxlength = atoi(o_maxlength);
+ OPT_getValue("gen", &o_gen);
+ OPT_getValue("case", &o_case);
+ OPT_getValue("attribute",&o_attribute);
+ OPT_getValue("hash", &o_hash);
+ if (o_hash) {
+ c = o_hash;
+ while (*c) {
+ if (isupper(*c)) {
+ *c = *c - 'A' + 'a';
+ }
+ c++;
+ }
+ }
+
+ OPT_getValue("objectclass",&o_objectclass);
+ OPT_getValue("output", &o_output);
+ OPT_getValue("retry", &o_retry);
+ i = OPT_getValue("debug", &o_debug);
+ if (i) {
+ if (! o_debug) {
+ o_debug = "yes";
+ }
+ }
+ i = OPT_getValue("write", &o_write);
+ if (i) o_write = "yes";
+ i = OPT_getValue("clobber", &o_clobber);
+ if (i) o_clobber = "yes";
+ OPT_getValue("saltattribute", &o_saltattribute);
+ i = OPT_getValue("testpingen", &o_testpingen);
+ if (i) {
+ if (!o_testpingen) {
+ o_testpingen = "25";
+ }
+ }
+ OPT_getValue("setup", &o_setup);
+ OPT_getValue("pinmanager", &o_pinmanager);
+ OPT_getValue("pinmanagerpwd", &o_pinmanagerpwd);
+ OPT_getValue("schemachange", &o_schemachange);
+
+
+}
+
+int equals(char *s, char *t) {
+ return !(strcmp(s,t));
+}
+
+void validateOptions() {
+ char errbuf[ERR_BUF_LENGTH];
+
+ if (o_nickname && equals(o_ssl,"no")) {
+ snprintf(errbuf, ERR_BUF_LENGTH, "specifying nickname doesn't make sense with no SSL");
+ goto loser;
+ }
+
+ if (o_gen == NULL || !
+ ( equals(o_gen,"RNG-printableascii") ||
+ equals(o_gen,"RNG-alpha") ||
+ equals(o_gen,"RNG-alphanum") ||
+ equals(o_gen,"FIPS181-printable"))
+ ) {
+ printf("Permissible values for gen:\n"
+ " RNG-alpha : alpha-only characters\n"
+ " RNG-alphanum : alphanumeric characters\n"
+ " RNG-printableascii : alphanumeric and punctuation\n");
+ if (o_gen) {
+ printf("You specified: gen=%s\n",o_gen);
+ }
+ exit(0);
+ }
+
+ if (o_length && (o_minlength || o_maxlength)) {
+ strcpy(errbuf,"cannot use minlength or maxlength with length option");
+ goto loser;
+ }
+
+ if (o_minlength && !o_maxlength) {
+ strcpy(errbuf,"if you set minlength, you must also set maxlength");
+ goto loser;
+ }
+
+ if (!o_minlength && o_maxlength) {
+ strcpy(errbuf,"if you set maxlength, you must also set minlength");
+ goto loser;
+ }
+
+ if (i_minlength > i_maxlength) {
+ strcpy(errbuf,"cannot set minlength to be more than maxlength");
+ goto loser;
+ }
+
+ if (i_length > 0) {
+ i_minlength = i_length;
+ i_maxlength = i_length;
+ }
+ else {
+ if (i_minlength == 0 && i_maxlength == 0) {
+ i_minlength = PW_DEFAULT_LENGTH;
+ i_maxlength = PW_DEFAULT_LENGTH;
+ }
+ }
+
+ if (o_testpingen) {
+ return;
+ }
+
+ if (!o_host || equals(o_host,"")) {
+ strcpy(errbuf,"host missing");
+ goto loser;
+ }
+
+ if (!o_binddn || equals(o_binddn,"")) {
+ strcpy(errbuf,"binddn missing");
+ goto loser;
+ }
+
+ if (!o_bindpw || equals(o_bindpw,"")) {
+ strcpy(errbuf,"bindpw missing");
+ goto loser;
+ }
+
+ if (o_setup != NULL) {
+ return;
+ }
+
+ if (!o_basedn) {
+ fprintf(stderr,"WARNING: basedn not set. Will search from root.\n");
+ }
+
+ if (!o_filter || equals(o_filter,"")) {
+ strcpy(errbuf,"filter missing. Example filters:\n filter=(uid=*) - all users with a UID attribute\n filter=(&(uid=*)(ou=Managers)) - all users with a UID and members of the managers group\n");
+ goto loser;
+ }
+
+ if (!
+ (equals(o_hash,"sha1") ||
+ equals(o_hash,"md5") ||
+ equals(o_hash,"none"))
+ ) {
+ snprintf(errbuf, ERR_BUF_LENGTH, "invalid hash: %s",o_hash);
+ goto loser;
+ }
+ if (equals(o_hash,"none")) o_hash = NULL;
+
+ return ;
+
+ loser:
+ errcode=13;
+ exitError(errbuf);
+
+}
+
+
diff --git a/base/native-tools/src/setpin/setpin_options.h b/base/native-tools/src/setpin/setpin_options.h
new file mode 100644
index 000000000..45373f356
--- /dev/null
+++ b/base/native-tools/src/setpin/setpin_options.h
@@ -0,0 +1,56 @@
+/* --- 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 ---
+ */
+
+
+#ifndef SETPIN_OPTIONS_H
+#define SETPIN_OPTIONS_H
+
+#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 */
+
+extern char *o_certdb,*o_nickname,*o_binddn,*o_bindpw,*o_bindpwfile,*o_filter,*o_ssl,
+ *o_input,*o_basedn,*o_dnfile,*o_host,*o_port,*o_length,*o_minlength,
+ *o_maxlength,*o_gen,*o_case,*o_attribute,*o_hash,*o_objectclass,*o_output,
+ *o_retry,*o_debug,*o_write,*o_clobber,*o_saltattribute,*o_testpingen,*o_setup,
+ *o_pinmanager,*o_pinmanagerpwd,*o_schemachange;
+
+extern char *valid_args[];
+extern int valid_args_len;
+
+extern void setDefaultOptions();
+extern void getOptions();
+extern void validateOptions();
+
+extern int i_length, i_minlength, i_maxlength;
+
+extern char* attribute;
+
+#endif
diff --git a/base/native-tools/src/sslget/CMakeLists.txt b/base/native-tools/src/sslget/CMakeLists.txt
new file mode 100644
index 000000000..ec4bd85f9
--- /dev/null
+++ b/base/native-tools/src/sslget/CMakeLists.txt
@@ -0,0 +1,30 @@
+project(sslget C)
+
+set(SSLGET_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(SSLGET_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(sslget_SRCS
+ sslget.c
+ getopt.c
+)
+
+include_directories(${SSLGET_PRIVATE_INCLUDE_DIRS})
+
+add_executable(sslget ${sslget_SRCS})
+
+target_link_libraries(sslget ${SSLGET_LINK_LIBRARIES})
+
+install(
+ TARGETS sslget
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/base/native-tools/src/sslget/getopt.c b/base/native-tools/src/sslget/getopt.c
new file mode 100644
index 000000000..7554e1a14
--- /dev/null
+++ b/base/native-tools/src/sslget/getopt.c
@@ -0,0 +1,126 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * END COPYRIGHT BLOCK **/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+#include <stdio.h>
+#include <string.h> /* for str*() */
+#include <io.h> /* for write() */
+
+int opterr = 1; /* boolean flag, says "report error on stderr." */
+int optind = 1; /* index to element of argv from which options are
+ ** being parsed. */
+int optopt = 0; /* option character */
+char *optarg; /* ptr to option's parameter arg. */
+
+#ifdef _WIN32
+static void
+do_opterr(const char *s, int c, char * const av[])
+{
+ if (opterr) {
+ char buff[2];
+ int fd = _fileno(stderr);
+
+ buff[0] = (char)c;
+ buff[1] = '\n';
+ (void)write(fd, av[0], strlen(av[0]));
+ (void)write(fd, s, strlen(s));
+ (void)write(fd, buff, 2);
+ }
+}
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int
+getopt(int ac, char * const av[], const char * opts)
+{
+ static int i = 1; /* offset of current option char in current arg. */
+ char *p; /* opt char in opts that matched. */
+
+ /* Move to next value from argv? */
+ if (i == 1) {
+ if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
+ return EOF;
+ if (strcmp(av[optind], "--") == 0) {
+ optind++;
+ return EOF;
+ }
+ }
+
+ /* Get next option character. */
+ if ((optopt = av[optind][i]) == ':' ||
+ (p = strchr(opts, optopt)) == NULL) {
+ ERR(": illegal option -- ", optopt);
+ if (av[optind][++i] == '\0') {
+ optind++;
+ i = 1;
+ }
+ return '?';
+ }
+
+ /* Snarf argument? */
+ if (*++p == ':') {
+ if (av[optind][i + 1] != '\0')
+ optarg = &av[optind++][i + 1];
+ else {
+ if (++optind >= ac) {
+ ERR(": option requires an argument -- ", optopt);
+ i = 1;
+ return '?';
+ }
+ optarg = av[optind++];
+ }
+ i = 1;
+ } else {
+ if (av[optind][++i] == '\0') {
+ i = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+
+ return optopt;
+}
+
+#endif /* XP_PC */
diff --git a/base/native-tools/src/sslget/sslget.c b/base/native-tools/src/sslget/sslget.c
new file mode 100644
index 000000000..7288a1c58
--- /dev/null
+++ b/base/native-tools/src/sslget/sslget.c
@@ -0,0 +1,836 @@
+/* --- 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 ---
+ */
+
+/* vi: set ts=4 sw=4 : */
+#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>
+#include <time.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "ssl.h"
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+
+
+/* set Tabs to 8 */
+
+
+/*from nss2.8.4 secopt.h*/
+#ifdef XP_PC
+
+/*
+** This comes from the AT&T public-domain getopt published in mod.sources
+** (i.e., comp.sources.unix before the great Usenet renaming).
+*/
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+
+#ifdef _WIN32
+static void do_opterr(const char *s, int c, char * const av[]);
+#define ERR(s, c) do_opterr(s, c, av)
+#else
+#define ERR(s, c) /* Win16 doesn't do stderr */
+#endif
+
+/*
+** Return options and their values from the command line.
+*/
+int getopt(int ac, char * const av[], const char * opts);
+#else
+#if defined(LINUX)
+#include <getopt.h>
+#endif
+#endif /* XP_PC */
+/*end secopt.h*/
+
+#define VERSIONSTRING "$Revision$ ($Date$)"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define RD_BUF_SIZE (60 * 1024)
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+#define FPUTS if (verbose) fputs
+
+#define MAX_SERIAL_LEN 8192
+
+int MakeCertOK=1;
+
+int verbose;
+SECItem bigBuf;
+
+
+char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-n nickname] [-p password | -w pwfile ] [-d dbdir] \n"
+ " [-e post] [-v] [-V] -r url hostname[:port]\n"
+ " -n : nickname or hsm:nickname\n"
+ " -v : verbose\n"
+ " -V : report version information\n",
+ progName);
+ exit(1);
+}
+
+
+static void
+errWarn(char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+
+ FPRINTF(stderr, "exit after %s with error %d:\n", funcString,perr );
+}
+
+static void
+errExit(char * funcString)
+{
+ errWarn(funcString);
+ exit(1);
+}
+
+/* This invokes the "default" AuthCert handler in libssl.
+** The only reason to use this one is that it prints out info as it goes.
+*/
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate * peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("Subject: %s\nIssuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ /* invoke the "default" AuthCert handler. */
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ if (rv == SECSuccess) {
+ FPUTS("-- SSL3: Server Certificate Validated.\n", stderr);
+ }
+ /* error, if any, will be displayed by the Bad Cert Handler. */
+ return rv;
+}
+
+static SECStatus
+myBadCertHandler( void *arg, PRFileDesc *fd)
+{
+ /* int err = PR_GetError(); */
+ /* fprintf(stderr, "-- SSL: Server Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err)); */
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+
+SECStatus
+my_GetClientAuthData(void * arg,
+ PRFileDesc * socket,
+ struct CERTDistNamesStr * caNames,
+ struct CERTCertificateStr ** pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ CERTCertificate * cert = NULL;
+ SECKEYPrivateKey * privkey = NULL;
+ char * chosenNickName = (char *)arg; /* CONST */
+ void * proto_win = NULL;
+ SECStatus rv = SECFailure;
+
+ FPRINTF(stderr,"Called mygetclientauthdata - nickname = %s\n",chosenNickName);
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - cert = %x\n",(unsigned int)cert);
+ if ( cert ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ FPRINTF(stderr," mygetclientauthdata - privkey = %x\n",(unsigned int)privkey);
+ if ( privkey ) {
+ rv = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no name given, automatically find the right cert. */
+ CERTCertNicknames * names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+ cert = PK11_FindCertFromNickname(names->nicknames[i],proto_win);
+ if ( !cert )
+ continue;
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
+ secCertTimeValid ) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+ rv = NSS_CmpCertChainWCANames(cert, caNames);
+ if ( rv == SECSuccess ) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if ( privkey )
+ break;
+ }
+ rv = SECFailure;
+ CERT_DestroyCertificate(cert);
+ }
+ CERT_FreeNicknames(names);
+ }
+ }
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privkey;
+ }
+ return rv;
+}
+
+
+
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ char * cp; /* bulk cipher name */
+ char * ip; /* cert issuer DN */
+ char * sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+
+ static int only_once;
+
+ if (! only_once++ && fd) {
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+#if 0
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ "subject DN: %s\n"
+ "issuer DN: %s\n", cp, kp1, kp0, op, sp, ip);
+#else
+ PRINTF("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n",
+ cp, kp1, kp0, op);
+#endif
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+ }
+
+}
+
+
+PRBool useModelSocket = PR_TRUE;
+
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Netscape-Enterprise/2.0a\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+
+PRInt32
+do_writes(
+ void * a
+)
+{
+ PRFileDesc * ssl_sock = (PRFileDesc *)a;
+ PRUint32 sent = 0;
+ PRInt32 count = 0;
+
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ exit(4);
+ break;
+ }
+ FPRINTF(stderr, "PR_Write wrote %d bytes from bigBuf\n", count );
+ FPRINTF(stderr, "bytes: [%*s]\n",count,bigBuf.data);
+
+ sent += (PRUint32)count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ FPRINTF(stderr, "do_writes shutting down send socket\n");
+ /* PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND); */
+ }
+
+ FPRINTF(stderr, "do_writes exiting with (failure = %d)\n",sent<bigBuf.len == SECFailure);
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+
+
+
+SECStatus
+do_io( PRFileDesc *ssl_sock, int connection)
+{
+ int countRead = 0;
+ PRInt32 rv;
+ char *buf;
+ char *buf2;
+ int first=1;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+ if (!buf) exit(5);
+
+ /* send the http request here. */
+
+ rv = do_writes(ssl_sock);
+
+ if (rv == SECFailure) {
+ errWarn("returning from after calling do_writes");
+ PR_Free(buf);
+ buf = 0;
+ exit(6);
+ }
+ printSecurityInfo(ssl_sock);
+
+ /* read until EOF */
+ while (1) {
+ rv = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
+ if (rv == 0) {
+ break; /* EOF */
+ }
+ if (rv < 0) {
+ errWarn("PR_Read");
+ PR_Free(buf);
+ buf = 0;
+ exit(1);
+ }
+
+ countRead += rv;
+ FPRINTF(stderr, "connection %d read %d bytes (%d total).\n",
+ connection, rv, countRead );
+ FPRINTF(stderr, "these bytes read:\n");
+ PR_Write(PR_STDOUT,buf,rv);
+
+ if (first) {
+ first=0;
+ if (rv < 13) {
+ int ret = 0;
+ buf2 = PR_Malloc(RD_BUF_SIZE);
+ if (!buf2) {
+ PR_Free(buf);
+ buf = 0;
+ exit(5);
+ }
+
+ for (ret=0; rv < 13 ; rv += ret) {
+ ret = PR_Read(ssl_sock, buf2, RD_BUF_SIZE - rv);
+ if (ret < 0 ) {
+ errWarn("PR_Read");
+ PR_Free(buf);
+ buf = 0;
+ PR_Free(buf2);
+ buf2 = 0;
+ exit(1);
+ }
+ if (ret == 0) {
+ errWarn("not enough bytes read in first read");
+ PR_Free(buf);
+ buf = 0;
+ PR_Free(buf2);
+ buf2 = 0;
+ exit(2);
+ }
+ countRead += ret;
+ FPRINTF(stderr, "connection %d read %d bytes (%d total).\n",
+ connection, ret, countRead );
+ FPRINTF(stderr, "these bytes read:\n");
+ PR_Write(PR_STDOUT, buf2, ret);
+
+ PR_snprintf(buf, RD_BUF_SIZE, "%s%s", buf, buf2);
+ }
+ PR_Free(buf2);
+ buf2 = 0;
+ }
+
+ if ( ! PL_strnstr(buf,"200",13)) {
+ PR_Free(buf);
+ buf = 0;
+ exit(3);
+ }
+ }
+ }
+ PR_fprintf(PR_STDOUT, "\n");
+
+ PR_Free(buf);
+ buf = 0;
+
+ /* Caller closes the socket. */
+
+ FPRINTF(stderr,
+ "connection %d read %d bytes total. -----------------------------\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+int
+do_connect(
+ PRNetAddr *addr,
+ PRFileDesc *model_sock,
+ int connection)
+{
+ PRFileDesc * ssl_sock;
+ PRFileDesc * tcp_sock;
+ PRStatus prStatus;
+ SECStatus result;
+ int rv = SECSuccess;
+ PRSocketOptionData opt;
+
+ int family = PR_NetAddrFamily( addr );
+
+ tcp_sock = PR_OpenTCPSocket( family );
+ if (tcp_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ /* Don't return SECFailure? */
+ return SECSuccess;
+ }
+
+ prStatus = PR_Connect(tcp_sock, addr, PR_SecondsToInterval(3));
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(6);
+ }
+
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ /* XXX if this import fails, close tcp_sock and return. */
+ if (!ssl_sock) {
+ if( tcp_sock != NULL ) {
+ PR_Close(tcp_sock);
+ tcp_sock = NULL;
+ }
+ exit(7);
+ }
+
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ exit(8);
+ }
+
+ result = do_io( ssl_sock, connection);
+
+ if( ssl_sock != NULL ) {
+ PR_Close(ssl_sock);
+ ssl_sock = NULL;
+ }
+ return SECSuccess;
+}
+
+/* Returns IP address for hostname as PRUint32 in Host Byte Order.
+** Since the value returned is an integer (not a string of bytes),
+** it is inherently in Host Byte Order.
+*/
+PRUint32
+getIPAddress(const char * hostName)
+{
+ const unsigned char *p;
+ PRStatus prStatus;
+ PRUint32 rv;
+ PRHostEnt prHostEnt;
+ char scratch[PR_NETDB_BUF_SIZE];
+
+ prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_GetHostByName");
+
+#undef h_addr
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+
+ p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
+ FPRINTF(stderr, "%s -> %d.%d.%d.%d\n", hostName, p[0], p[1], p[2], p[3]);
+ rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return rv;
+}
+
+void
+client_main(
+ unsigned short port,
+ int connections,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert,
+ const char * hostName,
+ char * nickName)
+{
+ PRFileDesc *model_sock = NULL;
+ int rv;
+
+
+ FPRINTF(stderr, "port: %d\n", port);
+
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+
+ /* enable FIPS ciphers */
+ SSL_CipherPrefSetDefault(0xc004 /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc003 /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xC005 /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc00a /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x2f /* TLS_RSA_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x35 /* TLS_RSA_WITH_AES_256_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc008 /* TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc009 /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc012 /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc013 /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0xc014 /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x32 /* TLS_DHE_DSS_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x38 /* TLS_DHE_DSS_WITH_AES_256_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x33 /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA */, PR_TRUE);
+ SSL_CipherPrefSetDefault(0x39 /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA */, PR_TRUE);
+
+ /*
+ * Rifle through the values for the host
+ */
+
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+ int family = PR_AF_INET;
+
+ ai = PR_GetAddrInfoByName(hostName, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (ai) {
+ FPRINTF( stderr, "addr='%s'\n", PR_GetCanonNameFromAddrInfo( ai ) );
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ family = PR_NetAddrFamily(&addr);
+ FPRINTF( stderr, "family='%d'\n", family );
+ break;
+ }
+ PR_FreeAddrInfo(ai);
+ }
+
+ PR_SetNetAddr( PR_IpAddrNull, family, port, &addr );
+
+ model_sock = PR_OpenTCPSocket( family );
+ if (model_sock == NULL) {
+ errExit("PR_OpenTCPSocket on tcp socket");
+ }
+
+ /* Should we really be re-using the same socket? */
+ model_sock = SSL_ImportFD(NULL, model_sock);
+
+
+ /* check on success of call to SSL_ImportFD() */
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+
+ /* enable ECC cipher also */
+
+ /* do SSL configuration. */
+
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ if (rv < 0) {
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ if( nickName) {
+ SSL_GetClientAuthDataHook(model_sock,
+ (SSLGetClientAuthData)my_GetClientAuthData,
+ nickName);
+ }
+
+ /* I'm not going to set the HandshakeCallback function. */
+
+ /* end of ssl configuration. */
+
+ rv = do_connect(&addr, model_sock, 1);
+
+ if( model_sock != NULL ) {
+ PR_Close( model_sock );
+ model_sock = NULL;
+ }
+}
+
+
+SECStatus
+createRequest(char * url, char *post)
+{
+ char * newstr;
+
+ if (post == NULL) {
+ newstr = PR_smprintf(
+ "GET %s HTTP/1.0\r\n\r\n",
+ url);
+ } else {
+ int len = strlen(post);
+ newstr = PR_smprintf(
+ "POST %s HTTP/1.0\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s", url, len, post);
+ }
+
+ bigBuf.data = (unsigned char *)newstr;
+
+ FPUTS((char *)bigBuf.data, stderr);
+
+ bigBuf.len = PORT_Strlen((char *)bigBuf.data);
+
+ return SECSuccess;
+}
+
+int
+main(int argc, char **argv)
+{
+ char * dir = ".";
+ char * hostName = NULL;
+ char * nickName = NULL;
+ char * progName = NULL;
+ char * tmp = NULL;
+ char * post = NULL;
+ CERTCertificate * cert [kt_kea_size] = { NULL };
+ SECKEYPrivateKey * privKey[kt_kea_size] = { NULL };
+ int optchar;
+ int connections = 1;
+ int tmpI;
+ unsigned short port = 443;
+ SECStatus rv;
+ char * passwd = NULL;
+ char * passwdfile = NULL;
+ char * url = NULL;
+ FILE *fp;
+ char pwbuf[256];
+ int co;
+ char *crlf;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+
+ while ((optchar = getopt(argc, argv, "Vd:e:n:p:r:w:v")) != -1) {
+ switch(optchar) {
+
+/* Version */
+ case 'V':
+ printf("%s\n",VERSIONSTRING);
+ PR_Cleanup();
+ return 0;
+
+/* Directory which holds cert8.db and key3.db */
+ case 'd':
+ dir = optarg;
+ break;
+
+/* Nickname of certificate to use */
+ case 'n':
+ nickName = optarg;
+ break;
+
+/* password to open key3.db */
+ case 'p':
+ passwd = optarg;
+ break;
+
+/* name of file holding password for key3.db */
+ case 'w':
+ passwdfile = optarg;
+ break;
+
+/* url */
+ case 'r':
+ url = optarg;
+ break;
+
+/* post parameters */
+ case 'e':
+ post = optarg;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ default:
+ case '?':
+ fprintf( stderr, "ERROR: Invalid option!\n" );
+ Usage(progName);
+ break;
+
+ }
+ }
+
+ if (optind != argc - 1) {
+ fprintf( stderr, "ERROR: Invalid number of arguments!\n" );
+ Usage(progName);
+ }
+
+ hostName = argv[optind];
+ tmp = strchr(hostName, ':');
+ if (tmp) {
+ *tmp++ = 0;
+ tmpI = atoi(tmp);
+ if (tmpI <= 0) {
+ fprintf( stderr, "ERROR: Invalid port!\n" );
+ Usage(progName);
+ }
+ port = (unsigned short)tmpI;
+ }
+
+ if ( !url) {
+ fprintf( stderr, "ERROR: Invalid url!\n" );
+ Usage(progName);
+ }
+
+ createRequest(url, post);
+
+ if (passwdfile) {
+ fp = fopen(passwdfile,"r");
+ if (!fp) { fprintf(stderr, "Couldn't open password file\n"); exit(7); }
+ co = fread(pwbuf,1,256,fp);
+ pwbuf[co] = '\0';
+ crlf = PL_strchr(pwbuf,'\n');
+ if (crlf) {
+ *crlf = '\0';
+ }
+ passwd = pwbuf;
+ }
+
+ /* set our password function */
+ if (passwd == NULL) {
+ fprintf( stderr, "ERROR: Invalid password!\n" );
+ PRINTF("Password must be provided on command line in this version of revoker.\n");
+ Usage(progName);
+ }
+ PK11_SetPasswordFunc(ownPasswd);
+
+ /* Call the libsec initialization routines */
+ rv = NSS_Init(dir);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(1);
+ }
+
+ if(nickName) {
+ cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
+ if (cert[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find certificate %s\n", nickName);
+ exit(1);
+ }
+
+ privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
+ if (privKey[kt_rsa] == NULL) {
+ fprintf(stderr, "Can't find Private Key for cert %s (possibly incorrect password)\n", nickName);
+ exit(1);
+ }
+ }
+
+ client_main(port, connections, privKey, cert, hostName, nickName);
+
+ NSS_Shutdown();
+ PR_Cleanup();
+ return 0;
+}
+
diff --git a/base/native-tools/src/tkstool/CMakeLists.txt b/base/native-tools/src/tkstool/CMakeLists.txt
new file mode 100644
index 000000000..8b07950eb
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/NSPRerrs.h b/base/native-tools/src/tkstool/NSPRerrs.h
new file mode 100644
index 000000000..f0bc8b77e
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/SECerrs.h b/base/native-tools/src/tkstool/SECerrs.h
new file mode 100644
index 000000000..55858b98f
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/SSLerrs.h b/base/native-tools/src/tkstool/SSLerrs.h
new file mode 100644
index 000000000..d6ec13b47
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/delete.c b/base/native-tools/src/tkstool/delete.c
new file mode 100644
index 000000000..f40e66d16
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/file.c b/base/native-tools/src/tkstool/file.c
new file mode 100644
index 000000000..d757225fc
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/find.c b/base/native-tools/src/tkstool/find.c
new file mode 100644
index 000000000..8926d5cbb
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/help.c b/base/native-tools/src/tkstool/help.c
new file mode 100644
index 000000000..97c724459
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/key.c b/base/native-tools/src/tkstool/key.c
new file mode 100644
index 000000000..4fd37963b
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/list.c b/base/native-tools/src/tkstool/list.c
new file mode 100644
index 000000000..44173fa36
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/modules.c b/base/native-tools/src/tkstool/modules.c
new file mode 100644
index 000000000..0c4297251
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/pppolicy.c b/base/native-tools/src/tkstool/pppolicy.c
new file mode 100644
index 000000000..8b198ca52
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/random.c b/base/native-tools/src/tkstool/random.c
new file mode 100644
index 000000000..49dfb525e
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/retrieve.c b/base/native-tools/src/tkstool/retrieve.c
new file mode 100644
index 000000000..44cf3c069
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/secerror.c b/base/native-tools/src/tkstool/secerror.c
new file mode 100644
index 000000000..6b0f40d70
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/secpwd.c b/base/native-tools/src/tkstool/secpwd.c
new file mode 100644
index 000000000..542885858
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/secutil.c b/base/native-tools/src/tkstool/secutil.c
new file mode 100644
index 000000000..9ece007fa
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/secutil.h b/base/native-tools/src/tkstool/secutil.h
new file mode 100644
index 000000000..a2f065067
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/tkstool.c b/base/native-tools/src/tkstool/tkstool.c
new file mode 100644
index 000000000..5368b2e7b
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/tkstool.h b/base/native-tools/src/tkstool/tkstool.h
new file mode 100644
index 000000000..3b0407227
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/util.c b/base/native-tools/src/tkstool/util.c
new file mode 100644
index 000000000..5fda75f8e
--- /dev/null
+++ b/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/base/native-tools/src/tkstool/version.c b/base/native-tools/src/tkstool/version.c
new file mode 100644
index 000000000..b8d4c5fbb
--- /dev/null
+++ b/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
+}
+