/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
var pkcs12Test = {

  /**
   * Opens a PKCS12 that was generated using Java and checks that its content
   * can be retrieved.
   *
   *
   * @param {String}
   *            pkcs12B64 the PKCS12, in Base64 encoded format.
   * @param {String}
   *            privateKeyEntryPasswordB64 the password to access a private
   *            key entry in the PKCS12, in Base64 encoded format.
   * @param {String}
   *            rootPrivateKeyAlias the storage alias of the root private key.
   * @param {String}
   *            rootPrivateKeyPem the expected root private key, in PEM
   *            format.
   * @param {String}
   *            rootCertificatePem the expected root certificate, in PEM
   *            format.
   * @param {String}
   *            intermediatePrivateKeyAlias the storage alias of the
   *            intermediate private key.
   * @param {String}
   *            intermediatePrivateKeyPem the expected intermediate private
   *            key, in PEM format.
   * @param {String}
   *            intermediateCertificatePem the expected intermediate
   *            certificate, in PEM format.
   * @param {String}
   *            leafPrivateKeyAlias the storage alias of the leaf private key.
   * @param {String}
   *            leafPrivateKeyPem the expected leaf private key, in PEM
   *            format.
   * @param {String}
   *            leafCertificatePem the expected leaf certificate, in PEM
   *            format.
   * @throws {Error}
   *             if the PKCS12 opening operation fails or the PKCS12's content
   *             cannot be retrieved.
   */
  open: function(
      pkcs12B64, privateKeyEntryPasswordB64, rootPrivateKeyAlias,
      rootPrivateKeyPem, rootCertificatePem, intermediatePrivateKeyAlias,
      intermediatePrivateKeyPem, intermediateCertificatePem,
      leafPrivateKeyAlias, leafPrivateKeyPem, leafCertificatePem) {

    'use strict';

    var errorData = {};
    errorData['PKCS12 (Base64 encoded) [Java]'] = pkcs12B64;
    errorData['Private key entry password (Base64 encoded) [Java]'] =
        privateKeyEntryPasswordB64;
    errorData['Root private key alias [Java]'] = rootPrivateKeyAlias;
    errorData['Root private key (PEM format) [Java]'] = rootPrivateKeyPem;
    errorData['Root certificate (PEM format) [Java]'] = rootCertificatePem;
    errorData['Intermediate private key alias [Java]'] =
        intermediatePrivateKeyAlias;
    errorData['Intermediate private key (PEM format) [Java]'] =
        intermediatePrivateKeyPem;
    errorData['Intermediate certificate (PEM format) [Java]'] =
        intermediateCertificatePem;
    errorData['Leaf private key alias [Java]'] = leafPrivateKeyAlias;
    errorData['Leaf private key (PEM format) [Java]'] = leafPrivateKeyPem;
    errorData['Leaf certificate (PEM format) [Java]'] = leafCertificatePem;

    try {
      cryptolib('stores.pkcs12', 'certificates.service', function(box) {
        var pkcs12 = new box.stores.pkcs12.Pkcs12(pkcs12B64);

        // Retrieve private keys from PKCS12.
        var privateKeyChain =
            pkcs12.getPrivateKeyChain(privateKeyEntryPasswordB64);
        var rootPrivateKeyPemFound = privateKeyChain.get(rootPrivateKeyAlias);
        errorData['Root private key from PKCS12 [JS]'] = rootPrivateKeyPemFound;
        var intermediatePrivateKeyPemFound =
            privateKeyChain.get(intermediatePrivateKeyAlias);
        errorData['Intermediate private key from PKCS12 [JS]'] =
            intermediatePrivateKeyPemFound;
        var leafPrivateKeyPemFound = privateKeyChain.get(leafPrivateKeyAlias);
        errorData['Leaf private key from PKCS12 [JS]'] = leafPrivateKeyPemFound;

        // Retrieve certificate chains from PKCS12.
        var rootCertificateChain = pkcs12.getCertificateChainByAlias(
            privateKeyEntryPasswordB64, rootPrivateKeyAlias);
        errorData['Root certificate chain from PKCS12 [JS]'] =
            rootCertificateChain;
        var intermediateCertificateChain = pkcs12.getCertificateChainByAlias(
            privateKeyEntryPasswordB64, intermediatePrivateKeyAlias);
        errorData['Intermediate certificate chain from PKCS12 [JS]'] =
            intermediateCertificateChain;
        var leafCertificateChain = pkcs12.getCertificateChainByAlias(
            privateKeyEntryPasswordB64, leafPrivateKeyAlias);
        errorData['Leaf certificate chain from PKCS12 [JS]'] =
            leafCertificateChain;

        // Check if private keys were successfully retrieved from PKCS12.
        testUtils.checkPrivateKey(rootPrivateKeyPemFound, rootPrivateKeyPem);
        testUtils.checkPrivateKey(
            intermediatePrivateKeyPemFound, intermediatePrivateKeyPem);
        testUtils.checkPrivateKey(leafPrivateKeyPemFound, leafPrivateKeyPem);

        // Check if certificate chains were successfully retrieved from PKCS12.
        testUtils.checkCertificate(rootCertificateChain[0], rootCertificatePem);
        testUtils.checkCertificate(
            intermediateCertificateChain[0], intermediateCertificatePem);
        testUtils.checkCertificate(
            intermediateCertificateChain[1], rootCertificatePem);
        testUtils.checkCertificate(leafCertificateChain[0], leafCertificatePem);
        testUtils.checkCertificate(
            leafCertificateChain[1], intermediateCertificatePem);
        testUtils.checkCertificate(leafCertificateChain[2], rootCertificatePem);

        // Check if certificates retrieved from PKCS12 can be verified.
        var rootCertificatePemFound = leafCertificateChain[2];
        var intermediateCertificatePemFound = leafCertificateChain[1];
        var leafCertificatePemFound = leafCertificateChain[0];
        var rootCertificateFound =
            new box.certificates.service.load(rootCertificatePemFound);
        var intermediateCertificateFound =
            new box.certificates.service.load(intermediateCertificatePemFound);
        if (!rootCertificateFound.verify(rootCertificatePemFound)) {
          throw 'Root certificate signature could not be verified.';
        }
        if (!rootCertificateFound.verify(intermediateCertificatePemFound)) {
          throw 'Intermediate certificate signature could not be verified.';
        }
        if (!intermediateCertificateFound.verify(leafCertificatePemFound)) {
          throw 'Leaf certificate signature could not be verified.';
        }
      });
    } catch (error) {
      throw testUtils.serializeError(error, errorData);
    }
  }
};