Exemple #1
0
/*
 * Unblock a PIN.
 */
int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card,
             struct sc_pkcs15_object *so_pin_obj,
			 struct sc_pkcs15_object *pin_obj,
			 const u8 *puk, size_t puklen,
			 const u8 *newpin, size_t newpinlen)
{
	int r;
	sc_card_t *card;
	struct sc_pin_cmd_data data;
	struct sc_pkcs15_object *puk_obj;
	struct sc_pkcs15_auth_info *puk_info = NULL;
	struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;

	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_NOT_SUPPORTED;

	/* make sure the pins are in valid range */
	if ((r = _validate_pin(p15card, auth_info, newpinlen)) != SC_SUCCESS)
		return r;

	card = p15card->card;

    if (so_pin_obj)
    {
        puk_info = (struct sc_pkcs15_auth_info *)so_pin_obj->data;
    }
    else
    {
	    /* get pin_info object of the puk (this is a little bit complicated
	     * as we don't have the id of the puk (at least now))
	     * note: for compatibility reasons we give no error if no puk object
	     * is found */
	    /* first step: try to get the pkcs15 object of the puk */
	    r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj);
	    if (r >= 0 && puk_obj) {
		    /* second step:  get the pkcs15 info object of the puk */
		    puk_info = (struct sc_pkcs15_auth_info *)puk_obj->data;
	    }
	    if (!puk_info) {
		    sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to get puk object, using pin object instead!");
		    puk_info = auth_info;
	    }
    }
	
	/* make sure the puk is in valid range */
	if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS)
		return r;

	r = sc_lock(card);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed");
	/* the path in the pin object is optional */
	if (auth_info->path.len > 0) {
		r = sc_select_file(card, &auth_info->path, NULL);
		if (r)
			goto out;
	}

	/* set pin_cmd data */
	memset(&data, 0, sizeof(data));
	data.cmd             = SC_PIN_CMD_UNBLOCK;
	data.pin_type        = SC_AC_CHV;
	data.pin_reference   = auth_info->attrs.pin.reference;
    data.so_pin_reference= puk_info->attrs.pin.reference;
	data.pin1.data       = puk;
	data.pin1.len        = puklen;
	data.pin1.pad_char   = auth_info->attrs.pin.pad_char;
	data.pin1.min_length = auth_info->attrs.pin.min_length;
	data.pin1.max_length = auth_info->attrs.pin.max_length;
	data.pin1.pad_length = auth_info->attrs.pin.stored_length;
	data.pin2.data       = newpin;
	data.pin2.len        = newpinlen;
	data.pin2.pad_char   = puk_info->attrs.pin.pad_char;
	data.pin2.min_length = puk_info->attrs.pin.min_length;
	data.pin2.max_length = puk_info->attrs.pin.max_length;
	data.pin2.pad_length = puk_info->attrs.pin.stored_length;

	if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
		data.flags |= SC_PIN_CMD_NEED_PADDING;

	switch (auth_info->attrs.pin.type) {
	case SC_PKCS15_PIN_TYPE_BCD:
		data.pin1.encoding = SC_PIN_ENCODING_BCD;
		break;
	case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
		data.pin1.encoding = SC_PIN_ENCODING_ASCII;
		break;
	}

	switch (puk_info->attrs.pin.type) {
	case SC_PKCS15_PIN_TYPE_BCD:
		data.pin2.encoding = SC_PIN_ENCODING_BCD;
		break;
	case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
		data.pin2.encoding = SC_PIN_ENCODING_ASCII;
		break;
	}
	
	if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
		data.flags |= SC_PIN_CMD_USE_PINPAD;
		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
			data.pin1.prompt = "Please enter PUK";
			data.pin2.prompt = "Please enter new SO PIN";
		} else {
			data.pin1.prompt = "Please enter PUK";
			data.pin2.prompt = "Please enter new PIN";
		}
	}

	r = sc_pin_cmd(card, &data, &auth_info->tries_left);
	if (r == SC_SUCCESS)
		sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen);

out:
	sc_unlock(card);
	return r;
}
Exemple #2
0
/*
 * Verify a PIN.
 *
 * If the code given to us has zero length, this means we
 * should ask the card reader to obtain the PIN from the
 * reader's PIN pad
 */
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
			 struct sc_pkcs15_object *pin_obj,
			 const unsigned char *pincode, size_t pinlen)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
	int r;
	sc_card_t *card;
	struct sc_pin_cmd_data data;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN(%p;len:%i)", pincode, pinlen);

	/* TODO: verify other authentication objects */
	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_NOT_SUPPORTED;

	r = _validate_pin(p15card, auth_info, pinlen);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "PIN value do not conforms the PIN policy");

	card = p15card->card;

	r = sc_lock(card);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed");
	/* the path in the pin object is optional */
	if (auth_info->path.len > 0) {
		r = sc_select_file(card, &auth_info->path, NULL);
		if (r)
			goto out;
	}

	/* Initialize arguments */
	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;
	data.pin_type = auth_info->auth_method;
	data.pin_reference = auth_info->attrs.pin.reference;
	data.pin1.min_length = auth_info->attrs.pin.min_length;
	data.pin1.max_length = auth_info->attrs.pin.max_length;
	data.pin1.pad_length = auth_info->attrs.pin.stored_length;
	data.pin1.pad_char = auth_info->attrs.pin.pad_char;
	data.pin1.data = pincode;
	data.pin1.len = pinlen;

	if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
		data.flags |= SC_PIN_CMD_NEED_PADDING;

	switch (auth_info->attrs.pin.type) {
	case SC_PKCS15_PIN_TYPE_BCD:
		data.pin1.encoding = SC_PIN_ENCODING_BCD;
		break;
	case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
		data.pin1.encoding = SC_PIN_ENCODING_ASCII;
		break;
	default:
		/* assume/hope the card driver knows how to encode the pin */
		data.pin1.encoding = 0;
	}

	if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
		if (!pincode && !pinlen)
			data.flags |= SC_PIN_CMD_USE_PINPAD;
		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
			data.pin1.prompt = "Please enter SO PIN";
		else
			data.pin1.prompt = "Please enter PIN";
	}

	r = sc_pin_cmd(card, &data, &auth_info->tries_left);
	if (r == SC_SUCCESS)
		sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen);
out:
	sc_unlock(card);
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}
Exemple #3
0
/*
 * Change a PIN.
 */
int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
			 struct sc_pkcs15_object *pin_obj,
			 const u8 *oldpin, size_t oldpinlen,
			 const u8 *newpin, size_t newpinlen)
{
	int r;
	sc_card_t *card;
	struct sc_pin_cmd_data data;
	struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
	
	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_NOT_SUPPORTED;

	/* make sure the pins are in valid range */
	if ((r = _validate_pin(p15card, auth_info, oldpinlen)) != SC_SUCCESS)
		return r;
	if ((r = _validate_pin(p15card, auth_info, newpinlen)) != SC_SUCCESS)
		return r;

	card = p15card->card;
	r = sc_lock(card);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed");
	/* the path in the pin object is optional */
	if (auth_info->path.len > 0) {
		r = sc_select_file(card, &auth_info->path, NULL);
		if (r)
			goto out;
	}

	/* set pin_cmd data */
	memset(&data, 0, sizeof(data));
	data.cmd             = SC_PIN_CMD_CHANGE;
	data.pin_type        = SC_AC_CHV;
	data.pin_reference   = auth_info->attrs.pin.reference;
	data.pin1.data       = oldpin;
	data.pin1.len        = oldpinlen;
	data.pin1.pad_char   = auth_info->attrs.pin.pad_char;
	data.pin1.min_length = auth_info->attrs.pin.min_length;
	data.pin1.max_length = auth_info->attrs.pin.max_length;
	data.pin1.pad_length = auth_info->attrs.pin.stored_length;
	data.pin2.data       = newpin;
	data.pin2.len        = newpinlen;
	data.pin2.pad_char   = auth_info->attrs.pin.pad_char;
	data.pin2.min_length = auth_info->attrs.pin.min_length;
	data.pin2.max_length = auth_info->attrs.pin.max_length;
	data.pin2.pad_length = auth_info->attrs.pin.stored_length;

	if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
		data.flags |= SC_PIN_CMD_NEED_PADDING;

	switch (auth_info->attrs.pin.type) {
	case SC_PKCS15_PIN_TYPE_BCD:
		data.pin1.encoding = SC_PIN_ENCODING_BCD;
		data.pin2.encoding = SC_PIN_ENCODING_BCD;
		break;
	case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
		data.pin1.encoding = SC_PIN_ENCODING_ASCII;
		data.pin2.encoding = SC_PIN_ENCODING_ASCII;
		break;
	}
	
	if((!oldpin || !newpin) 
			&& p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
		data.flags |= SC_PIN_CMD_USE_PINPAD;
		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
			data.pin1.prompt = "Please enter SO PIN";
			data.pin2.prompt = "Please enter new SO PIN";
		} else {
			data.pin1.prompt = "Please enter PIN";
			data.pin2.prompt = "Please enter new PIN";
		}
	}

	r = sc_pin_cmd(card, &data, &auth_info->tries_left);
	if (r == SC_SUCCESS)
		sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen);

out:
	sc_unlock(card);
	return r;
}
Exemple #4
0
static void print_info(sc_card_t *card, sc_file_t *file)
{
	int r, tries_left;
	struct sc_pin_cmd_data data;
	sc_cardctl_sc_hsm_dkek_t dkekinfo;

	u8 major, minor, opt;

	major = file->prop_attr[file->prop_attr_len - 2];
	minor = file->prop_attr[file->prop_attr_len - 1];
	printf("Version              : %d.%d\n", (int)major, (int)minor);

	if (file->prop_attr_len > 2) {	/* Version >= 2.0 */
		opt = file->prop_attr[file->prop_attr_len - 4];
		if (opt != 0) {
			printf("Config options       :\n");
			if (opt & INIT_RRC_ENABLED) {
				printf("  User PIN reset with SO-PIN enabled\n");
			}
			if (opt & INIT_TRANSPORT_PIN) {
				printf("  Transport-PIN mode enabled\n");
			}
		}

		/* Try to update SO-PIN info from card */
		memset(&data, 0, sizeof(data));
		data.cmd = SC_PIN_CMD_GET_INFO;
		data.pin_type = SC_AC_CHV;
		data.pin_reference = ID_SO_PIN;

		r = sc_pin_cmd(card, &data, &tries_left);
		if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) {
			printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n");
		} else {
			if (tries_left == 0) {
				printf("SO-PIN locked\n");
			} else {
				printf("SO-PIN tries left    : %d\n", tries_left);
			}
			/* Try to update PIN info from card */
			memset(&data, 0, sizeof(data));
			data.cmd = SC_PIN_CMD_GET_INFO;
			data.pin_type = SC_AC_CHV;
			data.pin_reference = ID_USER_PIN;

			r = sc_pin_cmd(card, &data, &tries_left);
			if (r == SC_ERROR_CARD_CMD_FAILED) {
				printf("Public key authentication active.\n");
			} else if (r == SC_ERROR_REF_DATA_NOT_USABLE) {
				printf("Transport-PIN active. Please change to user selected PIN first.\n");
			} else {
				if (tries_left == 0) {
					printf("User PIN locked\n");
				} else {
					printf("User PIN tries left  : %d\n", tries_left);
				}
			}
		}
	} else {	/* Version < 2.0 */
		/* Try to update PIN info from card */
		memset(&data, 0, sizeof(data));
		data.cmd = SC_PIN_CMD_GET_INFO;
		data.pin_type = SC_AC_CHV;
		data.pin_reference = ID_USER_PIN;

		r = sc_pin_cmd(card, &data, &tries_left);

		if (r == SC_ERROR_REF_DATA_NOT_USABLE) {
			printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n");
		} else {
			if (tries_left == 0) {
				printf("User PIN locked\n");
			} else {
				printf("User PIN tries left  : %d\n", tries_left);
			}
		}
	}

	memset(&dkekinfo, 0, sizeof(dkekinfo));

	r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, (void *)&dkekinfo);

	if (r == SC_ERROR_INS_NOT_SUPPORTED) {			// Not supported or not initialized for key shares
		return;
	}

	if (r < 0) {
		fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, *) failed with %s\n", sc_strerror(r));
	}
	print_dkek_info(&dkekinfo);
}
static int do_verify(int argc, char **argv)
{
	const id2str_t typeNames[] = {
		{ SC_AC_CHV,	"CHV"	},
		{ SC_AC_AUT,	"KEY"	},
		{ SC_AC_AUT,	"AUT"	},
		{ SC_AC_PRO,	"PRO"	},
		{ SC_AC_NONE,	NULL, 	}
	};
	int r, tries_left = -1;
	u8 buf[64];
	size_t buflen = sizeof(buf), i;
	struct sc_pin_cmd_data data;
	int prefix_len = 0;

	if (argc < 1 || argc > 2)
		return usage(do_verify);

	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;

	data.pin_type = SC_AC_NONE;
	for (i = 0; typeNames[i].str; i++) {
		prefix_len = strlen(typeNames[i].str);
		if (strncasecmp(argv[0], typeNames[i].str, prefix_len) == 0) {
			data.pin_type = typeNames[i].id;
			break;
		}
	}
	if (data.pin_type == SC_AC_NONE) {
		printf("Invalid type.\n");
		return usage(do_verify);
	}
	if (sscanf(argv[0] + prefix_len, "%d", &data.pin_reference) != 1) {
		printf("Invalid key reference.\n");
		return usage(do_verify);
	}

	if (argc < 2) {
		if (card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
			printf("Please enter PIN on the reader's pin pad.\n");
			data.pin1.prompt = "Please enter PIN";
			data.flags |= SC_PIN_CMD_USE_PINPAD;
		}
		else {
			char *pin = NULL;
			size_t len = 0;

			printf("Please enter PIN: ");
			r = util_getpass(&pin, &len, stdin);
			if (r < 0) {
				printf("No PIN entered - aborting VERIFY.\n");
				return -1;
			}

			if (strlcpy((char *)buf, pin, sizeof(buf)) >= sizeof(buf)) {
				free(pin);
				printf("PIN too long - aborting VERIFY.\n");
				return -1;
			}
			free(pin);
			data.pin1.data = buf;
			data.pin1.len = strlen((char *)buf);
		}
	} else {
		r = parse_string_or_hexdata(argv[1], buf, &buflen);
		if (0 != r) {
			printf("Invalid key value.\n");
			return usage(do_verify);
		}
		data.pin1.data = buf;
		data.pin1.len = buflen;
	}
	r = sc_pin_cmd(card, &data, &tries_left);

	if (r) {
		if (r == SC_ERROR_PIN_CODE_INCORRECT) {
			if (tries_left >= 0)
				printf("Incorrect code, %d tries left.\n", tries_left);
			else
				printf("Incorrect code.\n");
		} else
			printf("Unable to verify PIN code: %s\n", sc_strerror(r));
		return -1;
	}
	printf("Code correct.\n");
	return 0;
}
Exemple #6
0
/*
 * Verify a PIN.
 *
 * If the code given to us has zero length, this means we
 * should ask the card reader to obtain the PIN from the
 * reader's PIN pad
 */
int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
			 struct sc_pkcs15_object *pin_obj,
			 const unsigned char *pincode, size_t pinlen)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
	int r;
	sc_card_t *card;
	struct sc_pin_cmd_data data;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "PIN(type:%X;method:%X;len:)", auth_info->auth_type, auth_info->auth_method, pinlen);

	if (pinlen > SC_MAX_PIN_SIZE)
		LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_LENGTH, "Invalid PIN size");

	card = p15card->card;

	/* Initialize arguments */
	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;
	data.pin_type = auth_info->auth_method;

	if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN)   {
		data.pin_reference = auth_info->attrs.pin.reference;
		data.pin1.min_length = auth_info->attrs.pin.min_length;
		data.pin1.max_length = auth_info->attrs.pin.max_length;
		data.pin1.pad_length = auth_info->attrs.pin.stored_length;
		data.pin1.pad_char = auth_info->attrs.pin.pad_char;
		data.pin1.data = pincode;
		data.pin1.len = pinlen;

		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
			data.flags |= SC_PIN_CMD_NEED_PADDING;

		switch (auth_info->attrs.pin.type) {
		case SC_PKCS15_PIN_TYPE_BCD:
			data.pin1.encoding = SC_PIN_ENCODING_BCD;
			break;
		case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
			data.pin1.encoding = SC_PIN_ENCODING_ASCII;
			break;
		default:
			/* assume/hope the card driver knows how to encode the pin */
			data.pin1.encoding = 0;
		}
	}
	else if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_AUTH_KEY)   {
		struct sc_pkcs15_object *skey_obj = NULL;
		struct sc_pkcs15_id *skey_id =  &auth_info->attrs.authkey.skey_id;
		struct sc_pkcs15_skey_info *skey_info = NULL;

		r = sc_pkcs15_find_skey_by_id(p15card, skey_id, &skey_obj);
		if (r)   {
			sc_log(ctx, "cannot find secret key with id:%s", sc_pkcs15_print_id(skey_id));
			LOG_FUNC_RETURN(ctx, r);
		}
		skey_info = (struct sc_pkcs15_skey_info *)skey_obj->data;

		sc_log(ctx, "found secret key '%s'", skey_obj->label);
		data.pin_reference = skey_info->key_reference;
	}

	if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
		if (!pincode && !pinlen)
			data.flags |= SC_PIN_CMD_USE_PINPAD;
		if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
			data.pin1.prompt = "Please enter SO PIN";
		else
			data.pin1.prompt = "Please enter PIN";
	}

	r = sc_lock(card);
	LOG_TEST_RET(ctx, r, "sc_lock() failed");

	/* the path in the pin object is optional */
	if ((auth_info->path.len > 0) || ((auth_info->path.aid.len > 0))) {
		r = sc_select_file(card, &auth_info->path, NULL);
		if (r)
			goto out;
	}

	r = sc_pin_cmd(card, &data, &auth_info->tries_left);
	sc_log(ctx, "PIN cmd result %i", r);
	if (r == SC_SUCCESS)
		sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen);
out:
	sc_unlock(card);
	LOG_FUNC_RETURN(ctx, r);
}
Exemple #7
0
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
{
	u8 buf[1024];
	sc_pkcs15_df_t *df;
	sc_pkcs15_object_t *p15_obj;
	sc_path_t path;
	struct sc_file *file = NULL;
	size_t len;
	int rv;
	int i;

	sc_context_t *ctx = p15card->card->ctx;
	LOG_FUNC_CALLED(ctx);

	/* Check for correct card atr */
	if (pteid_detect_card(p15card->card) != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;

	sc_log(p15card->card->ctx, "Selecting application DF");
	sc_format_path("4F00", &path);
	rv = sc_select_file(p15card->card, &path, &file);
	if (rv != SC_SUCCESS || !file)
		return SC_ERROR_INTERNAL;
	/* set the application DF */
	if (p15card->file_app)
		free(p15card->file_app);
	p15card->file_app = file;

	/* Load TokenInfo */
	len = sizeof(buf);
	rv = dump_ef(p15card->card, "4F005032", buf, &len);
	if (rv != SC_SUCCESS) {
		sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv);
		LOG_FUNC_RETURN(ctx, rv);
	}
	memset(p15card->tokeninfo, 0, sizeof(*p15card->tokeninfo));
	rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo,
				       buf, len);
	if (rv != SC_SUCCESS) {
		sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv);
		LOG_FUNC_RETURN(ctx, rv);
	}

	p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION
				  | SC_PKCS15_TOKEN_EID_COMPLIANT
				  | SC_PKCS15_TOKEN_READONLY;

	/* Load ODF */
	len = sizeof(buf);
	rv = dump_ef(p15card->card, "4F005031", buf, &len);
	if (rv != SC_SUCCESS) {
		sc_log(ctx, "Reading of ODF failed: %d", rv);
		LOG_FUNC_RETURN(ctx, rv);
	}
	rv = parse_odf(buf, len, p15card);
	if (rv != SC_SUCCESS) {
		sc_log(ctx, "Decoding of ODF failed: %d", rv);
		LOG_FUNC_RETURN(ctx, rv);
	}

	/* Decode EF.PrKDF, EF.PuKDF, EF.CDF and EF.AODF */
	for (df = p15card->df_list; df != NULL; df = df->next) {
		if (df->type == SC_PKCS15_PRKDF) {
			rv = sc_pkcs15_parse_df(p15card, df);
			if (rv != SC_SUCCESS) {
				sc_log(ctx,
				       "Decoding of EF.PrKDF (%s) failed: %d",
				       sc_print_path(&df->path), rv);
			}
		}
		if (df->type == SC_PKCS15_PUKDF) {
			rv = sc_pkcs15_parse_df(p15card, df);
			if (rv != SC_SUCCESS) {
				sc_log(ctx,
				       "Decoding of EF.PuKDF (%s) failed: %d",
				       sc_print_path(&df->path), rv);
			}
		}
		if (df->type == SC_PKCS15_CDF) {
			rv = sc_pkcs15_parse_df(p15card, df);
			if (rv != SC_SUCCESS) {
				sc_log(ctx,
				       "Decoding of EF.CDF (%s) failed: %d",
				       sc_print_path(&df->path), rv);
			}
		}
		if (df->type == SC_PKCS15_AODF) {
			rv = sc_pkcs15_parse_df(p15card, df);
			if (rv != SC_SUCCESS) {
				sc_log(ctx,
				       "Decoding of EF.AODF (%s) failed: %d",
				       sc_print_path(&df->path), rv);
			}
		}
	}

	p15_obj = p15card->obj_list;
	while (p15_obj != NULL) {
		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PRKDF) ) {
			struct sc_pkcs15_prkey_info *prkey_info = (sc_pkcs15_prkey_info_t *) p15_obj->data;
			prkey_info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
					| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
					| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
					| SC_PKCS15_PRKEY_ACCESS_LOCAL;
			p15_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE;
		}


		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_AODF) ) {
			static const char *pteid_pin_names[3] = {
			    "Auth PIN",
			    "Sign PIN",
			    "Address PIN"
			};

			struct sc_pin_cmd_data pin_cmd_data;
			struct sc_pkcs15_auth_info *pin_info = (sc_pkcs15_auth_info_t *) p15_obj->data;

			strlcpy(p15_obj->label, pteid_pin_names[pin_info->auth_id.value[0]-1], sizeof(p15_obj->label));

			pin_info->attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
			pin_info->tries_left = -1;
			pin_info->max_tries = 3;
			pin_info->auth_method = SC_AC_CHV;

			memset(&pin_cmd_data, 0, sizeof(pin_cmd_data));
			pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO;
			pin_cmd_data.pin_type = pin_info->attrs.pin.type;
			pin_cmd_data.pin_reference = pin_info->attrs.pin.reference;
			rv = sc_pin_cmd(p15card->card, &pin_cmd_data, NULL);
			if (rv == SC_SUCCESS) {
				pin_info->tries_left = pin_cmd_data.pin1.tries_left;
			}
		}
		/* Remove found public keys as cannot be read_binary()'d */
		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) {
			sc_pkcs15_object_t *puk = p15_obj;
			p15_obj = p15_obj->next;
			sc_pkcs15_remove_object(p15card, puk);
			sc_pkcs15_free_object(puk);
		} else {
			p15_obj = p15_obj->next;
		}
	}

	/* Add data objects */
	for (i = 0; i < 5; i++) {
		static const char *object_ids[5] = {"1", "2", "3", "4", "5"};
		static const char *object_labels[5] = {
			"Citizen Data",
			"Citizen Address Data",
			"Citizen Notepad",
			"SOD",
			"TRACE",
		};
		static const char *object_authids[5] = {NULL, "3", NULL, NULL, NULL};
		static const char *object_paths[5] = {
			"3f005f00ef02",
			"3f005f00ef05",
			"3f005f00ef07",
			"3f005f00ef06",
			"3F000003",
		};
		static const int object_flags[5] = {
			0,
			SC_PKCS15_CO_FLAG_PRIVATE,
			0,
			0,
			0,
		};
		struct sc_pkcs15_data_info obj_info;
		struct sc_pkcs15_object obj_obj;

		memset(&obj_info, 0, sizeof(obj_info));
		memset(&obj_obj, 0, sizeof(obj_obj));

		sc_pkcs15_format_id(object_ids[i], &obj_info.id);
		sc_format_path(object_paths[i], &obj_info.path);
		strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
		if (object_authids[i] != NULL)
			sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id);
		strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
		obj_obj.flags = object_flags[i];

		rv = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info);
		if (rv != SC_SUCCESS){
			sc_log(ctx, "Object add failed: %d", rv);
			break;
		}
	}

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static int do_verify(int argc, char **argv)
{
	const id2str_t typeNames[] = {
		{ SC_AC_CHV,	"CHV"	},
		{ SC_AC_AUT,	"KEY"	},
		{ SC_AC_AUT,	"AUT"	},
		{ SC_AC_PRO,	"PRO"	},
		{ SC_AC_NONE,	NULL, 	}
	};
	int r, tries_left = -1;
	u8 buf[64];
	size_t buflen = sizeof(buf), i;
	struct sc_pin_cmd_data data;

	if (argc < 1 || argc > 2)
		goto usage;

	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;

	data.pin_type = SC_AC_NONE;
	for (i = 0; typeNames[i].str; i++) {
		if (strncasecmp(argv[0], typeNames[i].str, 3) == 0) {
			data.pin_type = typeNames[i].id;
			break;
		}
	}
	if (data.pin_type == SC_AC_NONE) {
		printf("Invalid type.\n");
		goto usage;
	}
	if (sscanf(argv[0] + 3, "%d", &data.pin_reference) != 1) {
		printf("Invalid key reference.\n");
		goto usage;
	}

	if (argc < 2) {
		if (!(card->reader->capabilities & SC_READER_CAP_PIN_PAD)) {
			printf("Card reader or driver doesn't support PIN PAD\n");
			return -1;
		}
		printf("Please enter PIN on the reader's pin pad.\n");
		data.pin1.prompt = "Please enter PIN";
		data.flags |= SC_PIN_CMD_USE_PINPAD;
	} else {
		r = parse_string_or_hexdata(argv[1], buf, &buflen);
		if (0 != r) {
			printf("Invalid key value.\n");
			goto usage;
		}
		data.pin1.data = buf;
		data.pin1.len = buflen;
	}
	r = sc_pin_cmd(card, &data, &tries_left);

	if (r) {
		if (r == SC_ERROR_PIN_CODE_INCORRECT) {
			if (tries_left >= 0) 
				printf("Incorrect code, %d tries left.\n", tries_left);
			else
				printf("Incorrect code.\n");
		} else
			printf("Unable to verify PIN code: %s\n", sc_strerror(r));
		return -1;
	}
	printf("Code correct.\n");
	return 0;
usage:
	printf("Usage: verify <key type><key ref> [<pin>]\n");
	printf("Possible values of <key type>:\n");
	for (i = 0; typeNames[i].str; i++)
		printf("\t%s\n", typeNames[i].str);
	printf("Example: verify CHV2 31:32:33:34:00:00:00:00\n");
	printf("If key is omitted, card reader's keypad will be used to collect PIN.\n");
	return -1;
}
Exemple #9
0
static int unblock(sc_card_t* card, const char *so_pin, const char *user_pin) {
	int r;
	char *_so_pin = NULL, *_user_pin = NULL;
	size_t len;
	u8 key[24];
	struct sc_pin_cmd_data data;

	memset(&data, 0, sizeof(struct sc_pin_cmd_data));

	if (so_pin == NULL) {
		printf("============================================================\n");
		printf("WARNING\n");
		printf("Entering an incorrect admin key can break your card\n");
		printf("WARNING\n");
		printf("============================================================\n");
		printf("Enter admin key (48 hexadecimal characters) : ");
		util_getpass(&_so_pin, NULL, stdin);
		printf("\n");
	} else {
		_so_pin = (char *)so_pin;
	}

	len = sizeof(key);
	r = sc_hex_to_bin(_so_pin, key, &len);
	if (r < 0) {
		fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r));
		return -1;
	}

	if (len != 24) {
		fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n");
		return -1;
	}

	r = sc_card_ctl(card, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, (void *)key);
	if (r < 0) {
		fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, *) failed with %s\n", sc_strerror(r));
		return -1;
	}
	printf("Administrator authentication successful\n");
	printf("Setting the new PIN\n");

	if (user_pin == NULL) {
		printf("Enter User-PIN (4 - 16 characters) : ");
		util_getpass(&_user_pin, NULL, stdin);
		printf("\n");
	} else {
		_user_pin = (char *)user_pin;
	}

	data.pin_type = SC_AC_CHV;
	data.cmd = SC_PIN_CMD_UNBLOCK;
	data.pin2.len = strlen(_user_pin);
	data.pin2.data = (unsigned char*) _user_pin;
	data.pin_reference = 0x80;
	r = sc_pin_cmd(card, &data, NULL);
	if (r < 0) {
		fprintf(stderr, "reset pin failed with %s\n", sc_strerror(r));
		return -1;
	}
	printf("Unblock PIN done successfuly\n");
	// the card should have deauthenticated the admin, but to be sure:
	sc_logout(card);
	return 0;
}
static int do_verify(int argc, char **argv)
{
	struct {
		const char *	name;
		int		type;
	} typeNames[] = {
		{ "CHV",	SC_AC_CHV	},
		{ "KEY",	SC_AC_AUT	},
		{ "AUT",	SC_AC_AUT	},
		{ "PRO",	SC_AC_PRO	},
		{ NULL, 	SC_AC_NONE	}
	};
	int r, tries_left = -1;
	u8 buf[64];
	const char *s;
	size_t buflen = sizeof(buf), i;
	struct sc_pin_cmd_data data;

	if (argc < 1 || argc > 2)
		goto usage;

	memset(&data, 0, sizeof(data));
	data.cmd = SC_PIN_CMD_VERIFY;

	data.pin_type = SC_AC_NONE;
	for (i = 0; typeNames[i].name; i++) {
		if (strncasecmp(argv[0], typeNames[i].name, 3) == 0) {
			data.pin_type = typeNames[i].type;
			break;
		}
	}
	if (data.pin_type == SC_AC_NONE) {
		printf("Invalid type.\n");
		goto usage;
	}
	if (sscanf(argv[0] + 3, "%d", &data.pin_reference) != 1) {
		printf("Invalid key reference.\n");
		goto usage;
	}

	if (argc < 2) {
		if (!(card->reader->slot[0].capabilities & SC_SLOT_CAP_PIN_PAD)) {
			printf("Card reader or driver doesn't support PIN PAD\n");
			return -1;
		}
		printf("Please enter PIN on the reader's pin pad.\n");
		data.pin1.prompt = "Please enter PIN";
		data.flags |= SC_PIN_CMD_USE_PINPAD;
	} else if (argv[1][0] == '"') {
		for (s=argv[1]+1, i=0; i < sizeof(buf) && *s && *s != '"';i++) 
			buf[i] = *s++;
		data.pin1.data = buf;
		data.pin1.len = i;
	} else {
		r = sc_hex_to_bin(argv[1], buf, &buflen); 
		if (0 != r) {
			printf("Invalid key value.\n");
			goto usage;
		}
		data.pin1.data = buf;
		data.pin1.len = buflen;
	}
	r = sc_pin_cmd(card, &data, &tries_left);

	if (r) {
		if (r == SC_ERROR_PIN_CODE_INCORRECT) {
			if (tries_left >= 0) 
				printf("Incorrect code, %d tries left.\n", tries_left);
			else
				printf("Incorrect code.\n");
		} else
			printf("Unable to verify PIN code: %s\n", sc_strerror(r));
		return -1;
	}
	printf("Code correct.\n");
	return 0;
usage:
	printf("Usage: verify <key type><key ref> [<key in hex>]\n");
	printf("Possible values of <key type>:\n");
	for (i = 0; typeNames[i].name; i++)
		printf("\t%s\n", typeNames[i].name);
	printf("Example: verify CHV2 31:32:33:34:00:00:00:00\n");
	printf("If key is omitted, card reader's keypad will be used to collect PIN.\n");
	return -1;
}