// Copyright (C) 1997-2002 IAIK
// email: jce-info@iaik.tu-graz.ac.at
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// $Header$
//
// $Header$
//

package testgenerator;

import iaik.utils.Util;
import iaik.x509.X509Certificate;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;

public class CMSKeyStore implements CMSKeyStoreConstants {

  static Object[][] certificates = new Object[3][7];
  static PrivateKey[][] keys = new PrivateKey[3][7];
  static X509Certificate[] ca_certificates = new X509Certificate[2];
  static PrivateKey[] ca_keys = new PrivateKey[2];

  public final static int RSA = 0;
  public final static int DSA = 1;
  public final static int ESDH = 2;

  public final static int SZ_512_SIGN = 0;
  public final static int SZ_1024_SIGN = 1;
  public final static int SZ_2048_SIGN = 2;
  public final static int SZ_512_CRYPT = 3;
  public final static int SZ_1024_CRYPT = 4;
  public final static int SZ_1024_CRYPT_ = 5;
  public final static int SZ_2048_CRYPT = 6;

  static KeyStore key_store;
  
  static {
    System.out.println("initializing KeyStore...");
    loadKeyStore();
    initKeyStore();
  }
  
  private static void loadKeyStore() {
    // try to locate the KeyStore
    // first check the current working directory
    System.out.println("User.dir:"+System.getProperty("user.dir"));
    File ks = new File(System.getProperty("user.dir"), KS_FILENAME);
    if (!ks.exists()) {
      System.out.println("Can not find the KeyStore in directory:");
      System.out.println(ks.getAbsolutePath());
      System.exit(1);
    }

    // now try to create and load the KeyStore
    try {
      key_store = KeyStore.getInstance("IAIKKeyStore");
      key_store.load(new FileInputStream(ks), KS_PASSWORD);
    } catch (Exception ex) {
      System.out.println("Unable to load KeyStore!");
      ex.printStackTrace();
      System.exit(1);
    }
  }

  private static void initKeyStore() {

    try {
      ca_certificates[RSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_RSA))[0];
      ca_keys[RSA] = (PrivateKey)key_store.getKey(CA_RSA, KS_PASSWORD);
      
      // RSA for signing
      certificates[RSA][SZ_512_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_512_SIGN));
      keys[RSA][SZ_512_SIGN] = (PrivateKey)key_store.getKey(RSA_512_SIGN, KS_PASSWORD);
      certificates[RSA][SZ_1024_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_1024_SIGN));
      keys[RSA][SZ_1024_SIGN] = (PrivateKey)key_store.getKey(RSA_1024_SIGN, KS_PASSWORD);
      certificates[RSA][SZ_2048_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN));
      keys[RSA][SZ_2048_SIGN] = (PrivateKey)key_store.getKey(RSA_2048_SIGN, KS_PASSWORD);
      // RSA for encrypting
      certificates[RSA][SZ_512_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_512_CRYPT));
      keys[RSA][SZ_512_CRYPT] = (PrivateKey)key_store.getKey(RSA_512_CRYPT, KS_PASSWORD);
      certificates[RSA][SZ_1024_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_1024_CRYPT));
      keys[RSA][SZ_1024_CRYPT] = (PrivateKey)key_store.getKey(RSA_1024_CRYPT, KS_PASSWORD);
      certificates[RSA][SZ_1024_CRYPT_] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_1024_CRYPT_));
      keys[RSA][SZ_1024_CRYPT_] = (PrivateKey)key_store.getKey(RSA_1024_CRYPT_, KS_PASSWORD);
      certificates[RSA][SZ_2048_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT));
      keys[RSA][SZ_2048_CRYPT] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT, KS_PASSWORD);
    } catch (Exception ex) {
      System.out.println("Unable to get RSA certificates from KeyStore.");
      ex.printStackTrace();
    }

    try {
      ca_certificates[DSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_DSA))[0];
      ca_keys[DSA] = (PrivateKey)key_store.getKey(CA_DSA, KS_PASSWORD);

      certificates[DSA][SZ_512_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_512));
      keys[DSA][SZ_512_SIGN] = (PrivateKey)key_store.getKey(DSA_512, KS_PASSWORD);
      certificates[DSA][SZ_1024_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_1024));
      keys[DSA][SZ_1024_SIGN] = (PrivateKey)key_store.getKey(DSA_1024, KS_PASSWORD);
      
    } catch (Exception ex) {
      System.out.println("Unable to get DSA certificate from KeyStore.");
      ex.printStackTrace();
    }

    /*try {
      certificates[ESDH][SZ_512_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_512));
      keys[ESDH][SZ_512_CRYPT] = (PrivateKey)key_store.getKey(ESDH_512, KS_PASSWORD);
      certificates[ESDH][SZ_1024_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_1024));
      keys[ESDH][SZ_1024_CRYPT] = (PrivateKey)key_store.getKey(ESDH_1024, KS_PASSWORD);
      certificates[ESDH][SZ_1024_CRYPT_] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_1024_));
      keys[ESDH][SZ_1024_CRYPT_] = (PrivateKey)key_store.getKey(ESDH_1024_, KS_PASSWORD);
      certificates[ESDH][SZ_2048_CRYPT] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_2048));
      keys[ESDH][SZ_2048_CRYPT] = (PrivateKey)key_store.getKey(ESDH_2048, KS_PASSWORD);
    } catch (Exception ex) {
      System.out.println("Unable to get Diffie-Hellman certificate from KeyStore.");
      ex.printStackTrace();
    }*/
  }
  
  /**
   * Returns the private key of a CA certificate.
   *
   * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH}
   */
  public static PrivateKey getPrivateKey(int type, int size) {
    try {
      return keys[type][size];
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new RuntimeException("Wrong type or size!");
    }
  }

  /**
   * Returns a demo user certificate.
   *
   * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH}
   */
  public static X509Certificate[] getCertificateChain(int type, int size) {
    try {
      return (X509Certificate[])certificates[type][size];
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new RuntimeException("Wrong type or size!");
    }
  }
  
  /**
   * Returns the private key of a CA certificate.
   *
   * @param type {@link #RSA RSA} or {@link #DSA DSA}
   */
  public static PrivateKey getCaPrivateKey(int type) {
    try {
      return ca_keys[type];
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new RuntimeException("Wrong type or size!");
    }
  }

  /**
   * Returns a demo CA certificate.
   *
   * @param type {@link #RSA RSA} or {@link #DSA DSA}
   */
  public static X509Certificate getCaCertificate(int type) {
    try {
      return ca_certificates[type];
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new RuntimeException("Wrong type or size!");
    }
  }
}