View Javadoc

1   /**
2    * LICENCIA LGPL:
3    * 
4    * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
5    * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
6    * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
7    * la Licencia, o (a su elección) cualquier versión posterior.
8    * 
9    * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
10   * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
11   * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
12   * License (LGPL) para más detalles
13   * 
14   * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
15   * junto con esta librería; si no es así, escriba a la Free Software Foundation 
16   * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
17   * <http://www.gnu.org/licenses/>.
18   *
19   * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
20   */
21  package es.accv.arangi.base.device.util.pkcs11;
22  
23  import iaik.pkcs.pkcs11.Mechanism;
24  import iaik.pkcs.pkcs11.MechanismInfo;
25  import iaik.pkcs.pkcs11.Module;
26  import iaik.pkcs.pkcs11.Session;
27  import iaik.pkcs.pkcs11.Slot;
28  import iaik.pkcs.pkcs11.Token;
29  import iaik.pkcs.pkcs11.TokenException;
30  import iaik.pkcs.pkcs11.objects.Attribute;
31  import iaik.pkcs.pkcs11.objects.CharArrayAttribute;
32  import iaik.pkcs.pkcs11.objects.Key;
33  import iaik.pkcs.pkcs11.objects.KeyPair;
34  import iaik.pkcs.pkcs11.objects.RSAPrivateKey;
35  import iaik.pkcs.pkcs11.objects.RSAPublicKey;
36  import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate;
37  import iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE;
38  import iaik.pkcs.pkcs11.wrapper.PKCS11;
39  import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
40  import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
41  
42  import java.io.ByteArrayInputStream;
43  import java.security.MessageDigest;
44  import java.security.NoSuchAlgorithmException;
45  import java.security.NoSuchProviderException;
46  import java.security.PrivateKey;
47  import java.security.PublicKey;
48  import java.security.cert.CertificateEncodingException;
49  import java.security.cert.CertificateException;
50  import java.security.cert.CertificateFactory;
51  import java.security.cert.X509Certificate;
52  import java.util.ArrayList;
53  import java.util.Arrays;
54  import java.util.Collection;
55  import java.util.HashSet;
56  import java.util.Hashtable;
57  import java.util.Iterator;
58  import java.util.List;
59  import java.util.Random;
60  
61  import org.apache.log4j.Logger;
62  
63  import es.accv.arangi.base.ArangiObject;
64  import es.accv.arangi.base.certificate.Certificate;
65  import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
66  import es.accv.arangi.base.exception.device.CertificateInvalidException;
67  import es.accv.arangi.base.exception.device.DeletingObjectException;
68  import es.accv.arangi.base.exception.device.DeviceFullException;
69  import es.accv.arangi.base.exception.device.KeyPairException;
70  import es.accv.arangi.base.exception.device.LoadingObjectException;
71  import es.accv.arangi.base.exception.device.SavingObjectException;
72  import es.accv.arangi.base.exception.device.SearchingException;
73  
74  /**
75   * Utilidades varias para las operaciones con PKCS11
76   * 
77   * @author faparicio
78   * 
79   */
80  public class Pkcs11Util {
81  
82  	  /**
83  	   * Loggger de clase
84  	   */
85  	  private static Logger logger = Logger.getLogger(Pkcs11Util.class);
86  	  
87  	  /**
88  	   * Número máximo de certificados que podemos almacenar en la tarjeta.
89  	   */
90  	  public static final int GBL_MAX_CERTIFICATES = 4;
91  	  
92  	  /**
93  	 * Obtiene el ID del token
94  	 * 
95  	 * @param pkcs11Module
96  	 * @return ID del slot donde se encuentra la tarjeta
97  	 * @throws TokenException
98  	 */
99  	public static long getUserTokenId(Module pkcs11Module) throws TokenException {
100 		logger.debug("IN");
101 
102 		long tokenId = -1;
103 
104 		Slot[] slotsWithToken = pkcs11Module
105 				.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
106 		List supportedAvailableTokenList = new ArrayList();
107 
108 		// -- Cargamos los tokens
109 		for (int i = 0; i < slotsWithToken.length; i++) {
110 
111 			Token token = slotsWithToken[i].getToken();
112 
113 			try {
114 				// -- Filtramos por los tokens disponibles para el modulo
115 				// cargado
116 				try {
117 					Thread.sleep(2000);
118 				} catch (InterruptedException e) {
119 					e.printStackTrace();
120 				}
121 				logger.debug("ID: " + token.getTokenID() + " NAME: "
122 						+ token.getTokenInfo().getLabel());
123 
124 				supportedAvailableTokenList.add(token);
125 				logger.debug("Asignado token a la lista de tokens disponibles ["
126 								+ token.getTokenID() + "].");
127 
128 			} catch (PKCS11Exception pkcs11ex) {
129 				logger.info(pkcs11ex.getMessage());
130 			}
131 		}
132 
133 		if (supportedAvailableTokenList != null
134 				&& !supportedAvailableTokenList.isEmpty()) {
135 			tokenId = ((Token) supportedAvailableTokenList.get(0)).getTokenID();
136 		} else {
137 			throw new TokenException("No se ha encontrado ninguna tarjeta soportada por el módulo criptográfico.");
138 		}
139 
140 		logger.debug("El primer token por defecto (" + tokenId + ")");
141 		return tokenId;
142 	}
143 
144 	  
145 	  /**
146 		 * Elimina del PKCS#11 los objetos cuyo LABEL coincida con el proporcionado
147 		 */
148 		public static int deleteObjectsByLabel(Session session, String label) throws DeletingObjectException {
149 			return deleteObjectsByLabel(session, label, true);
150 		}
151 		
152 	/**
153 	 * Elimina del PKCS#11 los objetos cuyo LABEL coincida con el proporcionado
154 	 */
155 	public static int deleteObjectsByLabel(Session session, String label, boolean deleteOrphans) throws DeletingObjectException {
156 		logger.debug("Borrando objetos por etiqueta...");
157 		logger.debug("Label: " + label);
158 		iaik.pkcs.pkcs11.objects.GenericTemplate template = new iaik.pkcs.pkcs11.objects.GenericTemplate();
159 		CharArrayAttribute ckLabel = new CharArrayAttribute(Attribute.LABEL);
160 		ckLabel.setCharArrayValue(label.toCharArray());
161 		template.addAttribute(ckLabel);
162 		int deleted = 0;
163 		try {
164 			List foundObjects = Pkcs11Util.findAllObjects(session, template);
165 			
166 			logger.debug("Buscados ``" + label +"´´. Encontrados: " + foundObjects.size());			
167 			if (!foundObjects.isEmpty()){
168 				Iterator it = foundObjects.iterator();
169 				while (it.hasNext()) {
170 					iaik.pkcs.pkcs11.objects.Object iaikObject = (iaik.pkcs.pkcs11.objects.Object)it.next();
171 					logger.debug("Borrando objeto: " + iaik.pkcs.pkcs11.objects.Object.getObjectClassName(iaikObject.getObjectClass().getLongValue()) + "...");
172 					session.destroyObject(iaikObject);
173 					logger.debug("Borrando objeto: " + iaik.pkcs.pkcs11.objects.Object.getObjectClassName(iaikObject.getObjectClass().getLongValue()) + "...OK");
174 					deleted++;
175 				}
176 			}
177 		} catch (Exception e) {
178 			logger.debug("Borrando objetos por etiqueta...ERROR", e);
179 			throw new DeletingObjectException("Error durante del grupo de objetos de label ``" + label + "´´", e);
180 		}
181 		logger.debug("Eliminados: " + deleted);
182 		
183 		if (deleteOrphans) {
184 	    	//-- Eliminar huerfanos y objetos extraños (GyD)
185 	    	Pkcs11Util.deleteOrphans(session);
186 		}
187 
188 		logger.debug("Borrando objetos por etiqueta...OK");
189 		return deleted;
190 	}
191 	
192 	/**
193 	 * @param session
194 	 * @param template
195 	 * @return Lista de objetos encontrados
196 	 * @throws OperatingException 
197 	 */
198 	  public static List<Object> findAllObjects(Session session, iaik.pkcs.pkcs11.objects.Object template) throws SearchingException {
199 
200 	    List<Object> objects = new ArrayList<Object>();
201 	    try {
202 		    // -- Buscamos todos los objetos que cumplen la plantilla
203 		    // -- o todos si la plantilla es null
204 		    session.findObjectsInit(template);
205 		    Object[] matchingKeys;
206 		    while ((matchingKeys = session.findObjects(1)).length > 0) {
207 		    	Object objTmp = matchingKeys[0];
208 		    	
209 		    	//-- Sólo los objetos correctos (certificados y claves)
210 		    	if (objTmp instanceof iaik.pkcs.pkcs11.objects.PrivateKey ||
211 		    			objTmp instanceof iaik.pkcs.pkcs11.objects.PublicKey ||
212 		    			objTmp instanceof iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate) {
213 		    		
214 		    		objects.add(objTmp);
215 		    		
216 		    	}
217 		    }
218 
219 		    // -- Liberamos busqueda
220 		    session.findObjectsFinal();
221 	    } catch (TokenException e){
222 			throw new SearchingException("Error durante la búsqueda",e);
223 		}
224 	    logger.debug("retorna: Num. obj. en la tarjeta: " + objects.size());
225 	    return objects;
226 	  }
227 
228 	  /**
229 	   * @param session
230 	   * @param label
231 	 * @return Lista de objetos encontrados
232 	 * @throws SearchingException 
233 	   * @throws TokenException
234 	   */
235 	  public static List findPrivateKeysByLabel(Session session, String label) throws SearchingException {
236 
237 	    logger.debug("IN: label: " + label);
238 
239 	    List keyList = new ArrayList();
240 
241 	    // -- Plantilla de busqueda de claves privadas por etiqueta
242 	    Key keyTemplate = new iaik.pkcs.pkcs11.objects.PrivateKey();
243 	    if (label != null) {
244 	      keyTemplate.getLabel().setCharArrayValue(label.toCharArray());
245 	    }
246 
247 	    // -- Buscamos claves privadas
248 	    keyList = findAllObjects(session, keyTemplate);
249 	    logger.debug("retorna: keyList: " + keyList.size());
250 	    return keyList;
251 
252 	  }
253 
254 	  /**
255 	   * Si el numero de intentos es = o mayor que 3 deja de intentar el borrado.
256 	   * 
257 	   * @param session
258 	   * @param obj
259 	   * @param numRetry
260 	   */
261 	  public static void deleteObject(Session session, Object obj, int numRetry) {
262 
263 	    try {
264 
265 	      // -- Intentamos el borrado
266 	      session.destroyObject((iaik.pkcs.pkcs11.objects.Object) obj);
267 
268 	    } catch (PKCS11Exception e) {
269 
270 	      if (numRetry < 3) {
271 	        deleteObject(session, obj, numRetry++);
272 	      }
273 	      else {
274 	        logger.info("Agotado el numero de reintentos.");
275 	      }
276 
277 	    } catch (TokenException e) {
278 	      logger.info("Error en el borrado.", e);
279 	    }
280 
281 	  }
282 	  
283 	  /**
284 	   * 
285 	   * 
286 	   * @throws TokenException
287 	   */
288 	  public static void deleteOrphans(Session session) {
289 
290 		//-- Primera pasada: eliminar las claves públicas que no tengan certificado
291 	    iaik.pkcs.pkcs11.objects.PublicKey publicKeyTemplate = new iaik.pkcs.pkcs11.objects.PublicKey();
292 	    List publicKeys;
293 		try {
294 			publicKeys = Pkcs11Util.findAllObjects(session, publicKeyTemplate);
295 		} catch (SearchingException e) {
296 			logger.debug ("[Pkcs11Util.deleteOrphans]::No se han podido obtener todas las claves públicas");
297 			return;
298 		}
299 
300 	    Hashtable ht;
301 		try {
302 			ht = createKeyCertificateTable(session, publicKeys);
303 		} catch (SearchingException e) {
304 			logger.debug ("[Pkcs11Util.deleteOrphans]::" + e.getMessage());
305 			return;
306 		}
307 
308 	    Iterator itPub = publicKeys.iterator();
309 	    while (itPub.hasNext()) {
310 	      iaik.pkcs.pkcs11.objects.Object pubKey = (iaik.pkcs.pkcs11.objects.Object) itPub.next();
311 	      X509PublicKeyCertificate x509PublicKeyCertificate = (X509PublicKeyCertificate) ht.get(pubKey);
312 
313 	      if (x509PublicKeyCertificate == null) {
314 	        deleteObject(session, pubKey, 0);
315 	      }
316 	    }
317 	    logger.debug("Claves publicas borradas.");
318 
319 
320 		//-- Segunda pasada: eliminar las claves privadas que no tengan certificado
321 	    List keys;
322 		try {
323 			keys = Pkcs11Util.findAllPrivateKeys(session);
324 		} catch (SearchingException e) {
325 			logger.debug ("[Pkcs11Util.deleteOrphans]::No se han podido obtener las claves privadas");
326 			return;
327 		}
328 
329 		try {
330 			ht = createKeyCertificateTable(session, keys);
331 		} catch (SearchingException e) {
332 			logger.debug ("[Pkcs11Util.deleteOrphans]::" + e.getMessage());
333 			return;
334 		}
335 
336 	    Iterator itPriv = keys.iterator();
337 	    while (itPriv.hasNext()) {
338 
339 	      Key privKey = (Key) itPriv.next();
340 	      X509PublicKeyCertificate x509PublicKeyCertificate = (X509PublicKeyCertificate) ht.get(privKey);
341 
342 	      if (x509PublicKeyCertificate == null) {
343 	        deleteObject(session, privKey, 0);
344 	      }
345 
346 	    }
347 	    logger.debug("Claves privadas huerfanas borradas.");
348 
349 		//-- Tercera pasada: en algunos casos (GyD) los elementos borrados quedan como elementos zombie
350 	    //-- Hay que eliminarlos porque si no dan múltiples problemas
351 	    
352 	    List lObjects;
353 		try {
354 			lObjects = findAllObjects(session, new iaik.pkcs.pkcs11.objects.Object ());
355 		} catch (SearchingException e1) {
356 			logger.debug ("[Pkcs11Util.deleteOrphans]::No se han podido obtener todos los objetos");
357 			return;
358 		}
359 	    Iterator itObject = lObjects.iterator();
360 	    while (itObject.hasNext()) {
361 			iaik.pkcs.pkcs11.objects.Object object = (iaik.pkcs.pkcs11.objects.Object) itObject.next();
362 			if (!(object instanceof iaik.pkcs.pkcs11.objects.PrivateKey ||
363 					object instanceof iaik.pkcs.pkcs11.objects.PublicKey ||
364 					object instanceof iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate)) {
365 				try {
366 					session.destroyObject (object);
367 				} catch (TokenException e) {
368 					logger.info ("[Pkcs11Util.deleteOrphans]::No se ha podido eliminar el objeto de tipo '" + object.getClass() + "'.", e);
369 				}
370 				continue;
371 			}
372 
373 		}
374 	  }
375 
376 	/**
377 	   * Busca todas las claves privadas de la tarjeta.
378 	   * 
379 	   * @param session
380 	   * @return
381 	 * @throws SearchingException 
382 	   * @throws TokenException
383 	   */
384 	  private static List findAllPrivateKeys(Session session) throws SearchingException {
385 	
386 	    logger.debug("IN");
387 	
388 	    List privateKeys = findPrivateKeysByLabel(session, null);
389 	
390 	    logger.debug("privateKeys: " + privateKeys.size());
391 	    return privateKeys;
392 	
393 	  }
394 
395 	/**
396 	   * Construye una hastable con clave valor en la que la clave es un elemento de
397 	   * la lista de claves y el valor el certificado asociado.
398 	   * 
399 	   * @param session
400 	   * @param keys
401 	   * @return
402 	 * @throws SearchingException 
403 	 * @throws OperatingException 
404 	   */
405 	  private static Hashtable createKeyCertificateTable(Session session, List keys) throws SearchingException  {
406 	
407 	    logger.debug("IN: " + keys.size());
408 	
409 	    Hashtable ht = new Hashtable();
410 	
411 	    // for each private signature key try to find a public key certificate
412 	    // with the same ID
413 	    Iterator it = keys.iterator();
414 	
415 	    while (it.hasNext()) {
416 	      Key key = (Key) it.next();
417 	      byte[] keyID = key.getId().getByteArrayValue();
418 	
419 	      // this is the implementation that uses a concrete object class
420 	      // (X509PublicKeyCertificate) for searching
421 	      X509PublicKeyCertificate certificateSearchTemplate = new X509PublicKeyCertificate();
422 	      certificateSearchTemplate.getId().setByteArrayValue(keyID);
423 	      try {
424 		      session.findObjectsInit(certificateSearchTemplate);
425 		
426 		      Object[] foundCertificateObjects;
427 		      if ((foundCertificateObjects = session.findObjects(1)).length > 0) {
428 		        ht.put(key, foundCertificateObjects[0]);
429 		      }
430 		
431 		      session.findObjectsFinal();
432 	      } catch (TokenException e){
433 	    	  throw new SearchingException("Error creando HashTable de pares Clave-Certificado", e);
434 	      }
435 	    }
436 	
437 	    logger.debug("retorna: " + ht.size());
438 	    return ht;
439 	
440 	  }
441 
442 	private static PrivateKey getJavaSecurityPrivateKey(RSAPrivateKey exportableRsaPrivateKey) {
443 	//    logger.debug("IN: exportableRsaPrivateKey: " + exportableRsaPrivateKey);
444 	    TokenPrivateKey key = new TokenPrivateKey(exportableRsaPrivateKey); 
445 	    return key;
446 	  }
447 
448 	private static PublicKey getJavaSecurityPublicKey(RSAPublicKey exportableRsaPublicKey) {
449 	    TokenPublicKey key = new TokenPublicKey(exportableRsaPublicKey);
450 	    return key;
451 	  }
452 
453 
454 /**
455    * Generacion de un par de claves.
456    * 
457    * @param session
458    * @param token
459    * @return Par de claves
460  * @throws KeyPairException 
461    */
462   public static KeyPair generateKeyPair(Session session, Token token, int keySize, int numRetry, String label) throws KeyPairException {
463 	  
464 	  logger.debug("IN: " + Arrays.asList(new Object[] { "<session>", "<token>", String.valueOf(keySize), String.valueOf(numRetry), label }));
465 	  MechanismInfo signatureMechanismInfo;
466 	  try {
467 		  // first check out what attributes of the keys we may set
468 		  HashSet supportedMechanisms = new HashSet(Arrays.asList(token.getMechanismList()));
469 		  
470 		  if (supportedMechanisms.contains(Mechanism.RSA_PKCS)) {
471 			  signatureMechanismInfo = token.getMechanismInfo(Mechanism.RSA_PKCS);
472 			  
473 		  } else if (supportedMechanisms.contains(Mechanism.RSA_X_509)) {
474 			  signatureMechanismInfo = token.getMechanismInfo(Mechanism.RSA_X_509);
475 			  
476 		  } else if (supportedMechanisms.contains(Mechanism.RSA_9796)) {
477 			  signatureMechanismInfo = token.getMechanismInfo(Mechanism.RSA_9796);
478 			  
479 		  } else if (supportedMechanisms.contains(Mechanism.RSA_PKCS_OAEP)) {
480 			  signatureMechanismInfo = token.getMechanismInfo(Mechanism.RSA_PKCS_OAEP);
481 			  
482 		  } else {
483 			  signatureMechanismInfo = null;
484 		  }
485 	  } catch (TokenException e1) {
486 			logger.info("[Pkcs11Util.generateKeyPair]::No se pueden obtener los mecanismos de cifrado del dispositivo", e1);
487 			throw new KeyPairException("No se pueden obtener los mecanismos de cifrado del dispositivo", e1);
488 	  }
489 	  Mechanism keyPairGenerationMechanism = Mechanism.RSA_PKCS_KEY_PAIR_GEN;
490 	  RSAPublicKey rsaPublicKeyTemplate = new RSAPublicKey();
491 	  RSAPrivateKey rsaPrivateKeyTemplate = new RSAPrivateKey();
492 	  
493 	  // set the general attributes for the public key
494 	  rsaPublicKeyTemplate.getModulusBits().setLongValue(new Long(keySize));
495 	  byte[] publicExponentBytes = { 0x01, 0x00, 0x01 }; // 2^16 + 1
496 	  rsaPublicKeyTemplate.getPublicExponent().setByteArrayValue(publicExponentBytes);
497 	  rsaPublicKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
498 	  byte[] id = new byte[20];
499 	  new Random().nextBytes(id);
500 	  rsaPublicKeyTemplate.getId().setByteArrayValue(id);
501 	  
502 	  if (label != null){
503 		  rsaPublicKeyTemplate.getLabel().setCharArrayValue(label.toCharArray());
504 	  }
505 	  
506 	  rsaPrivateKeyTemplate.getSensitive().setBooleanValue(Boolean.TRUE);
507 	  rsaPrivateKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
508 	  rsaPrivateKeyTemplate.getPrivate().setBooleanValue(Boolean.TRUE);
509 	  rsaPrivateKeyTemplate.getModifiable().setBooleanValue(Boolean.TRUE);
510 	  rsaPrivateKeyTemplate.getId().setByteArrayValue(id);
511 	  // byte[] subject = args[1].getBytes();
512 	  // rsaPrivateKeyTemplate.getSubject().setByteArrayValue(subject);
513 	  if (label != null){
514 		  rsaPrivateKeyTemplate.getLabel().setCharArrayValue(label.toCharArray());
515 	  }
516 	  
517 	  // set the attributes in a way netscape does, this should work with most
518 	  // tokens
519 	  if (signatureMechanismInfo != null) {
520 		  
521 		  rsaPublicKeyTemplate.getVerify().setBooleanValue(new Boolean(signatureMechanismInfo.isVerify()));
522 		  rsaPublicKeyTemplate.getVerifyRecover().setBooleanValue(new Boolean(signatureMechanismInfo.isVerifyRecover()));
523 		  rsaPublicKeyTemplate.getEncrypt().setBooleanValue(new Boolean(signatureMechanismInfo.isEncrypt()));
524 		  rsaPublicKeyTemplate.getDerive().setBooleanValue(new Boolean(signatureMechanismInfo.isDerive()));
525 		  
526 		  rsaPrivateKeyTemplate.getSign().setBooleanValue(new Boolean(signatureMechanismInfo.isSign()));
527 		  rsaPrivateKeyTemplate.getSignRecover().setBooleanValue(new Boolean(signatureMechanismInfo.isSignRecover()));
528 		  rsaPrivateKeyTemplate.getDecrypt().setBooleanValue(new Boolean(signatureMechanismInfo.isDecrypt()));
529 		  rsaPrivateKeyTemplate.getDerive().setBooleanValue(new Boolean(signatureMechanismInfo.isDerive()));
530 		  
531 	  } else {
532 		  
533 		  // if we have no information we assume these attributes
534 		  rsaPrivateKeyTemplate.getSign().setBooleanValue(Boolean.TRUE);
535 		  rsaPrivateKeyTemplate.getDecrypt().setBooleanValue(Boolean.TRUE);
536 		  
537 		  rsaPublicKeyTemplate.getVerify().setBooleanValue(Boolean.TRUE);
538 		  rsaPublicKeyTemplate.getEncrypt().setBooleanValue(Boolean.TRUE);
539 		  
540 	  }
541 	  
542 	  rsaPublicKeyTemplate.getWrap().setBooleanValue(Boolean.TRUE);
543 	  rsaPrivateKeyTemplate.getUnwrap().setBooleanValue(Boolean.TRUE); // Sin esto no van los certificados de logon
544 
545 	  // netscape does not set these attribute, so we do no either
546 	  rsaPublicKeyTemplate.getKeyType().setPresent(false);
547 	  rsaPublicKeyTemplate.getObjectClass().setPresent(false);
548 	  
549 	  rsaPrivateKeyTemplate.getKeyType().setPresent(false);
550 	  rsaPrivateKeyTemplate.getObjectClass().setPresent(false);
551 	  
552 	  logger.debug("Plantillas de generacion de claves creadas");
553 	  
554 	  KeyPair generatedKeyPair = null;
555 	  
556 	  try {
557 		  
558 		  // -- Intentamos generar las claves
559 		  generatedKeyPair = session.generateKeyPair(keyPairGenerationMechanism, rsaPublicKeyTemplate, rsaPrivateKeyTemplate);
560 		  
561 	  } catch (TokenException pkcsex) {
562 		  logger.info("Excepción en la operación con el PKCS11.\n Iniciando el borrado de elementos huerfanos.", pkcsex);
563 		  Pkcs11Util.deleteOrphans(session);
564 		  logger.debug("Fin del proceso de eliminación de elementos huerfanos.");
565 		  
566 		  if (numRetry < 3) {
567 			  logger.debug("Reintentamdo la generacion...");
568 			  numRetry++;
569 			  generatedKeyPair = Pkcs11Util.generateKeyPair(session, token, keySize, numRetry, label);
570 			  
571 		  } else {
572 			  logger.info("[Pkcs11Util.generateKeyPair]::No se ha podido generar el par de claves", pkcsex);
573 			  throw new KeyPairException("No se ha podido generar el par de claves", pkcsex);
574 		  }
575 		  
576 	  }
577 		  
578 	  return generatedKeyPair;
579   }
580 
581 /**
582    * @param rsaKeyPair
583    * @return Par de claves
584    */
585   public static java.security.KeyPair iakKeyPairToSun(KeyPair rsaKeyPair) {
586 
587 //    logger.debug("PublicKey:\n" + rsaKeyPair.getPublicKey().toString());
588 //    logger.debug("PrivateKey:\n" + rsaKeyPair.getPrivateKey().toString());
589 
590 //    java.security.PublicKey publicKey = getJavaSecurityPublicKey((RSAPublicKey) rsaKeyPair.getPublicKey());
591     TokenPublicKey tpk = new TokenPublicKey(rsaKeyPair.getPublicKey());
592 //    java.security.PublicKey publicKey = tpk.getSunPublicKey();
593     java.security.PublicKey publicKey = tpk;
594     
595     logger.debug("publicKey: " + publicKey.toString());
596 
597     java.security.PrivateKey privateKey = getJavaSecurityPrivateKey((RSAPrivateKey) rsaKeyPair.getPrivateKey());
598     logger.debug("privateKey: " + privateKey.toString());
599 
600     java.security.KeyPair kp = new java.security.KeyPair(publicKey, privateKey);
601 //    logger.debug("SUN PublicKey:\n" + kp.getPublic().getEncoded());
602 //    logger.debug("SUN KeyPair:\n" + kp);
603 
604     return kp;
605   }
606   
607   /**
608 	* Importa al PKCS11 un certificado a partir de un certificado X509.
609 	* 
610 	* @param session
611 	* @param token
612 	* @param cert
613 	* @param theLabel
614 	* @throws CertificateInvalidException 
615 	* @throws DeviceFullException 
616 	* @throws SavingObjectException 
617 	*/
618 	public static void importX509Cert(Session session, Token token,
619 			X509Certificate cert, String theLabel, boolean deletePublicKey) throws CertificateInvalidException, DeviceFullException, SavingObjectException  {
620 
621 		Collection certificateChain = null;
622 		try {
623 			//-- Parseo del certificado
624 			CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", ArangiObject.CRYPTOGRAPHIC_PROVIDER_NAME);
625 			certificateChain = certificateFactory.generateCertificates(new ByteArrayInputStream(cert.getEncoded()));
626 			if (certificateChain.size() < 1) {
627 				logger.info("Did not find any certificate in the given input file. Finished.");
628 				throw new CertificateInvalidException("El objeto X509 proporcionado no contiene ningún certificado");
629 			}
630 			// -- Quitamos el certificado de la cadena de confianza
631 			certificateChain.remove(cert);
632 		} catch (CertificateException e) {
633 			logger.info("Error criptográfico manipulando el Certificado X509 proporcionado", e);
634 			throw new CertificateInvalidException("Error criptográfico manipulando el Certificado X509 proporcionado", e);
635 		} catch (NoSuchProviderException e) {
636 			logger.info("El certificado proporcionado no puede ser manipulado por el proveedor de Bouncy Castle", e);
637 			throw new CertificateInvalidException("El certificado proporcionado no puede ser manipulado por el proveedor de Bouncy Castle", e);
638 		}
639 
640 		logger.debug("Searching for corresponding private key on token.");
641 
642 		PublicKey publicKey = cert.getPublicKey();
643 
644 		iaik.pkcs.pkcs11.objects.Object searchTemplate = null;
645 		if (publicKey.getAlgorithm().equalsIgnoreCase("RSA")) {
646 			java.security.interfaces.RSAPublicKey rsaPublicKey = (java.security.interfaces.RSAPublicKey) publicKey;
647 			RSAPrivateKey rsaPrivateKeySearchTemplate = new RSAPrivateKey();
648 			byte[] modulus = iaik.pkcs.pkcs11.Util.unsignedBigIntergerToByteArray(rsaPublicKey.getModulus());
649 			rsaPrivateKeySearchTemplate.getModulus().setByteArrayValue(modulus);
650 			searchTemplate = rsaPrivateKeySearchTemplate;
651 		}
652 
653 		byte[] objectID = null;
654 		try {
655 			if (searchTemplate != null) {
656 				session.findObjectsInit(searchTemplate);
657 				Object[] foundKeyObjects = session.findObjects(1);
658 				if (foundKeyObjects.length > 0) {
659 					Key foundKey = (Key) foundKeyObjects[0];
660 					objectID = foundKey.getId().getByteArrayValue();
661 					logger.debug("found a correponding key on the token: ");
662 					logger.debug(foundKey);
663 				} else {
664 					logger.debug("found no correponding key on the token.");
665 				}
666 				session.findObjectsFinal();
667 			} else {
668 				logger.debug("public key is neither RSA, DSA nor DH.");
669 			}
670 		} catch (TokenException e) {
671 			logger.debug("Error buscando clave privada", e);
672 		}
673 		
674 		logger.debug("Create certificate object(s) on token.");
675 
676 		X509Certificate currentCertificate = cert; // start with user cert
677 		boolean importedCompleteChain = false;
678 		while (!importedCompleteChain) {
679 			// create certificate object template
680 			X509PublicKeyCertificate pkcs11X509PublicKeyCertificate = new X509PublicKeyCertificate();
681 			char[] label = theLabel.toCharArray();
682 			byte[] newObjectID;
683 			try {
684 				// if we need a new object ID, create one
685 				if (objectID == null) {
686 					if (publicKey instanceof java.security.interfaces.RSAPublicKey) {
687 						newObjectID = ((java.security.interfaces.RSAPublicKey) publicKey).getModulus().toByteArray();
688 						MessageDigest digest = MessageDigest.getInstance("SHA-1");
689 						newObjectID = digest.digest(newObjectID);
690 					} else if (publicKey instanceof java.security.interfaces.DSAPublicKey) {
691 						newObjectID = ((java.security.interfaces.DSAPublicKey) publicKey).getY().toByteArray();
692 						MessageDigest digest = MessageDigest.getInstance("SHA-1");
693 						newObjectID = digest.digest(newObjectID);
694 					} else {
695 						Certificate certificate = null;
696 						try {
697 							certificate = new Certificate (currentCertificate);
698 						} catch (NormalizeCertificateException e) {
699 							logger.info("No se puede obtener el certificado de Arangi", e);
700 						}
701 						newObjectID = certificate.getFingerPrint().getBytes();
702 //						newObjectID = org.ejbca.util.CertTools.getFingerprintAsString(currentCertificate).getBytes();
703 					}
704 				} else {
705 					// we already got one from a corresponding private key before
706 					newObjectID = objectID;
707 				}
708 			} catch (NoSuchAlgorithmException e) {
709 				logger.info ("[Pkcs11Util.importX509Cert]::No se puede obtener un nuevo ID en el dispositivo debido a que el algoritmo criptográfico SHA-1 no soportado.", e);
710 				throw new SavingObjectException ("No se puede obtener un nuevo ID en el dispositivo debido a que el algoritmo criptográfico SHA-1 no soportado.", e);
711 			}	
712 			// byte[] encodedSubject = ((Name)
713 			// currentCertificate.getSubjectDN()).getEncoded();
714 			// byte[] encodedIssuer = ((Name)
715 			// currentCertificate.getIssuerDN()).getEncoded();
716 			byte[] encodedSubject = currentCertificate.getSubjectX500Principal().getEncoded();
717 			byte[] encodedIssuer = currentCertificate.getIssuerX500Principal().getEncoded();
718 
719 			// serial number should be an DER encoded ASN.1 integer
720 			/*
721 			 * INTEGER asn1Integer = new
722 			 * INTEGER(userCertificate.getSerialNumber()); ByteArrayOutputStream
723 			 * buffer = new ByteArrayOutputStream();
724 			 * DerCoder.encodeTo(asn1Integer, buffer);
725 			 * pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(buffer.toByteArray());
726 			 */
727 			// Netscape deviates from the standard here, for use with Netscape
728 			// rather use
729 //			byte[] serialNumber = currentCertificate.getSerialNumber().toByteArray();
730 
731 			pkcs11X509PublicKeyCertificate.getToken().setBooleanValue(Boolean.TRUE);
732 			pkcs11X509PublicKeyCertificate.getPrivate().setBooleanValue(Boolean.FALSE);
733 			pkcs11X509PublicKeyCertificate.getLabel().setCharArrayValue(label);
734 			pkcs11X509PublicKeyCertificate.getId().setByteArrayValue(newObjectID);
735 			pkcs11X509PublicKeyCertificate.getSubject().setByteArrayValue(encodedSubject);
736 			pkcs11X509PublicKeyCertificate.getIssuer().setByteArrayValue(encodedIssuer);
737 //			pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(serialNumber);
738 			try {
739 				pkcs11X509PublicKeyCertificate.getValue().setByteArrayValue(currentCertificate.getEncoded());
740 			} catch (CertificateEncodingException e) {
741 				logger.info ("[Pkcs11Util.importX509Cert]::La codificación del certificado es incorrecta", e);
742 				throw new CertificateInvalidException("La codificación del certificado es incorrecta", e);
743 			}
744 			logger.debug(pkcs11X509PublicKeyCertificate);
745 			try{
746 				session.createObject(pkcs11X509PublicKeyCertificate);
747 			} catch (TokenException e) {
748 				logger.info ("[Pkcs11Util.importX509Cert]::Error creando clave pública del certificado en el dispositivo", e);
749 				throw new SavingObjectException("Error creando clave pública del certificado en el dispositivo", e);
750 			}
751 
752 			if (certificateChain.size() > 0) {
753 				currentCertificate = (X509Certificate) certificateChain.iterator().next();
754 				certificateChain.remove(currentCertificate);
755 				objectID = null; // do not use the same ID for other
756 									// certificates
757 			} else {
758 				importedCompleteChain = true;
759 			}
760 		}
761 
762 		if (deletePublicKey) {
763 			// -- Borramos ahora la clave pública
764 			logger.debug("Borramos clave pública...");
765 		    iaik.pkcs.pkcs11.objects.PublicKey publicKeyTemplate = new iaik.pkcs.pkcs11.objects.PublicKey();
766 			publicKeyTemplate.getLabel().setCharArrayValue(theLabel.toCharArray());
767 			List<Object> lPKs;
768 			try {
769 				lPKs = findAllObjects(session, publicKeyTemplate);
770 				if (!lPKs.isEmpty()) {
771 					deleteObject(session, lPKs.get(0), 0);
772 					logger.debug("Clave pública borrada.");
773 				}
774 			} catch (SearchingException e) {
775 				logger.info("No se ha borrado la clave pública porque no existe");
776 			}
777 		}
778 
779 		//-- Borramos huerfanos
780 		deleteOrphans(session);
781 
782 	}
783 
784 	  /**
785 	   * Retorna el número de claves privadas en el PKCS11.
786 	   * 
787 	   * @param session
788 	   * @return Número de claves privadas en el PKCS11
789 	 * @throws SearchingException 
790 	   * @throws TokenException
791 	   */
792 	  public static int getNumPrivateKeysInPKCS11(Session session) throws SearchingException {
793 		  
794 		  int iRet = 0;
795 		  
796 		  List vKeys = findPrivateKeysByLabel(session, null);
797 		  if (vKeys != null) {
798 			  iRet = vKeys.size();
799 		  }
800 		  
801 		  return iRet;
802 	  }
803 
804 	  /**
805 	 * Cambia la etiqueta de uno o varios objetos por la indicada
806 	 * 
807 	 * @param session
808 	 * @throws SearchingException 
809 	 * @throws SavingObjectException 
810 	 * @throws Exception 
811 	 */
812 	public static void changeLabel(Module module, Session session, String label, String newLabel) throws SearchingException, SavingObjectException {
813 		
814 		//-- Buscamos todos los objetos con label temporal
815 		logger.debug("Buscando certificados con LABEL '" + label + "'. Cambio a '" + newLabel + "'");
816 		iaik.pkcs.pkcs11.objects.GenericTemplate template = new iaik.pkcs.pkcs11.objects.GenericTemplate();
817 		CharArrayAttribute ckLabel = new CharArrayAttribute(Attribute.LABEL);
818 		ckLabel.setCharArrayValue(label.toCharArray());
819 		template.addAttribute(ckLabel);
820 		List foundObjects = findAllObjects(session, template);
821 		logger.debug("Encontrados: " + foundObjects.size());
822 
823 		//-- Para cada objeto, obtenemos su label
824 		for (int i = 0; i < foundObjects.size(); i++) {
825 			iaik.pkcs.pkcs11.objects.Object object  = (iaik.pkcs.pkcs11.objects.Object)foundObjects.get(i);
826 			logger.debug(object + "\n\n");
827 			
828 			logger.debug("Atributos: " + object.getAttributeTable());			
829 			PKCS11 pkcs11Module = module.getPKCS11Module();
830 			long hSession = session.getSessionHandle();
831 			long hObject = object.getObjectHandle();
832 			
833 			iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE[] attributes;
834 			try {
835 				attributes = iaik.pkcs.pkcs11.objects.Object.getSetAttributes(object);
836 			} catch (PKCS11Exception e) {
837 				logger.info ("[Pkcs11Util.changeLabel]::Error obteniendo los atributos de uno de los objetos del alias '" +
838 						label + "'.", e);
839 				throw new SavingObjectException ("Error obteniendo los atributos de uno de los objetos del alias '" +
840 						label + "'.", e);
841 			}
842 			CK_ATTRIBUTE ck_label = null; 
843 			for (int j = 0; j < attributes.length; j++) {
844 				iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE ckAtt = attributes[j];
845 				if (ckAtt.type == PKCS11Constants.CKA_LABEL) {
846 					ckAtt.pValue = newLabel.toCharArray();
847 					ck_label = ckAtt;
848 				}
849 			}
850 			
851 			CK_ATTRIBUTE[] pTemplate = new CK_ATTRIBUTE[1];
852 			pTemplate[0] = ck_label;
853 			try {
854 				pkcs11Module.C_SetAttributeValue(hSession, hObject, pTemplate, true);
855 			} catch (PKCS11Exception e) {
856 				logger.info ("[Pkcs11Util.changeLabel]::Error cambiando el atributo 'label' de uno de los objetos del alias '" +
857 						label + "'.", e);
858 				throw new SavingObjectException ("Error cambiando el atributo 'label' de uno de los objetos del alias '" +
859 						label + "'.", e);
860 			}
861 			logger.debug("Cambiada label del objeto '" + hObject + "' en la sesion '" + hSession + "'");
862 		}
863 	}
864 
865 
866 
867 	
868 }