/** * 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én * * @param type Tipo del almacén de claves * @param store Flujo para la lectura directa del almacén de claves (solo para los * almacenes en disco) * @param pssCallBack CallBack encargado de recuperar la contrasenya del Keystore * @param params Parámetros adicionales (dependen del tipo de almacén) * @return Almacé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ón * @throws IOException Se ha insertado una contraseña incorrecta para la apertura del * almacén de certificados. * @throws es.gob.afirma.core.MissingLibraryException Cuando faltan bibliotecas necesarias para la * inicialización * @throws es.gob.afirma.core.InvalidOSException Cuando se pide un almacé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$ }
/** * Inicializa un almacén PKCS#11. * * @param pssCallBack Callback para la recuperación de la contraseña del * almacén. * @param params Parametros adicionales para la configuración del almacén. * @return Array con los almacenes configurados. * @throws AOKeyStoreManagerException Cuando ocurre un error durante la inicialización. * @throws IOException Cuando se indique una contraseña incorrecta para la apertura del * almacé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; }