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.model;
22  
23  import iaik.pkcs.pkcs11.Module;
24  import iaik.pkcs.pkcs11.Session;
25  import iaik.pkcs.pkcs11.Token;
26  import iaik.pkcs.pkcs11.TokenInfo;
27  import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate;
28  
29  import java.security.cert.X509Certificate;
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  
35  import org.apache.log4j.Logger;
36  
37  import es.accv.arangi.base.device.AbstractPkcs11Manager;
38  import es.accv.arangi.base.device.util.pkcs11.Pkcs11Util;
39  import es.accv.arangi.base.exception.device.LoadingObjectException;
40  import es.accv.arangi.base.exception.device.OpeningDeviceException;
41  import es.accv.arangi.base.exception.device.SearchingException;
42  import es.accv.arangi.base.util.Util;
43  
44  /**
45   * Clase que mantiene la información de un dispositivo PKCS#11. Un dispositivo puede
46   * enontrarse en tres estados:<br><br>
47   * <ul>
48   * 	<li>Abierto con PIN: se pueden realizar todas las tareas de lectura y escritura</li>
49   * 	<li>Abierto con PUK: sólo se permiten realizar ciertas tareas. Normalmente un 
50   * 	dispositivo se abre con PUK sólo para desbloquear el PIN.</li>
51   * 	<li>Sin abrir: en este estado se puede obtener información genérica del dispositivo,
52   * 	como por ejemplo el número de serie, y la lista de certificados que contiene</li>
53   * </ul> <br><br>
54   * 
55   * Aunque se puede programar la inicialización de un objeto de esta clase, lo normal
56   * es que se trabaje con objetos creados por el método getConnectedDevices de la clase
57   * {@link AbstractPkcs11Manager AbstractPkcs11Manager}. El manager PKCS#11 también 
58   * utiliza esta clase para abrir los dispositivos.
59   * 
60   * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
61   */
62  public class Pkcs11Device {
63  	
64  	/*
65  	 * Logger de la clase
66  	 */
67  	Logger logger = Logger.getLogger(Pkcs11Device.class);
68  
69  	private Pkcs11Manufacturer manufacturer;
70  	private String moduleName;
71  	private Module module;
72  	private Token token;
73  	private TokenInfo tokenInfo;
74  	private Session session;
75  	private X509Certificate[] certificates;
76  	private String[] aliases;
77  	private Map<String,X509Certificate> mapCertificates;
78  	
79  	/**
80  	 * Constructor que carga los valores del dispositivo para el caso en que el dispositivo
81  	 * esté abierto.
82  	 * 
83  	 * @param token Token IAIK
84  	 * @throws OpeningDeviceException Excepción debida a que no se ha podido abrir una 
85  	 * 	sesión con el token
86  	 * @throws SearchingException Excepción producida mientras se obtenía la lista de
87  	 * 	certificados del dispositivo
88  	 * @throws LoadingObjectException Excepción obteniendo los campos de información del
89  	 * 	dispositivo
90  	 */
91  	public Pkcs11Device (boolean isOpened, Pkcs11Manufacturer manufacturer, String moduleName, Module module, Token token, TokenInfo tokenInfo, Session session) {
92  		this.manufacturer = manufacturer;
93  		this.moduleName = moduleName;
94  		this.module = module;
95  		this.token = token;
96  		this.tokenInfo = tokenInfo;
97  		
98  		//-- Si se ha abierto guardamos la sesión. Si no obtenemos la lista de certificados y
99  		//-- cerramos la sesión (ya que no se va a usar para nada más)
100 		if (isOpened) {
101 			this.session = session;
102 		} else {
103 			try {
104 				loadAliasAndCertificates (session);
105 				session.closeSession();
106 			} catch (Throwable e) {
107 				logger.info("[Pkcs11Manufacturer.open]::Excepción durante cierre de dispositivo. Ignorando...", e);
108 			}
109 		}
110 	}
111 	
112 	/**
113 	 * Obtiene el identificador del dispositivo.
114 	 * 
115 	 * @return ID del dispositivo
116 	 */
117 	public long getId() {
118 		return token.getTokenID();
119 	}
120 	
121 	/**
122 	 * Obtiene el nombre del módulo con el que se abrió el dispositivo.
123 	 * 
124 	 * @return Nombre del módulo del dispositivo
125 	 */
126 	public String getModuleName() {
127 		return moduleName;
128 	}
129 	
130 	/**
131 	 * Obtiene el módulo con el que se abrió el dispositivo.
132 	 * 
133 	 * @return Módulo del dispositivo
134 	 */
135 	public Module getModule() {
136 		return module;
137 	}
138 	
139 	/**
140 	 * Obtiene el token de IAIK.
141 	 * 
142 	 * @return Token que representa al dispositivo
143 	 */
144 	public Token getToken() {
145 		return token;
146 	}
147 	
148 	/**
149 	 * Obtiene la información del token de IAIK.
150 	 * 
151 	 * @return Información del token que representa al dispositivo
152 	 */
153 	public TokenInfo getTokenInfo() {
154 		return tokenInfo;
155 	}
156 	
157 	/**
158 	 * Obtiene la sesión. Si el dispositivo no está abierto este valor
159 	 * será nulo.
160 	 * 
161 	 * @return Sesión en el dispositivo
162 	 */
163 	public Session getSession() {
164 		return session;
165 	}
166 	
167 	/**
168 	 * Carga una nueva sesión
169 	 * 
170 	 * @param session Sesión en el dispositivo
171 	 */
172 	public void setSession(Session session) {
173 		this.session = session;
174 	}
175 	
176 	/**
177 	 * Obtiene los certificados contenidos en el dispositivo si
178 	 * este no está abierto
179 	 * 
180 	 * @return Certificados contenidos en el dispositivo
181 	 */
182 	public X509Certificate[] getCertificates() {
183 		return certificates;
184 	}
185 	
186 	/**
187 	 * Obtiene un certificado a partir de su alias
188 	 * 
189 	 * @param alias Alias
190 	 * @return Certificado contenido en el alias
191 	 */
192 	public X509Certificate getCertificate (String alias) {
193 		return mapCertificates.get(alias);
194 	}
195 
196 	/**
197 	 * Obtiene el nombre de los alias, el orden coincide con el
198 	 * de los certificados devueltos por {@link #getCertificates()}
199 	 * 
200 	 * @return Lista de alias
201 	 */
202 	public String[] getAliases() {
203 		return aliases;
204 	}
205 
206 	/**
207 	 * Obtiene la etiqueta del dispositivo, normalmente relacionada con el módulo
208 	 * con el que se abrió.
209 	 * 
210 	 * @return Etiqueta del dispositivo
211 	 */
212 	public String getLabel() {
213 		return tokenInfo.getLabel().trim();
214 	}
215 	
216 	/**
217 	 * Obtiene el tamaño de la memoria de la tarjeta.
218 	 * 
219 	 * @return Tamaño de la memoria de la tarjeta
220 	 */
221 	public long getTotalMemory () {
222 		return tokenInfo.getTotalPublicMemory();
223 	}
224 	
225 	/**
226 	 * Obtiene el espacio libre de la tarjeta
227 	 * 
228 	 * @return Espacio libre en la tarjeta
229 	 */
230 	public long getFreeMemory () {
231 		return tokenInfo.getFreePublicMemory();
232 	}
233 	
234 	/**
235 	 * Obtiene el fabricante del dispositivo que ha inicializado esta clase
236 	 * 
237 	 * @return Fabricante del dispositivo
238 	 */
239 	public Pkcs11Manufacturer getManufacturer() {
240 		return manufacturer;
241 	}
242 	
243 	/**
244 	 * Obtiene el ID del fabricante del dispositivo tal y como aparece registrado
245 	 * en el dispositivo
246 	 * 
247 	 * @return ID del fabricante del dispositivo tal y como aparece registrado
248 	 * en el dispositivo
249 	 */
250 	public String getManufacturerId() {
251 		return tokenInfo.getManufacturerID().trim();
252 	}
253 	
254 	/**
255 	 * Obtiene el modelo del dispositivo
256 	 * 
257 	 * @return Modelo del dispostivo
258 	 */
259 	public String getModel() {
260 		return tokenInfo.getModel().trim();
261 	}
262 	
263 	/**
264 	 * Obtiene el número de serie del dispositivo
265 	 * 
266 	 * @return Número de serie del dispositivo
267 	 */
268 	public String getSerialNumber() {
269 		return tokenInfo.getSerialNumber().trim();
270 	}
271 	
272 	/**
273 	 * Obtiene la versión del firmware
274 	 * 
275 	 * @return Versión del firmware
276 	 */
277 	public String getFirmwareVersion() {
278 		return tokenInfo.getFirmwareVersion().getMajor() + "." + tokenInfo.getFirmwareVersion().getMinor();
279 	}
280 	
281 	/*
282 	 * Carga la lista completa de certificados y la lista de alias que existen dentro del dispositivo.
283 	 * 
284 	 * @throws SearchingException Error leyendo el dispositivo
285 	 */
286 	private void loadAliasAndCertificates(Session session) throws SearchingException {
287 		//-- Obtener la lista de todos los certificados
288 		mapCertificates = new HashMap<String, X509Certificate>();
289 		try {
290 			X509PublicKeyCertificate template = new X509PublicKeyCertificate();
291 			List result = Pkcs11Util.findAllObjects(session, template);
292 			List<X509Certificate> lX509Certificates = new ArrayList<X509Certificate> ();
293 			List<String> lAliases = new ArrayList<String> ();
294 			for (int f=0;f<result.size();f++) {
295 				X509PublicKeyCertificate iaikCert = (X509PublicKeyCertificate)result.get(f);
296 				X509Certificate certificate = Util.getCertificate(iaikCert.getValue().getByteArrayValue());
297 				String alias = iaikCert.getLabel().toString();
298 				
299 				lX509Certificates.add (certificate);
300 				lAliases.add(alias);
301 				mapCertificates.put(alias, certificate);
302 			}
303 			this.certificates =  lX509Certificates.toArray(new X509Certificate[0]);
304 			this.aliases =  lAliases.toArray(new String[0]);
305 		} catch (Exception e) {
306 			throw new SearchingException ("No ha sido posible obtener la lista de certificados del dispositivo", e);
307 		}
308 
309 	}
310 
311 }