summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2017-03-15 23:05:07 -0400
committerAde Lee <alee@redhat.com>2017-03-15 23:05:07 -0400
commit080f3d2a8bf36be407c79ddd71381450c8667b2e (patch)
tree58594f9c45e88c882579d9f6638ff6639e506729
parent764a17314e81cade8bf1192739b5a2fad11d18bd (diff)
parent07135b5906f97a8c68148a07484e63d6896f410b (diff)
downloadpki-080f3d2a8bf36be407c79ddd71381450c8667b2e.tar.gz
pki-080f3d2a8bf36be407c79ddd71381450c8667b2e.tar.xz
pki-080f3d2a8bf36be407c79ddd71381450c8667b2e.zip
Merge branch 'master' of github.com:dogtagpki/pki
-rw-r--r--base/ca/src/org/dogtagpki/server/ca/rest/CertService.java18
-rw-r--r--base/common/python/pki/cli/main.py236
-rw-r--r--base/common/python/pki/util.py33
-rw-r--r--base/common/src/com/netscape/certsrv/authentication/EInvalidCredentials.java4
-rw-r--r--base/common/src/com/netscape/certsrv/cert/CertData.java10
-rw-r--r--base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java5
-rw-r--r--base/common/src/com/netscape/certsrv/key/KeyRecoveryRequest.java30
-rw-r--r--base/common/src/com/netscape/certsrv/request/IRequest.java2
-rw-r--r--base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java153
-rw-r--r--base/common/src/com/netscape/certsrv/security/IStorageKeyUnit.java73
-rw-r--r--base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java94
-rw-r--r--base/common/src/com/netscape/certsrv/security/WrappingParams.java124
-rw-r--r--base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java27
-rw-r--r--base/common/src/org/dogtagpki/tps/TPSConnection.java8
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/APDU.java64
-rw-r--r--base/common/src/org/dogtagpki/tps/main/Util.java570
-rw-r--r--base/common/src/org/dogtagpki/tps/msg/TPSMessage.java6
-rw-r--r--base/java-tools/bin/pki233
-rw-r--r--base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java14
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java9
-rw-r--r--base/kra/functional/src/com/netscape/cms/servlet/test/GeneratePKIArchiveOptions.java17
-rw-r--r--base/kra/src/com/netscape/kra/AsymKeyGenService.java8
-rw-r--r--base/kra/src/com/netscape/kra/EncryptionUnit.java467
-rw-r--r--base/kra/src/com/netscape/kra/EnrollmentService.java18
-rw-r--r--base/kra/src/com/netscape/kra/NetkeyKeygenService.java55
-rw-r--r--base/kra/src/com/netscape/kra/RecoveryService.java33
-rw-r--r--base/kra/src/com/netscape/kra/SecurityDataProcessor.java196
-rw-r--r--base/kra/src/com/netscape/kra/StorageKeyUnit.java254
-rw-r--r--base/kra/src/com/netscape/kra/SymKeyGenService.java30
-rw-r--r--base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java80
-rw-r--r--base/kra/src/com/netscape/kra/TransportKeyUnit.java126
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java6
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java10
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java4
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java19
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java13
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/GPParams.java108
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java59
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java426
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java785
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java41
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java800
-rw-r--r--base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java2
-rw-r--r--base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java105
-rw-r--r--base/server/man/man5/pki_default.cfg.52
-rw-r--r--base/server/man/man8/pkispawn.82
-rw-r--r--base/server/python/pki/server/__init__.py14
-rw-r--r--base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java21
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java8
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java234
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java8
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java157
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java58
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java10
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java162
-rw-r--r--base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java226
-rw-r--r--base/util/src/netscape/security/pkcs/PKCS12Util.java31
-rwxr-xr-xpylint-build-scan.py13
-rw-r--r--specs/dogtag-pki-theme.spec5
-rw-r--r--specs/dogtag-pki.spec7
-rw-r--r--specs/pki-console.spec12
-rw-r--r--specs/pki-core.spec308
-rw-r--r--tox.ini2
63 files changed, 5149 insertions, 1506 deletions
diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
index 2f9f46729..ebbab2572 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
@@ -64,6 +64,7 @@ import com.netscape.certsrv.dbs.certdb.CertId;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
import com.netscape.certsrv.dbs.certdb.ICertRecordList;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
import com.netscape.certsrv.logging.AuditFormat;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.request.IRequest;
@@ -80,8 +81,11 @@ import netscape.security.pkcs.PKCS7;
import netscape.security.pkcs.SignerInfo;
import netscape.security.provider.RSAPublicKey;
import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLReasonExtension;
import netscape.security.x509.RevocationReason;
import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509ExtensionException;
import netscape.security.x509.X509Key;
/**
@@ -529,6 +533,20 @@ public class CertService extends PKIService implements CertResource {
certData.setRevokedOn(record.getRevokedOn());
certData.setRevokedBy(record.getRevokedBy());
+ IRevocationInfo revInfo = record.getRevocationInfo();
+ if (revInfo != null) {
+ CRLExtensions revExts = revInfo.getCRLEntryExtensions();
+ if (revExts != null) {
+ try {
+ CRLReasonExtension ext = (CRLReasonExtension)
+ revExts.get(CRLReasonExtension.NAME);
+ certData.setRevocationReason(ext.getReason().getCode());
+ } catch (X509ExtensionException e) {
+ // nothing to do
+ }
+ }
+ }
+
certData.setStatus(record.getStatus());
if (authority.noncesEnabled() && generateNonce) {
diff --git a/base/common/python/pki/cli/main.py b/base/common/python/pki/cli/main.py
new file mode 100644
index 000000000..53e1b893a
--- /dev/null
+++ b/base/common/python/pki/cli/main.py
@@ -0,0 +1,236 @@
+#!/usr/bin/python
+# Authors:
+# Endi S. Dewata <edewata@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2014 Red Hat, Inc.
+# All rights reserved.
+#
+
+from __future__ import absolute_import
+from __future__ import print_function
+import shlex
+import subprocess
+import sys
+import traceback
+
+import pki.cli
+import pki.cli.pkcs12
+
+
+PYTHON_COMMANDS = ['pkcs12-import']
+
+
+class PKICLI(pki.cli.CLI):
+
+ def __init__(self):
+ super(PKICLI, self).__init__(
+ 'pki', 'PKI command-line interface')
+
+ self.database = None
+ self.password = None
+ self.password_file = None
+ self.token = None
+
+ self.add_module(pki.cli.pkcs12.PKCS12CLI())
+
+ def get_full_module_name(self, module_name):
+ return module_name
+
+ def print_help(self):
+ print('Usage: pki [OPTIONS]')
+ print()
+ print(' --client-type <type> PKI client type (default: java)')
+ print(' -d <path> Client security database location ' +
+ '(default: ~/.dogtag/nssdb)')
+ print(' -c <password> Client security database password ' +
+ '(mutually exclusive to the -C option)')
+ print(' -C <path> Client-side password file ' +
+ '(mutually exclusive to the -c option)')
+ print(' --token <name> Security token name')
+ print()
+ print(' -v, --verbose Run in verbose mode.')
+ print(' --debug Show debug messages.')
+ print(' --help Show help message.')
+ print()
+
+ super(PKICLI, self).print_help()
+
+ def execute_java(self, args, stdout=sys.stdout):
+
+ # read Java home
+ value = subprocess.check_output(
+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $JAVA_HOME',
+ shell=True)
+ java_home = value.decode(sys.getfilesystemencoding()).strip()
+
+ # read PKI library
+ value = subprocess.check_output(
+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_LIB',
+ shell=True)
+ pki_lib = value.decode(sys.getfilesystemencoding()).strip()
+
+ # read logging configuration path
+ value = subprocess.check_output(
+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $LOGGING_CONFIG',
+ shell=True)
+ logging_config = value.decode(sys.getfilesystemencoding()).strip()
+
+ cmd = [
+ java_home + '/bin/java',
+ '-Djava.ext.dirs=' + pki_lib,
+ '-Djava.util.logging.config.file=' + logging_config,
+ 'com.netscape.cmstools.cli.MainCLI'
+ ]
+
+ # restore options for Java commands
+
+ if self.database:
+ cmd.extend(['-d', self.database])
+
+ if self.password:
+ cmd.extend(['-c', self.password])
+
+ if self.password_file:
+ cmd.extend(['-C', self.password_file])
+
+ if self.token and self.token != 'internal':
+ cmd.extend(['--token', self.token])
+
+ if self.verbose:
+ cmd.extend(['--verbose'])
+
+ cmd.extend(args)
+
+ if self.verbose:
+ print('Java command: %s' % ' '.join(cmd))
+
+ subprocess.check_call(cmd, stdout=stdout)
+
+ def execute(self, argv):
+
+ # append global options
+ value = subprocess.check_output(
+ '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_CLI_OPTIONS',
+ shell=True)
+ value = value.decode(sys.getfilesystemencoding()).strip()
+ args = shlex.split(value)
+ args.extend(argv[1:])
+
+ client_type = 'java'
+
+ pki_options = []
+ command = None
+ cmd_args = []
+
+ # read pki options before the command
+ # remove options for Python module
+
+ i = 0
+ while i < len(args):
+ # if arg is a command, stop
+ if args[i][0] != '-':
+ command = args[i]
+ break
+
+ # get database path
+ if args[i] == '-d':
+ self.database = args[i + 1]
+ pki_options.append(args[i])
+ pki_options.append(args[i + 1])
+ i = i + 2
+
+ # get database password
+ elif args[i] == '-c':
+ self.password = args[i + 1]
+ pki_options.append(args[i])
+ pki_options.append(args[i + 1])
+ i = i + 2
+
+ # get database password file path
+ elif args[i] == '-C':
+ self.password_file = args[i + 1]
+ pki_options.append(args[i])
+ pki_options.append(args[i + 1])
+ i = i + 2
+
+ # get token name
+ elif args[i] == '--token':
+ self.token = args[i + 1]
+ pki_options.append(args[i])
+ pki_options.append(args[i + 1])
+ i = i + 2
+
+ # check verbose option
+ elif args[i] == '-v' or args[i] == '--verbose':
+ self.set_verbose(True)
+ pki_options.append(args[i])
+ i = i + 1
+
+ # check debug option
+ elif args[i] == '--debug':
+ self.set_verbose(True)
+ self.set_debug(True)
+ pki_options.append(args[i])
+ i = i + 1
+
+ # get client type
+ elif args[i] == '--client-type':
+ client_type = args[i + 1]
+ pki_options.append(args[i])
+ pki_options.append(args[i + 1])
+ i = i + 2
+
+ else: # otherwise, save the arg for the next module
+ cmd_args.append(args[i])
+ i = i + 1
+
+ # save the rest of the args
+ while i < len(args):
+ cmd_args.append(args[i])
+ i = i + 1
+
+ if self.verbose:
+ print('PKI options: %s' % ' '.join(pki_options))
+ print('PKI command: %s %s' % (command, ' '.join(cmd_args)))
+
+ if client_type == 'python' or command in PYTHON_COMMANDS:
+ (module, module_args) = self.parse_args(cmd_args)
+ module.execute(module_args)
+
+ elif client_type == 'java':
+ self.execute_java(cmd_args)
+
+ else:
+ raise Exception('Unsupported client type: ' + client_type)
+
+
+if __name__ == '__main__':
+
+ cli = PKICLI()
+
+ try:
+ cli.execute(sys.argv)
+
+ except subprocess.CalledProcessError as e:
+ if cli.verbose:
+ print('ERROR: %s' % e)
+ elif cli.debug:
+ traceback.print_exc()
+ sys.exit(e.returncode)
+
+ except KeyboardInterrupt:
+ print()
+ sys.exit(-1)
diff --git a/base/common/python/pki/util.py b/base/common/python/pki/util.py
index 8a75ff6f5..68118f439 100644
--- a/base/common/python/pki/util.py
+++ b/base/common/python/pki/util.py
@@ -143,6 +143,39 @@ def customize_file(input_file, output_file, params):
outfile.write(line)
+def load_properties(filename, properties):
+
+ with open(filename) as f:
+
+ lines = f.read().splitlines()
+
+ for index, line in enumerate(lines):
+
+ line = line.strip()
+
+ if not line or line.startswith('#'):
+ continue
+
+ parts = line.split('=', 1)
+
+ if len(parts) < 2:
+ raise Exception('Missing delimiter in %s line %d' %
+ (filename, index + 1))
+
+ name = parts[0].strip()
+ value = parts[1].strip()
+ properties[name] = value
+
+
+def store_properties(filename, properties):
+
+ with open(filename, 'w') as f:
+
+ for name, value in properties.items():
+ line = '%s=%s\n' % (name, value)
+ f.write(line)
+
+
def copytree(src, dst, symlinks=False, ignore=None):
"""
Recursively copy a directory tree using copy2().
diff --git a/base/common/src/com/netscape/certsrv/authentication/EInvalidCredentials.java b/base/common/src/com/netscape/certsrv/authentication/EInvalidCredentials.java
index a562d69e5..f6d8e2d77 100644
--- a/base/common/src/com/netscape/certsrv/authentication/EInvalidCredentials.java
+++ b/base/common/src/com/netscape/certsrv/authentication/EInvalidCredentials.java
@@ -35,4 +35,8 @@ public class EInvalidCredentials extends EAuthException {
public EInvalidCredentials(String errorString) {
super(errorString);
}
+
+ public EInvalidCredentials(String errorString, Exception cause) {
+ super(errorString, cause);
+ }
}
diff --git a/base/common/src/com/netscape/certsrv/cert/CertData.java b/base/common/src/com/netscape/certsrv/cert/CertData.java
index bb6d4c07c..1e9ce04eb 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertData.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertData.java
@@ -71,6 +71,7 @@ public class CertData {
String status;
Date revokedOn;
String revokedBy;
+ Integer revocationReason;
Long nonce;
@@ -186,6 +187,15 @@ public class CertData {
this.revokedBy = revokedBy;
}
+ @XmlElement(name="RevocationReason")
+ public Integer getRevocationReason() {
+ return revocationReason;
+ }
+
+ public void setRevocationReason(Integer revocationReason) {
+ this.revocationReason = revocationReason;
+ }
+
@XmlElement(name="Link")
public Link getLink() {
return link;
diff --git a/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java b/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
index f66d53f1e..163d4dd5d 100644
--- a/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
+++ b/base/common/src/com/netscape/certsrv/dbs/keydb/IKeyRecord.java
@@ -22,6 +22,7 @@ import java.util.Date;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.MetaInfo;
+import com.netscape.certsrv.security.WrappingParams;
/**
* An interface contains constants for key record.
@@ -167,4 +168,8 @@ public interface IKeyRecord {
* @exception EBaseException failed to retrieve authorization realm
*/
public String getRealm() throws EBaseException;
+
+ public void setWrappingParams(WrappingParams params) throws Exception;
+
+ public WrappingParams getWrappingParams(WrappingParams oldParams) throws Exception;
}
diff --git a/base/common/src/com/netscape/certsrv/key/KeyRecoveryRequest.java b/base/common/src/com/netscape/certsrv/key/KeyRecoveryRequest.java
index 31a2c5005..26cf766a8 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyRecoveryRequest.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyRecoveryRequest.java
@@ -45,6 +45,8 @@ public class KeyRecoveryRequest extends ResourceMessage {
private static final String NONCE_DATA = "nonceData";
private static final String CERTIFICATE = "certificate";
private static final String PASSPHRASE = "passphrase";
+ private static final String PAYLOAD_ENCRYPTION_OID = "payloadEncryptionOID";
+ private static final String PAYLOAD_WRAPPING_NAME = "payloadWrappingName";
public KeyRecoveryRequest() {
// required for JAXB (defaults)
@@ -177,6 +179,34 @@ public class KeyRecoveryRequest extends ResourceMessage {
attributes.put(PASSPHRASE, passphrase);
}
+ /**
+ * @return the payloadEncryptionOID
+ */
+ public String getPaylodEncryptionOID() {
+ return attributes.get(PAYLOAD_ENCRYPTION_OID);
+ }
+
+ /**
+ * @param payloadEncryptionOID the payloadEncryptionOID to set
+ */
+ public void setPayloadEncryptionOID(String payloadEncryptionOID) {
+ attributes.put(PAYLOAD_ENCRYPTION_OID, payloadEncryptionOID);
+ }
+
+ /**
+ * @return the payloadWrappingName
+ */
+ public String getPayloadWrappingName() {
+ return attributes.get(PAYLOAD_WRAPPING_NAME);
+ }
+
+ /**
+ * @param payloadWrappingName the payloadWrappingName to set
+ */
+ public void setPayloadWrappingName(String payloadWrappingName) {
+ attributes.put(PAYLOAD_WRAPPING_NAME, payloadWrappingName);
+ }
+
public static KeyRecoveryRequest valueOf(String string) throws Exception {
try {
return ResourceMessage.unmarshal(string, KeyRecoveryRequest.class);
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index 29b1bbb87..94fd2fd3f 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -179,6 +179,8 @@ public interface IRequest extends Serializable {
public static final String SECURITY_DATA_IV_STRING_OUT = "iv_out";
public static final String SECURITY_DATA_SESS_WRAPPED_DATA = "sessWrappedSecData";
public static final String SECURITY_DATA_PASS_WRAPPED_DATA = "passPhraseWrappedData";
+ public static final String SECURITY_DATA_PL_ENCRYPTION_OID = "payloadEncryptionOID";
+ public static final String SECURITY_DATA_PL_WRAPPING_NAME = "payloadWrappingName";
// key generation request attributes
public static final String ASYMKEY_GENERATION_REQUEST = "asymkeyGenRequest";
diff --git a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
index 7f5e95ec3..abb5f11a2 100644
--- a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
+++ b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java
@@ -22,7 +22,6 @@ import java.security.PublicKey;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.SymmetricKey;
-import org.mozilla.jss.crypto.SymmetricKey.Type;
import com.netscape.certsrv.base.EBaseException;
@@ -41,26 +40,6 @@ public interface IEncryptionUnit extends IToken {
public PublicKey getPublicKey();
/**
- * Wraps data. The given key will be wrapped by the
- * private key in this unit.
- *
- * @param priKey private key to be wrapped
- * @return wrapped data
- * @exception EBaseException failed to wrap
- */
- public byte[] wrap(PrivateKey priKey) throws Exception;
-
- /**
- * Wraps data. The given key will be wrapped by the
- * private key in this unit.
- *
- * @param symKey symmetric key to be wrapped
- * @return wrapped data
- * @exception EBaseException failed to wrap
- */
- public byte[] wrap(SymmetricKey symKey) throws Exception;
-
- /**
* Verifies the given key pair.
*
* @param publicKey public key
@@ -70,143 +49,19 @@ public interface IEncryptionUnit extends IToken {
EBaseException;
/**
- * Unwraps data. This method rebuilds the private key by
- * unwrapping the private key data.
- *
- * @param sessionKey session key that unwrap the private key
- * @param symmAlgOID symmetric algorithm
- * @param symmAlgParams symmetric algorithm parameters
- * @param privateKey private key data
- * @param pubKey public key
- * @return private key object
- * @throws Exception
- */
- public PrivateKey unwrap(byte sessionKey[], String symmAlgOID,
- byte symmAlgParams[], byte privateKey[],
- PublicKey pubKey)
- throws Exception;
-
- /**
- * Unwraps data. This method rebuilds the private key by
- * unwrapping the private key data.
- *
- * @param symmAlgOID symmetric algorithm
- * @param symmAlgParams symmetric algorithm parameters
- * @param pubKey public key
- * @param transportCert transport certificate
- * @return private key object
- * @throws Exception
- */
- public PrivateKey unwrap(byte encSymmKey[], String symmAlgOID,
- byte symmAlgParams[], byte encValue[], PublicKey pubKey,
- org.mozilla.jss.crypto.X509Certificate transportCert)
- throws Exception;
-
- /**
- * Unwraps symmetric key data. This method rebuilds the symmetric key by
- * unwrapping the private data blob.
- *
- * @param wrappedKeyData symmetric key data wrapped up with session key
- * @return Symmetric key object
- * @exception Exception failed to unwrap
- */
-
- public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize)
- throws Exception;
-
- /**
- * Unwraps symmetric key . This method
- * unwraps the symmetric key.
- *
- * @param sessionKey session key that unwrap the symmetric key
- * @param symmAlgOID symmetric algorithm
- * @param symmAlgParams symmetric algorithm parameters
- * @param symmetricKey symmetric key data
- * @param type symmetric key algorithm
- * @param strength symmetric key strength in bytes
- * @return Symmetric key object
- * @throws Exception
- */
-
- public SymmetricKey unwrap_symmetric(byte sessionKey[], String symmAlgOID,
- byte symmAlgParams[], byte symmetricKey[], Type type, int strength)
- throws Exception;
-
- /**
* Unwraps symmetric key . This method
* unwraps the symmetric key.
*
* @param encSymmKey wrapped symmetric key to be unwrapped
* @return Symmetric key object
- */
-
- public SymmetricKey unwrap_session_key(CryptoToken token, byte encSymmKey[],
- SymmetricKey.Usage usage, WrappingParams params);
-
- public PrivateKey unwrap_temp(byte privateKey[], PublicKey pubKey)
- throws Exception;
-
- /**
- * Unwraps data. This method rebuilds the private key by
- * unwrapping the private key data.
- *
- * @param privateKey private key data
- * @param pubKey public key object
- * @return private key object
* @throws Exception
*/
- public PrivateKey unwrap(byte privateKey[], PublicKey pubKey)
- throws Exception;
- /**
- * Encrypts the internal private key (private key to the KRA's
- * internal storage).
- *
- * @param rawPrivate user's private key (key to be archived)
- * @return encrypted data
- * @exception EBaseException failed to encrypt
- */
- public byte[] encryptInternalPrivate(byte rawPrivate[]) throws Exception;
+ public SymmetricKey unwrap_session_key(CryptoToken token, byte encSymmKey[],
+ SymmetricKey.Usage usage, WrappingParams params) throws Exception;
- /**
- * Decrypts the internal private key (private key from the KRA's
- * internal storage).
- *
- * @param wrappedPrivateData unwrapped private key data (key to be recovered)
- * @return raw private key
- * @throws Exception
- */
- public byte[] decryptInternalPrivate(byte wrappedPrivateData[])
- throws Exception;
- /**
- * Decrypts the external private key (private key from the end-user).
- *
- * @param sessionKey session key that protects the user private
- * @param symmAlgOID symmetric algorithm
- * @param symmAlgParams symmetric algorithm parameters
- * @param privateKey private key data
- * @return private key data
- * @throws Exception
- */
- public byte[] decryptExternalPrivate(byte sessionKey[],
- String symmAlgOID,
- byte symmAlgParams[], byte privateKey[])
- throws Exception;
+ public WrappingParams getWrappingParams() throws EBaseException;
- /**
- * Decrypts the external private key (private key from the end-user).
- *
- * @param sessionKey session key that protects the user private
- * @param symmAlgOID symmetric algorithm
- * @param symmAlgParams symmetric algorithm parameters
- * @param privateKey private key data
- * @param transportCert transport certificate
- * @return private key data
- * @throws Exception
- */
- public byte[] decryptExternalPrivate(byte sessionKey[],
- String symmAlgOID, byte symmAlgParams[], byte privateKey[],
- org.mozilla.jss.crypto.X509Certificate transportCert)
- throws Exception;
+ public WrappingParams getOldWrappingParams();
}
diff --git a/base/common/src/com/netscape/certsrv/security/IStorageKeyUnit.java b/base/common/src/com/netscape/certsrv/security/IStorageKeyUnit.java
index 4e651d394..6f6e31201 100644
--- a/base/common/src/com/netscape/certsrv/security/IStorageKeyUnit.java
+++ b/base/common/src/com/netscape/certsrv/security/IStorageKeyUnit.java
@@ -17,9 +17,12 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.certsrv.security;
+import java.security.PublicKey;
import java.util.Enumeration;
import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.SymmetricKey;
import com.netscape.certsrv.base.EBaseException;
@@ -96,4 +99,74 @@ public interface IStorageKeyUnit extends IEncryptionUnit {
public CryptoToken getToken();
+ /**
+ * Encrypts the internal private key (private key to the KRA's
+ * internal storage).
+ *
+ * @param rawPrivate user's private key (key to be archived)
+ * @return encrypted data
+ * @exception EBaseException failed to encrypt
+ */
+ public byte[] encryptInternalPrivate(byte rawPrivate[]) throws Exception;
+
+ /**
+ * Wraps data. The given key will be wrapped by the
+ * private key in this unit.
+ *
+ * @param priKey private key to be wrapped
+ * @param WrappingParams - wrapping parameters
+ * @return wrapped data
+ * @exception EBaseException failed to wrap
+ */
+ public byte[] wrap(PrivateKey priKey) throws Exception;
+
+ /**
+ * Wraps data. The given key will be wrapped by the
+ * private key in this unit.
+ *
+ * @param symKey symmetric key to be wrapped
+ * @param wrappingParams - wrapping parameters
+ * @return wrapped data
+ * @exception EBaseException failed to wrap
+ */
+ public byte[] wrap(SymmetricKey symKey) throws Exception;
+
+ /**
+ * Decrypts the internal private key (private key from the KRA's
+ * internal storage).
+ *
+ * @param wrappedPrivateData unwrapped private key data (key to be recovered)
+ * @param params - wrapping params
+ * @return raw private key
+ * @throws Exception
+ */
+ public byte[] decryptInternalPrivate(byte wrappedPrivateData[], WrappingParams params)
+ throws Exception;
+
+ /**
+ * Unwraps symmetric key data. This method rebuilds the symmetric key by
+ * unwrapping the private data blob.
+ *
+ * @param wrappedKeyData symmetric key data wrapped up with session key
+ * @return Symmetric key object
+ * @exception Exception failed to unwrap
+ */
+
+ public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize,
+ WrappingParams params) throws Exception;
+
+ /**
+ * Unwraps data. This method rebuilds the private key by
+ * unwrapping the private key data.
+ *
+ * @param privateKey private key data
+ * @param pubKey public key object
+ * @param temporary - temporary key?
+ * @param params - wrapping parameters
+ * @return private key object
+ * @throws Exception
+ */
+ public PrivateKey unwrap(byte privateKey[], PublicKey pubKey, boolean temporary,
+ WrappingParams params) throws Exception;
+
}
diff --git a/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java b/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
index 965101ffa..c90a12ba1 100644
--- a/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
+++ b/base/common/src/com/netscape/certsrv/security/ITransportKeyUnit.java
@@ -22,6 +22,7 @@ import java.security.PublicKey;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.SymmetricKey.Type;
import com.netscape.certsrv.base.EBaseException;
@@ -63,58 +64,87 @@ public interface ITransportKeyUnit extends IEncryptionUnit {
public PrivateKey getPrivateKey(org.mozilla.jss.crypto.X509Certificate cert);
/**
- * Unwraps symmetric key . This method
- * unwraps the symmetric key.
- *
- * @param encSymmKey wrapped symmetric key to be unwrapped
- * @param usage Key usage for unwrapped key.
- * @return Symmetric key object
+ * Returns this Unit's crypto token object.
+ * @return CryptoToken object.
+ */
+
+ public CryptoToken getToken();
+
+ /**
+ * Returns this Unit's signing algorithm in String format.
+ * @return String of signing algorithm
+ * @throws EBaseException
*/
- public SymmetricKey unwrap_session_key(CryptoToken token, byte encSymmKey[], SymmetricKey.Usage usage,
- WrappingParams params);
+ public String getSigningAlgorithm() throws EBaseException;
+
+ /**
+ * Sets this Unit's signing algorithm.
+ * @param str String of signing algorithm to set.
+ * @throws EBaseException
+ */
+ public void setSigningAlgorithm(String str) throws EBaseException;
+
+ /**
+ * Decrypts the external private key (private key from the end-user).
+ *
+ * @param sessionKey session key that protects the user private
+ * @param symmAlgOID symmetric algorithm
+ * @param symmAlgParams symmetric algorithm parameters
+ * @param privateKey private key data
+ * @param transportCert transport certificate
+ * @return private key data
+ * @throws Exception
+ */
+ public byte[] decryptExternalPrivate(byte sessionKey[],
+ String symmAlgOID, byte symmAlgParams[], byte privateKey[],
+ org.mozilla.jss.crypto.X509Certificate transportCert)
+ throws Exception;
/**
* Unwraps symmetric key . This method
* unwraps the symmetric key.
*
- * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @param sessionKey session key that unwrap the symmetric key
+ * @param symmAlgOID symmetric algorithm
+ * @param symmAlgParams symmetric algorithm parameters
+ * @param symmetricKey symmetric key data
+ * @param type symmetric key algorithm
+ * @param strength symmetric key strength in bytes
* @return Symmetric key object
+ * @throws Exception
*/
- public SymmetricKey unwrap_sym(byte encSymmKey[], WrappingParams params);
+ public SymmetricKey unwrap_symmetric(byte sessionKey[], String symmAlgOID,
+ byte symmAlgParams[], byte symmetricKey[], Type type, int strength)
+ throws Exception;
/**
- * Unwraps temporary private key . This method
- * unwraps the temporary private key.
+ * Unwraps data. This method rebuilds the private key by
+ * unwrapping the private key data.
*
- * @param wrappedKeyData wrapped private key to be unwrapped
+ * @param symmAlgOID symmetric algorithm
+ * @param symmAlgParams symmetric algorithm parameters
* @param pubKey public key
- * @return Private key object
+ * @param transportCert transport certificate
+ * @return private key object
* @throws Exception
*/
+ public PrivateKey unwrap(byte encSymmKey[], String symmAlgOID,
+ byte symmAlgParams[], byte encValue[], PublicKey pubKey,
+ org.mozilla.jss.crypto.X509Certificate transportCert)
+ throws Exception;
- public PrivateKey unwrap_temp(byte wrappedKeyData[], PublicKey
- pubKey) throws Exception;
/**
- * Returns this Unit's crypto token object.
- * @return CryptoToken object.
+ * Unwraps symmetric key . This method
+ * unwraps the symmetric key.
+ *
+ * @param encSymmKey wrapped symmetric key to be unwrapped
+ * @return Symmetric key object
+ * @throws Exception
*/
- public CryptoToken getToken();
-
- /**
- * Returns this Unit's signing algorithm in String format.
- * @return String of signing algorithm
- * @throws EBaseException
- */
+ public SymmetricKey unwrap_sym(byte encSymmKey[], WrappingParams params) throws Exception;
- public String getSigningAlgorithm() throws EBaseException;
- /**
- * Sets this Unit's signing algorithm.
- * @param str String of signing algorithm to set.
- * @throws EBaseException
- */
- public void setSigningAlgorithm(String str) throws EBaseException;
}
diff --git a/base/common/src/com/netscape/certsrv/security/WrappingParams.java b/base/common/src/com/netscape/certsrv/security/WrappingParams.java
index 9689ecc60..5d8dc3a6e 100644
--- a/base/common/src/com/netscape/certsrv/security/WrappingParams.java
+++ b/base/common/src/com/netscape/certsrv/security/WrappingParams.java
@@ -1,16 +1,18 @@
package com.netscape.certsrv.security;
+import java.security.NoSuchAlgorithmException;
+
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.SymmetricKey.Type;
-import org.mozilla.jss.crypto.SymmetricKey.Usage;
public class WrappingParams {
// session key attributes
- SymmetricKey.Type skTyoe;
- SymmetricKey.Usage[] skUsages;
+ SymmetricKey.Type skType;
KeyGenAlgorithm skKeyGenAlgorithm;
int skLength;
@@ -23,33 +25,82 @@ public class WrappingParams {
//wrapping algorithm for payload
KeyWrapAlgorithm payloadWrapAlgorithm;
- public WrappingParams(Type skTyoe, Usage[] skUsages, KeyGenAlgorithm skKeyGenAlgorithm, int skLength,
+ // payload encryption IV
+ IVParameterSpec payloadEncryptionIV;
+
+ // payload wrapping IV
+ IVParameterSpec payloadWrappingIV;
+
+ public WrappingParams(Type skType, KeyGenAlgorithm skKeyGenAlgorithm, int skLength,
KeyWrapAlgorithm skWrapAlgorithm, EncryptionAlgorithm payloadEncryptionAlgorithm,
- KeyWrapAlgorithm payloadWrapAlgorithm) {
+ KeyWrapAlgorithm payloadWrapAlgorithm, IVParameterSpec payloadEncryptIV, IVParameterSpec payloadWrapIV) {
super();
- this.skTyoe = skTyoe;
- this.skUsages = skUsages;
+ this.skType = skType;
this.skKeyGenAlgorithm = skKeyGenAlgorithm;
this.skLength = skLength;
this.skWrapAlgorithm = skWrapAlgorithm;
this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm;
this.payloadWrapAlgorithm = payloadWrapAlgorithm;
+ this.payloadEncryptionIV = payloadEncryptIV;
+ this.payloadWrappingIV = payloadWrapIV;
}
- public SymmetricKey.Type getSkTyoe() {
- return skTyoe;
+ public WrappingParams() {}
+
+ public WrappingParams(String encryptOID, String wrapName, String priKeyAlgo, IVParameterSpec encryptIV, IVParameterSpec wrapIV)
+ throws NumberFormatException, NoSuchAlgorithmException {
+ EncryptionAlgorithm encrypt = EncryptionAlgorithm.fromOID(new OBJECT_IDENTIFIER(encryptOID));
+
+ KeyWrapAlgorithm wrap = null;
+ if (wrapName != null) {
+ wrap = KeyWrapAlgorithm.fromString(wrapName);
+ this.payloadWrapAlgorithm = wrap;
+ }
+
+ switch (encrypt.getAlg().toString()) {
+ case "AES":
+ this.skType = SymmetricKey.AES;
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.AES;
+ if (wrap == null) this.payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD;
+ break;
+ case "DESede":
+ this.skType = SymmetricKey.DES3;
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
+ this.skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
+ if (wrap == null) this.payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
+ break;
+ case "DES":
+ this.skType = SymmetricKey.DES;
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.DES;
+ this.skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
+ if (wrap == null) this.payloadWrapAlgorithm = KeyWrapAlgorithm.DES_CBC_PAD;
+ break;
+ default:
+ throw new NoSuchAlgorithmException("Invalid algorithm");
+ }
+
+ this.skLength = encrypt.getKeyStrength();
+ if (priKeyAlgo.equals("EC")) {
+ this.skWrapAlgorithm = KeyWrapAlgorithm.AES_ECB;
+ } else {
+ this.skWrapAlgorithm = KeyWrapAlgorithm.RSA;
+ }
+
+ this.payloadEncryptionAlgorithm = encrypt;
+ this.payloadEncryptionIV = encryptIV;
+ this.payloadWrappingIV = wrapIV;
}
- public void setSkTyoe(SymmetricKey.Type skTyoe) {
- this.skTyoe = skTyoe;
+ public SymmetricKey.Type getSkType() {
+ return skType;
}
- public SymmetricKey.Usage[] getSkUsages() {
- return skUsages;
+ public void setSkType(SymmetricKey.Type skType) {
+ this.skType = skType;
}
- public void setSkUsages(SymmetricKey.Usage[] skUsages) {
- this.skUsages = skUsages;
+ public void setSkType(String skTypeName) throws NoSuchAlgorithmException {
+ this.skType = SymmetricKey.Type.fromName(skTypeName);
}
public KeyGenAlgorithm getSkKeyGenAlgorithm() {
@@ -60,6 +111,20 @@ public class WrappingParams {
this.skKeyGenAlgorithm = skKeyGenAlgorithm;
}
+ public void setSkKeyGenAlgorithm(String algName) throws NoSuchAlgorithmException {
+ // JSS mapping is not working. Lets just do something brain-dead to
+ // handle the cases we expect.
+ if (algName.equalsIgnoreCase("AES")) {
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.AES;
+ } else if (algName.equalsIgnoreCase("DES")) {
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.DES;
+ } else if (algName.equalsIgnoreCase("DESede")) {
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
+ } else if (algName.equalsIgnoreCase("DES3")) {
+ this.skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
+ }
+ }
+
public int getSkLength() {
return skLength;
}
@@ -76,6 +141,10 @@ public class WrappingParams {
this.skWrapAlgorithm = skWrapAlgorithm;
}
+ public void setSkWrapAlgorithm(String name) throws NoSuchAlgorithmException {
+ this.skWrapAlgorithm = KeyWrapAlgorithm.fromString(name);
+ }
+
public EncryptionAlgorithm getPayloadEncryptionAlgorithm() {
return payloadEncryptionAlgorithm;
}
@@ -84,6 +153,11 @@ public class WrappingParams {
this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm;
}
+ public void setPayloadEncryptionAlgorithm(String algName, String modeName, String paddingName, int keyStrength)
+ throws NoSuchAlgorithmException {
+ this.payloadEncryptionAlgorithm = EncryptionAlgorithm.lookup(algName, modeName, paddingName, keyStrength);
+ }
+
public KeyWrapAlgorithm getPayloadWrapAlgorithm() {
return payloadWrapAlgorithm;
}
@@ -91,4 +165,24 @@ public class WrappingParams {
public void setPayloadWrapAlgorithm(KeyWrapAlgorithm payloadWrapAlgorithm) {
this.payloadWrapAlgorithm = payloadWrapAlgorithm;
}
+
+ public void setPayloadWrapAlgorithm(String name) throws NoSuchAlgorithmException {
+ this.payloadWrapAlgorithm = KeyWrapAlgorithm.fromString(name);
+ }
+
+ public IVParameterSpec getPayloadEncryptionIV() {
+ return payloadEncryptionIV;
+ }
+
+ public void setPayloadEncryptionIV(IVParameterSpec payloadEncryptionIV) {
+ this.payloadEncryptionIV = payloadEncryptionIV;
+ }
+
+ public IVParameterSpec getPayloadWrappingIV() {
+ return payloadWrappingIV;
+ }
+
+ public void setPayloadWrappingIV(IVParameterSpec payloadWrappingIV) {
+ this.payloadWrappingIV = payloadWrappingIV;
+ }
}
diff --git a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
index 7c20e5cf4..a2d204347 100644
--- a/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
+++ b/base/common/src/com/netscape/certsrv/util/NSSCryptoProvider.java
@@ -1,26 +1,19 @@
package com.netscape.certsrv.util;
-import java.io.CharConversionException;
import java.io.File;
-import java.io.IOException;
import java.security.GeneralSecurityException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
import org.mozilla.jss.CertDatabaseException;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.CryptoManager.NotInitializedException;
import org.mozilla.jss.KeyDatabaseException;
-import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.crypto.AlreadyInitializedException;
-import org.mozilla.jss.crypto.BadPaddingException;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
-import org.mozilla.jss.crypto.IllegalBlockSizeException;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
+import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.util.IncorrectPasswordException;
@@ -110,7 +103,7 @@ public class NSSCryptoProvider extends CryptoProvider {
if (token == null) {
throw new NotInitializedException();
}
- return CryptoUtil.generateKey(token, getKeyGenAlgorithm(keyAlgorithm), keySize);
+ return CryptoUtil.generateKey(token, getKeyGenAlgorithm(keyAlgorithm), keySize, null, false);
}
@Override
@@ -142,7 +135,7 @@ public class NSSCryptoProvider extends CryptoProvider {
if (token == null) {
throw new NotInitializedException();
}
- return CryptoUtil.unwrapUsingSymmetricKey(token, new IVParameterSpec(nonceData), wrappedRecoveredKey,
+ return CryptoUtil.decryptUsingSymmetricKey(token, new IVParameterSpec(nonceData), wrappedRecoveredKey,
recoveryKey,
getEncryptionAlgorithm(encryptionAlgorithm));
}
@@ -211,10 +204,7 @@ public class NSSCryptoProvider extends CryptoProvider {
@Override
public byte[] createPKIArchiveOptions(String transportCert, SymmetricKey secret, String passphrase,
- String keyAlgorithm, int symKeySize, byte[] nonceData) throws InvalidKeyException,
- CertificateEncodingException, CharConversionException, NoSuchAlgorithmException,
- InvalidAlgorithmParameterException, IllegalStateException, TokenException, IOException,
- IllegalBlockSizeException, BadPaddingException, InvalidBERException {
+ String keyAlgorithm, int symKeySize, byte[] nonceData) throws Exception {
return CryptoUtil.createPKIArchiveOptions(manager, token, transportCert, secret, passphrase,
getKeyGenAlgorithm(keyAlgorithm), symKeySize, new IVParameterSpec(nonceData));
@@ -222,8 +212,13 @@ public class NSSCryptoProvider extends CryptoProvider {
@Override
public byte[] wrapWithSessionKey(SymmetricKey secret, SymmetricKey sessionKey, byte[] iv)
- throws InvalidKeyException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, TokenException {
- return CryptoUtil.wrapSymmetricKey(token, secret, sessionKey, new IVParameterSpec(iv));
+ throws Exception {
+ return CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sessionKey,
+ secret,
+ new IVParameterSpec(iv),
+ KeyWrapAlgorithm.DES3_CBC_PAD);
}
}
diff --git a/base/common/src/org/dogtagpki/tps/TPSConnection.java b/base/common/src/org/dogtagpki/tps/TPSConnection.java
index c5a971edd..dd9538b18 100644
--- a/base/common/src/org/dogtagpki/tps/TPSConnection.java
+++ b/base/common/src/org/dogtagpki/tps/TPSConnection.java
@@ -93,9 +93,11 @@ public class TPSConnection {
String s = message.encode();
// don't print the pdu_data
- int idx = s.lastIndexOf("pdu_data=");
- String toDebug = null;
- if (idx == -1)
+ int idx = s.lastIndexOf("pdu_data=");
+
+ int debug = 0;
+ String toDebug = null;
+ if (idx == -1 || debug == 1)
CMS.debug("TPSConnection.write: Writing: " + s);
else {
toDebug = s.substring(0, idx-1);
diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDU.java b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
index 009c47094..e3d72c764 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/APDU.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
@@ -219,6 +219,70 @@ public abstract class APDU {
data.set(dataEncrypted);
}
+ //Used for scp03, provide a padding buffer of the requested size, first byte set to 0x80
+ public void padBuffer80(TPSBuffer buffer, int blockSize) {
+ int length = buffer.size();
+
+ int padSize = 0;
+
+ if( buffer == null || blockSize <= 0)
+ return;
+
+ int rem = length % blockSize ;
+
+ padSize = blockSize - rem;
+
+ TPSBuffer padding = new TPSBuffer( padSize);
+ padding.setAt(0, (byte) 0x80);
+
+ buffer.add(padding);
+
+ }
+
+ //Assume the whole buffer is to be incremented
+ //Used for SCP03 encrypted apdu messages
+ public void incrementBuffer(TPSBuffer buffer) {
+
+ if(buffer == null)
+ return;
+
+ int len = buffer.size();
+
+ if (len < 1)
+ return;
+ int offset = 0;
+ for (short i = (short) (offset + len - 1); i >= offset; i--) {
+ byte cur = buffer.at(i);
+ if (cur != (byte) 0xFF) {
+ cur++;
+ buffer.setAt(i, cur);
+ break;
+ } else
+ buffer.setAt(i,(byte) 0x00);
+ }
+
+ System.out.println("enc buffer: " + buffer.toHexString());
+ }
+
+ //Implement SCP03 encrypted apdu scheme.
+ public void secureMessageSCP03(PK11SymKey encKey, TPSBuffer encryptionCounter) throws EBaseException {
+
+ TPSBuffer data = this.getData();
+
+ if (data != null && data.size() > 0) {
+
+ padBuffer80(data, 16);
+
+ TPSBuffer encryptedCounter = Util.encryptDataAES(encryptionCounter, encKey, null);
+
+ TPSBuffer encryptedData = Util.encryptDataAES(data, encKey, encryptedCounter);
+
+ data.set(encryptedData);
+
+ }
+
+ }
+
public void secureMessageSCP02(PK11SymKey encKey) throws EBaseException {
if (encKey == null) {
diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java
index b212478d7..1410c72a2 100644
--- a/base/common/src/org/dogtagpki/tps/main/Util.java
+++ b/base/common/src/org/dogtagpki/tps/main/Util.java
@@ -24,6 +24,9 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Calendar;
@@ -34,10 +37,14 @@ import netscape.security.x509.SubjectKeyIdentifierExtension;
import netscape.security.x509.X509CertImpl;
import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.BadPaddingException;
import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.IllegalBlockSizeException;
+import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.pkcs11.PK11SymKey;
import com.netscape.certsrv.apps.CMS;
@@ -47,6 +54,13 @@ import com.netscape.symkey.SessionKey;
public class Util {
+ //SCP03 AES-CMAC related constants
+ private static final byte AES_CMAC_CONSTANT = (byte) 0x87;
+ private static final int AES_CMAC_BLOCK_SIZE = 16;
+
+ public static final byte CARD_CRYPTO_KDF_CONSTANT_SCP03 = 0x0;
+ public static final byte HOST_CRYPTO_KDF_CONSTANT_SCP03 = 0x1;
+
public Util() {
}
@@ -84,11 +98,6 @@ public class Util {
return Integer.toHexString(val);
}
- public static void main(String[] args) {
- // TODO Auto-generated method stub
-
- }
-
public static String uriDecode(String encoded) throws UnsupportedEncodingException {
return URLDecoder.decode(encoded, "UTF-8");
@@ -332,6 +341,196 @@ public class Util {
return output;
}
+ //Use AES-CMAC (SCP03, counter method) to calculate cryptogram, constant determines whether it is a card or host cryptogram
+ public static TPSBuffer compute_AES_CMAC_Cryptogram(SymmetricKey symKey, TPSBuffer context, byte kdfConstant)
+ throws EBaseException {
+
+ String method = "Util compute_AES_Crypto:";
+ // 11 bytes label
+ byte[] label = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ // sanity checking
+
+ if (symKey == null || context == null ) {
+ throw new EBaseException(method + " Invalid input!");
+ }
+
+ TPSBuffer data = new TPSBuffer();
+ int outputBits = 8 * 8;
+
+ //output size of cmac PRF
+ final int h = 128;
+
+ int remainder = outputBits % h;
+
+ //calculate counter size
+ int n = 0;
+ if (remainder == 0) {
+ n = outputBits / h;
+ } else {
+ n = outputBits / h + 1;
+ }
+
+ byte b1 = (byte) ((outputBits >> 8) & 0xFF);
+ byte b2 = (byte) (outputBits & 0xFF);
+
+ TPSBuffer outputBitsBinary = new TPSBuffer(2);
+ outputBitsBinary.setAt(0, b1);
+ outputBitsBinary.setAt(1, b2);
+
+ data.addBytes(label);
+ data.add(kdfConstant);
+ data.add((byte) 0x0);
+ data.add(outputBitsBinary);
+
+ TPSBuffer output = new TPSBuffer();
+ TPSBuffer input = new TPSBuffer();
+
+ TPSBuffer kI = null;
+
+ for (int i = 1; i <= n; i++) {
+ input.add(data);
+ input.add((byte) i);
+ input.add(context);
+
+ kI = Util.computeAES_CMAC(symKey, input);
+
+ output.add(kI);
+ }
+
+ return output.substr(0,8);
+ }
+
+ // Implements agorithm http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
+ // Input an aes key of 128, 192, or 256 bits
+
+ public static TPSBuffer computeAES_CMAC(SymmetricKey aesKey, TPSBuffer input) throws EBaseException {
+
+ String method = "Util.computeAES_CMAC:";
+ byte iv[] = null;
+
+ if (aesKey == null || input == null) {
+ throw new EBaseException(method + " invalid input data!");
+ }
+
+ TPSBuffer data = new TPSBuffer(input);
+
+ String alg = aesKey.getAlgorithm();
+ System.out.println(" AES ALG: " + alg);
+
+ EncryptionAlgorithm eAlg = EncryptionAlgorithm.AES_128_CBC;
+ int ivLength = eAlg.getIVLength();
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength];
+ }
+
+ if (!("AES".equals(alg))) {
+ throw new EBaseException(method + " invalid in put key type , must be AES!");
+ }
+
+ byte[] k0 = new byte[AES_CMAC_BLOCK_SIZE];
+
+ //Encrypt the zero array
+ CryptoToken token = aesKey.getOwningToken();
+ Cipher encryptor = null;
+
+ try {
+ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+ encryptor.initEncrypt(aesKey, new IVParameterSpec(iv));
+ k0 = encryptor.doFinal(k0);
+
+ } catch (NoSuchAlgorithmException | TokenException | IllegalStateException | IllegalBlockSizeException
+ | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
+ throw new EBaseException(e);
+ }
+
+ byte[] k1 = getAES_CMAC_SubKey(k0);
+ byte[] k2 = getAES_CMAC_SubKey(k1);
+
+ int numBlocks = 0;
+ int messageSize = data.size();
+ boolean perfectBlocks = false;
+
+ if (((messageSize % AES_CMAC_BLOCK_SIZE) == 0) && (messageSize != 0)) {
+ numBlocks = messageSize / AES_CMAC_BLOCK_SIZE;
+ perfectBlocks = true;
+ }
+ else {
+ numBlocks = messageSize / AES_CMAC_BLOCK_SIZE + 1;
+ perfectBlocks = false;
+ }
+
+ int index = 0;
+ byte inb = 0;
+ if (perfectBlocks == true)
+ {
+ // If the size of the message is an integer multiple of the block block size (namely, 128 bits) (16 bytes)
+ // the last block shall be exclusive-OR'ed with the first subKey k1
+
+ for (int j = 0; j < k1.length; j++) {
+ index = messageSize - AES_CMAC_BLOCK_SIZE + j;
+ inb = data.at(index);
+ data.setAt(index, (byte) (inb ^ k1[j]));
+ }
+ }
+ else
+ {
+ // Otherwise, the last block shall be padded with 10^i
+ TPSBuffer padding = new TPSBuffer(AES_CMAC_BLOCK_SIZE - messageSize % AES_CMAC_BLOCK_SIZE);
+ padding.setAt(0, (byte) 0x80);
+
+ data.add(padding);
+ //Get new data size , it's changed
+ messageSize = data.size();
+
+ // and exclusive-OR'ed with K2
+ for (int j = 0; j < k2.length; j++) {
+ index = messageSize - AES_CMAC_BLOCK_SIZE + j;
+ inb = data.at(index);
+ data.setAt(index, (byte) (inb ^ k2[j]));
+ }
+ }
+
+ // Initialization vector starts as zeroes but changes inside the loop's
+ // subsequent iterations, it becomes the last encryption output
+ byte[] encData = new byte[AES_CMAC_BLOCK_SIZE];
+ TPSBuffer currentBlock = null;
+
+ for (int i = 0; i < numBlocks; i++) {
+ try {
+ encryptor.initEncrypt(aesKey, new IVParameterSpec(encData));
+ currentBlock = data.substr(i * AES_CMAC_BLOCK_SIZE, AES_CMAC_BLOCK_SIZE);
+ encData = encryptor.doFinal(currentBlock.toBytesArray());
+ } catch (TokenException | IllegalStateException | IllegalBlockSizeException
+ | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
+ throw new EBaseException(e);
+ }
+ }
+
+ TPSBuffer aesMacData = new TPSBuffer(encData);
+ return aesMacData;
+
+ }
+
+ //Support method for AES-CMAC alg (SCP03).
+ private static byte[] getAES_CMAC_SubKey(byte[] input) {
+
+ byte[] output = new byte[input.length];
+
+ boolean msbSet = ((input[0]&0x80) != 0);
+ for (int i=0; i<input.length; i++) {
+ output[i] = (byte) (input[i] << 1);
+ if (i+1 < input.length && ((input[i+1]&0x80) != 0)) {
+ output[i] |= 0x01;
+ }
+ }
+ if (msbSet) {
+ output[output.length-1] ^= AES_CMAC_CONSTANT;
+ }
+ return output;
+ }
+
public static TPSBuffer computeMAC(PK11SymKey symKey, TPSBuffer input, TPSBuffer icv) throws EBaseException {
TPSBuffer output = null;
TPSBuffer result = null;
@@ -425,6 +624,43 @@ public class Util {
return tbuf;
}
+ //Encrypt data with aes. Supports 128 for now.
+ public static TPSBuffer encryptDataAES(TPSBuffer dataToEnc, PK11SymKey encKey,TPSBuffer iv) throws EBaseException {
+
+ TPSBuffer encrypted = null;
+ if (encKey == null || dataToEnc == null) {
+ throw new EBaseException("Util.encryptDataAES: called with no sym key or no data!");
+ }
+
+ CryptoToken token = null;
+
+
+ try {
+ token = CryptoManager.getInstance().getInternalKeyStorageToken();
+ Cipher cipher = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+ AlgorithmParameterSpec algSpec = null;
+ int len = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+
+ byte[] ivEnc = null;
+ if(iv == null) { //create one
+ ivEnc = new byte[len];
+ } else {
+ ivEnc = iv.toBytesArray();
+ }
+
+ algSpec = new IVParameterSpec(ivEnc);
+ cipher.initEncrypt(encKey, algSpec);
+ byte[] encryptedBytes = cipher.doFinal(dataToEnc.toBytesArray());
+ encrypted = new TPSBuffer(encryptedBytes);
+
+ } catch (Exception e) {
+ throw new EBaseException("Util.encryptDataAES: problem encrypting data: " + e.toString());
+ }
+
+ return encrypted;
+
+ }
+
public static TPSBuffer encryptData(TPSBuffer dataToEnc, PK11SymKey encKey) throws EBaseException {
TPSBuffer encrypted = null;
@@ -533,4 +769,328 @@ public class Util {
return timeString;
}
+ //AES CMAC test samples
+ public static void main(String[] args) {
+
+ /* Options options = new Options();
+
+ options.addOption("d", true, "Directory for tokendb");
+
+ String db_dir = null;
+ CryptoManager cm = null;
+
+ // 128 bit aes test key
+ byte devKey[] = { (byte) 0x2b, (byte) 0x7e, (byte) 0x15, (byte) 0x16, (byte) 0x28, (byte) 0xae, (byte) 0xd2,
+ (byte) 0xa6, (byte) 0xab, (byte) 0xf7, (byte) 0x15, (byte) 0x88, (byte) 0x09, (byte) 0xcf, (byte) 0x4f,
+ (byte) 0x3c };
+
+ // 192 bit aes test key
+ byte devKey192[] = { (byte) 0x8e, (byte) 0x73, (byte) 0xb0, (byte) 0xf7, (byte) 0xda, (byte) 0x0e, (byte) 0x64,
+ (byte) 0x52,
+ (byte) 0xc8, (byte) 0x10, (byte) 0xf3, (byte) 0x2b, (byte) 0x80, (byte) 0x90, (byte) 0x79, (byte) 0xe5,
+ (byte) 0x62, (byte) 0xf8, (byte) 0xea, (byte) 0xd2, (byte) 0x52, (byte) 0x2c, (byte) 0x6b, (byte) 0x7b
+ };
+
+ byte devKey256[] = { (byte) 0x60, (byte) 0x3d, (byte) 0xeb, (byte) 0x10, (byte) 0x15, (byte) 0xca, (byte) 0x71,
+ (byte) 0xbe,
+ (byte) 0x2b, (byte) 0x73, (byte) 0xae, (byte) 0xf0, (byte) 0x85, (byte) 0x7d, (byte) 0x77, (byte) 0x81,
+ (byte) 0x1f, (byte) 0x35, (byte) 0x2c, (byte) 0x07, (byte) 0x3b, (byte) 0x61, (byte) 0x08, (byte) 0xd7,
+ (byte) 0x2d,
+ (byte) 0x98, (byte) 0x10, (byte) 0xa3, (byte) 0x09, (byte) 0x14, (byte) 0xdf, (byte) 0xf4
+
+ };
+
+ byte message[] = { (byte) 0x6b, (byte) 0xc1, (byte) 0xbe, (byte) 0xe2, (byte) 0x2e, (byte) 0x40, (byte) 0x9f,
+ (byte) 0x96, (byte) 0xe9, (byte) 0x3d, (byte) 0x7e, (byte) 0x11,
+ (byte) 0x73, (byte) 0x93, (byte) 0x17, (byte) 0x2a };
+
+ byte message320[] = { (byte) 0x6b, (byte) 0xc1, (byte) 0xbe, (byte) 0xe2, (byte) 0x2e, (byte) 0x40,
+ (byte) 0x9f, (byte) 0x96, (byte) 0xe9,
+ (byte) 0x3d, (byte) 0x7e, (byte) 0x11, (byte) 0x73, (byte) 0x93, (byte) 0x17, (byte) 0x2a,
+ (byte) 0xae, (byte) 0x2d, (byte) 0x8a, (byte) 0x57, (byte) 0x1e, (byte) 0x03, (byte) 0xac, (byte) 0x9c,
+ (byte) 0x9e, (byte) 0xb7,
+ (byte) 0x6f, (byte) 0xac, (byte) 0x45, (byte) 0xaf, (byte) 0x8e, (byte) 0x51,
+ (byte) 0x30, (byte) 0xc8, (byte) 0x1c, (byte) 0x46, (byte) 0xa3, (byte) 0x5c, (byte) 0xe4, (byte) 0x11 };
+
+ byte message512[] = { (byte) 0x6b, (byte) 0xc1, (byte) 0xbe, (byte) 0xe2, (byte) 0x2e, (byte) 0x40,
+ (byte) 0x9f, (byte) 0x96, (byte) 0xe9, (byte) 0x3d,
+ (byte) 0x7e, (byte) 0x11, (byte) 0x73, (byte) 0x93, (byte) 0x17, (byte) 0x2a,
+ (byte) 0xae, (byte) 0x2d, (byte) 0x8a, (byte) 0x57, (byte) 0x1e, (byte) 0x03, (byte) 0xac, (byte) 0x9c,
+ (byte) 0x9e, (byte) 0xb7, (byte) 0x6f,
+ (byte) 0xac, (byte) 0x45, (byte) 0xaf, (byte) 0x8e, (byte) 0x51,
+ (byte) 0x30, (byte) 0xc8, (byte) 0x1c, (byte) 0x46, (byte) 0xa3, (byte) 0x5c, (byte) 0xe4, (byte) 0x11,
+ (byte) 0xe5, (byte) 0xfb, (byte) 0xc1,
+ (byte) 0x19, (byte) 0x1a, (byte) 0x0a, (byte) 0x52, (byte) 0xef,
+ (byte) 0xf6, (byte) 0x9f, (byte) 0x24, (byte) 0x45, (byte) 0xdf, (byte) 0x4f, (byte) 0x9b, (byte) 0x17,
+ (byte) 0xad, (byte) 0x2b, (byte) 0x41,
+ (byte) 0x7b, (byte) 0xe6, (byte) 0x6c, (byte) 0x37, (byte) 0x10
+
+ };
+
+
+ byte message_test1[] = { 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x04,0x0,0x0,(byte) 0x80,0x01,
+ (byte)0xd0,(byte)0x61,(byte) 0xff,(byte)0xf4,(byte)0xd8,(byte)0x2f,(byte)0xdf,
+ (byte)0x87,(byte)0x5a,(byte)0x5c,(byte)0x90,(byte)0x99,(byte)0x98,(byte)0x3b,(byte)0x24,(byte)0xdc };
+
+ byte devKey_test1[] = {(byte)0x88,(byte)0xc6,(byte)0x46,(byte)0x2e,(byte)0x55,(byte)0x58,(byte)0x6c,
+ (byte)0x47,(byte)0xf9,(byte)0xff,0x00,(byte)0x92,(byte)0x39,(byte)0xce,(byte)0xb6,(byte)0xea};
+
+ //Test keys and messages found here: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
+ //Results computed in this test program can be compared against those in the preceding document.
+
+ try {
+ CommandLineParser parser = new DefaultParser();
+ CommandLine cmd = parser.parse(options, args);
+
+ if (cmd.hasOption("d")) {
+ db_dir = cmd.getOptionValue("d");
+ }
+
+ } catch (ParseException e) {
+ System.err.println("Error in parsing command line options: " + e.getMessage());
+
+ }
+
+ SymmetricKey aes128 = null;
+ SymmetricKey aes192 = null;
+ SymmetricKey aes256 = null;
+
+ SymmetricKey tempKey = null;
+
+ // Initialize token
+ try {
+ CryptoManager.initialize(db_dir);
+ cm = CryptoManager.getInstance();
+
+ CryptoToken token = cm.getInternalKeyStorageToken();
+
+ // Generate temp key with only function is to
+ // unwrap the various test keys onto the token
+
+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.AES);
+
+ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4];
+ usages[0] = SymmetricKey.Usage.WRAP;
+ usages[1] = SymmetricKey.Usage.UNWRAP;
+ usages[2] = SymmetricKey.Usage.ENCRYPT;
+ usages[3] = SymmetricKey.Usage.DECRYPT;
+
+ kg.setKeyUsages(usages);
+ kg.temporaryKeys(true);
+ kg.initialize(128);
+ tempKey = kg.generate();
+
+ //unwrap the test aes keys onto the token
+
+ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+
+ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+ byte[] iv = null;
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength]; // all zeroes
+ }
+
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey = encryptor.doFinal(devKey);
+
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[]wrappedKey_test1 = encryptor.doFinal(devKey_test1);
+
+ // 192 bit key
+
+ TPSBuffer aesKey192Buf = new TPSBuffer(devKey192);
+ TPSBuffer aesKey192Pad = new TPSBuffer(8);
+ aesKey192Pad.setAt(0, (byte) 0x80);
+ aesKey192Buf.add(aesKey192Pad);
+
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey192 = encryptor.doFinal(aesKey192Buf.toBytesArray());
+
+ // 128 bit key
+
+ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv));
+ aes128 = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, 16);
+
+
+ KeyWrapper keyWrap1 = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap1.initUnwrap(tempKey,new IVParameterSpec(iv));
+ SymmetricKey aes128_test = keyWrap1.unwrapSymmetric(wrappedKey_test1,SymmetricKey.AES,16);
+
+ System.out.println(new TPSBuffer(message_test1).toHexString());
+ System.out.println(new TPSBuffer(devKey_test1).toHexString());
+ System.out.println(new TPSBuffer(aes128_test.getKeyData()).toHexString());
+ TPSBuffer input1 = new TPSBuffer(message_test1);
+ TPSBuffer output1 = Util.computeAES_CMAC(aes128_test, input1);
+ System.out.println("blub: " + output1.toHexString());
+
+ // 192 bit key
+
+ KeyWrapper keyWrap192 = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap192.initUnwrap(tempKey, new IVParameterSpec(iv));
+ aes192 = keyWrap.unwrapSymmetric(wrappedKey192, SymmetricKey.AES, 24);
+
+ // 256 bit key
+
+ TPSBuffer aesKey256Buf = new TPSBuffer(devKey256);
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey256 = encryptor.doFinal(aesKey256Buf.toBytesArray());
+
+ KeyWrapper keyWrap256 = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap256.initUnwrap(tempKey, new IVParameterSpec(iv));
+ aes256 = keyWrap.unwrapSymmetric(wrappedKey256, SymmetricKey.AES, 32);
+
+ System.out.println("");
+ System.out.println("Now use 128 bit AES key:");
+ System.out.println("");
+
+ //Attempt 0 bytes
+
+ System.out.println("");
+ System.out.println("Use message of 0 bytes:");
+ System.out.println("");
+
+ TPSBuffer input0 = new TPSBuffer(0);
+ TPSBuffer output0 = Util.computeAES_CMAC(aes128, input0);
+
+ System.out.println("Message:" + input0.toHexString());
+ System.out.println("AES-CMAC output: " + output0.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 16 bytes:");
+ System.out.println("");
+
+ //Attempt 16 bytes
+
+ TPSBuffer input = new TPSBuffer(message);
+ TPSBuffer output = Util.computeAES_CMAC(aes128, input);
+
+ System.out.println("Message:" + input.toHexString());
+ System.out.println("AES-CMAC output: " + output.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 40 bytes:");
+ System.out.println("");
+
+ //Attempt 40 bytes
+
+ TPSBuffer input320 = new TPSBuffer(message320);
+ TPSBuffer output320 = Util.computeAES_CMAC(aes128, input320);
+
+ System.out.println("Message:" + input320.toHexString());
+ System.out.println("AES-CMAC output: " + output320.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 64 bytes:");
+ System.out.println("");
+
+ //Attempt 64 bytes
+
+ TPSBuffer input512 = new TPSBuffer(message512);
+ TPSBuffer output512 = Util.computeAES_CMAC(aes128, input512);
+ System.out.println("Message:" + input512.toHexString());
+ System.out.println("AES-CMAC output: " + output512.toHexString());
+
+ // Now used the AES 192 key
+
+ System.out.println("");
+ System.out.println("Now use 192 bit AES key:");
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 0 bytes:");
+ System.out.println("");
+
+ // Attempt 0 bytes
+
+ TPSBuffer input192_0 = new TPSBuffer(0);
+ TPSBuffer output192_0 = Util.computeAES_CMAC(aes192, input192_0);
+ System.out.println("Message:" + input192_0.toHexString());
+ System.out.println("AES-CMAC output: " + output192_0.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 16 bytes:");
+ System.out.println("");
+
+ //Attempt 16 bytes
+
+ TPSBuffer input192_128 = new TPSBuffer(message);
+ TPSBuffer output192_128 = Util.computeAES_CMAC(aes192, input);
+ System.out.println("Message:" + input192_128.toHexString());
+ System.out.println("AES-CMAC output: " + output192_128.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 40 bytes:");
+ System.out.println("");
+
+ //Attempt 40 bytes
+
+ TPSBuffer input192_320 = new TPSBuffer(message320);
+ TPSBuffer output192_320 = Util.computeAES_CMAC(aes192, input192_320);
+ System.out.println("Message:" + input192_320.toHexString());
+ System.out.println("AES-CMAC output: " + output192_320.toHexString());
+ System.out.println("");
+
+ System.out.println("");
+ System.out.println("Use message of 64 bytes:");
+ System.out.println("");
+
+ //Attempt 64 bytes
+
+ TPSBuffer input192_512 = new TPSBuffer(message512);
+ TPSBuffer output192_512 = Util.computeAES_CMAC(aes192, input512);
+ System.out.println("Message:" + input192_512.toHexString());
+ System.out.println("AES-CMAC output: " + output192_512.toHexString());
+
+ System.out.println("");
+ System.out.println("Now use 256 bit AES key:");
+ System.out.println("");
+
+ // Attempt 0 bytes
+
+ TPSBuffer input256_0 = new TPSBuffer(0);
+ TPSBuffer output256_0 = Util.computeAES_CMAC(aes256, input256_0);
+ System.out.println("Message:" + input256_0.toHexString());
+ System.out.println("AES-CMAC output: " + output256_0.toHexString());
+ System.out.println("");
+
+ //Attempt 16 bytes
+
+ TPSBuffer input256_128 = new TPSBuffer(message);
+ TPSBuffer output256_128 = Util.computeAES_CMAC(aes256, input256_128);
+ System.out.println("Message:" + input256_128.toHexString());
+ System.out.println("AES-CMAC output: " + output256_128.toHexString());
+ System.out.println("");
+
+ //Attempt 40 bytes
+
+ TPSBuffer input256_320 = new TPSBuffer(message320);
+ TPSBuffer output256_320 = Util.computeAES_CMAC(aes256, input256_320);
+ System.out.println("Message:" + input256_320.toHexString());
+ System.out.println("AES-CMAC output: " + output256_320.toHexString());
+ System.out.println("");
+
+ //Attempt 64 bytes
+
+ TPSBuffer input256_512 = new TPSBuffer(message512);
+ TPSBuffer output256_512 = Util.computeAES_CMAC(aes256, input256_512);
+ System.out.println("Message:" + input256_512.toHexString());
+ System.out.println("AES-CMAC output: " + output256_512.toHexString());
+
+ } catch (AlreadyInitializedException e) {
+ // it is ok if it is already initialized
+ } catch (Exception e) {
+ System.err.println("JSS error!" + e);
+ System.exit(1);
+ }
+*/
+ }
+
+
}
diff --git a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
index c7ad7f7c3..aee430247 100644
--- a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
+++ b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
@@ -527,6 +527,12 @@ public class TPSMessage {
}
}
+ int debug = 1;
+
+ if (debug == 1) {
+ CMS.debug("TPSMessage.createMessage: message: " + message);
+ }
+
TPSMessage new_msg = new TPSMessage(message);
return new_msg.createMessage();
diff --git a/base/java-tools/bin/pki b/base/java-tools/bin/pki
index 53e1b893a..6060a6e11 100644
--- a/base/java-tools/bin/pki
+++ b/base/java-tools/bin/pki
@@ -1,7 +1,6 @@
-#!/usr/bin/python
-# Authors:
-# Endi S. Dewata <edewata@redhat.com>
+#!/bin/sh
#
+# --- 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.
@@ -15,222 +14,26 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
-# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2017 Red Hat, Inc.
# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
#
-from __future__ import absolute_import
-from __future__ import print_function
-import shlex
-import subprocess
-import sys
-import traceback
+# default PKI configuration
+. /usr/share/pki/etc/pki.conf
-import pki.cli
-import pki.cli.pkcs12
+# system-wide PKI configuration
+if [ -f /etc/pki/pki.conf ]
+then
+ . /etc/pki/pki.conf
+fi
+# user-specific PKI configuration
+if [ -f $HOME/.dogtag/pki.conf ]
+then
+ . $HOME/.dogtag/pki.conf
+fi
-PYTHON_COMMANDS = ['pkcs12-import']
+python -m pki.cli.main "$@"
-
-class PKICLI(pki.cli.CLI):
-
- def __init__(self):
- super(PKICLI, self).__init__(
- 'pki', 'PKI command-line interface')
-
- self.database = None
- self.password = None
- self.password_file = None
- self.token = None
-
- self.add_module(pki.cli.pkcs12.PKCS12CLI())
-
- def get_full_module_name(self, module_name):
- return module_name
-
- def print_help(self):
- print('Usage: pki [OPTIONS]')
- print()
- print(' --client-type <type> PKI client type (default: java)')
- print(' -d <path> Client security database location ' +
- '(default: ~/.dogtag/nssdb)')
- print(' -c <password> Client security database password ' +
- '(mutually exclusive to the -C option)')
- print(' -C <path> Client-side password file ' +
- '(mutually exclusive to the -c option)')
- print(' --token <name> Security token name')
- print()
- print(' -v, --verbose Run in verbose mode.')
- print(' --debug Show debug messages.')
- print(' --help Show help message.')
- print()
-
- super(PKICLI, self).print_help()
-
- def execute_java(self, args, stdout=sys.stdout):
-
- # read Java home
- value = subprocess.check_output(
- '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $JAVA_HOME',
- shell=True)
- java_home = value.decode(sys.getfilesystemencoding()).strip()
-
- # read PKI library
- value = subprocess.check_output(
- '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_LIB',
- shell=True)
- pki_lib = value.decode(sys.getfilesystemencoding()).strip()
-
- # read logging configuration path
- value = subprocess.check_output(
- '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $LOGGING_CONFIG',
- shell=True)
- logging_config = value.decode(sys.getfilesystemencoding()).strip()
-
- cmd = [
- java_home + '/bin/java',
- '-Djava.ext.dirs=' + pki_lib,
- '-Djava.util.logging.config.file=' + logging_config,
- 'com.netscape.cmstools.cli.MainCLI'
- ]
-
- # restore options for Java commands
-
- if self.database:
- cmd.extend(['-d', self.database])
-
- if self.password:
- cmd.extend(['-c', self.password])
-
- if self.password_file:
- cmd.extend(['-C', self.password_file])
-
- if self.token and self.token != 'internal':
- cmd.extend(['--token', self.token])
-
- if self.verbose:
- cmd.extend(['--verbose'])
-
- cmd.extend(args)
-
- if self.verbose:
- print('Java command: %s' % ' '.join(cmd))
-
- subprocess.check_call(cmd, stdout=stdout)
-
- def execute(self, argv):
-
- # append global options
- value = subprocess.check_output(
- '. /usr/share/pki/etc/pki.conf && . /etc/pki/pki.conf && echo $PKI_CLI_OPTIONS',
- shell=True)
- value = value.decode(sys.getfilesystemencoding()).strip()
- args = shlex.split(value)
- args.extend(argv[1:])
-
- client_type = 'java'
-
- pki_options = []
- command = None
- cmd_args = []
-
- # read pki options before the command
- # remove options for Python module
-
- i = 0
- while i < len(args):
- # if arg is a command, stop
- if args[i][0] != '-':
- command = args[i]
- break
-
- # get database path
- if args[i] == '-d':
- self.database = args[i + 1]
- pki_options.append(args[i])
- pki_options.append(args[i + 1])
- i = i + 2
-
- # get database password
- elif args[i] == '-c':
- self.password = args[i + 1]
- pki_options.append(args[i])
- pki_options.append(args[i + 1])
- i = i + 2
-
- # get database password file path
- elif args[i] == '-C':
- self.password_file = args[i + 1]
- pki_options.append(args[i])
- pki_options.append(args[i + 1])
- i = i + 2
-
- # get token name
- elif args[i] == '--token':
- self.token = args[i + 1]
- pki_options.append(args[i])
- pki_options.append(args[i + 1])
- i = i + 2
-
- # check verbose option
- elif args[i] == '-v' or args[i] == '--verbose':
- self.set_verbose(True)
- pki_options.append(args[i])
- i = i + 1
-
- # check debug option
- elif args[i] == '--debug':
- self.set_verbose(True)
- self.set_debug(True)
- pki_options.append(args[i])
- i = i + 1
-
- # get client type
- elif args[i] == '--client-type':
- client_type = args[i + 1]
- pki_options.append(args[i])
- pki_options.append(args[i + 1])
- i = i + 2
-
- else: # otherwise, save the arg for the next module
- cmd_args.append(args[i])
- i = i + 1
-
- # save the rest of the args
- while i < len(args):
- cmd_args.append(args[i])
- i = i + 1
-
- if self.verbose:
- print('PKI options: %s' % ' '.join(pki_options))
- print('PKI command: %s %s' % (command, ' '.join(cmd_args)))
-
- if client_type == 'python' or command in PYTHON_COMMANDS:
- (module, module_args) = self.parse_args(cmd_args)
- module.execute(module_args)
-
- elif client_type == 'java':
- self.execute_java(cmd_args)
-
- else:
- raise Exception('Unsupported client type: ' + client_type)
-
-
-if __name__ == '__main__':
-
- cli = PKICLI()
-
- try:
- cli.execute(sys.argv)
-
- except subprocess.CalledProcessError as e:
- if cli.verbose:
- print('ERROR: %s' % e)
- elif cli.debug:
- traceback.print_exc()
- sys.exit(e.returncode)
-
- except KeyboardInterrupt:
- print()
- sys.exit(-1)
+exit $?
diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
index 8d5bd1f8a..0a05a395a 100644
--- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -59,7 +59,6 @@ import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyPairAlgorithm;
import org.mozilla.jss.crypto.KeyPairGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.Signature;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
@@ -551,9 +550,12 @@ public class CRMFPopClient {
public byte[] wrapPrivateKey(CryptoToken token, SymmetricKey sessionKey, byte[] iv, KeyPair keyPair) throws Exception {
// wrap private key using session
- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper.initWrap(sessionKey, new IVParameterSpec(iv));
- return wrapper.wrap((org.mozilla.jss.crypto.PrivateKey) keyPair.getPrivate());
+ return CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sessionKey,
+ (org.mozilla.jss.crypto.PrivateKey) keyPair.getPrivate(),
+ new IVParameterSpec(iv),
+ KeyWrapAlgorithm.DES3_CBC_PAD);
}
public byte[] wrapSessionKey(CryptoToken token, X509Certificate transportCert, SymmetricKey sessionKey) throws Exception {
@@ -561,9 +563,7 @@ public class CRMFPopClient {
// wrap session key using KRA transport cert
// currently, a transport cert has to be an RSA cert,
// regardless of the key you are wrapping
- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
- wrapper.initWrap(transportCert.getPublicKey(), null);
- return wrapper.wrap(sessionKey);
+ return CryptoUtil.wrapUsingPublicKey(token, transportCert.getPublicKey(), sessionKey, KeyWrapAlgorithm.RSA);
}
public CertRequest createCertRequest(
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java
index 22bddcf32..a3f1deb36 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java
@@ -18,6 +18,7 @@
package com.netscape.cmstools.client;
+import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -97,11 +98,13 @@ public class ClientCertValidateCLI extends CLI {
CryptoManager cm = CryptoManager.getInstance();
if (cu.getUsage() != CryptoManager.CertificateUsage.CheckAllUsages.getUsage()) {
- if (cm.isCertValid(nickname, true, cu)) {
+ try {
+ cm.verifyCertificate(nickname, true, cu);
System.out.println("Valid certificate: " + nickname);
return true;
- } else {
- System.out.println("Invalid certificate: " + nickname);
+ } catch (CertificateException e) {
+ // Invalid certificate: (<code>) <message>
+ System.out.println(e.getMessage());
return false;
}
diff --git a/base/kra/functional/src/com/netscape/cms/servlet/test/GeneratePKIArchiveOptions.java b/base/kra/functional/src/com/netscape/cms/servlet/test/GeneratePKIArchiveOptions.java
index 03a0729e7..6c835b439 100644
--- a/base/kra/functional/src/com/netscape/cms/servlet/test/GeneratePKIArchiveOptions.java
+++ b/base/kra/functional/src/com/netscape/cms/servlet/test/GeneratePKIArchiveOptions.java
@@ -3,7 +3,6 @@ package com.netscape.cms.servlet.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
-import java.io.CharConversionException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -11,10 +10,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
@@ -23,16 +18,11 @@ import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.mozilla.jss.CryptoManager;
-import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.crypto.AlreadyInitializedException;
-import org.mozilla.jss.crypto.BadPaddingException;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.IVParameterSpec;
-import org.mozilla.jss.crypto.IllegalBlockSizeException;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
-import org.mozilla.jss.crypto.SymmetricKey.NotExtractableException;
-import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.util.Password;
import com.netscape.cmsutil.crypto.CryptoUtil;
@@ -101,10 +91,7 @@ public class GeneratePKIArchiveOptions {
out.close();
}
- public static void main(String args[]) throws InvalidKeyException, CertificateEncodingException,
- CharConversionException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
- IllegalStateException, TokenException, IOException, IllegalBlockSizeException, BadPaddingException,
- InvalidBERException, NotExtractableException {
+ public static void main(String args[]) throws Exception {
String token_pwd = null;
String db_dir = "./";
String out_file = "./options.out";
@@ -199,7 +186,7 @@ public class GeneratePKIArchiveOptions {
// Data to be archived
SymmetricKey vek = null;
if (!passphraseMode) {
- vek = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0);
+ vek = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, false);
// store vek in file
write_file(Utils.base64encode(vek.getKeyData()), key_file);
}
diff --git a/base/kra/src/com/netscape/kra/AsymKeyGenService.java b/base/kra/src/com/netscape/kra/AsymKeyGenService.java
index 7b43548d5..ffd8b03cf 100644
--- a/base/kra/src/com/netscape/kra/AsymKeyGenService.java
+++ b/base/kra/src/com/netscape/kra/AsymKeyGenService.java
@@ -197,6 +197,14 @@ public class AsymKeyGenService implements IService {
record.set(KeyRecord.ATTR_REALM, realm);
}
+ try {
+ record.setWrappingParams(storageUnit.getOldWrappingParams());
+ } catch (Exception e) {
+ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(),
+ clientKeyId, null, "Failed to store wrapping params");
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"));
+ }
+
storage.addKeyRecord(record);
auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.SUCCESS, request.getRequestId(),
diff --git a/base/kra/src/com/netscape/kra/EncryptionUnit.java b/base/kra/src/com/netscape/kra/EncryptionUnit.java
index af4c3ec19..6d101089d 100644
--- a/base/kra/src/com/netscape/kra/EncryptionUnit.java
+++ b/base/kra/src/com/netscape/kra/EncryptionUnit.java
@@ -19,25 +19,19 @@ package com.netscape.kra;
import java.security.PublicKey;
-import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.SymmetricKey;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.key.KeyRequestResource;
import com.netscape.certsrv.security.IEncryptionUnit;
import com.netscape.certsrv.security.WrappingParams;
-
-import netscape.security.util.DerInputStream;
-import netscape.security.util.DerOutputStream;
-import netscape.security.util.DerValue;
+import com.netscape.cmsutil.crypto.CryptoUtil;
/**
* A class represents the transport key pair. This key pair
@@ -51,13 +45,13 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
/* Establish one constant IV for base class, to be used for
internal operations. Constant IV acceptable for symmetric keys.
*/
- private byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
- protected IVParameterSpec IV = null;
+ public static final byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ public static final byte[] iv2 = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ public static final IVParameterSpec IV = new IVParameterSpec(iv);
+ public static final IVParameterSpec IV2 = new IVParameterSpec(iv2);
public EncryptionUnit() {
CMS.debug("EncryptionUnit.EncryptionUnit this: " + this.toString());
-
- IV = new IVParameterSpec(iv);
}
public abstract CryptoToken getToken();
@@ -72,343 +66,29 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
public abstract PrivateKey getPrivateKey(org.mozilla.jss.crypto.X509Certificate cert);
- /**
- * Protects the private key so that it can be stored in
- * internal database.
- */
- public byte[] encryptInternalPrivate(byte priKey[]) throws Exception {
- try (DerOutputStream out = new DerOutputStream()) {
- CMS.debug("EncryptionUnit.encryptInternalPrivate");
- CryptoToken internalToken = getInternalToken();
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- // (1) generate session key
- SymmetricKey sk = generate_session_key(internalToken, false, params);
-
- // (2) wrap private key with session key
- byte[] pri = encrypt_private_key(internalToken, sk, priKey, params);
-
- // (3) wrap session with transport public
- byte[] session = wrap_session_key(internalToken, getPublicKey(), sk, params);
-
- // use MY own structure for now:
- // SEQUENCE {
- // encryptedSession OCTET STRING,
- // encryptedPrivate OCTET STRING
- // }
+ public abstract WrappingParams getWrappingParams() throws EBaseException;
- DerOutputStream tmp = new DerOutputStream();
-
- tmp.putOctetString(session);
- tmp.putOctetString(pri);
- out.write(DerValue.tag_Sequence, tmp);
-
- return out.toByteArray();
- }
- }
-
- public byte[] wrap(PrivateKey privKey) throws Exception {
- return _wrap(privKey,null);
- }
-
- public byte[] wrap(SymmetricKey symmKey) throws Exception {
- return _wrap(null,symmKey);
+ public WrappingParams getOldWrappingParams() {
+ return new WrappingParams(
+ SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0,
+ KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
+ KeyWrapAlgorithm.DES3_CBC_PAD, IV, IV);
}
public SymmetricKey unwrap_session_key(CryptoToken token, byte encSymmKey[], SymmetricKey.Usage usage,
- WrappingParams params) {
+ WrappingParams params) throws Exception {
PrivateKey wrappingKey = getPrivateKey();
String priKeyAlgo = wrappingKey.getAlgorithm();
if (priKeyAlgo.equals("EC"))
params.setSkWrapAlgorithm(KeyWrapAlgorithm.AES_ECB);
- return unwrap_session_key(token, encSymmKey, usage, wrappingKey, params);
- }
-
- public SymmetricKey unwrap_sym(byte encSymmKey[], WrappingParams params) {
- return unwrap_session_key(getToken(), encSymmKey, SymmetricKey.Usage.WRAP, params);
- }
-
- /**
- * Decrypts the user private key.
- */
- public byte[] decryptExternalPrivate(byte encSymmKey[],
- String symmAlgOID, byte symmAlgParams[], byte encValue[])
- throws Exception {
- return decryptExternalPrivate(encSymmKey, symmAlgOID, symmAlgParams,
- encValue, null);
- }
-
- /**
- * Decrypts the user private key.
- */
- public byte[] decryptExternalPrivate(byte encSymmKey[],
- String symmAlgOID, byte symmAlgParams[], byte encValue[],
- org.mozilla.jss.crypto.X509Certificate transCert)
- throws Exception {
-
- CMS.debug("EncryptionUnit.decryptExternalPrivate");
- CryptoToken token = getToken(transCert);
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- PrivateKey wrappingKey = getPrivateKey(transCert);
- String priKeyAlgo = wrappingKey.getAlgorithm();
- if (priKeyAlgo.equals("EC"))
- params.setSkWrapAlgorithm(KeyWrapAlgorithm.AES_ECB);
-
- SymmetricKey sk = unwrap_session_key(
+ return CryptoUtil.unwrap(
token,
+ params.getSkType(),
+ 0,
+ usage, wrappingKey,
encSymmKey,
- SymmetricKey.Usage.DECRYPT,
- wrappingKey,
- params);
-
- return decrypt_private_key(token, new IVParameterSpec(symmAlgParams), sk, encValue, params);
- }
-
- /**
- * External unwrapping. Unwraps the symmetric key using
- * the transport private key.
- */
- public SymmetricKey unwrap_symmetric(byte encSymmKey[],
- String symmAlgOID, byte symmAlgParams[],
- byte encValue[], SymmetricKey.Type algorithm, int strength)
- throws Exception {
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- CryptoToken token = getToken();
- // (1) unwrap the session key
- SymmetricKey sk = unwrap_session_key(token, encSymmKey, SymmetricKey.Usage.UNWRAP, params);
-
- // (2) unwrap the session-wrapped-symmetric-key
- SymmetricKey symKey = unwrap_symmetric_key(
- token,
- new IVParameterSpec(symmAlgParams),
- algorithm,
- strength,
- SymmetricKey.Usage.DECRYPT,
- sk,
- encValue,
- params);
-
- return symKey;
- }
-
- /**
- * External unwrapping. Unwraps the data using
- * the transport private key.
- */
- public PrivateKey unwrap(byte encSymmKey[],
- String symmAlgOID, byte symmAlgParams[],
- byte encValue[], PublicKey pubKey)
- throws Exception {
- return unwrap (encSymmKey, symmAlgOID, symmAlgParams,
- encValue, pubKey, null);
- }
-
- /**
- * External unwrapping. Unwraps the data using
- * the transport private key.
- */
- public PrivateKey unwrap(byte encSymmKey[],
- String symmAlgOID, byte symmAlgParams[],
- byte encValue[], PublicKey pubKey,
- org.mozilla.jss.crypto.X509Certificate transCert)
- throws Exception {
- CryptoToken token = getToken(transCert);
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- PrivateKey wrappingKey = getPrivateKey(transCert);
- String priKeyAlgo = wrappingKey.getAlgorithm();
- if (priKeyAlgo.equals("EC"))
- params.setSkWrapAlgorithm(KeyWrapAlgorithm.AES_ECB);
-
- // (1) unwrap the session key
- SymmetricKey sk = unwrap_session_key(
- token,
- encSymmKey,
- SymmetricKey.Usage.UNWRAP,
- wrappingKey,
- params);
-
- // (2) unwrap the session-wrapped-private key
- return unwrap_private_key(
- token,
- pubKey,
- new IVParameterSpec(symmAlgParams),
- true /*temporary*/,
- sk,
- encValue,
- params);
- }
-
- /**
- * External unwrapping. Unwraps the data using
- * the transport private key.
- */
-
- public byte[] decryptInternalPrivate(byte wrappedKeyData[])
- throws Exception {
- CMS.debug("EncryptionUnit.decryptInternalPrivate");
- DerValue val = new DerValue(wrappedKeyData);
- // val.tag == DerValue.tag_Sequence
- DerInputStream in = val.data;
- DerValue dSession = in.getDerValue();
- byte session[] = dSession.getOctetString();
- DerValue dPri = in.getDerValue();
- byte pri[] = dPri.getOctetString();
-
- CryptoToken token = getToken();
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- // (1) unwrap the session key
- CMS.debug("decryptInternalPrivate(): getting key wrapper on slot:" + token.getName());
- SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.DECRYPT, params);
-
- // (2) decrypt the private key
- return decrypt_private_key(token, IV, sk, pri, params);
- }
-
- /**
- * External unwrapping of stored symmetric key.
- */
- public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize)
- throws Exception {
- DerValue val = new DerValue(wrappedKeyData);
- // val.tag == DerValue.tag_Sequence
- DerInputStream in = val.data;
- DerValue dSession = in.getDerValue();
- byte session[] = dSession.getOctetString();
- DerValue dPri = in.getDerValue();
- byte pri[] = dPri.getOctetString();
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- CryptoToken token = getToken();
- // (1) unwrap the session key
- SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.UNWRAP, params);
-
- // (2) unwrap the session-wrapped-symmetric key
- return unwrap_symmetric_key(token, IV, algorithm, keySize, SymmetricKey.Usage.UNWRAP, sk, pri, params);
- }
-
- /**
- * Internal unwrapping.
- */
- public PrivateKey unwrap_temp(byte wrappedKeyData[], PublicKey pubKey)
- throws Exception {
- return _unwrap(wrappedKeyData, pubKey, true);
- }
-
- /**
- * Internal unwrapping.
- */
- public PrivateKey unwrap(byte wrappedKeyData[], PublicKey pubKey)
- throws Exception {
- return _unwrap(wrappedKeyData, pubKey, false);
- }
-
- /**
- * Internal unwrapping.
- */
- private PrivateKey _unwrap(byte wrappedKeyData[], PublicKey pubKey, boolean temporary)
- throws Exception {
- DerValue val = new DerValue(wrappedKeyData);
- // val.tag == DerValue.tag_Sequence
- DerInputStream in = val.data;
- DerValue dSession = in.getDerValue();
- byte session[] = dSession.getOctetString();
- DerValue dPri = in.getDerValue();
- byte pri[] = dPri.getOctetString();
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- CryptoToken token = getToken();
- // (1) unwrap the session key
- SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.UNWRAP, params);
-
- // (2) unwrap the private key
- return unwrap_private_key(token, pubKey, IV, temporary, sk, pri, params);
- }
-
- /***
- * Internal wrap, accounts for either private or symmetric key
- */
- private byte[] _wrap(PrivateKey priKey, SymmetricKey symmKey) throws Exception {
- try (DerOutputStream out = new DerOutputStream()) {
- if ((priKey == null && symmKey == null) || (priKey != null && symmKey != null)) {
- return null;
- }
- CMS.debug("EncryptionUnit.wrap interal.");
- CryptoToken token = getToken();
-
- SymmetricKey.Usage usages[] = new SymmetricKey.Usage[2];
- usages[0] = SymmetricKey.Usage.WRAP;
- usages[1] = SymmetricKey.Usage.UNWRAP;
-
- WrappingParams params = new WrappingParams(
- SymmetricKey.DES3, usages, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- // (1) generate session key
- SymmetricKey sk = generate_session_key(token, true, params);
-
- // (2) wrap private key with session key
- // KeyWrapper wrapper = internalToken.getKeyWrapper(
-
- byte pri[] = null;
-
- if (priKey != null) {
- pri = wrap_private_key(token, sk, priKey, params);
- } else if (symmKey != null) {
- pri = wrap_symmetric_key(token, sk, symmKey, params);
- }
-
- CMS.debug("EncryptionUnit:wrap() privKey wrapped");
-
- byte[] session = wrap_session_key(token, getPublicKey(), sk, params);
- CMS.debug("EncryptionUnit:wrap() session key wrapped");
-
- // use MY own structure for now:
- // SEQUENCE {
- // encryptedSession OCTET STRING,
- // encryptedPrivate OCTET STRING
- // }
-
- DerOutputStream tmp = new DerOutputStream();
-
- tmp.putOctetString(session);
- tmp.putOctetString(pri);
- out.write(DerValue.tag_Sequence, tmp);
-
- return out.toByteArray();
- }
+ params.getSkWrapAlgorithm());
}
/**
@@ -418,117 +98,4 @@ public abstract class EncryptionUnit implements IEncryptionUnit {
EBaseException {
}
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Crypto specific methods below here ...
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- private SymmetricKey generate_session_key(CryptoToken token, boolean temporary, WrappingParams params)
- throws Exception{
- org.mozilla.jss.crypto.KeyGenerator kg = token.getKeyGenerator(params.getSkKeyGenAlgorithm());
- SymmetricKey.Usage[] usages = params.getSkUsages();
- if (usages != null)
- kg.setKeyUsages(usages);
- kg.temporaryKeys(temporary);
- if (params.getSkLength() > 0)
- kg.initialize(params.getSkLength());
- SymmetricKey sk = kg.generate();
- CMS.debug("EncryptionUnit:generate_session_key() session key generated on slot: " + token.getName());
- return sk;
- }
-
- private byte[] wrap_session_key(CryptoToken token, PublicKey wrappingKey, SymmetricKey sessionKey,
- WrappingParams params) throws Exception {
- KeyWrapper rsaWrap = token.getKeyWrapper(params.getSkWrapAlgorithm());
- rsaWrap.initWrap(wrappingKey, null);
- byte session[] = rsaWrap.wrap(sessionKey);
- return session;
- }
-
- public SymmetricKey unwrap_session_key(CryptoToken token, byte[] wrappedSessionKey, SymmetricKey.Usage usage,
- PrivateKey wrappingKey, WrappingParams params) {
- try {
- KeyWrapper keyWrapper = token.getKeyWrapper(params.getSkWrapAlgorithm());
- keyWrapper.initUnwrap(wrappingKey, null);
-
- SymmetricKey sk = keyWrapper.unwrapSymmetric(
- wrappedSessionKey,
- params.getSkTyoe(),
- usage,
- 0);
- CMS.debug("EncryptionUnit::unwrap_sym() unwrapped on slot: "
- + token.getName());
- return sk;
- } catch (Exception e) {
- CMS.debug("EncryptionUnit::unwrap_session_key() error:" + e.toString());
- return null;
- }
- }
-
- private byte[] wrap_symmetric_key(CryptoToken token, SymmetricKey sessionKey, SymmetricKey data,
- WrappingParams params) throws Exception {
- KeyWrapper wrapper = token.getKeyWrapper(params.getPayloadWrapAlgorithm());
-
- wrapper.initWrap(sessionKey, IV);
- return wrapper.wrap(data);
- }
-
- private SymmetricKey unwrap_symmetric_key(CryptoToken token, IVParameterSpec iv, SymmetricKey.Type algorithm,
- int strength, SymmetricKey.Usage usage, SymmetricKey sessionKey, byte[] wrappedData,
- WrappingParams params) throws Exception {
- KeyWrapper wrapper = token.getKeyWrapper(params.getPayloadWrapAlgorithm());
- wrapper.initUnwrap(sessionKey, iv);
- SymmetricKey symKey = wrapper.unwrapSymmetric(wrappedData, algorithm, usage, strength);
- return symKey;
- }
-
- private byte[] wrap_private_key(CryptoToken token, SymmetricKey sessionKey, PrivateKey data,
- WrappingParams params) throws Exception {
- KeyWrapper wrapper = token.getKeyWrapper(params.getPayloadWrapAlgorithm());
- wrapper.initWrap(sessionKey, IV);
- return wrapper.wrap(data);
- }
-
- private PrivateKey unwrap_private_key(CryptoToken token, PublicKey pubKey, IVParameterSpec iv,
- boolean temporary, SymmetricKey sessionKey, byte[] wrappedData, WrappingParams params)
- throws Exception {
- KeyWrapper wrapper = token.getKeyWrapper(params.getPayloadWrapAlgorithm());
- wrapper.initUnwrap(sessionKey, iv);
-
- // Get the key type for unwrapping the private key.
- PrivateKey.Type keyType = null;
- if (pubKey.getAlgorithm().equalsIgnoreCase(KeyRequestResource.RSA_ALGORITHM)) {
- keyType = PrivateKey.RSA;
- } else if (pubKey.getAlgorithm().equalsIgnoreCase(KeyRequestResource.DSA_ALGORITHM)) {
- keyType = PrivateKey.DSA;
- } else if (pubKey.getAlgorithm().equalsIgnoreCase(KeyRequestResource.EC_ALGORITHM)) {
- keyType = PrivateKey.EC;
- }
-
- PrivateKey pk = null;
- if (temporary) {
- pk = wrapper.unwrapTemporaryPrivate(wrappedData,
- keyType, pubKey);
- } else {
- pk = wrapper.unwrapPrivate(wrappedData,
- keyType, pubKey);
- }
- return pk;
- }
-
- private byte[] encrypt_private_key(CryptoToken token, SymmetricKey sessionKey, byte[] data, WrappingParams params)
- throws Exception {
- Cipher cipher = token.getCipherContext(params.getPayloadEncryptionAlgorithm());
-
- cipher.initEncrypt(sessionKey, IV);
- byte pri[] = cipher.doFinal(data);
- return pri;
- }
-
- private byte[] decrypt_private_key(CryptoToken token, IVParameterSpec iv, SymmetricKey sessionKey,
- byte[] encryptedData, WrappingParams params) throws Exception {
- Cipher cipher = token.getCipherContext(params.getPayloadEncryptionAlgorithm());
- cipher.initDecrypt(sessionKey, iv);
- return cipher.doFinal(encryptedData);
- }
-
}
diff --git a/base/kra/src/com/netscape/kra/EnrollmentService.java b/base/kra/src/com/netscape/kra/EnrollmentService.java
index fbefc549e..5aa35da57 100644
--- a/base/kra/src/com/netscape/kra/EnrollmentService.java
+++ b/base/kra/src/com/netscape/kra/EnrollmentService.java
@@ -169,7 +169,7 @@ public class EnrollmentService implements IService {
if (CMS.debugOn())
CMS.debug("EnrollmentServlet: KRA services enrollment request");
- // the request reocrd field delayLDAPCommit == "true" will cause
+ // the request record field delayLDAPCommit == "true" will cause
// updateRequest() to delay actual write to ldap
request.setExtData("delayLDAPCommit", "true");
@@ -502,6 +502,22 @@ public class EnrollmentService implements IService {
rec.set(KeyRecord.ATTR_REALM, realm);
}
+ try {
+ rec.setWrappingParams(mStorageUnit.getWrappingParams());
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE, "Failed to store wrapping parameters");
+ // TODO(alee) Set correct audit message here
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+ throw new EKRAException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"));
+ }
+
IKeyRepository storage = mKRA.getKeyRepository();
BigInteger serialNo = storage.getNextSerialNumber();
diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java
index d3937915b..4dec837a0 100644
--- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java
+++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java
@@ -31,7 +31,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import org.mozilla.jss.asn1.ASN1Util;
-import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
@@ -39,7 +38,6 @@ import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyPairAlgorithm;
import org.mozilla.jss.crypto.KeyPairGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.PQGParamGenException;
import org.mozilla.jss.crypto.PQGParams;
import org.mozilla.jss.crypto.PrivateKey;
@@ -326,23 +324,6 @@ public class NetkeyKeygenService implements IService {
}
}
- // this encrypts bytes with a symmetric key
- public byte[] encryptIt(byte[] toBeEncrypted, SymmetricKey symKey, CryptoToken token,
- IVParameterSpec IV) {
- try {
- Cipher cipher = token.getCipherContext(
- EncryptionAlgorithm.DES3_CBC_PAD);
-
- cipher.initEncrypt(symKey, IV);
- byte pri[] = cipher.doFinal(toBeEncrypted);
- return pri;
- } catch (Exception e) {
- CMS.debug("NetkeyKeygenService:initEncrypt() threw exception: " + e.toString());
- return null;
- }
-
- }
-
/**
* Services an archival request from netkey.
* <P>
@@ -371,7 +352,6 @@ public class NetkeyKeygenService implements IService {
wrapped_des_key = null;
boolean archive = true;
- PK11SymKey sk = null;
byte[] publicKeyData = null;
;
String PubKey = "";
@@ -456,12 +436,9 @@ public class NetkeyKeygenService implements IService {
(wrapped_des_key.length > 0)) {
WrappingParams wrapParams = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
+ SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0,
KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
-
- // unwrap the DES key
- sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams);
+ KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionUnit.IV, EncryptionUnit.IV);
/* XXX could be done in HSM*/
KeyPair keypair = null;
@@ -530,24 +507,29 @@ public class NetkeyKeygenService implements IService {
CMS.debug("NetkeyKeygenService: got private key");
}
- if (sk == null) {
- CMS.debug("NetkeyKeygenService: no DES key");
+ // unwrap the DES key
+ PK11SymKey sk = null;
+ try {
+ sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams);
+ CMS.debug("NetkeyKeygenService: received DES key");
+ } catch (Exception e) {
+ CMS.debug("NetkeyKeygenService: no DES key: " + e);
request.setExtData(IRequest.RESULT, Integer.valueOf(4));
return false;
- } else {
- CMS.debug("NetkeyKeygenService: received DES key");
}
// 3 wrapping should be done in HSM
// wrap private key with DES
- KeyWrapper symWrap =
- keygenToken.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
CMS.debug("NetkeyKeygenService: wrapper token=" + keygenToken.getName());
- CMS.debug("NetkeyKeygenService: got key wrapper");
-
CMS.debug("NetkeyKeygenService: key transport key is on slot: " + sk.getOwningToken().getName());
- symWrap.initWrap(sk, algParam);
- byte wrapped[] = symWrap.wrap((PrivateKey) privKey);
+
+ byte[] wrapped = CryptoUtil.wrapUsingSymmetricKey(
+ keygenToken,
+ sk,
+ (PrivateKey) privKey,
+ algParam,
+ KeyWrapAlgorithm.DES3_CBC_PAD);
+
/*
CMS.debug("NetkeyKeygenService: wrap called");
CMS.debug(wrapped);
@@ -686,6 +668,9 @@ public class NetkeyKeygenService implements IService {
CMS.debug("NetkeyKeygenService: serialNo null");
return false;
}
+
+ rec.setWrappingParams(mStorageUnit.getWrappingParams());
+
CMS.debug("NetkeyKeygenService: before addKeyRecord");
rec.set(KeyRecord.ATTR_ID, serialNo);
request.setExtData(ATTR_KEY_RECORD, serialNo);
diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java
index 70b5e57a7..c89e2f388 100644
--- a/base/kra/src/com/netscape/kra/RecoveryService.java
+++ b/base/kra/src/com/netscape/kra/RecoveryService.java
@@ -274,7 +274,10 @@ public class RecoveryService implements IService {
try {
mKRA.getStorageKeyUnit().unwrap(
- keyRecord.getPrivateKeyData(), null);
+ keyRecord.getPrivateKeyData(),
+ null,
+ false,
+ keyRecord.getWrappingParams(mKRA.getStorageKeyUnit().getOldWrappingParams()));
} catch (Exception e) {
throw new EBaseException("Failed to unwrap private key", e);
}
@@ -393,33 +396,21 @@ public class RecoveryService implements IService {
mStorageUnit.login(creds);
}
- /* wrapped retrieve session key and private key */
- DerValue val = new DerValue(keyRecord.getPrivateKeyData());
- DerInputStream in = val.data;
- DerValue dSession = in.getDerValue();
- byte session[] = dSession.getOctetString();
- DerValue dPri = in.getDerValue();
- byte pri[] = dPri.getOctetString();
-
- /* debug */
- byte publicKeyData[] = keyRecord.getPublicKeyData();
PublicKey pubkey = null;
try {
- pubkey = X509Key.parsePublicKey(new DerValue(publicKeyData));
+ pubkey = X509Key.parsePublicKey(new DerValue(keyRecord.getPublicKeyData()));
} catch (Exception e) {
CMS.debug("RecoverService: after parsePublicKey:" + e.toString());
throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "public key parsing failure"));
}
- byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+
PrivateKey privKey = null;
try {
privKey = mStorageUnit.unwrap(
- session,
- keyRecord.getAlgorithm(),
- iv,
- pri,
- pubkey);
-
+ keyRecord.getPrivateKeyData(),
+ pubkey,
+ false,
+ keyRecord.getWrappingParams(mKRA.getStorageKeyUnit().getOldWrappingParams()));
} catch (Exception e) {
mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_PRIVATE_KEY_NOT_FOUND"));
throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1",
@@ -564,7 +555,9 @@ public class RecoveryService implements IService {
mKRA.log(ILogger.LL_INFO, "KRA decrypts internal private");
try {
- byte[] privateKeyData = mStorageUnit.decryptInternalPrivate(keyRecord.getPrivateKeyData());
+ byte[] privateKeyData = mStorageUnit.decryptInternalPrivate(
+ keyRecord.getPrivateKeyData(),
+ keyRecord.getWrappingParams(mKRA.getStorageKeyUnit().getOldWrappingParams()));
if (CMS.getConfigStore().getBoolean("kra.keySplitting")) {
mStorageUnit.logout();
diff --git a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
index 1c94bca6e..598ed0232 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
@@ -1,11 +1,7 @@
package com.netscape.kra;
import java.io.ByteArrayOutputStream;
-import java.io.CharConversionException;
-import java.io.IOException;
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.AlgorithmParameterSpec;
@@ -16,21 +12,17 @@ import java.util.Random;
import javax.crypto.spec.RC2ParameterSpec;
import org.dogtagpki.server.kra.rest.KeyRequestService;
-import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.asn1.OCTET_STRING;
-import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.PBEAlgorithm;
import org.mozilla.jss.crypto.PBEKeyGenParams;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.SymmetricKey;
-import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.pkcs12.PasswordConverter;
import org.mozilla.jss.pkcs7.ContentInfo;
import org.mozilla.jss.pkcs7.EncryptedContentInfo;
@@ -54,6 +46,7 @@ import com.netscape.certsrv.security.IStorageKeyUnit;
import com.netscape.certsrv.security.ITransportKeyUnit;
import com.netscape.certsrv.security.WrappingParams;
import com.netscape.cmscore.dbs.KeyRecord;
+import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.util.Utils;
import netscape.security.util.DerValue;
@@ -179,7 +172,8 @@ public class SecurityDataProcessor {
wrappedSessionKey,
algStr,
sparams,
- secdata);
+ secdata,
+ null);
} catch (Exception e) {
throw new EBaseException("Can't decrypt symm key using allEncDecrypt_archival : true .");
@@ -215,7 +209,8 @@ public class SecurityDataProcessor {
wrappedSessionKey,
algStr,
sparams,
- secdata);
+ secdata,
+ null);
} catch (Exception e) {
throw new EBaseException("Can't decrypt passphrase.", e);
}
@@ -290,6 +285,16 @@ public class SecurityDataProcessor {
rec.set(KeyRecord.ATTR_REALM, realm);
}
+ try {
+ rec.setWrappingParams(storageUnit.getWrappingParams());
+ } catch (Exception e) {
+ kra.log(ILogger.LL_FAILURE,
+ "Failed to store wrapping parameters: " + e);
+ auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId,
+ clientKeyId, null, "Failed to store wrapping parameters");
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"), e);
+ }
+
CMS.debug("KRA adding Security Data key record " + serialNo);
keyRepository.addKeyRecord(rec);
@@ -307,11 +312,7 @@ public class SecurityDataProcessor {
CMS.debug("SecurityDataService.recover(): start");
- //Pave the way for allowing generated IV vector
- byte iv[]= null;
- byte iv_default[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
byte iv_in[] = null;
-
IConfigStore config = null;
try {
@@ -360,18 +361,6 @@ public class SecurityDataProcessor {
return false;
}
- //Create the return IV if needed.
- iv = new byte[8];
-
- try {
- Random rnd = new Random();
- rnd.nextBytes(iv);
- } catch (Exception e) {
- iv = iv_default;
- }
-
- String ivStr = Utils.base64encode(iv);
-
KeyRecord keyRecord = (KeyRecord) keyRepository.readKeyRecord(serialno);
String dataType = (String) keyRecord.get(IKeyRecord.ATTR_DATA_TYPE);
@@ -406,7 +395,11 @@ public class SecurityDataProcessor {
byte[] privateKeyData = keyRecord.getPrivateKeyData();
PublicKey publicKey = X509Key.parsePublicKey(new DerValue(publicKeyData));
- privateKey = storageUnit.unwrap_temp(privateKeyData, publicKey);
+ privateKey = storageUnit.unwrap(
+ privateKeyData,
+ publicKey,
+ true,
+ keyRecord.getWrappingParams(storageUnit.getOldWrappingParams()));
}
} catch (Exception e) {
@@ -419,10 +412,32 @@ public class SecurityDataProcessor {
CryptoToken ct = transportUnit.getToken();
- WrappingParams wrapParams = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
+ String payloadEncryptOID = (String) params.get(IRequest.SECURITY_DATA_PL_ENCRYPTION_OID);
+ String payloadWrapName = (String) params.get(IRequest.SECURITY_DATA_PL_WRAPPING_NAME);
+ String transportKeyAlgo = transportUnit.getCertificate().getPublicKey().getAlgorithm();
+
+ byte[] iv = generate_iv();
+ String ivStr = Utils.base64encode(iv);
+
+ WrappingParams wrapParams = null;
+ if (payloadEncryptOID == null) {
+ wrapParams = transportUnit.getOldWrappingParams();
+ wrapParams.setPayloadEncryptionIV(new IVParameterSpec(iv));
+ wrapParams.setPayloadWrappingIV(new IVParameterSpec(iv));
+ } else {
+ try {
+ wrapParams = new WrappingParams(
+ payloadEncryptOID,
+ payloadWrapName,
+ transportKeyAlgo,
+ new IVParameterSpec(iv),
+ null);
+ } catch (Exception e) {
+ auditRecoveryRequestProcessed(auditSubjectID, ILogger.FAILURE, requestID, serialno.toString(),
+ "Cannot generate wrapping params");
+ throw new EBaseException("Cannot generate wrapping params: " + e, e);
+ }
+ }
byte[] key_data = null;
String pbeWrappedData = null;
@@ -435,8 +450,14 @@ public class SecurityDataProcessor {
try {
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.DECRYPT, wrapParams);
- unwrappedPass = decryptWithSymmetricKey(ct, unwrappedSess, wrappedPassPhrase,
- new IVParameterSpec(iv_in), wrapParams);
+
+ unwrappedPass = CryptoUtil.decryptUsingSymmetricKey(
+ ct,
+ wrapParams.getPayloadEncryptionIV(),
+ wrappedPassPhrase,
+ unwrappedSess,
+ wrapParams.getPayloadEncryptionAlgorithm());
+
String passStr = new String(unwrappedPass, "UTF-8");
pass = new Password(passStr.toCharArray());
passStr = null;
@@ -499,13 +520,21 @@ public class SecurityDataProcessor {
CMS.debug("SecurityDataProcessor.recover(): encrypt symmetric key with session key as per allowEncDecrypt_recovery: true.");
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.ENCRYPT, wrapParams);
- key_data = encryptWithSymmetricKey(ct, unwrappedSess, unwrappedSecData,
- new IVParameterSpec(iv), wrapParams);
-
+ key_data = CryptoUtil.encryptUsingSymmetricKey(
+ ct,
+ unwrappedSess,
+ unwrappedSecData,
+ wrapParams.getPayloadEncryptionAlgorithm(),
+ wrapParams.getPayloadEncryptionIV());
} else {
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.WRAP, wrapParams);
- key_data = wrapWithSymmetricKey(ct, unwrappedSess, symKey, new IVParameterSpec(iv), wrapParams);
+ key_data = CryptoUtil.wrapUsingSymmetricKey(
+ ct,
+ unwrappedSess,
+ symKey,
+ wrapParams.getPayloadWrappingIV(),
+ wrapParams.getPayloadWrapAlgorithm());
}
} catch (Exception e) {
@@ -520,8 +549,12 @@ public class SecurityDataProcessor {
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.ENCRYPT, wrapParams);
- key_data = encryptWithSymmetricKey(ct, unwrappedSess, unwrappedSecData,
- new IVParameterSpec(iv), wrapParams);
+ key_data = CryptoUtil.encryptUsingSymmetricKey(
+ ct,
+ unwrappedSess,
+ unwrappedSecData,
+ wrapParams.getPayloadEncryptionAlgorithm(),
+ wrapParams.getPayloadEncryptionIV());
} catch (Exception e) {
auditRecoveryRequestProcessed(auditSubjectID, ILogger.FAILURE, requestID,
serialno.toString(), "Cannot encrypt passphrase");
@@ -535,12 +568,23 @@ public class SecurityDataProcessor {
CMS.debug("SecurityDataProcessor.recover(): encrypt symmetric key.");
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.ENCRYPT, wrapParams);
- key_data = encryptWithSymmetricKey(ct, unwrappedSess, unwrappedSecData,
- new IVParameterSpec(iv), wrapParams);
+
+ key_data = CryptoUtil.encryptUsingSymmetricKey(
+ ct,
+ unwrappedSess,
+ unwrappedSecData,
+ wrapParams.getPayloadEncryptionAlgorithm(),
+ wrapParams.getPayloadEncryptionIV());
+
} else {
unwrappedSess = transportUnit.unwrap_session_key(ct, wrappedSessKey,
SymmetricKey.Usage.WRAP, wrapParams);
- key_data = wrapWithSymmetricKey(ct, unwrappedSess, privateKey, new IVParameterSpec(iv), wrapParams);
+ key_data = CryptoUtil.wrapUsingSymmetricKey(
+ ct,
+ unwrappedSess,
+ privateKey,
+ wrapParams.getPayloadWrappingIV(),
+ wrapParams.getPayloadWrapAlgorithm());
}
} catch (Exception e) {
@@ -566,42 +610,20 @@ public class SecurityDataProcessor {
return false; //return true ? TODO
}
- private byte[] decryptWithSymmetricKey(CryptoToken ct, SymmetricKey wrappingKey, byte[] data, IVParameterSpec iv,
- WrappingParams params) throws Exception {
- Cipher decryptor = ct.getCipherContext(params.getPayloadEncryptionAlgorithm());
- if (decryptor == null)
- throw new IOException("Failed to create decryptor");
- decryptor.initDecrypt(wrappingKey, iv);
- return decryptor.doFinal(data);
- }
-
- private byte[] wrapWithSymmetricKey(CryptoToken ct, SymmetricKey wrappingKey, SymmetricKey data,
- IVParameterSpec iv, WrappingParams params) throws Exception {
- KeyWrapper wrapper = ct.getKeyWrapper(params.getPayloadWrapAlgorithm());
- if (wrapper == null)
- throw new IOException("Failed to create key wrapper");
- wrapper.initWrap(wrappingKey, iv);
- return wrapper.wrap(data);
- }
-
- private byte[] wrapWithSymmetricKey(CryptoToken ct, SymmetricKey wrappingKey, PrivateKey data,
- IVParameterSpec iv, WrappingParams params) throws Exception {
- KeyWrapper wrapper = ct.getKeyWrapper(params.getPayloadWrapAlgorithm());
- if (wrapper == null)
- throw new IOException("Failed to create key wrapper");
- wrapper.initWrap(wrappingKey, iv);
- return wrapper.wrap(data);
- }
-
- private byte[] encryptWithSymmetricKey(CryptoToken ct, SymmetricKey wrappingKey, byte[] data, IVParameterSpec iv,
- WrappingParams params) throws Exception {
- Cipher encryptor = ct.getCipherContext(params.getPayloadEncryptionAlgorithm());
-
- if (encryptor == null)
- throw new IOException("Failed to create cipher");
+ private byte[] generate_iv() {
+ //TODO(alee) Fix this -- this will only work for DES3. Needs to be based on algorithm.
+ // Is there a function in JSS for this? Also note that the iv generated here is actually
+ // used for both encryption and wrapping algorithms above.
+ byte[] iv = new byte[8];
+ byte iv_default[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
- encryptor.initEncrypt(wrappingKey, iv);
- return encryptor.doFinal(data);
+ try {
+ Random rnd = new Random();
+ rnd.nextBytes(iv);
+ } catch (Exception e) {
+ iv = iv_default;
+ }
+ return iv;
}
public SymmetricKey recoverSymKey(KeyRecord keyRecord)
@@ -612,7 +634,8 @@ public class SecurityDataProcessor {
storageUnit.unwrap(
keyRecord.getPrivateKeyData(),
KeyRequestService.SYMKEY_TYPES.get(keyRecord.getAlgorithm()),
- keyRecord.getKeySize());
+ keyRecord.getKeySize(),
+ keyRecord.getWrappingParams(storageUnit.getOldWrappingParams()));
return symKey;
} catch (Exception e) {
throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1",
@@ -623,7 +646,9 @@ public class SecurityDataProcessor {
public byte[] recoverSecurityData(KeyRecord keyRecord)
throws EBaseException {
try {
- return storageUnit.decryptInternalPrivate(keyRecord.getPrivateKeyData());
+ return storageUnit.decryptInternalPrivate(
+ keyRecord.getPrivateKeyData(),
+ keyRecord.getWrappingParams(storageUnit.getOldWrappingParams()));
} catch (Exception e) {
CMS.debug("Failed to recover security data: " + e);
throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1",
@@ -637,9 +662,7 @@ public class SecurityDataProcessor {
int iterationCount,
KeyGenerator.CharToByteConverter charToByteConverter,
SymmetricKey symKey, PrivateKey privateKey, CryptoToken token)
- throws CryptoManager.NotInitializedException, NoSuchAlgorithmException,
- InvalidKeyException, InvalidAlgorithmParameterException, TokenException,
- CharConversionException {
+ throws Exception {
if (keyGenAlg == null) {
throw new NoSuchAlgorithmException("Key generation algorithm is NULL");
@@ -665,14 +688,13 @@ public class SecurityDataProcessor {
kg.generatePBE_IV());
}
- KeyWrapper wrapper = token.getKeyWrapper(
- KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper.initWrap(key, params);
byte[] encrypted = null;
if (symKey != null) {
- encrypted = wrapper.wrap(symKey);
+ encrypted = CryptoUtil.wrapUsingSymmetricKey(token, key, symKey, (IVParameterSpec) params,
+ KeyWrapAlgorithm.DES3_CBC_PAD);
} else if (privateKey != null) {
- encrypted = wrapper.wrap(privateKey);
+ encrypted = CryptoUtil.wrapUsingSymmetricKey(token, key, privateKey, (IVParameterSpec) params,
+ KeyWrapAlgorithm.DES3_CBC_PAD);
}
if (encrypted == null) {
//TODO - think about the exception to be thrown
diff --git a/base/kra/src/com/netscape/kra/StorageKeyUnit.java b/base/kra/src/com/netscape/kra/StorageKeyUnit.java
index 83f3e2a79..8b4c801fb 100644
--- a/base/kra/src/com/netscape/kra/StorageKeyUnit.java
+++ b/base/kra/src/com/netscape/kra/StorageKeyUnit.java
@@ -36,6 +36,7 @@ import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IllegalBlockSizeException;
+import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.KeyWrapper;
@@ -60,9 +61,14 @@ import com.netscape.certsrv.kra.IShare;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.security.Credential;
import com.netscape.certsrv.security.IStorageKeyUnit;
+import com.netscape.certsrv.security.WrappingParams;
import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.util.Utils;
+import netscape.security.util.DerInputStream;
+import netscape.security.util.DerOutputStream;
+import netscape.security.util.DerValue;
+
/**
* A class represents a storage key unit. Currently, this
* is implemented with cryptix, the final implementation
@@ -99,6 +105,7 @@ public class StorageKeyUnit extends EncryptionUnit implements
public static final String PROP_KEYDB = "keydb";
public static final String PROP_CERTDB = "certdb";
public static final String PROP_MN = "mn";
+ public static final String PROP_OLD_WRAPPING = "useOldWrapping";
/**
* Constructs this token.
@@ -123,6 +130,17 @@ public class StorageKeyUnit extends EncryptionUnit implements
throw new EBaseException(CMS.getUserMessage("CMS_INVALID_OPERATION"));
}
+ public WrappingParams getWrappingParams() throws EBaseException {
+ if (mConfig.getBoolean(PROP_OLD_WRAPPING, false)) {
+ return this.getOldWrappingParams();
+ }
+
+ return new WrappingParams(
+ SymmetricKey.AES, KeyGenAlgorithm.AES, 256,
+ KeyWrapAlgorithm.RSA, EncryptionAlgorithm.AES_256_CBC_PAD,
+ KeyWrapAlgorithm.AES_KEY_WRAP_PAD, IV2, null);
+ }
+
/**
* return true if byte arrays are equal, false otherwise
*/
@@ -448,30 +466,16 @@ public class StorageKeyUnit extends EncryptionUnit implements
try {
// move public & private to config/storage.dat
// delete private key
- KeyWrapper wrapper = token.getKeyWrapper(
+ return CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sk,
+ pri,
+ IV,
KeyWrapAlgorithm.DES3_CBC_PAD);
-
- // next to randomly generate a symmetric
- // password
-
- wrapper.initWrap(sk, IV);
- return wrapper.wrap(pri);
- } catch (TokenException e) {
- throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
- "wrapStorageKey:" +
- e.toString()));
- } catch (NoSuchAlgorithmException e) {
- throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
- "wrapStorageKey:" +
- e.toString()));
- } catch (InvalidKeyException e) {
- throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
- "wrapStorageKey:" +
- e.toString()));
- } catch (InvalidAlgorithmParameterException e) {
+ } catch (Exception e) {
throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
"wrapStorageKey:" +
- e.toString()));
+ e.toString()), e);
}
}
@@ -1001,4 +1005,212 @@ public class StorageKeyUnit extends EncryptionUnit implements
return true;
}
+ /****************************************************************************************
+ * Methods to encrypt and store secrets in the database
+ ***************************************************************************************/
+
+ public byte[] encryptInternalPrivate(byte priKey[]) throws Exception {
+ try (DerOutputStream out = new DerOutputStream()) {
+ CMS.debug("EncryptionUnit.encryptInternalPrivate");
+ CryptoToken internalToken = getInternalToken();
+
+ WrappingParams params = getWrappingParams();
+
+ // (1) generate session key
+ SymmetricKey sk = CryptoUtil.generateKey(
+ internalToken,
+ params.getSkKeyGenAlgorithm(),
+ params.getSkLength(),
+ null,
+ false);
+
+ // (2) wrap private key with session key
+ byte[] pri = CryptoUtil.encryptUsingSymmetricKey(
+ internalToken,
+ sk,
+ priKey,
+ params.getPayloadEncryptionAlgorithm(),
+ params.getPayloadEncryptionIV());
+
+ // (3) wrap session with storage public
+ byte[] session = CryptoUtil.wrapUsingPublicKey(
+ internalToken,
+ getPublicKey(),
+ sk,
+ params.getSkWrapAlgorithm());
+
+ // use MY own structure for now:
+ // SEQUENCE {
+ // encryptedSession OCTET STRING,
+ // encryptedPrivate OCTET STRING
+ // }
+
+ DerOutputStream tmp = new DerOutputStream();
+
+ tmp.putOctetString(session);
+ tmp.putOctetString(pri);
+ out.write(DerValue.tag_Sequence, tmp);
+
+ return out.toByteArray();
+ }
+ }
+
+ public byte[] wrap(PrivateKey privKey) throws Exception {
+ return _wrap(privKey,null);
+ }
+
+ public byte[] wrap(SymmetricKey symmKey) throws Exception {
+ return _wrap(null,symmKey);
+ }
+
+ /***
+ * Internal wrap, accounts for either private or symmetric key
+ */
+ private byte[] _wrap(PrivateKey priKey, SymmetricKey symmKey) throws Exception {
+ try (DerOutputStream out = new DerOutputStream()) {
+ if ((priKey == null && symmKey == null) || (priKey != null && symmKey != null)) {
+ return null;
+ }
+ CMS.debug("EncryptionUnit.wrap interal.");
+ WrappingParams params = getWrappingParams();
+ CryptoToken token = getToken();
+
+ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[2];
+ usages[0] = SymmetricKey.Usage.WRAP;
+ usages[1] = SymmetricKey.Usage.UNWRAP;
+
+ // (1) generate session key
+ SymmetricKey sk = CryptoUtil.generateKey(
+ token,
+ params.getSkKeyGenAlgorithm(),
+ params.getSkLength(),
+ usages,
+ true);
+
+ // (2) wrap private key with session key
+ // KeyWrapper wrapper = internalToken.getKeyWrapper(
+
+ byte pri[] = null;
+
+ if (priKey != null) {
+ pri = CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sk,
+ priKey,
+ params.getPayloadWrappingIV(),
+ params.getPayloadWrapAlgorithm());
+ } else if (symmKey != null) {
+ pri = CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sk,
+ symmKey,
+ params.getPayloadWrappingIV(),
+ params.getPayloadWrapAlgorithm());
+ }
+
+ CMS.debug("EncryptionUnit:wrap() privKey wrapped");
+
+ byte[] session = CryptoUtil.wrapUsingPublicKey(
+ token,
+ getPublicKey(),
+ sk,
+ params.getSkWrapAlgorithm());
+ CMS.debug("EncryptionUnit:wrap() session key wrapped");
+
+ // use MY own structure for now:
+ // SEQUENCE {
+ // encryptedSession OCTET STRING,
+ // encryptedPrivate OCTET STRING
+ // }
+
+ DerOutputStream tmp = new DerOutputStream();
+
+ tmp.putOctetString(session);
+ tmp.putOctetString(pri);
+ out.write(DerValue.tag_Sequence, tmp);
+
+ return out.toByteArray();
+ }
+ }
+
+ /****************************************************************************************
+ * Methods to decrypt and retrieve secrets from the database
+ ***************************************************************************************/
+
+ public byte[] decryptInternalPrivate(byte wrappedKeyData[], WrappingParams params)
+ throws Exception {
+ CMS.debug("EncryptionUnit.decryptInternalPrivate");
+ DerValue val = new DerValue(wrappedKeyData);
+ // val.tag == DerValue.tag_Sequence
+ DerInputStream in = val.data;
+ DerValue dSession = in.getDerValue();
+ byte session[] = dSession.getOctetString();
+ DerValue dPri = in.getDerValue();
+ byte pri[] = dPri.getOctetString();
+
+ CryptoToken token = getToken();
+
+ // (1) unwrap the session key
+ CMS.debug("decryptInternalPrivate(): getting key wrapper on slot:" + token.getName());
+ SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.DECRYPT, params);
+
+ // (2) decrypt the private key
+ return CryptoUtil.decryptUsingSymmetricKey(
+ token,
+ params.getPayloadEncryptionIV(),
+ pri,
+ sk,
+ params.getPayloadEncryptionAlgorithm());
+ }
+
+ public SymmetricKey unwrap(byte wrappedKeyData[], SymmetricKey.Type algorithm, int keySize,
+ WrappingParams params) throws Exception {
+ DerValue val = new DerValue(wrappedKeyData);
+ // val.tag == DerValue.tag_Sequence
+ DerInputStream in = val.data;
+ DerValue dSession = in.getDerValue();
+ byte session[] = dSession.getOctetString();
+ DerValue dPri = in.getDerValue();
+ byte pri[] = dPri.getOctetString();
+
+ CryptoToken token = getToken();
+ // (1) unwrap the session key
+ SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.UNWRAP, params);
+
+ // (2) unwrap the session-wrapped-symmetric key
+ return CryptoUtil.unwrap(
+ token,
+ algorithm,
+ keySize,
+ SymmetricKey.Usage.UNWRAP,
+ sk,
+ pri,
+ params.getPayloadWrapAlgorithm(),
+ params.getPayloadWrappingIV());
+ }
+
+ public PrivateKey unwrap(byte wrappedKeyData[], PublicKey pubKey, boolean temporary, WrappingParams params)
+ throws Exception {
+ DerValue val = new DerValue(wrappedKeyData);
+ // val.tag == DerValue.tag_Sequence
+ DerInputStream in = val.data;
+ DerValue dSession = in.getDerValue();
+ byte session[] = dSession.getOctetString();
+ DerValue dPri = in.getDerValue();
+ byte pri[] = dPri.getOctetString();
+
+ CryptoToken token = getToken();
+ // (1) unwrap the session key
+ SymmetricKey sk = unwrap_session_key(token, session, SymmetricKey.Usage.UNWRAP, params);
+
+ // (2) unwrap the private key
+ return CryptoUtil.unwrap(
+ token,
+ pubKey,
+ temporary,
+ sk,
+ pri,
+ params.getPayloadWrapAlgorithm(),
+ params.getPayloadWrappingIV());
+ }
}
diff --git a/base/kra/src/com/netscape/kra/SymKeyGenService.java b/base/kra/src/com/netscape/kra/SymKeyGenService.java
index 7d42cb45b..94301b662 100644
--- a/base/kra/src/com/netscape/kra/SymKeyGenService.java
+++ b/base/kra/src/com/netscape/kra/SymKeyGenService.java
@@ -17,10 +17,7 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.kra;
-import java.io.CharConversionException;
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -28,9 +25,7 @@ import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
-import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.SymmetricKey;
-import org.mozilla.jss.crypto.TokenException;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
@@ -46,6 +41,7 @@ import com.netscape.certsrv.request.RequestId;
import com.netscape.certsrv.security.IStorageKeyUnit;
import com.netscape.cms.servlet.key.KeyRequestDAO;
import com.netscape.cmscore.dbs.KeyRecord;
+import com.netscape.cmsutil.crypto.CryptoUtil;
/**
* This implementation implements SecurityData archival operations.
@@ -154,21 +150,13 @@ public class SymKeyGenService implements IService {
SymmetricKey sk = null;
try {
- KeyGenerator kg = token.getKeyGenerator(kgAlg);
- kg.setKeyUsages(keyUsages);
- kg.temporaryKeys(true);
- if (kgAlg == KeyGenAlgorithm.AES || kgAlg == KeyGenAlgorithm.RC4
- || kgAlg == KeyGenAlgorithm.RC2) {
- kg.initialize(keySize);
- }
- sk = kg.generate();
+ sk = CryptoUtil.generateKey(token, kgAlg, keySize, keyUsages, true);
CMS.debug("SymKeyGenService:wrap() session key generated on slot: " + token.getName());
- } catch (TokenException | IllegalStateException | CharConversionException | NoSuchAlgorithmException
- | InvalidAlgorithmParameterException e) {
+ } catch (Exception e) {
CMS.debugStackTrace();
auditSymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(),
clientKeyId, null, "Failed to generate symmetric key");
- throw new EBaseException("Errors in generating symmetric key: " + e);
+ throw new EBaseException("Errors in generating symmetric key: " + e, e);
}
byte[] publicKey = null;
@@ -224,6 +212,16 @@ public class SymKeyGenService implements IService {
rec.set(KeyRecord.ATTR_REALM, realm);
}
+ try {
+ rec.setWrappingParams(mStorageUnit.getWrappingParams());
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ "Failed to store wrapping parameters: " + e);
+ auditSymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(),
+ clientKeyId, null, "Failed to store wraping parameters.");
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"), e);
+ }
+
CMS.debug("KRA adding Security Data key record " + serialNo);
storage.addKeyRecord(rec);
diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
index 5ad8044d7..8abf92046 100644
--- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
+++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java
@@ -27,13 +27,11 @@ import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Hashtable;
-import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.PrivateKey.Type;
import org.mozilla.jss.crypto.SymmetricKey;
@@ -54,6 +52,7 @@ import com.netscape.certsrv.security.IStorageKeyUnit;
import com.netscape.certsrv.security.ITransportKeyUnit;
import com.netscape.certsrv.security.WrappingParams;
import com.netscape.cmscore.dbs.KeyRecord;
+import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.util.Cert;
import netscape.security.util.BigInt;
@@ -170,23 +169,6 @@ public class TokenKeyRecoveryService implements IService {
}
}
- // this encrypts bytes with a symmetric key
- public byte[] encryptIt(byte[] toBeEncrypted, SymmetricKey symKey, CryptoToken token,
- IVParameterSpec IV) {
- try {
- Cipher cipher = token.getCipherContext(
- EncryptionAlgorithm.DES3_CBC_PAD);
-
- cipher.initEncrypt(symKey, IV);
- byte pri[] = cipher.doFinal(toBeEncrypted);
- return pri;
- } catch (Exception e) {
- CMS.debug("initEncrypt() threw exception: " + e.toString());
- return null;
- }
-
- }
-
/**
* Processes a recovery request. The method reads
* the key record from the database, and tries to recover the
@@ -273,18 +255,17 @@ public class TokenKeyRecoveryService implements IService {
(wrapped_des_key.length > 0)) {
WrappingParams wrapParams = new WrappingParams(
- SymmetricKey.DES3, null, KeyGenAlgorithm.DES3, 0,
+ SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0,
KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD,
- KeyWrapAlgorithm.DES3_CBC_PAD);
+ KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionUnit.IV, EncryptionUnit.IV);
// unwrap the des key
- sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams);
-
- if (sk == null) {
+ try {
+ sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams);
+ CMS.debug("TokenKeyRecoveryService: received des key");
+ } catch (Exception e) {
CMS.debug("TokenKeyRecoveryService: no des key");
request.setExtData(IRequest.RESULT, Integer.valueOf(4));
- } else {
- CMS.debug("TokenKeyRecoveryService: received des key");
}
} else {
CMS.debug("TokenKeyRecoveryService: not receive des key");
@@ -364,8 +345,6 @@ public class TokenKeyRecoveryService implements IService {
CMS.debug("TokenKeyRecoveryService: got token slot:" + token.getName());
IVParameterSpec algParam = new IVParameterSpec(iv);
- Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
-
KeyRecord keyRecord = null;
CMS.debug("KRA reading key record");
try {
@@ -512,8 +491,12 @@ public class TokenKeyRecoveryService implements IService {
}
//encrypt and put in private key
- cipher.initEncrypt(sk, algParam);
- wrapped = cipher.doFinal(privateKeyData);
+ wrapped = CryptoUtil.encryptUsingSymmetricKey(
+ token,
+ sk,
+ privateKeyData,
+ EncryptionAlgorithm.DES3_CBC_PAD,
+ algParam);
} else { //allowEncDecrypt_recovery == false
PrivateKey privKey = recoverKey(params, keyRecord, allowEncDecrypt_recovery);
if (privKey == null) {
@@ -531,11 +514,14 @@ public class TokenKeyRecoveryService implements IService {
}
CMS.debug("TokenKeyRecoveryService: about to wrap...");
- KeyWrapper wrapper = token.getKeyWrapper(
- KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper.initWrap(sk, algParam);
- wrapped = wrapper.wrap(privKey);
+ wrapped = CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sk,
+ privKey,
+ algParam,
+ KeyWrapAlgorithm.DES3_CBC_PAD);
+
iv_s = /*base64Encode(iv);*/com.netscape.cmsutil.util.Utils.SpecialEncode(iv);
request.setExtData("iv_s", iv_s);
}
@@ -676,31 +662,21 @@ public class TokenKeyRecoveryService implements IService {
}
try {
- /* wrapped retrieve session key and private key */
- DerValue val = new DerValue(keyRecord.getPrivateKeyData());
- DerInputStream in = val.data;
- DerValue dSession = in.getDerValue();
- byte session[] = dSession.getOctetString();
- DerValue dPri = in.getDerValue();
- byte pri[] = dPri.getOctetString();
-
- byte publicKeyData[] = keyRecord.getPublicKeyData();
PublicKey pubkey = null;
try {
- pubkey = X509Key.parsePublicKey (new DerValue(publicKeyData));
+ pubkey = X509Key.parsePublicKey (new DerValue(keyRecord.getPublicKeyData()));
} catch (Exception e) {
CMS.debug("TokenKeyRecoverService: after parsePublicKey:"+e.toString());
throw new EKRAException(CMS.getUserMessage("CMS_KRA_RECOVERY_FAILED_1", "public key parsing failure"));
}
- byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
+
PrivateKey privKey = null;
try {
privKey = mStorageUnit.unwrap(
- session,
- keyRecord.getAlgorithm(),
- iv,
- pri,
- pubkey);
+ keyRecord.getPrivateKeyData(),
+ pubkey,
+ false,
+ keyRecord.getWrappingParams(mStorageUnit.getOldWrappingParams()));
} catch (Exception e) {
CMS.debug("TokenKeyRecoveryService: recoverKey() - recovery failure");
throw new EKRAException(
@@ -728,7 +704,9 @@ public class TokenKeyRecoveryService implements IService {
mStorageUnit.login(creds);
*/
try {
- return mStorageUnit.decryptInternalPrivate(keyRecord.getPrivateKeyData());
+ return mStorageUnit.decryptInternalPrivate(
+ keyRecord.getPrivateKeyData(),
+ keyRecord.getWrappingParams(mStorageUnit.getOldWrappingParams()));
/* mStorageUnit.logout();*/
} catch (Exception e){
mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_PRIVATE_KEY_NOT_FOUND"));
diff --git a/base/kra/src/com/netscape/kra/TransportKeyUnit.java b/base/kra/src/com/netscape/kra/TransportKeyUnit.java
index 2efdac7ad..672cb857a 100644
--- a/base/kra/src/com/netscape/kra/TransportKeyUnit.java
+++ b/base/kra/src/com/netscape/kra/TransportKeyUnit.java
@@ -21,10 +21,12 @@ import java.security.PublicKey;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.ObjectNotFoundException;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.Signature;
import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.TokenException;
import com.netscape.certsrv.apps.CMS;
@@ -32,6 +34,8 @@ import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
import com.netscape.certsrv.security.ITransportKeyUnit;
+import com.netscape.certsrv.security.WrappingParams;
+import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.util.Cert;
/**
@@ -110,6 +114,10 @@ public class TransportKeyUnit extends EncryptionUnit implements
}
}
+ public WrappingParams getWrappingParams() {
+ return getOldWrappingParams();
+ }
+
public CryptoToken getInternalToken() {
try {
return CryptoManager.getInstance().getInternalKeyStorageToken();
@@ -253,4 +261,122 @@ public class TransportKeyUnit extends EncryptionUnit implements
throws EBaseException {
// XXX
}
+
+ public SymmetricKey unwrap_sym(byte encSymmKey[], WrappingParams params) throws Exception {
+ return unwrap_session_key(getToken(), encSymmKey, SymmetricKey.Usage.WRAP, params);
+ }
+
+ /**
+ * Decrypts the user private key. This is called on the transport unit.
+ */
+ public byte[] decryptExternalPrivate(byte encSymmKey[],
+ String symmAlgOID, byte symmAlgParams[], byte encValue[],
+ org.mozilla.jss.crypto.X509Certificate transCert)
+ throws Exception {
+
+ CMS.debug("EncryptionUnit.decryptExternalPrivate");
+
+ if (transCert == null) {
+ transCert = mCert;
+ }
+ CryptoToken token = getToken(transCert);
+ PrivateKey wrappingKey = getPrivateKey(transCert);
+ String priKeyAlgo = wrappingKey.getAlgorithm();
+ WrappingParams params = new WrappingParams(
+ symmAlgOID,
+ null,
+ priKeyAlgo,
+ new IVParameterSpec(symmAlgParams),
+ null);
+
+ SymmetricKey sk = CryptoUtil.unwrap(
+ token,
+ params.getSkType(),
+ 0,
+ SymmetricKey.Usage.DECRYPT,
+ wrappingKey,
+ encSymmKey,
+ params.getSkWrapAlgorithm());
+
+ return CryptoUtil.decryptUsingSymmetricKey(
+ token,
+ params.getPayloadEncryptionIV(),
+ encValue,
+ sk,
+ params.getPayloadEncryptionAlgorithm());
+ }
+
+ /**
+ * External unwrapping. Unwraps the symmetric key using
+ * the transport private key.
+ */
+ public SymmetricKey unwrap_symmetric(byte encSymmKey[],
+ String symmAlgOID, byte symmAlgParams[],
+ byte encValue[], SymmetricKey.Type algorithm, int strength)
+ throws Exception {
+
+ CryptoToken token = getToken();
+ PrivateKey wrappingKey = getPrivateKey(mCert);
+ String priKeyAlgo = wrappingKey.getAlgorithm();
+ WrappingParams params = new WrappingParams(
+ symmAlgOID,
+ null,
+ priKeyAlgo,
+ new IVParameterSpec(symmAlgParams),
+ null);
+
+ // (1) unwrap the session key
+ SymmetricKey sk = unwrap_session_key(token, encSymmKey, SymmetricKey.Usage.UNWRAP, params);
+
+ // (2) unwrap the session-wrapped-symmetric-key
+ return CryptoUtil.unwrap(
+ token,
+ algorithm,
+ strength,
+ SymmetricKey.Usage.DECRYPT,
+ sk,
+ encValue,
+ params.getPayloadWrapAlgorithm(),
+ params.getPayloadEncryptionIV());
+ }
+
+ /**
+ * External unwrapping. Unwraps the data using
+ * the transport private key.
+ */
+ public PrivateKey unwrap(byte encSymmKey[],
+ String symmAlgOID, byte symmAlgParams[],
+ byte encValue[], PublicKey pubKey,
+ org.mozilla.jss.crypto.X509Certificate transCert)
+ throws Exception {
+ CryptoToken token = getToken(transCert);
+ PrivateKey wrappingKey = getPrivateKey(transCert);
+ String priKeyAlgo = wrappingKey.getAlgorithm();
+ WrappingParams params = new WrappingParams(
+ symmAlgOID,
+ null,
+ priKeyAlgo,
+ new IVParameterSpec(symmAlgParams),
+ new IVParameterSpec(symmAlgParams));
+
+ // (1) unwrap the session key
+ SymmetricKey sk = CryptoUtil.unwrap(
+ token,
+ params.getSkType(),
+ 0,
+ SymmetricKey.Usage.UNWRAP,
+ wrappingKey,
+ encSymmKey,
+ params.getSkWrapAlgorithm());
+
+ // (2) unwrap the session-wrapped-private key
+ return CryptoUtil.unwrap(
+ token,
+ pubKey,
+ true,
+ sk,
+ encValue,
+ params.getPayloadWrapAlgorithm(),
+ params.getPayloadWrappingIV());
+ }
}
diff --git a/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java
index c65dd3971..e7f50fbc2 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/AgentCertAuthentication.java
@@ -22,8 +22,6 @@ import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
-import netscape.security.x509.X509CertImpl;
-
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.AuthToken;
import com.netscape.certsrv.authentication.EInvalidCredentials;
@@ -46,6 +44,8 @@ import com.netscape.certsrv.usrgrp.ICertUserLocator;
import com.netscape.certsrv.usrgrp.IUGSubsystem;
import com.netscape.certsrv.usrgrp.IUser;
+import netscape.security.x509.X509CertImpl;
+
/**
* Certificate server agent authentication.
* Maps a SSL client authenticate certificate to a user (agent) entry in the
@@ -196,7 +196,7 @@ public class AgentCertAuthentication implements IAuthManager,
try {
user = mCULocator.locateUser(certs);
} catch (EUsrGrpException e) {
- throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"), e);
} catch (netscape.ldap.LDAPException e) {
throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
e.toString()));
diff --git a/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java
index 2bec1b68d..a9b0ccc77 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/SSLclientCertAuthentication.java
@@ -24,9 +24,6 @@ import java.util.Enumeration;
import java.util.Locale;
import java.util.StringTokenizer;
-import netscape.security.x509.BasicConstraintsExtension;
-import netscape.security.x509.X509CertImpl;
-
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.AuthToken;
import com.netscape.certsrv.authentication.EInvalidCredentials;
@@ -45,6 +42,9 @@ import com.netscape.certsrv.property.IDescriptor;
import com.netscape.certsrv.request.IRequest;
import com.netscape.certsrv.usrgrp.Certificates;
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.X509CertImpl;
+
/**
* Certificate server SSL client authentication.
*
@@ -189,7 +189,7 @@ public class SSLclientCertAuthentication implements IAuthManager,
} catch (Exception e) {
CMS.debug("SSLclientCertAuthentication: authenticate: exception:" +
e.toString());
- throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"), e);
}
}
}
@@ -199,7 +199,7 @@ public class SSLclientCertAuthentication implements IAuthManager,
}
} catch (CertificateException e) {
CMS.debug(e.toString());
- throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"), e);
}
// check if certificate(s) is revoked
diff --git a/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java b/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java
index 7a0784c53..48a23536a 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/SharedSecret.java
@@ -35,4 +35,8 @@ public class SharedSecret implements ISharedToken {
public String getSharedToken(BigInteger serial) {
return "testing";
}
+
+ public String getSharedToken(String identification) {
+ return "testing";
+ }
}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index 0f3153d3d..ed2423ff1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -845,11 +845,7 @@ public class ConfigurationUtils {
return false;
}
- public static void restoreCertsFromP12(String p12File, String p12Pass) throws EPropertyNotFound, EBaseException,
- InvalidKeyException, CertificateException, NoSuchAlgorithmException,
- InvalidAlgorithmParameterException, IllegalStateException, TokenException, IllegalBlockSizeException,
- BadPaddingException, NotInitializedException, NicknameConflictException, UserCertConflictException,
- NoSuchItemOnTokenException, InvalidBERException, IOException {
+ public static void restoreCertsFromP12(String p12File, String p12Pass) throws Exception {
// TODO: The PKCS #12 file is already imported in security_database.py.
// This method should be removed.
@@ -1018,11 +1014,7 @@ public class ConfigurationUtils {
public static void importKeyCert(
Vector<Vector<Object>> pkeyinfo_collection,
Vector<Vector<Object>> cert_collection
- ) throws IOException, CertificateException, TokenException,
- NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException,
- IllegalStateException,
- IllegalBlockSizeException, BadPaddingException, NotInitializedException, NicknameConflictException,
- UserCertConflictException, NoSuchItemOnTokenException, EPropertyNotFound, EBaseException {
+ ) throws Exception {
CMS.debug("ConfigurationUtils.importKeyCert()");
CryptoManager cm = CryptoManager.getInstance();
@@ -1072,13 +1064,10 @@ public class ConfigurationUtils {
}
// encrypt private key
- KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
- SymmetricKey sk = kg.generate();
+ SymmetricKey sk = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, true);
byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
IVParameterSpec param = new IVParameterSpec(iv);
- Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
- c.initEncrypt(sk, param);
- byte[] encpkey = c.doFinal(pkey);
+ byte[] encpkey = CryptoUtil.encryptUsingSymmetricKey(token, sk, pkey, EncryptionAlgorithm.DES3_CBC_PAD, param);
// unwrap private key to load into database
KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java
index 256f72879..c471a2869 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRecordParser.java
@@ -46,6 +46,19 @@ public class KeyRecordParser {
public final static String OUT_RECOVERED_BY = "recoveredBy";
public final static String OUT_RECOVERED_ON = "recoveredOn";
+ /* parameters to populate WrappingParams */
+ public final static String OUT_SK_TYPE = "sessionKeyType";
+ public final static String OUT_SK_KEYGEN_ALGORITHM = "sessionKeyKeyGenAlgorithm";
+ public final static String OUT_SK_LENGTH = "sessionKeyLength";
+ public final static String OUT_SK_WRAP_ALGORITHM = "sessionKeyWrapAlgorithm";
+ public final static String OUT_PL_WRAP_ALGORITHM = "payloadWrapAlgorithm";
+ public final static String OUT_PL_WRAP_IV = "payloadWrapIV";
+ public final static String OUT_PL_ENCRYPTION_ALGORITHM = "payloadEncryptionAlgorithm";
+ public final static String OUT_PL_ENCRYPTION_MODE = "payloadEncryptionMode";
+ public final static String OUT_PL_ENCRYPTION_PADDING = "payloadEncryptionPadding";
+ public final static String OUT_PL_ENCRYPTION_IV = "payloadEncryptionIV";
+ public final static String OUT_PL_ENCRYPTION_OID = "payloadEncryptionOID";
+
/**
* Fills key record into argument block.
*/
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/GPParams.java b/base/server/cms/src/com/netscape/cms/servlet/tks/GPParams.java
new file mode 100644
index 000000000..f16481be5
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/GPParams.java
@@ -0,0 +1,108 @@
+// --- 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) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.tks;
+
+
+//Simple class used to hold scp03 related settings in TKS keyset config block
+// Ex: tks.defKeySet.prot3.divers=emv
+// tks.defKeySet.prot3.diversVer1Keys=emv
+
+// Will probably be extended to allow params for future tokens
+
+public class GPParams {
+
+ public static String DIVER_EMV = "emv";
+ public static String DIVER_NONE = "none";
+ public static String DIVER_VISA2 = "visa2";
+ public static String NIST_SP800 = "nistsp_800";
+
+ public GPParams() {
+ }
+
+ // Diversification scheme for all keysets after 1
+ private String diversificationScheme;
+ //Diversification scheme for just version one or developer keys
+ private String version1DiversificationScheme;
+
+ public boolean isDiversEmv() {
+ if (DIVER_EMV.equalsIgnoreCase(diversificationScheme))
+ return true;
+ else
+ return false;
+ }
+
+ public boolean isDiversVisa2() {
+ if (DIVER_VISA2.equalsIgnoreCase(diversificationScheme))
+ return true;
+ else
+ return false;
+ }
+
+ public boolean isDiversNone() {
+ if (DIVER_NONE.equalsIgnoreCase(diversificationScheme))
+ return true;
+ else
+ return false;
+ }
+
+ public boolean isVer1DiversEmv() {
+ if (DIVER_EMV.equalsIgnoreCase(version1DiversificationScheme))
+ return true;
+ else
+ return false;
+ }
+
+ public boolean isVer1DiversVisa2() {
+ if (DIVER_VISA2.equalsIgnoreCase(version1DiversificationScheme))
+ return true;
+ else
+ return false;
+
+ }
+
+ public boolean isVer1DiversNone() {
+ if (DIVER_NONE.equalsIgnoreCase(version1DiversificationScheme))
+ return true;
+ else
+ return false;
+ }
+
+ public void setDiversificationScheme(String scheme) {
+ diversificationScheme = scheme;
+ }
+
+ public String getDiversificationScheme() {
+ return diversificationScheme;
+ }
+
+ public String getVersion1DiversificationScheme() {
+ return version1DiversificationScheme;
+ }
+
+ public void setVersion1DiversificationScheme(String version1DiversificationScheme) {
+ this.version1DiversificationScheme = version1DiversificationScheme;
+ }
+
+ public String toString() {
+ String output = " Version1 Diversification Scheme: " + version1DiversificationScheme + " All other versions : "
+ + diversificationScheme;
+
+ return output;
+ }
+
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
index 0407e2934..e7b183b4e 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java
@@ -41,9 +41,64 @@ public class KDF {
/* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
/* E */0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe, };
- public static byte[] getDiversificationData(byte[] context, String type) throws EBaseException {
+ //Add the emv diversification method, used in SCP03 g&d card.
+ public static byte[] getDiversificationData_EMV(byte[] context, String type) throws EBaseException {
- String method = "KDF.getDiversificationData:";
+ String method = "KDF.getDiversificationData_EMV:";
+
+ CMS.debug(method + " entering ...");
+
+ if (context == null || type == null) {
+ throw new EBaseException(method + "Invalid input parameters!");
+ }
+
+ byte[] KDC = new byte[SecureChannelProtocol.DES2_LENGTH];
+
+ KDC[0] = context[4 + 0];
+ KDC[1] = context[4 + 1];
+ KDC[2] = context[4 + 2];
+ KDC[3] = context[4 + 3];
+ KDC[4] = context[4 + 4];
+ KDC[5] = context[4 + 5];
+ KDC[6] = (byte) 0xF0;
+
+ KDC[7] = 0x1;
+
+ KDC[8] = context[4 + 0];
+ KDC[9] = context[4 + 1];
+ KDC[10] = context[4 + 2];
+ KDC[11] = context[4 +3];
+ KDC[12] = context[4 + 4];
+ KDC[13] = context[4 + 5];
+ KDC[14] = (byte) 0x0f;
+
+ KDC[15] = 0x1;
+
+ if (type.equals(SecureChannelProtocol.encType))
+ return KDC;
+
+ KDC[7] = 0x02;
+ KDC[15] = 0x02;
+ if (type.equals(SecureChannelProtocol.macType))
+ return KDC;
+
+ KDC[7] = 0x03;
+ KDC[15] = 0x03;
+ if (type.equals(SecureChannelProtocol.kekType))
+ return KDC;
+
+ KDC[7] = 0x04;
+ KDC[15] = 0x04;
+ if (type.equals(SecureChannelProtocol.rmacType))
+ return KDC;
+ return KDC;
+
+ }
+
+ //Standard visa2 diversification method
+ public static byte[] getDiversificationData_VISA2(byte[] context, String type) throws EBaseException {
+
+ String method = "KDF.getDiversificationData_VISA2:";
CMS.debug(method + " entering ...");
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
index e392ce1a3..ad4a370c2 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java
@@ -1,13 +1,24 @@
package com.netscape.cms.servlet.tks;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import org.mozilla.jss.crypto.BadPaddingException;
+import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.HMACAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+import org.mozilla.jss.crypto.IllegalBlockSizeException;
import org.mozilla.jss.crypto.JSSMessageDigest;
import org.mozilla.jss.crypto.SymmetricKey;
+import org.mozilla.jss.crypto.TokenException;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
@@ -22,7 +33,18 @@ public class NistSP800_108KDF extends KDF {
static final byte KDF_LABEL = 0x04; // arbitra
- static final int SHA256_LENGTH = 32;
+ //SCP03, AES related constants
+
+ public static final int SHA256_LENGTH = 32;
+ private static final int AES_CMAC_BLOCK_SIZE = 16;
+ private static final byte AES_CMAC_CONSTANT = (byte) 0x87;
+ public static final byte ENC_KDF_CONSTANT = (byte) 0x04;
+ public static final byte MAC_KDF_CONSTANT = (byte) 0x06;
+ public static final byte RMAC_KDF_CONSTANT = (byte) 0x07;
+ public static final byte CARD_CRYPTO_KDF_CONSTANT = 0x0;
+ public static final byte HOST_CRYPTO_KDF_CONSTANT = 0x1;
+
+
SecureChannelProtocol protocol = null;
@@ -57,7 +79,7 @@ public class NistSP800_108KDF extends KDF {
String method = "NistSP800_108KDF.computeCardKeys:";
if (masterKey == null || context == null || token == null) {
- throw new EBaseException(method + " Invlalid input parameters!");
+ throw new EBaseException(method + " Invalid input parameters!");
}
Map<String, SymmetricKey> keys = new HashMap<String, SymmetricKey>();
@@ -101,9 +123,9 @@ public class NistSP800_108KDF extends KDF {
Arrays.fill(kek, (byte) 0);
Arrays.fill(kdf_output, (byte) 0);
- SymmetricKey macKey = protocol.unwrapSymKeyOnToken(token, null, macFinal, false);
- SymmetricKey encKey = protocol.unwrapSymKeyOnToken(token, null, encFinal, false);
- SymmetricKey kekKey = protocol.unwrapSymKeyOnToken(token, null, kekFinal, false);
+ SymmetricKey macKey = protocol.unwrapSymKeyOnToken(token, null, macFinal, false,SymmetricKey.DES3);
+ SymmetricKey encKey = protocol.unwrapSymKeyOnToken(token, null, encFinal, false,SymmetricKey.DES3);
+ SymmetricKey kekKey = protocol.unwrapSymKeyOnToken(token, null, kekFinal, false,SymmetricKey.DES3);
Arrays.fill(encFinal, (byte) 0);
Arrays.fill(macFinal, (byte) 0);
@@ -117,6 +139,79 @@ public class NistSP800_108KDF extends KDF {
}
+ //Compute the AES based CMAC operation. Used to derive session keys and cryptograms
+ public byte[] kdf_AES_CMAC_SCP03(SymmetricKey masterKey, byte[] context, byte kdfConstant,
+ int kdfOutputSizeBytes) throws EBaseException {
+
+ String method = "NistSP800_108KDF.kdf_AES_CMAC_SCP03:";
+ // 11 bytes label
+ byte[] label = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ // sanity checking
+
+ if (masterKey == null || context == null || kdfOutputSizeBytes <= 0) {
+ throw new EBaseException(method + " Invalid input!");
+ }
+
+ ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ int outputBits = kdfOutputSizeBytes * 8;
+
+ //output size of cmac PRF
+ final int h = 128;
+
+ int remainder = outputBits % h;
+
+ //calculate counter size
+ int n = 0;
+ if (remainder == 0) {
+ n = outputBits / h;
+ } else {
+ n = outputBits / h + 1;
+ }
+
+ byte b1 = (byte) ((outputBits >> 8) & 0xFF);
+ byte b2 = (byte) (outputBits & 0xFF);
+
+ byte[] outputBitsBinary = new byte[2];
+ outputBitsBinary[0] = b1;
+ outputBitsBinary[1] = b2;
+
+ try {
+ data.write(label);
+ data.write(kdfConstant);
+ data.write(0x0);
+ data.write(outputBitsBinary);
+ } catch (IOException e) {
+ throw new EBaseException(method + "Unable to calculate kdf!");
+ }
+
+ byte[] headerBytes = data.toByteArray();
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ByteArrayOutputStream input = new ByteArrayOutputStream();
+
+ byte[] kI = null;
+ for (int i = 1; i <= n; i++) {
+
+ try {
+ input.write(headerBytes);
+ input.write((byte) i);
+ input.write(context);
+
+ kI = computeAES_CMAC(masterKey, input.toByteArray());
+
+ output.write(kI);
+
+ } catch (IOException e) {
+ throw new EBaseException(method + "Unable to calculate kdf!");
+ }
+
+ }
+
+ return output.toByteArray();
+ }
+
/*******************************************************************************
Key Derivation Function in Counter Mode using PRF = SHA256HMAC (NIST SP 800-108)
Calculates 384 bits of diversified output from the provided master key (K_I)
@@ -132,7 +227,6 @@ public class NistSP800_108KDF extends KDF {
int L_BYTE_array_length = 2; // 384 = 0x0180 hex; 2 byte long representation
if (context == null) {
- throw new EBaseException(method + " Input value context must not be null.");
}
// sanity check that output buffer is large enough to contain 384 bits
if (kdfOutputSizeBytes < KDF_OUTPUT_SIZE_BYTES) {
@@ -215,4 +309,324 @@ public class NistSP800_108KDF extends KDF {
return digestBytes;
}
+ // Implements agorithm http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
+ // Input an aes key of 128, 192, or 256 bits
+ // For now calling code only using 128
+ // Will move later to common class used by both tks and tps
+
+ public static byte[] computeAES_CMAC(SymmetricKey aesKey, byte[] input) throws EBaseException {
+
+ String method = "NistSP800_108KDF.computeAES_CMAC:";
+ byte iv[] = null;
+
+ if (aesKey == null || input == null) {
+ throw new EBaseException(method + " invalid input data!");
+ }
+
+ byte[] data = new byte[input.length];
+ System.arraycopy(input, 0, data, 0, input.length);
+
+ String alg = aesKey.getAlgorithm();
+ System.out.println(" AES ALG: " + alg);
+
+ EncryptionAlgorithm eAlg = EncryptionAlgorithm.AES_128_CBC;
+ int ivLength = eAlg.getIVLength();
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength];
+ }
+
+ if (!("AES".equals(alg))) {
+ throw new EBaseException(method + " invalid in put key type , must be AES!");
+ }
+
+ byte[] k0 = new byte[AES_CMAC_BLOCK_SIZE];
+
+ //Encrypt the zero array
+ CryptoToken token = aesKey.getOwningToken();
+ Cipher encryptor = null;
+
+ try {
+ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+ encryptor.initEncrypt(aesKey, new IVParameterSpec(iv));
+ k0 = encryptor.doFinal(k0);
+
+ } catch (NoSuchAlgorithmException | TokenException | IllegalStateException | IllegalBlockSizeException
+ | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
+ throw new EBaseException(e);
+ }
+
+ byte[] k1 = getAES_CMAC_SubKey(k0);
+ byte[] k2 = getAES_CMAC_SubKey(k1);
+
+ int numBlocks = 0;
+ int messageSize = data.length;;
+ boolean perfectBlocks = false;
+
+ if (((messageSize % AES_CMAC_BLOCK_SIZE) == 0) && (messageSize != 0)) {
+ numBlocks = messageSize / AES_CMAC_BLOCK_SIZE;
+ perfectBlocks = true;
+ }
+ else {
+ numBlocks = messageSize / AES_CMAC_BLOCK_SIZE + 1;
+ perfectBlocks = false;
+ }
+
+ int index = 0;
+ byte inb = 0;
+
+ byte[] finalData = null;
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
+
+ if (perfectBlocks == true)
+ {
+ // If the size of the message is an integer multiple of the block block size (namely, 128 bits) (16 bytes)
+ // the last block shall be exclusive-OR'ed with the first subKey k1
+
+ for (int j = 0; j < k1.length; j++) {
+ index = messageSize - AES_CMAC_BLOCK_SIZE + j;
+ inb = data[index];
+ data[index] = (byte) (inb ^ k1[j]);
+ }
+ try {
+ outputStream.write(data);
+ } catch (IOException e) {
+ throw new EBaseException(method + " internal buffer erro!");
+ }
+ finalData = outputStream.toByteArray();
+ }
+ else
+ {
+ // Otherwise, the last block shall be padded with 10^i
+ byte[] padding = new byte[AES_CMAC_BLOCK_SIZE - messageSize % AES_CMAC_BLOCK_SIZE];
+ padding[0] = (byte) 0x80;
+
+ try {
+ outputStream.write(data);
+ outputStream.write(padding);
+ } catch (IOException e) {
+ throw new EBaseException(method + " internal buffer error!");
+ }
+
+ finalData = outputStream.toByteArray();
+
+ //Get new data size , it's changed
+ messageSize = finalData.length;
+
+ // and exclusive-OR'ed with K2
+ for (int j = 0; j < k2.length; j++) {
+ index = messageSize - AES_CMAC_BLOCK_SIZE + j;
+ inb = finalData[index];
+ finalData[index] = (byte) (inb ^ k2[j]);
+ }
+ }
+
+ // Initialization vector starts as zeroes but changes inside the loop's
+ // subsequent iterations, it becomes the last encryption output
+ byte[] encData = new byte[AES_CMAC_BLOCK_SIZE];
+ byte[] currentBlock = new byte[AES_CMAC_BLOCK_SIZE];
+ for (int i = 0; i < numBlocks; i++) {
+ try {
+ encryptor.initEncrypt(aesKey, new IVParameterSpec(encData));
+ System.arraycopy(finalData, i * AES_CMAC_BLOCK_SIZE, currentBlock, 0, AES_CMAC_BLOCK_SIZE);
+ encData = encryptor.doFinal(currentBlock);
+ } catch (TokenException | IllegalStateException | IllegalBlockSizeException
+ | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
+ throw new EBaseException(e);
+ }
+ }
+
+ return encData;
+
+ }
+
+ // SCP03 AES-CMAC support function
+ private static byte[] getAES_CMAC_SubKey(byte[] input) {
+
+ byte[] output = new byte[input.length];
+
+ boolean msbSet = ((input[0]&0x80) != 0);
+ for (int i=0; i<input.length; i++) {
+ output[i] = (byte) (input[i] << 1);
+ if (i+1 < input.length && ((input[i+1]&0x80) != 0)) {
+ output[i] |= 0x01;
+ }
+ }
+ if (msbSet) {
+ output[output.length-1] ^= AES_CMAC_CONSTANT;
+ }
+ return output;
+ }
+
+ // Collection of informal invocations of api used to create various session keys
+ // Done with test data.
+ public static void main(String[] args) {
+/*
+ Options options = new Options();
+
+ options.addOption("d", true, "Directory for tokendb");
+
+ String db_dir = null;
+ CryptoManager cm = null;
+
+ byte devKey[] = { (byte) 0x40, (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46,
+ (byte) 0x47, (byte) 0x48, (byte) 0x49, (byte) 0x4a, (byte) 0x4b, (byte) 0x4c, (byte) 0x4d, (byte) 0x4e,
+ (byte) 0x4f };
+
+ byte test_cuid[] = { (byte) 0x47,(byte) 0x90,(byte)0x50,(byte)0x37,(byte)0x72,(byte)0x71,(byte)0x97,(byte)0x00,(byte)0x74,(byte)0xA9 };
+ byte test_kdd[] = { (byte)0x00, (byte)0x00, (byte)0x50, (byte)0x24,(byte) 0x97,(byte) 0x00,(byte) 0x74, (byte) 0xA9, (byte)0x72,(byte)0x71 };
+
+
+ byte test_host_challenge[] = { 0x06 ,(byte)0xA4 ,0x46 ,0x57 ,(byte) 0x8B ,0x65 ,0x48 ,0x51 };
+ byte test_card_challenge[] = { (byte) 0xAD ,(byte) 0x2E ,(byte)0xD0 ,0x1E ,0x7C ,0x2D ,0x0C ,0x6F};
+
+ byte test_key_info[] = { (byte) 0x02,(byte) 03,(byte) 00 };
+ byte test_old_key_info[] = {0x01,0x03,0x00};
+
+ try {
+ CommandLineParser parser = new DefaultParser();
+ CommandLine cmd = parser.parse(options, args);
+
+ if (cmd.hasOption("d")) {
+ db_dir = cmd.getOptionValue("d");
+ }
+
+ } catch (ParseException e) {
+ System.err.println("Error in parsing command line options: " + e.getMessage());
+
+ }
+
+ SymmetricKey encKey = null;
+ SymmetricKey macKey = null;
+ SymmetricKey kekKey = null;
+
+ SymmetricKey putEncKey = null;
+ SymmetricKey putMacKey = null;
+ SymmetricKey putKekKey = null;
+
+ SymmetricKey tempKey = null;
+
+ try {
+ CryptoManager.initialize(db_dir);
+ cm = CryptoManager.getInstance();
+
+ CryptoToken token = cm.getInternalKeyStorageToken();
+
+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.AES);
+
+ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4];
+ usages[0] = SymmetricKey.Usage.WRAP;
+ usages[1] = SymmetricKey.Usage.UNWRAP;
+ usages[2] = SymmetricKey.Usage.ENCRYPT;
+ usages[3] = SymmetricKey.Usage.DECRYPT;
+
+ kg.setKeyUsages(usages);
+ kg.temporaryKeys(true);
+ kg.initialize(128);
+ tempKey = kg.generate();
+
+
+ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+
+ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+ byte[] iv = null;
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength]; // all zeroes
+ }
+
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey = encryptor.doFinal(devKey);
+
+ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv));
+
+ encKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, 16);
+ macKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, 16);
+ kekKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, 16);
+
+ String transportName = "TPS-dhcp-16-206.sjc.redhat.com-8443 sharedSecret";
+ SecureChannelProtocol prot = new SecureChannelProtocol(SecureChannelProtocol.PROTOCOL_THREE);
+
+ SymmetricKey masterKey = SecureChannelProtocol.getSymKeyByName(token,"new_master");
+
+ GPParams params = new GPParams();
+ params.setVersion1DiversificationScheme("visa2");
+ params.setDiversificationScheme("visa2");
+
+ putEncKey = prot.computeSessionKey_SCP03("internal", "new_master",test_old_key_info,
+ SecureChannelProtocol.encType, devKey, "defKeySet", test_cuid, test_kdd, null, null,
+ transportName,params);
+
+ putMacKey = prot.computeSessionKey_SCP03("internal", "new_master",test_old_key_info,
+ SecureChannelProtocol.macType, devKey, "defKeySet", test_cuid, test_kdd, null, null,
+ transportName,params);
+
+ putKekKey = prot.computeSessionKey_SCP03("internal", "new_master",test_old_key_info,
+ SecureChannelProtocol.kekType, devKey, "defKeySet", test_cuid, test_kdd, null, null,
+ transportName,params);
+
+ //create test session keys
+ encKey = prot.computeSessionKey_SCP03("internal", "new_master",test_key_info,
+ SecureChannelProtocol.encType, devKey, "defKeySet", test_cuid, test_kdd, test_host_challenge, test_card_challenge,
+ transportName,params);
+
+ macKey = prot.computeSessionKey_SCP03("internal", "new_master",test_key_info,
+ SecureChannelProtocol.macType,devKey,"defKeySet", test_cuid, test_kdd, test_host_challenge, test_card_challenge,
+ transportName,params);
+
+ kekKey = prot.computeSessionKey_SCP03("internal", "new_master",test_key_info,
+ SecureChannelProtocol.kekType, devKey, "defKeySet", test_cuid, test_kdd, test_host_challenge, test_card_challenge,
+ transportName,params);
+
+ System.out.println("masterKey: " + masterKey);
+
+ System.out.println("\n");
+
+ SecureChannelProtocol.debugByteArray(putEncKey.getKeyData(), " derived putEnc session key data: ");
+ SecureChannelProtocol.debugByteArray(putMacKey.getKeyData(), " derived putMac session key data: ");
+ SecureChannelProtocol.debugByteArray(putKekKey.getKeyData(), " derived putKek session key data: ");
+
+ System.out.println("\n");
+
+ SecureChannelProtocol.debugByteArray(encKey.getKeyData(), " derived enc session key data: ");
+ SecureChannelProtocol.debugByteArray(macKey.getKeyData(), " derived mac session key data: ");
+ SecureChannelProtocol.debugByteArray(kekKey.getKeyData(), " derived kek session key data: ");
+
+ ByteArrayOutputStream contextStream = new ByteArrayOutputStream();
+ try {
+ contextStream.write(test_host_challenge);
+ contextStream.write(test_card_challenge);
+ } catch (IOException e) {
+ }
+
+ StandardKDF standard = new StandardKDF(prot);
+
+ ByteArrayOutputStream testContext = new ByteArrayOutputStream();
+
+ testContext.write(test_host_challenge);
+ testContext.write(test_card_challenge);
+
+ NistSP800_108KDF nistKdf = new NistSP800_108KDF(prot);
+
+ byte[] finalEncBytes = nistKdf.kdf_AES_CMAC_SCP03(encKey, testContext.toByteArray(), (byte) 0x04, 16);
+ byte[] finalMacBytes = nistKdf.kdf_AES_CMAC_SCP03(macKey, testContext.toByteArray(), (byte) 0x06, 16);
+
+ SymmetricKey sEnc = prot.unwrapAESSymKeyOnToken(token, finalEncBytes, false);
+ SymmetricKey sMac = macKey = prot.unwrapAESSymKeyOnToken(token, finalMacBytes, false);
+
+ byte[] cardCryptoVerify = nistKdf.kdf_AES_CMAC_SCP03(sMac, testContext.toByteArray(), CARD_CRYPTO_KDF_CONSTANT, 8);
+ SecureChannelProtocol.debugByteArray(cardCryptoVerify, " calculated card cryptogram");
+
+ byte[] hostCrypto = nistKdf.kdf_AES_CMAC_SCP03(sMac, testContext.toByteArray(), HOST_CRYPTO_KDF_CONSTANT, 8);
+ SecureChannelProtocol.debugByteArray(hostCrypto, " calculated host cryptogram");
+
+ } catch (AlreadyInitializedException e) {
+ // it is ok if it is already initialized
+ } catch (Exception e) {
+ System.err.println("JSS error!" + e);
+ System.exit(1);
+ }
+*/
+ }
}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
index 1766f0459..371e734df 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java
@@ -15,6 +15,7 @@ import org.mozilla.jss.NoSuchTokenException;
import org.mozilla.jss.crypto.Cipher;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
@@ -24,12 +25,12 @@ import org.mozilla.jss.crypto.SymmetricKey.NotExtractableException;
import org.mozilla.jss.crypto.SymmetricKeyDeriver;
import org.mozilla.jss.crypto.TokenException;
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.cmsutil.crypto.CryptoUtil;
-import sun.security.pkcs11.wrapper.PKCS11Constants;
-
public class SecureChannelProtocol {
static String sharedSecretKeyName = null;
@@ -43,12 +44,14 @@ public class SecureChannelProtocol {
static final int KEYNAMELENGTH = PREFIXLENGHT + 7;
static final String TRANSPORT_KEY_NAME = "sharedSecret";
static final String DEFKEYSET_NAME = "defKeySet";
+ static int protocol = 1;
static final String encType = "enc";
static final String macType = "mac";
static final String kekType = "kek";
static final String authType = "auth";
static final String dekType = "dek";
+ static final String rmacType = "rmac";
static final int PROTOCOL_ONE = 1;
static final int PROTOCOL_TWO = 2;
static final int PROTOCOL_THREE = 3;
@@ -57,12 +60,26 @@ public class SecureChannelProtocol {
//Size of long type in bytes, since java7 has no define for this
static final int LONG_SIZE = 8;
+ // constants
+
+ static final int AES_128_BYTES = 16;
+ static final int AES_192_BYTES = 24;
+ static final int AES_256_BYTES = 32;
+
+ static final int AES_128_BITS = 128;
+ static final int AES_192_BITS = 192;
+ static final int AES_256_BITS = 256;
+
private SymmetricKey transportKey = null;
CryptoManager cryptoManager = null;
public SecureChannelProtocol() {
}
+ public SecureChannelProtocol(int theProtocol) {
+ protocol = theProtocol;
+ }
+
public byte[] computeCryptogram_SCP01(
String selectedToken, String keyNickName, byte[] card_challenge,
byte[] host_challenge, byte[] keyInfo,
@@ -144,6 +161,222 @@ public class SecureChannelProtocol {
throw new EBaseException(method + " Not yet implemented!");
}
+ public int getProtocol() {
+ return protocol;
+ }
+
+ // Either calculate a full session key, with the KDF applied or
+ // Merely calculate the card key. Card key mode is when host_challenge and
+ // card_challenge are passed in as null. Card keys are calculated
+ // when creating a new keyset to send to the token
+ public SymmetricKey computeSessionKey_SCP03(String selectedToken,
+ String keyNickName, byte[] keyInfo, String keyType,
+ byte[] devKeyArray, String keySet, byte[] xCUID, byte[] xKDD,
+ byte[] host_challenge, byte[] card_challenge, String transportKeyName, GPParams params)
+ throws EBaseException {
+
+ final byte mac_constant = 0x06;
+ final byte enc_constant = 0x04;
+ final byte rmac_constant = 0x07;
+
+ boolean noDerive = false;
+
+ byte constant = 0;
+
+ String method = "SecureChannelProtocol.computeSessionKey_SCP03:";
+
+ if (keyType == null || devKeyArray == null
+ || transportKeyName == null) {
+ throw new EBaseException(method + " invalid input data");
+ }
+
+ if (xCUID == null || xCUID.length <= 0) {
+ throw new EBaseException(method + "CUID invalid size!");
+ }
+
+ if (xKDD == null || xKDD.length != NistSP800_108KDF.KDD_SIZE_BYTES) {
+ throw new EBaseException(method + "KDD invalid size!");
+ }
+
+
+ //Detect card key mode or full derivation mode
+ if (card_challenge == null && host_challenge == null) {
+ noDerive = true;
+ } else {
+ if (card_challenge == null || host_challenge == null) {
+ throw new EBaseException(method + " Invalid challenge data!");
+ }
+ }
+
+ CMS.debug(method + " entering. nickname: " + keyNickName + " selectedToken: " + selectedToken);
+
+ CryptoManager cm = null;
+ CryptoToken token = null;
+ CryptoToken internalToken = null;
+ try {
+ cm = CryptoManager.getInstance();
+ token = returnTokenByName(selectedToken, cm);
+ internalToken = returnTokenByName("internal", cm);
+ } catch (NotInitializedException e) {
+ CMS.debug(method + " " + e);
+ throw new EBaseException(e);
+
+ } catch (NoSuchTokenException e) {
+ CMS.debug(method + " " + e);
+ throw new EBaseException(e);
+ }
+
+ sharedSecretKeyName = SecureChannelProtocol.getSharedSecretKeyName(transportKeyName);
+ transportKey = getSharedSecretKey(internalToken);
+
+ //concat host and card challenge:
+
+ byte[] context = null;
+
+ ByteArrayOutputStream contextStream = new ByteArrayOutputStream();
+
+ // Full derivation mode create context used in derivation
+ // host_challenge + card_challenge concatenated
+ if (noDerive == false) {
+ try {
+ contextStream.write(host_challenge);
+ contextStream.write(card_challenge);
+ } catch (IOException e) {
+ throw new EBaseException(method + " Error calculating derivation data!");
+ }
+
+ context = contextStream.toByteArray();
+ }
+
+ //Calculate the constant based on what type of key we want.
+ // Note the kek key never goes through final derivation in scp03
+
+ if (keyType.equalsIgnoreCase(SecureChannelProtocol.encType)) {
+ constant = enc_constant;
+ }
+
+ if (keyType.equalsIgnoreCase(SecureChannelProtocol.macType)) {
+ constant = mac_constant;
+ }
+
+ if (keyType.equalsIgnoreCase(SecureChannelProtocol.rmacType)) {
+ constant = rmac_constant;
+ }
+
+ if (keyType.equalsIgnoreCase(SecureChannelProtocol.kekType)) {
+ constant = 0;
+ }
+
+ String keyNameStr = null;
+
+ SymmetricKey sessionKey = null;
+ SymmetricKey masterKey = null;
+
+ if (keyNickName == null) {
+ keyNameStr = this.getKeyName(keyInfo);
+ } else {
+ keyNameStr = keyNickName;
+ }
+
+ boolean noDivers = false;
+
+ CMS.debug(method + " keyNameStr: " + keyNameStr);
+
+ //Starting with version 1 or factory keyset.
+ if ((keyInfo[0] == 0x1 && keyNameStr.contains("#01#")) ||
+ (keyInfo[0] == -1 && keyNameStr.indexOf("#FF") != -1))
+
+ {
+ String finalKeyType = keyType;
+ SymmetricKey devSymKey = returnDeveloperSymKey(token, finalKeyType, keySet, devKeyArray);
+
+ StandardKDF standard = new StandardKDF(this);
+ SymmetricKey divKey = null;
+
+ byte[] keyDiversified = null;
+
+ //Consult the config to determine with diversification method to use.
+ if (params.isVer1DiversNone()) {
+ noDivers = true;
+ } else if (params.isVer1DiversEmv()) {
+ keyDiversified = KDF.getDiversificationData_EMV(xKDD, keyType);
+ } else if (params.isVer1DiversVisa2()) {
+ keyDiversified = KDF.getDiversificationData_VISA2(xKDD, keyType);
+ } else {
+ throw new EBaseException(method + " Invalid diversification method!");
+ }
+
+ //Obtain the card key,it may just be the raw developer key
+ if (noDivers == true) {
+ divKey = unwrapAESSymKeyOnToken(token, devKeyArray, false);
+ } else {
+
+ // The g&d calls for computing the aes card key with DES, it will then be treated as aes
+ divKey = standard.computeCardKey_SCP03_WithDES3(devSymKey, keyDiversified, token);
+ }
+
+ NistSP800_108KDF nistKdf = new NistSP800_108KDF(this);
+
+ //IN scp03, the kek key IS the card key
+ if (constant == 0 /* kek key */) {
+ sessionKey = divKey;
+ } else { // session keys will become AES
+ if (noDerive) {
+ sessionKey = divKey;
+ }
+ else {
+ byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, 16);
+ sessionKey = unwrapAESSymKeyOnToken(token, finalKeyBytes, false);
+
+ Arrays.fill(finalKeyBytes,(byte) 0);
+
+ //The final session key is AES.
+ }
+ }
+ } else { // Creating a session key for the case where we have already upgraded the keys on the token, using the master key
+ CMS.debug(method + "In master key mode.");
+
+ masterKey = getSymKeyByName(token, keyNameStr);
+
+ StandardKDF standard = new StandardKDF(this);
+
+ byte[] keyDiversified = null;
+
+ if (params.isDiversNone()) {
+ throw new EBaseException(method + " No diversification requested in master key mode. Aborting...");
+ } //Allow choice of emv or standard diversification
+ else if (params.isDiversEmv()) {
+ keyDiversified = KDF.getDiversificationData_EMV(xKDD, keyType);
+ } else if (params.isDiversVisa2()) {
+ keyDiversified = KDF.getDiversificationData_VISA2(xKDD, keyType);
+ }
+
+ SymmetricKey divKey = null;
+
+ divKey = standard.computeCardKey_SCP03_WithDES3(masterKey, keyDiversified, token);
+
+ NistSP800_108KDF nistKdf = new NistSP800_108KDF(this);
+ // The kek session key does not call for derivation
+ if (constant == 0 /* kek key */) {
+ sessionKey = divKey;
+ } else {
+ if (noDerive) {
+ sessionKey = divKey;
+ }
+ else {
+ byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, 16);
+ sessionKey = unwrapAESSymKeyOnToken(token, finalKeyBytes, false);
+
+ Arrays.fill(finalKeyBytes,(byte) 0);
+ }
+ }
+ }
+
+ //SecureChannelProtocol.debugByteArray(sessionKey.getEncoded(), keyType + " : session key");
+
+ return sessionKey;
+ }
+
public SymmetricKey computeKEKKey_SCP01(
String selectedToken, String keyNickName,
byte[] keyInfo,
@@ -153,7 +386,6 @@ public class SecureChannelProtocol {
byte[] xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
byte[] devKeyArray, String useSoftToken_s, String keySet, String transportKeyName) throws EBaseException {
-
String method = "SecureChannelProtocol.computeKEKKey_SCP01:";
CMS.debug(method + " entering... ");
@@ -294,7 +526,7 @@ public class SecureChannelProtocol {
} else {
StandardKDF standardKDF = new StandardKDF(this);
CMS.debug(method + " ComputeSessionKey NistSP800_108KDF code: Using original KDF.");
- byte[] data = KDF.getDiversificationData(context, keyType);
+ byte[] data = KDF.getDiversificationData_VISA2(context, keyType);
devKey = standardKDF.computeCardKey(masterKey, data, token, PROTOCOL_ONE);
}
@@ -349,7 +581,7 @@ public class SecureChannelProtocol {
byte[] parityEncrypted = KDF.getDesParity(encrypted);
CMS.debug(method + "encryption completed");
- derivedKey = this.unwrapSymKeyOnToken(token, null, parityEncrypted, false);
+ derivedKey = this.unwrapSymKeyOnToken(token, null, parityEncrypted, false, SymmetricKey.DES3);
}
} catch (TokenException | InvalidKeyException | EBaseException e) {
@@ -440,7 +672,7 @@ public class SecureChannelProtocol {
From that point it is a simple matter of retrieving the desired key from the token.
No security advantage is implied or desired here.
*/
- private SymmetricKey returnDeveloperSymKey(CryptoToken token, String keyType, String keySet, byte[] inputKeyArray)
+ public SymmetricKey returnDeveloperSymKey(CryptoToken token, String keyType, String keySet, byte[] inputKeyArray)
throws EBaseException {
SymmetricKey devKey = null;
@@ -497,10 +729,157 @@ public class SecureChannelProtocol {
return devKey;
}
- public SymmetricKey unwrapSymKeyOnToken(CryptoToken token, SymmetricKey unwrappingKey, byte[] inputKeyArray,
+ //Takes raw des key 16 bytes, such as developer key and returns an AES key of the same size
+ //Supports 128 bits for now
+ public SymmetricKey unwrapAESSymKeyOnToken(CryptoToken token, byte[] inputKeyArray,
+ boolean isPerm)
+ throws EBaseException {
+
+ String method = "SecureChannelProtocol.unwrapAESSymKeyOnToken:";
+ CMS.debug(method + "Entering...");
+
+ if(token == null || inputKeyArray == null) {
+ throw new EBaseException(method + " Invalid input data!");
+ }
+
+ if(inputKeyArray.length < 16) {
+ throw new EBaseException(method + " Invalid key size!");
+ }
+
+ byte[] finalInputKeyArray = inputKeyArray;
+ if(inputKeyArray.length > 16) {
+ finalInputKeyArray = new byte[16];
+ System.arraycopy(inputKeyArray, 0, finalInputKeyArray, 0, 16);;
+
+ }
+
+ KeyGenerator kg;
+ SymmetricKey finalAESKey;
+ try {
+ kg = token.getKeyGenerator(KeyGenAlgorithm.AES);
+
+ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4];
+ usages[0] = SymmetricKey.Usage.WRAP;
+ usages[1] = SymmetricKey.Usage.UNWRAP;
+ usages[2] = SymmetricKey.Usage.ENCRYPT;
+ usages[3] = SymmetricKey.Usage.DECRYPT;
+
+ kg.setKeyUsages(usages);
+ kg.temporaryKeys(true);
+ kg.initialize(128);
+ SymmetricKey tempKey = kg.generate();
+
+ //unwrap the test aes keys onto the token
+
+ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+
+ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+ byte[] iv = null;
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength]; // all zeroes
+ }
+
+ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey = encryptor.doFinal(finalInputKeyArray);
+
+ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv));
+ finalAESKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, 16);
+
+ } catch (Exception e) {
+ throw new EBaseException(method + " Can't unwrap key onto token!");
+ }
+
+ return finalAESKey;
+ }
+
+ //Supports 128 bits for now
+ //Used to convert a des key (on token) to aes
+ //Not used as of now, future if needed
+ public SymmetricKey unwrapAESSymKeyOnToken(CryptoToken token, SymmetricKey keyToUnwrap,
boolean isPerm)
throws EBaseException {
+ String method = "SecureChannelProtocol.unwrapAESSymKeyOnToken:";
+ CMS.debug(method + "Entering...");
+
+ if(token == null || keyToUnwrap == null) {
+ throw new EBaseException(method + " Invalid input data!");
+ }
+
+ if(keyToUnwrap.getLength()< 16) {
+ throw new EBaseException(method + " Invalid key size!");
+ }
+
+ KeyGenerator kg;
+ SymmetricKey finalAESKey;
+ try {
+ kg = token.getKeyGenerator(KeyGenAlgorithm.AES);
+
+ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4];
+ usages[0] = SymmetricKey.Usage.WRAP;
+ usages[1] = SymmetricKey.Usage.UNWRAP;
+ usages[2] = SymmetricKey.Usage.ENCRYPT;
+ usages[3] = SymmetricKey.Usage.DECRYPT;
+
+ kg.setKeyUsages(usages);
+ kg.temporaryKeys(true);
+ kg.initialize(128);
+ SymmetricKey tempKey = kg.generate();
+
+
+ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+ byte[] iv = null;
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength]; // all zeroes
+ }
+
+ //Wrap the arbitrary key first
+
+ int len = keyToUnwrap.getLength();
+
+ SymmetricKey finalKeyToWrap = null;
+ SymmetricKey key16 = null;
+ if(len > 16) {
+ key16 = extractDes2FromDes3(keyToUnwrap, token.getName());
+ if(key16 != null)
+ len = key16.getLength();
+ finalKeyToWrap = key16;
+ } else {
+ finalKeyToWrap = keyToUnwrap;
+ }
+
+ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap.initWrap(tempKey, new IVParameterSpec(iv));
+ byte[] wrappedKey = keyWrap.wrap(finalKeyToWrap);
+
+ //Now unwrap to an AES key
+
+ KeyWrapper keyUnWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyUnWrap.initUnwrap(tempKey, new IVParameterSpec(iv));
+ finalAESKey = keyUnWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, 16);
+
+
+ Arrays.fill(wrappedKey,(byte) 0);
+
+ //byte[] finalKeyBytes = finalAESKey.getKeyData();
+ //displayByteArray(finalKeyBytes, false);
+
+ } catch (Exception e) {
+ throw new EBaseException(method + " Can't unwrap key onto token!");
+ }
+
+ return finalAESKey;
+
+ }
+
+ //Final param allows us to request the final type, DES or AES
+ public SymmetricKey unwrapSymKeyOnToken(CryptoToken token, SymmetricKey unwrappingKey, byte[] inputKeyArray,
+ boolean isPerm, SymmetricKey.Type finalKeyType)
+ throws EBaseException {
+
String method = "SecureChannelProtocol.unwrapSymKeyOnToken:";
CMS.debug(method + "Entering...");
SymmetricKey unwrapped = null;
@@ -535,7 +914,7 @@ public class SecureChannelProtocol {
byte[] finalKeyArray = null;
- if (inputKeyArray.length == DES2_LENGTH) {
+ if (inputKeyArray.length == DES2_LENGTH && finalKeyType == SymmetricKey.DES3) {
finalKeyArray = SecureChannelProtocol.makeDes3FromDes2(inputKeyArray);
}
@@ -570,9 +949,9 @@ public class SecureChannelProtocol {
if (isPerm == true) {
unwrapped = keyWrap.unwrapSymmetricPerm(wrappedKey,
- SymmetricKey.DES3, 0);
+ finalKeyType, 0);
} else {
- unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, 0);
+ unwrapped = keyWrap.unwrapSymmetric(wrappedKey, finalKeyType, 0);
}
} catch (Exception e) {
@@ -590,8 +969,9 @@ public class SecureChannelProtocol {
return unwrapped;
}
+ //Final param allows us to request the final type, DES or AES
public SymmetricKey unwrapWrappedSymKeyOnToken(CryptoToken token, SymmetricKey unwrappingKey, byte[] inputKeyArray,
- boolean isPerm)
+ boolean isPerm, SymmetricKey.Type keyType)
throws EBaseException {
String method = "SecureChannelProtocol.unwrapWrappedSymKeyOnToken:";
@@ -613,13 +993,15 @@ public class SecureChannelProtocol {
if (isPerm) {
unwrapped = keyWrap.unwrapSymmetricPerm(inputKeyArray,
- SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP, inputKeyArray.length);
+ keyType, SymmetricKey.Usage.UNWRAP, inputKeyArray.length);
} else {
- unwrapped = keyWrap.unwrapSymmetric(inputKeyArray, SymmetricKey.DES3, SymmetricKey.Usage.UNWRAP,
+ unwrapped = keyWrap.unwrapSymmetric(inputKeyArray, keyType, SymmetricKey.Usage.UNWRAP,
inputKeyArray.length);
}
- finalUnwrapped = makeDes3KeyDerivedFromDes2(unwrapped, token.getName());
+ if (keyType == SymmetricKey.DES3) {
+ finalUnwrapped = makeDes3KeyDerivedFromDes2(unwrapped, token.getName());
+ }
} catch (Exception e) {
CMS.debug(method + " " + e);
@@ -629,7 +1011,10 @@ public class SecureChannelProtocol {
//CMS.debug(method + "Returning symkey: " + unwrapped);
CMS.debug(method + "Returning symkey...");
- return finalUnwrapped;
+ if (finalUnwrapped != null)
+ return finalUnwrapped;
+ else
+ return unwrapped;
}
public SymmetricKey unwrapSymKeyOnToken(CryptoToken token, byte[] inputKeyArray, boolean isPerm)
@@ -648,7 +1033,7 @@ public class SecureChannelProtocol {
}
SymmetricKey transport = getSharedSecretKey(token);
- unwrapped = this.unwrapSymKeyOnToken(token, transport, inputKeyArray, isPerm);
+ unwrapped = this.unwrapSymKeyOnToken(token, transport, inputKeyArray, isPerm, SymmetricKey.DES3);
CMS.debug(method + "Returning symkey: " + unwrapped);
@@ -710,16 +1095,36 @@ public class SecureChannelProtocol {
public static void debugByteArray(byte[] array, String message) {
CMS.debug("About to dump array: " + message);
+ System.out.println("About to dump array: " + message);
if (array == null) {
CMS.debug("Array to dump is empty!");
return;
}
+ System.out.println("################### ");
CMS.debug("################### ");
String result = getHexString(array);
CMS.debug(result);
+ System.out.println(result);
+ }
+
+ public static void
+ displayByteArray(byte[] ba, boolean has_check_sum) {
+ char mask = 0xff;
+
+ if (has_check_sum == true)
+ mask = 0xfe;
+
+ for (int i = 0; i < ba.length; i++) {
+
+ System.out.print(Integer.toHexString(ba[i] & mask) + " ");
+ if ((i % 26) == 25) {
+ System.out.println("");
+ }
+ }
+ System.out.println("");
}
final protected static char[] hex = "0123456789abcdef".toCharArray();
@@ -815,6 +1220,8 @@ public class SecureChannelProtocol {
}
SymmetricKey des2 = this.extractDes2FromDes3(symKey, devKeyToken);
+ //SecureChannelProtocol.debugByteArray(des2.getEncoded(), method + " raw des2 key, to be wrapped.");
+
result = this.wrapSessionKey(selectedToken, des2, devKey);
// SecureChannelProtocol.debugByteArray(result, " Wrapped des2 key");
@@ -929,25 +1336,93 @@ public class SecureChannelProtocol {
wrapper = wrappingKey;
}
- try {
- CryptoManager cm = this.getCryptoManger();
- CryptoToken token = returnTokenByName(tokenName, cm);
+ CMS.debug(method + " wrapper key type: " + wrapper.getType());
- keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
- keyWrap.initWrap(wrapper, null);
- wrappedSessKeyData = keyWrap.wrap(sessionKey);
- } catch (Exception e) {
- CMS.debug(method + " " + e);
- throw new EBaseException(e);
+ if (wrapper.getType() != SymmetricKey.AES) {
+ CMS.debug(method + "Trying to wrap a key with an DES key!");
+
+ try {
+ CryptoManager cm = this.getCryptoManger();
+ CryptoToken token = returnTokenByName(tokenName, cm);
+
+ keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
+ keyWrap.initWrap(wrapper, null);
+ wrappedSessKeyData = keyWrap.wrap(sessionKey);
+
+ } catch (
+ Exception e) {
+ CMS.debug(method + " " + e);
+ throw new EBaseException(e);
+ }
+
+ } else if (wrapper.getType() == SymmetricKey.AES) {
+ CMS.debug(method + "Trying to wrap a key with an AES key!");
+ try {
+ CryptoManager cm = this.getCryptoManger();
+ CryptoToken token = returnTokenByName(tokenName, cm);
+
+ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
+ byte[] iv = null;
+
+ if (ivLength > 0) {
+ iv = new byte[ivLength]; // all zeroes
+ }
+
+ keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC);
+ keyWrap.initWrap(wrapper, new IVParameterSpec(iv));
+ wrappedSessKeyData = keyWrap.wrap(sessionKey);
+
+
+ } catch (Exception e) {
+ CMS.debug(method + " " + e);
+ throw new EBaseException(e);
+ }
}
- //CMS.debug(method + " About to return session key: " + wrappedSessKeyData);
+
+ //SecureChannelProtocol.debugByteArray(wrappedSessKeyData, "wrappedSessKeyData");
CMS.debug(method + " returning session key");
return wrappedSessKeyData;
}
+ //128 for now.
+ public byte[] computeAES_CBCEncryption(SymmetricKey symKey, String selectedToken, byte[] input, byte[] iv)
+ throws EBaseException
+ {
+ String method = "SecureChannelProtocol.computeAES_CBCEncryption";
+ byte[] output = null;
+ byte[] finalIv = null;
+
+ if (symKey == null || selectedToken == null) {
+ throw new EBaseException(method + " Invalid input data.");
+ }
+
+ if (iv == null) {
+ finalIv = new byte[16];
+
+ } else {
+ finalIv = iv;
+ }
+
+ try {
+ CryptoManager cm = this.getCryptoManger();
+ CryptoToken token = returnTokenByName(selectedToken, cm);
+ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC);
+ encryptor.initEncrypt(symKey, new IVParameterSpec(finalIv));
+ output = encryptor.doFinal(input);
+
+ SecureChannelProtocol.debugByteArray(output, "Encrypted data:");
+ } catch (Exception e) {
+
+ CMS.debug(method + e);
+ throw new EBaseException(method + e);
+ }
+
+ return output;
+ }
+
public byte[] computeDes3EcbEncryption(SymmetricKey desKey, String selectedToken, byte[] input)
throws EBaseException {
@@ -983,6 +1458,61 @@ public class SecureChannelProtocol {
return output;
}
+ //SCP03 uses aes
+ public byte[] computeKeyCheck_SCP03(SymmetricKey symKey, String selectedToken) throws EBaseException {
+
+ String method = "SecureChannelProtocol.computeKeyCheck_SCP03:";
+
+ if (symKey == null || selectedToken == null) {
+ throw new EBaseException(method + " invalid input data!");
+ }
+
+ byte[] key_check_message = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ //zero iv vector
+ byte[] key_check_iv = new byte[16];
+
+ byte[] output = null;
+ byte[] finalOutput = new byte[3];
+
+ try {
+ output = computeAES_CBCEncryption(symKey, selectedToken, key_check_message, key_check_iv);
+ } catch (EBaseException e) {
+ CMS.debug(method + e);
+ throw e;
+
+ }
+
+ //Get the 3 bytes needed
+ System.arraycopy(output, 0, finalOutput, 0, 3);
+
+ //SecureChannelProtocol.debugByteArray(finalOutput, method + " output: ");
+
+ return finalOutput;
+ }
+
+ //AES, uses AES_CMAC alg to do the work.
+ public byte[] computeCryptogram_SCP03(SymmetricKey symKey, String selectedToken, byte[] context, byte cryptoType)
+ throws EBaseException {
+ String method = "SecureChannelProtocol.computeCryptogram_";
+
+ CMS.debug(method + " entering ..");
+
+ if (symKey == null || selectedToken == null || (cryptoType != NistSP800_108KDF.CARD_CRYPTO_KDF_CONSTANT)
+ && cryptoType != NistSP800_108KDF.HOST_CRYPTO_KDF_CONSTANT) {
+ throw new EBaseException(method + " Invalid input data.");
+ }
+
+ NistSP800_108KDF nistKdf = new NistSP800_108KDF(this);
+ byte[] crypto = nistKdf.kdf_AES_CMAC_SCP03(symKey, context, cryptoType, 8);
+ //SecureChannelProtocol.debugByteArray(crypto, " calculated cryptogram");
+
+ byte[] finalCrypto = new byte[8];
+
+ System.arraycopy(crypto, 0, finalCrypto, 0, 8);
+
+ return finalCrypto;
+ }
+
public byte[] computeKeyCheck(SymmetricKey desKey, String selectedToken) throws EBaseException {
String method = "SecureChannelProtocol.computeKeyCheck:";
@@ -1115,6 +1645,9 @@ public class SecureChannelProtocol {
return output;
}
+ //Calculates the 3 new card keys to be written to the token for
+ //Symmetric key changeover. Supports SCP03 now.
+ //Provide all the static developer key arrays should we need them
public byte[] diversifyKey(String tokenName,
String newTokenName,
String oldMasterKeyName,
@@ -1125,12 +1658,18 @@ public class SecureChannelProtocol {
boolean nistSP800_108KdfUseCuidAsKdd,
byte[] CUIDValue,
byte[] KDD,
- byte[] kekKeyArray,
- String useSoftToken, String keySet, byte protocol) throws EBaseException {
+ byte[] kekKeyArray, byte[] encKeyArray, byte[] macKeyArray,
+ String useSoftToken, String keySet, byte protocol, GPParams params) throws EBaseException {
String method = "SecureChannelProtocol.diversifyKey:";
- CMS.debug(method + " Entering ... newTokenName: " + newTokenName);
+ CMS.debug(method + " Entering ... newTokenName: " + newTokenName + " protocol: " + protocol);
+ CMS.debug(method + " oldMasterKeyName: " + oldMasterKeyName);
+ CMS.debug(method + " newMasterKeyName: " + newMasterKeyName);
+
+ SecureChannelProtocol.debugByteArray(encKeyArray, " Developer enc key array: ");
+ SecureChannelProtocol.debugByteArray(macKeyArray, " Developer mac key array: ");
+ SecureChannelProtocol.debugByteArray(kekKeyArray, " Developer kek key array: ");
SymmetricKey masterKey = null;
SymmetricKey oldMasterKey = null;
@@ -1151,7 +1690,7 @@ public class SecureChannelProtocol {
byte[] output = null;
if (oldMasterKeyName == null || oldKeyInfo == null || newKeyInfo == null
- || keySet == null) {
+ || keySet == null || params == null) {
throw new EBaseException(method + "Invalid input!");
}
@@ -1162,6 +1701,9 @@ public class SecureChannelProtocol {
String fullNewMasterKeyName = getFullMasterKeyName(newMasterKeyName);
String fullOldMasterKeyName = getFullMasterKeyName(oldMasterKeyName);
+ CMS.debug(method + " fullOldMasterKeyName: " + fullOldMasterKeyName);
+ CMS.debug(method + " fullNewMasterKeyName: " + fullNewMasterKeyName);
+
CryptoManager cm = null;
CryptoToken token = null;
CryptoToken newToken = null;
@@ -1217,16 +1759,27 @@ public class SecureChannelProtocol {
StandardKDF standardKDF = new StandardKDF(this);
NistSP800_108KDF nistKDF = new NistSP800_108KDF(this);
- KDCenc = KDF.getDiversificationData(KDD, SecureChannelProtocol.encType);
- KDCmac = KDF.getDiversificationData(KDD, SecureChannelProtocol.macType);
- KDCkek = KDF.getDiversificationData(KDD, SecureChannelProtocol.kekType);
+ KDCenc = KDF.getDiversificationData_VISA2(KDD, SecureChannelProtocol.encType);
+ KDCmac = KDF.getDiversificationData_VISA2(KDD, SecureChannelProtocol.macType);
+ KDCkek = KDF.getDiversificationData_VISA2(KDD, SecureChannelProtocol.kekType);
- if (protocol == PROTOCOL_ONE) {
- if (checkForDeveloperKeySet(oldMasterKeyName) == true) {
- CMS.debug(method + " Developer key set case: ");
- } else {
- CMS.debug(method + " Not Developer key set case: ");
+ //This routine does not even support protocol 2, bail if asked to do so.
+ if (protocol == PROTOCOL_TWO) {
+ throw new EBaseException(method + " SCP 02 not yet supported here.");
+ }
+ String transportKeyName = SecureChannelProtocol.getSharedSecretKeyName(null);
+
+ if (checkForDeveloperKeySet(oldMasterKeyName) == true) {
+ //Starting with the deve key set, do nothing in this clause
+ CMS.debug(method + " Developer key set case: protocol: " + protocol);
+ } else {
+ //Case where down grading back to the deve key set, or to another master key set
+ // This clause does nothing but calculate the kek key of the
+ // Current keyset, which will be used to wrap the new keys, to be calculated
+ CMS.debug(method + " Not Developer key set case: ");
+
+ if (protocol == PROTOCOL_ONE ) {
if (NistSP800_108KDF.useThisKDF(nistSP800_108KdfOnKeyVersion, oldKeyVersion)) {
CMS.debug(method + " NistSP800_108KDF code: Using NIST SP800-108 KDF.");
@@ -1252,19 +1805,44 @@ public class SecureChannelProtocol {
old_kek_sym_key = standardKDF.computeCardKey(oldMasterKey, KDCkek, token, PROTOCOL_ONE);
}
- }
+ } else { // Protocol 3
- /* special case #01#01 */
- if (fullNewMasterKeyName != null && fullNewMasterKeyName.equals("#01#01"))
- {
- CMS.debug(method + " Special case dev key set for DiversifyKey!");
+ old_kek_sym_key = this.computeSessionKey_SCP03(tokenName, oldMasterKeyName,
+ oldKeyInfo, SecureChannelProtocol.kekType, kekKeyArray, keySet,
+ CUIDValue, KDD, null, null, transportKeyName, params);
+ CMS.debug(method + " Moving back to the developer key set case, protocol 3");
+ }
+ }
+
+ // Now compute the new keys to be written to the token.
+ /* special case #01#01 */
+ if (fullNewMasterKeyName != null
+ && (fullNewMasterKeyName.equals("#01#01") || fullNewMasterKeyName.contains("#01#03")))
+ {
+ //This is the case where we revert to the original developer key set or key set 1
+ if (protocol == PROTOCOL_ONE) {
+ CMS.debug(method + " Special case returning to the dev key set (1) for DiversifyKey, protocol 1!");
encKey = returnDeveloperSymKey(newToken, SecureChannelProtocol.encType, keySet, null);
macKey = returnDeveloperSymKey(newToken, SecureChannelProtocol.macType, keySet, null);
kekKey = returnDeveloperSymKey(newToken, SecureChannelProtocol.kekType, keySet, null);
- } else {
- CMS.debug(method + " Compute card key on token case ! For new key version");
+ } else if (protocol == PROTOCOL_THREE) {
+ CMS.debug(method + " Special case or returning to the dev key set (or ver 1) for DiversifyKey, protocol 3!");
+ encKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo,
+ SecureChannelProtocol.encType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ macKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo,
+ SecureChannelProtocol.macType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ kekKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo,
+ SecureChannelProtocol.kekType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ }
+ } else {
+ //Compute new card keys for upgraded key set
+ CMS.debug(method + " Compute card key on token case ! For new key version.");
+ if (protocol == PROTOCOL_ONE) {
if (NistSP800_108KDF.useThisKDF(nistSP800_108KdfOnKeyVersion, newKeyVersion)) {
CMS.debug(method + " NistSP800_108KDF code: Using NIST SP800-108 KDF. For new key version.");
@@ -1289,17 +1867,31 @@ public class SecureChannelProtocol {
kekKey = standardKDF.computeCardKeyOnToken(masterKey, KDCkek, protocol);
}
- if (encKey == null || macKey == null || kekKey == null) {
- throw new EBaseException(method
- + " Can't derive session keys with selected KDF. For new key version.");
- }
+ } else { // protocol 3
+ CMS.debug(method + " Generating new card keys to upgrade to, protocol 3.");
+ encKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo,
+ SecureChannelProtocol.encType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ macKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo,
+ SecureChannelProtocol.macType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ kekKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo,
+ SecureChannelProtocol.kekType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+
+ // Generate an old kek key to do the encrypting of the new static keys
+
+ old_kek_sym_key = this.computeSessionKey_SCP03(tokenName, oldMasterKeyName, oldKeyInfo,
+ SecureChannelProtocol.kekType, kekKeyArray,
+ keySet, CUIDValue, KDD, null, null, transportKeyName, params);
+ }
+
+ if (encKey == null || macKey == null || kekKey == null) {
+ throw new EBaseException(method
+ + " Can't derive session keys with selected KDF. For new key version.");
}
- } else if (protocol == PROTOCOL_TWO) {
- throw new EBaseException(method + " SCP 02 not yet supported here.");
- } else {
- throw new EBaseException(method + " Unsupported protocol verison.");
}
boolean showKeysForDebug = false;
@@ -1327,7 +1919,9 @@ public class SecureChannelProtocol {
} else {
CMS.debug(method + " old kek sym key is null");
+
old_kek_sym_key = returnDeveloperSymKey(token, SecureChannelProtocol.kekType, keySet, kekKeyArray);
+
output = createKeySetDataWithSymKeys(newKeyVersion, (byte[]) null,
old_kek_sym_key,
encKey,
@@ -1340,6 +1934,8 @@ public class SecureChannelProtocol {
return output;
}
+ //Create the actual blob of new keys to be written to the token
+ // Suports prot1 and prot3
private byte[] createKeySetDataWithSymKeys(byte newKeyVersion, byte[] old_kek_key_array,
SymmetricKey old_kek_sym_key,
SymmetricKey encKey, SymmetricKey macKey, SymmetricKey kekKey, byte protocol, String tokenName)
@@ -1392,6 +1988,8 @@ public class SecureChannelProtocol {
wrappingKey = old_kek_sym_key;
}
+ CMS.debug(method + "Wrapping key: length: " + wrappingKey.getLength());
+
alg = (byte) 0x81;
encKey16 = extractDes2FromDes3(encKey, tokenName);
macKey16 = extractDes2FromDes3(macKey, tokenName);
@@ -1404,23 +2002,48 @@ public class SecureChannelProtocol {
keycheck_enc_key = this.computeKeyCheck(encKey, tokenName);
keycheck_mac_key = this.computeKeyCheck(macKey, tokenName);
keycheck_kek_key = this.computeKeyCheck(kekKey, tokenName);
- /*
- debugByteArray(keycheck_enc_key, " Keycheck enc key: ");
- debugByteArray(keycheck_mac_key, " Keycheck mac key: ");
- debugByteArray(keycheck_kek_key, " KeyCheck kek key: ");
- */
} else if (protocol == PROTOCOL_TWO) {
- alg = (byte) 0x80;
throw new EBaseException(method + " SCP 02 not yet implemented!");
+ } else if (protocol == PROTOCOL_THREE) {
+ CMS.debug(method + " Attempting SCP03");
+
+ if (old_kek_sym_key == null) {
+ CMS.debug(method + " SCP03: Using old kek key array.");
+ wrappingKey = unwrapAESSymKeyOnToken(token, old_kek_key_array, false);
+ } else {
+ CMS.debug(method + "SCP03: Using input old key key sym key.");
+ wrappingKey = old_kek_sym_key;
+ }
+
+ alg = (byte) 0x88;
+
+ encrypted_enc_key = this.wrapSessionKey(tokenName, encKey, wrappingKey);
+ encrypted_mac_key = this.wrapSessionKey(tokenName, macKey, wrappingKey);
+ encrypted_kek_key = this.wrapSessionKey(tokenName, kekKey, wrappingKey);
+
+ keycheck_enc_key = this.computeKeyCheck_SCP03(encKey, tokenName);
+ keycheck_mac_key = this.computeKeyCheck_SCP03(macKey, tokenName);
+ keycheck_kek_key = this.computeKeyCheck_SCP03(kekKey, tokenName);
+
} else {
throw new EBaseException(method + " Invalid SCP version requested!");
}
// Compose the final key set data byte array
- byte[] b1 = new byte[] { alg, 0x10 };
- byte[] b2 = new byte[] { 0x3 };
+ byte[] b1 = null;
+ byte[] b2 = null;
+
+ if (protocol == PROTOCOL_THREE) {
+ //Will be different if the key is bigger than AES 128
+ // Support 128 for now
+ b1 = new byte[] { alg, 0x11, (byte) encrypted_enc_key.length };
+ } else {
+ b1 = new byte[] { alg, 0x10 };
+ }
+
+ b2 = new byte[] { 0x3 };
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
@@ -1484,6 +2107,10 @@ public class SecureChannelProtocol {
if (keyInfo.equals("#01#02") || keyInfo.equals("#FF#02"))
return true;
+ //SCP03
+ if (keyInfo.contains("#01#03") || keyInfo.contains("#FF#03"))
+ return true;
+
return false;
}
@@ -1493,6 +2120,42 @@ public class SecureChannelProtocol {
}
}
+
+ //SCP03 wrap a session key with AES kek key.
+ public byte[] encryptData_SCP03(String selectedToken, String keyNickName, byte[] data, byte[] keyInfo,
+ byte nistSP800_108KdfOnKeyVersion, boolean nistSP800_108KdfUseCuidAsKdd, byte[] xCUID, byte[] xKDD,
+ byte[] kekKeyArray, String useSoftToken_s, String keySet, GPParams params) throws EBaseException {
+
+ String method = "SecureChannelProtocol.encryptData_SCP03:";
+
+ CMS.debug(method + " Entering ....");
+
+ String transportKeyName = SecureChannelProtocol.getSharedSecretKeyName(null);
+
+ if (keyInfo == null || keySet == null || (keyInfo == null || keyInfo.length < 2) || params == null) {
+ throw new EBaseException(method + "Invalid input!");
+ }
+
+ if (xCUID == null || xCUID.length <= 0) {
+ throw new EBaseException(method + "CUID invalid size!");
+ }
+
+ if (xKDD == null || xKDD.length != NistSP800_108KDF.KDD_SIZE_BYTES) {
+ throw new EBaseException(method + "KDD invalid size!");
+ }
+
+ SymmetricKey kekKey = computeSessionKey_SCP03(selectedToken, keyNickName,
+ keyInfo, kekType, kekKeyArray, keySet, xCUID, xKDD,
+ null, null, transportKeyName, params);
+
+ byte[] output = null;
+ output = computeAES_CBCEncryption(kekKey, selectedToken, data, null);
+
+ debugByteArray(output, method + " encryptData: Output: ");
+
+ return output;
+ }
+
public byte[] encryptData(String selectedToken, String keyNickName, byte[] data, byte[] keyInfo,
byte nistSP800_108KdfOnKeyVersion, boolean nistSP800_108KdfUseCuidAsKdd, byte[] xCUID, byte[] xKDD,
byte[] kekKeyArray, String useSoftToken_s, String keySet) throws EBaseException {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java
index 1d61a465d..8c228a15c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/StandardKDF.java
@@ -19,6 +19,39 @@ public class StandardKDF extends KDF {
this.protocol = protocol;
}
+ // For the scp03 g&d smart cafe, the dev keys must start out as DES3 keys
+ // but then this routine must return the AES version of the key
+
+ public SymmetricKey computeCardKey_SCP03_WithDES3(SymmetricKey masterKey, byte[] derivationData, CryptoToken token)
+ throws EBaseException {
+
+ String method = "StandardKDF.computeCardKey_SCP03_WithDES3:";
+
+ CMS.debug(method + " entering ...");
+
+ if (masterKey == null || token == null
+ || derivationData == null || ((derivationData.length != SecureChannelProtocol.AES_128_BYTES) &&
+ (derivationData.length != SecureChannelProtocol.AES_192_BYTES) &&
+ (derivationData.length != SecureChannelProtocol.AES_256_BYTES))) {
+
+ CMS.debug(method + " Invalid input parameters!");
+
+ throw new EBaseException(method + " Invalid input parameters!");
+ }
+
+ //Now the new key data is the derivation data encrypted with DESS3
+
+ byte[] encrypted;
+ try {
+ encrypted = this.protocol.computeDes3EcbEncryption(masterKey, token.getName(), derivationData);
+ } catch (TokenException e) {
+ throw new EBaseException(method + "Can't derive key data!");
+ }
+ //SecureChannelProtocol.debugByteArray(encrypted, "calculated key: ");
+
+ return this.protocol.unwrapAESSymKeyOnToken(token, encrypted, false);
+
+ }
public SymmetricKey computeCardKey(SymmetricKey masterKey, byte[] derivationData, CryptoToken token, int protocol)
throws EBaseException {
@@ -54,12 +87,14 @@ public class StandardKDF extends KDF {
CMS.debug(method + "Now try this the old fashioned way");
byte[] encrypted = this.protocol.computeDes3EcbEncryption(masterKey, token.getName(), derivationData);
- byte[] parityEncrypted = KDF.getDesParity(encrypted);
+ SecureChannelProtocol.debugByteArray(encrypted, "calculated key: ");
+ // byte[] parityEncrypted = KDF.getDesParity(encrypted);
CMS.debug(method + "done computeDes3EcbEncryptiong");
+
derivedKey = this.protocol.unwrapSymKeyOnToken(token, null,
- parityEncrypted, false);
+ encrypted, false,SymmetricKey.DES3);
- // The key this way is aleady des3, return
+ // The key this way is already final, return
return derivedKey;
}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
index a282cd26f..6a1746616 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.servlet.ServletConfig;
@@ -1570,8 +1571,11 @@ public class TokenServlet extends CMSServlet {
return cs.getString("tks.tksSharedSymKeyName", TRANSPORT_KEY_NAME);
}
+ //Accepts protocol param and supports scp03.
private void processDiversifyKey(HttpServletRequest req,
HttpServletResponse resp) throws EBaseException {
+
+ String method = "TokenServlet.processDiversifyKey: ";
byte[] KeySetData, xCUID, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
// AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
@@ -1609,6 +1613,9 @@ public class TokenServlet extends CMSServlet {
String rProtocol = req.getParameter(IRemoteRequest.CHANNEL_PROTOCOL);
String rWrappedDekKey = req.getParameter(IRemoteRequest.WRAPPED_DEK_SESSION_KEY);
+
+ CMS.debug(method + "rWrappedDekKey: " + rWrappedDekKey);
+
int protocol = 1;
String auditMessage = "";
@@ -1670,13 +1677,13 @@ public class TokenServlet extends CMSServlet {
if (!missingParam) {
xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(oldMasterKeyName);
- if (xkeyInfo == null || xkeyInfo.length != 2) {
+ if (xkeyInfo == null || (xkeyInfo.length != 2 && xkeyInfo.length != 3)) {
badParams += " KeyInfo length,";
CMS.debug("TokenServlet: Invalid key info length");
missingParam = true;
}
xnewkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(newMasterKeyName);
- if (xnewkeyInfo == null || xnewkeyInfo.length != 2) {
+ if (xnewkeyInfo == null || (xnewkeyInfo.length != 2 && xnewkeyInfo.length != 3)) {
badParams += " NewKeyInfo length,";
CMS.debug("TokenServlet: Invalid new key info length");
missingParam = true;
@@ -1692,7 +1699,6 @@ public class TokenServlet extends CMSServlet {
CMS.debug("process DiversifyKey: protocol value: " + protocol);
if (protocol == 2) {
-
if ((rWrappedDekKey == null) || (rWrappedDekKey.equals(""))) {
badParams += " WrappedDekKey,";
CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: WrappedDekKey, with SCP02.");
@@ -1766,7 +1772,12 @@ public class TokenServlet extends CMSServlet {
if (mNewKeyNickName != null)
newMasterKeyName = mNewKeyNickName;
- String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + req.getParameter(IRemoteRequest.TOKEN_KEYINFO); //#xx#xx
+ String tokKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
+
+ // Get the first 6 characters, since scp03 gives us extra characters.
+ tokKeyInfo = tokKeyInfo.substring(0,6);
+ String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + tokKeyInfo; //#xx#xx
+ CMS.debug(method + " oldKeyInfoMap: " + oldKeyInfoMap);
String oldMappingValue = CMS.getConfigStore().getString(oldKeyInfoMap, null);
String oldSelectedToken = null;
if (oldMappingValue == null) {
@@ -1778,7 +1789,9 @@ public class TokenServlet extends CMSServlet {
oldKeyNickName = st.nextToken();
}
- String newKeyInfoMap = "tks.mk_mappings." + rnewKeyInfo; //#xx#xx
+
+ String newKeyInfoMap = "tks.mk_mappings." + rnewKeyInfo.substring(0,6); //#xx#xx
+ CMS.debug(method + " newKeyInfoMap: " + newKeyInfoMap);
String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null);
String newSelectedToken = null;
if (newMappingValue == null) {
@@ -1795,14 +1808,22 @@ public class TokenServlet extends CMSServlet {
" oldKeyNickName=" + oldKeyNickName + " newKeyNickName=" +
newKeyNickName);
- byte kekKeyArray[] =
- com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
+ byte kekKeyArray[] = getDeveKeyArray("kek_key", sconfig, keySet);
+ byte macKeyArray[] = getDeveKeyArray("auth_key", sconfig, keySet);
+ byte encKeyArray[] = getDeveKeyArray("mac_key", sconfig, keySet);
+
+ // com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
+
+ //GPParams for scp03 right now, reads some scp03 specific values from the config of a given keyset
+ // passed down to the SecureChannelProtocol functions that deal with SCP03
+
+ GPParams gp3Params = readGPSettings(keySet);
- SecureChannelProtocol secProtocol = new SecureChannelProtocol();
+ SecureChannelProtocol secProtocol = new SecureChannelProtocol(protocol);
// AC: KDF SPEC CHANGE - check for error reading settings
if (missingSetting_exception == null) {
- if (protocol == 1) {
- KeySetData = secProtocol.diversifyKey(oldSelectedToken,
+ if (protocol == 1 || protocol == 3) {
+ KeySetData = secProtocol.diversifyKey(oldSelectedToken,
newSelectedToken, oldKeyNickName,
newKeyNickName,
xkeyInfo, // AC: KDF SPEC CHANGE - pass in old key info so symkey can make decision about which KDF version to use
@@ -1811,7 +1832,7 @@ public class TokenServlet extends CMSServlet {
nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- (protocol == 2) ? xWrappedDekKey : kekKeyArray, useSoftToken_s, keySet, (byte) protocol);
+ kekKeyArray,encKeyArray,macKeyArray, useSoftToken_s, keySet, (byte) protocol,gp3Params);
} else if (protocol == 2) {
KeySetData = SessionKey.DiversifyKey(oldSelectedToken, newSelectedToken, oldKeyNickName,
@@ -1954,6 +1975,8 @@ public class TokenServlet extends CMSServlet {
String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
+ String protocolValue = req.getParameter(IRemoteRequest.CHANNEL_PROTOCOL);
+
// AC: KDF SPEC CHANGE - read new KDD parameter from TPS
String rKDD = req.getParameter("KDD");
if ((rKDD == null) || (rKDD.length() == 0)) {
@@ -1996,6 +2019,8 @@ public class TokenServlet extends CMSServlet {
s_isRandom);
audit(auditMessage);
+ GPParams gp3Params = readGPSettings(keySet);
+
if (isRandom) {
if ((rdata == null) || (rdata.equals(""))) {
CMS.debug("TokenServlet: processEncryptData(): no data in request. Generating random number as data");
@@ -2058,7 +2083,7 @@ public class TokenServlet extends CMSServlet {
}
xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
- if (xkeyInfo == null || xkeyInfo.length != 2) {
+ if (xkeyInfo == null || (xkeyInfo.length != 2 && xkeyInfo.length != 3)) {
badParams += " KeyInfo length,";
CMS.debug("TokenServlet: Invalid key info length");
missingParam = true;
@@ -2103,7 +2128,7 @@ public class TokenServlet extends CMSServlet {
data = com.netscape.cmsutil.util.Utils.SpecialDecode(rdata);
keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
- String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo;
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo.substring(0,6);
String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
if (mappingValue == null) {
selectedToken = CMS.getConfigStore().getString("tks.defaultSlot", CryptoUtil.INTERNAL_TOKEN_NAME);
@@ -2114,20 +2139,53 @@ public class TokenServlet extends CMSServlet {
keyNickName = st.nextToken();
}
+
+ //calculate the protocol
+
+ int protocolInt = SecureChannelProtocol.PROTOCOL_ONE;
+ try
+ {
+ protocolInt = Integer.parseInt(protocolValue);
+ }
+ catch (NumberFormatException nfe)
+ {
+ protocolInt = SecureChannelProtocol.PROTOCOL_ONE;
+ }
+
+ CMS.debug( "TokenServerlet.encryptData: protocol input: " + protocolInt);
+
+ //Check for reasonable sanity, leave room for future versions
+ if(protocolInt <= 0 || protocolInt > 20) {
+ CMS.debug( "TokenServerlet.encryptData: unfamliar protocl, assume default of 1.");
+ protocolInt = 1;
+
+ }
+
byte kekKeyArray[] =
com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
// AC: KDF SPEC CHANGE - check for error reading settings
if (missingSetting_exception == null) {
- SecureChannelProtocol protocol = new SecureChannelProtocol();
- encryptedData = protocol.encryptData(
- selectedToken, keyNickName, data, keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- kekKeyArray, useSoftToken_s, keySet);
+ SecureChannelProtocol protocol = new SecureChannelProtocol(protocolInt);
+
+ if (protocolInt != SecureChannelProtocol.PROTOCOL_THREE) {
+
+ encryptedData = protocol.encryptData(
+ selectedToken, keyNickName, data, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ kekKeyArray, useSoftToken_s, keySet);
+
+ } else {
+
+ encryptedData = protocol.encryptData_SCP03(selectedToken, keyNickName, data, xkeyInfo,
+ nistSP800_108KdfOnKeyVersion, nistSP800_108KdfUseCuidAsKdd, xCUID, xKDD, kekKeyArray,
+ useSoftToken_s, keySet,gp3Params);
+
+ }
SecureChannelProtocol.debugByteArray(encryptedData, "New Encrypt Data: ");
@@ -2402,7 +2460,7 @@ public class TokenServlet extends CMSServlet {
//CMS.debug("Protocol: " + protocol + " temp: " + temp);
setDefaultSlotAndKeyName(req);
- if (temp != null) {
+ if (temp != null && protocol == null) {
processComputeSessionKey(req, resp);
} else if (req.getParameter(IRemoteRequest.TOKEN_DATA) != null) {
processEncryptData(req, resp);
@@ -2413,10 +2471,515 @@ public class TokenServlet extends CMSServlet {
} else if (protocol != null && protocol.contains("2") && (derivationConstant != null)) {
//SCP02 compute one session key.
processComputeSessionKeySCP02(req, resp);
+
+ } else if (protocol != null && protocol.contains("3") ) {
+ processComputeSessionKeysSCP03(req,resp);
} else {
throw new EBaseException("Process: Can't decide upon function to call!");
+ }
+ }
+
+ //Create all the session keys for scp03 at once and return.
+ //ToDo: calcualte the optional rmac key
+ private void processComputeSessionKeysSCP03(HttpServletRequest req, HttpServletResponse resp) throws EBaseException {
+ String method = "processComputeSessionKeysSCP03:";
+ CMS.debug(method + " entering ...");
+
+ byte[] card_challenge, host_challenge, xCUID, xKDD;
+ byte[] card_crypto, host_cryptogram, input_card_crypto;
+ byte[] xcard_challenge, xhost_challenge;
+ byte[] enc_session_key, xkeyInfo,mac_session_key, kek_session_key;
+ String auditMessage = null;
+ String errorMsg = "";
+ String badParams = "";
+ String transportKeyName = "";
+ String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
+
+ String rKDD = req.getParameter("KDD");
+ if ((rKDD == null) || (rKDD.length() == 0)) {
+ // KDF phase1: default to rCUID if not present
+ CMS.debug("TokenServlet: KDD not supplied, set to CUID before TPS change");
+ rKDD = rCUID;
+ }
+
+ String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+ CMS.debug("keySet selected: " + keySet);
+
+ GPParams gp3Params = readGPSettings(keySet);
+
+ boolean serversideKeygen = false;
+
+ IConfigStore sconfig = CMS.getConfigStore();
+ boolean isCryptoValidate = true;
+ boolean missingParam = false;
+
+ Exception missingSetting_exception = null;
+
+ mac_session_key = null;
+ kek_session_key = null;
+ card_crypto = null;
+ host_cryptogram = null;
+ enc_session_key = null;
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST,
+ rCUID,
+ rKDD,
+ ILogger.SUCCESS,
+ agentId);
+
+ audit(auditMessage);
+
+ String kek_wrapped_desKeyString = null;
+ String keycheck_s = null;
+
+ String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
+ if (!useSoftToken_s.equalsIgnoreCase("true"))
+ useSoftToken_s = "false";
+
+ CMS.debug(method + " useSoftToken: " + useSoftToken_s);
+
+ String rServersideKeygen = req.getParameter(IRemoteRequest.SERVER_SIDE_KEYGEN);
+ if (rServersideKeygen.equals("true")) {
+
+ serversideKeygen = true;
+ }
+
+ CMS.debug(method + " serversideKeygen: " + serversideKeygen);
+
+ try {
+ isCryptoValidate = sconfig.getBoolean("cardcryptogram.validate.enable", true);
+ } catch (EBaseException eee) {
+ }
+
+ CMS.debug(method + " Do crypto validation: " + isCryptoValidate);
+
+ transportKeyName = getSharedSecretName(sconfig);
+
+ String rcard_challenge = req.getParameter(IRemoteRequest.TOKEN_CARD_CHALLENGE);
+ String rhost_challenge = req.getParameter(IRemoteRequest.TOKEN_HOST_CHALLENGE);
+ String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
+ String rcard_cryptogram = req.getParameter(IRemoteRequest.TOKEN_CARD_CRYPTOGRAM);
+
+ if ((rCUID == null) || (rCUID.equals(""))) {
+ CMS.debug(method + " missing request parameter: CUID");
+ badParams += " CUID,";
+ missingParam = true;
+ }
+
+ if ((rKDD == null) || (rKDD.length() == 0)) {
+ CMS.debug(method + " missing request parameter: KDD");
+ badParams += " KDD,";
+ missingParam = true;
+ }
+
+ if ((rcard_challenge == null) || (rcard_challenge.equals(""))) {
+ badParams += " card_challenge,";
+ CMS.debug(method + " missing request parameter: card challenge");
+ missingParam = true;
+ }
+
+ if ((rhost_challenge == null) || (rhost_challenge.equals(""))) {
+ badParams += " host_challenge,";
+ CMS.debug(method + " missing request parameter: host challenge");
+ missingParam = true;
+ }
+
+ if ((rcard_cryptogram == null) || (rcard_cryptogram.equals(""))) {
+ badParams += " card_cryptogram,";
+ CMS.debug(method + " missing request parameter: card_cryptogram");
+ missingParam = true;
+ }
+
+ if ((rKeyInfo == null) || (rKeyInfo.equals(""))) {
+ badParams += " KeyInfo,";
+ CMS.debug(method + "missing request parameter: key info");
+ missingParam = true;
+ }
+
+ String selectedToken = null;
+ String keyNickName = null;
+ boolean sameCardCrypto = true;
+
+ xCUID = null;
+ xKDD = null;
+ xkeyInfo = null;
+ xcard_challenge = null;
+ xhost_challenge = null;
+
+ if (!missingParam) {
+ xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+ if (xCUID == null || xCUID.length != 10) {
+ badParams += " CUID length,";
+ CMS.debug("TokenServlet: Invalid CUID length");
+ missingParam = true;
+ }
+
+ xKDD = com.netscape.cmsutil.util.Utils.SpecialDecode(rKDD);
+ if (xKDD == null || xKDD.length != 10) {
+ badParams += " KDD length,";
+ CMS.debug("TokenServlet: Invalid KDD length");
+ missingParam = true;
+ }
+
+ xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+ if (xkeyInfo == null || xkeyInfo.length != 3) {
+ badParams += " KeyInfo length,";
+ CMS.debug("TokenServlet: Invalid key info length.");
+ missingParam = true;
+ }
+ xcard_challenge =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge);
+ if (xcard_challenge == null || xcard_challenge.length != 8) {
+ badParams += " card_challenge length,";
+ CMS.debug("TokenServlet: Invalid card challenge length.");
+ missingParam = true;
+ }
+
+ xhost_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge);
+ if (xhost_challenge == null || xhost_challenge.length != 8) {
+ badParams += " host_challenge length,";
+ CMS.debug("TokenServlet: Invalid host challenge length");
+ missingParam = true;
+ }
+ }
+
+ ArrayList<String> serverSideValues = null;
+
+ if (!missingParam) {
+ card_challenge =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge);
+
+ host_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge);
+
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo.substring(0,6); //#xx#xx
+ String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+
+
+ if (mappingValue == null) {
+ selectedToken =
+ CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ keyNickName = rKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ if (st.hasMoreTokens())
+ selectedToken = st.nextToken();
+ if (st.hasMoreTokens())
+ keyNickName = st.nextToken();
+ }
+
+ CMS.debug(method + " selectedToken: " + selectedToken + " keyNickName: " + keyNickName );
+
+ SymmetricKey macSessionKey = null;
+ SymmetricKey encSessionKey = null;
+ SymmetricKey kekSessionKey = null;
+
+ if (selectedToken != null && keyNickName != null
+ && missingSetting_exception == null) {
+
+ try {
+
+ byte macKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".mac_key"));
+ CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken="
+ + selectedToken + " keyNickName=" + keyNickName);
+
+ SecureChannelProtocol protocol = new SecureChannelProtocol(SecureChannelProtocol.PROTOCOL_THREE);
+
+ macSessionKey = protocol.computeSessionKey_SCP03(selectedToken, keyNickName,xkeyInfo,
+ SecureChannelProtocol.macType, macKeyArray, keySet,xCUID, xKDD, xhost_challenge, xcard_challenge,
+ transportKeyName,gp3Params);
+
+ mac_session_key = protocol.wrapSessionKey(selectedToken, macSessionKey, null);
+
+ if (mac_session_key == null) {
+ CMS.debug(method + " Can't get mac session key bytes");
+ throw new Exception(method + " Can't get mac session key bytes");
+
+ }
+
+ byte encKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".auth_key"));
+
+ encSessionKey = protocol.computeSessionKey_SCP03(selectedToken, keyNickName,xkeyInfo,
+ SecureChannelProtocol.encType, encKeyArray, keySet, xCUID, xKDD, xhost_challenge, xcard_challenge,
+ transportKeyName,gp3Params);
+
+ enc_session_key = protocol.wrapSessionKey(selectedToken, encSessionKey, null);
+
+ if (enc_session_key == null) {
+ CMS.debug("TokenServlet:Tried ComputeEncSessionKey, got NULL ");
+ throw new Exception("Can't compute enc session key!");
+
+ }
+
+ byte kekKeyArray[] =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".kek_key"));
+
+ kekSessionKey = protocol.computeSessionKey_SCP03(selectedToken, keyNickName, xkeyInfo,
+ SecureChannelProtocol.kekType, kekKeyArray, keySet, xCUID, xKDD, xhost_challenge,
+ xcard_challenge,
+ transportKeyName,gp3Params);
+
+ kek_session_key = protocol.wrapSessionKey(selectedToken, kekSessionKey, null);
+
+
+ //Offload some of the tedious params gathering to another method
+ //ToDo, create a method that reads all this stuff at once for all major methods
+ if (serversideKeygen) {
+ try {
+ serverSideValues = calculateServerSideKeygenValues(useSoftToken_s, selectedToken,
+ kekSessionKey, protocol);
+ } catch (EBaseException e) {
+
+ CMS.debug(method + " Can't calcualte server side keygen required values...");
+
+ }
+ }
+
+ try {
+ isCryptoValidate = sconfig.getBoolean("cardcryptogram.validate.enable", true);
+ } catch (EBaseException eee) {
+ }
+
+ ByteArrayOutputStream contextStream = new ByteArrayOutputStream();
+ try {
+ contextStream.write(host_challenge);
+ contextStream.write(card_challenge);
+ } catch (IOException e) {
+ throw new EBaseException(method + " Error calculating derivation data!");
+ }
+
+ host_cryptogram = protocol.computeCryptogram_SCP03(macSessionKey, selectedToken, contextStream.toByteArray(),NistSP800_108KDF.HOST_CRYPTO_KDF_CONSTANT);
+ SecureChannelProtocol.debugByteArray(host_cryptogram, method + " calculated host crypto: " + host_cryptogram.length);
+
+
+ if( isCryptoValidate) {
+ if (rcard_cryptogram == null) {
+ CMS.debug(method + " missing card cryptogram");
+ throw new Exception(method + "Missing card cryptogram");
+ }
+ input_card_crypto =
+ com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_cryptogram);
+ card_crypto = protocol.computeCryptogram_SCP03(macSessionKey, selectedToken, contextStream.toByteArray(),NistSP800_108KDF.CARD_CRYPTO_KDF_CONSTANT);
+ SecureChannelProtocol.debugByteArray(card_crypto, method + " calculated card crypto: ");
+ SecureChannelProtocol.debugByteArray(input_card_crypto, method + " original card crypto: ");
+
+ if(!cryptoGramsAreEqual(input_card_crypto, card_crypto)) {
+ throw new Exception(method + "Card cryptogram mismatch!");
+ }
+
+ }
+ } catch (Exception e) {
+ CMS.debug(e);
+ CMS.debug("TokenServlet Computing Session Key: " + e.toString());
+ if (isCryptoValidate)
+ sameCardCrypto = false;
+ }
+ }
+ } // ! missingParam
+
+ String value = "";
+
+ resp.setContentType("text/html");
+
+ String encSessionKeyString = "";
+ String macSessionKeyString = "";
+ String kekSessionKeyString = "";
+
+ String drm_trans_wrapped_desKeyString = "";
+ String cryptogram = "";
+ String status = "0";
+
+ if (enc_session_key != null && enc_session_key.length > 0) {
+ encSessionKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(enc_session_key);
+ } else {
+ status = "1";
+ }
+
+ if (mac_session_key != null && mac_session_key.length > 0) {
+ macSessionKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(mac_session_key);
+ } else {
+ status = "1";
+ }
+
+ if (kek_session_key != null && kek_session_key.length > 0) {
+ kekSessionKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(kek_session_key);
+ } else {
+ status = "1";
+ }
+
+ if (serversideKeygen == true) {
+ if (serverSideValues.size() == 3) {
+ drm_trans_wrapped_desKeyString = serverSideValues.get(2);
+ kek_wrapped_desKeyString = serverSideValues.get(0);
+ keycheck_s = serverSideValues.get(1);
+ }
+ else {
+ status = "1";
+ }
+ }
+ if (host_cryptogram != null && host_cryptogram.length > 0) {
+ cryptogram =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(host_cryptogram);
+ } else {
+ if (status.equals("0") == true) {
+ status = "2";
+ }
+ }
+
+ if (selectedToken == null || keyNickName == null) {
+ // AC: Bugfix: Don't override status's value if an error was already flagged
+ if (status.equals("0") == true) {
+ status = "4";
+ }
}
+
+ if (!sameCardCrypto) {
+ if (status.equals("0") == true) {
+ status = "5";
+ }
+ }
+
+ if (missingSetting_exception != null) {
+ status = "6";
+ }
+
+ if (missingParam) {
+ status = "3";
+ }
+
+ if (!status.equals("0")) {
+
+ if (status.equals("1")) {
+ errorMsg = "Problem generating session key info.";
+ }
+
+ if (status.equals("2")) {
+ errorMsg = "Problem creating host_cryptogram.";
+ }
+
+ if (status.equals("5")) {
+ errorMsg = "Card cryptogram mismatch. Token likely has incorrect keys.";
+ }
+
+ if (status.equals("4")) {
+ errorMsg = "Problem obtaining token information.";
+ }
+
+ if (status.equals("6")) {
+ errorMsg = "Problem reading required configuration value.";
+ }
+
+ if (status.equals("3")) {
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters :" + badParams;
+ }
+
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
+ } else {
+ if (serversideKeygen == true) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_MacSessionKey + "=");
+ sb.append(macSessionKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_HostCryptogram + "=");
+ sb.append(cryptogram);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_EncSessionKey + "=");
+ sb.append(encSessionKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KekSessionKey + "=");
+ sb.append(kekSessionKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_DesKey + "=");
+ sb.append(kek_wrapped_desKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "=");
+ sb.append(keycheck_s);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "=");
+ sb.append(drm_trans_wrapped_desKeyString);
+ value = sb.toString();
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_MacSessionKey + "=");
+ sb.append(macSessionKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_HostCryptogram + "=");
+ sb.append(cryptogram);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_EncSessionKey + "=");
+ sb.append(encSessionKeyString);
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KekSessionKey + "=");
+ value = sb.toString();
+ }
+
+ }
+ //CMS.debug(method + "outputString.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServlet:outputString.length " + value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (IOException e) {
+ CMS.debug("TokenServlet: " + e.toString());
+ }
+
+ if (status.equals("0")) {
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.SUCCESS, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS,
+ logParams);
+
+ } else {
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.FAILURE, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ errorMsg // Error
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,
+ logParams);
+
+ }
+
+ audit(auditMessage);
+
}
/**
@@ -2479,4 +3042,197 @@ public class TokenServlet extends CMSServlet {
}
+ //returns ArrayList of following values
+ // 0 : Kek wrapped des key
+ // 1 : keycheck value
+ // 2 : trans wrapped des key
+ private ArrayList<String> calculateServerSideKeygenValues(String useSoftToken, String selectedToken,
+ SymmetricKey kekSessionKey, SecureChannelProtocol protocol) throws EBaseException {
+
+ SymmetricKey desKey = null;
+ String method = "TokenServlet.calculateSErverSideKeygenValues: ";
+ ArrayList<String> values = new ArrayList<String>();
+
+ /**
+ * 0. generate des key
+ * 1. encrypt des key with kek key
+ * 2. encrypt des key with DRM transport key
+ * These two wrapped items are to be sent back to
+ * TPS. 2nd item is to DRM
+ **/
+ CMS.debug(method + " entering...");
+
+ // (1) generate DES key
+ /* applet does not support DES3
+ org.mozilla.jss.crypto.KeyGenerator kg =
+ internalToken.getKeyGenerator(KeyGenAlgorithm.DES3);
+ desKey = kg.generate();*/
+
+ /*
+ * GenerateSymkey firt generates a 16 byte DES2 key.
+ * It then pads it into a 24 byte key with last
+ * 8 bytes copied from the 1st 8 bytes. Effectively
+ * making it a 24 byte DES2 key. We need this for
+ * wrapping private keys on DRM.
+ */
+ /*generate it on whichever token the master key is at*/
+
+ if (useSoftToken.equals("true")) {
+ CMS.debug(method + " key encryption key generated on internal");
+ desKey = protocol.generateSymKey("internal");
+ //cfu audit here? sym key gen done
+ } else {
+ CMS.debug("TokenServlet: key encryption key generated on " + selectedToken);
+ desKey = protocol.generateSymKey(selectedToken);
+ }
+ if (desKey == null) {
+ throw new EBaseException(method + "can't generate key encryption key");
+ }
+
+ /*
+ * ECBencrypt actually takes the 24 byte DES2 key
+ * and discard the last 8 bytes before it encrypts.
+ * This is done so that the applet can digest it
+ */
+
+
+ // protocol.wrapSessionKey(tokenName, sessionKey, wrappingKey)
+
+ byte[] encDesKey = protocol.ecbEncrypt(kekSessionKey, desKey, selectedToken);
+
+ String kek_wrapped_desKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey);
+
+ CMS.debug(method + "kek_wrapped_desKeyString: " + kek_wrapped_desKeyString);
+
+ values.add(kek_wrapped_desKeyString);
+
+ // get keycheck
+
+ byte[] keycheck = null;
+
+ keycheck = protocol.computeKeyCheck(desKey, selectedToken);
+
+ String keycheck_s =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck);
+
+ CMS.debug(method + "keycheck_s " + keycheck_s);
+
+ values.add(keycheck_s);
+
+ //use DRM transport cert to wrap desKey
+ String drmTransNickname = CMS.getConfigStore().getString("tks.drm_transport_cert_nickname", "");
+
+ if ((drmTransNickname == null) || (drmTransNickname == "")) {
+ CMS.debug(method + " did not find DRM transport certificate nickname");
+ throw new EBaseException(method + "can't find DRM transport certificate nickname");
+ } else {
+ CMS.debug(method + " drmtransport_cert_nickname=" + drmTransNickname);
+ }
+
+ X509Certificate drmTransCert = null;
+ try {
+
+ drmTransCert = CryptoManager.getInstance().findCertByNickname(drmTransNickname);
+ // wrap kek session key with DRM transport public key
+ CryptoToken token = null;
+ if (useSoftToken.equals("true")) {
+ //token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ token = CryptoManager.getInstance().getInternalCryptoToken();
+ } else {
+ token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ }
+ PublicKey pubKey = drmTransCert.getPublicKey();
+ String pubKeyAlgo = pubKey.getAlgorithm();
+ CMS.debug("Transport Cert Key Algorithm: " + pubKeyAlgo);
+ KeyWrapper keyWrapper = null;
+ //For wrapping symmetric keys don't need IV, use ECB
+ if (pubKeyAlgo.equals("EC")) {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB);
+ keyWrapper.initWrap(pubKey, null);
+ } else {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
+ keyWrapper.initWrap(pubKey, null);
+ }
+ CMS.debug("desKey token " + desKey.getOwningToken().getName() + " token: " + token.getName());
+ byte[] drm_trans_wrapped_desKey = keyWrapper.wrap(desKey);
+
+ String drmWrappedDesStr =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey);
+
+ CMS.debug(method + " drmWrappedDesStr: " + drmWrappedDesStr);
+ values.add(drmWrappedDesStr);
+
+ } catch (Exception e) {
+ throw new EBaseException(e);
+ }
+
+ return values;
+ }
+
+ private boolean cryptoGramsAreEqual(byte[] original_cryptogram, byte[] calculated_cryptogram) {
+ boolean sameCardCrypto = true;
+
+ if (original_cryptogram == null || calculated_cryptogram == null) {
+ return false;
+ }
+ if (original_cryptogram.length == calculated_cryptogram.length) {
+ for (int i = 0; i < original_cryptogram.length; i++) {
+ if (original_cryptogram[i] != calculated_cryptogram[i]) {
+ sameCardCrypto = false;
+ break;
+ }
+ }
+ } else {
+ // different length; must be different
+ sameCardCrypto = false;
+ }
+
+ return sameCardCrypto;
+ }
+
+ //For now only used for scp03
+
+ static GPParams readGPSettings(String keySet) {
+ GPParams params = new GPParams();
+
+ String method = "TokenServlet.readGPSettings: ";
+ String gp3Settings = "tks." + keySet + ".prot3";
+
+ String divers = "emv";
+ try {
+ divers = CMS.getConfigStore().getString(gp3Settings + ".divers", "emv");
+ } catch (EBaseException e) {
+ }
+
+ params.setDiversificationScheme(divers);
+
+ CMS.debug(method + " Divers: " + divers);
+
+ String diversVer1Keys = "emv";
+
+ try {
+ diversVer1Keys = CMS.getConfigStore().getString(gp3Settings + ".diversVer1Keys","emv");
+ } catch (EBaseException e) {
+ }
+
+ params.setVersion1DiversificationScheme(diversVer1Keys);
+ CMS.debug(method + " Version 1 keys Divers: " + divers);
+
+ return params;
+ }
+
+ private byte[] getDeveKeyArray(String keyType,IConfigStore sconfig,String keySet) throws EBaseException {
+ byte devKeyArray[] = null;
+ try {
+ devKeyArray = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + "." + keyType));
+ } catch (Exception e) {
+ throw new EBaseException("Can't read static developer key array: " + keySet + ": " + keyType);
+ }
+
+ return devKeyArray;
+ }
+
+
}
diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
index 233124968..82482d09c 100644
--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
+++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
@@ -53,6 +53,8 @@ public interface IRemoteRequest {
/* computeSessionKey responses */
public static final String TKS_RESPONSE_SessionKey = "sessionKey";
public static final String TKS_RESPONSE_EncSessionKey = "encSessionKey";
+ public static final String TKS_RESPONSE_MacSessionKey = "macSessionKey";
+ public static final String TKS_RESPONSE_KekSessionKey = "kekSessionKey";
public static final String TKS_RESPONSE_KEK_DesKey = "kek_wrapped_desKey";
public static final String TKS_RESPONSE_DRM_Trans_DesKey = "drm_trans_desKey";
public static final String TKS_RESPONSE_KeyCheck = "keycheck";
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
index 90050132b..6e594f849 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
@@ -18,15 +18,23 @@
package com.netscape.cmscore.dbs;
import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
+import org.apache.commons.codec.binary.Base64;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
+import org.mozilla.jss.crypto.IVParameterSpec;
+
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.MetaInfo;
import com.netscape.certsrv.dbs.IDBObj;
import com.netscape.certsrv.dbs.keydb.IKeyRecord;
import com.netscape.certsrv.dbs.keydb.KeyState;
+import com.netscape.certsrv.security.WrappingParams;
+import com.netscape.cms.servlet.key.KeyRecordParser;
/**
* A class represents a Key record. It maintains the key
@@ -397,4 +405,101 @@ public class KeyRecord implements IDBObj, IKeyRecord {
public String getRealm() throws EBaseException {
return realm;
}
+
+ public void setWrappingParams(WrappingParams params) throws Exception {
+ if (mMetaInfo == null) {
+ mMetaInfo = new MetaInfo();
+ }
+ // set session key parameters
+ mMetaInfo.set(KeyRecordParser.OUT_SK_LENGTH, String.valueOf(params.getSkLength()));
+ if (params.getSkType() != null) {
+ mMetaInfo.set(KeyRecordParser.OUT_SK_TYPE, params.getSkType().toString());
+ }
+ if (params.getSkKeyGenAlgorithm() != null) {
+ // JSS doesn't have a name map or a functional OID map
+ // for now, save the "name"
+ mMetaInfo.set(KeyRecordParser.OUT_SK_KEYGEN_ALGORITHM, params.getSkKeyGenAlgorithm().toString());
+ }
+ if (params.getSkWrapAlgorithm() != null) {
+ mMetaInfo.set(KeyRecordParser.OUT_SK_WRAP_ALGORITHM, params.getSkWrapAlgorithm().toString());
+ }
+
+ // set payload parameters
+ if (params.getPayloadEncryptionAlgorithm() != null) {
+ EncryptionAlgorithm encrypt = params.getPayloadEncryptionAlgorithm();
+ try {
+ OBJECT_IDENTIFIER oid = encrypt.toOID();
+ mMetaInfo.set(KeyRecordParser.OUT_PL_ENCRYPTION_OID, oid.toDottedString());
+ } catch (NoSuchAlgorithmException e) {
+ // oid not defined in JSS
+ mMetaInfo.set(KeyRecordParser.OUT_PL_ENCRYPTION_ALGORITHM, encrypt.getAlg().toString());
+ mMetaInfo.set(KeyRecordParser.OUT_PL_ENCRYPTION_MODE, encrypt.getMode().toString());
+ mMetaInfo.set(KeyRecordParser.OUT_PL_ENCRYPTION_PADDING, encrypt.getPadding().toString());
+ }
+ }
+ if (params.getPayloadWrapAlgorithm() != null) {
+ mMetaInfo.set(KeyRecordParser.OUT_PL_WRAP_ALGORITHM, params.getPayloadWrapAlgorithm().toString());
+ }
+ if (params.getPayloadWrappingIV() != null) {
+ // store as base64 encoded string
+ mMetaInfo.set(
+ KeyRecordParser.OUT_PL_WRAP_IV,
+ Base64.encodeBase64String(params.getPayloadWrappingIV().getIV())
+ );
+ }
+ if (params.getPayloadEncryptionIV() != null) {
+ // store as base 64 encoded string
+ mMetaInfo.set(
+ KeyRecordParser.OUT_PL_ENCRYPTION_IV,
+ Base64.encodeBase64String(params.getPayloadEncryptionIV().getIV())
+ );
+ }
+
+ }
+
+ public WrappingParams getWrappingParams(WrappingParams oldParams) throws Exception {
+ if ((mMetaInfo == null) || (mMetaInfo.get(KeyRecordParser.OUT_SK_TYPE) == null)) {
+ // This is likely a legacy record. Return the old DES3 parameters.
+ // TODO(alee) modify to pass this in - to keep bean-ness
+ return oldParams;
+ }
+
+ WrappingParams params = new WrappingParams();
+ params.setSkType(mMetaInfo.get(KeyRecordParser.OUT_SK_TYPE).toString());
+ params.setSkLength(Integer.parseInt(mMetaInfo.get(KeyRecordParser.OUT_SK_LENGTH).toString()));
+
+ Object data = mMetaInfo.get(KeyRecordParser.OUT_SK_WRAP_ALGORITHM);
+ if (data != null) params.setSkWrapAlgorithm(data.toString());
+
+ data = mMetaInfo.get(KeyRecordParser.OUT_SK_KEYGEN_ALGORITHM);
+ if (data != null) params.setSkKeyGenAlgorithm(data.toString());
+
+ data = mMetaInfo.get(KeyRecordParser.OUT_PL_WRAP_ALGORITHM);
+ if (data != null) params.setPayloadWrapAlgorithm(data.toString());
+
+ if (mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_OID) != null) {
+ String oidString = mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_OID).toString();
+ params.setPayloadEncryptionAlgorithm(EncryptionAlgorithm.fromOID(new OBJECT_IDENTIFIER(oidString)));
+ } else {
+ params.setPayloadEncryptionAlgorithm(
+ mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_ALGORITHM).toString(),
+ mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_MODE).toString(),
+ mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_PADDING).toString(),
+ Integer.parseInt(mMetaInfo.get(KeyRecordParser.OUT_SK_LENGTH).toString()));
+ }
+
+ data = mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTION_IV);
+ if (data != null) {
+ byte[] iv = Base64.decodeBase64(data.toString());
+ params.setPayloadEncryptionIV(new IVParameterSpec(iv));
+ }
+
+ data = mMetaInfo.get(KeyRecordParser.OUT_PL_WRAP_IV);
+ if (data != null) {
+ byte[] iv = Base64.decodeBase64(data.toString());
+ params.setPayloadWrappingIV(new IVParameterSpec(iv));
+ }
+
+ return params;
+ }
}
diff --git a/base/server/man/man5/pki_default.cfg.5 b/base/server/man/man5/pki_default.cfg.5
index 1eb4ab99b..856081dcf 100644
--- a/base/server/man/man5/pki_default.cfg.5
+++ b/base/server/man/man5/pki_default.cfg.5
@@ -107,7 +107,7 @@ If an optional hardware security module (HSM) is being utilized (rather than the
.SS SYSTEM CERTIFICATE PARAMETERS
\fBpkispawn\fP sets up a number of system certificates for each subsystem. The system certificates which are required differ between subsystems. Each system certificate is denoted by a tag, as noted below. The different system certificates are:
.IP
-* signing certificate ("signing"). Used to sign other certificates. Required for CA.
+* signing certificate ("ca_signing"). Used to sign other certificates. Required for CA.
.IP
* OCSP signing certificate ("ocsp_signing" in CA, "signing" in OCSP). Used to sign CRLs. Required for OCSP and CA.
.IP
diff --git a/base/server/man/man8/pkispawn.8 b/base/server/man/man8/pkispawn.8
index 40ec7f0ad..002520a0b 100644
--- a/base/server/man/man8/pkispawn.8
+++ b/base/server/man/man8/pkispawn.8
@@ -1387,7 +1387,7 @@ Directory Server and Admin Server instances can be created with the following
command:
.IP
-\fBsetup-ds-admin.pl\fP
+\fBsetup-ds.pl\fP
.PP
Enable LDAPS in the Directory Server with the following command:
diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py
index d556312a7..70734c3db 100644
--- a/base/server/python/pki/server/__init__.py
+++ b/base/server/python/pki/server/__init__.py
@@ -568,19 +568,7 @@ class PKIInstance(object):
# load passwords
self.passwords.clear()
if os.path.exists(self.password_conf):
-
- lines = open(self.password_conf).read().splitlines()
-
- for index, line in enumerate(lines):
- if not line or line.startswith('#'):
- continue
- parts = line.split('=', 1)
- if len(parts) < 2:
- raise Exception('Missing delimiter in %s line %d' %
- (self.password_conf, index + 1))
- name = parts[0]
- value = parts[1]
- self.passwords[name] = value
+ pki.util.load_properties(self.password_conf, self.passwords)
self.load_external_certs(self.external_certs_conf)
diff --git a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
index a2d18f166..9119d7779 100644
--- a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
+++ b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java
@@ -1,9 +1,7 @@
package org.dogtagpki.server.tks.rest;
import java.io.CharConversionException;
-import java.io.IOException;
import java.net.URI;
-import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
@@ -25,7 +23,6 @@ import org.jboss.resteasy.plugins.providers.atom.Link;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.CryptoManager.NotInitializedException;
import org.mozilla.jss.crypto.CryptoToken;
-import org.mozilla.jss.crypto.InvalidKeyFormatException;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.SymmetricKey;
@@ -347,12 +344,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
return createOKResponse(keyData);
- } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
- | InvalidAlgorithmParameterException | EBaseException
- | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ } catch (Exception e) {
e.printStackTrace();
CMS.debug("Error in generating and exporting shared secret: " + e);
- throw new PKIException("Error in generating and exporting shared secret: " + e);
+ throw new PKIException("Error in generating and exporting shared secret: " + e, e);
}
}
@@ -418,12 +413,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
return createOKResponse(keyData);
- } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
- | InvalidAlgorithmParameterException | EBaseException
- | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ } catch (Exception e) {
e.printStackTrace();
CMS.debug("Error in replacing shared secret: " + e);
- throw new PKIException("Error in replacing shared secret: " + e);
+ throw new PKIException("Error in replacing shared secret: " + e, e);
}
}
@@ -504,12 +497,10 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou
return createOKResponse(keyData);
- } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException
- | InvalidAlgorithmParameterException | EBaseException
- | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) {
+ } catch (Exception e) {
e.printStackTrace();
CMS.debug("Error in obtaining shared secret: " + e);
- throw new PKIException("Error in obtaining shared secret: " + e);
+ throw new PKIException("Error in obtaining shared secret: " + e, e);
}
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java b/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java
index e5f38e108..e1de8f23d 100644
--- a/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java
@@ -62,6 +62,14 @@ public class PlatformAndSecChannelProtoInfo {
}
return false;
}
+
+ public boolean isSCP03() {
+ if(protocol == SecureChannel.SECURE_PROTO_03) {
+ return true;
+ }
+ return false;
+ }
+
public void setProtocol(byte protocol) {
this.protocol = protocol;
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index f2e32368f..fc5472c79 100644
--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -65,15 +65,22 @@ public class SecureChannel {
public TPSProcessor processor;
private PK11SymKey sessionKey;
- //SCP01 or SCP02 key
+ //SCP01 or SCP02 or SCP03 key
private PK11SymKey encSessionKey;
+
//SCP02 session keys
private PK11SymKey cmacSessionKey;
//Used for security level we do not yet suport.
+
+
+
private PK11SymKey rmacSessionKey;
private PK11SymKey dekSessionKey;
+ //SCP03
+ private PK11SymKey macSessionKey;
+
private TPSBuffer dekSessionKeyWrapped;
private TPSBuffer drmDesKey;
@@ -112,11 +119,65 @@ public class SecureChannel {
public final static byte[] GP201_GET_DATA_CPLC_WHOLE_CPLC = { (byte) 0x9F, (byte) 0x7F };
public final static byte[] GP211_GET_DATA_CPLC_WHOLE_CPLC = { (byte) 0x9F, (byte) 0x7F };
+ // SCP02
public final static byte[] C_MACDerivationConstant = { 0x01, 0x01 };
public final static byte[] ENCDerivationConstant = { (byte) 0x01, (byte) 0x82 };
public final static byte[] DEKDerivationConstant = { 0x01, (byte) 0x81 };
public final static byte[] R_MACDerivationConstant = { 0x01, 0x02 };
+ //SCP03 encryption counter
+
+ private TPSBuffer encryptionCounter;
+
+
+ //For SCP03
+
+ public SecureChannel(TPSProcessor processor, PK11SymKey encSessionKey, PK11SymKey macSessionKey, PK11SymKey dekSessionKey,
+ TPSBuffer drmDesKey,TPSBuffer kekDesKey,
+ TPSBuffer keyCheck, TPSBuffer keyDiversificationData, TPSBuffer cardChallenge,
+ TPSBuffer cardCryptogram, TPSBuffer hostChallenge, TPSBuffer hostCryptogram, TPSBuffer keyInfoData,
+ PlatformAndSecChannelProtoInfo platformInfo)
+ throws TPSException {
+
+ if (processor == null || encSessionKey == null || keyDiversificationData == null
+ || cardChallenge == null || cardCryptogram == null || hostChallenge == null || hostCryptogram == null
+ || keyInfoData == null) {
+ throw new TPSException("SecureChannel.SecureChannel: Invalid data in constructor!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.SecureChannel: For SCP03. : ");
+
+ CMS.debug("kekDesKey: " + kekDesKey.toHexString());
+ CMS.debug("keyCheck: " + keyCheck.toHexString());
+
+ this.platProtInfo = platformInfo;
+ this.processor = processor;
+ this.encSessionKey = encSessionKey;
+ this.macSessionKey = macSessionKey;
+ this.dekSessionKey = dekSessionKey;
+
+ this.drmDesKey = drmDesKey;
+ this.setKekDesKey(kekDesKey);
+
+ this.keyCheck = keyCheck;
+ this.keyDiversificationData = keyDiversificationData;
+ this.cardChallenge = cardChallenge;
+ this.cardCryptogram = cardCryptogram;
+ this.hostChallenge = hostChallenge;
+ this.hostCryptogram = hostCryptogram;
+
+ //16 bytes of chaining value
+ this.icv = new TPSBuffer(16);
+
+ this.keyInfoData = keyInfoData;
+
+ this.secLevel = SecurityLevel.SECURE_MSG_NONE;
+ this.secLevelGP211 = ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC;
+ encryptionCounter = new TPSBuffer(16);
+
+ }
+
//For SCP01
public SecureChannel(TPSProcessor processor, PK11SymKey sessionKey, PK11SymKey encSessionKey, TPSBuffer drmDesKey,
TPSBuffer kekDesKey, TPSBuffer keyCheck, TPSBuffer keyDiversificationData, TPSBuffer cardChallenge,
@@ -345,12 +406,46 @@ public class SecureChannel {
public void externalAuthenticate() throws TPSException, IOException {
- CMS.debug("SecureChannel.externalAuthenticate: entering. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+ String method = "SecureChannel.externalAuthenticate.";
+ CMS.debug(method + ": entering. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
- if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ TPSBuffer calculatedCardCryptogram = null;
+ if(platProtInfo.isSCP03()) {
+ CMS.debug("SecureChannel.externalAuthenticate: Attempting an External Authenticate for SCP03!");
+
+ TPSBuffer context = new TPSBuffer(hostChallenge);
+ context.add(cardChallenge);
+ try {
+ calculatedCardCryptogram = Util.compute_AES_CMAC_Cryptogram(macSessionKey, context, Util.CARD_CRYPTO_KDF_CONSTANT_SCP03);
+ } catch (EBaseException e) {
+ throw new TPSException(method + "Failed to calculate card cryptogram!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug(method + " dumped macSessionKey: " + new TPSBuffer(macSessionKey.getEncoded()).toHexString() );
+
+ CMS.debug(method + " actual card cryptogram " + cardCryptogram.toHexString());
+ CMS.debug(method + " calculated card cryptogram " + calculatedCardCryptogram.toHexString());
+
+ ExternalAuthenticateAPDUGP211 externalAuth = new ExternalAuthenticateAPDUGP211(hostCryptogram,
+ /* secLevel */secLevelGP211);
+
+ computeAPDUMacSCP03(externalAuth);
+
+ APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+ if (!response.checkResult()) {
+ throw new TPSException(
+ "SecureChannel.eternalAuthenticate SCP03. Failed to external authenticate to token.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ }
+
+
+ if (platProtInfo.isSCP02()) {
CMS.debug("SecureChannel.externalAuthenticate: Attempting an External Authenticate for SCP02!");
- TPSBuffer calculatedCardCryptogram = computeCardCryptogramSCP02(encSessionKey);
+ calculatedCardCryptogram = computeCardCryptogramSCP02(encSessionKey);
if (false == cardCryptogram.equals(calculatedCardCryptogram)) {
@@ -383,7 +478,7 @@ public class SecureChannel {
CMS.debug("SecureChannel.externalAuthenticate: SCP02 external authenticate returns Success!!!");
- } else { //SCP01
+ } else if(platProtInfo.isSCP01()){ //SCP01
ExternalAuthenticateAPDU externalAuth = new ExternalAuthenticateAPDU(hostCryptogram,
/* secLevel */ExternalAuthenticateAPDU.SecurityLevel.SECURE_MSG_MAC_ENC);
@@ -410,15 +505,20 @@ public class SecureChannel {
CMS.debug("SecureChannel.computeAPDU: entering..");
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
if (isSCP02()) {
computeAPDU_SCP02(apdu);
return;
}
- if (apdu == null) {
- throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
- TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ if (isSCP03() ) {
+ computeAPDU_SCP03(apdu);
+ return;
}
computeAPDUMac(apdu);
@@ -436,6 +536,60 @@ public class SecureChannel {
}
}
+ private void computeAPDU_SCP03(APDU apdu) throws TPSException {
+ String method = "SecureChannel.computeAPDU_SCP03:";
+
+ CMS.debug(method + "entering..");
+ if (apdu == null) {
+ throw new TPSException(method + " bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ if (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC) {
+ try {
+ //CMS.debug("SecureChannel.computeAPDU_SCP03: Before encryption data value: "
+ // + apdu.getData().toHexString());
+ this.incrementBuffer(encryptionCounter);
+ TPSBuffer currentEncryptionCounter = new TPSBuffer(encryptionCounter);
+ apdu.secureMessageSCP03(encSessionKey,currentEncryptionCounter);
+ ;
+ //CMS.debug("SecureChannel.computeAPDU_SCP03: After encryption data value: "
+ // + apdu.getData().toHexString());
+ } catch (EBaseException e) {
+ throw new TPSException("SecureChannel.computeAPDU_SCP03: Can't encrypt outgoing data! " + e);
+ }
+
+ CMS.debug("SecureChannel.computeAPDU_SCP03: Successfully encrypted apdu data.");
+ }
+
+ computeAPDUMacSCP03(apdu);
+ }
+
+ //Assume the whole buffer is to be incremented
+ //Used for SCP03 encrypted apdu messages
+ public void incrementBuffer(TPSBuffer buffer) {
+
+ if(buffer == null)
+ return;
+
+ int len = buffer.size();
+
+ if (len < 1)
+ return;
+ int offset = 0;
+ for (short i = (short) (offset + len - 1); i >= offset; i--) {
+ byte cur = buffer.at(i);
+ if (cur != (byte) 0xFF) {
+ cur++;
+ buffer.setAt(i, cur);
+ break;
+ } else
+ buffer.setAt(i,(byte) 0x00);
+ }
+
+ System.out.println("enc buffer: " + buffer.toHexString());
+ }
+
private void computeAPDU_SCP02(APDU apdu) throws TPSException {
CMS.debug("SecureChannel.computeAPDU_SCP02: entering..");
@@ -448,11 +602,11 @@ public class SecureChannel {
if (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC) {
try {
- CMS.debug("SecureChannel.computeAPDU_SCP02: Before encryption data value: "
- + apdu.getData().toHexString());
+ //CMS.debug("SecureChannel.computeAPDU_SCP02: Before encryption data value: "
+ // + apdu.getData().toHexString());
apdu.secureMessageSCP02(encSessionKey);
- CMS.debug("SecureChannel.computeAPDU_SCP02: After encryption data value: "
- + apdu.getData().toHexString());
+ //CMS.debug("SecureChannel.computeAPDU_SCP02: After encryption data value: "
+ // + apdu.getData().toHexString());
} catch (EBaseException e) {
throw new TPSException("SecureChannel.computeAPDU_SCP02: Can't encrypt outgoing data! " + e);
}
@@ -462,6 +616,48 @@ public class SecureChannel {
}
+ private void computeAPDUMacSCP03(APDU apdu) throws TPSException {
+ TPSBuffer newMac = null;
+ TPSBuffer data = null;
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDUMacSCP03: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ data = apdu.getDataToMAC();
+
+ //CMS.debug("SecureChannel.computeAPDUMacSCP03: data To MAC: " + data.toHexString() + " incoming icv: "
+ // + icv.toHexString());
+
+ try {
+
+ CMS.debug("SecureChannel.computeAPDUMacSCP03: No ecnrypton of ICV.");
+
+ TPSBuffer dataToMac = new TPSBuffer(icv);
+ /// Prepend the chaining value to the data to be maced.
+ dataToMac.add(data);
+
+ //CMS.debug("SecureChannel.computeAPDUMacSCP03: final data To MAC: " + dataToMac.toHexString() + " incoming icv: "
+ // + icv.toHexString());
+
+ newMac = Util.computeAES_CMAC(macSessionKey, dataToMac);
+
+
+ } catch (EBaseException e) {
+ CMS.debug("SecureChannel.computeAPDUMacSCP03: Can't compute mac. " + e);
+ throw new TPSException("SecureChannel.compuatAPDUMacSCP03: Can't compute mac.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.computeAPDUMacSCP03: computed MAC: " /* + newMac.toHexString() */);
+
+ apdu.setMAC(newMac.substr(0,8));
+
+ icv.set(newMac);
+
+ }
+
private void computeAPDUMacSCP02(APDU apdu) throws TPSException {
TPSBuffer newMac = null;
@@ -571,7 +767,7 @@ public class SecureChannel {
public void installLoad(TPSBuffer packageAID, TPSBuffer sdAID, int fileLength) throws TPSException, IOException {
CMS.debug("SecureChannel.installLoad: entering ... packageAID: " + packageAID.toHexString() + " sdAID: "
- + sdAID.toHexString());
+ + sdAID.toHexString() + " fileLength: " + fileLength);
if (packageAID == null || sdAID == null || fileLength <= 0) {
throw new TPSException("SecureChannel.insallLoad bad input parameters!",
@@ -1363,14 +1559,15 @@ public class SecureChannel {
PutKeyAPDU putKey = new PutKeyAPDU(keyVersion, (byte) 0x81, keySetData);
- if (isSCP02()) {
+ if (isSCP02() || isSCP03()) {
+ CMS.debug("SecureChannel.putKeys: adding trailing 0 byte");
TPSBuffer trailer = new TPSBuffer(1);
putKey.setTrailer(trailer);
}
computeAPDU(putKey);
- int kill = 0;
+ int kill = 0;
if (kill == 1) {
throw new TPSException("putKeys end of progress.");
}
@@ -1503,6 +1700,13 @@ public class SecureChannel {
}
+ public boolean isSCP03() {
+ if (platProtInfo.isSCP03())
+ return true;
+ else
+ return false;
+ }
+
public boolean isSCP02() {
if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
index 2fe382539..910294e53 100644
--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
@@ -62,4 +62,12 @@ public class TKSComputeSessionKeyResponse extends RemoteResponse
public TPSBuffer getKekWrappedDesKey() {
return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
}
+
+ public TPSBuffer getKekSessionKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KekSessionKey);
+ }
+
+ public TPSBuffer getMacSessionKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_MacSessionKey);
+ }
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
index f38d7def5..65d0ed0ac 100644
--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -226,6 +226,157 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
}
}
+ public TKSComputeSessionKeyResponse computeSessionKeysSCP03(
+ TPSBuffer kdd
+ ,TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer card_challenge,
+ TPSBuffer card_cryptogram,
+ TPSBuffer host_challenge,
+ String tokenType) throws EBaseException {
+
+ String method = "TKSRemoteRequestHandler: computeSessionKeysSCP03()";
+
+ CMS.debug(method + " Entering: ");
+
+ if (cuid == null || kdd == null || keyInfo == null || card_challenge == null ||
+ card_cryptogram == null || host_challenge == null || tokenType == null
+
+ ) {
+ throw new EBaseException(method + " invalid input!");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ boolean serverKeygen =
+ conf.getBoolean("op.enroll." +
+ tokenType + ".keyGen.encryption.serverKeygen.enable",
+ false);
+ if (keySet == null)
+ keySet = conf.getString("tps.connector." + connid + ".keySet", "defKeySet");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+
+ String requestString = IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
+ "&" + IRemoteRequest.TOKEN_KDD + "=" + Util.specialURLEncode(kdd) +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_CARD_CHALLENGE + "=" + Util.specialURLEncode(card_challenge) +
+ "&" + IRemoteRequest.TOKEN_HOST_CHALLENGE + "=" + Util.specialURLEncode(host_challenge) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(keyInfo) +
+ "&" + IRemoteRequest.CHANNEL_PROTOCOL + "=" + SecureChannel.SECURE_PROTO_03 +
+ "&" + IRemoteRequest.TOKEN_CARD_CRYPTOGRAM + "="
+ + Util.specialURLEncode(card_cryptogram.toBytesArray()) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet;
+
+ HttpResponse resp =
+ conn.send("computeSessionKey",
+ requestString
+ );
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: serverKeygen and !serverKeygen returns different set of
+ * response values so "missing" might not be bad
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug(method + " status not found.");
+ //CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got content = " + content);
+ } else {
+ CMS.debug(method + " got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+ if (value == null) {
+ CMS.debug(method + " response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+ } else {
+ CMS.debug(method+ "got IRemoteRequest.TKS_RESPONSE_EncSessionKey");
+ response.put(IRemoteRequest.TKS_RESPONSE_EncSessionKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ if (value == null) {
+ CMS.debug(method + " response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ } else {
+ CMS.debug(method + "got IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey");
+ response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_MacSessionKey);
+ if (value == null) {
+ CMS.debug(method + "response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_MacSessionKey);
+ } else {
+ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_MacSessionKey");
+ response.put(IRemoteRequest.TKS_RESPONSE_MacSessionKey, Util.specialDecode(value));
+
+ }
+
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KekSessionKey);
+ if (value == null) {
+ CMS.debug(method + "response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KekSessionKey);
+ } else {
+ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KekSessionKey");
+ response.put(IRemoteRequest.TKS_RESPONSE_KekSessionKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ if (value == null) {
+ CMS.debug(method + "response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ } else {
+ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KEK_DesKey");
+ response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value));
+
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+
+ if (value == null) {
+ CMS.debug(method + "response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KeyCheck);
+
+ } else {
+ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KeyCheck");
+ response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ if ( value == null ) {
+ CMS.debug(method + " response missing name-value pair for: " + IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ } else {
+ CMS.debug(method + " got " + IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ response.put(IRemoteRequest.TKS_RESPONSE_HostCryptogram, Util.specialDecode(value));
+ }
+
+ CMS.debug(method + " ends.");
+
+ return new TKSComputeSessionKeyResponse(response);
+
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: computeSessionKeySCP02(): no response content.");
+ }
+
+ }
+
/*
* computeSessionKey
*
@@ -559,7 +710,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
TPSBuffer kdd,
TPSBuffer cuid,
TPSBuffer version,
- TPSBuffer inData)
+ TPSBuffer inData,int protocol)
throws EBaseException {
CMS.debug("TKSRemoteRequestHandler: encryptData(): begins.");
if (cuid == null || kdd == null || version == null || inData == null) {
@@ -582,7 +733,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
"&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
"&" + IRemoteRequest.TOKEN_KDD + "=" + Util.specialURLEncode(kdd) +
"&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(version) +
- "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet +
+ "&" + IRemoteRequest.CHANNEL_PROTOCOL + "=" + protocol
+ );
String content = resp.getContent();
diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index 319ff67b5..540da4019 100644
--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -250,6 +250,48 @@ public class TPSEngine {
}
+ // Compute 3 session keys enc, mac, and kek / dek in one shot and return the results
+ public TKSComputeSessionKeyResponse computeSessionKeysSCP03(TPSBuffer kdd, TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer card_challenge,
+ TPSBuffer host_challenge,
+ TPSBuffer card_cryptogram,
+ String connId,
+ String tokenType, String inKeySet) throws TPSException {
+
+ if (cuid == null || kdd == null || keyInfo == null || card_challenge == null || host_challenge == null
+ || card_cryptogram == null || connId == null || tokenType == null) {
+
+ throw new TPSException("TPSEngine.computeSessionKeySCP03: Invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSEngine.computeSessionKeysSCP03");
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSComputeSessionKeyResponse resp = null;
+ try {
+ tks = new TKSRemoteRequestHandler(connId, inKeySet);
+ resp = tks.computeSessionKeysSCP03(kdd, cuid, keyInfo, card_challenge, card_cryptogram, host_challenge,
+ tokenType);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEngine.computeSessionKeysSCP03: Error computing session keys!" + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ int status = resp.getStatus();
+ if (status != 0) {
+ CMS.debug("TPSEngine.computeSessionKeysSCP03: Non zero status result: " + status);
+ throw new TPSException("TPSEngine.computeSessionKeysSCP03: invalid returned status: " + status);
+
+ }
+
+ return resp;
+
+ }
+
+
public TKSComputeSessionKeyResponse computeSessionKey(TPSBuffer kdd, TPSBuffer cuid,
TPSBuffer keyInfo,
TPSBuffer card_challenge,
@@ -378,10 +420,12 @@ public class TPSEngine {
public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer kdd, TPSBuffer wrappedDekSessionKey, String connId, String inKeyset)
throws TPSException {
- CMS.debug("TPSEngine.createKeySetData. entering...");
+
+ String method = "TPSEngine.createKeySetData:";
+ CMS.debug(method + " entering...");
if (newMasterVersion == null || oldVersion == null || cuid == null || kdd == null || connId == null) {
- throw new TPSException("TPSEngine.createKeySetData: Invalid input data",
+ throw new TPSException(method + " Invalid input data",
TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
}
@@ -394,14 +438,14 @@ public class TPSEngine {
resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, kdd, protocol,wrappedDekSessionKey);
} catch (EBaseException e) {
- throw new TPSException("TPSEngine.createKeySetData, failure to get key set data from TKS",
+ throw new TPSException(method + " failure to get key set data from TKS",
TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
}
int status = resp.getStatus();
if (status != 0) {
- CMS.debug("TPSEngine.createKeySetData: Non zero status result: " + status);
- throw new TPSException("TPSEngine.computeSessionKey: invalid returned status: " + status,
+ CMS.debug(method + " Non zero status result: " + status);
+ throw new TPSException(method + " invalid returned status: " + status,
TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
}
@@ -409,8 +453,8 @@ public class TPSEngine {
TPSBuffer keySetData = resp.getKeySetData();
if (keySetData == null) {
- CMS.debug("TPSEngine.createKeySetData: No valid key set data returned.");
- throw new TPSException("TPSEngine.createKeySetData: No valid key set data returned.",
+ CMS.debug(method + " No valid key set data returned.");
+ throw new TPSException(method + " No valid key set data returned.",
TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index 8b6370337..672f53d83 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -378,8 +378,10 @@ public class TPSEnrollProcessor extends TPSProcessor {
String tksConnId = getTKSConnectorID();
TPSBuffer plaintextChallenge = computeRandomData(16, tksConnId);
+ CMS.debug(method + " plaintextChallenge: " + plaintextChallenge.toHexString());
+
//These will be used shortly
- TPSBuffer wrappedChallenge = encryptData(appletInfo, channel.getKeyInfoData(), plaintextChallenge, tksConnId);
+ TPSBuffer wrappedChallenge = encryptData(appletInfo, channel.getKeyInfoData(), plaintextChallenge, tksConnId,this.getProtocol());
PKCS11Obj pkcs11objx = null;
try {
@@ -3006,7 +3008,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
//CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8 : keyCheck: " + keyCheck.toHexString());
CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8 : got keyCheck");
- // String ivParams = ssKeyGenResponse.getIVParam();
+ //String ivParams = ssKeyGenResponse.getIVParam();
//CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: ivParams: " + ivParams);
TPSBuffer ivParamsBuff = new TPSBuffer(Util.uriDecodeFromHex(ivParams));
@@ -3019,7 +3021,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
TPSBuffer kekWrappedDesKey = channel.getKekDesKey();
if (kekWrappedDesKey != null) {
- //CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString());
+ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString());
CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: got keyWrappedDesKey");
} else
CMS.debug("TPSEnrollProcessor.iportPrivateKeyPKC8: null kekWrappedDesKey!");
@@ -3041,7 +3043,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
}
data.add((byte) ivParamsBuff.size());
data.add(ivParamsBuff);
- //CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: key data outgoing: " + data.toHexString());
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: key data outgoing: " + data.toHexString());
int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber();
int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber();
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index 825df3f23..7d17f36b7 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -33,6 +33,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import netscape.security.x509.RevocationReason;
+
import org.dogtagpki.server.tps.TPSSession;
import org.dogtagpki.server.tps.TPSSubsystem;
import org.dogtagpki.server.tps.authentication.AuthUIParameter;
@@ -99,8 +101,6 @@ import com.netscape.cms.servlet.tks.SecureChannelProtocol;
import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.symkey.SessionKey;
-import netscape.security.x509.RevocationReason;
-
public class TPSProcessor {
public static final int RESULT_NO_ERROR = 0;
@@ -111,10 +111,14 @@ public class TPSProcessor {
public static final int CPLC_MSN_SIZE = 4;
public static final int INIT_UPDATE_DATA_SIZE = 28;
+ public static final int INIT_UPDATE_DATA_SIZE_02 = 29;
+ public static final int INIT_UPDATE_DATA_SIZE_03 = 32;
public static final int DIVERSIFICATION_DATA_SIZE = 10;
public static final int CARD_CRYPTOGRAM_OFFSET = 20;
+ public static final int CARD_CRYPTOGRAM_OFFSET_GP211_SC03 = 21;
public static final int CARD_CRYPTOGRAM_SIZE = 8;
public static final int CARD_CHALLENGE_SIZE_GP211_SC02 = 6;
+ public static final int CARD_CHALLENGE_OFFSET_GP211_SC03 = 13 ;
public static final int SEQUENCE_COUNTER_OFFSET_GP211_SC02 = 12;
public static final int SEQUENCE_COUNTER_SIZE_GP211_SC02 = 2;
public static final int CARD_CHALLENGE_OFFSET = 12;
@@ -431,7 +435,7 @@ public class TPSProcessor {
protected TPSBuffer encryptData(AppletInfo appletInfo, TPSBuffer keyInfo, TPSBuffer plaintextChallenge,
- String connId) throws TPSException {
+ String connId,int protocol) throws TPSException {
TKSRemoteRequestHandler tks = null;
@@ -439,7 +443,7 @@ public class TPSProcessor {
try {
tks = new TKSRemoteRequestHandler(connId, getSelectedKeySet());
- data = tks.encryptData(appletInfo.getKDD(),appletInfo.getCUID(), keyInfo, plaintextChallenge);
+ data = tks.encryptData(appletInfo.getKDD(),appletInfo.getCUID(), keyInfo, plaintextChallenge,protocol);
} catch (EBaseException e) {
throw new TPSException("TPSProcessor.encryptData: Erorr getting wrapped data from TKS!",
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -482,7 +486,9 @@ public class TPSProcessor {
protected TPSBuffer initializeUpdate(byte keyVersion, byte keyIndex, TPSBuffer randomData) throws IOException,
TPSException {
- CMS.debug("In TPS_Processor.initializeUpdate.");
+ String method = "TPSProcessor.initializeUpdate:";
+
+ CMS.debug(method + " Entering...");
InitializeUpdateAPDU initUpdate = new InitializeUpdateAPDU(keyVersion, keyIndex, randomData);
int done = 0;
@@ -500,7 +506,10 @@ public class TPSProcessor {
TPSBuffer data = resp.getResultDataNoCode();
- if (data.size() != INIT_UPDATE_DATA_SIZE) {
+ CMS.debug(method + " data.size() " + data.size());
+
+ if ((data.size() != INIT_UPDATE_DATA_SIZE) && (data.size() != INIT_UPDATE_DATA_SIZE_02)
+ && (data.size() != INIT_UPDATE_DATA_SIZE_03)) {
throw new TPSException("TPSBuffer.initializeUpdate: Invalid response from token!",
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
@@ -550,12 +559,22 @@ public class TPSProcessor {
TPSBuffer initUpdateResp = initializeUpdate(keyVersion, keyIndex, randomData);
+ CMS.debug("TPSProcessor.setupSecureChanne: initUpdateResponse: " + initUpdateResp.toHexString());
+
TPSBuffer key_diversification_data = initUpdateResp.substr(0, DIVERSIFICATION_DATA_SIZE);
appletInfo.setKDD(key_diversification_data);
CMS.debug("TPSProcessor.setupSecureChannel: diversification data: " + key_diversification_data.toHexString());
- TPSBuffer key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 2);
+ TPSBuffer key_info_data = null;
+
+ if (platProtInfo.isSCP03()) {
+ key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 3);
+ } else {
+ key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 2);
+ }
+
+
CMS.debug("TPSProcessor.setupSecureChannel: key info data: " + key_info_data.toHexString());
TokenRecord tokenRecord = getTokenRecord();
@@ -564,19 +583,13 @@ public class TPSProcessor {
TPSBuffer card_cryptogram = null;
TPSBuffer sequenceCounter = null;
- boolean isGp211scp02 = false;
-
- if (platProtInfo.getPlatform().equals(SecureChannel.GP211)) {
- isGp211scp02 = true;
- }
-
card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
//CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: " + card_cryptogram.toHexString());
CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: extracted");
TPSBuffer card_challenge = null;
- if (isGp211scp02) {
+ if (platProtInfo.isSCP02()) {
sequenceCounter = initUpdateResp.substr(SEQUENCE_COUNTER_OFFSET_GP211_SC02, 2);
{
@@ -602,7 +615,15 @@ public class TPSProcessor {
tokenRecord.setKeyInfo(key_info_data.toHexStringPlain());
+ } else if (platProtInfo.isSCP03()) {
+ card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET_GP211_SC03,CARD_CHALLENGE_SIZE);
+ card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET_GP211_SC03, CARD_CRYPTOGRAM_SIZE);
+
+ CMS.debug("TPSProcessor.setupSecureChannel 03: card cryptogram: " + card_cryptogram.toHexString());
+ CMS.debug("TPSProcessor.setupSecureChannel 03: card challenge: " + card_challenge.toHexString());
+ CMS.debug("TPSProcessor.setupSecureChannel 03: host challenge: " + randomData.toHexString());
} else {
+
card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE);
}
//CMS.debug("TPSProcessor.setupSecureChannel: card challenge: " + card_challenge.toHexString());
@@ -628,6 +649,8 @@ public class TPSProcessor {
TPSBuffer sequenceCounter,AppletInfo appletInfo)
throws EBaseException, TPSException, IOException {
+ String method = "TPSProcessor.generateSecureChannel:";
+
if (connId == null || keyDiversificationData == null || keyInfoData == null || cardChallenge == null
|| cardCryptogram == null || hostChallenge == null || appletInfo == null) {
throw new TPSException("TPSProcessor.generateSecureChannel: Invalid input data!",
@@ -654,6 +677,11 @@ public class TPSProcessor {
PK11SymKey cmacSessionKeySCP02 = null;
PK11SymKey rmacSessionKeySCP02 = null;
+ PK11SymKey encSessionKeySCP03 = null;
+ PK11SymKey macSessionKeySCP03 = null;
+ PK11SymKey kekSessionKeySCP03 = null;
+ PK11SymKey rmacSessionKeySCP03 = null;
+
SymmetricKey sharedSecret = null;
//Sanity checking
@@ -680,7 +708,14 @@ public class TPSProcessor {
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
- SecureChannelProtocol protocol = new SecureChannelProtocol();
+ SecureChannelProtocol protocol = null; //new SecureChannelProtocol();
+
+
+ if(platProtInfo.isSCP01() || platProtInfo.isSCP02() ) {
+ protocol = new SecureChannelProtocol(1);
+ } else if (platProtInfo.isSCP03()) {
+ protocol = new SecureChannelProtocol(3);
+ }
String tokenName = CryptoUtil.INTERNAL_TOKEN_FULL_NAME;
@@ -715,7 +750,6 @@ public class TPSProcessor {
if (hostCryptogram == null) {
throw new TPSException("TPSProcessor.generateSecureChannel: No host cryptogram returned from token!",
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
-
}
try {
@@ -725,9 +759,7 @@ public class TPSProcessor {
/* sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, (PK11SymKey) sharedSecret,
sessionKeyWrapped.toBytesArray()); */
-
- sessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, sessionKeyWrapped.toBytesArray(), false);
-
+ sessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, sessionKeyWrapped.toBytesArray(), false,SymmetricKey.DES3);
if (sessionKey == null) {
CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
@@ -740,7 +772,7 @@ public class TPSProcessor {
/* encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName,(PK11SymKey) sharedSecret,
encSessionKeyWrapped.toBytesArray()); */
- encSessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,encSessionKeyWrapped.toBytesArray(),false);
+ encSessionKey = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,encSessionKeyWrapped.toBytesArray(),false,SymmetricKey.DES3);
if (encSessionKey == null) {
CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
@@ -781,7 +813,7 @@ public class TPSProcessor {
}
- if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ if (platProtInfo.isSCP02()) {
//Generate the 4 keys we need for SCP02, Impl 15
if (sequenceCounter == null) {
@@ -805,8 +837,8 @@ public class TPSProcessor {
}
respCMac02 = engine.computeSessionKeySCP02(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
- sequenceCounter, new TPSBuffer(SecureChannel.C_MACDerivationConstant),
- connId, getSelectedTokenType(), getSelectedKeySet());
+ sequenceCounter, new TPSBuffer(SecureChannel.C_MACDerivationConstant), connId,
+ getSelectedTokenType(), getSelectedKeySet());
TPSBuffer cmacSessionKeyWrappedSCP02 = respCMac02.getSessionKey();
@@ -875,6 +907,43 @@ public class TPSProcessor {
}
+ if (platProtInfo.isSCP03()) {
+ CMS.debug("TPSProcessor.generateSecureChannel Trying secure channel protocol 03");
+
+ resp = engine.computeSessionKeysSCP03(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
+ cardChallenge, hostChallenge, cardCryptogram, connId, getSelectedTokenType(), getSelectedKeySet());
+
+ TPSBuffer encSessionKeyBuff = resp.getEncSessionKey();
+ TPSBuffer kekSessionKeyBuff = resp.getKekSessionKey();
+ TPSBuffer macSessionKeyBuff = resp.getMacSessionKey();
+ TPSBuffer hostCryptogramBuff = resp.getHostCryptogram();
+ TPSBuffer keyCheckBuff = resp.getKeyCheck();
+
+ TPSBuffer drmDesKeyBuff = resp.getDRM_Trans_DesKey();
+ TPSBuffer kekDesKeyBuff = resp.getKekWrappedDesKey();
+
+ CMS.debug(method + " encSessionKeyBuff: " + encSessionKeyBuff.toHexString());
+ CMS.debug(method + " kekSessionKeyBuff: " + kekSessionKeyBuff.toHexString());
+ CMS.debug(method + " macSessionKeyBuff: " + macSessionKeyBuff.toHexString());
+ CMS.debug(method + " hostCryptogramBuff: " + hostCryptogramBuff.toHexString());
+ CMS.debug(method + " keyCheckBuff: " + keyCheckBuff.toHexString());
+ CMS.debug(method + " drmDessKeyBuff: " + drmDesKeyBuff.toHexString());
+ CMS.debug(method + " kekDesKeyBuff: " + kekDesKeyBuff.toHexString());
+
+ encSessionKeySCP03 = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,
+ encSessionKeyBuff.toBytesArray(), false, SymmetricKey.AES);
+ macSessionKeySCP03 = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,
+ macSessionKeyBuff.toBytesArray(), false, SymmetricKey.AES);
+ kekSessionKeySCP03 = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret,
+ kekSessionKeyBuff.toBytesArray(), false, SymmetricKey.AES);
+
+ channel = new SecureChannel(this, encSessionKeySCP03, macSessionKeySCP03, kekSessionKeySCP03,
+ drmDesKeyBuff, kekDesKeyBuff,
+ keyCheckBuff, keyDiversificationData, cardChallenge,
+ cardCryptogram, hostChallenge, hostCryptogramBuff, keyInfoData,
+ platProtInfo);
+ }
+
if (channel == null) {
throw new TPSException(
"TPSProcessor.generateSecureChannel: Can't create Secure Channel, possibly invalid secure channel protocol requested.",
@@ -3141,9 +3210,6 @@ public class TPSProcessor {
The second byte is the key offset, which is always 1
*/
- byte[] nv = { (byte) requiredVersion, 0x01 };
- TPSBuffer newVersion = new TPSBuffer(nv);
-
// GetKeyInfoData will return a buffer which is bytes 11,12 of
// the data structure on page 89 of Cyberflex Access Programmer's
// Guide
@@ -3157,8 +3223,21 @@ public class TPSProcessor {
int protocol = 1;
if (channel.isSCP02()) {
protocol = 2;
+ } if (channel.isSCP03()) {
+ protocol = 3;
}
+ byte[] nv = null;
+
+ if(protocol == 3) {
+ nv = new byte[] { (byte) requiredVersion,curKeyInfo.at(1),curKeyInfo.at(2) };
+
+ } else {
+ nv = new byte[] { (byte) requiredVersion, 0x01 };
+ }
+
+ TPSBuffer newVersion = new TPSBuffer(nv);
+
//Sanity checking
boolean cuidOK = checkCUIDMatchesKDD(appletInfo.getCUIDhexStringPlain(), appletInfo.getKDDhexStringPlain());
@@ -3574,14 +3653,21 @@ public class TPSProcessor {
try {
gp211GetSecureChannelProtocolDetails();
} catch (TPSException e) {
+
+ if(platProtInfo.getProtocol() == SecureChannel.SECURE_PROTO_03) {
+ CMS.debug("PSProcessor.acquireChannelPlatformProtocolInfo: card is reporting SCP03, bail, we don't yet support!");
+ throw e;
+ }
+
CMS.debug("TPSProcessor.acquireChannelPlatformProtocolInfo: Error getting gp211 protocol data, assume scp01 "
+ e);
+
platProtInfo.setPlatform(SecureChannel.GP201);
platProtInfo.setProtocol(SecureChannel.SECURE_PROTO_01);
}
- if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ if (platProtInfo.isSCP02()) {
// We only support impl 15, the most common, at this point.
if (platProtInfo.getImplementation() != SecureChannel.GP211_SCP02_IMPL_15) {
@@ -3690,16 +3776,17 @@ public class TPSProcessor {
byte protocol = oidSecureChannelProtocol.at(length - 2);
byte implementation = oidSecureChannelProtocol.at(length - 1);
- if (protocol == SecureChannel.SECURE_PROTO_03) {
- throw new TPSException("TPSProcessor.gp211GetSecureChannelProtocolDetails: No support for SCP03 as of yet, bailing.",
- TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
- }
+
platProtInfo.setProtocol(protocol);
platProtInfo.setImplementation(implementation);
platProtInfo.setKeysetInfoData(keyData);
- if (protocol == SecureChannel.SECURE_PROTO_02)
+ if (protocol == SecureChannel.SECURE_PROTO_03) {
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: Found protocol 03!");
+ }
+
+ if ((protocol == SecureChannel.SECURE_PROTO_02) || (protocol == SecureChannel.SECURE_PROTO_03))
platProtInfo.setPlatform(SecureChannel.GP211);
else
platProtInfo.setPlatform(SecureChannel.GP201);
@@ -3714,6 +3801,12 @@ public class TPSProcessor {
return platProtInfo;
}
+ public int getProtocol() {
+ if(platProtInfo == null)
+ return SecureChannel.SECURE_PROTO_01;
+ return platProtInfo.getProtocol();
+ }
+
boolean checkCardGPKeyVersionIsInRange(String CUID, String KDD, String keyInfoData) throws TPSException {
boolean result = true;
@@ -3772,11 +3865,14 @@ public class TPSProcessor {
CMS.debug(method + " minVersion: " + minVersion + " maxVersion: " + maxVersion);
- if (keyInfoData.length() != 4) {
+ if( keyInfoData.length() != 4 && keyInfoData.length() != 6) {
result = false;
} else {
+
+
// Actually check the version range;
+
String keyInfoVer = keyInfoData.substring(0, 2);
CMS.debug(method + " Version reported from key Info Data: " + keyInfoVer);
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 57119ce2c..de1ac442c 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -19,7 +19,6 @@ package com.netscape.cmsutil.crypto;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.CharConversionException;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.PrintStream;
@@ -1614,25 +1613,18 @@ public class CryptoUtil {
}
}
- /**
- * Generates a symmetric key.
- */
- public static SymmetricKey generateKey(CryptoToken token,
- KeyGenAlgorithm alg, int keySize)
- throws TokenException, NoSuchAlgorithmException,
- IllegalStateException, InvalidAlgorithmParameterException {
- try {
- KeyGenerator kg = token.getKeyGenerator(alg);
- if (alg == KeyGenAlgorithm.AES || alg == KeyGenAlgorithm.RC4
- || alg == KeyGenAlgorithm.RC2) {
- kg.initialize(keySize);
- }
-
- return kg.generate();
- } catch (CharConversionException e) {
- throw new RuntimeException(
- "CharConversionException while generating symmetric key");
+ public static SymmetricKey generateKey(CryptoToken token, KeyGenAlgorithm alg, int keySize,
+ SymmetricKey.Usage[] usages, boolean temporary) throws Exception {
+ KeyGenerator kg = token.getKeyGenerator(alg);
+ if (usages != null)
+ kg.setKeyUsages(usages);
+ kg.temporaryKeys(temporary);
+ if (alg == KeyGenAlgorithm.AES || alg == KeyGenAlgorithm.RC4
+ || alg == KeyGenAlgorithm.RC2) {
+ kg.initialize(keySize);
}
+
+ return kg.generate();
}
/**
@@ -1908,18 +1900,6 @@ public class CryptoUtil {
return decodedData;
}
- public static byte[] unwrapUsingSymmetricKey(CryptoToken token, IVParameterSpec IV, byte[] wrappedRecoveredKey,
- SymmetricKey recoveryKey, EncryptionAlgorithm alg) throws NoSuchAlgorithmException, TokenException,
- BadPaddingException,
- IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException {
-
- Cipher decryptor = token.getCipherContext(alg);
- decryptor.initDecrypt(recoveryKey, IV);
- byte[] unwrappedData = decryptor.doFinal(wrappedRecoveredKey);
-
- return unwrappedData;
- }
-
public static byte[] wrapPassphrase(CryptoToken token, String passphrase, IVParameterSpec IV, SymmetricKey sk,
EncryptionAlgorithm alg)
throws NoSuchAlgorithmException, TokenException, InvalidKeyException,
@@ -1940,56 +1920,25 @@ public class CryptoUtil {
}
public static byte[] wrapSymmetricKey(CryptoManager manager, CryptoToken token, String transportCert,
- SymmetricKey sk) throws CertificateEncodingException, TokenException, NoSuchAlgorithmException,
- InvalidKeyException, InvalidAlgorithmParameterException {
+ SymmetricKey sk) throws Exception {
byte transport[] = Utils.base64decode(transportCert);
X509Certificate tcert = manager.importCACertPackage(transport);
- KeyWrapper rsaWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
- rsaWrap.initWrap(tcert.getPublicKey(), null);
- byte session_data[] = rsaWrap.wrap(sk);
- return session_data;
- }
-
- /**
- * Wrap a symmetric Key with a SymmetricKey
- *
- * @param token
- * @param secret
- * @param wrapper
- * @return
- * @throws TokenException
- * @throws NoSuchAlgorithmException
- * @throws InvalidAlgorithmParameterException
- * @throws InvalidKeyException
- */
- public static byte[] wrapSymmetricKey(CryptoToken token, SymmetricKey secret, SymmetricKey wrapper,
- IVParameterSpec IV) throws NoSuchAlgorithmException, TokenException, InvalidKeyException,
- InvalidAlgorithmParameterException {
- KeyWrapper wrapper1 = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper1.initWrap(wrapper, IV);
- byte[] keyData = wrapper1.wrap(secret);
-
- return keyData;
+ return wrapUsingPublicKey(token, tcert.getPublicKey(), sk, KeyWrapAlgorithm.RSA);
}
public static byte[] createPKIArchiveOptions(CryptoManager manager, CryptoToken token, String transportCert,
- SymmetricKey vek, String passphrase, KeyGenAlgorithm keyGenAlg, int symKeySize, IVParameterSpec IV) throws TokenException,
- CharConversionException,
- NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException,
- CertificateEncodingException, IOException, IllegalStateException, IllegalBlockSizeException,
- BadPaddingException, InvalidBERException {
+ SymmetricKey vek, String passphrase, KeyGenAlgorithm keyGenAlg, int symKeySize, IVParameterSpec IV)
+ throws Exception {
byte[] key_data = null;
//generate session key
- SymmetricKey sk = CryptoUtil.generateKey(token, keyGenAlg, symKeySize);
+ SymmetricKey sk = CryptoUtil.generateKey(token, keyGenAlg, symKeySize, null, false);
if (passphrase != null) {
key_data = wrapPassphrase(token, passphrase, IV, sk, EncryptionAlgorithm.DES3_CBC_PAD);
} else {
// wrap payload using session key
- KeyWrapper wrapper1 = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper1.initWrap(sk, IV);
- key_data = wrapper1.wrap(vek);
+ key_data = wrapUsingSymmetricKey(token, sk, vek, IV, KeyWrapAlgorithm.DES3_CBC_PAD);
}
// wrap session key using transport key
@@ -2001,19 +1950,11 @@ public class CryptoUtil {
public static byte[] createPKIArchiveOptions(
CryptoToken token, PublicKey wrappingKey, PrivateKey toBeWrapped,
KeyGenAlgorithm keyGenAlg, int symKeySize, IVParameterSpec IV)
- throws TokenException, NoSuchAlgorithmException,
- InvalidAlgorithmParameterException, InvalidKeyException,
- IOException, InvalidBERException {
- SymmetricKey sessionKey = CryptoUtil.generateKey(token, keyGenAlg, symKeySize);
-
- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper.initWrap(sessionKey, IV);
- byte[] key_data = wrapper.wrap(toBeWrapped);
-
- wrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
- wrapper.initWrap(wrappingKey, null);
- byte session_data[] = wrapper.wrap(sessionKey);
+ throws Exception {
+ SymmetricKey sessionKey = CryptoUtil.generateKey(token, keyGenAlg, symKeySize, null, false);
+ byte[] key_data = wrapUsingSymmetricKey(token, sessionKey, toBeWrapped, IV, KeyWrapAlgorithm.DES3_CBC_PAD);
+ byte[] session_data = wrapUsingPublicKey(token, wrappingKey, sessionKey, KeyWrapAlgorithm.RSA);
return createPKIArchiveOptions(IV, session_data, key_data);
}
@@ -2050,30 +1991,22 @@ public class CryptoUtil {
PublicKey pubkey, byte[] data)
throws InvalidBERException, Exception {
ByteArrayInputStream in = new ByteArrayInputStream(data);
- PKIArchiveOptions options = (PKIArchiveOptions)
- (new PKIArchiveOptions.Template()).decode(in);
+ PKIArchiveOptions options = (PKIArchiveOptions) (new PKIArchiveOptions.Template()).decode(in);
EncryptedKey encKey = options.getEncryptedKey();
EncryptedValue encVal = encKey.getEncryptedValue();
AlgorithmIdentifier algId = encVal.getSymmAlg();
BIT_STRING encSymKey = encVal.getEncSymmKey();
BIT_STRING encPrivKey = encVal.getEncValue();
- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
- wrapper.initUnwrap(unwrappingKey, null);
- SymmetricKey sk = wrapper.unwrapSymmetric(
- encSymKey.getBits(), SymmetricKey.Type.DES3, 0);
+ SymmetricKey sk = unwrap(token, SymmetricKey.Type.DES3, 0, null, unwrappingKey, encSymKey.getBits(),
+ KeyWrapAlgorithm.RSA);
ASN1Value v = algId.getParameters();
v = ((ANY) v).decodeWith(new OCTET_STRING.Template());
byte iv[] = ((OCTET_STRING) v).toByteArray();
IVParameterSpec ivps = new IVParameterSpec(iv);
- wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
- wrapper.initUnwrap(sk, ivps);
- PrivateKey.Type keyType = pubkey.getAlgorithm().equals("EC")
- ? PrivateKey.Type.EC
- : PrivateKey.Type.RSA;
- return wrapper.unwrapPrivate(encPrivKey.getBits(), keyType, pubkey);
+ return unwrap(token, pubkey, false, sk, encPrivKey.getBits(), KeyWrapAlgorithm.DES3_CBC_PAD, ivps);
}
public static boolean sharedSecretExists(String nickname) throws NotInitializedException, TokenException {
@@ -2098,22 +2031,22 @@ public class CryptoUtil {
km.deleteUniqueNamedKey(nickname);
}
- // Return a list of two wrapped keys: first element: temp DES3 key wrapped by cert , second element: shared secret wrapped by temp DES3 key
- public static List<byte[]> exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert,SymmetricKey wrappingKey)
- throws NotInitializedException, TokenException, IOException, NoSuchAlgorithmException, InvalidKeyException,
- InvalidAlgorithmParameterException, InvalidKeyFormatException {
+ // Return a list of two wrapped keys:
+ // first element: temp DES3 key wrapped by cert ,
+ // second element: shared secret wrapped by temp DES3 key
+ public static List<byte[]> exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert,
+ SymmetricKey wrappingKey) throws Exception {
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalKeyStorageToken();
List<byte[]> listWrappedKeys = new ArrayList<byte[]>();
-
KeyManager km = new KeyManager(token);
if (!km.uniqueNamedKeyExists(nickname)) {
throw new IOException("Shared secret " + nickname + " does not exist");
}
- SymmetricKey sharedSecretKey = null;
+ SymmetricKey sharedSecretKey = null;
try {
sharedSecretKey = getSymKeyByName(token, nickname);
@@ -2125,25 +2058,18 @@ public class CryptoUtil {
throw new IOException("Shared secret " + nickname + " does not exist");
}
- KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
PublicKey pub = wrappingCert.getPublicKey();
PK11PubKey pubK = PK11PubKey.fromSPKI(pub.getEncoded());
- keyWrap.initWrap(pubK, null);
//Wrap the temp DES3 key with the cert
- byte[] wrappedKey = keyWrap.wrap(wrappingKey);
-
+ byte[] wrappedKey = wrapUsingPublicKey(token, pubK, wrappingKey, KeyWrapAlgorithm.RSA);
listWrappedKeys.add(wrappedKey);
//Use the DES3 key to wrap the shared secret
- KeyWrapper keyWrapSharedSecret = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB);
- keyWrapSharedSecret.initWrap(wrappingKey,null);
-
- byte[] wrappedSharedSecret = keyWrapSharedSecret.wrap(sharedSecretKey);
-
+ byte[] wrappedSharedSecret = wrapUsingSymmetricKey(token, wrappingKey, sharedSecretKey, null, KeyWrapAlgorithm.DES3_ECB);
listWrappedKeys.add(wrappedSharedSecret);
- if(listWrappedKeys.size() != 2) {
+ if (listWrappedKeys.size() != 2) {
throw new IOException("Can't write out shared secret data to export for nickname: " + nickname);
}
@@ -2236,6 +2162,90 @@ public class CryptoUtil {
return vect;
}
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ //generic crypto operations
+ //////////////////////////////////////////////////////////////////////////////////////////////
+
+ public static byte[] decryptUsingSymmetricKey(CryptoToken token, IVParameterSpec ivspec, byte[] encryptedData,
+ SymmetricKey wrappingKey, EncryptionAlgorithm encryptionAlgorithm) throws Exception {
+ Cipher decryptor = token.getCipherContext(encryptionAlgorithm);
+ decryptor.initDecrypt(wrappingKey, ivspec);
+ return decryptor.doFinal(encryptedData);
+ }
+
+ public static byte[] encryptUsingSymmetricKey(CryptoToken token, SymmetricKey wrappingKey, byte[] data,
+ EncryptionAlgorithm alg, IVParameterSpec ivspec)
+ throws Exception {
+ Cipher cipher = token.getCipherContext(alg);
+ cipher.initEncrypt(wrappingKey, ivspec);
+ return cipher.doFinal(data);
+ }
+
+ public static byte[] wrapUsingSymmetricKey(CryptoToken token, SymmetricKey wrappingKey, SymmetricKey data,
+ IVParameterSpec ivspec, KeyWrapAlgorithm alg) throws Exception {
+ KeyWrapper wrapper = token.getKeyWrapper(alg);
+ wrapper.initWrap(wrappingKey, ivspec);
+ return wrapper.wrap(data);
+ }
+
+ public static byte[] wrapUsingSymmetricKey(CryptoToken token, SymmetricKey wrappingKey, PrivateKey data,
+ IVParameterSpec ivspec, KeyWrapAlgorithm alg) throws Exception {
+ KeyWrapper wrapper = token.getKeyWrapper(alg);
+ wrapper.initWrap(wrappingKey, ivspec);
+ return wrapper.wrap(data);
+ }
+
+ public static byte[] wrapUsingPublicKey(CryptoToken token, PublicKey wrappingKey, SymmetricKey data,
+ KeyWrapAlgorithm alg) throws Exception {
+ KeyWrapper rsaWrap = token.getKeyWrapper(alg);
+ rsaWrap.initWrap(wrappingKey, null);
+ return rsaWrap.wrap(data);
+ }
+
+ public static SymmetricKey unwrap(CryptoToken token, SymmetricKey.Type keyType,
+ int strength, SymmetricKey.Usage usage, SymmetricKey wrappingKey, byte[] wrappedData,
+ KeyWrapAlgorithm wrapAlgorithm, IVParameterSpec wrappingIV) throws Exception {
+ KeyWrapper wrapper = token.getKeyWrapper(wrapAlgorithm);
+ wrapper.initUnwrap(wrappingKey, wrappingIV);
+ return wrapper.unwrapSymmetric(wrappedData, keyType, usage, strength);
+ }
+
+ public static SymmetricKey unwrap(CryptoToken token, SymmetricKey.Type keyType,
+ int strength, SymmetricKey.Usage usage, PrivateKey wrappingKey, byte[] wrappedData,
+ KeyWrapAlgorithm wrapAlgorithm) throws Exception {
+ KeyWrapper keyWrapper = token.getKeyWrapper(wrapAlgorithm);
+ keyWrapper.initUnwrap(wrappingKey, null);
+
+ return keyWrapper.unwrapSymmetric(wrappedData, keyType, usage, strength);
+ }
+
+ public static PrivateKey unwrap(CryptoToken token, PublicKey pubKey, boolean temporary,
+ SymmetricKey wrappingKey, byte[] wrappedData, KeyWrapAlgorithm wrapAlgorithm, IVParameterSpec wrapIV)
+ throws Exception {
+ KeyWrapper wrapper = token.getKeyWrapper(wrapAlgorithm);
+ wrapper.initUnwrap(wrappingKey, wrapIV);
+
+ // Get the key type for unwrapping the private key.
+ PrivateKey.Type keyType = null;
+ if (pubKey.getAlgorithm().equalsIgnoreCase("RSA")) {
+ keyType = PrivateKey.RSA;
+ } else if (pubKey.getAlgorithm().equalsIgnoreCase("DSA")) {
+ keyType = PrivateKey.DSA;
+ } else if (pubKey.getAlgorithm().equalsIgnoreCase("EC")) {
+ keyType = PrivateKey.EC;
+ }
+
+ PrivateKey pk = null;
+ if (temporary) {
+ pk = wrapper.unwrapTemporaryPrivate(wrappedData,
+ keyType, pubKey);
+ } else {
+ pk = wrapper.unwrapPrivate(wrappedData,
+ keyType, pubKey);
+ }
+ return pk;
+ }
}
// START ENABLE_ECC
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 9adb62972..0b164aafc 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -47,7 +47,6 @@ import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.InternalCertificate;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
-import org.mozilla.jss.crypto.KeyGenerator;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.KeyWrapper;
import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
@@ -68,6 +67,8 @@ import org.mozilla.jss.util.Password;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
import netscape.ldap.LDAPDN;
import netscape.ldap.util.DN;
import netscape.security.x509.X509CertImpl;
@@ -114,18 +115,19 @@ public class PKCS12Util {
}
byte[] getEncodedKey(PrivateKey privateKey) throws Exception {
-
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalKeyStorageToken();
- KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
- SymmetricKey sk = kg.generate();
-
- KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
IVParameterSpec param = new IVParameterSpec(iv);
- wrapper.initWrap(sk, param);
- byte[] enckey = wrapper.wrap(privateKey);
+
+ SymmetricKey sk = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, true);
+ byte[] enckey = CryptoUtil.wrapUsingSymmetricKey(
+ token,
+ sk,
+ privateKey,
+ param,
+ KeyWrapAlgorithm.DES3_CBC_PAD);
Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
c.initDecrypt(sk, param);
@@ -592,6 +594,9 @@ public class PKCS12Util {
logger.debug("Importing private key " + keyInfo.subjectDN);
+ byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+ IVParameterSpec param = new IVParameterSpec(iv);
+
PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo;
// encode private key
@@ -622,13 +627,9 @@ public class PKCS12Util {
}
// encrypt private key
- KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
- SymmetricKey sk = kg.generate();
- byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
- IVParameterSpec param = new IVParameterSpec(iv);
- Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
- c.initEncrypt(sk, param);
- byte[] encpkey = c.doFinal(privateKey);
+ SymmetricKey sk = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, true);
+ byte[] encpkey = CryptoUtil.encryptUsingSymmetricKey(
+ token, sk, privateKey, EncryptionAlgorithm.DES3_CBC_PAD, param);
// unwrap private key to load into database
KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
diff --git a/pylint-build-scan.py b/pylint-build-scan.py
index d4156e87b..3a7b47321 100755
--- a/pylint-build-scan.py
+++ b/pylint-build-scan.py
@@ -38,7 +38,6 @@ PYLINTRC = os.path.join(SCRIPTPATH, 'dogtag.pylintrc')
FILENAMES = [
os.path.abspath(__file__),
'{sitepackages}/pki',
- '{bin}/pki-cmd', # see HACK
'{sbin}/pkispawn',
'{sbin}/pkidestroy',
'{sbin}/pki-upgrade',
@@ -130,17 +129,7 @@ def main():
if args.verbose:
pprint.pprint(pylint)
- # HACK:
- # pylint confuses the pki command with the pki package. We create a
- # symlink from bin/pki to bin/pki-cmd and test bin/pki-cmd instead.
- pki_bin = '{bin}/pki'.format(**env)
- pki_cmd = '{bin}/pki-cmd'.format(**env)
- os.symlink(pki_bin, pki_cmd)
-
- try:
- return subprocess.call(pylint, cwd=env['sitepackages'])
- finally:
- os.unlink(pki_cmd)
+ return subprocess.call(pylint, cwd=env['sitepackages'])
if __name__ == '__main__':
sys.exit(main())
diff --git a/specs/dogtag-pki-theme.spec b/specs/dogtag-pki-theme.spec
index f87c1b578..12b73702a 100644
--- a/specs/dogtag-pki-theme.spec
+++ b/specs/dogtag-pki-theme.spec
@@ -1,6 +1,6 @@
Name: dogtag-pki-theme
Version: 10.4.0
-Release: 0.1%{?dist}
+Release: 1%{?dist}
Summary: Certificate System - Dogtag PKI Theme Components
URL: http://pki.fedoraproject.org/
License: GPLv2
@@ -168,6 +168,9 @@ cd build
%changelog
+* Tue Mar 14 2017 Dogtag Team <pki-devel@redhat.com> 10.4.0-1
+- dogtagpki Pagure Issue #2541 - Re-base Dogtag pki packages to 10.4.x
+
* Mon Aug 8 2016 Dogtag Team <pki-devel@redhat.com> 10.4.0-0.1
- Updated version number to 10.4.0-0.1
diff --git a/specs/dogtag-pki.spec b/specs/dogtag-pki.spec
index 040ca0151..4e0b13d47 100644
--- a/specs/dogtag-pki.spec
+++ b/specs/dogtag-pki.spec
@@ -7,7 +7,7 @@
Summary: Dogtag Public Key Infrastructure (PKI) Suite
Name: dogtag-pki
Version: 10.4.0
-Release: 0.1%{?dist}
+Release: 1%{?dist}
# The entire source code is GPLv2 except for 'pki-tps' which is LGPLv2
License: GPLv2 and LGPLv2
URL: http://pki.fedoraproject.org/
@@ -19,7 +19,7 @@ BuildArch: noarch
%define esc_version 1.1.0
# NOTE: The following package versions are TLS compliant:
%if 0%{?rhel}
-%define pki_core_rhel_version 10.3.3
+%define pki_core_rhel_version 10.4.0
%define pki_core_rhcs_version %{version}
%else
%define pki_core_version %{version}
@@ -124,6 +124,9 @@ rm -rf %{buildroot}
%doc README
%changelog
+* Tue Mar 14 2017 Dogtag Team <pki-devel@redhat.com> 10.4.0-1
+- dogtagpki Pagure Issue #2541 - Re-base Dogtag pki packages to 10.4.x
+
* Mon Aug 8 2016 Dogtag Team <pki-devel@redhat.com> 10.4.0-0.1
- Updated version number to 10.4.0-0.1
diff --git a/specs/pki-console.spec b/specs/pki-console.spec
index 6a6a282e5..86c3f2d0e 100644
--- a/specs/pki-console.spec
+++ b/specs/pki-console.spec
@@ -1,6 +1,6 @@
Name: pki-console
Version: 10.4.0
-Release: 0.1%{?dist}
+Release: 1%{?dist}
Summary: Certificate System - PKI Console
URL: http://pki.fedoraproject.org/
License: GPLv2
@@ -9,7 +9,7 @@ Group: System Environment/Base
%bcond_without javadoc
%if 0%{?rhel}
-%define pki_core_rhel_version 10.3.3
+%define pki_core_rhel_version 10.4.0
%define pki_core_version %{pki_core_rhel_version}
%else
%define pki_core_version %{version}
@@ -27,7 +27,7 @@ BuildRequires: nspr-devel
BuildRequires: nss-devel
BuildRequires: junit
BuildRequires: jpackage-utils >= 1.7.5-10
-BuildRequires: jss >= 4.2.6-40
+BuildRequires: jss >= 4.4.0-1
BuildRequires: pki-base-java >= %{pki_core_version}
Requires: idm-console-framework
@@ -36,7 +36,7 @@ Requires: ldapjdk
Requires: pki-base-java >= %{pki_core_version}
Requires: pki-console-theme >= %{version}
Requires: jpackage-utils >= 1.7.5-10
-Requires: jss >= 4.2.6-40
+Requires: jss >= 4.4.0-1
%if 0%{?rhel}
# NOTE: In the future, as a part of its path, this URL will contain a release
@@ -98,6 +98,10 @@ cd build
%changelog
+* Tue Mar 14 2017 Dogtag Team <pki-devel@redhat.com> 10.4.0-1
+- Require "jss >= 4.4.0-1" as a build and runtime requirement
+- dogtagpki Pagure Issue #2541 - Re-base Dogtag pki packages to 10.4.x
+
* Mon Aug 8 2016 Dogtag Team <pki-devel@redhat.com> 10.4.0-0.1
- Updated version number to 10.4.0-0.1
diff --git a/specs/pki-core.spec b/specs/pki-core.spec
index 39911af41..2ef46e28d 100644
--- a/specs/pki-core.spec
+++ b/specs/pki-core.spec
@@ -13,7 +13,7 @@
%global package_rhel_packages 1
# Package RHCS-specific RPMS Only
%global package_rhcs_packages 1
-%define pki_core_rhel_version 10.3.3
+%define pki_core_rhel_version 10.4.0
%else
# 0%{?fedora}
# Fedora always packages all RPMS
@@ -65,7 +65,7 @@
Name: pki-core
Version: 10.4.0
-Release: 0.1%{?dist}
+Release: 1%{?dist}
Summary: Certificate System - PKI Core Components
URL: http://pki.fedoraproject.org/
License: GPLv2
@@ -170,16 +170,16 @@ BuildRequires: policycoreutils-python-utils
BuildRequires: python-ldap
BuildRequires: junit
BuildRequires: jpackage-utils >= 0:1.7.5-10
-BuildRequires: jss >= 4.2.6-40
+BuildRequires: jss >= 4.4.0-1
BuildRequires: systemd-units
%if 0%{?rhel}
-BuildRequires: tomcatjss >= 7.1.2-2
+BuildRequires: tomcatjss >= 7.2.1-1
%else
%if 0%{?fedora} >= 23
-BuildRequires: tomcatjss >= 7.1.3
+BuildRequires: tomcatjss >= 7.2.1-1
%else
-BuildRequires: tomcatjss >= 7.1.2-2
+BuildRequires: tomcatjss >= 7.1.3
%endif
%endif
@@ -318,7 +318,7 @@ Requires: nss >= 3.14.3
%endif
Requires: jpackage-utils >= 0:1.7.5-10
-Requires: jss >= 4.2.6-40
+Requires: jss >= 4.4.0-1
Provides: symkey = %{version}-%{release}
@@ -400,7 +400,7 @@ Requires: slf4j-jdk14
%endif
Requires: javassist
Requires: jpackage-utils >= 0:1.7.5-10
-Requires: jss >= 4.2.6-40
+Requires: jss >= 4.4.0-1
Requires: ldapjdk
Requires: pki-base = %{version}-%{release}
@@ -583,12 +583,12 @@ Requires(postun): systemd-units
Requires(pre): shadow-utils
%if 0%{?rhel}
-Requires: tomcatjss >= 7.1.2-2
+Requires: tomcatjss >= 7.2.1-1
%else
%if 0%{?fedora} >= 23
-Requires: tomcatjss >= 7.1.3
+Requires: tomcatjss >= 7.2.1-1
%else
-Requires: tomcatjss >= 7.1.2-2
+Requires: tomcatjss >= 7.1.3
%endif
%endif
@@ -1347,17 +1347,297 @@ systemctl daemon-reload
%endif # %{with server}
%changelog
-* Mon Aug 8 2016 Dogtag Team <pki-devel@redhat.com> 10.4.0-0.1
+* Tue Mar 14 2017 Dogtag Team <pki-devel@redhat.com> 10.4.0-1
+- Require "jss >= 4.4.0-1" as a build and runtime requirement
+- Require "tomcatjss >= 7.2.1-1" as a build and runtime requirement
+- ############################################################################
+- dogtagpki Pagure Issue #2541 - Re-base Dogtag pki packages to 10.4.x
+- ############################################################################
+- dogtagpki Pagure Issue #6 - Remove Policy Framework Deprecations (edewata)
+- dogtagpki Pagure Issue #850 - JSS certificate validation function does not
+ pass up exact errors from NSS (edewata)
+- dogtagpki Pagure Issue #1114 - [MAN] Generting Symmetric key fails with
+ key-generate when --usages verify is passed (vakwetu)
+- dogtagpki Pagure Issue #1247 - Better error message when try to renew a
+ certificate that expires outside renewal grace period (vakwetu)
+- dogtagpki Pagure Issue #1309 - Recovering of a revoked cert erroneously
+ reflects "active" in the token db cert entry (cfu)
+- dogtagpki Pagure Issue #1490 - add option to bypass dnsdomainname check in
+ pkispawn (vakwetu)
+- dogtagpki Pagure Issue #1517 - user-cert-add --serial CLI request to secure
+ port with remote CA shows authentication failure (edewata)
+- dogtagpki Pagure Issue #1527 - TPS Enrollment always goes to "ca1" (cfu)
+- dogtagpki Pagure Issue #1536 - CA EE: Submit caUserCert request without uid
+ does not show proper error message (vakwetu)
+- dogtagpki Pagure Issue #1663 - Add SCP03 support (jmagne)
+- dogtagpki Pagure Issue #1664 - [BUG] Add ability to disallow TPS to enroll
+ a single user on multiple tokens. (jmagne)
+- dogtagpki Pagure Issue #1710 - Add profile component that copies CN to SAN
+ (ftweedal)
+- dogtagpki Pagure Issue #1741 - ECDSA Certificates Generated by Certificate
+ System fail NIST validation test with parameter field. (cfu)
+- dogtagpki Pagure Issue #1897 - [MAN] Man page for logging configuration.
+ (edewata)
+- dogtagpki Pagure Issue #1920 - [MAN] Man page for PKCS #12 utilities
+ (edewata)
+- dogtagpki Pagure Issue #2275 - add options to enable/disable cert or crl
+ publishing. (vakwetu)
+- dogtagpki Pagure Issue #2289 - [MAN] pki ca-cert-request-submit fails
+ presumably because of missing authentication even if it should not require
+ any (edewata)
+- dogtagpki Pagure Issue #2450 - Unable to search certificate requests using
+ the latest request ID (edewata)
+- dogtagpki Pagure Issue #2453 - IPA replica-prepare failed with error
+ "Profile caIPAserviceCert Not Found" (ftweedal)
+- dogtagpki Pagure Issue #2457 - Misleading Logging for HSM (edewata)
+- dogtagpki Pagure Issue #2460 - Typo in comment line of
+ UserPwdDirAuthentication.java (edewata)
+- dogtagpki Pagure Issue #2463 - Troubleshooting improvements (edewata)
+- dogtagpki Pagure Issue #2466 - two-step externally-signed CA installation
+ fails due to missing AuthorityID (ftweedal)
+- dogtagpki Pagure Issue #2475 - Multiple host authority entries created
+ (ftweedal)
+- dogtagpki Pagure Issue #2476 - Miscellaneous Minor Changes (edewata)
+- dogtagpki Pagure Issue #2478 - pkispawn fails as it is not able to find
+ openssl as a dependency package (mharmsen)
+- dogtagpki Pagure Issue #2483 - Unable to read an encrypted email using
+ renewed tokens (jmagne)
+- dogtagpki Pagure Issue #2486 - Automatic recovery of encryption cert is not
+ working when a token is physically damaged and a temporary token is issue
+ (jmagne)
+- dogtagpki Pagure Issue #2496 -Cert/Key recovery is successful when the cert
+ serial number and key id on the ldap user mismatches (cfu)
+- dogtagpki Pagure Issue #2497 - KRA installation failed against
+ externally-signed CA with partial certificate chain (edewata)
+- dogtagpki Pagure Issue #2498 -Token format with external reg fails when
+ op.format.externalRegAddToToken.revokeCert=true (cfu)
+- dogtagpki Pagure Issue #2500 - Problems with FIPS mode (edewata)
+- dogtagpki Pagure Issue #2505 - Fix packaging duplicates of classes in
+ multiple jar files (edewata)
+- dogtagpki Pagure Issue #2510 - PIN_RESET policy is not giving expected
+ results when set on a token (jmagne)
+- dogtagpki Pagure Issue #2513 -TPS token enrollment fails to
+ setupSecureChannel when TPS and TKS security db is on fips mode. (jmagne)
+- dogtagpki Pagure Issue #2523 - Changes to target.agent.approve.list
+ parameter is not reflected in the TPS Web UI (edewata)
+- dogtagpki Pagure Issue #2524 - Remove xenroll.dll from pki-core (mharmsen)
+- dogtagpki Pagure Issue #2525 - [RFE] FreeIPA to Dogtag permission mapping
+ plugin (ftweedal)
+- dogtagpki Pagure Issue #2532 - [RFE] add express archivals and retrievals
+ from KRA (vakwetu)
+- dogtagpki Pagure Issue #2534 - Automatic recovery of encryption cert - CA
+ and TPS tokendb shows different certificate status (cfu)
+- dogtagpki Pagure Issue #2543 - Unable to install subordinate CA with HSM in
+ FIPS mode (edewata)
+- dogtagpki Pagure Issue #2544 - TPS throws "err=6" when attempting to format
+ and enroll G&D Cards (jmagne)
+- dogtagpki Pagure Issue #2552 - pkispawn does not change default ecc key size
+ from nistp256 when nistp384 is specified in spawn config (jmagne)
+- dogtagpki Pagure Issue #2556 - pkispawn fails to create PKI subsystem on
+ FIPS enabled system (edewata)
+- dogtagpki Pagure Issue #2564 - pki-tomcat for 10+ minutes before generating
+ cert (edewata)
+- dogtagpki Pagure Issue #2569 - Token memory not wiped after key deletion
+ (jmagne)
+- dogtagpki Pagure Issue #2570 - Problem with default AJP hostname in IPv6
+ environment. (edewata)
+- dogtagpki Pagure Issue #2571 - Request ID undefined for CA signing
+ certificate (vakwetu)
+- dogtagpki Pagure Issue #2573 - CA Certificate Issuance Date displayed on CA
+ website incorrect (vakwetu)
+- dogtagpki Pagure Issue #2579 - NumberFormatException in
+ LDAPProfileSubsystem (ftweedal)
+- dogtagpki Pagure Issue #2582 - Access banner (edewata)
+- dogtagpki Pagure Issue #2601 - Return revocation reason in GET
+ /ca/rest/certs/{id} response. (ftweedal)
+- ############################################################################
+
+* Mon Mar 6 2017 Dogtag Team <pki-devel@redhat.com> 10.4.0-0.1
- Updated version number to 10.4.0-0.1
+- NOTE: Original date was Mon Aug 8 2016
+
+* Mon Mar 6 2017 Dogtag Team <pki-devel@redhat.com> 10.3.5-13
+- PKI TRAC Ticket #1710 - Add profile component that copies CN to SAN (ftweedal)
+
+* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 10.3.5-12
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Tue Jan 31 2017 Dogtag Team <pki-devel@redhat.com> 10.3.5-11
+
+* Thu Dec 22 2016 Miro HronĨok <mhroncok@redhat.com> - 10.3.5-10
+- Rebuild for Python 3.6 (Fedora 26)
+
+* Tue Dec 13 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-9
+- PKI TRAC Ticket #1517 - user-cert-add --serial CLI request to secure port
+ with remote CA shows authentication failure (edewata)
+- PKI TRAC Ticket #1897 - [MAN] Man page for logging configuration. (edewata)
+- PKI TRAC Ticket #1920 - [MAN] Man page for PKCS #12 utilities (edewata)
+- PKI TRAC Ticket #2226 - KRA installation: NullPointerException in
+ ProxyRealm.findSecurityConstraints (edewata)
+- PKI TRAC Ticket #2289 - [MAN] pki ca-cert-request-submit fails presumably
+ because of missing authentication even if it should not require any (edewata)
+- PKI TRAC Ticket #2523 - Changes to target.agent.approve.list parameter is
+ not reflected in the TPS Web UI [pki-base] (edewata)
+- PKI TRAC Ticket #2534 - Automatic recovery of encryption cert - CA and TPS
+ tokendb shows different certificate status (cfu)
+- PKI TRAC Ticket #2543 - Unable to install subordinate CA with HSM in FIPS
+ mode (edewata)
+- PKI TRAC Ticket #2544 - TPS throws "err=6" when attempting to format and
+ enroll G&D Cards (jmagne)
+- PKI TRAC Ticket #2552 - pkispawn does not change default ecc key size from
+ nistp256 when nistp384 is specified in spawn config (jmagne)
+
+* Fri Nov 4 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-8
+- PKI TRAC Ticket #850 - JSS certificate validation function does not pass up
+ exact errors from NSS (edewata)
+ (Failed to start pki-tomcatd Service - "ipa-cacert-manage renew" failed?)
+- PKI TRAC Ticket #1247 - Better error message when try to renew a certificate
+ that expires outside renewal grace period (alee)
+- PKI TRAC Ticket #1536 - CA EE: Submit caUserCert request without uid does
+ not show proper error message (alee)
+- PKI TRAC Ticket #2460 - Typo in comment line of UserPwdDirAuthentication.java
+ (edewata)
+- PKI TRAC Ticket #2486 - Automatic recovery of encryption cert is not working
+ when a token is physically damaged and a temporary token is issued (jmagne)
+- PKI TRAC Ticket #2498 - Token format with external reg fails when
+ op.format.externalRegAddToToken.revokeCert=true (cfu)
+- PKI TRAC Ticket #2500 - Problems with FIPS mode (edewata)
+- PKI TRAC Ticket #2500 - Problems with FIPS mode (edewata)
+ (added KRA key recovery via CLI in FIPS mode)
+- PKI TRAC Ticket #2510 - PIN_RESET policy is not giving expected results when
+ set on a token (jmagne)
+- PKI TRAC Ticket #2513 - TPS token enrollment fails to setupSecureChannel
+ when TPS and TKS security db is on fips mode. (jmagne)
+- Reverted patches associated with
+ PKI TRAC Ticket #2523 - Changes to target.agent.approve.list parameter is
+ not reflected in the TPS Web UI
+
+* Mon Oct 10 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-7
+- PKI TRAC Ticket #1527 - TPS Enrollment always goes to "ca1" (cfu)
+- PKI TRAC Ticket #1664 - [BUG] Add ability to disallow TPS to enroll a single
+ user on multiple tokens. (jmagne)
+- PKI TRAC Ticket #2463 - Troubleshooting improvements (edewata)
+- PKI TRAC Ticket #2466 - two-step externally-signed CA installation fails due
+ to missing AuthorityID (ftweedal)
+- PKI TRAC Ticket #2475 - Multiple host authority entries created (ftweedal)
+- PKI TRAC Ticket #2476 - Dogtag 10.4.0 Miscellaneous Minor Changes
+ (edewata)
+- PKI TRAC Ticket #2478 - pkispawn fails as it is not able to find openssl as a
+ dependency package (mharmsen)
+- PKI TRAC Ticket #2483 - Unable to read an encrypted email using renewed
+ tokens (jmagne)
+- PKI TRAC Ticket #2496 - Cert/Key recovery is successful when the cert serial
+ number and key id on the ldap user mismatches (cfu)
+- PKI TRAC Ticket #2497 - KRA installation failed against externally-signed CA
+ with partial certificate chain (edewata)
+- PKI TRAC Ticket #2505 - Fix packaging duplicates of classes in multiple jar
+ files (edewata)
+- Fix for flake8 errors on Fedora 26 (cheimes)
+
+* Fri Sep 9 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-6
+- Revert Patch: PKI TRAC Ticket #2449 - Unable to create system certificates
+ in different tokens (edewata)
+
+* Tue Sep 6 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-5
+- PKI TRAC Ticket #1638 - Lightweight CAs: revoke certificate on CA deletion
+ (ftweedal)
+- PKI TRAC Ticket #2436 - Dogtag 10.3.6: Miscellaneous Enhancements
+ (edewata)
+- PKI TRAC Ticket #2443 - Prevent deletion of host CA's keys if LWCA entry
+ deleted (ftweedal)
+- PKI TRAC Ticket #2444 - Authority entry without entryUSN is skipped even if
+ USN plugin enabled (ftweedal)
+- PKI TRAC Ticket #2446 - pkispawn: make subject_dn defaults unique per
+ instance name (for shared HSM) (cfu)
+- PKI TRAC Ticket #2447 - CertRequestInfo has incorrect URLs (vakwetu)
+- PKI TRAC Ticket #2449 - Unable to create system certificates in different
+ tokens (edewata)
+
+* Mon Aug 29 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-4
+- PKI TRAC Ticket #1578 - Authentication Instance Id PinDirEnrollment with authType value as SslclientAuth is not working (jmagne)
+- PKI TRAC TIcket #2414 - pki pkcs12-cert-del shows a successfully deleted message when a wrong nickname is provided (gkapoor)
+- PKI TRAC Ticket #2423 - pki_ca_signing_token when not specified does not fallback to pki_token_name value (edewata)
+- PKI TRAC Ticket #2436 - Dogtag 10.3.6: Miscellaneous Enhancements (akasurde) - ticket remains open
+- PKI TRAC Ticket #2439 - Outdated deployment descriptors in upgraded server(edewata)
+
+* Mon Aug 22 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-3
+- spec file changes
+
+* Mon Aug 22 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-2
+- PKI TRAC Ticket #690 - [MAN] pki-tools man pages (mharmsen)
+ - CMCEnroll
+- PKI TRAC Ticket #833 - pki user-mod fullName="" gives an error message
+ "PKIException: LDAP error (21): error result" (edewata)
+- PKI TRAC Ticket #2431 - Errors noticed during ipa server upgrade.
+ (cheimes, edewata, mharmsen)
+- PKI TRAC Ticket #2432 - Kra-selftest behavior is not as expected (edewata)
+- PKI TRAC Ticket #2436 - Dogtag 10.3.6: Miscellaneous Enhancements
+ (edewata, mharmsen)
+- PKI TRAC Ticket #2437 - TPS UI: while adding certs for users from TPSUI pem
+ format with/without header works while pkcs7 with header is not allowed
+ (edewata)
+- PKI TRAC Ticket #2440 - Optional CA signing CSR for migration (edewata)
* Mon Aug 8 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-1
- Updated version number to 10.3.5-1
-* Tue Jul 5 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-0.1
+* Tue Jul 19 2016 Dogtag Team <pki-devel@redhat.com> 10.3.5-0.1
- Updated version number to 10.3.5-0.1
+- NOTE: Original date was Tue Jul 5 2016
-* Tue Jun 21 2016 Dogtag Team <pki-devel@redhat.com> 10.3.4-0.1
+* Tue Jul 19 2016 Dogtag Team <pki-devel@redhat.com> 10.3.4-0.1
- Updated version number to 10.3.4-0.1
+- NOTE: Original date was Tue Jun 21 2016
+
+* Tue Jul 19 2016 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 10.3.3-4
+- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages
+
+* Tue Jul 5 2016 Dogtag Team <pki-devel@redhat.com> 10.3.3-3
+- PKI TRAC Ticket #691 - [MAN] pki-server man pages (mharmsen)
+- PKI TRAC Ticket #1114 - [MAN] Generting Symmetric key fails with
+ key-generate when --usages verify is passed (jmagne)
+- PKI TRAC Ticket #1306 - [RFE] Add granularity to token termination in TPS
+ (cfu)
+- PKI TRAC Ticket #1308 - [RFE] Provide ability to perform off-card key
+ generation for non-encryption token keys (cfu)
+- PKI TRAC Ticket #1405 - [MAN] Add additional HSM details to
+ 'pki_default.cfg' & 'pkispawn' man pages (mharmsen)
+- PKI TRAC Ticket #1607 - [MAN] man pkispawn has inadequate description for
+ shared vs non shared tomcat instance installation (mharmsen)
+- PKI TRAC Ticket #1664 - [BUG] Add ability to disallow TPS to enroll a single
+ user on multiple tokens. (jmagne)
+- PKI TRAC Ticket #1711 - CLI :: pki-server ca-cert-request-find throws
+ IOError (edewata, ftweedal)
+- PKI TRAC Ticket #2285 - freeipa fails to start correctly after pki-core
+ update on upgraded system (ftweedal)
+- PKI TRAC Ticket #2311 - When pki_token_name=Internal, consider normalizing
+ it to "internal" (mharmsen)
+- PKI TRAC Ticket #2349 - Separated TPS does not automatically receive shared
+ secret from remote TKS (jmagne)
+- PKI TRAC Ticket #2364 - CLI :: pki-server ca-cert-request-show throws
+ attribute error (ftweedal)
+- PKI TRAC Ticket #2368 - pki-server subsystem subcommands throws error with
+ --help option (edewata)
+- PKI TRAC Ticket #2374 - KRA cloning overwrites CA signing certificate trust
+ flags (edewata)
+- PKI TRAC Ticket #2380 - Pki-server instance commands throws exception while
+ specifying invalid parameters. (edewata)
+- PKI TRAC Ticket #2384 - CA installation with HSM prompts for HSM password
+ during silent installation (edewata)
+- PKI TRAC Ticket #2385 - Upgraded CA lacks ca.sslserver.certreq in CS.cfg
+ (ftweedal)
+- PKI TRAC Ticket #2387 - Add config for default OCSP URI if none given
+ (ftweedal)
+- PKI TRAC Ticket #2388 - CA creation responds 500 if certificate issuance
+ fails (ftweedal)
+- PKI TRAC Ticket #2389 - Installation: subsystem certs could have notAfter
+ beyond CA signing cert in case of external or existing CA (cfu)
+- PKI TRAC Ticket #2390 - Dogtag 10.3.4: Miscellaneous Enhancements
+ (akasurde, edewata)
+
+* Thu Jun 30 2016 Dogtag Team <pki-devel@redhat.com> 10.3.3-2
+- PKI TRAC Ticket #2373 - Fedora 25: RestEasy 3.0.6 ==> 3.0.17 breaks
+ pki-core (ftweedal)
* Mon Jun 20 2016 Dogtag Team <pki-devel@redhat.com> 10.3.3-1
- Updated release number to 10.3.3-1
diff --git a/tox.ini b/tox.ini
index 2430a95ee..f73818d9c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -92,7 +92,7 @@ python_files = tests/python/*.py
[flake8]
ignore = N802,N806,N812
exclude = .tox,*.egg,dist,build,conf.py,tests/dogtag/*,.git
-filename = *.py,pki,pkidestroy,pki-upgrade,pki-server,pki-server-upgrade,pkispawn,[0-9][0-9]-*
+filename = *.py,pkidestroy,pki-upgrade,pki-server,pki-server-upgrade,pkispawn,[0-9][0-9]-*
show-source = true
max-line-length = 99
# application-import-names = pki