diff options
| author | Ade Lee <alee@redhat.com> | 2017-03-15 23:05:07 -0400 |
|---|---|---|
| committer | Ade Lee <alee@redhat.com> | 2017-03-15 23:05:07 -0400 |
| commit | 080f3d2a8bf36be407c79ddd71381450c8667b2e (patch) | |
| tree | 58594f9c45e88c882579d9f6638ff6639e506729 /base/common | |
| parent | 764a17314e81cade8bf1192739b5a2fad11d18bd (diff) | |
| parent | 07135b5906f97a8c68148a07484e63d6896f410b (diff) | |
Merge branch 'master' of github.com:dogtagpki/pki
Diffstat (limited to 'base/common')
16 files changed, 1219 insertions, 220 deletions
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(); |
