예제 #1
0
  /**
   * Obtiene un almacén de claves ya inicializado. Se encarga también de añadir
   * o retirar los <i>Provider</i> necesarios para operar con dicho almac&eacute;n
   *
   * @param type Tipo del almac&eacute;n de claves
   * @param store Flujo para la lectura directa del almac&eacute;n de claves (solo para los
   *     almacenes en disco)
   * @param pssCallBack CallBack encargado de recuperar la contrasenya del Keystore
   * @param params Par&aacute;metros adicionales (dependen del tipo de almac&eacute;n)
   * @return Almac&eacute;n de claves solicitado (<b>ya inicializado</b>, pueden ser varios en el
   *     caso de Mozilla, el interno y los externos)
   * @throws AOKeyStoreManagerException Cuando ocurre cualquier problema durante la
   *     inicializaci&oacute;n
   * @throws IOException Se ha insertado una contrase&ntilde;a incorrecta para la apertura del
   *     almac&eacute;n de certificados.
   * @throws es.gob.afirma.core.MissingLibraryException Cuando faltan bibliotecas necesarias para la
   *     inicializaci&oacute;n
   * @throws es.gob.afirma.core.InvalidOSException Cuando se pide un almac&eacute;n disponible solo
   *     en un sistema operativo distinto al actual
   */
  public List<KeyStore> init(
      final AOKeyStore type,
      final InputStream store,
      final PasswordCallback pssCallBack,
      final Object[] params)
      throws AOKeyStoreManagerException, IOException {
    if (type == null) {
      throw new IllegalArgumentException(
          "Se ha solicitado inicializar un AOKeyStore nulo"); //$NON-NLS-1$
    }
    LOGGER.info("Inicializamos el almacen de tipo: " + type); // $NON-NLS-1$

    this.ksType = type;

    if (this.ksType.equals(AOKeyStore.SINGLE)) {
      return initSingle(store, pssCallBack);
    }

    if (this.ksType.equals(AOKeyStore.DNIEJAVA)) {
      return initDnieJava(pssCallBack, params != null && params.length > 0 ? params[0] : null);
    } else if (this.ksType.equals(AOKeyStore.JAVA)
        || this.ksType.equals(AOKeyStore.JAVACE)
        || this.ksType.equals(AOKeyStore.JCEKS)) {
      return initJava(store, pssCallBack);
    } else if (this.ksType.equals(AOKeyStore.WINCA)
        || this.ksType.equals(AOKeyStore.WINADDRESSBOOK)) {
      return initCAPIAddressBook();
    } else if (this.ksType.equals(AOKeyStore.PKCS11)) {
      // En el "params" debemos traer los parametros:
      // [0] - p11lib: Biblioteca PKCS#11, debe estar en el Path (Windows) o en el LD_LIBRARY_PATH
      // (UNIX, Linux, Mac OS X)
      // [1] -desc: Descripcion del token PKCS#11 (opcional)
      // [2] -slot: Numero de lector de tarjeta (Sistema Operativo) [OPCIONAL]
      return initPKCS11(pssCallBack, params);
    } else if (this.ksType.equals(
        AOKeyStore.APPLE)) { // Por ahora no anadimos soporte a llaveros en ficheros sueltos
      return initApple(store);
    } else if (this.ksType.equals(AOKeyStore.DNIE)) {
      return initPKCS11(
          pssCallBack != null
              ? pssCallBack
              : new UIPasswordCallback(KeyStoreMessages.getString("AOKeyStoreManager.0"), null),
          new String[] {
            KeyStoreUtilities.getPKCS11DNIeLib(), "DNIe-Afirma"
          }); //$NON-NLS-1$//$NON-NLS-2$
    }

    throw new UnsupportedOperationException("Tipo de almacen no soportado"); // $NON-NLS-1$
  }
예제 #2
0
  /**
   * Inicializa un almac&eacute;n PKCS#11.
   *
   * @param pssCallBack Callback para la recuperaci&oacute;n de la contrase&ntilde;a del
   *     almac&eacute;n.
   * @param params Parametros adicionales para la configuraci&oacute;n del almac&eacute;n.
   * @return Array con los almacenes configurados.
   * @throws AOKeyStoreManagerException Cuando ocurre un error durante la inicializaci&oacute;n.
   * @throws IOException Cuando se indique una contrase&ntilde;a incorrecta para la apertura del
   *     almac&eacute;n.
   * @throws es.gob.afirma.keystores.main.common.MissingSunPKCS11Exception Si no se encuentra la
   *     biblioteca SunPKCS11
   */
  private List<KeyStore> initPKCS11(final PasswordCallback pssCallBack, final Object[] params)
      throws AOKeyStoreManagerException, IOException {
    // En el "params" debemos traer los parametros:
    // [0] -p11lib: Biblioteca PKCS#11, debe estar en el Path (Windows) o en el LD_LIBRARY_PATH
    // (UNIX, Linux, Mac OS X)
    // [1] -desc: Descripcion del token PKCS#11 (opcional)
    // [2] -slot: Numero de lector de tarjeta (Sistema Operativo) [OPCIONAL]

    // Anadimos el proveedor PKCS11 de Sun
    if (params == null || params.length < 2) {
      throw new IOException(
          "No se puede acceder al KeyStore PKCS#11 si no se especifica la biblioteca"); //$NON-NLS-1$
    }
    final String p11lib;
    if (params[0] != null) {
      p11lib = params[0].toString();
    } else {
      throw new IllegalArgumentException(
          "No se puede acceder al KeyStore PKCS#11 si se especifica una biblioteca nula"); //$NON-NLS-1$
    }

    // Numero de lector
    Integer slot = null;
    if (params.length >= 3 && params[2] instanceof Integer) {
      slot = (Integer) params[2];
    }

    // Agregamos un nombre a cada PKCS#11 para asegurarnos de no se
    // agregan mas de una vez como provider.
    // Si ya se cargo el PKCS#11 anteriormente, se volvera a instanciar.
    final String p11ProviderName = new File(p11lib).getName().replace('.', '_').replace(' ', '_');
    Provider p11Provider = Security.getProvider("SunPKCS11-" + p11ProviderName); // $NON-NLS-1$

    if (p11Provider == null) {

      Constructor<?> sunPKCS11Contructor;
      try {
        sunPKCS11Contructor =
            Class.forName("sun.security.pkcs11.SunPKCS11")
                .getConstructor(InputStream.class); // $NON-NLS-1$
      } catch (final Exception e) {
        throw new MissingSunPKCS11Exception(e);
      }

      final byte[] config =
          KeyStoreUtilities.createPKCS11ConfigFile(p11lib, p11ProviderName, slot).getBytes();
      try {
        p11Provider = (Provider) sunPKCS11Contructor.newInstance(new ByteArrayInputStream(config));
      } catch (final Exception e) {
        // El PKCS#11 del DNIe a veces falla a la primera pero va
        // correctamente a la segunda
        // asi que reintentamos una vez mas
        try {
          p11Provider =
              (Provider) sunPKCS11Contructor.newInstance(new ByteArrayInputStream(config));
        } catch (final Exception ex) {
          throw new AOKeyStoreManagerException(
              "No se ha podido instanciar el proveedor SunPKCS11 para la la biblioteca " + p11lib,
              ex); //$NON-NLS-1$
        }
      }
      Security.addProvider(p11Provider);
    } else {
      LOGGER.info(
          "El proveedor SunPKCS11 solicitado ya estaba instanciado, se reutilizara esa instancia: "
              + p11Provider.getName()); // $NON-NLS-1$
    }

    try {
      this.ks = KeyStore.getInstance(this.ksType.getProviderName(), p11Provider);
    } catch (final Exception e) {
      Security.removeProvider(p11Provider.getName());
      p11Provider = null;
      throw new AOKeyStoreManagerException(
          "No se ha podido obtener el almacen PKCS#11", e); // $NON-NLS-1$
    }

    try {
      this.ks.load(null, pssCallBack != null ? pssCallBack.getPassword() : null);
    } catch (final IOException e) {
      if (e.getCause() instanceof UnrecoverableKeyException
          || e.getCause() instanceof BadPaddingException) {
        throw new IOException("Contrasena invalida: " + e, e); // $NON-NLS-1$
      }
      throw new AOKeyStoreManagerException(
          "No se ha podido obtener el almacen PKCS#11 solicitado", e); // $NON-NLS-1$
    } catch (final CertificateException e) {
      Security.removeProvider(p11Provider.getName());
      p11Provider = null;
      throw new AOKeyStoreManagerException(
          "No se han podido cargar los certificados del almacen PKCS#11 solicitado",
          e); //$NON-NLS-1$
    } catch (final NoSuchAlgorithmException e) {
      Security.removeProvider(p11Provider.getName());
      p11Provider = null;
      throw new AOKeyStoreManagerException(
          "No se ha podido verificar la integridad del almacen PKCS#11 solicitado",
          e); //$NON-NLS-1$
    }
    final List<KeyStore> ret = new ArrayList<KeyStore>(1);
    ret.add(this.ks);
    return ret;
  }