/* X509Certificate.java -- X.509 certificate.
   Copyright (C) 2003, 2004, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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; either version 2, or (at your option)
any later version.

GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.security.x509;

import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.ext.BasicConstraints;
import gnu.java.security.x509.ext.ExtendedKeyUsage;
import gnu.java.security.x509.ext.Extension;
import gnu.java.security.x509.ext.GeneralName;
import gnu.java.security.x509.ext.IssuerAlternativeNames;
import gnu.java.security.x509.ext.KeyUsage;
import gnu.java.security.x509.ext.SubjectAlternativeNames;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.security.auth.x500.X500Principal;

/**
 * An implementation of X.509 certificates.
 *
 * @author Casey Marshall (rsdio@metastatic.org)
 */
public class X509Certificate extends java.security.cert.X509Certificate
  implements Serializable, GnuPKIExtension
{

  // Constants and fields.
  // ------------------------------------------------------------------------

  private static final long serialVersionUID = -2491127588187038216L;
  private static final Logger logger = SystemLogger.SYSTEM;

  protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1");
  protected static final OID ID_DSA_WITH_SHA1 = new OID ("1.2.840.10040.4.3");
  protected static final OID ID_RSA = new OID ("1.2.840.113549.1.1.1");
  protected static final OID ID_RSA_WITH_MD2 = new OID ("1.2.840.113549.1.1.2");
  protected static final OID ID_RSA_WITH_MD5 = new OID ("1.2.840.113549.1.1.4");
  protected static final OID ID_RSA_WITH_SHA1 = new OID ("1.2.840.113549.1.1.5");
  protected static final OID ID_ECDSA_WITH_SHA1 = new OID ("1.2.840.10045.4.1");

  // This object SHOULD be serialized with an instance of
  // java.security.cert.Certificate.CertificateRep, thus all fields are
  // transient.

  // The encoded certificate.
  protected transient byte[] encoded;

  // TBSCertificate part.
  protected transient byte[] tbsCertBytes;
  protected transient int version;
  protected transient BigInteger serialNo;
  protected transient OID algId;
  protected transient byte[] algVal;
  protected transient X500DistinguishedName issuer;
  protected transient Date notBefore;
  protected transient Date notAfter;
  protected transient X500DistinguishedName subject;
  protected transient PublicKey subjectKey;
  protected transient BitString issuerUniqueId;
  protected transient BitString subjectUniqueId;
  protected transient Map<OID, Extension> extensions;

  // Signature.
  protected transient OID sigAlgId;
  protected transient byte[] sigAlgVal;
  protected transient byte[] signature;

  // Constructors.
  // ------------------------------------------------------------------------

  /**
   * Create a new X.509 certificate from the encoded data. The input
   * data are expected to be the ASN.1 DER encoding of the certificate.
   *
   * @param encoded The encoded certificate data.
   * @throws IOException If the certificate cannot be read, possibly
   * from a formatting error.
   * @throws CertificateException If the data read is not an X.509
   * certificate.
   */
  public X509Certificate(InputStream encoded)
    throws CertificateException, IOException
  {
    super();
    extensions = new HashMap<OID, Extension>();
    try
      {
        parse(encoded);
      }
    catch (IOException ioe)
      {
        logger.log (Component.X509, "", ioe);
        throw ioe;
      }
    catch (Exception e)
      {
        logger.log (Component.X509, "", e);
        CertificateException ce = new CertificateException(e.getMessage());
        ce.initCause (e);
        throw ce;
      }
  }

  protected X509Certificate()
  {
    extensions = new HashMap<OID, Extension>();
  }

  // X509Certificate methods.
  // ------------------------------------------------------------------------

  public void checkValidity()
    throws CertificateExpiredException, CertificateNotYetValidException
  {
    checkValidity(new Date());
  }

  public void checkValidity(Date date)
    throws CertificateExpiredException, CertificateNotYetValidException
  {
    if (date.compareTo(notBefore) < 0)
      {
        throw new CertificateNotYetValidException();
      }
    if (date.compareTo(notAfter) > 0)
      {
        throw new CertificateExpiredException();
      }
  }

  public int getVersion()
  {
    return version;
  }

  public BigInteger getSerialNumber()
  {
    return serialNo;
  }

  public Principal getIssuerDN()
  {
    return issuer;
  }

  public X500Principal getIssuerX500Principal()
  {
    return new X500Principal(issuer.getDer());
  }

  public Principal getSubjectDN()
  {
    return subject;
  }

  public X500Principal getSubjectX500Principal()
  {
    return new X500Principal(subject.getDer());
  }

  public Date getNotBefore()
  {
    return (Date) notBefore.clone();
  }

  public Date getNotAfter()
  {
    return (Date) notAfter.clone();
  }

  public byte[] getTBSCertificate() throws CertificateEncodingException
  {
    return (byte[]) tbsCertBytes.clone();
  }

  public byte[] getSignature()
  {
    return (byte[]) signature.clone();
  }

  public String getSigAlgName()
  {
    if (sigAlgId.equals(ID_DSA_WITH_SHA1))
      {
        return "SHA1withDSA";
      }
    if (sigAlgId.equals(ID_RSA_WITH_MD2))
      {
        return "MD2withRSA";
      }
    if (sigAlgId.equals(ID_RSA_WITH_MD5))
      {
        return "MD5withRSA";
      }
    if (sigAlgId.equals(ID_RSA_WITH_SHA1))
      {
        return "SHA1withRSA";
      }
    return "unknown";
  }

  public String getSigAlgOID()
  {
    return sigAlgId.toString();
  }

  public byte[] getSigAlgParams()
  {
    return (byte[]) sigAlgVal.clone();
  }

  public boolean[] getIssuerUniqueID()
  {
    if (issuerUniqueId != null)
      {
        return issuerUniqueId.toBooleanArray();
      }
    return null;
  }

  public boolean[] getSubjectUniqueID()
  {
    if (subjectUniqueId != null)
      {
        return subjectUniqueId.toBooleanArray();
      }
    return null;
  }

  public boolean[] getKeyUsage()
  {
    Extension e = getExtension(KeyUsage.ID);
    if (e != null)
      {
        KeyUsage ku = (KeyUsage) e.getValue();
        boolean[] result = new boolean[9];
        boolean[] b = ku.getKeyUsage().toBooleanArray();
        System.arraycopy(b, 0, result, 0, b.length);
        return result;
      }
    return null;
  }

  public List<String> getExtendedKeyUsage() throws CertificateParsingException
  {
    Extension e = getExtension(ExtendedKeyUsage.ID);
    if (e != null)
      {
        List<OID> a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
        List<String> b = new ArrayList<String>(a.size());
        for (OID oid : a)
          b.add(oid.toString());
        return Collections.unmodifiableList(b);
      }
    return null;
  }

  public int getBasicConstraints()
  {
    Extension e = getExtension(BasicConstraints.ID);
    if (e != null)
      {
        return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
      }
    return -1;
  }

  public Collection<List<?>> getSubjectAlternativeNames()
    throws CertificateParsingException
  {
    Extension e = getExtension(SubjectAlternativeNames.ID);
    if (e != null)
      {
        List<GeneralName> names
          = ((SubjectAlternativeNames) e.getValue()).getNames();
        List<List<?>> list = new ArrayList<List<?>>(names.size());
        for (GeneralName name : names)
          {
            List<Object> n = new ArrayList<Object>(2);
            n.add(name.kind().tag());
            n.add(name.name());
            list.add(n);
          }
        return list;
      }
    return null;
  }

  public Collection<List<?>> getIssuerAlternativeNames()
    throws CertificateParsingException
  {
    Extension e = getExtension(IssuerAlternativeNames.ID);
    if (e != null)
      {
        List<GeneralName> names
          = ((IssuerAlternativeNames) e.getValue()).getNames();
        List<List<?>> list = new ArrayList<List<?>>(names.size());
        for (GeneralName name : names)
          {
            List<Object> n = new ArrayList<Object>(2);
            n.add(name.kind().tag());
            n.add(name.name());
            list.add(n);
          }
        return list;
      }
    return null;
  }

// X509Extension methods.
  // ------------------------------------------------------------------------

  public boolean hasUnsupportedCriticalExtension()
  {
    for (Iterator it = extensions.values().iterator(); it.hasNext(); )
      {
        Extension e = (Extension) it.next();
        if (e.isCritical() && !e.isSupported())
          return true;
      }
    return false;
  }

  public Set<String> getCriticalExtensionOIDs()
  {
    HashSet<String> s = new HashSet<String>();
    for (Extension e : extensions.values())
      {
        if (e.isCritical())
          s.add(e.getOid().toString());
      }
    return Collections.unmodifiableSet(s);
  }

  public Set<String> getNonCriticalExtensionOIDs()
  {
    HashSet<String> s = new HashSet<String>();
    for (Extension e : extensions.values())
      {
        if (!e.isCritical())
          s.add(e.getOid().toString());
      }
    return Collections.unmodifiableSet(s);
  }

  public byte[] getExtensionValue(String oid)
  {
    Extension e = getExtension(new OID(oid));
    if (e != null)
      {
        return e.getValue().getEncoded();
      }
    return null;
  }

  // GnuPKIExtension method.
  // -------------------------------------------------------------------------

  public Extension getExtension(OID oid)
  {
    return (Extension) extensions.get(oid);
  }

  public Collection getExtensions()
  {
    return extensions.values();
  }

  // Certificate methods.
  // -------------------------------------------------------------------------

  public byte[] getEncoded() throws CertificateEncodingException
  {
    return (byte[]) encoded.clone();
  }

  public void verify(PublicKey key)
    throws CertificateException, NoSuchAlgorithmException,
           InvalidKeyException, NoSuchProviderException, SignatureException
  {
    Signature sig = Signature.getInstance(sigAlgId.toString());
    doVerify(sig, key);
  }

  public void verify(PublicKey key, String provider)
    throws CertificateException, NoSuchAlgorithmException,
           InvalidKeyException, NoSuchProviderException, SignatureException
  {
    Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
    doVerify(sig, key);
  }

  public String toString()
  {
    StringWriter str = new StringWriter();
    PrintWriter out = new PrintWriter(str);
    out.println(X509Certificate.class.getName() + " {");
    out.println("  TBSCertificate {");
    out.println("    version = " + version + ";");
    out.println("    serialNo = " + serialNo + ";");
    out.println("    signature = {");
    out.println("      algorithm = " + getSigAlgName() + ";");
    out.print("      parameters =");
    if (sigAlgVal != null)
      {
        out.println();
        out.print(Util.hexDump(sigAlgVal, "        "));
      }
    else
      {
        out.println(" null;");
      }
    out.println("    }");
    out.println("    issuer = " + issuer.getName() + ";");
    out.println("    validity = {");
    out.println("      notBefore = " + notBefore + ";");
    out.println("      notAfter  = " + notAfter + ";");
    out.println("    }");
    out.println("    subject = " + subject.getName() + ";");
    out.println("    subjectPublicKeyInfo = {");
    out.println("      algorithm = " + subjectKey.getAlgorithm());
    out.println("      key =");
    out.print(Util.hexDump(subjectKey.getEncoded(), "        "));
    out.println("    };");
    out.println("    issuerUniqueId  = " + issuerUniqueId + ";");
    out.println("    subjectUniqueId = " + subjectUniqueId + ";");
    out.println("    extensions = {");
    for (Iterator it = extensions.values().iterator(); it.hasNext(); )
      {
        out.println("      " + it.next());
      }
    out.println("    }");
    out.println("  }");
    out.println("  signatureAlgorithm = " + getSigAlgName() + ";");
    out.println("  signatureValue =");
    out.print(Util.hexDump(signature, "    "));
    out.println("}");
    return str.toString();
  }

  public PublicKey getPublicKey()
  {
    return subjectKey;
  }

  public boolean equals(Object other)
  {
    if (!(other instanceof X509Certificate))
      return false;
    try
      {
        if (other instanceof X509Certificate)
          return Arrays.equals(encoded, ((X509Certificate) other).encoded);
        byte[] enc = ((X509Certificate) other).getEncoded();
        if (enc == null)
          return false;
        return Arrays.equals(encoded, enc);
      }
    catch (CertificateEncodingException cee)
      {
        return false;
      }
  }

  // Own methods.
  // ------------------------------------------------------------------------

  /**
   * Verify this certificate's signature.
   */
  private void doVerify(Signature sig, PublicKey key)
    throws CertificateException, InvalidKeyException, SignatureException
  {
    logger.log (Component.X509, "verifying sig={0} key={1}",
                new Object[] { sig, key });
    sig.initVerify(key);
    sig.update(tbsCertBytes);
    if (!sig.verify(signature))
      {
        throw new CertificateException("signature not validated");
      }
  }

  /**
   * Parse a DER stream into an X.509 certificate.
   *
   * @param encoded The encoded bytes.
   */
  private void parse(InputStream encoded) throws Exception
  {
    DERReader der = new DERReader(encoded);

    // Certificate ::= SEQUENCE {
    DERValue cert = der.read();
    logger.log (Component.X509, "start Certificate  len == {0}",
                Integer.valueOf(cert.getLength()));

    this.encoded = cert.getEncoded();
    if (!cert.isConstructed())
      {
        throw new IOException("malformed Certificate");
      }

    // TBSCertificate ::= SEQUENCE {
    DERValue tbsCert = der.read();
    if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
      {
        throw new IOException("malformed TBSCertificate");
      }
    tbsCertBytes = tbsCert.getEncoded();
    logger.log (Component.X509, "start TBSCertificate  len == {0}",
                Integer.valueOf(tbsCert.getLength()));

    // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
    DERValue val = der.read();
    if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
      {
        version = ((BigInteger) der.read().getValue()).intValue() + 1;
        val = der.read();
      }
    else
      {
        version = 1;
      }
    logger.log (Component.X509, "read version == {0}",
                Integer.valueOf(version));

    // SerialNumber ::= INTEGER
    serialNo = (BigInteger) val.getValue();
    logger.log (Component.X509, "read serial number == {0}", serialNo);

    // AlgorithmIdentifier ::= SEQUENCE {
    val = der.read();
    if (!val.isConstructed())
      {
        throw new IOException("malformed AlgorithmIdentifier");
      }
    int certAlgLen = val.getLength();
    logger.log (Component.X509, "start AlgorithmIdentifier  len == {0}",
                Integer.valueOf(certAlgLen));
    val = der.read();

    //   algorithm    OBJECT IDENTIFIER,
    algId = (OID) val.getValue();
    logger.log (Component.X509, "read algorithm ID == {0}", algId);

    //   parameters   ANY DEFINED BY algorithm OPTIONAL }
    if (certAlgLen > val.getEncodedLength())
      {
        val = der.read();
        if (val == null)
          {
            algVal = null;
          }
        else
          {
            algVal = val.getEncoded();

            if (val.isConstructed())
              encoded.skip(val.getLength());
          }
        logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
      }

    // issuer   Name,
    val = der.read();
    issuer = new X500DistinguishedName(val.getEncoded());
    der.skip(val.getLength());
    logger.log (Component.X509, "read issuer == {0}", issuer);

    // Validity ::= SEQUENCE {
    //   notBefore   Time,
    //   notAfter    Time }
    if (!der.read().isConstructed())
      {
        throw new IOException("malformed Validity");
      }
    notBefore = (Date) der.read().getValue();
    logger.log (Component.X509, "read notBefore == {0}", notBefore);
    notAfter  = (Date) der.read().getValue();
    logger.log (Component.X509, "read notAfter == {0}", notAfter);

    // subject   Name,
    val = der.read();
    subject = new X500DistinguishedName(val.getEncoded());
    der.skip(val.getLength());
    logger.log (Component.X509, "read subject == {0}", subject);

    // SubjectPublicKeyInfo ::= SEQUENCE {
    //   algorithm         AlgorithmIdentifier,
    //   subjectPublicKey  BIT STRING }
    DERValue spki = der.read();
    if (!spki.isConstructed())
      {
        throw new IOException("malformed SubjectPublicKeyInfo");
      }
    KeyFactory spkFac = KeyFactory.getInstance("X.509");
    subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
    der.skip(spki.getLength());
    logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);

    val = der.read();
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
      {
        byte[] b = (byte[]) val.getValue();
        issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
        logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
        val = der.read();
      }
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
      {
        byte[] b = (byte[]) val.getValue();
        subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
        logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
        val = der.read();
      }
    if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
      {
        val = der.read();
        logger.log (Component.X509, "start Extensions  len == {0}",
                    Integer.valueOf(val.getLength()));
        int len = 0;
        while (len < val.getLength())
          {
            DERValue ext = der.read();
            logger.log (Component.X509, "start extension  len == {0}",
                        Integer.valueOf(ext.getLength()));
            Extension e = new Extension(ext.getEncoded());
            extensions.put(e.getOid(), e);
            der.skip(ext.getLength());
            len += ext.getEncodedLength();
            logger.log (Component.X509, "read extension {0} == {1}",
                        new Object[] { e.getOid (), e });
            logger.log (Component.X509, "count == {0}", Integer.valueOf(len));
          }

        val = der.read ();
      }

    logger.log (Component.X509, "read value {0}", val);
    if (!val.isConstructed())
      {
        throw new CertificateException ("malformed AlgorithmIdentifier");
      }
    int sigAlgLen = val.getLength();
    logger.log (Component.X509, "start AlgorithmIdentifier  len == {0}",
                Integer.valueOf(sigAlgLen));
    val = der.read();
    sigAlgId = (OID) val.getValue();
    logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
    if (sigAlgLen > val.getEncodedLength())
      {
        val = der.read();
        if (val.getValue() == null)
          {
            if (subjectKey instanceof DSAPublicKey)
              {
                AlgorithmParameters params =
                  AlgorithmParameters.getInstance("DSA");
                DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
                DSAParameterSpec spec =
                  new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
                params.init(spec);
                sigAlgVal = params.getEncoded();
              }
          }
        else
          {
            sigAlgVal = (byte[]) val.getEncoded();
          }
        if (val.isConstructed())
          {
            encoded.skip(val.getLength());
          }
        logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
      }
    signature = ((BitString) der.read().getValue()).toByteArray();
    logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));
  }
}
