/* SFHelper -- A .SF file helper
   Copyright (C) 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.classpath.tools.jarsigner;

import gnu.classpath.Configuration;
import gnu.java.security.OID;
import gnu.java.security.Registry;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import gnu.java.security.pkcs.PKCS7Data;
import gnu.java.security.pkcs.PKCS7SignedData;
import gnu.java.security.pkcs.SignerInfo;
import gnu.java.security.sig.ISignature;
import gnu.java.security.sig.ISignatureCodec;
import gnu.java.security.sig.dss.DSSSignature;
import gnu.java.security.sig.dss.DSSSignatureX509Codec;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
import gnu.java.security.util.Util;
import gnu.java.util.jar.JarUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509CRL;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Logger;

import javax.security.auth.x500.X500Principal;
import java.security.cert.X509Certificate;

/**
 * A helper class for the .SF file found in signed jars.
 */
public class SFHelper
{
  // Constants and fields
  // --------------------------------------------------------------------------

  private static final Logger log = Logger.getLogger(SFHelper.class.getName());
  private static final int READY = 0;
  private static final int STARTED = 1;
  private static final int FINISHED = 2;
  private static final int SF_GENERATED = 3;
  private static final int DSA_GENERATED = 4;
  /** http://asn1.elibel.tm.fr/cgi-bin/oid/display?oid=1.3.14.3.2.26&action=display */
  private static final OID hashAlgorithmIdentifierSHA1 = new OID("1.3.14.3.2.26"); //$NON-NLS-1$

  private int state;
  private JarFile jar;
  private Manifest manifest;
  private Attributes sfMainAttributes;
  private Map sfEntries;
  private byte[] sfBytes;
  private HashUtils util;

  // Constructor(s)
  // --------------------------------------------------------------------------

  /**
   * @param jar the JAR archive the .SF file belongs to.
   */
  public SFHelper(JarFile jar)
  {
    super();

    this.jar = jar;
    this.state = READY;
  }

  // Class methods
  // --------------------------------------------------------------------------

  // Instance methods
  // --------------------------------------------------------------------------

  /**
   * Writes the contents of the <code>.SF</code> file to the designated JAR
   * output stream. Line-endings are platform-independent and consist of the
   * 2-codepoint sequence <code>0x0D</code> and <code>0x0A</code>.
   * 
   * @param jar the JAR output stream to write a <code>.SF</code> file to.
   * @throws IOException if an I/O related exception occurs during the process.
   */
  void writeSF(JarOutputStream jar) throws IOException
  {
    if (this.state != FINISHED)
      throw new IllegalStateException(Messages.getString("SFHelper.1")); //$NON-NLS-1$

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    JarUtils.writeSFManifest(sfMainAttributes, sfEntries, baos);
    sfBytes = baos.toByteArray();
    if (Configuration.DEBUG)
      log.fine("\n" + Util.dumpString(sfBytes, "+++ sfBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
    jar.write(sfBytes);
    jar.flush();

    this.state = SF_GENERATED;
  }

  /**
   * The contents of the .DSA file is the DER encoded form of a PKCS#7
   * ContentInfo of the type SignedData.
   * <p>
   * The ContentInfo ASN.1 syntax is as described in the "PKCS#7 Cryptographic
   * Message Syntax Standard" (RSA Labs) specifications:
   * <pre>
   * ContentInfo ::= SEQUENCE {
   *   contentType     ContentType,
   *   content     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
   * }
   * 
   * ContentType ::= OBJECT IDENTIFIER
   * </pre>
   * <p>
   * The ContentType is an OID which determines the type of the contents field
   * that follows it. For the .DSA file the OID is "1.2.840.113549.1.7.2", while
   * the content field is the byte array representing the DER encoded form of a
   * SignedData content-type. The ASN.1 syntax of the SignedData type is as
   * follows:
   * <pre>
   * SignedData ::= SEQUENCE {
   *   version          Version, -- always 1 for PKCS#7 1.5
   *   digestAlgorithms DigestAlgorithmIdentifiers,
   *   contentInfo      ContentInfo,
   *   certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
   *   crls         [1] IMPLICIT CertificateRevocationLists OPTIONAL,
   *   signerInfos      SignerInfos
   * }
   * 
   * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
   * 
   * SignerInfos ::= SET OF SignerInfo
   * </pre>
   * <p>
   * Finally the SignerInfo is a per-signer structure. Its ASN.1 syntax looks
   * like so:
   * <pre>
   * SignerInfo ::= SEQUENCE {
   *   version                       Version, -- always 1 for PKCS#7 1.5
   *   issuerAndSerialNumber         IssuerAndSerialNumber,
   *   digestAlgorithm               DigestAlgorithmIdentifier,
   *   authenticatedAttributes   [0] IMPLICIT Attributes OPTIONAL,
   *   digestEncryptionAlgorithm     DigestEncryptionAlgorithmIdentifier,
   *   encryptedDigest               EncryptedDigest,
   *   unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
   * }
   * 
   * EncryptedDigest ::= OCTET STRING
   * </pre>
   * 
   * @param jar the JAR output stream to write a <code>.DSA</code> file to.
   * @param signerKey the private key to sign with.
   * @param certificates the possibly null signer certificate chain.
   * @param internalSF if <code>true</code> then include the .SF file contents
   * in the signed .DSA file; otherwise don't. 
   * @throws IOException if an I/O related exception occurs during the process.
   * @throws CRLException 
   * @throws CertificateEncodingException 
   */
  void writeDSA(JarOutputStream jar, PrivateKey signerKey,
                Certificate[] certificates, boolean internalSF)
      throws IOException, CertificateEncodingException, CRLException
  {
    if (this.state != SF_GENERATED)
      throw new IllegalStateException(Messages.getString("SFHelper.4")); //$NON-NLS-1$

    if (Configuration.DEBUG)
      log.fine("+++ signer private key = " + signerKey); //$NON-NLS-1$
    ISignature signatureAlgorithm;
    ISignatureCodec signatureCodec;
    OID digestEncryptionAlgorithmOID;
    if (signerKey instanceof DSAPrivateKey)
      {
        signatureAlgorithm = new DSSSignature();
        signatureCodec = new DSSSignatureX509Codec();
        digestEncryptionAlgorithmOID = Main.DSA_SIGNATURE_OID;
      }
    else if (signerKey instanceof RSAPrivateKey)
      {
        signatureAlgorithm = new RSAPKCS1V1_5Signature(Registry.MD5_HASH);
        signatureCodec = new RSAPKCS1V1_5SignatureX509Codec();
        digestEncryptionAlgorithmOID = Main.RSA_SIGNATURE_OID;
      }
    else
      throw new SecurityException(Messages.getString("SFHelper.6")); //$NON-NLS-1$

    Map signatureAttributes = new HashMap();
    signatureAttributes.put(ISignature.SIGNER_KEY, signerKey);
    signatureAlgorithm.setupSign(signatureAttributes);
    signatureAlgorithm.update(sfBytes, 0, sfBytes.length);
    Object signature = signatureAlgorithm.sign();
    byte[] signedSFBytes = signatureCodec.encodeSignature(signature);
    if (Configuration.DEBUG)
      log.fine("\n" + Util.dumpString(signedSFBytes, "+++ signedSFBytes ")); //$NON-NLS-1$ //$NON-NLS-2$

    Set digestAlgorithms = new HashSet();
    List digestAlgorithm = new ArrayList(2);
    DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
                                                  hashAlgorithmIdentifierSHA1);
    DERValue derDigestAlgorithmParams = new DERValue(DER.NULL, null);
    digestAlgorithm.add(derDigestAlgorithmOID);
    digestAlgorithm.add(derDigestAlgorithmParams);
    DERValue derDigestAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
                                               digestAlgorithm);
    digestAlgorithms.add(derDigestAlgorithm);

    // TODO (rsn): test with internalsf == true
    PKCS7Data data = internalSF ? new PKCS7Data(sfBytes) : null;

    X509CRL[] crls = null;

    Set signerInfos = new HashSet();
    X509Certificate cert = (X509Certificate) certificates[0];
    try
      {
        cert.checkValidity();
      }
    catch (CertificateExpiredException x)
      {
        String issuerName = getIssuerName(cert);
        String subjectName = getSubjectName(cert);
        Date notAfterDate = getNotAfterDate(cert);
        System.out.println(Messages.getFormattedString("SFHelper.0", //$NON-NLS-1$
                                                       new Object[] { issuerName,
                                                                      subjectName,
                                                                      notAfterDate }));
      }
    catch (CertificateNotYetValidException x)
      {
        String issuerName = getIssuerName(cert);
        String subjectName = getSubjectName(cert);
        Date notBeforeDate = getNotBeforeDate(cert);
        System.out.println(Messages.getFormattedString("SFHelper.11", //$NON-NLS-1$
                                                       new Object[] { issuerName,
                                                                      subjectName,
                                                                      notBeforeDate }));
      }
    X500Principal issuer = cert.getIssuerX500Principal();
    BigInteger serialNumber = cert.getSerialNumber();
    byte[] authenticatedAttributes = null;
    byte[] encryptedDigest = signedSFBytes;
    byte[] unauthenticatedAttributes = null;
    SignerInfo signerInfo = new SignerInfo(issuer,
                                           serialNumber,
                                           hashAlgorithmIdentifierSHA1,
                                           authenticatedAttributes,
                                           digestEncryptionAlgorithmOID,
                                           encryptedDigest,
                                           unauthenticatedAttributes);
    signerInfos.add(signerInfo);

    PKCS7SignedData dsaContents = new PKCS7SignedData(digestAlgorithms,
                                                      data,
                                                      certificates,
                                                      crls,
                                                      signerInfos);
    dsaContents.encode(jar);

    jar.flush();
    this.state = DSA_GENERATED;
  }

  Manifest getManifest()
  {
    return this.manifest;
  }

  // own methods --------------------------------------------------------------

  void startSigning() throws IOException
  {
    if (this.state != READY)
      throw new IllegalStateException(Messages.getString("SFHelper.9")); //$NON-NLS-1$

    Manifest oldManifest = jar.getManifest();
    this.manifest = oldManifest == null ? new Manifest()
                                        : new Manifest(oldManifest);
    this.sfMainAttributes = new Attributes();
    this.sfEntries = new HashMap();
    util = new HashUtils();

    this.state = STARTED;
  }

  /**
   * Hashes the designated JAR entry (the file itself); adds the resulting hash
   * as an attribute to the manifest, and computes the hash of the added (to
   * the Manifest) two headers and add the result as an attribute of the
   * corresponding entry in the .SF file.
   */
  void updateEntry(JarEntry entry) throws IOException
  {
    if (this.state != STARTED)
      throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$
      
    String name = entry.getName();
    InputStream jeis = jar.getInputStream(entry);
    String hash = util.hashStream(jeis);
    if (Configuration.DEBUG)
      log.fine("Hash of " + name + " = " + hash); //$NON-NLS-1$ //$NON-NLS-2$

    Attributes mainfestAttributes = manifest.getAttributes(name);
    if (mainfestAttributes == null)
      {
        mainfestAttributes = new Attributes();
        manifest.getEntries().put(name, mainfestAttributes);
      }

    mainfestAttributes.putValue(Main.DIGEST, hash);

    // hash the newly added 2-header block and add it as an attribute to .SF

    String sfHash = util.hashManifestEntry(name, hash);
    Attributes sfAttributes = (Attributes) sfEntries.get(name);
    if (sfAttributes == null)
      {
        sfAttributes = new Attributes();
        sfEntries.put(name, sfAttributes);
      }

    sfAttributes.putValue(Main.DIGEST, sfHash);
    if (Configuration.DEBUG)
      {
        log.fine("Name: " + name); //$NON-NLS-1$
        log.fine(Main.DIGEST + ": " + sfHash); //$NON-NLS-1$
        log.fine(""); //$NON-NLS-1$
      }
  }

  /**
   * @param sectionsOnly whether to compute, in addition to the files, the hash
   * of the mainfest itself (<code>false</code>) or not (<code>true</code>).
   */
  void finishSigning(boolean sectionsOnly) throws IOException
  {
    if (state != STARTED)
      throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$

    if (sectionsOnly)
      return;

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    manifest.write(baos);
    baos.flush();
    String manifestHash = util.hashByteArray(baos.toByteArray());
    if (Configuration.DEBUG)
      log.fine("Hashed Manifest " + manifestHash); //$NON-NLS-1$
    sfMainAttributes.putValue(Main.DIGEST_MANIFEST, manifestHash);

    this.state = FINISHED;
  }

  /**
   * Given an X.509 certificate this method returns the string representation of
   * the Issuer Distinguished Name.
   * 
   * @param cert an X.509 certificate.
   * @return the string representation of the Issuer's DN.
   */
  private String getIssuerName(X509Certificate cert)
  {
    X500Principal xp = cert.getIssuerX500Principal();
    if (xp == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has null Issuer. Return [unknown]"); //$NON-NLS-1$
        return Messages.getString("SFHelper.14"); //$NON-NLS-1$
      }
    String result = xp.getName();
    if (result == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has an Issuer with null DN. Return [unnamed]"); //$NON-NLS-1$
        return Messages.getString("SFHelper.17"); //$NON-NLS-1$
      }
    return result;
  }

  /**
   * Given an X.509 certificate this method returns the string representation of
   * the Subject Distinguished Name.
   * 
   * @param cert an X.509 certificate.
   * @return the string representation of the Subject's DN.
   */
  private String getSubjectName(X509Certificate cert)
  {
    X500Principal xp = cert.getSubjectX500Principal();
    if (xp == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has null Subject. Return [unknown]"); //$NON-NLS-1$
        return Messages.getString("SFHelper.14"); //$NON-NLS-1$
      }
    String result = xp.getName();
    if (result == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has a Subject with null DN. Return [unnamed]"); //$NON-NLS-1$
        return Messages.getString("SFHelper.17"); //$NON-NLS-1$
      }
    return result;
  }

  /**
   * Given an X.509 certificate this method returns the end validity date of 
   * this certificate.
   * 
   * @param cert an X.509 certificate.
   * @return the date when this certificate stops being valid.
   */
  private Date getNotAfterDate(X509Certificate cert)
  {
    Date result = cert.getNotAfter();
    if (result == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has null start-validity date. Return epoch"); //$NON-NLS-1$
        return new Date(0);
      }
    return result;
  }

  /**
   * Given an X.509 certificate this method returns the start validity date of
   * this certificate.
   * 
   * @param cert an X.509 certificate.
   * @return the date when this certificate starts being valid.
   */
  private Date getNotBeforeDate(X509Certificate cert)
  {
    Date result = cert.getNotBefore();
    if (result == null)
      {
        if (Configuration.DEBUG)
          log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
                   + ", has null end-validity date. Return epoch"); //$NON-NLS-1$
        return new Date(0);
      }
    return result;
  }
}
