summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java271
1 files changed, 271 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
new file mode 100644
index 000000000..979e0fdd8
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/cert/CertificatePair.java
@@ -0,0 +1,271 @@
+// --- 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.*;
+import java.security.cert.*;
+import org.mozilla.jss.asn1.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.cert.ICrossCertPairSubsystem;
+
+
+/**
+ * This class implements CertificatePair used for Cross Certification
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CertificatePair implements ASN1Value {
+ private byte[] mForward; // cert cross-siged by another CA
+ private byte[] mReverse; // subordinate cert signed by this CA
+ private static final Tag TAG = SEQUENCE.TAG;
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ * @param cert1 one X509Certificate
+ * @param cert2 one X509Certificate
+ */
+ public CertificatePair (X509Certificate cert1, X509Certificate cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ debug("in CertificatePair()");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ try {
+ if (rightOrder == false) {
+ mForward = cert2.getEncoded();
+ mReverse = cert1.getEncoded();
+ } else {
+ mForward = cert1.getEncoded();
+ mReverse = cert2.getEncoded();
+ }
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: constructor failed:" + e.toString());
+ }
+ }
+
+ /**
+ * construct a CertificatePair. It doesn't matter which is
+ * forward and which is reverse in the parameters. It will figure
+ * it out
+ * @param cert1 one certificate byte array
+ * @param cert2 one certificate byte array
+ */
+ public CertificatePair (byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ if ((cert1 == null) || (cert2 == null))
+ throw new EBaseException("CertificatePair: both certs can not be null");
+ boolean rightOrder = certOrders(cert1, cert2);
+
+ if (rightOrder == false) {
+ mForward = cert2;
+ mReverse = cert1;
+ } else {
+ mForward = cert1;
+ mReverse = cert2;
+ }
+ }
+
+ /*
+ * returns true if c1 is forward and cert2 is reverse
+ * returns false if c2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(X509Certificate c1, X509Certificate c2)
+ throws EBaseException {
+ debug("in certOrders() with X509Cert");
+
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca");
+ X509Certificate caCert = (X509Certificate) ca.getCACert();
+
+ debug("got this caCert");
+ // reverse cert is the one signed by this ca
+ // more check really should be done here regarding the
+ // validity of the two certs...later
+
+ /* It looks the DN's returned are not normalized and fail
+ * comparison
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c1");
+ else {
+ debug("c1 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c2.getSubjectDN()))
+ debug("myCA subject == c2 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c2 subjectDN="+c2.getSubjectDN().toString());
+ }
+
+ if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN())))
+ debug("myCA signed c2");
+ else {
+ debug("c2 issuerDN="+c1.getIssuerDN().toString());
+ debug("myCA subjectDN="+caCert.getSubjectDN().toString());
+ }
+
+ if(caCert.getSubjectDN().equals((Object) c1.getSubjectDN()))
+ debug("myCA subject == c1 subject");
+ else {
+ debug("caCert subjectDN="+caCert.getSubjectDN().toString());
+ debug("c1 subjectDN="+c1.getSubjectDN().toString());
+ }
+
+ if ((c1.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c2.getSubjectDN())))
+
+ {
+ return false;
+ } else if ((c2.getIssuerDN().equals((Object) caCert.getSubjectDN()))
+ && (caCert.getSubjectDN().equals((Object) c1.getSubjectDN())))
+ {
+ return true;
+ } else {
+ throw new EBaseException("CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ */
+
+ /*
+ * my other attempt:
+ * one of the certs has to share the same public key as this
+ * CA, and that will be the "forward" cert; the other one is
+ * assumed to be the "reverse" cert
+ */
+ byte[] caCertBytes = caCert.getPublicKey().getEncoded();
+
+ if (caCertBytes != null)
+ debug("got cacert public key bytes length=" + caCertBytes.length);
+ else {
+ debug("cacert public key bytes null");
+ throw new EBaseException("CertificatePair: certOrders() fails to get this CA's signing certificate public key encoded");
+ }
+
+ byte[] c1Bytes = c1.getPublicKey().getEncoded();
+
+ if (c1Bytes != null)
+ debug("got c1 public key bytes length=" + c1Bytes.length);
+ else {
+ debug("c1 cert public key bytes length null");
+ throw new EBaseException("CertificatePair::certOrders() public key bytes are of length null");
+ }
+
+ byte[] c2Bytes = c2.getPublicKey().getEncoded();
+
+ if (c2Bytes != null)
+ debug("got c2 public key bytes length=" + c2Bytes.length);
+ else
+ debug("c2 cert public key bytes length null");
+
+ if (byteArraysAreEqual(c1Bytes, caCertBytes)) {
+ debug("c1 has same public key as this ca");
+ return true;
+ } else if (byteArraysAreEqual(c2Bytes, caCertBytes)) {
+ debug("c2 has same public key as this ca");
+
+ return false;
+ } else {
+ debug("neither c1 nor c2 public key matches with this ca");
+ throw new EBaseException("CertificatePair: need correct forward and reverse relationship to construct CertificatePair");
+ }
+ }
+
+ /**
+ * compares contents two byte arrays returning true if exactly same.
+ */
+ public boolean byteArraysAreEqual(byte[] a, byte[] b) {
+ debug("in byteArraysAreEqual()");
+ if (a.length != b.length) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ debug("exiting byteArraysAreEqual(): false");
+ return false;
+ }
+ }
+ debug("exiting byteArraysAreEqual(): true");
+ return true;
+ }
+
+ /*
+ * returns true if cert1 is forward and cert2 is reverse
+ * returns false if cert2 is forward and cert1 is reverse
+ */
+ private boolean certOrders(byte[] cert1, byte[] cert2)
+ throws EBaseException {
+ debug("in certOrders() with byte[]");
+ ICrossCertPairSubsystem ccps =
+ (ICrossCertPairSubsystem) CMS.getSubsystem("CrossCertPair");
+ X509Certificate c1 = null;
+ X509Certificate c2 = null;
+
+ try {
+ c1 = ccps.byteArray2X509Cert(cert1);
+ c2 = ccps.byteArray2X509Cert(cert2);
+ } catch (CertificateException e) {
+ throw new EBaseException("CertificatePair: certOrders() failed:" + e.toString());
+ }
+ return certOrders(c1, c2);
+ }
+
+ public void encode(OutputStream os) throws IOException {
+ encode(TAG, os);
+ }
+
+ public void encode(Tag implicitTag, OutputStream os) throws IOException {
+ SEQUENCE seq = new SEQUENCE();
+
+ if (mForward != null) {
+ try {
+ ANY any = new ANY(mForward);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+ if (mReverse != null) {
+ try {
+ ANY any = new ANY(mReverse);
+
+ seq.addElement(any);
+ } catch (InvalidBERException e) {
+ debug("encode error:" + e.toString());
+ }
+ }
+
+ seq.encode(implicitTag, os);
+ }
+
+ public Tag getTag() {
+ return TAG;
+ }
+
+ private void debug(String msg) {
+ CMS.debug("CertifiatePair: " + msg);
+ }
+}