>From db2a9326ed3c93e0463444900875021d269f27ae Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 17 Mar 2017 11:49:41 -0700
Subject: [PATCH] pagure#2605 CMC feature: id-cmc-identityProofV2 per rfc5272
 (part 1) This patch provides methods that can be shared between the CA and
 the ISharedToken plugins:  1. the convenience routines for quick encryption,
 decryption, hashing methods that take default algorithms.  2. The
 establishment of Issuance Protection Certificate

---
 .../src/com/netscape/ca/CertificateAuthority.java  |  57 +++++++-
 .../netscape/certsrv/ca/ICertificateAuthority.java |  10 ++
 .../com/netscape/cmsutil/crypto/CryptoUtil.java    | 145 +++++++++++++++++++++
 3 files changed, 211 insertions(+), 1 deletion(-)

diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 7ad40a9f6e436d4d3c4c947165a2c7ae18dc960a..a6d56ac6b576371a3f2454b2faf5f90b43b51d29 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -305,6 +305,10 @@ public class CertificateAuthority
 
     protected Hashtable<String, ListenerPlugin> mListenerPlugins = null;
 
+    // for CMC shared secret operations
+    protected PublicKey mSysEncKey = null;
+    protected PrivateKey mSysDecKey = null;
+
     /**
      * Internal constants
      */
@@ -606,16 +610,67 @@ public class CertificateAuthority
 
                 CMS.debug("CertificateAuthority: finished init of host authority");
             }
+
+            // set up CA Issuance Protection Cert
+            if (initSigUnitSucceeded)
+                initIssuanceProtectionCert();
         } catch (EBaseException e) {
             CMS.debug(e);
             if (CMS.isPreOpMode()) {
-                CMS.debug("CertificateAuthority.init(): Swallow exception in pre-op mode");
+                CMS.debug("CertificateAuthority: Swallow exception in pre-op mode");
                 return;
             }
             throw e;
         }
     }
 
+    /**
+     * initIssuanceProtectionCert sets the CA Issuance Protection cert
+     */
+    private void initIssuanceProtectionCert()
+           throws EBaseException {
+        String method = "CertificateAuthority: initIssuanceProtectionCert: ";
+        CryptoManager cManager = null;
+
+        String name = null;
+        String defaultName = "cert.subsystem.nickname";
+        String certNickName = null;
+        try {
+            cManager = CryptoManager.getInstance();
+            name = "cert.issuance_protection.nickname";
+            CMS.debug(method + " about to look for CA Issuance Protection cert: "+
+                name);
+            certNickName = mConfig.getString(name);
+        } catch (EBaseException e) {
+            CMS.debug(method + name + " not found; use defaultName : " + defaultName );
+            name = defaultName ;
+            certNickName = mConfig.getString(name);
+        } catch (Exception e) {
+            throw new EBaseException(method + e);
+        }
+        CMS.debug(method + "found nickname: "+ certNickName);
+
+        try {
+            org.mozilla.jss.crypto.X509Certificate cert = null;
+                cert = cManager.findCertByNickname(certNickName);
+            if (cert != null) {
+                CMS.debug(method + " found CA Issuance Protection cert:" + certNickName);
+                mSysEncKey = cert.getPublicKey();
+                mSysDecKey = cManager.getInstance().findPrivKeyByCert(cert);
+            }
+        } catch (Exception e) {
+            throw new EBaseException(method + e);
+        }
+    }
+
+    public PublicKey getIssuanceProtPubKey() {
+        return mSysEncKey;
+    }
+
+    public PrivateKey getIssuanceProtPrivKey() {
+        return mSysDecKey;
+    }
+
     private void checkForNewerCert() throws EBaseException {
         if (authoritySerial == null)
             return;
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index 8ddc601e565f0b3ca901266cfe10928b3f9e4438..8e34880e512e0f59f9d3850961ec42ad72628567 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -607,4 +607,14 @@ public interface ICertificateAuthority extends ISubsystem {
      */
     public void deleteAuthority(HttpServletRequest httpReq)
         throws EBaseException;
+
+    /**
+     * get Issuance Protection Public Key
+     */
+    public java.security.PublicKey getIssuanceProtPubKey();
+
+    /**
+     * get Issuance Protection Private Key
+     */
+    public org.mozilla.jss.crypto.PrivateKey getIssuanceProtPrivKey();
 }
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 8bf4c27afc6b7f000d84c29d3a4500e3cbb65c7f..0c63819a8bcbd3c7f56c6d85e39ca9cf081079a2 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -66,6 +66,7 @@ import org.mozilla.jss.crypto.CryptoStore;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.DigestAlgorithm;
 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.InternalCertificate;
@@ -2274,6 +2275,150 @@ public class CryptoUtil {
         }
         return pk;
     }
+
+    /**
+     * The following are convenience routines for quick preliminary
+     * feature development or test programs that would just take
+     * the defaults
+     */
+
+    private static byte default_iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
+    private static IVParameterSpec default_IV = new IVParameterSpec(default_iv);
+
+    // this generates a temporary 128 bit AES symkey with defaults
+    public static SymmetricKey generateKey(CryptoToken token) throws Exception {
+        return generateKey(token,
+//TODO:                KeyGenAlgorithm.AES, 128,
+                KeyGenAlgorithm.DES3, 128 /*unused*/,
+                null, true);
+    }
+
+    // decryptUsingSymmetricKey with default algorithms
+    public static byte[] decryptUsingSymmetricKey(CryptoToken token, byte[] encryptedData, SymmetricKey wrappingKey) throws Exception {
+        return decryptUsingSymmetricKey(token, default_IV, encryptedData,
+                wrappingKey,
+                EncryptionAlgorithm.DES3_CBC_PAD);
+//TODO:                EncryptionAlgorithm.AES_128_CBC);
+    }
+
+    // encryptUsingSymmetricKey with default algorithms
+    public static byte[] encryptUsingSymmetricKey(CryptoToken token, SymmetricKey wrappingKey, byte[] data) throws Exception {
+        return encryptUsingSymmetricKey(
+                token,
+                wrappingKey,
+                data,
+                EncryptionAlgorithm.DES3_CBC_PAD,
+//TODO:                EncryptionAlgorithm.AES_128_CBC,
+                default_IV);
+    }
+
+    // unwrap sym key using default algorithms
+    public static SymmetricKey unwrap(CryptoToken token, SymmetricKey.Usage usage, PrivateKey wrappingKey, byte[] wrappedSymKey) throws Exception {
+        return unwrap(
+               token,
+//TODO:               SymmetricKey.AES,
+               SymmetricKey.DES3,
+               0,
+               usage,
+               wrappingKey,
+               wrappedSymKey,
+               getDefaultKeyWrapAlg());
+    }
+
+    public static AlgorithmIdentifier getDefaultEncAlg()
+           throws Exception {
+        OBJECT_IDENTIFIER oid =
+                EncryptionAlgorithm.DES3_CBC.toOID();
+//TODO:                EncryptionAlgorithm.AES_128_CBC.toOID();
+
+        AlgorithmIdentifier aid =
+                new AlgorithmIdentifier(oid, new OCTET_STRING(default_iv));
+        return aid;
+    }
+
+    public static String getDefaultHashAlgName() {
+        return ("SHA-256");
+    }
+
+    public static KeyWrapAlgorithm getDefaultKeyWrapAlg() {
+        return KeyWrapAlgorithm.RSA;
+    }
+
+    public static AlgorithmIdentifier getDefaultHashAlg()
+           throws Exception {
+        AlgorithmIdentifier hashAlg;
+            hashAlg = new AlgorithmIdentifier(CryptoUtil.getHashAlgorithmOID("SHA-256"));
+        return hashAlg;
+    }
+
+    // The following are useful mapping functions
+
+    /**
+     * maps from HMACAlgorithm name to FIPS 180-2 MessageDigest algorithm name
+     */
+    public static String getHMACtoMessageDigestName(String name) {
+        String mdName = name;
+        if (name != null) {
+            if (name.equals("SHA-256-HMAC")) {
+                mdName = "SHA-256";
+            } else if (name.equals("SHA-384-HMAC")) {
+                mdName = "SHA-384";
+            } else if (name.equals("SHA-512-HMAC")) {
+                mdName = "SHA-512";
+            }
+        }
+
+        return mdName;
+    }
+
+    /**
+     * getHMACAlgorithmOID returns OID of the HMAC algorithm name
+     *
+     * @param name name of the HMAC algorithm
+     * @return OID of the HMAC algorithm
+     */
+    public static OBJECT_IDENTIFIER getHMACAlgorithmOID(String name)
+           throws NoSuchAlgorithmException {
+        OBJECT_IDENTIFIER oid = null;
+        if (name != null) {
+            if (name.equals("SHA-256-HMAC")) {
+                oid = (HMACAlgorithm.SHA256).toOID();
+            } else if (name.equals("SHA-384-HMAC")) {
+                oid = (HMACAlgorithm.SHA384).toOID();
+            } else if (name.equals("SHA-512-HMAC")) {
+                oid = (HMACAlgorithm.SHA512).toOID();
+            }
+        }
+        if ( oid == null) {
+            throw new NoSuchAlgorithmException();
+        }
+        return oid;
+    }
+
+    /**
+     * getHashAlgorithmOID returns OID of the hashing algorithm name
+     *
+     * @param name name of the hashing algorithm
+     * @return OID of the hashing algorithm
+     *
+     */
+    public static OBJECT_IDENTIFIER getHashAlgorithmOID(String name)
+           throws NoSuchAlgorithmException {
+        OBJECT_IDENTIFIER oid = null;
+        if (name != null) {
+            if (name.equals("SHA-256")) {
+                oid = (DigestAlgorithm.SHA256).toOID();
+            } else if (name.equals("SHA-384")) {
+                oid = (DigestAlgorithm.SHA384).toOID();
+            } else if (name.equals("SHA-512")) {
+                oid = (DigestAlgorithm.SHA512).toOID();
+            }
+        }
+        if ( oid == null) {
+            throw new NoSuchAlgorithmException();
+        }
+        return oid;
+    }
 }
 
 // START ENABLE_ECC
-- 
2.7.4

