From fb9acc2c02ad35443eb8b6ac0f2279dddd9449ab Mon Sep 17 00:00:00 2001 From: Ade Lee Date: Wed, 30 Oct 2013 15:50:28 -0400 Subject: [PATCH 3/6] Fixed logic for setting admin cert signing algorithm Should now be SHA256 by default. Bugzilla BZ 1024445 --- base/ca/shared/conf/CS.cfg.in | 1 + base/ca/shared/profiles/ca/caAdminCert.cfg | 2 +- .../com/netscape/cms/servlet/csadmin/CertUtil.java | 123 +++++++++++++-------- 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/base/ca/shared/conf/CS.cfg.in b/base/ca/shared/conf/CS.cfg.in index c1acc57..cca5209 100644 --- a/base/ca/shared/conf/CS.cfg.in +++ b/base/ca/shared/conf/CS.cfg.in @@ -660,6 +660,7 @@ ca.notification.requestInQ.senderEmail= ca.ocsp_signing.cacertnickname=ocspSigningCert cert-[PKI_INSTANCE_ID] ca.ocsp_signing.defaultSigningAlgorithm=SHA256withRSA ca.ocsp_signing.tokenname=internal +ca.profiles.defaultSigningAlgsAllowed==SHA256withRSA,SHA1withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA256withEC,SHA1withEC,SHA384withEC,SHA512withEC ca.publish.createOwnDNEntry=false ca.publish.queue.enable=true ca.publish.queue.maxNumberOfThreads=3 diff --git a/base/ca/shared/profiles/ca/caAdminCert.cfg b/base/ca/shared/profiles/ca/caAdminCert.cfg index c44079a..cd29703 100644 --- a/base/ca/shared/profiles/ca/caAdminCert.cfg +++ b/base/ca/shared/profiles/ca/caAdminCert.cfg @@ -81,7 +81,7 @@ policyset.adminCertSet.7.default.params.exKeyUsageCritical=false policyset.adminCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4 policyset.adminCertSet.8.constraint.class_id=signingAlgConstraintImpl policyset.adminCertSet.8.constraint.name=No Constraint -policyset.adminCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC +policyset.adminCertSet.8.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA1withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA256withEC,SHA1withEC,SHA384withEC,SHA512withEC policyset.adminCertSet.8.default.class_id=signingAlgDefaultImpl policyset.adminCertSet.8.default.name=Signing Alg policyset.adminCertSet.8.default.params.signingAlg=- diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java index 789c0aa..1936b2c 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java @@ -17,14 +17,15 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.csadmin; -import java.io.BufferedReader; import java.io.ByteArrayInputStream; -import java.io.DataInputStream; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStreamReader; import java.math.BigInteger; import java.util.Date; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; import javax.servlet.http.HttpServletResponse; @@ -36,6 +37,8 @@ import netscape.security.x509.X509CertImpl; import netscape.security.x509.X509CertInfo; import netscape.security.x509.X509Key; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; import org.apache.velocity.context.Context; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.PrivateKey; @@ -271,52 +274,84 @@ public class CertUtil { } /** - * reads from the admin cert profile caAdminCert.profile and takes the first - * entry in the list of allowed algorithms. Users that wish a different algorithm - * can specify it in the profile using default.params.signingAlg + * reads from the admin cert profile caAdminCert.profile and determines the algorithm as follows: + * + * 1. First gets list of allowed algorithms from profile (constraint.params.signingAlgsAllowed) + * If entry does not exist, uses entry "ca.profiles.defaultSigningAlgsAllowed" from CS.cfg + * If that entry does not exist, uses basic default + * + * 2. Gets default.params.signingAlg from profile. + * If entry does not exist or equals "-", selects first algorithm in allowed algorithm list + * that matches CA signing key type + * Otherwise returns entry if it matches signing CA key type. + * + * @throws EBaseException + * @throws IOException + * @throws FileNotFoundException */ - public static String getAdminProfileAlgorithm(IConfigStore config) { - String algorithm = "SHA256withRSA"; - try { - String caSigningKeyType = config.getString("preop.cert.signing.keytype", "rsa"); - String pfile = config.getString("profile.caAdminCert.config"); - FileInputStream fis = new FileInputStream(pfile); - DataInputStream in = new DataInputStream(fis); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - - String strLine; - while ((strLine = br.readLine()) != null) { - String marker2 = "default.params.signingAlg="; - int indx = strLine.indexOf(marker2); - if (indx != -1) { - String alg = strLine.substring(indx + marker2.length()); - if ((alg.length() > 0) && (!alg.equals("-"))) { - algorithm = alg; - break; - } - ; - } - ; - - String marker = "signingAlgsAllowed="; - indx = strLine.indexOf(marker); - if (indx != -1) { - String[] algs = strLine.substring(indx + marker.length()).split(","); - for (int i = 0; i < algs.length; i++) { - if ((caSigningKeyType.equals("rsa") && (algs[i].indexOf("RSA") != -1)) || - (caSigningKeyType.equals("ecc") && (algs[i].indexOf("EC") != -1))) { - algorithm = algs[i]; - break; - } - } + public static String getAdminProfileAlgorithm(IConfigStore config) throws EBaseException, FileNotFoundException, + IOException { + String caSigningKeyType = config.getString("preop.cert.signing.keytype", "rsa"); + String pfile = config.getString("profile.caAdminCert.config"); + Properties props = new Properties(); + props.load(new FileInputStream(pfile)); + + Set keys = props.stringPropertyNames(); + Iterator iter = keys.iterator(); + String defaultAlg = null; + String[] algsAllowed = null; + + while (iter.hasNext()) { + String key = iter.next(); + if (key.endsWith("default.params.signingAlg")) { + defaultAlg = props.getProperty(key); + } + if (key.endsWith("constraint.params.signingAlgsAllowed")) { + algsAllowed = StringUtils.split(props.getProperty(key), ","); + } + } + + if (algsAllowed == null) { //algsAllowed not defined in profile, use a global setting + algsAllowed = StringUtils.split(config.getString("ca.profiles.defaultSigningAlgsAllowed", + "SHA256withRSA,SHA256withEC,SHA1withDSA"), ","); + } + + if (ArrayUtils.isEmpty(algsAllowed)) { + throw new EBaseException("No allowed signing algorithms defined."); + } + + if (StringUtils.isNotEmpty(defaultAlg) && !defaultAlg.equals("-")) { + // check if the defined default algorithm is valid + if (! isAlgorithmValid(caSigningKeyType, defaultAlg)) { + throw new EBaseException("Administrator cert cannot be signed by specfied algorithm." + + "Algorithm incompatible with signing key"); + } + + for (String alg : algsAllowed) { + if (defaultAlg.trim().equals(alg.trim())) { + return defaultAlg; } } - in.close(); - } catch (Exception e) { - CMS.debug("getAdminProfleAlgorithm: exception: " + e); + throw new EBaseException( + "Administrator Certificate cannot be signed by the specified algorithm " + + "as it is not one of the allowed signing algorithms. Check the admin cert profile."); } - return algorithm; + + // no algorithm specified. Pick the first allowed algorithm. + for (String alg : algsAllowed) { + if (isAlgorithmValid(caSigningKeyType, alg)) return alg; + } + + throw new EBaseException( + "Admin certificate cannot be signed by any of the specified possible algorithms." + + "Algorithm is incompatible with the CA signing key type" ); + } + + private static boolean isAlgorithmValid(String signingKeyType, String algorithm) { + return ((signingKeyType.equals("rsa") && algorithm.contains("RSA")) || + (signingKeyType.equals("ecc") && algorithm.contains("EC")) || + (signingKeyType.equals("dsa") && algorithm.contains("DSA"))); } public static X509CertImpl createLocalCert(IConfigStore config, X509Key x509key, -- 1.8.3.1