|
|
3630b7 |
diff --git a/.gitignore b/.gitignore
|
|
|
3630b7 |
index 2f0768d..4e11a3c 100644
|
|
|
3630b7 |
--- a/.gitignore
|
|
|
3630b7 |
+++ b/.gitignore
|
|
|
3630b7 |
@@ -18,6 +18,7 @@ libtool
|
|
|
3630b7 |
ltmain.sh
|
|
|
3630b7 |
man/man1/pkcsconf.1
|
|
|
3630b7 |
man/man1/pkcsicsf.1
|
|
|
3630b7 |
+man/man1/pkcscca.1
|
|
|
3630b7 |
man/man5/opencryptoki.conf.5
|
|
|
3630b7 |
man/man7/opencryptoki.7
|
|
|
3630b7 |
man/man8/pkcsslotd.8
|
|
|
3630b7 |
diff --git a/configure.in b/configure.in
|
|
|
3630b7 |
index 8a47472..083c597 100644
|
|
|
3630b7 |
--- a/configure.in
|
|
|
3630b7 |
+++ b/configure.in
|
|
|
3630b7 |
@@ -739,6 +739,7 @@ AC_CONFIG_FILES([Makefile usr/Makefile \
|
|
|
3630b7 |
usr/sbin/pkcsslotd/Makefile \
|
|
|
3630b7 |
usr/sbin/pkcsconf/Makefile \
|
|
|
3630b7 |
usr/sbin/pkcsicsf/Makefile \
|
|
|
3630b7 |
+ usr/sbin/pkcscca/Makefile \
|
|
|
3630b7 |
usr/sbin/pkcscca_migrate/Makefile \
|
|
|
3630b7 |
usr/lib/pkcs11/methods/Makefile \
|
|
|
3630b7 |
usr/lib/pkcs11/leeds_stdll/Makefile \
|
|
|
3630b7 |
@@ -761,6 +762,7 @@ AC_CONFIG_FILES([Makefile usr/Makefile \
|
|
|
3630b7 |
man/man1/Makefile \
|
|
|
3630b7 |
man/man1/pkcsconf.1 \
|
|
|
3630b7 |
man/man1/pkcsicsf.1 \
|
|
|
3630b7 |
+ man/man1/pkcscca.1 \
|
|
|
3630b7 |
man/man5/Makefile \
|
|
|
3630b7 |
man/man5/opencryptoki.conf.5 \
|
|
|
3630b7 |
man/man7/Makefile \
|
|
|
3630b7 |
diff --git a/doc/README.cca_stdll b/doc/README.cca_stdll
|
|
|
3630b7 |
index f535dfa..a0d13f1 100644
|
|
|
3630b7 |
--- a/doc/README.cca_stdll
|
|
|
3630b7 |
+++ b/doc/README.cca_stdll
|
|
|
3630b7 |
@@ -1,24 +1,173 @@
|
|
|
3630b7 |
+CCA TOKEN
|
|
|
3630b7 |
|
|
|
3630b7 |
-README for the CCA secure-key token
|
|
|
3630b7 |
+OverView
|
|
|
3630b7 |
+--------
|
|
|
3630b7 |
+The CCA token is a secure key token.
|
|
|
3630b7 |
+A Secure key - key value does not exist in the clear outside of the HSM
|
|
|
3630b7 |
+(secure, tamper-resistent boundary of the card). It is a clear key wrapped
|
|
|
3630b7 |
+with the appropriate MasterKey that has been installed into the secure hardware.
|
|
|
3630b7 |
+A clear key is generated in the hardware, wrapped with the appropriate
|
|
|
3630b7 |
+master key that has been installed into the hardware. The wrapped key is then
|
|
|
3630b7 |
+passed back to the invoker. Upon an encryption and/or decryption request,
|
|
|
3630b7 |
+the wrapped key and the data to be encrypted are passed into the hardware.
|
|
|
3630b7 |
+The wrapped key is verified, and the clear key is used to encrypt and/or
|
|
|
3630b7 |
+decrypt the data. All this is done in the CCA hardware.
|
|
|
3630b7 |
|
|
|
3630b7 |
-Kent Yoder <yoder1@us.ibm.com>
|
|
|
3630b7 |
+Within opencryptoki, this wrapped key value is stored in the CKA_IBM_OPAQUE
|
|
|
3630b7 |
+attribute rather than the CKA_VALUE attribute.
|
|
|
3630b7 |
|
|
|
3630b7 |
- The key used to encrypt private objects on disk is a secure key.
|
|
|
3630b7 |
+Pre-requisites:
|
|
|
3630b7 |
+The CCA token requires cca library, libcsulcca.so, which is part of the
|
|
|
3630b7 |
+csulcca rpm.
|
|
|
3630b7 |
+It also requires proper configuration and installation of the MK keys into
|
|
|
3630b7 |
+the hardware which is outside the scope of this document.
|
|
|
3630b7 |
|
|
|
3630b7 |
- The key used to encrypt that secure key is based on the hash of the
|
|
|
3630b7 |
-USER and SO pins. Therefore it is a clear key and software is used to
|
|
|
3630b7 |
-do the encryption/decryption of the secure key.
|
|
|
3630b7 |
+Configuration
|
|
|
3630b7 |
+-------------
|
|
|
3630b7 |
|
|
|
3630b7 |
-MK_USER: The secure key used for internal on-disk encryption, encrypted
|
|
|
3630b7 |
+To use the CCA token a slot entry must be defined in the
|
|
|
3630b7 |
+opencryptoki.conf configuration file that sets the stdll attribute to
|
|
|
3630b7 |
+libcsulcca.so.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+The CCA token also requires that the appropriate master keys have
|
|
|
3630b7 |
+been installed into the hardware. The corresponding driver must also be
|
|
|
3630b7 |
+loaded, i.e. modprobe z90crypt.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+CCA Token Objects
|
|
|
3630b7 |
+-------------------------
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Opencryptoki stores token objects on disk. Public token objects are not
|
|
|
3630b7 |
+encrypted. Private token objects are encrypted.
|
|
|
3630b7 |
+Versions of opencryptoki prior to version 3, used a CCA generated secure key
|
|
|
3630b7 |
+(des3 key) and the crypto adapter to encrypt the private token object's data.
|
|
|
3630b7 |
+In version 3, a clear key (des3 key) and software crypto (openssl) are used
|
|
|
3630b7 |
+to encrypt this data.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Migration Information
|
|
|
3630b7 |
+---------------------
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Migrating version 2 private token objects to version 3 is ONLY required if
|
|
|
3630b7 |
+the system will run opencryptoki version 3 and will use private token
|
|
|
3630b7 |
+objects saved or preserved from version 2.
|
|
|
3630b7 |
+Note, public token objects do not need to be migrated.
|
|
|
3630b7 |
+If there are no private token objects from version 2, then the version 3
|
|
|
3630b7 |
+does not require any migrating.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+In version 2 private token objects are encrypted and decrypted with a secure
|
|
|
3630b7 |
+key in the crypto adapter. In version 3, this encryption and decryption is
|
|
|
3630b7 |
+done with a clear key using software crypto. Therefore, opencryptoki
|
|
|
3630b7 |
+version 3, will not succesfully decrypt a version 2 private token object.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Version 2 private token objects must be "migrated" to version 3 so that
|
|
|
3630b7 |
+opencryptoki version 3 can access these objects. This migration will
|
|
|
3630b7 |
+decrypt the objects using the CCA call, CSNBDEC and the current
|
|
|
3630b7 |
+opencryptoki key stored in MK_USER. The objects will then be re-encrypted
|
|
|
3630b7 |
+using software crypto. The key bits that are stored in MK_USER will then be
|
|
|
3630b7 |
+used as a clear key.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Once the migration has completed, these private token objects should then be
|
|
|
3630b7 |
+accessable to version 3.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Migration Steps
|
|
|
3630b7 |
+---------------
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+1. Either update or install version 3.
|
|
|
3630b7 |
+a. Update to opencryptoki version 3. In most linux distributions, an update
|
|
|
3630b7 |
+from version 2 to version 3 will preserve the contents of the CCA data-store.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+b. Install opencryptoki version 3. In most distributions, an install will
|
|
|
3630b7 |
+remove the contents of the CCA data-store. You will essentially be starting
|
|
|
3630b7 |
+from the beginning and have to initialize the CCA token.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+In this scenario, if a prior version of opencryptoki had been running on the
|
|
|
3630b7 |
+system, and you wanted to preserve your token objects, you will have saved
|
|
|
3630b7 |
+or backed them up somewhere.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+2. Backup the CCA data-store before migrating. It is always a good idea to
|
|
|
3630b7 |
+back up the data in case the migration is unsuccessful or data is corrupted.
|
|
|
3630b7 |
+The data-store is the directory in which the CCA token information is stored
|
|
|
3630b7 |
+on disk. In most distributions it can be found in /var/lib/opencryptoki/ccatok.
|
|
|
3630b7 |
+Within this directory there is,
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+MK_USER: The des3 key used for internal on-disk encryption, encrypted
|
|
|
3630b7 |
under the USER's PIN by software routines
|
|
|
3630b7 |
|
|
|
3630b7 |
-MK_SO: The secure key used for internal on-disk encryption, encrypted
|
|
|
3630b7 |
+MK_SO: The des3 key used for internal on-disk encryption, encrypted
|
|
|
3630b7 |
under the SO's PIN by software routines
|
|
|
3630b7 |
|
|
|
3630b7 |
-So, MK_USER and MK_SO contain the same key, encrypted under different PINs
|
|
|
3630b7 |
+NKTOK.DAT: Token information.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+TOK_OBJ: The directory in which token objects are stored.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+TOK_OBJ/OBJ.IDX: A list of current token objects.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+**NOTE: MK_USER and MK_SO contain the same key, encrypted under
|
|
|
3630b7 |
+different PINs
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+3. Ensure no opencryptoki processes are running. Stop the pkcsslotd daemon
|
|
|
3630b7 |
+if it is running.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+4. Run the pkcscca tool to perform the migration.
|
|
|
3630b7 |
+For example,
|
|
|
3630b7 |
+ pkcscca -m v2objectsv3 -v
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Note that the "-v" option will allow you to see which objects did and did not
|
|
|
3630b7 |
+get migrated. Specify the "-d" flag if you wish to migrate CCA token objects
|
|
|
3630b7 |
+stored in a data-store different from the default, /var/lib/opencryptoki/ccatok.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+5. (Optional) Removing shared memory may be required to pick up
|
|
|
3630b7 |
+the newly migrated objects.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+CCA token's shared memory segment tracks its token objects.
|
|
|
3630b7 |
+Token objects stored on disk are only loaded into shared memory
|
|
|
3630b7 |
+when the shared memory is created. The shared memory is usually
|
|
|
3630b7 |
+created after a reboot, an install, or an update of the opencryptoki package.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+If another opencryptoki process accessed the CCA token after install
|
|
|
3630b7 |
+or update, then opencryptoki will have loaded all the token objects into
|
|
|
3630b7 |
+shared memory, except for the private token objects requiring migration,
|
|
|
3630b7 |
+since they will have failed decryption. Subsequent calls to the
|
|
|
3630b7 |
+opencryptoki api will not find these objects since they have not
|
|
|
3630b7 |
+been loaded into shared memory. Opencryptoki won't read the
|
|
|
3630b7 |
+objects from disk and load into shared memory again until the next time
|
|
|
3630b7 |
+shared memory is created.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+So, in this case, shared memory must be removed and created again so
|
|
|
3630b7 |
+that opencryptoki can successfuly load all the token objects including the
|
|
|
3630b7 |
+newly migrated private token objects into CCA token's shared memory segment.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+Remove shared memory if,
|
|
|
3630b7 |
+ - after updating or installing, any opencryptoki processes or tools tried
|
|
|
3630b7 |
+ to access the CCA token before migrating CCA token's private token
|
|
|
3630b7 |
+ objects. For example, the pkcsconf command was run.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ The pre-migrated objects will have failed decryption and not
|
|
|
3630b7 |
+ been loaded into shared memory. A reboot or removing shared memory
|
|
|
3630b7 |
+ will cause the token to create shared memory again and load the newly
|
|
|
3630b7 |
+ migrated private token objects into it.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+CCA's shared memory can be removed two ways.
|
|
|
3630b7 |
+ 1. a reboot
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ 2. remove the shared memory file,
|
|
|
3630b7 |
+ i.e. "rm /dev/shm/var.lib.opencryptoki.ccatok"
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ Notes: (1). Ensure that no opencryptoki processes are running
|
|
|
3630b7 |
+ before removing the shared memory. Otherwise, you risk corrupting
|
|
|
3630b7 |
+ any running opencryptoki processes.
|
|
|
3630b7 |
+ (2). If you have installed opencryptoki manually (not via a distro
|
|
|
3630b7 |
+ rpm) the CCA token shared memory segment may be named
|
|
|
3630b7 |
+ usr.local.var.lib.opencryptoki.ccatok.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+The next opencryptoki process to run will cause opencryptoki to create
|
|
|
3630b7 |
+a shared memory segment for the token and load the newly migrated objects
|
|
|
3630b7 |
+as well as any other token objects for the token.
|
|
|
3630b7 |
|
|
|
3630b7 |
-PKCS#11 Notes:
|
|
|
3630b7 |
+6. After a successful migration, the CCA private token objects should be
|
|
|
3630b7 |
+encrypted and ready to be accessed by opencryptoki version 3.
|
|
|
3630b7 |
|
|
|
3630b7 |
-DES/3DES PKCS#11 key objects have the CCA key identifier stored in the CKA_VALUE
|
|
|
3630b7 |
-attribute. Usually the CKA_VALUE attribute would hold a plaintext key, however
|
|
|
3630b7 |
-in this case, the id used to reference the secure key is stored here.
|
|
|
3630b7 |
+TroubleShooting:
|
|
|
3630b7 |
+1. If version 3 cannot find the newly migrated CCA private token objects,
|
|
|
3630b7 |
+reboot or remove the shared memory file. This will cause token to create
|
|
|
3630b7 |
+shared memory again and load the newly migrated private token objects
|
|
|
3630b7 |
+into shared memory.
|
|
|
3630b7 |
diff --git a/man/man1/Makefile.am b/man/man1/Makefile.am
|
|
|
3630b7 |
index a5f3c17..41a1259 100644
|
|
|
3630b7 |
--- a/man/man1/Makefile.am
|
|
|
3630b7 |
+++ b/man/man1/Makefile.am
|
|
|
3630b7 |
@@ -1,3 +1,3 @@
|
|
|
3630b7 |
-man1_MANS=pkcsconf.1 pkcsicsf.1
|
|
|
3630b7 |
+man1_MANS=pkcsconf.1 pkcsicsf.1 pkcscca.1
|
|
|
3630b7 |
EXTRA_DIST = $(man1_MANS)
|
|
|
3630b7 |
CLEANFILES = $(man1_MANS)
|
|
|
3630b7 |
diff --git a/man/man1/pkcscca.1.in b/man/man1/pkcscca.1.in
|
|
|
3630b7 |
new file mode 100644
|
|
|
3630b7 |
index 0000000..c6e49d6
|
|
|
3630b7 |
--- /dev/null
|
|
|
3630b7 |
+++ b/man/man1/pkcscca.1.in
|
|
|
3630b7 |
@@ -0,0 +1,45 @@
|
|
|
3630b7 |
+.TH PKCSCCA 1 "September 2014" "@PACKAGE_VERSION@" "openCryptoki"
|
|
|
3630b7 |
+.SH NAME
|
|
|
3630b7 |
+pkcscca \- configuration utility for the CCA token
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH SYNOPSIS
|
|
|
3630b7 |
+\fBpkcscca\fP
|
|
|
3630b7 |
+[\fB-h\fP]
|
|
|
3630b7 |
+[\fB-m v2objectsv3\fP]
|
|
|
3630b7 |
+[\fIOPTIONS\fP]
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH DESCRIPTION
|
|
|
3630b7 |
+The \fBpkcscca\fP utility assists in administering the CCA token. Currently it
|
|
|
3630b7 |
+migrates opencryptoki version 2 private token objects to the encryption
|
|
|
3630b7 |
+method used in opencryptoki version 3.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+In verion 2 of opencryptoki, CCA private token objects were encrypted in CCA
|
|
|
3630b7 |
+hardware. In version 3 these objects are encrypted in software. The
|
|
|
3630b7 |
+\fBv2objectsv3\fP migration option migrates these version 2 objects by
|
|
|
3630b7 |
+decrypting them in CCA hardware using a secure key and then re-encrypting
|
|
|
3630b7 |
+them in software using a software key. Afterwards, v2 objects can be accessed
|
|
|
3630b7 |
+in version 3.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH "FLAGS"
|
|
|
3630b7 |
+.IP "\fB-h\fP" 10
|
|
|
3630b7 |
+show usage information
|
|
|
3630b7 |
+.IP "\fB-m\fP" 10
|
|
|
3630b7 |
+perform a migration. \fBv2objectsv3\fP is currently the only type of migration
|
|
|
3630b7 |
+supported and must be specified along with this flag.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH "MIGRATION OPTIONS"
|
|
|
3630b7 |
+.IP "\fB-d|--datastore\fP \fIdirectory\fp" 10
|
|
|
3630b7 |
+the directory where the CCA token information is kept. This directory will be
|
|
|
3630b7 |
+used to locate the private token objects to be migrated. i.e. /var/lib/opencryptoki/ccatok
|
|
|
3630b7 |
+.IP "\fB-v|--verbose\fP" 10
|
|
|
3630b7 |
+provide detailed output during migration
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH "FILES"
|
|
|
3630b7 |
+.IP "/var/lib/opencryptoki/ccatok/TOK_OBJ/OBJ.IDX"
|
|
|
3630b7 |
+contains current list of public and private token objects for the CCA token.
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+.SH SEE ALSO
|
|
|
3630b7 |
+.PD 0
|
|
|
3630b7 |
+.TP
|
|
|
3630b7 |
+\fBREADME.cca_stdll\fP (in system's doc directory)
|
|
|
3630b7 |
+.PD
|
|
|
3630b7 |
diff --git a/usr/sbin/Makefile.am b/usr/sbin/Makefile.am
|
|
|
3630b7 |
index 1e61ece..3757735 100644
|
|
|
3630b7 |
--- a/usr/sbin/Makefile.am
|
|
|
3630b7 |
+++ b/usr/sbin/Makefile.am
|
|
|
3630b7 |
@@ -7,4 +7,8 @@ if ENABLE_ICSFTOK
|
|
|
3630b7 |
PKCSICSF_DIR = pkcsicsf
|
|
|
3630b7 |
endif
|
|
|
3630b7 |
|
|
|
3630b7 |
-SUBDIRS = pkcsslotd pkcsconf $(PKCSICSF_DIR) $(PKCSCCA_MIGRATE_DIR)
|
|
|
3630b7 |
+if ENABLE_CCATOK
|
|
|
3630b7 |
+PKCSCCA_DIR = pkcscca
|
|
|
3630b7 |
+endif
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+SUBDIRS = pkcsslotd pkcsconf $(PKCSICSF_DIR) $(PKCSCCA_MIGRATE_DIR) $(PKCSCCA_DIR)
|
|
|
3630b7 |
diff --git a/usr/sbin/pkcscca/Makefile.am b/usr/sbin/pkcscca/Makefile.am
|
|
|
3630b7 |
new file mode 100644
|
|
|
3630b7 |
index 0000000..4d5f6c7
|
|
|
3630b7 |
--- /dev/null
|
|
|
3630b7 |
+++ b/usr/sbin/pkcscca/Makefile.am
|
|
|
3630b7 |
@@ -0,0 +1,14 @@
|
|
|
3630b7 |
+sbin_PROGRAMS=pkcscca
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+pkcscca_CFLAGS = -DSTDLL_NAME=\"pkcscca\"
|
|
|
3630b7 |
+pkcscca_LDFLAGS = -lcrypto -ldl
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+# Not all versions of automake observe sbinname_CFLAGS
|
|
|
3630b7 |
+AM_CFLAGS = -DSTDLL_NAME=\"pkcscca\"
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+pkcscca_SOURCES = ../../lib/pkcs11/common/p11util.c \
|
|
|
3630b7 |
+ ../../lib/pkcs11/common/sw_crypt.c \
|
|
|
3630b7 |
+ ../../lib/pkcs11/common/log.c \
|
|
|
3630b7 |
+ pkcscca.c
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+INCLUDES = -I. -I../../include/pkcs11 -I../../lib/pkcs11/common
|
|
|
3630b7 |
diff --git a/usr/sbin/pkcscca/pkcscca.c b/usr/sbin/pkcscca/pkcscca.c
|
|
|
3630b7 |
new file mode 100644
|
|
|
3630b7 |
index 0000000..a1e3bae
|
|
|
3630b7 |
--- /dev/null
|
|
|
3630b7 |
+++ b/usr/sbin/pkcscca/pkcscca.c
|
|
|
3630b7 |
@@ -0,0 +1,661 @@
|
|
|
3630b7 |
+/*
|
|
|
3630b7 |
+ * Licensed materials - Property of IBM
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ * pkcscca - A tool for PKCS#11 CCA token.
|
|
|
3630b7 |
+ * Currently, only migrates CCA private token objects from CCA cipher
|
|
|
3630b7 |
+ * to using a software cipher.
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ * Copyright (C) International Business Machines Corp. 2014
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+#include <stdio.h>
|
|
|
3630b7 |
+#include <stdlib.h>
|
|
|
3630b7 |
+#include <unistd.h>
|
|
|
3630b7 |
+#include <string.h>
|
|
|
3630b7 |
+#include <getopt.h>
|
|
|
3630b7 |
+#include <termios.h>
|
|
|
3630b7 |
+#include <dlfcn.h>
|
|
|
3630b7 |
+#include <errno.h>
|
|
|
3630b7 |
+#include <sys/types.h>
|
|
|
3630b7 |
+#include <sys/stat.h>
|
|
|
3630b7 |
+#include <linux/limits.h>
|
|
|
3630b7 |
+#include <openssl/evp.h>
|
|
|
3630b7 |
+#include <pkcs11types.h>
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+#include "sw_crypt.h"
|
|
|
3630b7 |
+#include "pkcscca.h"
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+void (*CSNBDEC)();
|
|
|
3630b7 |
+int v_flag = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int compute_hash(int hash_type, int buf_size, char *buf, char *digest)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ EVP_MD_CTX md_ctx;
|
|
|
3630b7 |
+ unsigned int result_size;
|
|
|
3630b7 |
+ int rc;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ switch (hash_type) {
|
|
|
3630b7 |
+ case HASH_SHA1:
|
|
|
3630b7 |
+ rc = EVP_DigestInit(&md_ctx, EVP_sha1());
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+ case HASH_MD5:
|
|
|
3630b7 |
+ rc = EVP_DigestInit(&md_ctx, EVP_md5());
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+ default:
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (rc != 1) {
|
|
|
3630b7 |
+ fprintf(stderr, "EVP_DigestInit() failed: rc = %d\n", rc);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ rc = EVP_DigestUpdate(&md_ctx, buf, buf_size);
|
|
|
3630b7 |
+ if (rc != 1) {
|
|
|
3630b7 |
+ fprintf(stderr, "EVP_DigestUpdate() failed: rc = %d\n", rc);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ result_size = EVP_MD_CTX_size(&md_ctx);
|
|
|
3630b7 |
+ rc = EVP_DigestFinal(&md_ctx, (unsigned char *)digest, &result_size);
|
|
|
3630b7 |
+ if (rc != 1) {
|
|
|
3630b7 |
+ fprintf(stderr, "EVP_DigestFinal() failed: rc = %d\n", rc);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return 0;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int cca_decrypt(unsigned char *in_data, unsigned long in_data_len,
|
|
|
3630b7 |
+ unsigned char *out_data, unsigned long *out_data_len,
|
|
|
3630b7 |
+ unsigned char *init_v, unsigned char *key_value)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ long return_code, reason_code, rule_array_count, length;
|
|
|
3630b7 |
+ unsigned char chaining_vector[18];
|
|
|
3630b7 |
+ unsigned char rule_array[256];
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ length = in_data_len;
|
|
|
3630b7 |
+ rule_array_count = 1;
|
|
|
3630b7 |
+ memcpy(rule_array, "CBC ", 8);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ CSNBDEC(&return_code, &reason_code, NULL, NULL, key_value,
|
|
|
3630b7 |
+ &length, in_data, init_v, &rule_array_count,
|
|
|
3630b7 |
+ rule_array, chaining_vector, out_data);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (return_code != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "CSNBDEC (DES3 DECRYPT) failed: return_code=%ld reason_code=%ld\n", return_code, reason_code);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ *out_data_len = length;
|
|
|
3630b7 |
+ return 0;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int reencrypt_private_token_object(unsigned char *data, unsigned long len,
|
|
|
3630b7 |
+ unsigned char *new_cipher,
|
|
|
3630b7 |
+ unsigned long *new_cipher_len,
|
|
|
3630b7 |
+ unsigned char *masterkey)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ unsigned char *clear = NULL;
|
|
|
3630b7 |
+ unsigned char des3_key[64];
|
|
|
3630b7 |
+ unsigned char sw_des3_key[3 * DES_KEY_SIZE];
|
|
|
3630b7 |
+ unsigned long clear_len;
|
|
|
3630b7 |
+ CK_RV rc;
|
|
|
3630b7 |
+ int ret;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* cca wants 8 extra bytes for padding purposes */
|
|
|
3630b7 |
+ clear_len = len + 8;
|
|
|
3630b7 |
+ clear = (unsigned char *) malloc(clear_len);
|
|
|
3630b7 |
+ if (!clear) {
|
|
|
3630b7 |
+ fprintf(stderr, "malloc() failed: %s.\n", strerror(errno));
|
|
|
3630b7 |
+ ret =-1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* decrypt using cca des3 */
|
|
|
3630b7 |
+ memcpy(des3_key, masterkey, MASTER_KEY_SIZE);
|
|
|
3630b7 |
+ ret = cca_decrypt(data, len, clear, &clear_len, "10293847", des3_key);
|
|
|
3630b7 |
+ if (ret)
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* now encrypt using software des3 */
|
|
|
3630b7 |
+ memcpy(sw_des3_key, masterkey, 3 * DES_KEY_SIZE);
|
|
|
3630b7 |
+ rc = sw_des3_cbc_encrypt(clear, clear_len, new_cipher, new_cipher_len,
|
|
|
3630b7 |
+ "10293847", sw_des3_key);
|
|
|
3630b7 |
+ if (rc != CKR_OK)
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+done:
|
|
|
3630b7 |
+ if (clear)
|
|
|
3630b7 |
+ free(clear);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return ret;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int load_private_token_objects(unsigned char *data_store,
|
|
|
3630b7 |
+ unsigned char *masterkey)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ FILE *fp1 = NULL, *fp2 = NULL;
|
|
|
3630b7 |
+ unsigned char *buf = NULL;
|
|
|
3630b7 |
+ unsigned char tmp[PATH_MAX], fname[PATH_MAX], iname[PATH_MAX];
|
|
|
3630b7 |
+ CK_BBOOL priv;
|
|
|
3630b7 |
+ unsigned int size;
|
|
|
3630b7 |
+ int rc, scount= 0, fcount = 0;
|
|
|
3630b7 |
+ size_t read_size;
|
|
|
3630b7 |
+ unsigned char *new_cipher;
|
|
|
3630b7 |
+ unsigned long new_cipher_len;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ snprintf(iname, sizeof(iname), "%s/TOK_OBJ/OBJ.IDX", data_store);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ fp1 = fopen((char *)iname, "r");
|
|
|
3630b7 |
+ if (!fp1)
|
|
|
3630b7 |
+ return -1; // no token objects
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ while (!feof(fp1)) {
|
|
|
3630b7 |
+ (void)fgets((char *)tmp, 50, fp1);
|
|
|
3630b7 |
+ if (!feof(fp1)) {
|
|
|
3630b7 |
+ tmp[strlen((char *)tmp) - 1] = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ snprintf((char *)fname, sizeof(fname), "%s/TOK_OBJ/",
|
|
|
3630b7 |
+ data_store);
|
|
|
3630b7 |
+ strcat((char *)fname, (char *)tmp);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ fp2 = fopen((char *)fname, "r");
|
|
|
3630b7 |
+ if (!fp2)
|
|
|
3630b7 |
+ continue;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ fread(&size, sizeof(unsigned int), 1, fp2);
|
|
|
3630b7 |
+ fread(&priv, sizeof(CK_BBOOL), 1, fp2);
|
|
|
3630b7 |
+ if (priv == FALSE) {
|
|
|
3630b7 |
+ fclose(fp2);
|
|
|
3630b7 |
+ continue;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ size = size - sizeof(unsigned int) - sizeof(CK_BBOOL);
|
|
|
3630b7 |
+ buf = (unsigned char *) malloc(size);
|
|
|
3630b7 |
+ if (!buf) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot malloc for object %s "
|
|
|
3630b7 |
+ "(ignoring it).\n", tmp);
|
|
|
3630b7 |
+ goto cleanup;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ read_size = fread((char *)buf, 1, size, fp2);
|
|
|
3630b7 |
+ if (read_size != size) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot read object %s "
|
|
|
3630b7 |
+ "(ignoring it).\n", tmp);
|
|
|
3630b7 |
+ goto cleanup;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ new_cipher_len = size;
|
|
|
3630b7 |
+ new_cipher = malloc(new_cipher_len);
|
|
|
3630b7 |
+ if (!new_cipher) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot malloc space for new "
|
|
|
3630b7 |
+ "cipher (ignoring object %s).\n", tmp);
|
|
|
3630b7 |
+ goto cleanup;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* After reading the private token object,
|
|
|
3630b7 |
+ * decrypt it using CCA des3 and then re-encrypt it
|
|
|
3630b7 |
+ * using software des3.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ memset(new_cipher, 0, new_cipher_len);
|
|
|
3630b7 |
+ rc = reencrypt_private_token_object(buf, size,
|
|
|
3630b7 |
+ new_cipher, &new_cipher_len,
|
|
|
3630b7 |
+ masterkey);
|
|
|
3630b7 |
+ if (rc)
|
|
|
3630b7 |
+ goto cleanup;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ fclose(fp2);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* now save the newly re-encrypted object back to
|
|
|
3630b7 |
+ * disk in its original file.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ fp2 = fopen((char *)fname, "w");
|
|
|
3630b7 |
+ size = sizeof(unsigned int) + sizeof(CK_BBOOL)
|
|
|
3630b7 |
+ + new_cipher_len;
|
|
|
3630b7 |
+ (void)fwrite(&size, sizeof(unsigned int), 1, fp2);
|
|
|
3630b7 |
+ (void)fwrite(&priv, sizeof(CK_BBOOL), 1, fp2);
|
|
|
3630b7 |
+ (void)fwrite(new_cipher, new_cipher_len, 1, fp2);
|
|
|
3630b7 |
+ rc = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+cleanup:
|
|
|
3630b7 |
+ if (fp2)
|
|
|
3630b7 |
+ fclose(fp2);
|
|
|
3630b7 |
+ if (buf)
|
|
|
3630b7 |
+ free(buf);
|
|
|
3630b7 |
+ if (new_cipher)
|
|
|
3630b7 |
+ free(new_cipher);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (rc) {
|
|
|
3630b7 |
+ if (v_flag)
|
|
|
3630b7 |
+ printf("Failed to process %s\n", fname);
|
|
|
3630b7 |
+ fcount++;
|
|
|
3630b7 |
+ } else {
|
|
|
3630b7 |
+ if (v_flag)
|
|
|
3630b7 |
+ printf("Processed %s.\n", fname);
|
|
|
3630b7 |
+ scount++;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ fclose(fp1);
|
|
|
3630b7 |
+ printf("Successfully migrated %d object(s).\n", scount);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (v_flag && fcount)
|
|
|
3630b7 |
+ printf("Failed to migrate %d object(s).\n", fcount);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return 0;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int load_masterkey(char *mkfile, char *pin, char *masterkey)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ unsigned char des3_key[3 * DES_KEY_SIZE];
|
|
|
3630b7 |
+ unsigned char hash_sha[SHA1_HASH_SIZE];
|
|
|
3630b7 |
+ unsigned char pin_md5_hash[MD5_HASH_SIZE];
|
|
|
3630b7 |
+ unsigned char *cipher = NULL;
|
|
|
3630b7 |
+ unsigned char *clear = NULL;
|
|
|
3630b7 |
+ unsigned long cipher_len, clear_len;
|
|
|
3630b7 |
+ int ret;
|
|
|
3630b7 |
+ CK_RV rc;
|
|
|
3630b7 |
+ FILE *fp = NULL;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ clear_len = cipher_len = MASTER_KEY_SIZE + SHA1_HASH_SIZE + (DES_BLOCK_SIZE - 1) & ~(DES_BLOCK_SIZE - 1);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ fp = fopen((char *)mkfile, "r");
|
|
|
3630b7 |
+ if (!fp) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not open %s: %s\n", mkfile,
|
|
|
3630b7 |
+ strerror(errno));
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ cipher = malloc(cipher_len);
|
|
|
3630b7 |
+ clear = malloc(clear_len);
|
|
|
3630b7 |
+ if (cipher == NULL || clear == NULL) {
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ ret = fread(cipher, cipher_len, 1, fp);
|
|
|
3630b7 |
+ if (ret != 1) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not read %s: %s\n", mkfile,
|
|
|
3630b7 |
+ strerror(errno));
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* decrypt the masterkey */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ ret = compute_md5(pin, strlen(pin), pin_md5_hash);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Error calculating MD5 of PIN!\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ memcpy(des3_key, pin_md5_hash, MD5_HASH_SIZE);
|
|
|
3630b7 |
+ memcpy(des3_key + MD5_HASH_SIZE, pin_md5_hash, DES_KEY_SIZE);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ rc = sw_des3_cbc_decrypt(cipher, cipher_len, clear, &clear_len,
|
|
|
3630b7 |
+ (unsigned char *)"12345678", des3_key);
|
|
|
3630b7 |
+ if (rc != CKR_OK) {
|
|
|
3630b7 |
+ fprintf(stderr, "Error decrypting master key file after read");
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /*
|
|
|
3630b7 |
+ * technically should strip PKCS padding here but since I already know
|
|
|
3630b7 |
+ * what the length should be, I don't bother.
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ * compare the hashes to verify integrity
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ ret = compute_sha1(clear, MASTER_KEY_SIZE, hash_sha);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Failed to compute sha for masterkey.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (memcmp(hash_sha, clear + MASTER_KEY_SIZE, SHA1_HASH_SIZE) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "%s appears to have been tampered!\n", mkfile);
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot migrate.\n");
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ memcpy(masterkey, clear, MASTER_KEY_SIZE);
|
|
|
3630b7 |
+ ret = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+done:
|
|
|
3630b7 |
+ if (fp)
|
|
|
3630b7 |
+ fclose(fp);
|
|
|
3630b7 |
+ if (clear)
|
|
|
3630b7 |
+ free(clear);
|
|
|
3630b7 |
+ if (cipher)
|
|
|
3630b7 |
+ free(cipher);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return ret;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int get_pin(char **pin, size_t *pinlen)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ struct termios old, new;
|
|
|
3630b7 |
+ int nread;
|
|
|
3630b7 |
+ char *buff = NULL;
|
|
|
3630b7 |
+ size_t buflen;
|
|
|
3630b7 |
+ int rc = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* turn echoing off */
|
|
|
3630b7 |
+ if (tcgetattr(fileno(stdin), &old) != 0)
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ new = old;
|
|
|
3630b7 |
+ new.c_lflag &= ~ECHO;
|
|
|
3630b7 |
+ if (tcsetattr (fileno(stdin), TCSAFLUSH, &new) != 0)
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* read the pin
|
|
|
3630b7 |
+ * Note: getline will allocate memory for buff. free it when done.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ nread = getline(&buff, &buflen, stdin);
|
|
|
3630b7 |
+ if (nread == -1) {
|
|
|
3630b7 |
+ rc = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Restore terminal */
|
|
|
3630b7 |
+ (void) tcsetattr(fileno(stdin), TCSAFLUSH, &old;;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* start a newline */
|
|
|
3630b7 |
+ printf("\n");
|
|
|
3630b7 |
+ fflush(stdout);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Allocate PIN.
|
|
|
3630b7 |
+ * Note: nread includes carriage return.
|
|
|
3630b7 |
+ * Replace with terminating NULL.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ *pin = (unsigned char *)malloc(nread);
|
|
|
3630b7 |
+ if (*pin == NULL) {
|
|
|
3630b7 |
+ rc = -ENOMEM;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* strip the carriage return since not part of pin. */
|
|
|
3630b7 |
+ buff[nread - 1] = '\0';
|
|
|
3630b7 |
+ memcpy(*pin, buff, nread);
|
|
|
3630b7 |
+ /* don't include the terminating null in the pinlen */
|
|
|
3630b7 |
+ *pinlen = nread - 1;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+done:
|
|
|
3630b7 |
+ if (buff)
|
|
|
3630b7 |
+ free(buff);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return rc;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int verify_pins(char *data_store, char *sopin, unsigned long sopinlen,
|
|
|
3630b7 |
+ char *userpin, unsigned long userpinlen)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ TOKEN_DATA td;
|
|
|
3630b7 |
+ unsigned char fname[PATH_MAX];
|
|
|
3630b7 |
+ unsigned char pin_sha[SHA1_HASH_SIZE];
|
|
|
3630b7 |
+ FILE *fp = NULL;
|
|
|
3630b7 |
+ int ret;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* read the NVTOK.DAT */
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store);
|
|
|
3630b7 |
+ fp = fopen((char *)fname, "r");
|
|
|
3630b7 |
+ if (!fp) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not open %s: %s\n", fname,
|
|
|
3630b7 |
+ strerror(errno));
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ ret = fread(&td, sizeof(TOKEN_DATA), 1, fp);
|
|
|
3630b7 |
+ if (ret != 1) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not read %s: %s\n", fname,
|
|
|
3630b7 |
+ strerror(errno));
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Now compute the SHAs for the SO and USER pins entered.
|
|
|
3630b7 |
+ * Compare with the SHAs for SO and USER PINs saved in
|
|
|
3630b7 |
+ * NVTOK.DAT to verify.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (sopin != NULL) {
|
|
|
3630b7 |
+ ret = compute_sha1(sopin, sopinlen, pin_sha);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Failed to compute sha for SO.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (memcmp(td.so_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "SO PIN is incorrect.\n");
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (userpin != NULL) {
|
|
|
3630b7 |
+ ret = compute_sha1(userpin, userpinlen, pin_sha);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Failed to compute sha for USER.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (memcmp(td.user_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "USER PIN is incorrect.\n");
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ ret = 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+done:
|
|
|
3630b7 |
+ /* clear out the hash */
|
|
|
3630b7 |
+ memset(pin_sha, 0, SHA1_HASH_SIZE);
|
|
|
3630b7 |
+ if (fp)
|
|
|
3630b7 |
+ fclose(fp);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return ret;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+void usage(char *progname)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ printf("usage:\t%s -h | -m v2objectsv3 [OPTIONS] \n", progname);
|
|
|
3630b7 |
+ printf(" -h\t\t\t\tshow this help\n");
|
|
|
3630b7 |
+ printf(" -m=migration_type\t\tCurrently the only type of CCA ");
|
|
|
3630b7 |
+ printf("migration\n\t\t\t\tsupported is v2objectsv3. v2objectsv3 ");
|
|
|
3630b7 |
+ printf("migrates\n\t\t\t\tCCA private token objects from CCA ");
|
|
|
3630b7 |
+ printf("encryption\n\t\t\t\t(used in v2)to software encryption ");
|
|
|
3630b7 |
+ printf("(used in v3). \n\n");
|
|
|
3630b7 |
+ printf("Migrate options (with -m v2objectsv3):\n");
|
|
|
3630b7 |
+ printf(" -d, --datastore=DIRECTORY\tCCA token datastore location\n");
|
|
|
3630b7 |
+ printf(" -v, --verbose\t\t\tprovide more detailed output\n");
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+int main(int argc, char **argv)
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ int ret, opt;
|
|
|
3630b7 |
+ unsigned int m_flag = 0;
|
|
|
3630b7 |
+ char *sopin = NULL, *userpin = NULL;
|
|
|
3630b7 |
+ size_t sopinlen, userpinlen;
|
|
|
3630b7 |
+ unsigned char masterkey[MASTER_KEY_SIZE];
|
|
|
3630b7 |
+ unsigned char *data_store = NULL;
|
|
|
3630b7 |
+ unsigned char *m_type = NULL;
|
|
|
3630b7 |
+ int data_store_len;
|
|
|
3630b7 |
+ char fname[PATH_MAX];
|
|
|
3630b7 |
+ struct stat statbuf;
|
|
|
3630b7 |
+ void *lib_csulcca;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ struct option long_opts[] = {
|
|
|
3630b7 |
+ { "datastore", required_argument, NULL, 'd' },
|
|
|
3630b7 |
+ { "verbose", no_argument, NULL, 'v'},
|
|
|
3630b7 |
+ { 0, 0, 0, 0 }
|
|
|
3630b7 |
+ };
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ int long_index;
|
|
|
3630b7 |
+ while ((opt = getopt_long(argc, argv, "d:m:hv", long_opts, NULL)) != -1) {
|
|
|
3630b7 |
+ switch (opt) {
|
|
|
3630b7 |
+ case 'd':
|
|
|
3630b7 |
+ data_store = strdup(optarg);
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ case 'h':
|
|
|
3630b7 |
+ usage(argv[0]);
|
|
|
3630b7 |
+ return 0;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ case 'm':
|
|
|
3630b7 |
+ m_type = strdup(optarg);
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ case 'v':
|
|
|
3630b7 |
+ v_flag++;
|
|
|
3630b7 |
+ break;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ default:
|
|
|
3630b7 |
+ usage(argv[0]);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (m_type) {
|
|
|
3630b7 |
+ if (memcmp(m_type, "v2objectsv3", strlen("v2objectsv3"))) {
|
|
|
3630b7 |
+ fprintf(stderr, "unknown migration type\n");
|
|
|
3630b7 |
+ usage(argv[0]);
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* use default data_store if one is not given */
|
|
|
3630b7 |
+ if (data_store == NULL) {
|
|
|
3630b7 |
+ data_store_len = strlen(TOK_DATASTORE);
|
|
|
3630b7 |
+ data_store = malloc(data_store_len + 1);
|
|
|
3630b7 |
+ if (data_store == NULL) {
|
|
|
3630b7 |
+ fprintf(stderr, "malloc failed: %s\n",strerror(errno));
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+ memset(data_store, 0, data_store_len + 1);
|
|
|
3630b7 |
+ memcpy(data_store, TOK_DATASTORE, data_store_len);
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Verify that the data store is valid by looking for
|
|
|
3630b7 |
+ * MK_SO, MK_USER, and TOK_OBJ/OBJ.IDX.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ memset(fname, 0, PATH_MAX);
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/MK_SO", data_store);
|
|
|
3630b7 |
+ if (stat(fname, &statbuf) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot find %s.\n", fname);
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ memset(fname, 0, PATH_MAX);
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/MK_USER", data_store);
|
|
|
3630b7 |
+ if (stat(fname, &statbuf) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot find %s.\n", fname);
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ memset(fname, 0, PATH_MAX);
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/TOK_OBJ/OBJ.IDX", data_store);
|
|
|
3630b7 |
+ if (stat(fname, &statbuf) != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "Cannot find %s.\n", fname);
|
|
|
3630b7 |
+ ret = -1;
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* If the OBJ.IDX is empty, then no objects to migrate. */
|
|
|
3630b7 |
+ if (statbuf.st_size == 0) {
|
|
|
3630b7 |
+ printf("OBJ.IDX file is empty. Thus no objects to migrate.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (v_flag)
|
|
|
3630b7 |
+ printf("%s has an MK_SO, MK_USER and TOK/OBJ.IDX\n",
|
|
|
3630b7 |
+ data_store);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* get the SO pin to authorize migration */
|
|
|
3630b7 |
+ printf("Enter the SO PIN: ");
|
|
|
3630b7 |
+ fflush(stdout);
|
|
|
3630b7 |
+ ret = get_pin(&sopin, &sopinlen);
|
|
|
3630b7 |
+ if (ret != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not get SO PIN.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* get the USER pin to authorize migration */
|
|
|
3630b7 |
+ printf("Enter the USER PIN: ");
|
|
|
3630b7 |
+ fflush(stdout);
|
|
|
3630b7 |
+ ret = get_pin(&userpin, &userpinlen);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (ret != 0) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not get USER PIN.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Verify the SO and USER PINs entered. */
|
|
|
3630b7 |
+ ret = verify_pins(data_store, sopin, sopinlen, userpin, userpinlen);
|
|
|
3630b7 |
+ if (ret)
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ lib_csulcca = dlopen(CCA_LIBRARY, (RTLD_GLOBAL | RTLD_NOW));
|
|
|
3630b7 |
+ if (lib_csulcca == NULL) {
|
|
|
3630b7 |
+ fprintf(stderr, "dlopen(%s) failed: %s\n", CCA_LIBRARY,
|
|
|
3630b7 |
+ strerror(errno));
|
|
|
3630b7 |
+ return -1;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ CSNBDEC = dlsym(lib_csulcca, "CSNBDEC");
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Get the masterkey from MK_SO.
|
|
|
3630b7 |
+ * This also helps verify that correct SO pin was entered.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ memset(masterkey, 0, MASTER_KEY_SIZE);
|
|
|
3630b7 |
+ memset(fname, 0, PATH_MAX);
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/MK_SO", data_store);
|
|
|
3630b7 |
+ ret = load_masterkey(fname, sopin, masterkey);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not load masterkey from MK_SO.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (v_flag)
|
|
|
3630b7 |
+ printf("Successfully verified SO Pin.\n");
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Get the masterkey from MK_USER.
|
|
|
3630b7 |
+ * This also helps verift that correct USER pin was entered.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ memset(masterkey, 0, MASTER_KEY_SIZE);
|
|
|
3630b7 |
+ memset(fname, 0, PATH_MAX);
|
|
|
3630b7 |
+ snprintf(fname, PATH_MAX, "%s/MK_USER", data_store);
|
|
|
3630b7 |
+ ret = load_masterkey(fname, userpin, masterkey);
|
|
|
3630b7 |
+ if (ret) {
|
|
|
3630b7 |
+ fprintf(stderr, "Could not load masterkey from MK_USER.\n");
|
|
|
3630b7 |
+ goto done;
|
|
|
3630b7 |
+ }
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (v_flag)
|
|
|
3630b7 |
+ printf("Successfully verified USER Pin.\n");
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ /* Load all the private token objects and re-encrypt them
|
|
|
3630b7 |
+ * using software des3, instead of CSNBENC.
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+ (void)load_private_token_objects(data_store, masterkey);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+done:
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ if (sopin)
|
|
|
3630b7 |
+ free(sopin);
|
|
|
3630b7 |
+ if (userpin)
|
|
|
3630b7 |
+ free(userpin);
|
|
|
3630b7 |
+ if (data_store)
|
|
|
3630b7 |
+ free(data_store);
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ return ret;
|
|
|
3630b7 |
+}
|
|
|
3630b7 |
diff --git a/usr/sbin/pkcscca/pkcscca.h b/usr/sbin/pkcscca/pkcscca.h
|
|
|
3630b7 |
new file mode 100644
|
|
|
3630b7 |
index 0000000..4b23c7a
|
|
|
3630b7 |
--- /dev/null
|
|
|
3630b7 |
+++ b/usr/sbin/pkcscca/pkcscca.h
|
|
|
3630b7 |
@@ -0,0 +1,49 @@
|
|
|
3630b7 |
+/*
|
|
|
3630b7 |
+ * Licensed materials - Property of IBM
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ * pkcscca - A tool for PKCS#11 CCA token.
|
|
|
3630b7 |
+ * Currently, only migrates CCA private token objects from using a
|
|
|
3630b7 |
+ * CCA cipher to using a software cipher.
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ * Copyright (C) International Business Machines Corp. 2014
|
|
|
3630b7 |
+ *
|
|
|
3630b7 |
+ */
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+#ifndef __PKCSCCA_H_
|
|
|
3630b7 |
+#define __PKCSCCA_H_
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+#define CCA_LIBRARY "libcsulcca.so"
|
|
|
3630b7 |
+#define TOK_DATASTORE "/var/lib/opencryptoki/ccatok"
|
|
|
3630b7 |
+#define MASTER_KEY_SIZE 64
|
|
|
3630b7 |
+#define SHA1_HASH_SIZE 20
|
|
|
3630b7 |
+#define MD5_HASH_SIZE 16
|
|
|
3630b7 |
+#define DES_BLOCK_SIZE 8
|
|
|
3630b7 |
+#define DES_KEY_SIZE 8
|
|
|
3630b7 |
+#define compute_sha1(a,b,c) compute_hash(HASH_SHA1,b,a,c)
|
|
|
3630b7 |
+#define compute_md5(a,b,c) compute_hash(HASH_MD5,b,a,c)
|
|
|
3630b7 |
+#define HASH_SHA1 1
|
|
|
3630b7 |
+#define HASH_MD5 2
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+/* from host_defs.h */
|
|
|
3630b7 |
+#include "pkcs32.h"
|
|
|
3630b7 |
+typedef struct _TWEAK_VEC
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ int allow_weak_des ;
|
|
|
3630b7 |
+ int check_des_parity ;
|
|
|
3630b7 |
+ int allow_key_mods ;
|
|
|
3630b7 |
+ int netscape_mods ;
|
|
|
3630b7 |
+} TWEAK_VEC;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+typedef struct _TOKEN_DATA
|
|
|
3630b7 |
+{
|
|
|
3630b7 |
+ CK_TOKEN_INFO_32 token_info;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+ CK_BYTE user_pin_sha[3 * DES_BLOCK_SIZE];
|
|
|
3630b7 |
+ CK_BYTE so_pin_sha[3 * DES_BLOCK_SIZE];
|
|
|
3630b7 |
+ CK_BYTE next_token_object_name[8];
|
|
|
3630b7 |
+ TWEAK_VEC tweak_vector;
|
|
|
3630b7 |
+} TOKEN_DATA;
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+
|
|
|
3630b7 |
+#endif
|