summaryrefslogtreecommitdiffstats
path: root/base/symkey
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/symkey
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/symkey')
-rw-r--r--base/symkey/CMakeLists.txt4
-rw-r--r--base/symkey/LICENSE291
-rw-r--r--base/symkey/src/CMakeLists.txt24
-rw-r--r--base/symkey/src/com/netscape/symkey/Base.h44
-rw-r--r--base/symkey/src/com/netscape/symkey/Buffer.cpp183
-rw-r--r--base/symkey/src/com/netscape/symkey/Buffer.h173
-rw-r--r--base/symkey/src/com/netscape/symkey/CMakeLists.txt63
-rw-r--r--base/symkey/src/com/netscape/symkey/EncryptData.cpp250
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.cpp2005
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.java167
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.cpp1407
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.h55
12 files changed, 4666 insertions, 0 deletions
diff --git a/base/symkey/CMakeLists.txt b/base/symkey/CMakeLists.txt
new file mode 100644
index 000000000..e994c0721
--- /dev/null
+++ b/base/symkey/CMakeLists.txt
@@ -0,0 +1,4 @@
+project(symkey)
+
+add_subdirectory(src)
+add_subdirectory(src/com/netscape/symkey)
diff --git a/base/symkey/LICENSE b/base/symkey/LICENSE
new file mode 100644
index 000000000..fbd2b7ff4
--- /dev/null
+++ b/base/symkey/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/symkey/src/CMakeLists.txt b/base/symkey/src/CMakeLists.txt
new file mode 100644
index 000000000..599a7cb5a
--- /dev/null
+++ b/base/symkey/src/CMakeLists.txt
@@ -0,0 +1,24 @@
+project(symkey Java)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+set(symkey_java_SRCS
+ com/netscape/symkey/SessionKey.java
+)
+
+set(CMAKE_JNI_TARGET TRUE)
+set(CMAKE_JAVA_INCLUDE_PATH ${JSS_JAR})
+set(CMAKE_JAVA_TARGET_VERSION ${APPLICATION_VERSION})
+
+add_jar(symkey ${symkey_java_SRCS})
+install_jar(symkey ${LIB_INSTALL_DIR}/symkey)
+install_jni_symlink(symkey ${JAVA_LIB_INSTALL_DIR})
+
+set(SYMKEY_JAVA_OBJECT_DIR ${symkey_CLASS_DIR} PARENT_SCOPE)
+set(SYMKEY_JAR ${symkey_JAR_FILE} CACHE INTERNAL "symkey jar file")
diff --git a/base/symkey/src/com/netscape/symkey/Base.h b/base/symkey/src/com/netscape/symkey/Base.h
new file mode 100644
index 000000000..cdcf72bcf
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/Base.h
@@ -0,0 +1,44 @@
+// --- 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifndef BASE_H
+#define BASE_H
+#include <nspr.h>
+
+typedef unsigned char BYTE;
+
+enum nsNKeyMsgEnum {
+ VRFY_FAILURE,
+ VRFY_SUCCESS,
+ ENCODE_DER_PUBKEY_FAILURE,
+ B64ENCODE_FAILURE,
+ VFY_BEGIN_FAILURE,
+ VFY_UPDATE_FAILURE,
+ HTTP_REQ_EXE_FAILURE,
+ HTTP_ERROR_RCVD,
+ BASE64_DECODE_FAILURE,
+ REQ_TO_CA_SUCCESS,
+ MSG_INVALID
+};
+
+struct ReturnStatus {
+ PRStatus status;
+ nsNKeyMsgEnum statusNum;
+};
+
+#endif /* BASE_H */
diff --git a/base/symkey/src/com/netscape/symkey/Buffer.cpp b/base/symkey/src/com/netscape/symkey/Buffer.cpp
new file mode 100644
index 000000000..5c687c5f5
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/Buffer.cpp
@@ -0,0 +1,183 @@
+// --- 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <cstdarg>
+#include <string>
+
+#include "Buffer.h"
+
+Buffer::Buffer(const BYTE *buf_, unsigned int len_) : len(len_), res(len_)
+{
+ buf = new BYTE[len];
+ memcpy(buf, buf_, len);
+}
+
+Buffer::Buffer(const Buffer& cpy)
+{
+ buf = 0;
+ *this = cpy;
+}
+
+Buffer::Buffer(unsigned int len_) : len(len_), res(len_)
+{
+ buf = new BYTE[res];
+ memset(buf, 0, len_);
+}
+
+Buffer::Buffer(unsigned int len_, BYTE b) : len(len_), res(len_)
+{
+ buf = new BYTE[res];
+ memset(buf, b, len);
+}
+
+Buffer::~Buffer()
+{
+ delete [] buf;
+}
+
+bool
+Buffer::operator==(const Buffer& cmp) const
+{
+ if( len != cmp.len ) return false;
+ for( unsigned int i=0; i < len; ++i ) {
+ if( buf[i] != cmp.buf[i] ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+Buffer&
+Buffer::operator=(const Buffer& cpy)
+{
+ if( this == &cpy ) return *this;
+ len = cpy.len;
+ delete [] buf;
+ buf = new BYTE[len];
+ memcpy(buf, cpy.buf, len);
+ res = len;
+
+ return *this;
+}
+
+void
+Buffer::zeroize()
+{
+ if( len > 0 ) {
+ memset( buf, 0, len );
+ }
+}
+
+Buffer
+Buffer::operator+(const Buffer& addend) const
+{
+ Buffer result(len + addend.len);
+ memcpy(result.buf, buf, len);
+ memcpy(result.buf+len, addend.buf, addend.len);
+ return result;
+}
+
+Buffer&
+Buffer::operator+=(const Buffer& addend)
+{
+ unsigned int oldLen = len;
+ resize(len + addend.len);
+ memcpy(buf+oldLen, addend.buf, addend.len);
+ return *this;
+}
+
+Buffer&
+Buffer::operator+=(BYTE b)
+{
+ resize(len+1);
+ buf[len-1] = b;
+ return *this;
+}
+
+void
+Buffer::reserve(unsigned int n)
+{
+ if( n > res ) {
+ BYTE *newBuf = new BYTE[n];
+ memcpy(newBuf, buf, len);
+ delete [] buf;
+ buf = newBuf;
+ res = n;
+ }
+}
+
+void
+Buffer::resize(unsigned int newLen)
+{
+ if( newLen == len ) {
+ return;
+ } else if( newLen < len ) {
+ len = newLen;
+ } else if( newLen <= res ) {
+ assert( newLen > len );
+ memset(buf+len, 0, newLen-len);
+ len = newLen;
+ } else {
+ assert( newLen > len && newLen > res );
+ BYTE *newBuf = new BYTE[newLen];
+ memcpy(newBuf, buf, len);
+ memset(newBuf+len, 0, newLen-len);
+ delete [] buf;
+ buf = newBuf;
+ len = newLen;
+ res = newLen;
+ }
+}
+
+Buffer
+Buffer::substr(unsigned int i, unsigned int n) const
+{
+ assert( i < len && (i+n) <= len );
+ return Buffer( buf+i, n );
+}
+
+void
+Buffer::replace(unsigned int i, const BYTE* cpy, unsigned int n)
+{
+ if (len > i+n) {
+ resize( len);
+ }else {
+ resize( i+n );
+ }
+ memcpy(buf+i, cpy, n);
+}
+
+void
+Buffer::dump() const
+{
+ unsigned int i;
+
+ for( i=0; i < len; ++i ) {
+ printf("%02x ", buf[i]);
+ if( i % 16 == 15 ) printf("\n");
+ }
+ printf("\n");
+}
+
+static const char hextbl[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
diff --git a/base/symkey/src/com/netscape/symkey/Buffer.h b/base/symkey/src/com/netscape/symkey/Buffer.h
new file mode 100644
index 000000000..2e0256d87
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/Buffer.h
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include <stdio.h>
+#include "Base.h"
+
+/**
+ * This class represents a byte array.
+ */
+class Buffer {
+
+ private:
+ BYTE *buf;
+ unsigned int len;
+ unsigned int res;
+
+ public:
+ /**
+ * Creates an empty Buffer.
+ */
+ Buffer() : buf(0), len(0), res(0) { }
+
+ /**
+ * Creates a Buffer of length 'len', with each byte initialized to 'b'.
+ */
+ Buffer(unsigned int len, BYTE b);
+
+ /**
+ * Creates a Buffer of length 'len', initialized to zeroes.
+ */
+ explicit Buffer(unsigned int len);
+
+ /**
+ * Creates a Buffer of length 'len', initialized from 'buf'. 'buf' must
+ * contain at least 'len' bytes.
+ */
+ Buffer(const BYTE* buf, unsigned int len);
+
+ /**
+ * Copy constructor.
+ */
+ Buffer(const Buffer& cpy);
+
+ /**
+ * Destructor.
+ */
+ ~Buffer();
+
+ /**
+ * Assignment operator.
+ */
+ Buffer& operator=(const Buffer& cpy);
+
+ /**
+ * Returns true if the two buffers are the same length and contain
+ * the same byte at each offset.
+ */
+ bool operator==(const Buffer& cmp) const;
+
+ /**
+ * Returns ! operator==(cmp).
+ */
+ bool operator!=(const Buffer& cmp) const { return ! (*this == cmp); }
+
+ /**
+ * Concatenation operator.
+ */
+ Buffer operator+(const Buffer&addend) const;
+
+ /**
+ * Append operators.
+ */
+ Buffer& operator+=(const Buffer&addend);
+ Buffer& operator+=(BYTE b);
+
+ /**
+ * Returns a pointer into the Buffer. This also enables the subscript
+ * operator, so you can say, for example, 'buf[4] = b' or 'b = buf[4]'.
+ */
+ operator BYTE*() { return buf; }
+ operator const BYTE*() const { return buf; }
+
+ /**
+ * The length of buffer. The actual amount of space allocated may be
+ * higher--see capacity().
+ */
+ unsigned int size() const { return len; }
+
+ /**
+ * The amount of memory allocated for the buffer. This is the maximum
+ * size the buffer can grow before it needs to allocate more memory.
+ */
+ unsigned int capacity() const { return res; }
+
+ /**
+ * Sets all bytes in the buffer to 0.
+ */
+ void zeroize();
+
+ /**
+ * Changes the length of the Buffer. If 'newLen' is shorter than the
+ * current length, the Buffer is truncated. If 'newLen' is longer, the
+ * new bytes are initialized to 0. If 'newLen' is the same as size(),
+ * this is a no-op.
+ */
+ void resize(unsigned int newLen);
+
+ /**
+ * Ensures that capacity() is at least 'reserve'. Allocates more memory
+ * if necessary. If 'reserve' is <= capacity(), this is a no-op.
+ * Does not affect size().
+ */
+ void reserve(unsigned int reserve);
+
+ /**
+ * Returns a new Buffer that is a substring of this Buffer, starting
+ * from offset 'start' and continuing for 'len' bytes. This Buffer
+ * must have size() >= (start + len).
+ */
+ Buffer substr(unsigned int start, unsigned int len) const;
+
+ /**
+ * Replaces bytes i through i+n in this Buffer using the values in 'cpy'.
+ * This Buffer is resized if necessary. The 'cpy' argument can be a
+ * Buffer.
+ */
+ void replace(unsigned int i, const BYTE* cpy, unsigned int n);
+
+ /**
+ * returns a hex version of the buffer
+ */
+ char *toHex();
+
+ /**
+ * Dumps this Buffer to the given file as formatted hex: 16 bytes per
+ * line, separated by spaces.
+ */
+ void dump(FILE* file) const;
+
+ /**
+ * returns a null-terminated string of the buf.
+ * should be called only by callers that are certain that buf
+ * is entirely representable by printable characters and wants
+ * a string instead.
+ */
+ char *string();
+
+ /**
+ * dump()s this Buffer to stdout.
+ */
+ void dump() const;
+
+};
+
+#endif
diff --git a/base/symkey/src/com/netscape/symkey/CMakeLists.txt b/base/symkey/src/com/netscape/symkey/CMakeLists.txt
new file mode 100644
index 000000000..47d40a3f1
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/CMakeLists.txt
@@ -0,0 +1,63 @@
+project(symkey_library CXX)
+
+set(SYMKEY_PUBLIC_INCLUDE_DIRS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ CACHE INTERNAL "symkey public include directories"
+)
+
+set(SYMKEY_PRIVATE_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${JNI_INCLUDE_DIRS}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(SYMKEY_SHARED_LIBRARY
+ symkey_library
+ CACHE INTERNAL "symkey shared library"
+)
+
+set(SYMKEY_LINK_LIBRARIES
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(symkey_library_HDRS
+ SessionKey.h
+)
+
+set(symkey_library_SRCS
+ Buffer.cpp
+ EncryptData.cpp
+ SessionKey.cpp
+ SymKey.cpp
+)
+
+include_directories(${SYMKEY_PRIVATE_INCLUDE_DIRS})
+
+add_custom_command(
+ OUTPUT
+ ${symkey_library_HDRS}
+ COMMAND
+ ${JAVA_HEADER}
+ -classpath ${SYMKEY_JAVA_OBJECT_DIR}:${JAVA_LIB_INSTALL_DIR}/jss4.jar
+ -jni -d ${CMAKE_CURRENT_BINARY_DIR}
+ com.netscape.symkey.SessionKey
+)
+
+add_library(${SYMKEY_SHARED_LIBRARY} SHARED ${symkey_library_HDRS} ${symkey_library_SRCS})
+target_link_libraries(${SYMKEY_SHARED_LIBRARY} ${SYMKEY_LINK_LIBRARIES})
+add_dependencies(${SYMKEY_SHARED_LIBRARY} symkey)
+
+set_target_properties(${SYMKEY_SHARED_LIBRARY}
+ PROPERTIES
+ OUTPUT_NAME
+ symkey
+)
+
+install(
+ TARGETS
+ ${SYMKEY_SHARED_LIBRARY}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}/symkey
+)
diff --git a/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
new file mode 100644
index 000000000..ccb817f7c
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
@@ -0,0 +1,250 @@
+// --- 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "pk11func.h"
+#include "nspr.h"
+#ifdef __cplusplus
+#include <jni.h>
+#include <assert.h>
+#include <string.h>
+
+}
+#endif
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <cstdarg>
+#include <string>
+#include <stdlib.h>
+#include "Buffer.h"
+#include "SymKey.h"
+#define DES2_WORKAROUND
+
+PRFileDesc *d = NULL;
+
+void GetKeyName(jbyte *keyVersion, char *keyname)
+{
+ int index=0;
+
+ if( !keyname || !keyVersion ||
+ (strlen(keyname) < KEYNAMELENGTH)) {
+ return;
+ }
+
+ if(strlen(masterKeyPrefix)!=0)
+ {
+ index= strlen(masterKeyPrefix);
+ strcpy(keyname,masterKeyPrefix);
+ }
+
+ if( (index + 3) >= KEYNAMELENGTH) {
+ return;
+ }
+
+ keyname[index+0]='#';
+ sprintf(keyname+index+1,"%.2d", keyVersion[0]);
+ keyname[index+3]='#';
+ sprintf(keyname+index+4,"%.2d", keyVersion[1]);
+}
+
+
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_EncryptData
+(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+
+extern "C" JNIEXPORT jbyteArray JNICALL
+Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstring j_tokenName, jstring j_keyName, jbyteArray j_in, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s,jstring keySet)
+{
+ jbyte * kek_key = NULL;
+
+ PK11SymKey *masterKey = NULL;
+ PK11SymKey *kekKey = NULL;
+
+ Buffer out = Buffer(KEYLENGTH, (BYTE)0);
+ BYTE kekData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+
+ int status = PR_FAILURE;
+
+ jbyte *cc = NULL;
+ int cc_len = 0;
+ jbyte * cuidValue = NULL;
+
+ if( kekKeyArray != NULL) {
+ kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ PK11SlotInfo *slot = NULL;
+ PK11SlotInfo *internal = PK11_GetInternalKeySlot();
+
+ Buffer kek_buffer = Buffer((BYTE*)kek_key, KEYLENGTH);
+ char *keySetStringChars = NULL;
+ if( keySet != NULL) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ) {
+ goto done;
+ }
+
+ if( CUID != NULL) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ if( j_in != NULL) {
+ cc = (jbyte*)(env)->GetByteArrayElements( j_in, NULL);
+ cc_len = (env)->GetArrayLength(j_in);
+ }
+
+ if( cc == NULL) {
+ goto done;
+ }
+
+ GetDiversificationData(cuidValue,kekData,kek);
+
+ PR_fprintf(PR_STDOUT,"In SessionKey: EncryptData! \n");
+
+ if(j_tokenName != NULL) {
+ char *tokenNameChars = (char *)(env)->GetStringUTFChars(j_tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(j_tokenName, (const char *)tokenNameChars);
+ tokenNameChars = NULL;
+ }
+
+ if(j_keyName != NULL) {
+ char *keyNameChars= (char *)(env)->GetStringUTFChars(j_keyName, NULL);
+ strcpy(keyname,keyNameChars);
+ env->ReleaseStringUTFChars(j_keyName, (const char *)keyNameChars);
+ keyNameChars = NULL;
+ }
+ else {
+ GetKeyName(keyVersion,keyname);
+ }
+
+ if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) ||
+ (keyVersion[0] == -1 && strstr(keyname, "#FF") ))
+ {
+ /* default development keyset */
+ Buffer devInput = Buffer((BYTE*)cc, cc_len);
+ Buffer empty = Buffer();
+
+ kekKey = ReturnDeveloperSymKey( internal, (char *) "kek", keySetString, empty);
+
+ if ( kekKey ) {
+ status = EncryptData(Buffer(),kekKey,devInput, out);
+ } else {
+ status = EncryptData(kek_buffer, NULL, devInput, out);
+ }
+ }
+ else
+ {
+ if (slot!=NULL)
+ {
+ masterKey = ReturnSymKey( slot,keyname);
+
+ /* We need to use internal so that the key
+ * can be exported by using PK11_GetKeyData()
+ */
+ if (masterKey != NULL)
+ {
+ kekKey = ComputeCardKeyOnToken(masterKey,kekData);
+ if (kekKey != NULL)
+ {
+ Buffer input = Buffer((BYTE*)cc, cc_len);
+ status = EncryptData(Buffer(), kekKey, input, out);
+ }
+ }
+ }
+ }
+
+done:
+
+ if (masterKey != NULL) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( slot != NULL ) {
+ PK11_FreeSlot( slot);
+ slot = NULL;
+ }
+
+ if( internal != NULL) {
+ PK11_FreeSlot( internal);
+ internal = NULL;
+ }
+
+ if ( kekKey != NULL) {
+ PK11_FreeSymKey( kekKey);
+ kekKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ jbyteArray handleBA=NULL;
+ if (status != PR_FAILURE && (out.size()>0) ) {
+ jbyte *handleBytes=NULL;
+ handleBA = (env)->NewByteArray( out.size());
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+ BYTE* outp = (BYTE*)out;
+ memcpy(handleBytes, outp,out.size());
+ env->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ handleBytes=NULL;
+ }
+
+ if( cc != NULL) {
+ env->ReleaseByteArrayElements(j_in, cc, JNI_ABORT);
+ }
+
+ if( keyVersion != NULL) {
+ env->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if( cuidValue != NULL) {
+ env->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ return handleBA;
+}
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.cpp b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
new file mode 100644
index 000000000..eb412f01a
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
@@ -0,0 +1,2005 @@
+
+// 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "pk11func.h"
+#include "seccomon.h"
+#include "nspr.h"
+#ifdef __cplusplus
+#include <jni.h>
+#include <assert.h>
+#include <string.h>
+#include "secerr.h"
+
+/*
+#include <jss_exceptions.h>
+#include <jssutil.h>
+*/
+
+}
+#endif
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <cstdarg>
+#include <string>
+
+// DRM_PROTO begins
+#define PK11SYMKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11SymKey"
+#define PK11SYMKEY_CONSTRUCTOR_SIG "([B)V"
+#define ALL_SYMKEY_OPS (CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP)
+// DRM_PROTO ends
+
+#include "Buffer.h"
+#include "SymKey.h"
+
+#define STEAL_JSS
+#ifdef STEAL_JSS
+// stealing code from JSS to handle DRM support
+/*
+ * NativeProxy
+ */
+#define NATIVE_PROXY_CLASS_NAME "org/mozilla/jss/util/NativeProxy"
+#define NATIVE_PROXY_POINTER_FIELD "mPointer"
+#define NATIVE_PROXY_POINTER_SIG "[B"
+
+/*
+ * SymKeyProxy
+ */
+#define SYM_KEY_PROXY_FIELD "keyProxy"
+#define SYM_KEY_PROXY_SIG "Lorg/mozilla/jss/pkcs11/SymKeyProxy;"
+
+
+/***********************************************************************
+ **
+ ** J S S _ p t r T o B y t e A r r a y
+ **
+ ** Turn a C pointer into a Java byte array. The byte array can be passed
+ ** into a NativeProxy constructor.
+ **
+ ** Returns a byte array containing the pointer, or NULL if an exception
+ ** was thrown.
+ */
+jbyteArray
+JSS_ptrToByteArray(JNIEnv *env, void *ptr)
+{
+ jbyteArray byteArray;
+
+ /* Construct byte array from the pointer */
+ byteArray = (env)->NewByteArray(sizeof(ptr));
+ if(byteArray==NULL)
+ {
+ PR_ASSERT( (env)->ExceptionOccurred() != NULL);
+ return NULL;
+ }
+ (env)->SetByteArrayRegion(byteArray, 0, sizeof(ptr), (jbyte*)&ptr);
+ if((env)->ExceptionOccurred() != NULL)
+ {
+ PR_ASSERT(PR_FALSE);
+ return NULL;
+ }
+ return byteArray;
+}
+
+
+/***********************************************************************
+ *
+ * J S S _ P K 1 1 _ w r a p S y m K e y
+
+ * Puts a Symmetric Key into a Java object.
+ * (Does NOT perform a cryptographic "wrap" operation.)
+ * symKey: will be stored in a Java wrapper.
+ * Returns: a new PK11SymKey, or NULL if an exception occurred.
+ */
+jobject
+JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey)
+{
+// return JSS_PK11_wrapSymKey(env, symKey, NULL);
+// hmmm, looks like I may not need to steal code after all
+ return JSS_PK11_wrapSymKey(env, symKey);
+}
+
+
+jobject
+JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey, PRFileDesc *debug_fd)
+{
+ jclass keyClass;
+ jmethodID constructor;
+ jbyteArray ptrArray;
+ jobject Key=NULL;
+
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey\n");
+
+ PR_ASSERT(env!=NULL && symKey!=NULL && *symKey!=NULL);
+
+ /* find the class */
+ keyClass = (env)->FindClass(PK11SYMKEY_CLASS_NAME);
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey called FindClass\n");
+ if( keyClass == NULL )
+ {
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey FindClass NULL\n");
+// ASSERT_OUTOFMEM(env);
+ goto finish;
+ }
+
+ /* find the constructor */
+ constructor = (env)->GetMethodID(keyClass,
+ "<init>"/*PLAIN_CONSTRUCTOR*/,
+ PK11SYMKEY_CONSTRUCTOR_SIG);
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey called GetMethodID\n");
+ if(constructor == NULL)
+ {
+// ASSERT_OUTOFMEM(env);
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey GetMethodID returns NULL\n");
+ goto finish;
+ }
+
+ /* convert the pointer to a byte array */
+ ptrArray = JSS_ptrToByteArray(env, (void*)*symKey);
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey called JSS_ptrToByteArray\n");
+ if( ptrArray == NULL )
+ {
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey JSS_ptrToByteArray returns NULL\n");
+ goto finish;
+ }
+
+ /* call the constructor */
+ Key = (env)->NewObject( keyClass, constructor, ptrArray);
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey called NewObject\n");
+
+finish:
+ if(Key == NULL)
+ {
+ if (debug_fd)
+ PR_fprintf(debug_fd, "DRMproto in JSS_PK11_wrapSymKey NewObject returns NULL\n");
+ PK11_FreeSymKey(*symKey);
+ }
+ *symKey = NULL;
+ return Key;
+}
+
+
+/***********************************************************************
+ **
+ ** J S S _ g e t P t r F r o m P r o x y
+ **
+ ** Given a NativeProxy, extract the pointer and store it at the given
+ ** address.
+ **
+ ** nativeProxy: a JNI reference to a NativeProxy.
+ ** ptr: address of a void* that will receive the pointer extracted from
+ ** the NativeProxy.
+ ** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown.
+ **
+ ** Example:
+ ** DataStructure *recovered;
+ ** jobject proxy;
+ ** JNIEnv *env;
+ ** [...]
+ ** if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) {
+ ** return; // exception was thrown!
+ ** }
+ */
+PRStatus
+JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr)
+{
+#ifdef DEBUG
+ jclass nativeProxyClass;
+#endif
+ jclass proxyClass;
+ jfieldID byteArrayField;
+ jbyteArray byteArray;
+ int size;
+
+ PR_ASSERT(env!=NULL && nativeProxy != NULL && ptr != NULL);
+ if( nativeProxy == NULL )
+ {
+// JSS_throw(env, NULL_POINTER_EXCEPTION);
+ return PR_FAILURE;
+ }
+
+ proxyClass = (env)->GetObjectClass(nativeProxy);
+ PR_ASSERT(proxyClass != NULL);
+
+#ifdef DEBUG
+ nativeProxyClass = (env)->FindClass(
+ NATIVE_PROXY_CLASS_NAME);
+ if(nativeProxyClass == NULL)
+ {
+// ASSERT_OUTOFMEM(env);
+ return PR_FAILURE;
+ }
+
+ /* make sure what we got was really a NativeProxy object */
+ PR_ASSERT( (env)->IsInstanceOf(nativeProxy, nativeProxyClass) );
+#endif
+
+ byteArrayField = (env)->GetFieldID(
+ proxyClass,
+ NATIVE_PROXY_POINTER_FIELD,
+ NATIVE_PROXY_POINTER_SIG);
+ if(byteArrayField==NULL)
+ {
+// ASSERT_OUTOFMEM(env);
+ return PR_FAILURE;
+ }
+
+ byteArray = (jbyteArray) (env)->GetObjectField(nativeProxy,
+ byteArrayField);
+ PR_ASSERT(byteArray != NULL);
+
+ size = sizeof(*ptr);
+ PR_ASSERT((env)->GetArrayLength( byteArray) == size);
+ (env)->GetByteArrayRegion(byteArray, 0, size, (jbyte*)ptr);
+ if( (env)->ExceptionOccurred() )
+ {
+ PR_ASSERT(PR_FALSE);
+ return PR_FAILURE;
+ }
+ else
+ {
+ return PR_SUCCESS;
+ }
+}
+
+
+/***********************************************************************
+ **
+ ** J S S _ g e t P t r F r o m P r o x y O w n e r
+ **
+ ** Given an object which contains a NativeProxy, extract the pointer
+ ** from the NativeProxy and store it at the given address.
+ **
+ ** proxyOwner: an object which contains a NativeProxy member.
+ ** proxyFieldName: the name of the NativeProxy member.
+ ** proxyFieldSig: the signature of the NativeProxy member.
+ ** ptr: address of a void* that will receive the extract pointer.
+ ** Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown.
+ **
+ ** Example:
+ ** <Java>
+ ** public class Owner {
+ ** protected MyProxy myProxy;
+ ** [...]
+ ** }
+ **
+ ** <C>
+ ** DataStructure *recovered;
+ ** jobject owner;
+ ** JNIEnv *env;
+ ** [...]
+ ** if(JSS_getPtrFromProxyOwner(env, owner, "myProxy", (void**)&recovered)
+ ** != PR_SUCCESS) {
+ ** return; // exception was thrown!
+ ** }
+ */
+PRStatus
+JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName,
+char *proxyFieldSig, void **ptr)
+{
+ jclass ownerClass;
+ jfieldID proxyField;
+ jobject proxyObject;
+
+ PR_ASSERT(env!=NULL && proxyOwner!=NULL && proxyFieldName!=NULL &&
+ ptr!=NULL);
+
+ /*
+ * Get proxy object
+ */
+ ownerClass = (env)->GetObjectClass(proxyOwner);
+ proxyField = (env)->GetFieldID(ownerClass, proxyFieldName,
+ proxyFieldSig);
+ if(proxyField == NULL)
+ {
+ return PR_FAILURE;
+ }
+ proxyObject = (env)->GetObjectField(proxyOwner, proxyField);
+ PR_ASSERT(proxyObject != NULL);
+
+ /*
+ * Get the pointer from the Native Reference object
+ */
+ return JSS_getPtrFromProxy(env, proxyObject, ptr);
+}
+
+
+/***********************************************************************
+ *
+ * J S S _ P K 1 1 _ g e t S y m K e y P t r
+ *
+ */
+PRStatus
+JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr)
+{
+ PR_ASSERT(env!=NULL && symKeyObject!=NULL);
+
+ /* Get the pointer from the key proxy */
+ return JSS_getPtrFromProxyOwner(env, symKeyObject, SYM_KEY_PROXY_FIELD,
+ SYM_KEY_PROXY_SIG, (void**)ptr);
+}
+#endif //STEAL_JSS
+// Function takes wither a symkey OR a keybuffer (for the default keyset case)
+// To derive a new key.
+PK11SymKey *DeriveKey(PK11SymKey *cardKey, const Buffer& hostChallenge, const Buffer& cardChallenge)
+{
+ PK11SymKey *key = NULL, *master = NULL;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11Context *context = NULL;
+ unsigned char derivationData[KEYLENGTH];
+#ifdef DES2_WORKAROUND
+ unsigned char keyData[DES3_LENGTH];
+#else
+ unsigned char keyData[KEYLENGTH];
+#endif
+ int i = 0;
+ SECStatus s = SECSuccess;
+ int len = 0;;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+
+ /* vars for PK11_Derive section */
+ SECItem param = { siBuffer, NULL, 0 };
+ CK_KEY_DERIVATION_STRING_DATA string;
+ PK11SymKey *tmp1 = NULL;
+ PK11SymKey *tmp2 = NULL;
+ PRBool invalid_mechanism = PR_FALSE;
+ CK_OBJECT_HANDLE keyhandle = 0;
+
+ PR_fprintf(PR_STDOUT,"In DeriveKey! \n");
+ master = cardKey;
+
+ if( ! master ) goto done;
+
+ for(i = 0;i < 4;i++)
+ {
+ derivationData[i] = cardChallenge[i+4];
+ derivationData[i+4] = hostChallenge[i];
+ derivationData[i+8] = cardChallenge[i];
+ derivationData[i+12] = hostChallenge[i+4];
+ }
+
+ string.pData = &derivationData[0];
+ string.ulLen = EIGHT_BYTES;
+ param.data = (unsigned char*)&string;
+ param.len = sizeof(string);
+
+ invalid_mechanism = PR_FALSE;
+
+ tmp1 = PK11_Derive( master , CKM_DES_ECB_ENCRYPT_DATA , &param , CKM_CONCATENATE_BASE_AND_KEY , CKA_DERIVE, 0);
+
+ if ( tmp1 == NULL) {
+ if ( PR_GetError() == SEC_ERROR_NO_TOKEN)
+ invalid_mechanism = PR_TRUE;
+
+ PR_fprintf(PR_STDERR,"DeriveKey: Can't create key, using encrypt and derive method ! error %d \n", PR_GetError());
+ } else {
+ PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created key using encrypt and derive method! \n");
+ }
+
+ if ( invalid_mechanism == PR_FALSE) {
+
+ string.pData = &derivationData[EIGHT_BYTES];
+ string.ulLen = EIGHT_BYTES;
+
+ tmp2 = PK11_Derive( master , CKM_DES_ECB_ENCRYPT_DATA , &param , CKM_CONCATENATE_BASE_AND_KEY , CKA_DERIVE , 0);
+
+ if ( tmp2 == NULL) {
+ PR_fprintf(PR_STDERR,"DeriveKey: Can't derive key using CONCATENATE method! \n");
+ goto done;
+ } else {
+ PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created key using CONCATENATE method! \n");
+ }
+
+ keyhandle = PK11_GetSymKeyHandle(tmp2);
+
+ param.data=(unsigned char *) &keyhandle;
+ param.len=sizeof(keyhandle);
+
+ key = PK11_Derive ( tmp1 , CKM_CONCATENATE_BASE_AND_KEY , &param ,CKM_DES3_ECB , CKA_DERIVE , 16);
+
+ if ( key == NULL) {
+ PR_fprintf(PR_STDERR,"DeriveKey: Can't create final derived key! \n");
+ goto done;
+ } else {
+ PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created final derived key! \n");
+ }
+
+ } else { /* We don't have access to the proper derive mechanism, use primitive mechanisms now */
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master,
+ &noParams);
+
+ if (!context) goto done;
+
+ s = PK11_CipherOp(context, &keyData[0], &len, EIGHT_BYTES, &derivationData[0], EIGHT_BYTES);
+ if (s != SECSuccess) goto done;
+
+ s = PK11_CipherOp(context, &keyData[EIGHT_BYTES], &len, 8, &derivationData[EIGHT_BYTES], EIGHT_BYTES);
+ if (s != SECSuccess) goto done;
+
+ for(i = 0;i < EIGHT_BYTES ;i++)
+ {
+ keyData[i+KEYLENGTH] = keyData[i];
+ }
+
+ key = CreateUnWrappedSymKeyOnToken( slot, master, &keyData[0] , DES3_LENGTH, PR_FALSE );
+
+ if ( key == NULL ) {
+ PR_fprintf(PR_STDERR,"DeriveKey: CreateUnWrappedSymKey failed! %d \n", PR_GetError());
+ } else {
+ PR_fprintf(PR_STDOUT,"DeriveKey: CreateUnWrappedSymKey succeeded! \n");
+ }
+ }
+
+ done:
+ memset(keyData, 0, sizeof keyData);
+ if ( context != NULL) {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+
+ if (slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if (tmp1) {
+ PK11_FreeSymKey(tmp1);
+ tmp1 = NULL;
+ }
+
+ if (tmp2) {
+ PK11_FreeSymKey(tmp2);
+ tmp2 = NULL;
+ }
+
+ return key;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeKeyCheck
+ (JNIEnv *, jclass, jobject deskeyObj);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jbyteArray JNICALL
+Java_com_netscape_symkey_SessionKey_ComputeKeyCheck
+(JNIEnv* env, jclass this2, jobject deskeyObj)
+{
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+
+ PK11SymKey *key = NULL;
+// PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11Context *context = NULL;
+ SECStatus s = SECFailure;
+ PRStatus r = PR_FAILURE;
+ int lenx = 0;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+
+ unsigned char value[EIGHT_BYTES];
+
+ memset(value, 0, sizeof value);
+
+ r = JSS_PK11_getSymKeyPtr(env, deskeyObj, &key);
+
+ if (r != PR_SUCCESS) {
+ goto finish;
+ }
+
+ if ( ! key ) {
+ goto finish;
+ }
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key,
+ &noParams);
+ if (!context) {
+ goto finish;
+ }
+
+ s = PK11_CipherOp(context, &value[0], &lenx, EIGHT_BYTES, &value[0], EIGHT_BYTES);
+ if (s != SECSuccess)
+ {
+ goto finish;
+ }
+ handleBA = (env)->NewByteArray(3);
+ if(handleBA == NULL ) {
+ goto finish;
+ }
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+ if(handleBytes==NULL) {
+ goto finish;
+ }
+ memcpy(handleBytes, value, 3);
+
+ if( handleBytes != NULL) {
+ (env)->ReleaseByteArrayElements(handleBA, handleBytes, 0);
+ }
+
+finish:
+
+ if ( context != NULL) {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+
+// if ( slot != NULL) {
+// PK11_FreeSlot(slot);
+// slot = NULL;
+// }
+
+ return handleBA;
+}
+
+
+//=================================================================================
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ComputeSessionKey
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKey
+ (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+#define KEYLENGTH 16
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray macKeyArray, jstring useSoftToken_s, jstring keySet, jstring sharedSecretKeyName)
+{
+ /* hardcore permanent mac key */
+ jbyte *mac_key = NULL;
+ if (macKeyArray != NULL) {
+ mac_key = (jbyte*)(env)->GetByteArrayElements(macKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ char input[KEYLENGTH];
+ int i = 0;
+
+ SECItem wrappedKeyItem = { siBuffer, NULL , 0};
+ SECItem noParams = { siBuffer, NULL, 0 };
+ SECStatus wrapStatus = SECFailure;
+
+
+ char *keyNameChars=NULL;
+ char *tokenNameChars=NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11SlotInfo *internal = PK11_GetInternalKeySlot();
+
+ PK11SymKey *symkey = NULL;
+ PK11SymKey *transportKey = NULL;
+ PK11SymKey *masterKey = NULL;
+
+ PK11SymKey *macSymKey = NULL;
+ PK11SymKey *symkey16 = NULL;
+ PK11SymKey *macKey = NULL;
+
+
+ BYTE macData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+
+
+ /* Derive vars */
+
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+
+ /* Java object return vars */
+
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+
+ jbyte * cuidValue = NULL;
+
+ jbyte *cc = NULL;
+ int cc_len = 0;
+
+ int hc_len = 0;
+ jbyte *hc = NULL;
+
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+
+ Buffer macBuff( ( BYTE *) mac_key , KEYLENGTH );
+
+ char *keySetStringChars = NULL;
+ if( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ char *sharedSecretKeyNameChars = NULL;
+
+ if( sharedSecretKeyName != NULL ) {
+ sharedSecretKeyNameChars = (char *) (env)->GetStringUTFChars( sharedSecretKeyName, NULL);
+ }
+
+ char *sharedSecretKeyNameString = sharedSecretKeyNameChars;
+
+ if ( sharedSecretKeyNameString == NULL ) {
+ sharedSecretKeyNameString = (char *) TRANSPORT_KEY_NAME;
+ }
+
+ GetSharedSecretKeyName(sharedSecretKeyNameString);
+
+ if( card_challenge != NULL) {
+ cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL);
+ cc_len = (env)->GetArrayLength(card_challenge);
+ }
+
+ if( cc == NULL) {
+ goto done;
+ }
+
+ if( host_challenge != NULL) {
+ hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL);
+ hc_len = (env)->GetArrayLength( host_challenge);
+ }
+
+ if( hc == NULL) {
+ goto done;
+ }
+
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ){
+ goto done;
+ }
+
+ if ( CUID != NULL ) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < 8; i++)
+ {
+ input[i] = cc[i];
+ }
+ for (i = 0; i < 8; i++)
+ {
+ input[8+i] = hc[i];
+ }
+
+ GetDiversificationData(cuidValue,macData,mac);//keytype is mac
+
+ if(tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ if(keyName)
+ {
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ strncpy(keyname,keyNameChars,KEYNAMELENGTH);
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }else
+ GetKeyName(keyVersion,keyname);
+
+ PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! \n");
+
+ if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) ||
+ (keyVersion[0] == -1 && strstr(keyname, "#FF")))
+
+ {
+ /* default manufacturers key */
+
+ macSymKey = ReturnDeveloperSymKey(slot, (char *) "mac" , keySetString, macBuff);
+
+ if( macSymKey == NULL ) {
+ goto done;
+ }
+
+ symkey = DeriveKey( //Util::DeriveKey(
+ macSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+
+ }else
+ {
+ masterKey = ReturnSymKey( slot,keyname);
+ if(masterKey == NULL)
+ {
+ goto done;
+ }
+
+ macKey =ComputeCardKeyOnToken(masterKey,macData);
+ if(macKey == NULL)
+ {
+ goto done;
+ }
+
+ symkey = DeriveKey(macKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+
+ if(symkey == NULL)
+ {
+ goto done;
+ }
+ }
+ //Now wrap the key for the trip back to TPS with shared secret transport key
+
+ symkey16 = NULL;
+ transportKey = ReturnSymKey( internal, GetSharedSecretKeyName(NULL));
+ if ( transportKey == NULL ) {
+ PR_fprintf(PR_STDERR, "Can't find shared secret transport key! \n");
+ goto done;
+ }
+
+ handleBA = (env)->NewByteArray( KEYLENGTH);
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ symkey16 = PK11_Derive(symkey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, 16);
+ if ( !symkey16 ) {
+ PR_fprintf(PR_STDERR,"Can't derive 16 byte key from 24 byte symkey! \n");
+ goto done;
+ }
+
+ wrappedKeyItem.data = (unsigned char *) handleBytes;
+ wrappedKeyItem.len = KEYLENGTH;
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, transportKey, symkey16, &wrappedKeyItem);
+
+ if(wrapStatus == SECFailure )
+ {
+ PR_fprintf(PR_STDERR, "Can't wrap session key! Error: %d \n", PR_GetError());
+ }
+
+done:
+
+ if( slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if( internal ) {
+ PK11_FreeSlot(internal);
+ internal = NULL;
+ }
+
+ if ( symkey ) {
+ PK11_FreeSymKey( symkey);
+ symkey = NULL;
+ }
+
+ if ( transportKey ) {
+ PK11_FreeSymKey( transportKey );
+ transportKey = NULL;
+ }
+
+ if ( symkey16 ) {
+ PK11_FreeSymKey( symkey16 );
+ symkey16 = NULL;
+ }
+
+ if( masterKey ) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( macKey ) {
+ PK11_FreeSymKey( macKey);
+ macKey = NULL;
+ }
+
+ if( macSymKey ) {
+ PK11_FreeSymKey( macSymKey );
+ macSymKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if( sharedSecretKeyNameChars ) {
+ (env)->ReleaseStringUTFChars(sharedSecretKeyName, (const char *)sharedSecretKeyNameChars);
+ sharedSecretKeyNameChars = NULL;
+ }
+
+ if ( handleBA != NULL) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+
+ if ( cc != NULL) {
+ (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT);
+ }
+
+ if ( hc != NULL) {
+ (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT);
+ }
+
+ if( keyVersion != NULL) {
+ (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if ( cuidValue != NULL) {
+ (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ if( mac_key != NULL) {
+ (env)->ReleaseByteArrayElements(macKeyArray, mac_key, JNI_ABORT);
+ }
+
+ return handleBA;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ComputeEncSessionKey
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeEncSessionKey
+ (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+#define KEYLENGTH 16
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeEncSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray encKeyArray, jstring useSoftToken_s, jstring keySet)
+{
+ /* hardcoded permanent enc key */
+ jbyte *enc_key = NULL;
+ if(encKeyArray != NULL ) {
+ enc_key = (jbyte*)(env)->GetByteArrayElements(encKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ char input[KEYLENGTH];
+ int i = 0;
+
+ SECItem wrappedKeyItem = { siBuffer, NULL , 0};
+ SECItem noParams = { siBuffer, NULL, 0 };
+ SECStatus wrapStatus = SECFailure;
+
+ char *keyNameChars = NULL;
+ char *tokenNameChars = NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11SlotInfo *internal = PK11_GetInternalKeySlot();
+
+ PK11SymKey *symkey = NULL;
+ PK11SymKey * transportKey = NULL;
+ PK11SymKey *masterKey = NULL;
+
+ PK11SymKey *encSymKey = NULL;
+ PK11SymKey *encKey = NULL;
+ PK11SymKey *symkey16 = NULL;
+
+ BYTE encData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+
+ /* Derive vars */
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+
+ /* Java object return vars */
+
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+
+ jbyte * cuidValue = NULL;
+
+ jbyte *cc = NULL;
+ int cc_len = 0;
+
+ int hc_len = 0;
+ jbyte *hc = NULL;
+
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+
+ Buffer encBuff( ( BYTE *) enc_key , KEYLENGTH );
+
+ char *keySetStringChars = NULL;
+
+ if( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ if( card_challenge != NULL) {
+ cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL);
+ cc_len = (env)->GetArrayLength(card_challenge);
+ }
+
+ if( cc == NULL) {
+ goto done;
+ }
+
+ if( host_challenge != NULL) {
+ hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL);
+ hc_len = (env)->GetArrayLength( host_challenge);
+ }
+
+ if( hc == NULL) {
+ goto done;
+ }
+
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ){
+ goto done;
+ }
+
+ if( CUID != NULL) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < 8; i++)
+ {
+ input[i] = cc[i];
+ }
+ for (i = 0; i < 8; i++)
+ {
+ input[8+i] = hc[i];
+ }
+
+ GetDiversificationData(cuidValue,encData,enc);
+
+ if(tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ if(keyName)
+ {
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ strncpy(keyname,keyNameChars,KEYNAMELENGTH);
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }
+ else {
+ GetKeyName(keyVersion,keyname);
+ }
+
+ if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0) ||
+ (keyVersion[0] == -1 && strstr(keyname, "#FF")))
+ {
+ /* default manufacturers key */
+
+ encSymKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, encBuff);
+
+ if( encSymKey == NULL ) {
+ goto done;
+ }
+
+ symkey = DeriveKey( //Util::DeriveKey(
+ encSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+
+ }else
+ {
+ masterKey = ReturnSymKey( slot,keyname);
+
+ /* We need to use internal so that the key
+ * can be exported by using PK11_GetKeyData()
+ */
+ if(masterKey == NULL) {
+ goto done;
+ }
+
+ encKey =ComputeCardKeyOnToken(masterKey,encData);
+ if(encKey == NULL) {
+ goto done;
+ }
+ symkey = DeriveKey(encKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+ }
+
+ if(symkey == NULL) {
+ goto done;
+ }
+
+ //Now wrap the key for the trip back to TPS with shared secret transport key
+ transportKey = ReturnSymKey( internal, GetSharedSecretKeyName(NULL));
+ if ( transportKey == NULL ) {
+ goto done;
+ }
+
+ handleBA = (env)->NewByteArray( KEYLENGTH);
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ symkey16 = PK11_Derive(symkey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, KEYLENGTH);
+
+ if ( !symkey16 ) {
+ PR_fprintf(PR_STDERR,"SessionKey: ComputeEncSessionKey - Can't derive 16 byte key from 24 byte symkey! \n");
+ goto done;
+ }
+
+ wrappedKeyItem.data = (unsigned char *) handleBytes;
+ wrappedKeyItem.len = KEYLENGTH;
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, transportKey, symkey16, &wrappedKeyItem);
+
+ if ( wrapStatus == SECFailure ) {
+ PR_fprintf(PR_STDERR,"SessionKey: ComputeEncSessionKey - Can't wrap encSessionKey ! Error: %d \n", PR_GetError());
+ }
+
+done:
+
+ if ( slot ) {
+ PK11_FreeSlot ( slot );
+ slot = NULL;
+ }
+
+ if ( internal) {
+ PK11_FreeSlot( internal);
+ internal = NULL;
+ }
+
+ if( symkey) {
+ PK11_FreeSymKey( symkey);
+ symkey = NULL;
+ }
+
+ if( transportKey) {
+ PK11_FreeSymKey( transportKey );
+ transportKey = NULL;
+ }
+
+ if( masterKey) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( symkey16) {
+ PK11_FreeSymKey( symkey16);
+ symkey16 = NULL;
+ }
+
+ if ( encSymKey ) {
+ PK11_FreeSymKey( encSymKey);
+ encSymKey = NULL;
+ }
+
+ if( encKey) {
+ PK11_FreeSymKey( encKey);
+ encKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if ( handleBytes != NULL ) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+
+ if( cc != NULL ) {
+ (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT);
+ }
+
+ if( hc != NULL ) {
+ (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT);
+ }
+ if(keyVersion != NULL ) {
+ (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if(cuidValue != NULL) {
+ (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ if( enc_key != NULL) {
+ (env)->ReleaseByteArrayElements(encKeyArray, enc_key, JNI_ABORT);
+ }
+
+ return handleBA;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ComputeKekKey
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekKey
+ (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+#define KEYLENGTH 16
+
+extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet)
+{
+ /* hardcoded permanent kek key */
+ jbyte *kek_key = NULL;
+ if( kekKeyArray != NULL) {
+ kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ Buffer kekBuff( ( BYTE *) kek_key , KEYLENGTH );
+
+ char *keySetStringChars = NULL;
+ if( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ char input[KEYLENGTH];
+ int i;
+ jobject keyObj = NULL;
+
+ jbyte *cc = NULL;
+ jbyte *hc = NULL;
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+ jbyte * cuidValue = NULL;
+
+ char *keyNameChars=NULL;
+ char *tokenNameChars = NULL;
+ PK11SlotInfo *slot = NULL;
+
+ PK11SymKey *kekKey = NULL;
+ PK11SymKey *masterKey = NULL;
+
+ BYTE kekData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+
+ if( card_challenge != NULL) {
+ cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL);
+ }
+
+ if( cc == NULL) {
+ goto done;
+ }
+
+ if( host_challenge != NULL) {
+ hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL);
+ }
+
+ if( hc == NULL) {
+ goto done;
+ }
+
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ){
+ goto done;
+ }
+
+ if( CUID != NULL) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < 8; i++)
+ {
+ input[i] = cc[i];
+ }
+ for (i = 0; i < 8; i++)
+ {
+ input[8+i] = hc[i];
+ }
+
+ GetDiversificationData(cuidValue,kekData,kek);//keytype is kek
+
+ if (tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ if (keyName)
+ {
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ strcpy(keyname,keyNameChars);
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }else
+ GetKeyName(keyVersion,keyname);
+
+ PR_fprintf(PR_STDOUT,"In SessionKey.ComputeKekKey! \n");
+
+ if (( keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 ) ||
+ (keyVersion[0] == -1 && strcmp(keyname, "#FF")))
+ {
+ /* default manufacturers key */
+
+ kekKey = ReturnDeveloperSymKey(slot, (char *) "kek" , keySetString, kekBuff);
+
+ } else {
+ masterKey = ReturnSymKey( slot,keyname);
+
+ if(masterKey == NULL)
+ {
+ goto done;
+ }
+
+ kekKey =ComputeCardKeyOnToken(masterKey,kekData);
+
+ }
+
+ if(kekKey == NULL) {
+ goto done;
+ }
+
+ keyObj = JSS_PK11_wrapSymKey(env, &kekKey, NULL);
+
+done:
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if(masterKey) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if(kekKey) {
+ PK11_FreeSymKey( kekKey);
+ kekKey = NULL;
+ }
+
+ if(slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if (cc != NULL) {
+ (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT);
+ }
+
+ if (hc != NULL) {
+ (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT);
+ }
+
+ if( keyVersion != NULL ) {
+ (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if (cuidValue != NULL ) {
+ (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ return keyObj;
+}
+
+PRStatus ComputeMAC(PK11SymKey *key, Buffer &x_input,
+const Buffer &icv, Buffer &output)
+{
+ PRStatus rv = PR_SUCCESS;
+ PK11Context *context = NULL;
+// NetkeyICV temp;
+ unsigned char result[8];
+ int i;
+ SECStatus s;
+ int len;
+#ifdef USE_DESMAC
+ CK_ULONG macLen = sizeof result;
+ SECItem params = { siBuffer, (unsigned char *)&macLen, sizeof macLen };
+#endif
+ static SECItem noParams = { siBuffer, NULL, 0 };
+ static unsigned char macPad[] =
+ {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ BYTE *input = (BYTE *) x_input;
+ int inputLen = x_input.size();
+
+ if(key == NULL)
+ {
+ rv = PR_FAILURE; goto done;
+ }
+
+#ifdef USE_DESMAC
+ context = PK11_CreateContextBySymKey(CKM_DES3_MAC_GENERAL, CKA_SIGN,
+ key, &params);
+ if (!context) { rv = PR_FAILURE; goto done; }
+
+ s = PK11_DigestBegin(context);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+
+ s = PK11_DigestOp(context, icv, 8);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+
+ while(inputLen >= 8)
+ {
+ s = PK11_DigestOp(context, input, 8);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+
+ input += 8;
+ inputLen -= 8;
+ }
+
+ for (i = 0;i < inputLen;i++)
+ {
+ result[i] = input[i];
+ }
+
+ input = macPad;
+ for(;i < 8;i++)
+ {
+ result[i] = *input++;
+ }
+
+ s = PK11_DigestOp(context, result, sizeof result);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+
+ s = PK11_DigestFinal(context, output, (unsigned int *)&len, sizeof output);
+ if (1 != SECSuccess) { rv = PR_FAILURE; goto done; }
+
+#else
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams);
+ if (!context) { rv = PR_FAILURE; goto done; }
+
+ memcpy(result, icv, sizeof result);
+
+ /* Process whole blocks */
+ while (inputLen >= 8)
+ {
+ for(i = 0;i < 8;i++)
+ {
+ result[i] ^= input[i];
+ }
+
+ s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+ if (len != sizeof result) /* assert? */
+ {
+//PR_SetError(PR_UNKNOWN_ERROR, 0);
+ rv = PR_FAILURE;
+ goto done;
+ }
+
+ input += 8;
+ inputLen -= 8;
+ }
+
+/*
+ * Fold in remaining data (if any)
+ * Set i to number of bytes processed
+ */
+ for(i = 0;i < inputLen;i++)
+ {
+ result[i] ^= input[i];
+ }
+
+ /*
+ * Fill remainder of last block. There
+ * will be at least one byte handled here.
+ */
+ input = macPad;
+ while(i < 8)
+ {
+ result[i] ^= *input++;
+ i++;
+ }
+
+ s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result);
+ if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
+ if (len != sizeof result)
+ {
+//PR_SetError(PR_UNKNOWN_ERROR, 0);
+ rv = PR_FAILURE;
+ goto done;
+ }
+
+ output.replace(0, result, sizeof result);
+#endif
+
+ done:
+ if (context)
+ {
+ PK11_Finalize(context);
+ PK11_DestroyContext(context, PR_TRUE);
+ }
+ memset(result, 0, sizeof result);
+
+ return rv;
+} /* ComputeMAC */
+
+
+//=================================================================================
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ComputeCryptogram
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCryptogram
+ (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, int, jbyteArray, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+#define KEYLENGTH 16
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCryptogram(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, int type, jbyteArray authKeyArray, jstring useSoftToken_s, jstring keySet)
+{
+/* hardcore permanent mac key */
+ jbyte *auth_key = NULL;
+ if( authKeyArray != NULL) {
+ auth_key = (jbyte*)(env)->GetByteArrayElements(authKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ Buffer authBuff( ( BYTE *) auth_key , KEYLENGTH );
+ Buffer icv = Buffer(EIGHT_BYTES, (BYTE)0);
+ Buffer output = Buffer(EIGHT_BYTES, (BYTE)0);
+
+ char *keySetStringChars = NULL;
+ if( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ char input[KEYLENGTH];
+ int i;
+
+ PR_fprintf(PR_STDOUT,"In SessionKey: ComputeCryptogram! \n");
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+
+ jbyte *cc = NULL;
+ jbyte *hc = NULL;
+ int cc_len = 0;
+ int hc_len = 0;
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+ jbyte * cuidValue = NULL;
+
+ char *tokenNameChars = NULL;
+ char *keyNameChars=NULL;
+ PK11SlotInfo *slot = NULL;
+
+ jbyte * session_key = NULL;
+ PK11SymKey *symkey = NULL;
+ PK11SymKey *masterKey = NULL;
+ PK11SymKey *authKey = NULL;
+ PK11SymKey *authSymKey = NULL;
+
+ BYTE authData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+ Buffer input_x = Buffer(KEYLENGTH);
+
+ if( card_challenge != NULL ) {
+ cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL);
+ cc_len = (env)->GetArrayLength(card_challenge);
+ }
+
+ if( cc == NULL) {
+ goto done;
+ }
+
+ if( host_challenge != NULL ) {
+ hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL);
+ hc_len = (env)->GetArrayLength( host_challenge);
+ }
+
+ if( hc == NULL) {
+ goto done;
+ }
+
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ){
+ goto done;
+ }
+
+ if( CUID != NULL) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ if (type == 0) // compute host cryptogram
+ {
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < EIGHT_BYTES; i++)
+ {
+ input[i] = cc[i];
+ }
+ for (i = 0; i < EIGHT_BYTES; i++)
+ {
+ input[EIGHT_BYTES +i] = hc[i];
+ }
+ } // compute card cryptogram
+ else if (type == 1)
+ {
+ for (i = 0; i < EIGHT_BYTES; i++)
+ {
+ input[i] = hc[i];
+ }
+ for (i = 0; i < EIGHT_BYTES; i++)
+ {
+ input[EIGHT_BYTES+i] = cc[i];
+ }
+ }
+
+ input_x.replace(0, (BYTE*) input, KEYLENGTH);
+
+ GetDiversificationData(cuidValue,authData,enc);
+
+ if (tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ if (keyName)
+ {
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ strcpy(keyname,keyNameChars);
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }else
+ GetKeyName(keyVersion,keyname);
+
+ if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 ) ||
+ (keyVersion[0] == -1 && strstr(keyname, "#FF")))
+ {
+
+ /* default manufacturers key */
+
+ authSymKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, authBuff);
+ if( authSymKey == NULL ) {
+ goto done;
+ }
+
+ symkey = DeriveKey(
+ authSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+ }
+ else
+ {
+ masterKey = ReturnSymKey( slot,keyname);
+ if (masterKey == NULL)
+ {
+ goto done;
+ }
+
+ authKey = ComputeCardKeyOnToken(masterKey,authData);
+ if (authKey == NULL)
+ {
+ goto done;
+ }
+
+ symkey = DeriveKey(authKey,
+ Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
+
+ }
+
+ ComputeMAC(symkey, input_x, icv, output);
+ session_key = (jbyte *) (BYTE*)output;
+
+ handleBA = (env)->NewByteArray( EIGHT_BYTES);
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+ if( handleBytes ) {
+ memcpy(handleBytes, session_key, EIGHT_BYTES);
+ }
+
+done:
+
+ if( slot ) {
+ PK11_FreeSlot( slot );
+ slot = NULL;
+ }
+
+ if( symkey ) {
+ PK11_FreeSymKey( symkey );
+ symkey = NULL;
+ }
+
+ if( authSymKey ) {
+ PK11_FreeSymKey( authSymKey );
+ authSymKey = NULL;
+ }
+
+ if( authKey) {
+ PK11_FreeSymKey( authKey);
+ authKey = NULL;
+ }
+
+ if( masterKey) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if( handleBytes != NULL) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+
+ if( cc != NULL) {
+ (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT);
+ }
+
+ if( hc != NULL) {
+ (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT);
+ }
+
+ if( keyVersion != NULL) {
+ (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if( cuidValue != NULL) {
+ (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ return handleBA;
+}
+
+
+//=================================================================================
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_ECBencrypt
+ * Method: ECBencrypt
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jbyteArray JNICALL
+ Java_com_netscape_symkey_SessionKey_ECBencrypt
+ (JNIEnv*, jclass, jobject, jobject);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jbyteArray JNICALL
+Java_com_netscape_symkey_SessionKey_ECBencrypt
+(JNIEnv* env, jclass this2, jobject symkeyObj, jobject deskeyObj )
+{
+ jbyteArray handleBA=NULL;
+ jint dlen=KEYLENGTH; // applet only supports 16 bytes
+ jbyte *handleBytes=NULL;
+
+ PK11SymKey *symkey = NULL;
+ PK11SymKey *deskey = NULL;
+ PK11SymKey *newdeskey = NULL;
+ PRStatus r = PR_FAILURE;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+ SECItem wrappedKeyItem = { siBuffer, NULL, 0 };
+ SECStatus wrapStatus = SECFailure;
+
+ /* PK11_Derive vars. */
+
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+ CK_ULONG bitPosition = 0;
+
+ PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! \n");
+
+ if( !symkeyObj || !deskeyObj) {
+ goto finish;
+ }
+
+ r = JSS_PK11_getSymKeyPtr(env, symkeyObj, &symkey);
+ if (r != PR_SUCCESS) {
+ goto finish;
+ }
+
+ r = JSS_PK11_getSymKeyPtr(env, deskeyObj, &deskey);
+ if (r != PR_SUCCESS) {
+ goto finish;
+ }
+ // Instead of playing with raw keys, let's derive the 16 byte des2 key from
+ // the 24 byte des2 key.
+
+ bitPosition = 0;
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ newdeskey = PK11_Derive(deskey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, 16);
+
+ if ( ! newdeskey ) {
+ goto finish;
+ }
+
+ dlen = KEYLENGTH; // applet suports only 16 bytes
+
+ handleBA = (env)->NewByteArray(dlen);
+ if(handleBA == NULL )
+ {
+ goto finish;
+ }
+ handleBytes = (jbyte *)(env)->GetByteArrayElements(handleBA, NULL);
+
+ if(handleBytes==NULL)
+ {
+ goto finish;
+ }
+
+ //Wrap the new 16 bit key with the input symkey.
+
+ wrappedKeyItem.data = (unsigned char *) handleBytes;
+ wrappedKeyItem.len = dlen;
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, symkey, newdeskey, &wrappedKeyItem);
+
+ if( wrapStatus == SECSuccess) {
+ PR_fprintf(PR_STDERR, "ECBencrypt wrapStatus %d wrappedKeySize %d \n", wrapStatus, wrappedKeyItem.len);
+ } else {
+ PR_fprintf(PR_STDERR, "ECBecrypt wrap failed! Error %d \n", PR_GetError());
+ }
+
+finish:
+
+ if( handleBytes != NULL) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+
+ if ( newdeskey ) {
+ PK11_FreeSymKey( newdeskey );
+ newdeskey = NULL;
+ }
+
+ return handleBA;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_GenerateSymkey
+ * Method: GenerateSymkey
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jobject JNICALL
+ Java_com_netscape_symkey_SessionKey_GenerateSymkey
+ (JNIEnv*, jclass, jstring);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jobject JNICALL
+Java_com_netscape_symkey_SessionKey_GenerateSymkey
+(JNIEnv* env, jclass this2, jstring tokenName)
+{
+ jobject keyObj = NULL;
+ PK11SymKey *okey = NULL;
+ PK11SymKey *okeyFirstEight = NULL;
+ PK11SymKey *concatKey = NULL;
+ PK11SymKey *finalKey = NULL;
+
+ char *tokenNameChars = NULL;
+ PK11SlotInfo *slot = NULL;
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+ CK_OBJECT_HANDLE keyhandle = 0;
+
+ PR_fprintf(PR_STDOUT,"In SessionKey GenerateSymkey!\n");
+ if (tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) {
+ slot = PK11_GetInternalSlot();
+ } else {
+ slot = ReturnSlot(tokenNameChars);
+ }
+
+ PR_fprintf(PR_STDOUT,"SessinKey: GenerateSymkey slot %p name %s tokenName %s \n",slot, PK11_GetSlotName(slot), PK11_GetTokenName(slot));
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ //Generate original 16 byte DES2 key
+ okey = PK11_TokenKeyGen(slot, CKM_DES2_KEY_GEN,0, 0, 0, PR_FALSE, NULL);
+
+ if (okey == NULL) {
+ goto finish;
+ }
+
+ // Extract first eight bytes from generated key into another key.
+ bitPosition = 0;
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ okeyFirstEight = PK11_Derive(okey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT , CKA_DERIVE, 8);
+ if (okeyFirstEight == NULL ) {
+ goto finish;
+ }
+
+ //Concatenate 8 byte key to the end of the original key, giving new 24 byte key
+ keyhandle = PK11_GetSymKeyHandle(okeyFirstEight);
+ paramsItem.data=(unsigned char *) &keyhandle;
+ paramsItem.len=sizeof(keyhandle);
+
+ concatKey = PK11_Derive ( okey , CKM_CONCATENATE_BASE_AND_KEY , &paramsItem ,CKM_DES3_ECB , CKA_DERIVE , 0);
+ if ( concatKey == NULL ) {
+ goto finish;
+ }
+
+ //Make sure we move this to the orig token, in case it got moved by NSS
+ //during the derive phase.
+
+ finalKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, concatKey);
+
+ /* wrap the symkey in java object. This sets symkey to NULL. */
+ keyObj = JSS_PK11_wrapSymKey(env, &finalKey, NULL);
+
+finish:
+ if ( slot != NULL) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if ( okey != NULL) {
+ PK11_FreeSymKey(okey);
+ okey = NULL;
+ }
+
+ if ( okeyFirstEight != NULL) {
+ PK11_FreeSymKey(okeyFirstEight);
+ okeyFirstEight = NULL;
+ }
+
+ if ( concatKey != NULL) {
+ PK11_FreeSymKey(concatKey);
+ concatKey = NULL;
+ }
+
+ if ( finalKey != NULL) {
+ PK11_FreeSymKey(finalKey);
+ finalKey = NULL;
+ }
+
+ return keyObj;
+}
+
+// begin DRM proto
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: bytes2PK11SymKey
+ * Signature:
+ */
+ JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_bytes2PK11SymKey
+ (JNIEnv *, jclass, jbyteArray);
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef DRM_SUPPORT_DEBUG
+extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_bytes2PK11SymKey(JNIEnv * env, jclass this2, jbyteArray symKeyBytes)
+{
+ PK11SlotInfo *slot=NULL;
+ jobject keyObj = NULL;
+ PK11SymKey *symKey=NULL;
+
+// how about do unwrap (decrypt of the symkey in here??
+
+// DRM proto just use internal slot
+ slot = PK11_GetInternalKeySlot();
+
+ BYTE masterKeyData[24];
+ SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData)};
+
+ memcpy(masterKeyData, (char*)symKeyBytes, 16);
+ memcpy(masterKeyData+16, (char*)symKeyBytes, 8);
+
+ // ToDo: possibly get rid of whole function, not used
+ // For now , no need to get rid of PK11_ImportSymKeyWithFlags call.
+
+ symKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
+ PK11_OriginUnwrap, CKA_ENCRYPT, &masterKeyItem,
+ ALL_SYMKEY_OPS /*CKF_ENCRYPT*/, PR_FALSE, 0);
+
+ /* wrap the symkey in java object. This sets symkey to NULL. */
+ keyObj = JSS_PK11_wrapSymKey(env, &symKey, debug_fd);
+
+finish:
+ return keyObj;
+}
+
+
+// end DRM proto
+#endif // DRM_SUPPORT_DEBUG
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.java b/base/symkey/src/com/netscape/symkey/SessionKey.java
new file mode 100644
index 000000000..47f9385f7
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.java
@@ -0,0 +1,167 @@
+// --- 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.symkey;
+
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+/**
+ * This object contains the OS independent interfaces.
+ */
+public class SessionKey {
+ static boolean tryLoad(String filename) {
+ try {
+ System.load(filename);
+ } catch (Exception e) {
+ return false;
+ } catch (UnsatisfiedLinkError e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ // Load native library
+ static {
+ boolean mNativeLibrariesLoaded = false;
+ String os = System.getProperty("os.name");
+ if ((os.equals("Linux"))) {
+ // Check for 64-bit library availability
+ // prior to 32-bit library availability.
+ mNativeLibrariesLoaded =
+ tryLoad("/usr/lib64/symkey/libsymkey.so");
+ if (mNativeLibrariesLoaded) {
+ System.out.println("64-bit symkey library loaded");
+ } else {
+ // REMINDER: May be trying to run a 32-bit app
+ // on 64-bit platform.
+ mNativeLibrariesLoaded =
+ tryLoad("/usr/lib/symkey/libsymkey.so");
+ if (mNativeLibrariesLoaded) {
+ System.out.println("32-bit symkey library loaded");
+ } else {
+ System.out.println("FAILED loading symkey library!");
+ System.exit(-1);
+ }
+ }
+ } else {
+ try {
+ System.loadLibrary("symkey");
+ System.out.println("symkey library loaded");
+ mNativeLibrariesLoaded = true;
+ } catch (Throwable t) {
+ // This is bad news, the program is doomed at this point
+ t.printStackTrace();
+ }
+ }
+ }
+
+ // external calls from RA
+ public static native byte[] ComputeKeyCheck(PK11SymKey desKey); /* byte data[] ); */
+
+ public static native byte[] ComputeSessionKey(String tokenName,
+ String keyName,
+ byte[] card_challenge,
+ byte[] host_challenge,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] macKeyArray,
+ String useSoftToken,
+ String keySet,
+ String sharedSecretKeyName);
+
+ public static native byte[] ComputeEncSessionKey(String tokenName,
+ String keyName,
+ byte[] card_challenge,
+ byte[] host_challenge,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] encKeyArray,
+ String useSoftToken,
+ String keySet);
+
+ public static native PK11SymKey ComputeKekSessionKey(String tokenName,
+ String keyName,
+ byte[] card_challenge,
+ byte[] host_challenge,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] kekKeyArray,
+ String useSoftToken,
+ String keySet);
+
+ public static native PK11SymKey ComputeKekKey(String tokenName,
+ String keyName,
+ byte[] card_challenge,
+ byte[] host_challenge,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] kekKeyArray,
+ String useSoftToken, String keySet);
+
+ public static native byte[] ECBencrypt(PK11SymKey key,
+ PK11SymKey desKey); //byte[] data );
+
+ public static native PK11SymKey GenerateSymkey(String tokenName);
+
+ /*
+ * DRM_SUPPORT_DEBUG
+ */
+
+ // public static native PK11SymKey bytes2PK11SymKey( byte[] symKeyBytes );
+
+ public static native byte[] ComputeCryptogram(String tokenName,
+ String keyName,
+ byte[] card_challenge,
+ byte[] host_challenge,
+ byte[] keyInfo,
+ byte[] CUID,
+ int type,
+ byte[] authKeyArray,
+ String useSoftToken, String keySet);
+
+ public static native byte[] EncryptData(String tokenName,
+ String keyName,
+ byte[] in,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] kekKeyArray,
+ String useSoftToken, String keySet);
+
+ public static native byte[] DiversifyKey(String tokenName,
+ String newTokenName,
+ String oldMasterKeyName,
+ String newMasterKeyName,
+ String keyInfo,
+ byte[] CUIDValue,
+ byte[] kekKeyArray,
+ String useSoftToken, String keySet);
+
+ // internal calls from config TKS keys tab
+ public static native String GenMasterKey(String token,
+ String keyName);
+
+ public static native String DeleteSymmetricKey(String token,
+ String keyName);
+
+ public static native String ListSymmetricKeys(String token);
+
+ // set when called from the config TKS tab to create master key
+ // get when called from the RA to create session key
+ public static native void SetDefaultPrefix(String masterPrefix);
+}
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.cpp b/base/symkey/src/com/netscape/symkey/SymKey.cpp
new file mode 100644
index 000000000..c300d1ada
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/SymKey.cpp
@@ -0,0 +1,1407 @@
+// --- 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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#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 "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"
+
+#include "nspr.h"
+#ifdef __cplusplus
+#include <jni.h>
+#include <assert.h>
+#include <string.h>
+
+}
+#endif
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <cstdarg>
+#include <string>
+
+#include "Buffer.h"
+#include "SymKey.h"
+
+typedef unsigned char BYTE;
+
+typedef struct
+{
+ enum
+ {
+ PW_NONE = 0,
+ PW_FROMFILE = 1,
+ PW_PLAINTEXT = 2,
+ PW_EXTERNAL = 3
+ } source;
+ char *data;
+} secuPWData;
+
+char masterKeyPrefix[PREFIXLENGHT];
+char masterKeyNickName[KEYNAMELENGTH];
+char masterNewKeyNickName[KEYNAMELENGTH];
+char sharedSecretSymKeyName[KEYNAMELENGTH] = { 0 };
+
+//=================================================================================
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ListSymmetricKeys
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+ JNIEXPORT jstring JNICALL Java_com_netscape_symkey_SessionKey_ListSymmetricKeys
+ (JNIEnv *, jclass, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+
+PK11SlotInfo *ReturnSlot(char *tokenNameChars)
+{
+ if( tokenNameChars == NULL)
+ {
+ return NULL;
+ }
+ PK11SlotInfo *slot=NULL;
+
+ if(!strcmp( tokenNameChars, "internal" ) || !strcmp( tokenNameChars, "Internal Key Storage Token"))
+ {
+ slot = PK11_GetInternalKeySlot();
+ }
+ else
+ {
+ slot = PK11_FindSlotByName( tokenNameChars );
+ }
+ return slot;
+}
+
+
+/* Find the Symmetric key with the given nickname
+ Returns null if the key could not be found
+ Steve wrote this code to replace the old impl */
+
+PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname)
+{
+ char *name = NULL;
+ PK11SymKey *foundSymKey= NULL;
+ PK11SymKey *firstSymKey= NULL;
+ PK11SymKey *sk = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ secuPWData pwdata;
+
+ pwdata.source = secuPWData::PW_NONE;
+ pwdata.data = (char *) NULL;
+ PR_fprintf(PR_STDOUT,"In ReturnSymKey name %s \n",keyname);
+ if (keyname == NULL)
+ {
+ goto cleanup;
+ }
+ if (slot== NULL)
+ {
+ goto cleanup;
+ }
+ /* Initialize the symmetric key list. */
+ firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata );
+ /* scan through the symmetric key list for a key matching our nickname */
+ sk = firstSymKey;
+ while( sk != NULL )
+ {
+ /* get the nickname of this symkey */
+ name = PK11_GetSymKeyNickname( sk );
+
+ /* if the name matches, make a 'copy' of it */
+ if ( name != NULL && !strcmp( keyname, name ))
+ {
+ if (foundSymKey == NULL)
+ {
+ foundSymKey = PK11_ReferenceSymKey(sk);
+ }
+ PORT_Free(name);
+ }
+
+ sk = PK11_GetNextSymKey( sk );
+ }
+
+ /* We're done with the list now, let's free all the keys in it
+ It's okay to free our key, because we made a copy of it */
+
+ sk = firstSymKey;
+ while( sk != NULL )
+ {
+ nextSymKey = PK11_GetNextSymKey(sk);
+ PK11_FreeSymKey(sk);
+ sk = nextSymKey;
+ }
+
+ cleanup:
+ return foundSymKey;
+}
+
+
+extern "C" JNIEXPORT jstring
+JNICALL Java_com_netscape_symkey_SessionKey_DeleteKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName)
+
+{
+ char *tokenNameChars;
+ char *keyNameChars;
+ int count = 0;
+ int keys_deleted = 0;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ PK11SlotInfo *slot = NULL;
+ SECStatus rv;
+ secuPWData pwdata;
+ pwdata.source = secuPWData::PW_NONE;
+ pwdata.data = (char *) NULL;
+ jstring retval = NULL;
+
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ char *result= (char *)malloc(1);
+
+ result[0] = '\0';
+ if( tokenNameChars == NULL || keyNameChars==NULL)
+ {
+ goto finish;
+ }
+ if(strcmp( tokenNameChars, "internal" ) == 0 )
+ {
+ slot = PK11_GetInternalKeySlot();
+ }
+ else if( tokenNameChars != NULL )
+ {
+ slot = PK11_FindSlotByName( tokenNameChars );
+ }
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while( symKey != NULL )
+ {
+ char *name = NULL;
+ rv = SECFailure;
+ name = PK11_GetSymKeyNickname( symKey );
+
+ if( strcmp( keyNameChars, name ) == 0 )
+ {
+ rv = PK11_DeleteTokenSymKey( symKey );
+ }
+ PORT_Free(name);
+
+ if( rv != SECFailure )
+ {
+ keys_deleted++;
+ }
+
+ nextSymKey = PK11_GetNextSymKey( symKey );
+ PK11_FreeSymKey( symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ if( keys_deleted == 0 )
+ {
+
+ rv = SECFailure;
+ }
+ else
+ {
+
+ rv = SECSuccess;
+ }
+
+ finish:
+ if (slot)
+ {
+ PK11_FreeSlot(slot);
+ }
+ if(tokenNameChars)
+ {
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+ if(keyNameChars)
+ {
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }
+ retval = (env)->NewStringUTF( result);
+ free(result);
+ return retval;
+}
+
+
+#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
+(x)->pValue=(v); (x)->ulValueLen = (l);
+
+extern "C" JNIEXPORT jstring
+JNICALL Java_com_netscape_symkey_SessionKey_ListSymmetricKeys(JNIEnv * env, jclass this2, jstring tokenName)
+{
+ char *tokenNameChars;
+ jstring retval = NULL;
+ PK11SymKey *symKey = NULL;
+ PK11SymKey *nextSymKey = NULL;
+ secuPWData pwdata;
+ pwdata.source = secuPWData::PW_NONE;
+ pwdata.data = (char *) NULL;
+ PK11SlotInfo *slot = NULL;
+
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ char *result= (char *)malloc(1);
+ result[0] = '\0';
+ if( tokenNameChars == NULL )
+ {
+ goto finish;
+ }
+ if(strcmp( tokenNameChars, "internal" ) == 0 )
+ {
+ slot = PK11_GetInternalKeySlot();
+ }
+ else if( tokenNameChars != NULL )
+ {
+ slot = PK11_FindSlotByName( tokenNameChars );
+ }
+
+ /* Initialize the symmetric key list. */
+ symKey = PK11_ListFixedKeysInSlot( slot , NULL, (void *)&pwdata );
+
+ /* Iterate through the symmetric key list. */
+ while (symKey != NULL)
+ {
+ int count = 0;
+ char *name = NULL;
+ char *temp = NULL;
+ name = PK11_GetSymKeyNickname( symKey );
+ temp = result;
+ result = (char*)malloc( strlen(name) + strlen(temp) + 2 );
+ result[0]='\0';
+ strcat(result, temp);
+ strcat(result, ",");
+ strcat(result, name);
+ free(temp);
+
+ PORT_Free(name);
+
+ nextSymKey = PK11_GetNextSymKey( symKey );
+ PK11_FreeSymKey( symKey );
+ symKey = nextSymKey;
+
+ count++;
+ }
+
+ finish:
+ if (slot)
+ {
+ PK11_FreeSlot(slot);
+ }
+ if(tokenNameChars)
+ {
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+ retval = (env)->NewStringUTF(result);
+ free(result);
+ return retval;
+}
+
+
+/* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
+ * that byte with the proper parity bit set */
+static const unsigned char parityTable[256] =
+{
+/* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
+ /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e,
+/* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
+ /* O */ 0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f,
+/* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
+ /* O */ 0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f,
+/* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
+ /* E */ 0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e,
+/* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
+ /* O */ 0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f,
+/* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
+ /* E */ 0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e,
+/* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
+ /* E */ 0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e,
+/* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
+ /* O */ 0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f,
+/* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
+ /* O */ 0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f,
+/* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
+ /* E */ 0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e,
+/* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
+ /* E */ 0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae,
+/* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
+ /* O */ 0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf,
+/* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
+ /* E */ 0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce,
+/* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
+ /* O */ 0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf,
+/* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
+ /* O */ 0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef,
+/* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
+ /* E */ 0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe,
+};
+
+void
+pk11_FormatDESKey(unsigned char *key, int length)
+{
+ int i;
+
+ /* format the des key */
+ for (i=0; i < length; i++)
+ {
+ key[i] = parityTable[key[i]>>1];
+ }
+}
+
+
+static secuPWData pwdata = { secuPWData::PW_NONE, 0 };
+
+/**
+ * Internal token is required when we are doing key diversification
+ * where raw key material needs to be accessed
+ */
+PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data)
+{
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11SymKey *key = ComputeCardKey(masterKey, data, slot);
+ if( slot != NULL) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ return key;
+}
+
+PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot)
+{
+ PK11SymKey *key = NULL;
+ PK11Context *context = NULL;
+ int keysize = DES3_LENGTH;
+ unsigned char *keyData = NULL;
+ SECStatus s = SECSuccess;
+ int i = 0;
+ int len = 0;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+ unsigned char *in = data;
+ PK11SymKey *tmpkey = NULL;
+ unsigned char wrappedkey[DES3_LENGTH];
+ SECItem wrappeditem = { siBuffer, NULL, 0 };
+
+ keyData = (unsigned char*)malloc(keysize);
+
+ for (i = 0;i < keysize; i++)
+ {
+ keyData[i] = 0x0;
+ }
+
+ if (masterKey == NULL) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: master key is null.\n");
+ goto done;
+ }
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT,
+ masterKey,
+ &noParams);
+
+ if (context == NULL) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to create context.\n");
+ goto done;
+ }
+
+ /* Part 1 */
+ s = PK11_CipherOp(context, &keyData[0], &len, 8, in, 8);
+ if (s != SECSuccess) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encrypt #1\n");
+ goto done;
+ }
+ pk11_FormatDESKey(&keyData[0], EIGHT_BYTES); /* set parity */
+
+ /* Part 2 */
+ s = PK11_CipherOp(context, &keyData[EIGHT_BYTES], &len, EIGHT_BYTES, in+EIGHT_BYTES, EIGHT_BYTES);
+ if (s != SECSuccess) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encryp #2.\n");
+ goto done;
+ }
+ pk11_FormatDESKey(&keyData[EIGHT_BYTES], EIGHT_BYTES);
+
+ /* Part 3 */
+ for(i = 0;i < EIGHT_BYTES;i++)
+ {
+ keyData[i+KEYLENGTH] = keyData[i];
+ }
+
+#define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL
+
+ /* generate a tmp key to import the sym key */
+ tmpkey = PK11_TokenKeyGenWithFlags(slot,
+ CKM_DES3_KEY_GEN, 0, 0, 0,
+ (CKF_WRAP | CKF_UNWRAP | CKF_ENCRYPT | CKF_DECRYPT) & CKF_KEY_OPERATION_FLAGS,
+ PR_FALSE, &pwdata);
+
+ if (tmpkey == NULL) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to keygen. \n");
+ goto done;
+ }
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT,
+ tmpkey,
+ &noParams);
+
+ if (context == NULL) {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to set context. \n");
+ goto done;
+ }
+
+ /* encrypt the key with the master key */
+ s = PK11_CipherOp(context, wrappedkey, &len, 24, keyData, 24);
+ if (s != SECSuccess)
+ {
+ PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encrypt #3.\n");
+ goto done;
+ }
+
+ wrappeditem.data = wrappedkey;
+ wrappeditem.len = len;
+
+ key = PK11_UnwrapSymKeyWithFlags(tmpkey, CKM_DES3_ECB, &noParams,
+ &wrappeditem, CKM_DES3_KEY_GEN, CKA_DECRYPT, 24,
+ (CKA_ENCRYPT | CKA_DECRYPT) & CKF_KEY_OPERATION_FLAGS );
+
+done:
+ if (keyData != NULL)
+ {
+ free(keyData);
+ }
+ if (context != NULL)
+ {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+ if (tmpkey != NULL)
+ {
+ PK11_FreeSymKey(tmpkey);
+ tmpkey = NULL;
+ }
+
+ return key;
+}
+
+PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data)
+{
+ PK11SlotInfo *slot = PK11_GetSlotFromKey(masterKey);
+ PK11SymKey *key = ComputeCardKey(masterKey, data, slot);
+
+ if( slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ return key;
+}
+
+// Either encrypt data with a provided SymKey OR a key buffer array (for the Default keyset case).
+PRStatus EncryptData(const Buffer &kek_key,PK11SymKey *cardKey, Buffer &input, Buffer &output)
+{
+ PRStatus rv = PR_FAILURE;
+
+ PK11SymKey *master = NULL;
+ PK11SymKey *transportKey = NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11Context *context = NULL;
+ int i = 0;
+ SECStatus s = SECFailure;
+ int len = 0;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+#ifdef DES2_WORKAROUND
+ unsigned char masterKeyData[DES3_LENGTH];
+#else
+ unsigned char masterKeyData[KEYLENGTH];
+#endif
+ unsigned char result[EIGHT_BYTES];
+
+ slot = PK11_GetInternalKeySlot();
+
+ if (slot == NULL) {
+ goto done;
+ }
+
+ if ( cardKey == NULL ) { /* Developer key set mode.*/
+ transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
+
+ /* convert 16-byte to 24-byte triple-DES key */
+ memcpy(masterKeyData, kek_key, 16);
+ memcpy(masterKeyData+16, kek_key, 8);
+
+ master = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE);
+
+ } else {
+ master = cardKey;
+ }
+
+ if( master == NULL) {
+ goto done;
+ }
+
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master,
+ &noParams);
+
+ if (context == NULL) {
+ goto done;
+ }
+
+ for(i = 0;i < (int)input.size();i += EIGHT_BYTES)
+ {
+ s = PK11_CipherOp(context, result, &len, EIGHT_BYTES,
+ (unsigned char *)(((BYTE*)input)+i), EIGHT_BYTES);
+
+ if (s != SECSuccess) {
+ goto done;
+ }
+ output.replace(i, result, EIGHT_BYTES);
+ }
+
+ rv = PR_SUCCESS;
+
+done:
+
+ memset(masterKeyData, 0, sizeof masterKeyData);
+ if (context)
+ {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+ if (slot)
+ {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+ if (master && cardKey == NULL)
+ {
+ PK11_FreeSymKey(master);
+ master = NULL;
+ }
+
+ return rv;
+}
+
+PRStatus ComputeKeyCheckWithSymKey(PK11SymKey * newKey, Buffer& output)
+{
+ PK11SymKey *key = NULL;
+ PRStatus status = PR_FAILURE ;
+ PK11SlotInfo *slot = NULL;
+ PK11Context *context = NULL;
+ SECStatus s = SECFailure;
+ int len = 0;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+ unsigned char value[EIGHT_BYTES];
+
+ if ( newKey == NULL ) {
+ return status;
+ }
+
+ memset(value, 0, sizeof value);
+
+ slot = PK11_GetInternalKeySlot();
+ if (slot != NULL)
+ {
+ key = newKey ;
+ if( key != NULL )
+ {
+ context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key,
+ &noParams);
+ if (context != NULL)
+ {
+ s = PK11_CipherOp(context, &value[0], &len, 8, &value[0], 8);
+
+ if (s == SECSuccess)
+ {
+ output.resize(3);
+ output.replace(0, value, 3);
+ status = PR_SUCCESS;
+ }
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+ //PK11_FreeSymKey(key);
+ //key = NULL;
+
+ }
+ if( slot != NULL) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+ }
+
+ return status;
+}
+
+// Create key set data with the help of either a provided old_keyk_ke2_sym key or key buffer (for the Default keyset case).
+PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek_key2, PK11SymKey *old_kek_key2_sym, PK11SymKey *new_auth_key, PK11SymKey *new_mac_key, PK11SymKey *new_kek_key, Buffer &output)
+{
+ PRStatus rv = PR_FAILURE;
+ static SECItem noParams = { siBuffer, NULL, 0 };
+ PK11SymKey *transportKey = NULL;
+ PK11SymKey *wrappingKey = NULL;
+ BYTE masterKeyData[DES3_LENGTH];
+
+ /* Wrapping vars */
+ SECItem wrappedKeyItem = { siBuffer, NULL , 0 };
+ SECStatus wrapStatus = SECFailure;
+ PK11SlotInfo *slot = NULL;
+ /* Extracting vars */
+
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ PK11SymKey *macKey16 = NULL;
+ PK11SymKey *authKey16 = NULL;
+ PK11SymKey *kekKey16 = NULL;
+
+ Buffer encrypted_auth_key(KEYLENGTH);
+ Buffer encrypted_mac_key(KEYLENGTH);
+ Buffer encrypted_kek_key(KEYLENGTH);
+
+ Buffer kc_auth_key(3);
+ Buffer kc_mac_key(3);
+ Buffer kc_kek_key(3);
+ Buffer result;
+
+ PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys!\n");
+
+ if ( new_auth_key == NULL || new_mac_key == NULL || new_kek_key == NULL) {
+ return rv;
+ }
+
+ slot = PK11_GetSlotFromKey(new_auth_key);
+ if ( old_kek_key2_sym == NULL ) { /* perm key mode */
+ /* Find transport key, shared secret */
+ transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
+ if ( transportKey == NULL ) {
+ goto done;
+ }
+
+ /* convert 16-byte to 24-byte triple-DES key */
+ memcpy(masterKeyData, old_kek_key2, KEYLENGTH);
+ memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES);
+
+ wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE);
+
+ } else { /* card key mode */
+ wrappingKey = old_kek_key2_sym;
+ }
+
+ //Now derive 16 byte versions of the provided symkeys
+ authKey16 = PK11_Derive(new_auth_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, 16);
+
+ if ( authKey16 == NULL ) {
+ PR_fprintf(PR_STDERR,"Error deriving authKey16. Error %d \n", PR_GetError());
+ goto done;
+ }
+
+ wrappedKeyItem.data = (unsigned char *) encrypted_auth_key;
+ wrappedKeyItem.len = encrypted_auth_key.size();
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, authKey16, &wrappedKeyItem);
+ if ( wrapStatus == SECFailure ) {
+ PR_fprintf(PR_STDERR,"Error wrapping authKey16. Error %d \n", PR_GetError());
+ goto done;
+ }
+
+ macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT, CKA_DERIVE, 16);
+
+ if ( macKey16 == NULL ) {
+ PR_fprintf(PR_STDERR,"Error deriving macKey16. Error %d \n", PR_GetError());
+ goto done;
+ }
+
+ wrappedKeyItem.data = (unsigned char *) encrypted_mac_key;
+ wrappedKeyItem.len = encrypted_mac_key.size();
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, macKey16, &wrappedKeyItem);
+ if ( wrapStatus == SECFailure) {
+ PR_fprintf(PR_STDERR,"Error wrapping macKey16. Error %d \n", PR_GetError());
+ goto done;
+ }
+
+ kekKey16 = PK11_Derive(new_kek_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, 16);
+
+ if ( kekKey16 == NULL ) {
+ goto done;
+ PR_fprintf(PR_STDERR,"Error deriving kekKey16. Error %d \n", PR_GetError());
+ }
+
+ wrappedKeyItem.data = (unsigned char *) encrypted_kek_key;
+ wrappedKeyItem.len = encrypted_mac_key.size();
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, kekKey16, &wrappedKeyItem);
+ if ( wrapStatus == SECFailure) {
+ PR_fprintf(PR_STDERR,"Error wrapping kekKey16. Error %d \n", PR_GetError());
+ goto done;
+ }
+
+ ComputeKeyCheckWithSymKey(new_auth_key, kc_auth_key);
+
+ ComputeKeyCheckWithSymKey(new_mac_key, kc_mac_key);
+
+ ComputeKeyCheckWithSymKey(new_kek_key, kc_kek_key);
+
+ result = newMasterVer +
+ Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)0x10) +
+ encrypted_auth_key +
+ Buffer(1, (BYTE)0x03) +
+ kc_auth_key +
+ Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)0x10) +
+ encrypted_mac_key +
+ Buffer(1, (BYTE)0x03) +
+ kc_mac_key +
+ Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)0x10) +
+ encrypted_kek_key +
+ Buffer(1, (BYTE)0x03) +
+ kc_kek_key;
+ output = result;
+
+ rv = PR_SUCCESS;
+
+done:
+
+ if ( kekKey16 != NULL) {
+ PK11_FreeSymKey( kekKey16);
+ kekKey16 = NULL;
+ }
+
+ if ( authKey16 != NULL) {
+ PK11_FreeSymKey( authKey16);
+ authKey16 = NULL;
+ }
+
+ if ( macKey16 != NULL) {
+ PK11_FreeSymKey( macKey16);
+ macKey16 = NULL;
+ }
+
+ if ( slot != NULL ) {
+ PK11_FreeSlot( slot);
+ slot = NULL;
+ }
+
+ if ( transportKey != NULL ) {
+ PK11_FreeSymKey( transportKey);
+ transportKey = NULL;
+ }
+
+ return rv;
+}
+
+void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype)
+{
+ if( ( cuidValue == NULL) || ( KDC == NULL)) {
+ return;
+ }
+
+ BYTE *lastTwoBytesOfAID = (BYTE *)cuidValue;
+// BYTE *ICFabricationDate = (BYTE *)cuidValue + 2;
+ BYTE *ICSerialNumber = (BYTE *)cuidValue + 4;
+// BYTE *ICBatchIdentifier = (BYTE *)cuidValue + 8;
+
+// Last 2 bytes of AID
+ KDC[0]= (BYTE)lastTwoBytesOfAID[0];
+ KDC[1]= (BYTE)lastTwoBytesOfAID[1];
+ KDC[2]= (BYTE)ICSerialNumber[0];
+ KDC[3]= (BYTE)ICSerialNumber[1];
+ KDC[4]= (BYTE)ICSerialNumber[2];
+ KDC[5]= (BYTE)ICSerialNumber[3];
+ KDC[6]= 0xF0;
+ KDC[7]= 0x01;
+ KDC[8]= (BYTE)lastTwoBytesOfAID[0];
+ KDC[9]= (BYTE)lastTwoBytesOfAID[1];
+ KDC[10]= (BYTE)ICSerialNumber[0];
+ KDC[11]= (BYTE)ICSerialNumber[1];
+ KDC[12]= (BYTE)ICSerialNumber[2];
+ KDC[13]= (BYTE)ICSerialNumber[3];
+ KDC[14]= 0x0F;
+ KDC[15]= 0x01;
+ if(keytype == enc)
+ return;
+
+ KDC[6]= 0xF0;
+ KDC[7]= 0x02;
+ KDC[14]= 0x0F;
+ KDC[15]= 0x02;
+ if(keytype == mac)
+ return;
+
+ KDC[6]= 0xF0;
+ KDC[7]= 0x03;
+ KDC[14]= 0x0F;
+ KDC[15]= 0x03;
+ if(keytype == kek)
+ return;
+
+}
+
+static int getMasterKeyVersion(char *newMasterKeyNameChars)
+{
+ if( newMasterKeyNameChars == NULL ||
+ strlen( newMasterKeyNameChars) < 3) {
+ return 0;
+ }
+
+ char masterKeyVersionNumber[3];
+ masterKeyVersionNumber[0]=newMasterKeyNameChars[1];
+ masterKeyVersionNumber[1]=newMasterKeyNameChars[2];
+ masterKeyVersionNumber[2]=0;
+ int newMasterKeyVesion = atoi(masterKeyVersionNumber);
+ return newMasterKeyVesion;
+}
+
+char *GetSharedSecretKeyName(char *newKeyName) {
+ if ( newKeyName && strlen( newKeyName ) > 0 ) {
+ if( strlen( sharedSecretSymKeyName) == 0) {
+ strncpy( sharedSecretSymKeyName, newKeyName, KEYNAMELENGTH);
+ }
+ }
+
+ return (char *) sharedSecretSymKeyName ;
+}
+
+void getFullName(char * fullMasterKeyName, char * masterKeyNameChars )
+{
+ if( fullMasterKeyName == NULL || masterKeyNameChars == NULL
+ || ( strlen(fullMasterKeyName) + strlen(masterKeyNameChars)) > KEYNAMELENGTH) {
+ return;
+ }
+ fullMasterKeyName[0]='\0';
+ if(strlen(masterKeyPrefix)>0)
+ strncpy(fullMasterKeyName,masterKeyPrefix, KEYNAMELENGTH);
+ strcat(fullMasterKeyName,masterKeyNameChars);
+}
+
+
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: DiversifyKey
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[B)[B
+ */
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey
+(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jstring, jstring);
+
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jstring keyInfo, jbyteArray CUIDValue, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet)
+{
+ PK11SymKey *encKey = NULL;
+ PK11SymKey *macKey = NULL;
+ PK11SymKey *kekKey = NULL;
+ Buffer encKeyBuff;
+ Buffer macKeyBuff;
+ Buffer kekKeyBuff;
+ char * oldMasterKeyNameChars=NULL;
+ Buffer old_kek_key_buff;
+ Buffer newMasterKeyBuffer;
+ char fullMasterKeyName[KEYNAMELENGTH];
+ char fullNewMasterKeyName[KEYNAMELENGTH];
+ PRBool specified_key_is_present = PR_TRUE;
+ PK11SymKey *old_kek_sym_key = NULL;
+
+ char *keySetStringChars = NULL;
+ if ( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+ int newMasterKeyVesion = 1;
+
+ /* find slot */
+ char *tokenNameChars = NULL;
+ char * newMasterKeyNameChars = NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11SlotInfo *internal = PK11_GetInternalKeySlot();
+
+ Buffer output;
+ PK11SlotInfo *newSlot =NULL;
+ char * newTokenNameChars = NULL;
+ char *keyInfoChars = NULL;
+
+ jbyte * cuidValue = NULL;
+ jbyte * old_kek_key = NULL;
+
+ PK11SymKey * masterKey = NULL;
+ PK11SymKey * oldMasterKey = NULL;
+
+ BYTE KDCenc[KEYLENGTH];
+ BYTE KDCmac[KEYLENGTH];
+ BYTE KDCkek[KEYLENGTH];
+
+ if( CUIDValue != NULL) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUIDValue, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ if( kekKeyArray != NULL) {
+ old_kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL);
+ }
+
+ if( old_kek_key == NULL) {
+ goto done;
+ }
+
+ PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! \n");
+
+ GetDiversificationData(cuidValue,KDCenc,enc);
+ GetDiversificationData(cuidValue,KDCmac,mac);
+ GetDiversificationData(cuidValue,KDCkek,kek);
+
+ if(tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ PR_fprintf(PR_STDOUT,"DiversifyKey: tokenNameChars %s slot %p \n", tokenNameChars,slot);
+ if( tokenNameChars != NULL) {
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+ }
+
+ if(newMasterKeyName)
+ {
+ /* newMasterKeyNameChars #02#01 */
+ newMasterKeyNameChars= (char *)(env)->GetStringUTFChars(newMasterKeyName, NULL);
+ }
+ /* fullNewMasterKeyName - no prefix #02#01 */
+ getFullName(fullNewMasterKeyName,newMasterKeyNameChars);
+ PR_fprintf(PR_STDOUT,"DiversifyKey: fullNewMasterKeyName %s . \n", fullNewMasterKeyName);
+
+ if(newTokenName)
+ {
+ newTokenNameChars = (char *)(env)->GetStringUTFChars(newTokenName, NULL);
+ newSlot = ReturnSlot(newTokenNameChars);
+ PR_fprintf(PR_STDOUT,"DiversifyKey: newTokenNameChars %s newSlot %p . \n", newTokenNameChars,newSlot);
+ if( newTokenNameChars != NULL) {
+ (env)->ReleaseStringUTFChars(newTokenName, (const char *)newTokenNameChars);
+ }
+ }
+
+ masterKey = ReturnSymKey(newSlot,fullNewMasterKeyName);
+
+ if(newMasterKeyNameChars) {
+ (env)->ReleaseStringUTFChars(newMasterKeyName, (const char *)newMasterKeyNameChars);
+ }
+
+ /* packing return */
+ if( keyInfo != NULL) {
+ keyInfoChars = (char *)(env)->GetStringUTFChars(keyInfo, NULL);
+ }
+
+ newMasterKeyVesion = getMasterKeyVersion(keyInfoChars);
+
+ if(keyInfoChars)
+ {
+ (env)->ReleaseStringUTFChars(keyInfo, (const char *)keyInfoChars);
+ }
+
+ /* NEW MASTER KEY VERSION */
+ newMasterKeyBuffer = Buffer((unsigned int) 1, (BYTE)newMasterKeyVesion);
+ if(oldMasterKeyName)
+ {
+ oldMasterKeyNameChars = (char *)(env)->GetStringUTFChars(oldMasterKeyName, NULL);
+ PR_fprintf(PR_STDOUT,"DiversifyKey oldMasterKeyNameChars %s \n", oldMasterKeyNameChars);
+ }
+ getFullName(fullMasterKeyName,oldMasterKeyNameChars);
+ PR_fprintf(PR_STDOUT,"DiversifyKey fullMasterKeyName %s \n", fullMasterKeyName);
+ if(newSlot == NULL) {
+ newSlot = slot;
+ }
+ if(strcmp( oldMasterKeyNameChars, "#01#01") == 0 || strcmp( oldMasterKeyNameChars, "#FF#01") == 0)
+ {
+ old_kek_key_buff = Buffer((BYTE*)old_kek_key, KEYLENGTH);
+ }else if(strcmp( oldMasterKeyNameChars, "#00#00") == 0)
+ {
+ /* print Debug message - do not create real keysetdata */
+ old_kek_key_buff = Buffer((BYTE*)"#00#00", 6);
+ output = Buffer((BYTE*)old_kek_key, KEYLENGTH);
+ }
+ else
+ {
+ oldMasterKey = ReturnSymKey(slot,fullMasterKeyName);
+ old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek);
+ if (oldMasterKey) {
+ PK11_FreeSymKey( oldMasterKey );
+ oldMasterKey = NULL;
+ }
+ }
+ if(oldMasterKeyNameChars) {
+ (env)->ReleaseStringUTFChars(oldMasterKeyName, (const char *)oldMasterKeyNameChars);
+ }
+
+ /* special case #01#01 */
+ if (fullNewMasterKeyName != NULL && strcmp(fullNewMasterKeyName, "#01#01") == 0)
+ {
+ Buffer empty = Buffer();
+
+ encKey = ReturnDeveloperSymKey(internal,(char *) "auth", keySetString, empty);
+
+ if ( encKey == NULL ) {
+ goto done;
+ }
+ PR_fprintf(PR_STDOUT, "Special case dev key set for DiversifyKey!\n");
+
+ macKey = ReturnDeveloperSymKey(internal, (char *) "mac", keySetString, empty);
+ if ( macKey == NULL ) {
+ goto done;
+ }
+
+ kekKey = ReturnDeveloperSymKey(internal, (char *) "kek", keySetString, empty);
+
+ if ( kekKey == NULL ) {
+ goto done;
+ }
+
+ } else {
+ PR_fprintf(PR_STDOUT,"DiversifyKey: Compute card key on token case ! \n");
+ /* compute card key */
+ encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc);
+ macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac);
+ kekKey = ComputeCardKeyOnSoftToken(masterKey, KDCkek);
+
+ /* Fixes Bugscape Bug #55855: TKS crashes if specified key
+ * is not present -- for each portion of the key, check if
+ * the PK11SymKey is NULL before sending it to PK11_GetKeyData()!
+ */
+ if( encKey == NULL) {
+ PR_fprintf(PR_STDERR,"Can't create encKey in DiversifyKey! \n");
+ specified_key_is_present = PR_FALSE;
+ goto done;
+ }
+ if( macKey == NULL) {
+ PR_fprintf(PR_STDERR,"Can't create macKey in DiversifyKey! \n");
+ specified_key_is_present = PR_FALSE;
+ goto done;
+ }
+ if( kekKey == NULL) {
+ PR_fprintf(PR_STDERR,"Can't create kekKey in DiversifyKey! \n");
+ specified_key_is_present = PR_FALSE;
+ goto done;
+ }
+ }
+
+ if (old_kek_sym_key != NULL) {
+ CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(),
+ old_kek_sym_key,
+ encKey,
+ macKey,
+ kekKey,
+ output); }
+ else {
+ old_kek_sym_key = ReturnDeveloperSymKey(slot, (char *) "kek", keySetString, old_kek_key_buff);
+ CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(),
+ old_kek_sym_key,
+ encKey,
+ macKey,
+ kekKey,
+ output);
+ }
+
+done:
+ if (masterKey != NULL) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if (encKey != NULL) {
+ PK11_FreeSymKey( encKey );
+ encKey = NULL;
+ }
+
+ if (macKey != NULL) {
+ PK11_FreeSymKey( macKey );
+ macKey = NULL;
+ }
+
+ if (kekKey != NULL) {
+ PK11_FreeSymKey( kekKey );
+ kekKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if( specified_key_is_present )
+ {
+ if(output.size()>0)
+ handleBA = (env)->NewByteArray( output.size());
+ else
+ handleBA = (env)->NewByteArray(1);
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+ memcpy(handleBytes, (BYTE*)output,output.size());
+
+ if( handleBytes != NULL) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+ }
+
+ if( cuidValue != NULL) {
+ (env)->ReleaseByteArrayElements(CUIDValue, cuidValue, JNI_ABORT);
+ }
+
+ if( kekKeyArray != NULL) {
+ (env)->ReleaseByteArrayElements(kekKeyArray, old_kek_key, JNI_ABORT);
+ }
+
+ if((newSlot != slot) && newSlot) {
+ PK11_FreeSlot( newSlot);
+ newSlot = NULL;
+ }
+
+ if( slot ) {
+ PK11_FreeSlot( slot);
+ slot = NULL;
+ }
+
+ if( internal) {
+ PK11_FreeSlot( internal);
+ internal = NULL;
+ }
+
+ return handleBA;
+}
+
+PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm)
+{
+ PK11SymKey * unWrappedSymKey = NULL;
+ int bufSize = 48;
+ unsigned char outbuf[bufSize];
+ int final_len = 0;
+ SECStatus s = SECSuccess;
+ PK11Context * EncContext = NULL;
+ SECItem unWrappedKeyItem = { siBuffer, NULL, 0};
+ PK11SymKey *unwrapper = NULL;
+
+ PR_fprintf( PR_STDOUT,
+ "Creating UnWrappedSymKey on token. \n");
+
+ if ( (slot == NULL) || (unWrappingKey == NULL) ||
+ (keyToBeUnWrapped == NULL) ||
+ (sizeOfKeyToBeUnWrapped != DES3_LENGTH)
+ ) {
+ return NULL;
+ }
+
+ PK11SlotInfo *unwrapKeySlot = PK11_GetSlotFromKey( unWrappingKey );
+
+ if ( unwrapKeySlot != slot ) {
+ unwrapper = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, unWrappingKey);
+ }
+
+ SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL);
+ if ( SecParam == NULL) {
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(CKM_DES3_ECB,
+ CKA_ENCRYPT,
+ unWrappingKey, SecParam);
+
+ if ( EncContext == NULL) {
+ goto done;
+ }
+
+ s = PK11_CipherOp(EncContext, outbuf, &final_len, sizeof( outbuf), keyToBeUnWrapped,
+ sizeOfKeyToBeUnWrapped);
+
+ if ( s != SECSuccess) {
+ goto done;
+ }
+
+ if ( final_len != DES3_LENGTH ) {
+ goto done;
+ }
+
+ unWrappedKeyItem.data = outbuf;
+ unWrappedKeyItem.len = final_len;
+
+
+ /* Now try to unwrap our key into the token */
+ unWrappedSymKey = PK11_UnwrapSymKeyWithFlagsPerm(unwrapper ? unwrapper : unWrappingKey,
+ CKM_DES3_ECB,SecParam, &unWrappedKeyItem,
+ CKM_DES3_ECB,
+ CKA_UNWRAP,
+ sizeOfKeyToBeUnWrapped, 0, isPerm );
+
+done:
+
+ if( SecParam != NULL ) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ SecParam = NULL;
+ }
+
+ if( EncContext != NULL ) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ EncContext = NULL;
+ }
+
+ if( unwrapper != NULL ) {
+ PK11_FreeSymKey( unwrapper );
+ unwrapper = NULL;
+ }
+
+ if( unwrapKeySlot != NULL) {
+ PK11_FreeSlot( unwrapKeySlot);
+ unwrapKeySlot = NULL;
+ }
+
+ PR_fprintf( PR_STDOUT,
+ "UnWrappedSymKey on token result: %p \n",unWrappedSymKey);
+
+ return unWrappedSymKey;
+}
+//Return default keyset developer key. Either auth, mac, or kek
+PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey)
+{
+ const int maxKeyNameSize = 56;
+ PK11SymKey *devSymKey = NULL;
+ PK11SymKey *transportKey = NULL;
+ char devKeyName[maxKeyNameSize];
+
+ SECStatus rv = SECSuccess;
+
+ BYTE sessionKey[DES3_LENGTH];
+
+ if( slot == NULL || keyType == NULL || keySet == NULL) {
+ return NULL;
+ }
+
+ snprintf(devKeyName,maxKeyNameSize,"%s-%sKey", keySet, keyType);
+
+ devSymKey = ReturnSymKey( slot, devKeyName );
+
+ // Try to create the key once and leave it there.
+ if( devSymKey == NULL ) {
+ PR_fprintf(PR_STDOUT, "Can't find devSymKey, try to create it on token. \n");
+ if ( inputKey.size() == DES2_LENGTH ) { //Any other size ignored
+ transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
+
+ if( transportKey == NULL) {
+ PR_fprintf(PR_STDERR,"Can't get transport key in ReturnDeveloperSymKey! \n");
+ goto done;
+ }
+
+ /* convert 16-byte to 24-byte triple-DES key */
+ memcpy(sessionKey, inputKey, DES2_LENGTH);
+ memcpy(sessionKey+ DES2_LENGTH, inputKey, EIGHT_BYTES);
+
+ //Unwrap this thing on there as permanent, so we don't have to create it again for a given keySet.
+ if( transportKey) {
+ devSymKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, sessionKey, sizeof(sessionKey), PR_TRUE);
+ }
+
+ PR_fprintf(PR_STDERR,"Tried to create devSymKey %p \n",devSymKey);
+
+ rv = SECSuccess;
+ if( devSymKey ) {
+ rv = PK11_SetSymKeyNickname( devSymKey, devKeyName );
+
+ if ( rv != SECSuccess ) {
+ PR_fprintf(PR_STDERR, "Can't set the nickname of just written devKey! \n");
+ }
+ }
+ }
+ }
+
+done:
+ if( transportKey ) {
+ PK11_FreeSymKey( transportKey );
+ transportKey = NULL;
+ }
+
+ // Dont' free slot , let the caller.
+ return devSymKey;
+}
+
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: SetDefaultPrefix
+ * Signature: (Ljava/lang/String;)V
+ */
+extern "C" JNIEXPORT void JNICALL Java_com_netscape_symkey_SessionKey_SetDefaultPrefix
+(JNIEnv *, jclass, jstring);
+extern "C" JNIEXPORT void
+JNICALL Java_com_netscape_symkey_SessionKey_SetDefaultPrefix(JNIEnv * env, jclass this2, jstring masterPrefix)
+{
+ char *masterPrefixChars;
+
+ masterPrefixChars = (char *)(env)->GetStringUTFChars(masterPrefix, NULL);
+
+ if(masterPrefixChars)
+ strcpy(masterKeyPrefix,masterPrefixChars);
+ else
+ masterKeyPrefix[0] = '\0';
+
+ if(masterPrefixChars)
+ {
+ (env)->ReleaseStringUTFChars(masterPrefix, (const char *)masterPrefixChars);
+ }
+
+ return;
+}
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.h b/base/symkey/src/com/netscape/symkey/SymKey.h
new file mode 100644
index 000000000..5a53d48c9
--- /dev/null
+++ b/base/symkey/src/com/netscape/symkey/SymKey.h
@@ -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.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+#ifndef _TKSSYMKEY_H_
+#define _TKSSYMKEY_H_
+
+extern PK11SlotInfo *defaultSlot;
+
+typedef enum {
+ enc,
+ mac,
+ kek
+ } keyType;
+#define KEYLENGTH 16
+#define PREFIXLENGHT 128
+#define DES2_LENGTH 16
+#define DES3_LENGTH 24
+#define EIGHT_BYTES 8
+#define KEYNAMELENGTH PREFIXLENGHT+7
+#define TRANSPORT_KEY_NAME "sharedSecret"
+#define DEFKEYSET_NAME "defKeySet"
+
+extern char masterKeyPrefix[PREFIXLENGHT];
+extern char sharedSecretSymKeyName[KEYNAMELENGTH];
+
+void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype);
+PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname);
+void GetKeyName(jbyte *keyVersion,char *keyname);
+PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data);
+PRStatus EncryptData(const Buffer &kek_key, PK11SymKey *card_key, Buffer &input, Buffer &output);
+PK11SlotInfo *ReturnSlot(char *tokenNameChars);
+PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot);
+PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm);
+PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey);
+
+char *GetSharedSecretKeyName(char *newKeyName);
+
+#define DES2_WORKAROUND
+#endif /* _TKSSYMKEY_H_ */
+