summaryrefslogtreecommitdiffstats
path: root/pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java')
-rw-r--r--pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java959
1 files changed, 959 insertions, 0 deletions
diff --git a/pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java b/pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java
new file mode 100644
index 000000000..baec75494
--- /dev/null
+++ b/pki/base/kra/src/com/netscape/kra/StorageKeyUnit.java
@@ -0,0 +1,959 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.kra;
+
+
+import org.mozilla.jss.util.Password;
+import java.util.*;
+import java.io.*;
+import com.netscape.certsrv.security.*;
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.crypto.TokenCertificate;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.cmscore.util.*;
+//import com.netscape.cmscore.kra.*;
+import com.netscape.certsrv.dbs.keydb.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.kra.*;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.*;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.crypto.*;
+import com.netscape.cmscore.cert.*;
+
+
+/**
+ * A class represents a storage key unit. Currently, this
+ * is implemented with cryptix, the final implementation
+ * should be built on JSS/HCL.
+ *
+ * @author thomask
+ * @version $Revision$, $Date$
+ */
+public class StorageKeyUnit extends EncryptionUnit implements
+ ISubsystem, IStorageKeyUnit {
+
+ private IConfigStore mConfig = null;
+
+ // private RSAPublicKey mPublicKey = null;
+ // private RSAPrivateKey mPrivateKey = null;
+
+ private IConfigStore mStorageConfig = null;
+ private IKeyRecoveryAuthority mKRA = null;
+ private String mTokenFile = null;
+ private X509Certificate mCert = null;
+ private CryptoManager mManager = null;
+ private CryptoToken mToken = null;
+ private PrivateKey mPrivateKey = null;
+ private byte mPrivateKeyData[] = null;
+ private boolean mKeySplitting = false;
+
+
+ private static final String PROP_N = "n";
+ private static final String PROP_M = "m";
+ private static final String PROP_UID = "uid";
+ private static final String PROP_SHARE = "share";
+ private static final String PROP_HARDWARE = "hardware";
+ private static final String PROP_LOGOUT = "logout";
+ public static final String PROP_NICKNAME = "nickName";
+ public static final String PROP_KEYDB = "keydb";
+ public static final String PROP_CERTDB = "certdb";
+ public static final String PROP_MN = "mn";
+
+ /**
+ * Constructs this token.
+ */
+ public StorageKeyUnit() {
+ super();
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return "storageKeyUnit";
+ }
+
+ /**
+ * Sets subsystem identifier. Once the system is
+ * loaded, system identifier cannot be changed
+ * dynamically.
+ */
+ public void setId(String id) throws EBaseException {
+ throw new EBaseException(CMS.getUserMessage("CMS_INVALID_OPERATION"));
+ }
+
+ /**
+ * return true if byte arrays are equal, false otherwise
+ */
+ private boolean byteArraysMatch(byte a[], byte b[]) {
+ if (a==null || b==null) { return false; }
+ if (a.length != b.length) { return false; }
+ for (int i=0; i<a.length; i++) {
+ if (a[i] != b[i]) { return false; }
+ }
+ return true;
+ }
+
+
+ /**
+ * Initializes this subsystem.
+ */
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mKRA = (IKeyRecoveryAuthority) owner;
+ mConfig = config;
+
+ mKeySplitting = owner.getConfigStore().getBoolean("keySplitting", false);
+
+ try {
+ mManager = CryptoManager.getInstance();
+ mToken = getToken();
+ } catch (org.mozilla.jss.CryptoManager.NotInitializedException e) {
+ mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_STORAGE_INIT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+
+ if (mConfig.getString(PROP_HARDWARE, null) != null) {
+ System.setProperty("cms.skip_token", mConfig.getString(PROP_HARDWARE));
+
+// The strategy here is to read all the certs in the token
+// and cycle through them until we find one that matches the
+// kra-cert.db file
+
+ if (mKeySplitting) {
+
+ byte certFileData[] = null;
+ try {
+ File certFile = new File(
+ mConfig.getString(PROP_CERTDB));
+
+ certFileData = new byte[
+ (Long.valueOf(certFile.length())).intValue()];
+ FileInputStream fi = new FileInputStream(certFile);
+
+ fi.read(certFileData);
+ fi.close();
+
+ // pick up cert by nickName
+
+ } catch (IOException e) {
+ mKRA.log(ILogger.LL_INFO,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+
+ try {
+ X509Certificate certs[] =
+ getToken().getCryptoStore().getCertificates();
+ for (int i=0;i <certs.length;i++) {
+ if (byteArraysMatch(certs[i].getEncoded(),certFileData)) {
+ mCert = certs[i];
+ }
+ }
+ if (mCert == null) {
+ mKRA.log(ILogger.LL_FAILURE, "Storage Cert could not be initialized. No cert in token matched kra-cert file");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", "mCert == null"));
+ } else {
+ mKRA.log(ILogger.LL_INFO, "Using Storage Cert "+mCert.getSubjectDN());
+ }
+ } catch (CertificateEncodingException e) {
+ mKRA.log(ILogger.LL_FAILURE, "Error encoding cert ");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (TokenException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+ }
+
+ } else {
+
+ // read certificate from file
+ byte certData[] = null;
+
+ try {
+ if (mKeySplitting) {
+ File certFile = new File(
+ mConfig.getString(PROP_CERTDB));
+
+ certData = new byte[
+ (Long.valueOf(certFile.length())).intValue()];
+ FileInputStream fi = new FileInputStream(certFile);
+
+ fi.read(certData);
+ fi.close();
+
+ // pick up cert by nickName
+ mCert = mManager.findCertByNickname(
+ config.getString(PROP_NICKNAME));
+
+ } else {
+ mCert = mManager.findCertByNickname(
+ config.getString(PROP_NICKNAME));
+ }
+ } catch (IOException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (TokenException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ } catch (ObjectNotFoundException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ // XXX - this import wont work
+ try {
+ mCert = mManager.importCertPackage(certData,
+ "kraStorageCert");
+ } catch (Exception ex) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_IMPORT_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", ex.toString()));
+ }
+ }
+
+ if (mKeySplitting) {
+ // read private key from the file
+ try {
+ File priFile = new File(mConfig.getString(PROP_KEYDB));
+
+ mPrivateKeyData = new byte[
+ (Long.valueOf(priFile.length())).intValue()];
+ FileInputStream fi = new FileInputStream(priFile);
+
+ fi.read(mPrivateKeyData);
+ fi.close();
+ } catch (IOException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_PRIVATE", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1", e.toString()));
+ }
+ }
+
+ }
+
+ if (mKeySplitting) {
+ // open internal data storage configuration
+ mTokenFile = mConfig.getString(PROP_MN);
+ try {
+ // read m, n and no of identifier
+ mStorageConfig = CMS.createFileConfigStore(mTokenFile);
+ } catch (EBaseException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_MN",
+ e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION"));
+
+ }
+ }
+
+ try {
+ if (mCert == null) {
+ CMS.debug("mCert is null...retrieving "+ config.getString(PROP_NICKNAME));
+ mCert = mManager.findCertByNickname(
+ config.getString(PROP_NICKNAME));
+ CMS.debug("mCert = "+mCert);
+ }
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_READ_CERT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR", e.toString()));
+ }
+
+ }
+
+ /**
+ * Starts up this subsystem.
+ */
+ public void startup() throws EBaseException {
+ }
+
+ /**
+ * Shutdowns this subsystem.
+ */
+ public void shutdown() {
+ }
+
+ /**
+ * Returns the configuration store of this token.
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ public static SymmetricKey buildSymmetricKeyWithInternalStorage(
+ String pin) throws EBaseException {
+ try {
+ return buildSymmetricKey(CryptoManager.getInstance().getInternalKeyStorageToken(), pin);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Builds symmetric key from the given password.
+ */
+ public static SymmetricKey buildSymmetricKey(CryptoToken token,
+ String pin) throws EBaseException {
+ try {
+
+ Password pass = new Password(pin.toCharArray());
+ KeyGenerator kg = null;
+
+ kg = token.getKeyGenerator(
+ PBEAlgorithm.PBE_SHA1_DES3_CBC);
+ byte salt[] = {0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01};
+ PBEKeyGenParams kgp = new PBEKeyGenParams(pass,
+ salt, 5);
+
+ pass.clear();
+ kg.initialize(kgp);
+ return kg.generate();
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "buildSymmetricKey:" +
+ e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "buildSymmetricKey:" +
+ e.toString()));
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "buildSymmetricKey:" +
+ e.toString()));
+ } catch (CharConversionException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "buildSymmetricKey:" +
+ e.toString()));
+ }
+ }
+
+ /**
+ * Unwraps the storage key with the given symmetric key.
+ */
+ public PrivateKey unwrapStorageKey(CryptoToken token,
+ SymmetricKey sk, byte wrapped[],
+ PublicKey pubKey)
+ throws EBaseException {
+ try {
+
+ CMS.debug("StorageKeyUnit.unwrapStorageKey.");
+
+ KeyWrapper wrapper = token.getKeyWrapper(
+ KeyWrapAlgorithm.DES3_CBC_PAD);
+
+ wrapper.initUnwrap(sk, IV);
+
+ // XXX - it does not like the public key that is
+ // not a crypto X509Certificate
+ PrivateKey pk = wrapper.unwrapTemporaryPrivate(wrapped,
+ PrivateKey.RSA, pubKey);
+
+ return pk;
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "unwrapStorageKey:" +
+ e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "unwrapStorageKey:" +
+ e.toString()));
+ } catch (InvalidKeyException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "unwrapStorageKey:" +
+ e.toString()));
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "unwrapStorageKey:" +
+ e.toString()));
+ }
+ }
+
+ /**
+ * Used by config-cert.
+ */
+ public byte[] wrapStorageKey(CryptoToken token,
+ SymmetricKey sk, PrivateKey pri)
+ throws EBaseException {
+ CMS.debug("StorageKeyUnit.wrapStorageKey.");
+ try {
+ // move public & private to config/storage.dat
+ // delete private key
+ KeyWrapper wrapper = token.getKeyWrapper(
+ 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) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ "wrapStorageKey:" +
+ e.toString()));
+ }
+ }
+
+ /**
+ * Logins to this token.
+ */
+ public void login(String pin) throws EBaseException {
+ if (mConfig.getString(PROP_HARDWARE, null) != null) {
+ try {
+ getToken().login(new Password(pin.toCharArray()));
+ PrivateKey pk[] = getToken().getCryptoStore().getPrivateKeys();
+
+ for (int i = 0; i < pk.length; i++) {
+ if (arraysEqual(pk[i].getUniqueID(),
+ ((TokenCertificate) mCert).getUniqueID())) {
+ mPrivateKey = pk[i];
+ }
+ }
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_STORAGE_LOGIN", e.toString()));
+ }
+
+ } else {
+ try {
+ SymmetricKey sk = buildSymmetricKey(mToken, pin);
+
+ mPrivateKey = unwrapStorageKey(mToken, sk,
+ mPrivateKeyData, getPublicKey());
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_STORAGE_LOGIN", e.toString()));
+ }
+ if (mPrivateKey == null) {
+ mPrivateKey = getPrivateKey();
+ }
+ }
+ }
+
+ /**
+ * Logins to this token.
+ */
+ public void login(Credential creds[])
+ throws EBaseException {
+ String pwd = constructPassword(creds);
+
+ login(pwd);
+ }
+
+ /**
+ * Logout from this token.
+ */
+ public void logout() {
+ try {
+ if (mConfig.getString(PROP_HARDWARE, null) != null) {
+ if (mConfig.getBoolean(PROP_LOGOUT, false)) {
+ getToken().logout();
+ }
+ }
+ } catch (Exception e) {
+ mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_STORAGE_LOGOUT", e.toString()));
+
+ }
+ mPrivateKey = null;
+ }
+
+ /**
+ * Returns a list of recovery agent identifiers.
+ */
+ public Enumeration getAgentIdentifiers() {
+ Vector v = new Vector();
+
+ for (int i = 0;; i++) {
+ try {
+ String uid =
+ mStorageConfig.getString(PROP_UID + i);
+
+ if (uid == null)
+ break;
+ v.addElement(uid);
+ } catch (EBaseException e) {
+ break;
+ }
+ }
+ return v.elements();
+ }
+
+ /**
+ * Changes agent password.
+ */
+ public boolean changeAgentPassword(String id, String oldpwd,
+ String newpwd) throws EBaseException {
+ // locate the id(s)
+ for (int i = 0;; i++) {
+ try {
+ String uid =
+ mStorageConfig.getString(PROP_UID + i);
+
+ if (uid == null)
+ break;
+ if (id.equals(uid)) {
+ byte share[] = decryptShareWithInternalStorage(mStorageConfig.getString(PROP_SHARE + i), oldpwd);
+
+ mStorageConfig.putString(PROP_SHARE + i,
+ encryptShareWithInternalStorage(
+ share, newpwd));
+ mStorageConfig.commit(false);
+ return true;
+ }
+ } catch (Exception e) {
+ break;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Changes the m out of n recovery schema.
+ */
+ public boolean changeAgentMN(int new_n, int new_m,
+ Credential oldcreds[],
+ Credential newcreds[])
+ throws EBaseException {
+
+ if (new_n != newcreds.length) {
+ throw new EKRAException(CMS.getUserMessage("CMS_KRA_INVALID_N"));
+ }
+
+ // XXX - verify and construct original password
+ String secret = constructPassword(oldcreds);
+
+ // XXX - remove extra configuration
+ for (int j = new_n; j < getNoOfAgents(); j++) {
+ mStorageConfig.remove(PROP_UID + j);
+ mStorageConfig.remove(PROP_SHARE + j);
+ }
+
+ // XXX - split pwd into n pieces
+ byte shares[][] = new byte[newcreds.length][];
+
+ IShare s = null;
+ try {
+ String className = mConfig.getString("share_class",
+ "com.netscape.cms.shares.OldShare");
+ s = (IShare)Class.forName(className).newInstance();
+ } catch (Exception e) {
+ CMS.debug("Loading Shares error " + e);
+ }
+ if (s == null) {
+ CMS.debug("Share plugin is not found");
+ return false;
+ }
+
+ try {
+ s.initialize(secret.getBytes(), new_m);
+ } catch (Exception e) {
+ CMS.debug("Failed to initialize Share plugin");
+ return false;
+ }
+
+ for (int i = 0; i < newcreds.length; i++) {
+ byte share[] = s.createShare(i + 1);
+
+ shares[i] = share;
+ }
+
+ // store the new shares into configuration
+ mStorageConfig.putInteger(PROP_N, new_n);
+ mStorageConfig.putInteger(PROP_M, new_m);
+ for (int i = 0; i < newcreds.length; i++) {
+ mStorageConfig.putString(PROP_UID + i,
+ newcreds[i].getIdentifier());
+ // use password to encrypt shares...
+ mStorageConfig.putString(PROP_SHARE + i,
+ encryptShareWithInternalStorage(shares[i],
+ newcreds[i].getPassword()));
+ }
+
+ try {
+ mStorageConfig.commit(false);
+ return true;
+ } catch (EBaseException e) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_CHANGE_MN", e.toString()));
+ }
+ return false;
+ }
+
+ /**
+ * Returns number of recovery agents.
+ */
+ public int getNoOfAgents() throws EBaseException {
+ return mStorageConfig.getInteger(PROP_N);
+ }
+
+ /**
+ * Returns number of recovery agents required for
+ * recovery operation.
+ */
+ public int getNoOfRequiredAgents() throws EBaseException {
+ return mStorageConfig.getInteger(PROP_M);
+ }
+
+ public void setNoOfRequiredAgents(int number) {
+ mStorageConfig.putInteger(PROP_M, number);
+ }
+
+ public CryptoToken getInternalToken() {
+ try {
+ return CryptoManager.getInstance().getInternalKeyStorageToken();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public CryptoToken getToken() {
+ try {
+ if (mConfig.getString(PROP_HARDWARE, null) != null) {
+ return mManager.getTokenByName(mConfig.getString(PROP_HARDWARE));
+ } else {
+ return CryptoManager.getInstance().getInternalKeyStorageToken();
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the certificate blob.
+ */
+ public PublicKey getPublicKey() {
+ // NEED to move this key into internal storage token.
+ return mCert.getPublicKey();
+ }
+
+ public PrivateKey getPrivateKey() {
+
+ if (!mKeySplitting) {
+ try {
+ PrivateKey pk[] = getToken().getCryptoStore().getPrivateKeys();
+ for (int i = 0; i < pk.length; i++) {
+ if (arraysEqual(pk[i].getUniqueID(),
+ ((TokenCertificate) mCert).getUniqueID())) {
+ return pk[i];
+ }
+ }
+ } catch (TokenException e) {
+ }
+ return null;
+ } else {
+ return mPrivateKey;
+ }
+ }
+
+ /**
+ * Verifies the integrity of the given key pairs.
+ */
+ public void verify(byte publicKey[], PrivateKey privateKey)
+ throws EBaseException {
+ // XXX
+ }
+
+ public String encryptShareWithInternalStorage(
+ byte share[], String pwd)
+ throws EBaseException {
+ try {
+ return encryptShare(CryptoManager.getInstance().getInternalKeyStorageToken(), share, pwd);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Protectes the share with the given password.
+ */
+ public String encryptShare(CryptoToken token,
+ byte share[], String pwd)
+ throws EBaseException {
+ try {
+ CMS.debug("StorageKeyUnit.encryptShare");
+ Cipher cipher = token.getCipherContext(
+ EncryptionAlgorithm.DES3_CBC_PAD);
+ SymmetricKey sk = StorageKeyUnit.buildSymmetricKey(token, pwd);
+
+ cipher.initEncrypt(sk, IV);
+ byte prev[] = preVerify(share);
+ byte enc[] = cipher.doFinal(prev);
+
+ // #615387 - cannot use CMS.BtoA because CMS is not present during
+ // configuration
+ return com.netscape.osutil.OSUtil.BtoA(enc).trim();
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ } catch (InvalidKeyException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ } catch (BadPaddingException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ } catch (IllegalBlockSizeException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_KEY_1",
+ e.toString()));
+ }
+ }
+
+ public static byte[] preVerify(byte share[]) {
+ byte data[] = new byte[share.length + 2];
+
+ data[0] = 0;
+ data[1] = 0;
+ for (int i = 0; i < share.length; i++) {
+ data[2 + i] = share[i];
+ }
+ return data;
+ }
+
+ public static boolean verifyShare(byte share[]) {
+ if (share[0] == 0 && share[1] == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static byte[] postVerify(byte share[]) {
+ byte data[] = new byte[share.length - 2];
+
+ for (int i = 2; i < share.length; i++) {
+ data[i - 2] = share[i];
+ }
+ return data;
+ }
+
+ public void checkPassword(String userid, String pwd) throws EBaseException {
+ for (int i = 0;; i++) {
+ String uid = null;
+
+ try {
+ uid = mStorageConfig.getString(PROP_UID + i);
+ if (uid == null)
+ break;
+ } catch (Exception e) {
+ break;
+ }
+ if (uid.equals(userid)) {
+ byte data[] = decryptShareWithInternalStorage(
+ mStorageConfig.getString(PROP_SHARE + i),
+ pwd);
+ if (data == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ return;
+ }
+ }
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+
+ }
+
+ public byte[] decryptShareWithInternalStorage(
+ String encoding, String pwd)
+ throws EBaseException {
+ try {
+ return decryptShare(CryptoManager.getInstance().getInternalKeyStorageToken(), encoding, pwd);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Decrypts shares with the given password.
+ */
+ public byte[] decryptShare(CryptoToken token,
+ String encoding, String pwd)
+ throws EBaseException {
+ try {
+ CMS.debug("StorageKeyUnit.decryptShare");
+ byte share[] = CMS.AtoB(encoding);
+ Cipher cipher = token.getCipherContext(
+ EncryptionAlgorithm.DES3_CBC_PAD);
+ SymmetricKey sk = StorageKeyUnit.buildSymmetricKey(
+ token, pwd);
+
+ cipher.initDecrypt(sk, IV);
+ byte dec[] = cipher.doFinal(share);
+
+ if (dec == null || !verifyShare(dec)) {
+ // invalid passwod
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ return postVerify(dec);
+ } catch (OutOfMemoryError e) {
+ // XXX - this happens in cipher.doFinal when
+ // the given share is not valid (the password
+ // given from the agent is not correct).
+ // Actulla, cipher.doFinal should return
+ // something better than this!
+ //
+ // e.printStackTrace();
+ //
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (TokenException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (InvalidKeyException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (IllegalBlockSizeException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ } catch (BadPaddingException e) {
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ e.toString()));
+ }
+ }
+
+ /**
+ * Reconstructs password from recovery agents.
+ */
+ private String constructPassword(Credential creds[])
+ throws EBaseException {
+ // sort the credential according to the order in
+ // configuration file
+ Hashtable v = new Hashtable();
+
+ for (int i = 0;; i++) {
+ String uid = null;
+
+ try {
+ uid = mStorageConfig.getString(PROP_UID + i);
+ if (uid == null)
+ break;
+ } catch (Exception e) {
+ break;
+ }
+ for (int j = 0; j < creds.length; j++) {
+ if (uid.equals(creds[j].getIdentifier())) {
+ byte pwd[] = decryptShareWithInternalStorage(
+ mStorageConfig.getString(
+ PROP_SHARE + i),
+ creds[j].getPassword());
+ if (pwd == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ v.put(Integer.toString(i), pwd);
+ break;
+ }
+ }
+ }
+
+ if (v.size() < 0) {
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ if (v.size() != creds.length) {
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ IJoinShares j = null;
+ try {
+ String className = mConfig.getString("joinshares_class",
+ "com.netscape.cms.shares.OldJoinShares");
+ j = (IJoinShares)Class.forName(className).newInstance();
+ } catch (Exception e) {
+ CMS.debug("JoinShares error " + e);
+ }
+ if (j == null) {
+ CMS.debug("JoinShares plugin is not found");
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+
+ try {
+ j.initialize(v.size());
+ } catch (Exception e) {
+ CMS.debug("Failed to initialize JoinShares");
+ throw new EBaseException(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+ }
+ Enumeration e = v.keys();
+
+ while (e.hasMoreElements()) {
+ String next = (String) e.nextElement();
+
+ j.addShare(Integer.parseInt(next) + 1,
+ (byte[]) v.get(next));
+ }
+ try {
+ byte secret[] = j.recoverSecret();
+ String pwd = new String(secret);
+
+ return pwd;
+ } catch (Exception ee) {
+ mKRA.log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_KRA_STORAGE_RECONSTRUCT", e.toString()));
+ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PASSWORD",
+ ee.toString()));
+ }
+ }
+
+ public static boolean arraysEqual(byte[] bytes, byte[] ints) {
+ if (bytes == null || ints == null) {
+ return false;
+ }
+
+ if (bytes.length != ints.length) {
+ return false;
+ }
+
+ for (int i = 0; i < bytes.length; i++) {
+ if (bytes[i] != ints[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}