1 /*
2  * misc.c: Miscellaneous PKCS#11 library helper functions
3  *
4  * Copyright (C) 2002  Timo Teräs <timo.teras@iki.fi>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include "config.h"
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "sc-pkcs11.h"
27 
28 #define DUMP_TEMPLATE_MAX	32
29 
30 struct sc_to_cryptoki_error_conversion  {
31 	const char *context;
32 	int sc_error;
33 	CK_RV ck_error;
34 };
35 
36 static struct sc_to_cryptoki_error_conversion sc_to_cryptoki_error_map[]  = {
37 	{ "C_GenerateKeyPair",	SC_ERROR_INVALID_PIN_LENGTH,	CKR_GENERAL_ERROR },
38 	{ "C_Sign",		SC_ERROR_NOT_ALLOWED,		CKR_FUNCTION_FAILED},
39 	{ "C_Decrypt",		SC_ERROR_NOT_ALLOWED,		CKR_FUNCTION_FAILED},
40 	{NULL, 0, 0}
41 };
42 
43 
strcpy_bp(u8 * dst,const char * src,size_t dstsize)44 void strcpy_bp(u8 * dst, const char *src, size_t dstsize)
45 {
46 	if (!dst || !dstsize)
47 		return;
48 
49 	memset((char *)dst, ' ', dstsize);
50 
51 	if (src) {
52 		size_t src_len = strlen(src);
53 
54 		if (src_len > dstsize) {
55 			/* string will be truncated */
56 			memcpy((char *)dst, src, dstsize);
57 			if (dstsize > 3) {
58 				/* show truncation with '...' */
59 				/* FIXME avoid breaking an UTF-8 character on multiple bytes */
60 				memset((char *)dst + dstsize - 3, '.', 3);
61 			}
62 		} else {
63 			memcpy((char *)dst, src, src_len);
64 		}
65 	}
66 }
67 
68 
sc_to_cryptoki_error_common(int rc)69 static CK_RV sc_to_cryptoki_error_common(int rc)
70 {
71 	sc_log(context, "libopensc return value: %d (%s)\n", rc, sc_strerror(rc));
72 	switch (rc) {
73 	case SC_SUCCESS:
74 		return CKR_OK;
75 	case SC_ERROR_NOT_SUPPORTED:
76 		return CKR_FUNCTION_NOT_SUPPORTED;
77 	case SC_ERROR_OUT_OF_MEMORY:
78 		return CKR_HOST_MEMORY;
79 	case SC_ERROR_PIN_CODE_INCORRECT:
80 		return CKR_PIN_INCORRECT;
81 	case SC_ERROR_AUTH_METHOD_BLOCKED:
82 		return CKR_PIN_LOCKED;
83 	case SC_ERROR_BUFFER_TOO_SMALL:
84 		return CKR_BUFFER_TOO_SMALL;
85 	case SC_ERROR_CARD_NOT_PRESENT:
86 		return CKR_TOKEN_NOT_PRESENT;
87 	case SC_ERROR_INVALID_CARD:
88 	case SC_ERROR_WRONG_CARD:
89 	case SC_ERROR_NO_CARD_SUPPORT:
90 		return CKR_TOKEN_NOT_RECOGNIZED;
91 	case SC_ERROR_WRONG_LENGTH:
92 		return CKR_DATA_LEN_RANGE;
93 	case SC_ERROR_INVALID_PIN_LENGTH:
94 		return CKR_PIN_LEN_RANGE;
95 	case SC_ERROR_KEYPAD_CANCELLED:
96 	case SC_ERROR_KEYPAD_TIMEOUT:
97 		return CKR_FUNCTION_CANCELED;
98 	case SC_ERROR_CARD_REMOVED:
99 		return CKR_DEVICE_REMOVED;
100 	case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED:
101 		return CKR_USER_NOT_LOGGED_IN;
102 	case SC_ERROR_KEYPAD_PIN_MISMATCH:
103 		return CKR_PIN_INVALID;
104 	case SC_ERROR_INVALID_ARGUMENTS:
105 		return CKR_ARGUMENTS_BAD;
106 	case SC_ERROR_INVALID_DATA:
107 	case SC_ERROR_INCORRECT_PARAMETERS:
108 		return CKR_DATA_INVALID;
109 	case SC_ERROR_CARD_UNRESPONSIVE:
110 	case SC_ERROR_READER_LOCKED:
111 		return CKR_DEVICE_ERROR;
112 	case SC_ERROR_READER_DETACHED:
113 		return CKR_TOKEN_NOT_PRESENT;	/* Maybe CKR_DEVICE_REMOVED ? */
114 	case SC_ERROR_NOT_ENOUGH_MEMORY:
115 		return CKR_DEVICE_MEMORY;
116 	case SC_ERROR_MEMORY_FAILURE:	/* EEPROM has failed */
117 		return CKR_DEVICE_ERROR;
118 	}
119 	return CKR_GENERAL_ERROR;
120 }
121 
122 
sc_to_cryptoki_error(int rc,const char * ctx)123 CK_RV sc_to_cryptoki_error(int rc, const char *ctx)
124 {
125 	if (ctx)   {
126 		int ii;
127 
128 		for (ii = 0; sc_to_cryptoki_error_map[ii].context; ii++) {
129 			if (sc_to_cryptoki_error_map[ii].sc_error != rc)
130 				continue;
131 			if (strcmp(sc_to_cryptoki_error_map[ii].context, ctx))
132 				continue;
133 			return sc_to_cryptoki_error_map[ii].ck_error;
134 		}
135 	}
136 	return sc_to_cryptoki_error_common(rc);
137 }
138 
139 
140 struct sc_pkcs11_login {
141 	CK_USER_TYPE userType;
142 	CK_CHAR_PTR pPin;
143 	CK_ULONG ulPinLen;
144 };
145 
restore_login_state(struct sc_pkcs11_slot * slot)146 CK_RV restore_login_state(struct sc_pkcs11_slot *slot)
147 {
148 	CK_RV r = CKR_OK;
149 
150 	if (sc_pkcs11_conf.atomic && slot) {
151 		if (list_iterator_start(&slot->logins)) {
152 			struct sc_pkcs11_login *login = list_iterator_next(&slot->logins);
153 			while (login && slot->p11card && slot->p11card->framework) {
154 				r = slot->p11card->framework->login(slot, login->userType,
155 						login->pPin, login->ulPinLen);
156 				if (r != CKR_OK)
157 					break;
158 				login = list_iterator_next(&slot->logins);
159 			}
160 			list_iterator_stop(&slot->logins);
161 		}
162 	}
163 
164 	return r;
165 }
166 
reset_login_state(struct sc_pkcs11_slot * slot,CK_RV rv)167 CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv)
168 {
169 	if (slot) {
170 		if (sc_pkcs11_conf.atomic
171 				&& slot->p11card && slot->p11card->framework) {
172 			slot->p11card->framework->logout(slot);
173 		}
174 
175 		if (rv == CKR_USER_NOT_LOGGED_IN) {
176 			slot->login_user = -1;
177 			pop_all_login_states(slot);
178 		}
179 	}
180 
181 	return rv;
182 }
183 
push_login_state(struct sc_pkcs11_slot * slot,CK_USER_TYPE userType,CK_CHAR_PTR pPin,CK_ULONG ulPinLen)184 CK_RV push_login_state(struct sc_pkcs11_slot *slot,
185 		CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
186 {
187 	CK_RV r = CKR_HOST_MEMORY;
188 	struct sc_pkcs11_login *login = NULL;
189 
190 	if (!sc_pkcs11_conf.atomic || !slot) {
191 		return CKR_OK;
192 	}
193 
194 	login = (struct sc_pkcs11_login *) calloc(1, sizeof *login);
195 	if (login == NULL) {
196 		goto err;
197 	}
198 
199 	if (pPin && ulPinLen) {
200 		login->pPin = sc_mem_secure_alloc((sizeof *pPin)*ulPinLen);
201 		if (login->pPin == NULL) {
202 			goto err;
203 		}
204 		memcpy(login->pPin, pPin, (sizeof *pPin)*ulPinLen);
205 		login->ulPinLen = ulPinLen;
206 	}
207 	login->userType = userType;
208 
209 	if (0 > list_append(&slot->logins, login)) {
210 		goto err;
211 	}
212 
213 	login = NULL;
214 	r = CKR_OK;
215 
216 err:
217 	if (login) {
218 		if (login->pPin) {
219 			sc_mem_clear(login->pPin, login->ulPinLen);
220 			sc_mem_secure_free(login->pPin, login->ulPinLen);
221 		}
222 		free(login);
223 	}
224 
225 	return r;
226 }
227 
pop_login_state(struct sc_pkcs11_slot * slot)228 void pop_login_state(struct sc_pkcs11_slot *slot)
229 {
230 	if (slot) {
231 		unsigned int size = list_size(&slot->logins);
232 		if (size > 0) {
233 			struct sc_pkcs11_login *login = list_get_at(&slot->logins, size-1);
234 			if (login) {
235 				sc_mem_clear(login->pPin, login->ulPinLen);
236 				sc_mem_secure_free(login->pPin, login->ulPinLen);
237 				free(login);
238 			}
239 			if (0 > list_delete_at(&slot->logins, size-1))
240 				sc_log(context, "Error deleting login state");
241 		}
242 	}
243 }
244 
pop_all_login_states(struct sc_pkcs11_slot * slot)245 void pop_all_login_states(struct sc_pkcs11_slot *slot)
246 {
247 	if (sc_pkcs11_conf.atomic && slot) {
248 		struct sc_pkcs11_login *login = list_fetch(&slot->logins);
249 		while (login) {
250 			sc_mem_clear(login->pPin, login->ulPinLen);
251 			sc_mem_secure_free(login->pPin, login->ulPinLen);
252 			free(login);
253 			login = list_fetch(&slot->logins);
254 		}
255 	}
256 }
257 
258 
259 /* Session manipulation */
session_start_operation(struct sc_pkcs11_session * session,int type,sc_pkcs11_mechanism_type_t * mech,struct sc_pkcs11_operation ** operation)260 CK_RV session_start_operation(struct sc_pkcs11_session * session,
261 			      int type, sc_pkcs11_mechanism_type_t * mech, struct sc_pkcs11_operation ** operation)
262 {
263 	sc_pkcs11_operation_t *op;
264 
265 	if (context == NULL)
266 		return CKR_CRYPTOKI_NOT_INITIALIZED;
267 
268 	LOG_FUNC_CALLED(context);
269 	sc_log(context, "Session 0x%lx, type %d", session->handle, type);
270 	if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
271 		return CKR_ARGUMENTS_BAD;
272 
273 	if (session->operation[type] != NULL)
274 		return CKR_OPERATION_ACTIVE;
275 
276 	if (!(op = sc_pkcs11_new_operation(session, mech)))
277 		return CKR_HOST_MEMORY;
278 
279 	session->operation[type] = op;
280 	if (operation)
281 		*operation = op;
282 
283 	return CKR_OK;
284 }
285 
session_get_operation(struct sc_pkcs11_session * session,int type,sc_pkcs11_operation_t ** operation)286 CK_RV session_get_operation(struct sc_pkcs11_session * session, int type, sc_pkcs11_operation_t ** operation)
287 {
288 	sc_pkcs11_operation_t *op;
289 
290 	LOG_FUNC_CALLED(context);
291 
292 	if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
293 		return CKR_ARGUMENTS_BAD;
294 
295 	if (!(op = session->operation[type]))
296 		return CKR_OPERATION_NOT_INITIALIZED;
297 
298 	if (operation)
299 		*operation = op;
300 
301 	return CKR_OK;
302 }
303 
session_stop_operation(struct sc_pkcs11_session * session,int type)304 CK_RV session_stop_operation(struct sc_pkcs11_session * session, int type)
305 {
306 	if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
307 		return CKR_ARGUMENTS_BAD;
308 
309 	if (session->operation[type] == NULL)
310 		return CKR_OPERATION_NOT_INITIALIZED;
311 
312 	sc_pkcs11_release_operation(&session->operation[type]);
313 	return CKR_OK;
314 }
315 
attr_extract(CK_ATTRIBUTE_PTR pAttr,void * ptr,size_t * sizep)316 CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t * sizep)
317 {
318 	size_t size;
319 
320 	if (sizep) {
321 		size = *sizep;
322 		if (size < pAttr->ulValueLen)
323 			return CKR_ATTRIBUTE_VALUE_INVALID;
324 		*sizep = pAttr->ulValueLen;
325 	} else {
326 		switch (pAttr->type) {
327 		case CKA_CLASS:
328 			size = sizeof(CK_OBJECT_CLASS);
329 			break;
330 		case CKA_KEY_TYPE:
331 			size = sizeof(CK_KEY_TYPE);
332 			break;
333 		case CKA_PRIVATE:
334 		case CKA_TOKEN:
335 			size = sizeof(CK_BBOOL);
336 			break;
337 		case CKA_CERTIFICATE_TYPE:
338 			size = sizeof(CK_CERTIFICATE_TYPE);
339 			break;
340 		case CKA_VALUE_LEN:
341 		case CKA_MODULUS_BITS:
342 			size = sizeof(CK_ULONG);
343 			break;
344 		case CKA_OBJECT_ID:
345 			size = sizeof(struct sc_object_id);
346 			break;
347 		default:
348 			return CKR_FUNCTION_FAILED;
349 		}
350 		if (size != pAttr->ulValueLen)
351 			return CKR_ATTRIBUTE_VALUE_INVALID;
352 	}
353 	memcpy(ptr, pAttr->pValue, pAttr->ulValueLen);
354 	return CKR_OK;
355 }
356 
attr_find(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG type,void * ptr,size_t * sizep)357 CK_RV attr_find(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void *ptr, size_t * sizep)
358 {
359 	unsigned int n;
360 
361 	for (n = 0; n < ulCount; n++, pTemplate++) {
362 		if (pTemplate->type == type)
363 			break;
364 	}
365 
366 	if (n >= ulCount)
367 		return CKR_TEMPLATE_INCOMPLETE;
368 	return attr_extract(pTemplate, ptr, sizep);
369 }
370 
attr_find2(CK_ATTRIBUTE_PTR pTemp1,CK_ULONG ulCount1,CK_ATTRIBUTE_PTR pTemp2,CK_ULONG ulCount2,CK_ULONG type,void * ptr,size_t * sizep)371 CK_RV attr_find2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1,
372 		 CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2, CK_ULONG type, void *ptr, size_t * sizep)
373 {
374 	CK_RV rv;
375 
376 	rv = attr_find(pTemp1, ulCount1, type, ptr, sizep);
377 	if (rv != CKR_OK)
378 		rv = attr_find(pTemp2, ulCount2, type, ptr, sizep);
379 
380 	return rv;
381 }
382 
attr_find_and_allocate_ptr(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG type,void ** out,size_t * out_len)383 CK_RV attr_find_and_allocate_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void **out, size_t *out_len)
384 {
385 	void *ptr;
386 	size_t len;
387 	CK_RV rv;
388 
389 	if (!out || !out_len)
390 		return CKR_ARGUMENTS_BAD;
391 	len = *out_len;
392 
393 	rv = attr_find_ptr(pTemplate, ulCount, type, &ptr, &len);
394 	if (rv != CKR_OK)
395 		return rv;
396 
397 	*out = calloc(1, len);
398 	if (*out == NULL)
399 		return CKR_HOST_MEMORY;
400 
401 	memcpy(*out, ptr, len);
402 	*out_len = len;
403 
404 	return CKR_OK;
405 }
406 
attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG type,void ** ptr,size_t * sizep)407 CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void **ptr, size_t * sizep)
408 {
409 	unsigned int n;
410 
411 	for (n = 0; n < ulCount; n++, pTemplate++) {
412 		if (pTemplate->type == type)
413 			break;
414 	}
415 
416 	if (n >= ulCount)
417 		return CKR_TEMPLATE_INCOMPLETE;
418 
419 	if (sizep)
420 		*sizep = pTemplate->ulValueLen;
421 	*ptr = pTemplate->pValue;
422 	return CKR_OK;
423 }
424 
attr_find_ptr2(CK_ATTRIBUTE_PTR pTemp1,CK_ULONG ulCount1,CK_ATTRIBUTE_PTR pTemp2,CK_ULONG ulCount2,CK_ULONG type,void ** ptr,size_t * sizep)425 CK_RV attr_find_ptr2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1,
426 		 CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2, CK_ULONG type, void **ptr, size_t * sizep)
427 {
428 	CK_RV rv;
429 
430 	rv = attr_find_ptr(pTemp1, ulCount1, type, ptr, sizep);
431 	if (rv != CKR_OK)
432 		rv = attr_find_ptr(pTemp2, ulCount2, type, ptr, sizep);
433 
434 	return rv;
435 }
436 
attr_find_var(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG type,void * ptr,size_t * sizep)437 CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void *ptr, size_t * sizep)
438 {
439 	unsigned int n;
440 
441 	for (n = 0; n < ulCount; n++, pTemplate++) {
442 		if (pTemplate->type == type)
443 			break;
444 	}
445 
446 	if (n >= ulCount)
447 		return CKR_TEMPLATE_INCOMPLETE;
448 
449 	return attr_extract(pTemplate, ptr, sizep);
450 }
451 
load_pkcs11_parameters(struct sc_pkcs11_config * conf,sc_context_t * ctx)452 void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx)
453 {
454 	scconf_block *conf_block = NULL;
455 	char *unblock_style = NULL;
456 	char *create_slots_for_pins = NULL, *op, *tmp;
457 
458 	/* Set defaults */
459 	conf->max_virtual_slots = 16;
460 	if (strcmp(ctx->app_name, "onepin-opensc-pkcs11") == 0) {
461 		conf->slots_per_card = 1;
462 	} else {
463 		conf->slots_per_card = 4;
464 	}
465 	conf->atomic = 0;
466 	conf->lock_login = 0;
467 	conf->init_sloppy = 1;
468 	conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED;
469 	conf->create_puk_slot = 0;
470 	conf->create_slots_flags = SC_PKCS11_SLOT_CREATE_ALL;
471 
472 	conf_block = sc_get_conf_block(ctx, "pkcs11", NULL, 1);
473 	if (!conf_block)
474 		return;
475 
476 	/* contains the defaults, if there is a "pkcs11" config block */
477 	conf->max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->max_virtual_slots);
478 	conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card);
479 	conf->atomic = scconf_get_bool(conf_block, "atomic", conf->atomic);
480 	if (conf->atomic)
481 		conf->lock_login = 1;
482 	conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
483 	conf->init_sloppy = scconf_get_bool(conf_block, "init_sloppy", conf->init_sloppy);
484 
485 	unblock_style = (char *)scconf_get_str(conf_block, "user_pin_unblock_style", NULL);
486 	if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session"))
487 		conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN;
488 	else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context"))
489 		conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN;
490 	else if (unblock_style && !strcmp(unblock_style, "init_pin_in_so_session"))
491 		conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN;
492 
493 	conf->create_puk_slot = scconf_get_bool(conf_block, "create_puk_slot", conf->create_puk_slot);
494 
495 	create_slots_for_pins = (char *)scconf_get_str(conf_block, "create_slots_for_pins", "all");
496 	conf->create_slots_flags = 0;
497 	tmp = strdup(create_slots_for_pins);
498 	op = strtok(tmp, " ,");
499 	while (op) {
500 		if (!strcmp(op, "user"))
501 			conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_USER;
502 		else if (!strcmp(op, "sign"))
503 			conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_SIGN;
504 		else if (!strcmp(op, "all"))
505 			conf->create_slots_flags |= SC_PKCS11_SLOT_CREATE_ALL;
506 		op = strtok(NULL, " ,");
507 	}
508 	free(tmp);
509 
510 	sc_log(ctx, "PKCS#11 options: max_virtual_slots=%d slots_per_card=%d "
511 		 "lock_login=%d atomic=%d pin_unblock_style=%d "
512 		 "create_slots_flags=0x%X",
513 		 conf->max_virtual_slots, conf->slots_per_card,
514 		 conf->lock_login, conf->atomic, conf->pin_unblock_style,
515 		 conf->create_slots_flags);
516 }
517