/*
 * Copyright (C) 2009 Google Inc.  All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.polo.ssl;

import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.ASN1Sequence;
import com.android.org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
import com.android.org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import com.android.org.bouncycastle.asn1.x509.GeneralName;
import com.android.org.bouncycastle.asn1.x509.GeneralNames;
import com.android.org.bouncycastle.asn1.x509.KeyPurposeId;
import com.android.org.bouncycastle.asn1.x509.KeyUsage;
import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import com.android.org.bouncycastle.asn1.x509.X509Extensions;
import com.android.org.bouncycastle.asn1.x509.X509Name;
import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
import com.android.org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import com.android.org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;

import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.security.auth.x500.X500Principal;

/**
 * A collection of miscellaneous utility functions for use in Polo.
 */
public class SslUtil {

  /**
   * Generates a new RSA key pair.
   * 
   * @return                           the new object
   * @throws NoSuchAlgorithmException  if the RSA generator could not be loaded
   */
  public static KeyPair generateRsaKeyPair() throws NoSuchAlgorithmException {
    KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
    KeyPair kp = kg.generateKeyPair();
    return kp;
  }
  
  /**
   * Creates a new, empty {@link KeyStore}
   * 
   * @return                           the new KeyStore
   * @throws GeneralSecurityException  on error creating the keystore
   * @throws IOException               on error loading the keystore
   */
  public static KeyStore getEmptyKeyStore()
      throws GeneralSecurityException, IOException {
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, null);
    return ks;
  }
  
  /**
   * Generates a new, self-signed X509 V1 certificate for a KeyPair.
   * 
   * @param  pair                      the {@link KeyPair} to be used
   * @param  name                      X.500 distinguished name
   * @return                           the new certificate
   * @throws GeneralSecurityException  on error generating the certificate
   */
  @SuppressWarnings("deprecation")
  public static X509Certificate generateX509V1Certificate(KeyPair pair,
      String name)
        throws GeneralSecurityException {
    java.security.Security.addProvider(
        new com.android.org.bouncycastle.jce.provider.BouncyCastleProvider());

    Calendar calendar = Calendar.getInstance();
    calendar.set(2009, 0, 1);
    Date startDate = new Date(calendar.getTimeInMillis());
    calendar.set(2029, 0, 1);
    Date expiryDate = new Date(calendar.getTimeInMillis());
    
    BigInteger serialNumber = BigInteger.valueOf(Math.abs(
        System.currentTimeMillis()));
    
    X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
    X500Principal dnName = new X500Principal(name);
    certGen.setSerialNumber(serialNumber);
    certGen.setIssuerDN(dnName);
    certGen.setNotBefore(startDate);
    certGen.setNotAfter(expiryDate);
    certGen.setSubjectDN(dnName);   // note: same as issuer
    certGen.setPublicKey(pair.getPublic());
    certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
    
    // This method is deprecated, but Android Eclair does not provide the 
    // generate() methods.
    X509Certificate cert = certGen.generateX509Certificate(pair.getPrivate(), "BC");
    return cert;
  }
  
  /**
   * Generates a new, self-signed X509 V3 certificate for a KeyPair.
   * 
   * @param  pair                      the {@link KeyPair} to be used
   * @param  name                      X.500 distinguished name
   * @param  notBefore                 not valid before this date
   * @param  notAfter                  not valid after this date
   * @param  serialNumber              serial number
   * @return                           the new certificate
   * @throws GeneralSecurityException  on error generating the certificate
   */
  @SuppressWarnings("deprecation")
  public static X509Certificate generateX509V3Certificate(KeyPair pair,
      String name, Date notBefore, Date notAfter, BigInteger serialNumber)
        throws GeneralSecurityException {
    java.security.Security.addProvider(
        new com.android.org.bouncycastle.jce.provider.BouncyCastleProvider());

    X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
    X509Name dnName = new X509Name(name);
    
    certGen.setSerialNumber(serialNumber);
    certGen.setIssuerDN(dnName);
    certGen.setSubjectDN(dnName);   // note: same as issuer
    certGen.setNotBefore(notBefore);
    certGen.setNotAfter(notAfter);
    certGen.setPublicKey(pair.getPublic());
    certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
    
    // For self-signed certificates, OpenSSL 0.9.6 has specific requirements
    // about certificate and extension content.  Quoting the `man verify`:
    //
    //   In OpenSSL 0.9.6 and later all certificates whose subject name matches
    //   the issuer name of the current certificate are subject to further
    //   tests. The relevant authority key identifier components of the current
    //   certificate (if present) must match the subject key identifier (if
    //   present) and issuer and serial number of the candidate issuer, in
    //   addition the keyUsage extension of the candidate issuer (if present)
    //   must permit certificate signing.
    //
    // In the code that follows,
    //   - the KeyUsage extension permits cert signing (KeyUsage.keyCertSign);
    //   - the Authority Key Identifier extension is added, matching the
    //     subject key identifier, and using the issuer, and serial number.

    certGen.addExtension(X509Extensions.BasicConstraints, true,
        new BasicConstraints(false));
    
    certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature
        | KeyUsage.keyEncipherment | KeyUsage.keyCertSign));
    certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(
        KeyPurposeId.id_kp_serverAuth));

    AuthorityKeyIdentifier authIdentifier = createAuthorityKeyIdentifier(
        pair.getPublic(), dnName, serialNumber);
    
    certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, true,
        authIdentifier);
    certGen.addExtension(X509Extensions.SubjectKeyIdentifier, true,
        new SubjectKeyIdentifierStructure(pair.getPublic()));

    certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(
        new GeneralName(GeneralName.rfc822Name, "googletv@test.test")));

    // This method is deprecated, but Android Eclair does not provide the 
    // generate() methods.
    X509Certificate cert = certGen.generateX509Certificate(pair.getPrivate(), "BC");
    return cert;
  }
  
  /**
   * Creates an AuthorityKeyIdentifier from a public key, name, and serial
   * number.
   * <p>
   * {@link AuthorityKeyIdentifierStructure} is <i>almost</i> perfect for this,
   * but sadly it does not have a constructor suitable for us:
   * {@link AuthorityKeyIdentifierStructure#AuthorityKeyIdentifierStructure(PublicKey)}
   * does not set the serial number or name (which is important to us), while 
   * {@link AuthorityKeyIdentifierStructure#AuthorityKeyIdentifierStructure(X509Certificate)}
   * sets those fields but needs a completed certificate to do so.
   * <p>
   * This method addresses the gap in available {@link AuthorityKeyIdentifier}
   * constructors provided by BouncyCastle; its implementation is derived from
   * {@link AuthorityKeyIdentifierStructure#AuthorityKeyIdentifierStructure(X509Certificate)}.
   *  
   * @param publicKey  the public key
   * @param name  the name
   * @param serialNumber  the serial number
   * @return  a new {@link AuthorityKeyIdentifier}
   */
  private static AuthorityKeyIdentifier createAuthorityKeyIdentifier(
      PublicKey publicKey, X509Name name, BigInteger serialNumber) {
    GeneralName genName = new GeneralName(name);
    SubjectPublicKeyInfo info;
    try {
      info = new SubjectPublicKeyInfo(
          (ASN1Sequence)new ASN1InputStream(publicKey.getEncoded()).readObject());
    } catch (IOException e) {
      throw new RuntimeException("Error encoding public key");
    }
    return new AuthorityKeyIdentifier(info, new GeneralNames(genName), serialNumber);
  }
  
  /**
   * Wrapper for {@link SslUtil#generateX509V3Certificate(KeyPair, String, Date, Date, BigInteger)}
   * which uses a default validity period and serial number.
   * <p>
   * The validity period is Jan 1 2009 - Jan 1 2099.  The serial number is the
   * current system time.
   */
  public static X509Certificate generateX509V3Certificate(KeyPair pair,
      String name) throws GeneralSecurityException {
    Calendar calendar = Calendar.getInstance();
    calendar.set(2009, 0, 1);
    Date notBefore  = new Date(calendar.getTimeInMillis());
    calendar.set(2099, 0, 1);
    Date notAfter = new Date(calendar.getTimeInMillis());
    
    BigInteger serialNumber = BigInteger.valueOf(Math.abs(
        System.currentTimeMillis()));
    
    return generateX509V3Certificate(pair, name, notBefore, notAfter,
        serialNumber);
  }
  
  /**
   * Wrapper for {@link SslUtil#generateX509V3Certificate(KeyPair, String, Date, Date, BigInteger)}
   * which uses a default validity period.
   * <p>
   * The validity period is Jan 1 2009 - Jan 1 2099.
   */
  public static X509Certificate generateX509V3Certificate(KeyPair pair,
      String name, BigInteger serialNumber) throws GeneralSecurityException {
    Calendar calendar = Calendar.getInstance();
    calendar.set(2009, 0, 1);
    Date notBefore  = new Date(calendar.getTimeInMillis());
    calendar.set(2099, 0, 1);
    Date notAfter = new Date(calendar.getTimeInMillis());
    
    return generateX509V3Certificate(pair, name, notBefore, notAfter,
        serialNumber);
  }
  
  /**
   * Generates a new {@code SSLContext} suitable for a test environment.
   * <p>
   * A new {@link KeyPair}, {@link X509Certificate},
   * {@link DummyTrustManager}, and an empty
   * {@link KeyStore} are created and used to initialize the context.
   * 
   * @return                            the new context
   * @throws  GeneralSecurityException  if an error occurred during
   *                                    initialization
   * @throws  IOException               if an empty KeyStore could not be
   *                                    generated
   */
  public SSLContext generateTestSslContext()
      throws GeneralSecurityException, IOException {
    SSLContext sslcontext = SSLContext.getInstance("SSLv3");
    KeyManager[] keyManagers = SslUtil.generateTestServerKeyManager("SunX509",
        "test");
    sslcontext.init(keyManagers,
        new TrustManager[] { new DummyTrustManager()},
        null);
    return sslcontext;
  }
  
  /**
   * Creates a new pain of {@link KeyManager}s, backed by a keystore file.
   * 
   * @param  keyManagerInstanceName    name of the {@link KeyManagerFactory} to
   *                                   request
   * @param  fileName                  the name of the keystore to load
   * @param  password                  the password for the keystore
   * @return                           the new object
   * @throws GeneralSecurityException  if an error occurred during
   *                                   initialization
   * @throws IOException               if the keystore could not be loaded
   */
  public static KeyManager[] getFileBackedKeyManagers(
      String keyManagerInstanceName, String fileName, String password)
      throws GeneralSecurityException, IOException {
    KeyManagerFactory km = KeyManagerFactory.getInstance(
        keyManagerInstanceName);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(new FileInputStream(fileName), password.toCharArray());
    km.init(ks, password.toCharArray());    
    return km.getKeyManagers();
  }
  
  /**
   * Creates a pair of {@link KeyManager}s suitable for use in testing.
   * <p>
   * A new {@link KeyPair} and {@link X509Certificate} are created and used to
   * initialize the KeyManager.
   * 
   * @param  keyManagerInstanceName    name of the {@link KeyManagerFactory}
   * @param  password                  password to apply to the new key store
   * @return                           the new key managers
   * @throws GeneralSecurityException  if an error occurred during
   *                                   initialization
   * @throws IOException               if the keystore could not be generated
   */
  public static KeyManager[] generateTestServerKeyManager(
      String keyManagerInstanceName, String password)
      throws GeneralSecurityException, IOException {
    KeyManagerFactory km = KeyManagerFactory.getInstance(
        keyManagerInstanceName);
    KeyPair pair = SslUtil.generateRsaKeyPair();
    X509Certificate cert = SslUtil.generateX509V1Certificate(pair,
        "CN=Test Server Cert");
    Certificate[] chain = { cert };
    
    KeyStore ks = SslUtil.getEmptyKeyStore();
    ks.setKeyEntry("test-server", pair.getPrivate(),
        password.toCharArray(), chain);
    km.init(ks, password.toCharArray());
    return km.getKeyManagers();
  }
 
}
