diff options
Diffstat (limited to 'base/common/src/com/netscape/cmscore/cert/CertUtils.java')
-rw-r--r-- | base/common/src/com/netscape/cmscore/cert/CertUtils.java | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cmscore/cert/CertUtils.java b/base/common/src/com/netscape/cmscore/cert/CertUtils.java new file mode 100644 index 000000000..9710d63f5 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/cert/CertUtils.java @@ -0,0 +1,1103 @@ +// --- 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.cmscore.cert; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Date; +import java.util.StringTokenizer; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS7; +import netscape.security.util.DerInputStream; +import netscape.security.util.DerOutputStream; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateIssuerName; +import netscape.security.x509.CertificateSerialNumber; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CRLImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.CryptoManager.CertificateUsage; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cmsutil.util.Utils; + +/** + * Utility class with assorted methods to check for + * smime pairs, determining the type of cert - signature + * or encryption ..etc. + * + * @author kanda + * @version $Revision$, $Date$ + */ +public class CertUtils { + public static final String CERT_NEW_REQUEST_HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + public static final String CERT_NEW_REQUEST_TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + public static final String CERT_REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----"; + public static final String CERT_REQUEST_TRAILER = "-----END CERTIFICATE REQUEST-----"; + public static final String CERT_RENEWAL_HEADER = "-----BEGIN RENEWAL CERTIFICATE REQUEST-----"; + public static final String CERT_RENEWAL_TRAILER = "-----END RENEWAL CERTIFICATE REQUEST-----"; + public static final String BEGIN_CRL_HEADER = + "-----BEGIN CERTIFICATE REVOCATION LIST-----"; + public static final String END_CRL_HEADER = + "-----END CERTIFICATE REVOCATION LIST-----"; + + protected static ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private final static String LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION = + "LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION_3"; + + /** + * Remove the header and footer in the PKCS10 request. + */ + public static String unwrapPKCS10(String request, boolean checkHeader) + throws EBaseException { + String unwrapped; + String header = null; + int head = -1; + int trail = -1; + + // check for "-----BEGIN NEW CERTIFICATE REQUEST-----"; + if (header == null) { + head = request.indexOf(CERT_NEW_REQUEST_HEADER); + trail = request.indexOf(CERT_NEW_REQUEST_TRAILER); + + if (!(head == -1 && trail == -1)) { + header = CERT_NEW_REQUEST_HEADER; + } + } + + // check for "-----BEGIN CERTIFICATE REQUEST-----"; + if (header == null) { + head = request.indexOf(CERT_REQUEST_HEADER); + trail = request.indexOf(CERT_REQUEST_TRAILER); + + // If this is not a request header, check if this is a renewal header. + if (!(head == -1 && trail == -1)) { + header = CERT_REQUEST_HEADER; + + } + } + + // check for "-----BEGIN RENEWAL CERTIFICATE REQUEST-----"; + if (header == null) { + head = request.indexOf(CERT_RENEWAL_HEADER); + trail = request.indexOf(CERT_RENEWAL_TRAILER); + if (!(head == -1 && trail == -1)) { + header = CERT_RENEWAL_HEADER; + } + } + + // Now validate if any headers or trailers are in place + if (head == -1 && checkHeader) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_HEADER")); + } + if (trail == -1 && checkHeader) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_MISSING_PKCS10_TRAILER")); + } + + if (header != null) { + unwrapped = request.substring(head + header.length(), trail); + } else { + unwrapped = request; + } + + // strip all the crtl-characters (i.e. \r\n) + StringTokenizer st = new StringTokenizer(unwrapped, "\t\r\n "); + StringBuffer stripped = new StringBuffer(); + + while (st.hasMoreTokens()) { + stripped.append(st.nextToken()); + } + + return stripped.toString(); + } + + public static PKCS10 decodePKCS10(String req) throws EBaseException { + String normalized = unwrapPKCS10(req, true); + PKCS10 pkcs10 = null; + + try { + byte[] decodedBytes = Utils.base64decode(normalized); + + pkcs10 = new PKCS10(decodedBytes); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString())); + } + return pkcs10; + } + + public static void setRSAKeyToCertInfo(X509CertInfo info, + byte encoded[]) throws EBaseException { + try { + if (info == null) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION")); + } + X509Key key = new X509Key(AlgorithmId.getAlgorithmId( + "RSAEncryption"), encoded); + + info.set(X509CertInfo.KEY, key); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION")); + } + } + + public static X509CertInfo createCertInfo(int ver, + BigInteger serialno, String alg, String issuerName, + Date notBefore, Date notAfter) throws EBaseException { + try { + X509CertInfo info = new X509CertInfo(); + + info.set(X509CertInfo.VERSION, new CertificateVersion(ver)); + info.set(X509CertInfo.SERIAL_NUMBER, new + CertificateSerialNumber(serialno)); + info.set(X509CertInfo.ALGORITHM_ID, new + CertificateAlgorithmId(AlgorithmId.getAlgorithmId(alg))); + info.set(X509CertInfo.ISSUER, new + CertificateIssuerName(new X500Name(issuerName))); + info.set(X509CertInfo.VALIDITY, new + CertificateValidity(notBefore, notAfter)); + return info; + } catch (Exception e) { + System.out.println(e.toString()); + return null; + } + } + + public static void sortCerts(X509CertImpl[] arr) { + Arrays.sort(arr, new CertDateCompare()); + } + + public static boolean isSigningCert(X509CertImpl cert) { + boolean[] keyUsage = null; + + try { + keyUsage = cert.getKeyUsage(); + } catch (Exception e) { + e.printStackTrace(); + } + return (keyUsage == null) ? false : keyUsage[0]; + } + + public static boolean isEncryptionCert(X509CertImpl cert) { + boolean[] keyUsage = null; + + try { + keyUsage = cert.getKeyUsage(); + } catch (Exception e) { + e.printStackTrace(); + } + if (keyUsage == null) + return false; + if (keyUsage.length < 3) + return false; + else if (keyUsage.length == 3) + return keyUsage[2]; + else + return keyUsage[2] || keyUsage[3]; + } + + public static boolean haveSameValidityPeriod(X509CertImpl cert1, + X509CertImpl cert2) { + long notBefDiff = 0; + long notAfterDiff = 0; + + try { + notBefDiff = Math.abs(cert1.getNotBefore().getTime() - + cert2.getNotBefore().getTime()); + notAfterDiff = Math.abs(cert1.getNotAfter().getTime() - + cert2.getNotAfter().getTime()); + } catch (Exception e) { + e.printStackTrace(); + } + if (notBefDiff > 1000 || notAfterDiff > 1000) + return false; + else + return true; + } + + public static boolean isSmimePair(X509CertImpl cert1, X509CertImpl cert2, boolean matchSubjectDN) { + // Check for subjectDN equality. + if (matchSubjectDN) { + String dn1 = cert1.getSubjectDN().toString(); + String dn2 = cert2.getSubjectDN().toString(); + + if (!sameSubjectDN(dn1, dn2)) + return false; + } + + // Check for the presence of signing and encryption certs. + boolean hasSigningCert = isSigningCert(cert1) || isSigningCert(cert2); + + if (!hasSigningCert) + return false; + + boolean hasEncryptionCert = isEncryptionCert(cert1) || isEncryptionCert(cert2); + + if (!hasEncryptionCert) + return false; + + // If both certs have signing & encryption usage set, they are + // not really pairs. + if ((isSigningCert(cert1) && isEncryptionCert(cert1)) || + (isSigningCert(cert2) && isEncryptionCert(cert2))) + return false; + + // See if the certs have the same validity. + boolean haveSameValidity = + haveSameValidityPeriod(cert1, cert2); + + return haveSameValidity; + } + + public static boolean isNotYetValidCert(X509CertImpl cert) { + boolean ret = false; + + try { + cert.checkValidity(); + } catch (CertificateExpiredException e) { + } catch (CertificateNotYetValidException e) { + ret = true; + } catch (Exception e) { + } + return ret; + } + + public static boolean isValidCert(X509CertImpl cert) { + boolean ret = true; + + try { + cert.checkValidity(); + } catch (Exception e) { + ret = false; + } + return ret; + } + + public static boolean isExpiredCert(X509CertImpl cert) { + boolean ret = false; + + try { + cert.checkValidity(); + } catch (CertificateExpiredException e) { + ret = true; + } catch (Exception e) { + } + return ret; + } + + public static boolean sameSubjectDN(String dn1, String dn2) { + boolean ret = false; + + // The dn cannot be null. + if (dn1 == null || dn2 == null) + return false; + try { + X500Name n1 = new X500Name(dn1); + X500Name n2 = new X500Name(dn2); + + ret = n1.equals(n2); + } catch (Exception e) { + } + return ret; + } + + public static String getValidCertsDisplayInfo(String cn, X509CertImpl[] validCerts) { + StringBuffer sb = new StringBuffer(1024); + + sb.append(cn + "'s Currently Valid Certificates\n\n"); + sb.append(getCertsDisplayInfo(validCerts)); + return new String(sb); + } + + public static String getExpiredCertsDisplayInfo(String cn, X509CertImpl[] expiredCerts) { + StringBuffer sb = new StringBuffer(1024); + + sb.append(cn + "'s Expired Certificates\n\n"); + sb.append(getCertsDisplayInfo(expiredCerts)); + return new String(sb); + } + + public static String getRenewedCertsDisplayInfo(String cn, + X509CertImpl[] validCerts, X509CertImpl[] renewedCerts) { + StringBuffer sb = new StringBuffer(1024); + + if (validCerts != null) { + sb.append(cn + "'s Currently Valid Certificates\n\n"); + sb.append(getCertsDisplayInfo(validCerts)); + sb.append("\n\nRenewed Certificates\n\n\n"); + } else + sb.append(cn + "'s Renewed Certificates\n\n"); + sb.append(getCertsDisplayInfo(renewedCerts)); + return new String(sb); + } + + public static String getCertsDisplayInfo(X509CertImpl[] validCerts) { + // We assume that the given pair is a valid S/MIME pair. + StringBuffer sb = new StringBuffer(1024); + + sb.append("Subject DN: " + validCerts[0].getSubjectDN().toString()); + sb.append("\n"); + X509CertImpl signingCert, encryptionCert; + + if (isSigningCert(validCerts[0])) { + signingCert = validCerts[0]; + encryptionCert = validCerts[1]; + } else { + signingCert = validCerts[1]; + encryptionCert = validCerts[0]; + } + sb.append("Signing Certificate Serial No: " + signingCert.getSerialNumber().toString(16).toUpperCase()); + sb.append("\n"); + sb.append("Encryption Certificate Serial No: " + encryptionCert.getSerialNumber().toString(16).toUpperCase()); + sb.append("\n"); + sb.append("Validity: From: " + + signingCert.getNotBefore().toString() + " To: " + signingCert.getNotAfter().toString()); + sb.append("\n"); + return new String(sb); + } + + /** + * Returns the index of the given cert in an array of certs. + * + * Assumptions: The certs are issued by the same CA + * + * @param certArray The array of certs. + * @param givenCert The certificate we are lokking for in the array. + * @return -1 if not found or the index of the given cert in the array. + */ + public static int getCertIndex(X509CertImpl[] certArray, X509CertImpl givenCert) { + int i = 0; + + for (; i < certArray.length; i++) { + if (certArray[i].getSerialNumber().equals( + givenCert.getSerialNumber())) { + break; + } + } + + return ((i == certArray.length) ? -1 : i); + } + + /** + * Returns the most recently issued signing certificate from an + * an array of certs. + * + * Assumptions: The certs are issued by the same CA + * + * @param certArray The array of certs. + * @param givenCert The certificate we are lokking for in the array. + * @return null if there is no recent cert or the most recent cert. + */ + public static X509CertImpl getRecentSigningCert(X509CertImpl[] certArray, + X509CertImpl currentCert) { + if (certArray == null || currentCert == null) + return null; + + // Sort the certificate array. + Arrays.sort(certArray, new CertDateCompare()); + + // Get the index of the current cert in the array. + int i = getCertIndex(certArray, currentCert); + + if (i < 0) + return null; + + X509CertImpl recentCert = currentCert; + + for (; i < certArray.length; i++) { + // Check if it is a signing cert and has its + // NotAfter later than the current cert. + if (isSigningCert(certArray[i]) && + certArray[i].getNotAfter().after(recentCert.getNotAfter())) + recentCert = certArray[i]; + } + return ((recentCert == currentCert) ? null : recentCert); + } + + public static String getCertType(X509CertImpl cert) { + StringBuffer sb = new StringBuffer(); + + if (isSigningCert(cert)) + sb.append("signing"); + if (isEncryptionCert(cert)) { + if (sb.length() > 0) + sb.append(" "); + sb.append("encryption"); + } + + // Is is object signing cert? + try { + CertificateExtensions extns = (CertificateExtensions) + cert.get(X509CertImpl.NAME + "." + + X509CertImpl.INFO + "." + + X509CertInfo.EXTENSIONS); + + if (extns != null) { + NSCertTypeExtension nsExtn = (NSCertTypeExtension) + extns.get(NSCertTypeExtension.NAME); + + if (nsExtn != null) { + String nsType = getNSExtensionInfo(nsExtn); + + if (nsType != null) { + if (sb.length() > 0) + sb.append(" "); + sb.append(nsType); + } + } + } + } catch (Exception e) { + } + return (sb.length() > 0) ? sb.toString() : null; + } + + public static String getNSExtensionInfo(NSCertTypeExtension nsExtn) { + StringBuffer sb = new StringBuffer(); + + try { + Boolean res; + + res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CLIENT); + if (res.equals(Boolean.TRUE)) + sb.append(" ssl_client"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_SERVER); + if (res.equals(Boolean.TRUE)) + sb.append(" ssl_server"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL); + if (res.equals(Boolean.TRUE)) + sb.append(" email"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING); + if (res.equals(Boolean.TRUE)) + sb.append(" object_signing"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.SSL_CA); + if (res.equals(Boolean.TRUE)) + sb.append(" ssl_CA"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.EMAIL_CA); + if (res.equals(Boolean.TRUE)) + sb.append(" email_CA"); + res = (Boolean) nsExtn.get(NSCertTypeExtension.OBJECT_SIGNING_CA); + if (res.equals(Boolean.TRUE)) + sb.append(" object_signing_CA"); + } catch (Exception e) { + } + + return (sb.length() > 0) ? sb.toString() : null; + } + + public static byte[] readFromFile(String fileName) + throws IOException { + FileInputStream fin = new FileInputStream(fileName); + int available = fin.available(); + byte[] ba = new byte[available]; + int nRead = fin.read(ba); + + if (nRead != available) + throw new IOException("Error reading data from file: " + fileName); + fin.close(); + return ba; + } + + public static void storeInFile(String fileName, byte[] ba) + throws IOException { + FileOutputStream fout = new FileOutputStream(fileName); + + fout.write(ba); + fout.close(); + } + + public static String toMIME64(X509CertImpl cert) { + try { + return "-----BEGIN CERTIFICATE-----\n" + + Utils.base64encode(cert.getEncoded()) + + "-----END CERTIFICATE-----\n"; + } catch (CertificateException e) { + } + return null; + } + + public static X509Certificate mapCert(String mime64) + throws IOException { + mime64 = stripCertBrackets(mime64.trim()); + String newval = normalizeCertStr(mime64); + byte rawPub[] = Utils.base64decode(newval); + X509Certificate cert = null; + + try { + cert = new X509CertImpl(rawPub); + } catch (CertificateException e) { + } + return cert; + } + + public static X509Certificate[] mapCertFromPKCS7(String mime64) + throws IOException { + mime64 = stripCertBrackets(mime64.trim()); + String newval = normalizeCertStr(mime64); + byte rawPub[] = Utils.base64decode(newval); + PKCS7 p7 = null; + + try { + p7 = new PKCS7(rawPub); + return p7.getCertificates(); + } catch (Exception e) { + throw new IOException(e.toString()); + } + } + + public static X509CRL mapCRL(String mime64) + throws IOException { + mime64 = stripCRLBrackets(mime64.trim()); + String newval = normalizeCertStr(mime64); + byte rawPub[] = Utils.base64decode(newval); + X509CRL crl = null; + + try { + crl = new X509CRLImpl(rawPub); + } catch (Exception e) { + } + return crl; + } + + public static X509CRL mapCRL1(String mime64) + throws IOException { + mime64 = stripCRLBrackets(mime64.trim()); + byte rawPub[] = Utils.base64decode(mime64); + X509CRL crl = null; + + try { + crl = new X509CRLImpl(rawPub); + } catch (Exception e) { + throw new IOException(e.toString()); + } + return crl; + } + + public static String normalizeCertStr(String s) { + String val = ""; + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\n') { + continue; + } else if (s.charAt(i) == '\r') { + continue; + } else if (s.charAt(i) == '"') { + continue; + } else if (s.charAt(i) == ' ') { + continue; + } + val += s.charAt(i); + } + return val; + } + + public static String stripCRLBrackets(String s) { + if (s == null) { + return s; + } + if ((s.startsWith("-----BEGIN CERTIFICATE REVOCATION LIST-----")) && + (s.endsWith("-----END CERTIFICATE REVOCATION LIST-----"))) { + return (s.substring(43, (s.length() - 41))); + } + return s; + } + + /** + * strips out the begin and end certificate brackets + * + * @param s the string potentially bracketed with + * "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" + * @return string without the brackets + */ + public static String stripCertBrackets(String s) { + if (s == null) { + return s; + } + + if ((s.startsWith("-----BEGIN CERTIFICATE-----")) && + (s.endsWith("-----END CERTIFICATE-----"))) { + return (s.substring(27, (s.length() - 25))); + } + + // To support Thawte's header and footer + if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) && + (s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) { + return (s.substring(35, (s.length() - 33))); + } + + return s; + } + + /** + * Returns a string that represents a cert's fingerprint. + * The fingerprint is a MD5 digest of the DER encoded certificate. + * + * @param cert Certificate to get the fingerprint of. + * @return a String that represents the cert's fingerprint. + */ + public static String getFingerPrint(Certificate cert) + throws CertificateEncodingException, NoSuchAlgorithmException { + byte certDer[] = cert.getEncoded(); + MessageDigest md = MessageDigest.getInstance("MD5"); + + md.update(certDer); + byte digestedCert[] = md.digest(); + PrettyPrintFormat pp = new PrettyPrintFormat(":"); + StringBuffer sb = new StringBuffer(); + + sb.append(pp.toHexString(digestedCert, 4, 20)); + return sb.toString(); + } + + /** + * Returns a string that has the certificate's fingerprint using + * MD5, MD2 and SHA1 hashes. + * A certificate's fingerprint is a hash digest of the DER encoded + * certificate. + * + * @param cert Certificate to get the fingerprints of. + * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes. + * For example, + * + * <pre> + * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71 + * + * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75 + * + * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00 + * </pre> + */ + public static String getFingerPrints(Certificate cert) + throws NoSuchAlgorithmException, CertificateEncodingException { + byte certDer[] = cert.getEncoded(); + /* + String[] hashes = new String[] {"MD2", "MD5", "SHA1"}; + String certFingerprints = ""; + PrettyPrintFormat pp = new PrettyPrintFormat(":"); + + for (int i = 0; i < hashes.length; i++) { + MessageDigest md = MessageDigest.getInstance(hashes[i]); + + md.update(certDer); + certFingerprints += " " + hashes[i] + ":" + + pp.toHexString(md.digest(), 6 - hashes[i].length()); + } + return certFingerprints; + */ + return getFingerPrints(certDer); + } + + /** + * Returns a string that has the certificate's fingerprint using + * MD5, MD2 and SHA1 hashes. + * A certificate's fingerprint is a hash digest of the DER encoded + * certificate. + * + * @param cert Certificate to get the fingerprints of. + * @return a String with fingerprints using the MD5, MD2 and SHA1 hashes. + * For example, + * + * <pre> + * MD2: 78:7E:D1:F9:3E:AF:50:18:68:A7:29:50:C3:21:1F:71 + * + * MD5: 0E:89:91:AC:40:50:F7:BE:6E:7B:39:4F:56:73:75:75 + * + * SHA1: DC:D9:F7:AF:E2:83:10:B2:F7:0A:77:E8:50:E2:F7:D1:15:9A:9D:00 + * </pre> + */ + public static String getFingerPrints(byte[] certDer) + throws NoSuchAlgorithmException/*, CertificateEncodingException*/{ + // byte certDer[] = cert.getEncoded(); + String[] hashes = new String[] { "MD2", "MD5", "SHA1", "SHA256", "SHA512" }; + String certFingerprints = ""; + PrettyPrintFormat pp = new PrettyPrintFormat(":"); + + for (int i = 0; i < hashes.length; i++) { + MessageDigest md = MessageDigest.getInstance(hashes[i]); + + md.update(certDer); + certFingerprints += hashes[i] + ":\n" + + pp.toHexString(md.digest(), 8, 16); + } + return certFingerprints; + } + + /** + * Check if a object identifier in string form is valid, + * that is a string in the form n.n.n.n and der encode and decode-able. + * + * @param attrName attribute name (from the configuration file) + * @param value object identifier string. + */ + public static ObjectIdentifier checkOID(String attrName, String value) + throws EBaseException { + String msg = "value must be a object identifier in the form n.n.n.n"; + String msg1 = "not a valid object identifier."; + ObjectIdentifier oid; + + try { + oid = ObjectIdentifier.getObjectIdentifier(value); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + attrName, msg)); + } + + // if the OID isn't valid (ex. n.n) the error isn't caught til + // encoding time leaving a bad request in the request queue. + try { + DerOutputStream derOut = new DerOutputStream(); + + derOut.putOID(oid); + new ObjectIdentifier(new DerInputStream(derOut.toByteArray())); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + attrName, msg1)); + } + return oid; + } + + public static String trimB64E(String b64e) { + StringBuffer tmp = new StringBuffer(""); + String line = null; + StringTokenizer tokens = new StringTokenizer(b64e, "\n"); + + while (tokens.hasMoreTokens()) { + line = tokens.nextToken(); + line = line.trim(); + tmp.append(line.trim()); + if (tokens.hasMoreTokens()) + tmp.append("\n"); + } + + return tmp.toString(); + } + + /* + * verify a certificate by its nickname + * returns true if it verifies; false if any not + */ + public static boolean verifySystemCertByNickname(String nickname, String certusage) { + boolean r = true; + CertificateUsage cu = null; + cu = getCertificateUsage(certusage); + int ccu = 0; + + if (cu == null) { + CMS.debug("CertUtils: verifySystemCertByNickname() failed: " + + nickname + " with unsupported certusage =" + certusage); + return false; + } + + if (certusage == "") + CMS.debug("CertUtils: verifySystemCertByNickname(): required certusage not defined, getting current certusage"); + CMS.debug("CertUtils: verifySystemCertByNickname(): calling isCertValid()"); + try { + CryptoManager cm = CryptoManager.getInstance(); + if (cu.getUsage() != CryptoManager.CertificateUsage.CheckAllUsages.getUsage()) { + if (cm.isCertValid(nickname, true, cu)) { + r = true; + CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname); + } else { + CMS.debug("CertUtils: verifySystemCertByNickname() failed:" + nickname); + r = false; + } + } else { + // find out about current cert usage + ccu = cm.isCertValid(nickname, true); + if (ccu == CertificateUsage.basicCertificateUsages) { + /* cert is good for nothing */ + r = false; + CMS.debug("CertUtils: verifySystemCertByNickname() failed: cert is good for nothing:" + nickname); + } else { + r = true; + CMS.debug("CertUtils: verifySystemCertByNickname() passed:" + nickname); + + if ((ccu & CryptoManager.CertificateUsage.SSLServer.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServer"); + if ((ccu & CryptoManager.CertificateUsage.SSLClient.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLClient"); + if ((ccu & CryptoManager.CertificateUsage.SSLServerWithStepUp.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLServerWithStepUp"); + if ((ccu & CryptoManager.CertificateUsage.SSLCA.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is SSLCA"); + if ((ccu & CryptoManager.CertificateUsage.EmailSigner.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailSigner"); + if ((ccu & CryptoManager.CertificateUsage.EmailRecipient.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is EmailRecipient"); + if ((ccu & CryptoManager.CertificateUsage.ObjectSigner.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ObjectSigner"); + if ((ccu & CryptoManager.CertificateUsage.UserCertImport.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is UserCertImport"); + if ((ccu & CryptoManager.CertificateUsage.VerifyCA.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is VerifyCA"); + if ((ccu & CryptoManager.CertificateUsage.ProtectedObjectSigner.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is ProtectedObjectSigner"); + if ((ccu & CryptoManager.CertificateUsage.StatusResponder.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is StatusResponder"); + if ((ccu & CryptoManager.CertificateUsage.AnyCA.getUsage()) != 0) + CMS.debug("CertUtils: verifySystemCertByNickname(): cert is AnyCA"); + } + } + } catch (Exception e) { + CMS.debug("CertUtils: verifySystemCertByNickname() failed: " + + e.toString()); + r = false; + } + return r; + } + + /* + * verify a certificate by its tag name + * returns true if it verifies; false if any not + */ + public static boolean verifySystemCertByTag(String tag) { + String auditMessage = null; + IConfigStore config = CMS.getConfigStore(); + boolean r = true; + try { + String subsysType = config.getString("cs.type", ""); + if (subsysType.equals("")) { + CMS.debug("CertUtils: verifySystemCertByTag() cs.type not defined in CS.cfg. System certificates verification not done"); + r = false; + } + subsysType = toLowerCaseSubsystemType(subsysType); + if (subsysType == null) { + CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + r = false; + return r; + } + String nickname = config.getString(subsysType + ".cert." + tag + ".nickname", ""); + if (nickname.equals("")) { + CMS.debug("CertUtils: verifySystemCertByTag() nickname for cert tag " + tag + " undefined in CS.cfg"); + r = false; + } + String certusage = config.getString(subsysType + ".cert." + tag + ".certusage", ""); + if (certusage.equals("")) { + CMS.debug("CertUtils: verifySystemCertByTag() certusage for cert tag " + + tag + " undefined in CS.cfg, getting current certificate usage"); + } + r = verifySystemCertByNickname(nickname, certusage); + if (r == true) { + // audit here + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.SUCCESS, + nickname); + + audit(auditMessage); + } else { + // audit here + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + nickname); + + audit(auditMessage); + } + } catch (Exception e) { + CMS.debug("CertUtils: verifySystemCertsByTag() failed: " + + e.toString()); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + r = false; + } + + return r; + } + + /* + * returns CertificateUsage mapping to JSS + */ + public static CertificateUsage getCertificateUsage(String certusage) { + CertificateUsage cu = null; + if ((certusage == null) || certusage.equals("")) + cu = CryptoManager.CertificateUsage.CheckAllUsages; + else if (certusage.equalsIgnoreCase("CheckAllUsages")) + cu = CryptoManager.CertificateUsage.CheckAllUsages; + else if (certusage.equalsIgnoreCase("SSLServer")) + cu = CryptoManager.CertificateUsage.SSLServer; + else if (certusage.equalsIgnoreCase("SSLServerWithStepUp")) + cu = CryptoManager.CertificateUsage.SSLServerWithStepUp; + else if (certusage.equalsIgnoreCase("SSLClient")) + cu = CryptoManager.CertificateUsage.SSLClient; + else if (certusage.equalsIgnoreCase("SSLCA")) + cu = CryptoManager.CertificateUsage.SSLCA; + else if (certusage.equalsIgnoreCase("AnyCA")) + cu = CryptoManager.CertificateUsage.AnyCA; + else if (certusage.equalsIgnoreCase("StatusResponder")) + cu = CryptoManager.CertificateUsage.StatusResponder; + else if (certusage.equalsIgnoreCase("ObjectSigner")) + cu = CryptoManager.CertificateUsage.ObjectSigner; + else if (certusage.equalsIgnoreCase("UserCertImport")) + cu = CryptoManager.CertificateUsage.UserCertImport; + else if (certusage.equalsIgnoreCase("ProtectedObjectSigner")) + cu = CryptoManager.CertificateUsage.ProtectedObjectSigner; + else if (certusage.equalsIgnoreCase("VerifyCA")) + cu = CryptoManager.CertificateUsage.VerifyCA; + else if (certusage.equalsIgnoreCase("EmailSigner")) + cu = CryptoManager.CertificateUsage.EmailSigner; + + return cu; + } + + /* + * goes through all system certs and check to see if they are good + * and audit the result + * returns true if all verifies; false if any not + */ + public static boolean verifySystemCerts() { + String auditMessage = null; + IConfigStore config = CMS.getConfigStore(); + boolean verifyResult = true; + boolean r = true; /* the final return value */ + try { + String subsysType = config.getString("cs.type", ""); + if (subsysType.equals("")) { + CMS.debug("CertUtils: verifySystemCerts() cs.type not defined in CS.cfg. System certificates verification not done"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + return false; + } + subsysType = toLowerCaseSubsystemType(subsysType); + if (subsysType == null) { + CMS.debug("CertUtils: verifySystemCerts() invalid cs.type in CS.cfg. System certificates verification not done"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + return false; + } + String certlist = config.getString(subsysType + ".cert.list", ""); + if (certlist.equals("")) { + CMS.debug("CertUtils: verifySystemCerts() " + + subsysType + ".cert.list not defined in CS.cfg. System certificates verification not done"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + return false; + } + StringTokenizer tokenizer = new StringTokenizer(certlist, ","); + while (tokenizer.hasMoreTokens()) { + String tag = tokenizer.nextToken(); + tag = tag.trim(); + CMS.debug("CertUtils: verifySystemCerts() cert tag=" + tag); + verifyResult = verifySystemCertByTag(tag); + if (verifyResult == false) + r = false; //r captures the value for final return + } + } catch (Exception e) { + // audit here + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + ILogger.SYSTEM_UID, + ILogger.FAILURE, + ""); + + audit(auditMessage); + r = false; + CMS.debug("CertUtils: verifySystemCerts():" + e.toString()); + } + return r; + } + + public static String toLowerCaseSubsystemType(String s) { + String x = null; + if (s.equalsIgnoreCase("CA")) { + x = "ca"; + } else if (s.equalsIgnoreCase("KRA")) { + x = "kra"; + } else if (s.equalsIgnoreCase("OCSP")) { + x = "ocsp"; + } else if (s.equalsIgnoreCase("TKS")) { + x = "tks"; + } + + return x; + } + + /** + * Signed Audit Log + * This method is called to store messages to the signed audit log. + * + * @param msg signed audit log message + */ + private static void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + +} |