コード例 #1
0
static int starcert_detect_card(sc_pkcs15_card_t *p15card)
{
	int       r;
	u8        buf[128];
	sc_path_t path;
	sc_card_t *card = p15card->card;

	/* check if we have the correct card OS */
	if (strcmp(card->name, "STARCOS SPK 2.3"))
		return SC_ERROR_WRONG_CARD;
	/* read EF_Info file */
	sc_format_path("3F00FE13", &path);
	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);
	if (r != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;
	r = sc_read_binary(card, 0, buf, 64, 0);
	if (r != 64)
		return SC_ERROR_WRONG_CARD;
	if (memcmp(buf + 24, STARCERT, strlen(STARCERT))) 
		return SC_ERROR_WRONG_CARD;

	return SC_SUCCESS;
}
コード例 #2
0
static int
gpk_read_rsa_key(sc_card_t *card, struct sc_pkcs15_pubkey_rsa *rsa)
{
    int	n, r;

    /* Read modulus and exponent */
    for (n = 2; ; n++) {
        sc_pkcs15_bignum_t *bn;
        u8		buffer[256];
        size_t		m;

        sc_ctx_suppress_errors_on(card->ctx);
        r = sc_read_record(card, n, buffer, sizeof(buffer),
                           SC_RECORD_BY_REC_NR);
        sc_ctx_suppress_errors_off(card->ctx);
        if (r < 1)
            break;

        if (buffer[0] == 0x01)
            bn = &rsa->modulus;
        else if  (buffer[0] == 0x07)
            bn = &rsa->exponent;
        else
            continue;
        bn->len  = r - 1;
        bn->data = (u8 *) malloc(bn->len);
        for (m = 0; m < bn->len; m++)
            bn->data[m] = buffer[bn->len - m];
    }

    return 0;
}
コード例 #3
0
static int atrust_acos_logout(struct sc_card *card)
{
	int r;
	struct sc_apdu apdu;
	const u8 mf_buf[2] = {0x3f, 0x00};

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x0C);
	apdu.le = 0;
	apdu.lc = 2;
	apdu.data    = mf_buf;
	apdu.datalen = 2;
	apdu.resplen = 0;
	
	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_transmit_apdu(card, &apdu);
	sc_ctx_suppress_errors_off(card->ctx);
	SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");

	if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
		/* the only possible reason for this error here is, afaik,
		 * that no MF exists, but then there's no need to logout
		 * => return SC_SUCCESS
		 */
		return SC_SUCCESS;
	return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
コード例 #4
0
/*
 * Create the PK file
 * XXX: Handle the UPDATE ACL = NEVER case just like for EFsc files
 */
static int
gpk_pkfile_create(sc_profile_t *profile, sc_card_t *card, sc_file_t *file)
{
    struct sc_file	*found = NULL;
    int		r;

    sc_ctx_suppress_errors_on(card->ctx);
    r = sc_select_file(card, &file->path, &found);
    sc_ctx_suppress_errors_off(card->ctx);
    if (r == SC_ERROR_FILE_NOT_FOUND) {
        r = sc_pkcs15init_create_file(profile, card, file);
        if (r >= 0)
            r = sc_select_file(card, &file->path, &found);
    } else {
        /* XXX: make sure the file has correct type and size? */
    }

    if (r >= 0)
        r = sc_pkcs15init_authenticate(profile, card,
                                       file, SC_AC_OP_UPDATE);
    if (found)
        sc_file_free(found);

    return r;
}
コード例 #5
0
static int dump_unusedspace(void)
{
	u8 *buf = NULL;
	size_t buf_len;
	sc_path_t path;
	sc_pkcs15_unusedspace_t *us;
	int r;

	if (p15card->file_unusedspace != NULL)
		path = p15card->file_unusedspace->path;
	else {
		path = p15card->file_app->path;
		sc_append_path_id(&path, (const u8 *) "\x50\x33", 2);
	}
	path.count = -1;

	sc_ctx_suppress_errors_on(p15card->card->ctx);
	r = sc_pkcs15_read_file(p15card, &path, &buf, &buf_len, NULL);
	sc_ctx_suppress_errors_off(p15card->card->ctx);
	if (r < 0) {
		if (r == SC_ERROR_FILE_NOT_FOUND) {
			printf("\nNo EF(UnusedSpace) file\n");
			r = 0;
		}
		else
			printf("\nError reading file \"%s\": %s\n",
				sc_print_path(&path), sc_strerror(r));
		goto err;
	}

	r = sc_pkcs15_parse_unusedspace(buf, buf_len, p15card);
	if (r != 0) {
		printf("\nError parsing EF(UnusedSpace): %s\n", sc_strerror(r));
		goto err;
	}

	if (p15card->unusedspace_list == NULL)
		printf("\nEF(UnusedSpace) file is empty\n");
	else {
		printf("\nContents of EF(UnusedSpace):\n");
		for (us = p15card->unusedspace_list; us != NULL; us = us->next)
		printf("  - path=%s, index=%d, length=%d  -- auth_id = %s\n",
			sc_print_path(&us->path), us->path.index, us->path.count,
			us->auth_id.len == 0 ? "<empty>" : sc_pkcs15_print_id(&us->auth_id));
	}

err:
	if (buf != NULL)
		free(buf);
	return r;
}
コード例 #6
0
static int acos_detect_card(sc_pkcs15_card_t *p15card)
{
	int       r;
	u8        buf[128];
	sc_path_t path;
	sc_card_t *card = p15card->card;

	/* check if we have the correct card OS */
	if (strncmp(card->name, "A-TRUST ACOS", strlen("A-TRUST ACOS")))
		return SC_ERROR_WRONG_CARD;
	/* read EF_CIN_CSN file */
	sc_format_path("DF71D001", &path);
	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);
	if (r != SC_SUCCESS)
		return SC_ERROR_WRONG_CARD;
	r = sc_read_binary(card, 0, buf, 8, 0);
	if (r != 8)
		return SC_ERROR_WRONG_CARD;

	return SC_SUCCESS;
}
コード例 #7
0
static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
{
	const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
	const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN
	    | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
	    | SC_PKCS15_PRKEY_USAGE_ENCRYPT
	    | SC_PKCS15_PRKEY_USAGE_DECRYPT;

	sc_card_t *card = p15card->card;
	sc_path_t path;
	sc_file_t *file;
	sc_pkcs15_id_t id, auth_id;
	unsigned char buffer[256];
	unsigned char ef_gdo[256];
	char serial[256];
	unsigned char certlen[2];
	int authority, change_sign = 0;
	struct sc_pkcs15_cert_info cert_info;
        struct sc_pkcs15_object    cert_obj;

	const char *label = "User Non-repudiation Certificate";
	const char *calabel = "CA Certificate";
	const char *authlabel = "User Authentication Certificate";

	const char *infocamere_cert_path[2] = {
		"DF01C000",
		"3F00000011111A02"
	};

	const char *infocamere_auth_certpath[2] = {
		"11111A02",
		"000011111B02"
	};

	const char *infocamere_cacert_path[2] = {
		"DF01C008",
		"000011114101"
	};

	const char *infocamere_auth_path[2] = {
		"3F001111",
		"3F0000001111"
	};

	const char *infocamere_nrepud_path[2] = {
		"3F00DF01",
		"3F0000001111"
	};

	const int infocamere_idpin_auth_obj[2] = {
		0x95,
		0x81
	};

	const int infocamere_idpin_nrepud_obj[2] = {
		0x99,
		0x81
	};

	const int infocamere_idprkey_auth_obj[2] = {
		0x9B,
		0x01
	};

	const int infocamere_idprkey_nrepud_obj[2] = {
		0x84,
		0x01
	};

	const char *authPIN = "Authentication PIN";
	const char *nonrepPIN = "Non-repudiation PIN";

	const char *authPRKEY = "Authentication Key";
	const char *nonrepPRKEY = "Non repudiation Key";

	const int flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
	    SC_PKCS15_PIN_FLAG_INITIALIZED |
	    SC_PKCS15_PIN_FLAG_NEEDS_PADDING;

	int r, len_iccsn, len_chn;

	sc_format_path("3F002F02", &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, &file);
	sc_ctx_suppress_errors_off(card->ctx);
	
	if (r != SC_SUCCESS || file->size > 255) {
		/* Not EF.GDO */
		return SC_ERROR_WRONG_CARD;
	}

	sc_read_binary(card, 0, ef_gdo, file->size, 0);

	if (ef_gdo[0] != 0x5A || file->size < 3) {
		/* Not EF.GDO */
		return SC_ERROR_WRONG_CARD;
	}

	len_iccsn = ef_gdo[1];

	memcpy(buffer, ef_gdo + 2, len_iccsn);

	sc_bin_to_hex(buffer, len_iccsn, serial, sizeof(serial), 0);

	if (file->size < (size_t) (len_iccsn + 5)) {
		/* Not CHN */
		return SC_ERROR_WRONG_CARD;
	}

	if (!
	    (ef_gdo[len_iccsn + 2] == 0x5F
	     && ef_gdo[len_iccsn + 3] == 0x20)) {
		/* Not CHN */
		return SC_ERROR_WRONG_CARD;
	}

	len_chn = ef_gdo[len_iccsn + 4];

	if (len_chn < 2 || len_chn > 8) {
		/* Length CHN incorrect */
		return SC_ERROR_WRONG_CARD;
	}

	if (!
	    (ef_gdo[len_iccsn + 5] == 0x12
	     && (ef_gdo[len_iccsn + 6] == 0x02
		 || ef_gdo[len_iccsn + 6] == 0x03))) {
		/* Not Infocamere Card */
		return SC_ERROR_WRONG_CARD;
	}

	set_string(&p15card->serial_number, serial);

	if (ef_gdo[len_iccsn + 6] == 0x02)
		set_string(&p15card->label, "Infocamere 1202 Card");
	else {
		set_string(&p15card->label, "Infocamere 1203 Card");
		change_sign = 1;
	}

	set_string(&p15card->manufacturer_id, "Infocamere");

	authority = 0;

	/* Get the authentication certificate length */

	sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);

	if (r >= 0) {

		sc_read_binary(card, 0, certlen, 2, 0);

		/* Now set the certificate offset/len */

		path.index = 2;
		path.count = (certlen[1] << 8) + certlen[0];

		memset(&cert_info, 0, sizeof(cert_info));
                memset(&cert_obj,  0, sizeof(cert_obj));

		sc_pkcs15_format_id("1", &cert_info.id);
        	cert_info.authority = authority;
        	cert_info.path = path;
		strlcpy(cert_obj.label, authlabel, sizeof(cert_obj.label));
	        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        	if (r < 0)
        		return SC_ERROR_INTERNAL;

		/* XXX: the IDs for the key/pin in case of the 1203 type 
		 * are wrong, therefore I disable them for now -- Nils */
		if (!change_sign) {    
		/* add authentication PIN */

                sc_format_path(infocamere_auth_path[ef_gdo[len_iccsn+6]-2], &path);
                
		sc_pkcs15_format_id("1", &id);
		sc_pkcs15emu_add_pin(p15card, &id,
                                authPIN, &path, infocamere_idpin_auth_obj[ef_gdo[len_iccsn+6]-2],
                                SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
                                5, 8, flags, 3, 0, 
				SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);

		/* add authentication private key */

		auth_id.value[0] = 1;
		auth_id.len = 1;

		sc_pkcs15emu_add_prkey(p15card, &id,
				authPRKEY,
				SC_PKCS15_TYPE_PRKEY_RSA, 
				1024, authprkey_usage,
				&path, infocamere_idprkey_auth_obj[ef_gdo[len_iccsn+6]-2],
				&auth_id, SC_PKCS15_CO_FLAG_PRIVATE);
		}

	}

	/* Get the non-repudiation certificate length */

	sc_format_path(infocamere_cert_path[ef_gdo[len_iccsn+6]-2], &path);

	if (sc_select_file(card, &path, NULL) < 0)
		{
		return SC_ERROR_INTERNAL;
		}

	sc_read_binary(card, 0, certlen, 2, 0);

	/* Now set the certificate offset/len */
	path.index = 2;
	path.count = (certlen[1] << 8) + certlen[0];
	
        memset(&cert_info, 0, sizeof(cert_info));
        memset(&cert_obj,  0, sizeof(cert_obj));

	sc_pkcs15_format_id("2", &cert_info.id);

        cert_info.authority = authority;
        cert_info.path = path;
        strlcpy(cert_obj.label, label, sizeof(cert_obj.label));
        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

	r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        if (r < 0)
        	return SC_ERROR_INTERNAL;

	/* Get the CA certificate length */

	authority = 1;

	sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path);

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);

	if (r >= 0) {
		size_t len;

		sc_read_binary(card, 0, certlen, 2, 0);

		len = (certlen[1] << 8) + certlen[0];

		if (len != 0) {
			/* Now set the certificate offset/len */
			path.index = 2;
			path.count = len;

			memset(&cert_info, 0, sizeof(cert_info));
	                memset(&cert_obj,  0, sizeof(cert_obj));

			sc_pkcs15_format_id("3", &cert_info.id);
	        	cert_info.authority = authority;
	        	cert_info.path = path;
	        	strlcpy(cert_obj.label, calabel, sizeof(cert_obj.label));
		        cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;

			r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
        		if (r < 0)
        		return SC_ERROR_INTERNAL;
		}
	}

        /* add non repudiation PIN */

	sc_format_path(infocamere_nrepud_path[ef_gdo[len_iccsn+6]-2], &path);

	sc_pkcs15_format_id("2", &id);
	sc_pkcs15emu_add_pin(p15card, &id,
		nonrepPIN, &path, infocamere_idpin_nrepud_obj[ef_gdo[len_iccsn+6]-2],
		SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0,
		SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);


	/* add non repudiation private key */

	auth_id.value[0] = 2;
	auth_id.len = 1;

	sc_pkcs15emu_add_prkey(p15card, &id, nonrepPRKEY,
			       SC_PKCS15_TYPE_PRKEY_RSA, 
                               1024, prkey_usage,
                               &path, infocamere_idprkey_nrepud_obj[ef_gdo[len_iccsn+6]-2],
                               &auth_id, SC_PKCS15_CO_FLAG_PRIVATE);


	/* return to MF */
	sc_format_path("3F00", &path);
	r = sc_select_file(card, &path, NULL);
	if (r != SC_SUCCESS)
		return r;

	if (change_sign) {
		/* save old signature funcs */
		set_security_env = card->ops->set_security_env;
		/* set new one */
		card->ops->set_security_env = set_sec_env;
		card->ops->compute_signature = do_sign;
	}

	return SC_SUCCESS;
}
コード例 #8
0
static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
{
	unsigned char *buf = NULL;
	int    err, ok = 0;
	size_t len;
	sc_path_t tmppath;
	sc_card_t    *card = p15card->card;
	sc_context_t *ctx  = card->ctx;
	sc_pkcs15_tokeninfo_t tokeninfo;

	if (ctx->debug > 4)
		sc_debug(ctx, "trying normal pkcs15 processing\n");

	/* Enumerate apps now */
	if (card->app_count < 0) {
		err = sc_enum_apps(card);
		if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) {
			sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err));
			goto end;
		}
	}
	p15card->file_app = sc_file_new();
	if (p15card->file_app == NULL) {
		err = SC_ERROR_OUT_OF_MEMORY;
		goto end;
	}
	sc_format_path("3F005015", &p15card->file_app->path);
	if (card->app_count > 0) {
		const sc_app_info_t *info;
		
		info = sc_find_pkcs15_app(card);
		if (info != NULL) {
			if (info->path.len)
				p15card->file_app->path = info->path;
			if (info->ddo != NULL)
				parse_ddo(p15card, info->ddo, info->ddo_len);
		}
	}

	/* Check if pkcs15 directory exists */
	sc_ctx_suppress_errors_on(card->ctx);
	err = sc_select_file(card, &p15card->file_app->path, NULL);
#if 1
	/* If the above test failed on cards without EF(DIR),
	 * try to continue read ODF from 3F005031. -aet
	 */
	if ((err == SC_ERROR_FILE_NOT_FOUND) &&
	    (card->app_count < 1)) {
		sc_format_path("3F00", &p15card->file_app->path);
		err = SC_NO_ERROR;
	}
#endif
	sc_ctx_suppress_errors_off(card->ctx);
	if (err < 0)
		goto end;

	if (p15card->file_odf == NULL) {
		/* check if an ODF is present; suppress errors as we
		 * don't know yet whether we have a pkcs15 card */
		tmppath = p15card->file_app->path;
		sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2);
		sc_ctx_suppress_errors_on(card->ctx);
		err = sc_select_file(card, &tmppath, &p15card->file_odf);
		sc_ctx_suppress_errors_off(card->ctx);
		
	} else {
		tmppath = p15card->file_odf->path;
		sc_file_free(p15card->file_odf);
		p15card->file_odf = NULL;
		err = sc_select_file(card, &tmppath, &p15card->file_odf);
	}
	if (err != SC_SUCCESS) {
		char pbuf[SC_MAX_PATH_STRING_SIZE];

		int r = sc_path_print(pbuf, sizeof(pbuf), &tmppath);
		if (r != SC_SUCCESS)
			pbuf[0] = '\0';

		sc_debug(ctx, "EF(ODF) not found in '%s'\n", pbuf);
		goto end;
	}

	if ((len = p15card->file_odf->size) == 0) {
		sc_error(card->ctx, "EF(ODF) is empty\n");
		goto end;
	}
	buf = malloc(len);
	if(buf == NULL)
		return SC_ERROR_OUT_OF_MEMORY;
	err = sc_read_binary(card, 0, buf, len, 0);
	if (err < 0)
		goto end;
	if (err < 2) {
		err = SC_ERROR_PKCS15_APP_NOT_FOUND;
		goto end;
	}
	len = err;
	if (parse_odf(buf, len, p15card)) {
		err = SC_ERROR_PKCS15_APP_NOT_FOUND;
		sc_error(card->ctx, "Unable to parse ODF\n");
		goto end;
	}
	free(buf);
	buf = NULL;

	if (card->ctx->debug) {
		sc_pkcs15_df_t *df;

		sc_debug(card->ctx, "The following DFs were found:\n");
		for (df = p15card->df_list; df; df = df->next) {
			char pbuf[SC_MAX_PATH_STRING_SIZE];

			int r = sc_path_print(pbuf, sizeof(pbuf), &df->path);
			if (r != SC_SUCCESS)
				pbuf[0] = '\0';

			sc_debug(card->ctx,
				"  DF type %u, path %s, index %u, count %d\n",
				df->type, pbuf, df->path.index, df->path.count);
		}
	}

	if (p15card->file_tokeninfo == NULL) {
		tmppath = p15card->file_app->path;
		sc_append_path_id(&tmppath, (const u8 *) "\x50\x32", 2);
	} else {
		tmppath = p15card->file_tokeninfo->path;
		sc_file_free(p15card->file_tokeninfo);
		p15card->file_tokeninfo = NULL;
	}
	err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
	if (err)
		goto end;

	if ((len = p15card->file_tokeninfo->size) == 0) {
		sc_error(card->ctx, "EF(TokenInfo) is empty\n");
		goto end;
	}
	buf = malloc(len);
	if(buf == NULL)
		return SC_ERROR_OUT_OF_MEMORY;
	err = sc_read_binary(card, 0, buf, len, 0);
	if (err < 0)
		goto end;
	if (err <= 2) {
		err = SC_ERROR_PKCS15_APP_NOT_FOUND;
		goto end;
	}

	memset(&tokeninfo, 0, sizeof(tokeninfo));
	err = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t)err);
	if (err != SC_SUCCESS)
		goto end;
	p15card->version         = tokeninfo.version;
	p15card->label           = tokeninfo.label;
	p15card->serial_number   = tokeninfo.serial_number;
	p15card->manufacturer_id = tokeninfo.manufacturer_id;
	p15card->last_update     = tokeninfo.last_update;
	p15card->flags           = tokeninfo.flags;
	p15card->preferred_language = tokeninfo.preferred_language;
	p15card->seInfo          = tokeninfo.seInfo;
	p15card->num_seInfo      = tokeninfo.num_seInfo;

	/* for cardos cards initialized by Siemens: sign with decrypt */
	if (strcmp(p15card->card->driver->short_name,"cardos") == 0
                && ( strcmp(p15card->manufacturer_id,"Siemens AG (C)") == 0
			|| strcmp(p15card->manufacturer_id,"Prime") == 0 ))
		p15card->flags |= SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT;

	ok = 1;
end:
	if(buf != NULL)
		free(buf);
	if (!ok) {
		sc_pkcs15_card_clear(p15card);
		return err;
	}

	return SC_SUCCESS;
}
コード例 #9
0
/** atrust_acos_set_security_env
 * sets the security enviroment
 * \param card pointer to the sc_card object
 * \param env pointer to a sc_security_env object
 * \param se_num not used here
 * \return SC_SUCCESS on success or an error code
 *
 * This function sets the security enviroment (using the 
 * command MANAGE SECURITY ENVIROMENT). In case a COMPUTE SIGNATURE
 * operation is requested , this function tries to detect whether
 * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE must be used for signature
 * calculation.
 */
static int atrust_acos_set_security_env(struct sc_card *card,
				    const struct sc_security_env *env,
				    int se_num)
{
	u8              *p, *pp, keyID;
	int              r, operation = env->operation;
	struct sc_apdu   apdu;
	u8               sbuf[SC_MAX_APDU_BUFFER_SIZE];
	atrust_acos_ex_data *ex_data = (atrust_acos_ex_data *)card->drv_data;

	p     = sbuf;
	keyID = env->key_ref[0];

	/* copy key reference, if present */
	if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
		if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
			*p++ = 0x83;
		else
			*p++ = 0x84;
		*p++ = env->key_ref_len;
		memcpy(p, env->key_ref, env->key_ref_len);
		p += env->key_ref_len;
	}
	pp = p;
	if (operation == SC_SEC_OPERATION_DECIPHER){
		if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
			*p++ = 0x80;
			*p++ = 0x01;
			*p++ = 0x02;
		} else
			return SC_ERROR_INVALID_ARGUMENTS;
		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81,
		               0xb8);
		apdu.data    = sbuf;
		apdu.datalen = p - sbuf;
		apdu.lc      = p - sbuf;
		apdu.le      = 0;
		r = sc_transmit_apdu(card, &apdu);
		SC_TEST_RET(card->ctx, r, "APDU transmit failed");
		if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
			SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
		return SC_SUCCESS;
	}
	/* try COMPUTE SIGNATURE */
	if (operation == SC_SEC_OPERATION_SIGN && (
	    env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 ||
	    env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)) {
		if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
			*p++ = 0x80;
			*p++ = 0x01;
			*p++ = env->algorithm_ref & 0xFF;
		} else if (env->flags & SC_SEC_ENV_ALG_PRESENT &&
		            env->algorithm == SC_ALGORITHM_RSA) {
			/* set the method to use based on the algorithm_flags */
			*p++ = 0x80;
			*p++ = 0x01;
			if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
				if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
					*p++ = 0x12;
				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
					*p++ = 0x22;
				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
					*p++ = 0x32;
				else {
					/* can't use COMPUTE SIGNATURE =>
					 * try INTERNAL AUTHENTICATE */
					p = pp;
					operation = SC_SEC_OPERATION_AUTHENTICATE;
					goto try_authenticate;
				}
			} else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796) {
				if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
					*p++ = 0x11;
				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
					*p++ = 0x21;
				else
					return SC_ERROR_INVALID_ARGUMENTS;
			} else
				return SC_ERROR_INVALID_ARGUMENTS;
		}
		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xb6);
		apdu.data    = sbuf;
		apdu.datalen = p - sbuf;
		apdu.lc      = p - sbuf;
		apdu.le      = 0;
		/* suppress errors, as don't know whether to use 
		 * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
		sc_ctx_suppress_errors_on(card->ctx);
		r = sc_transmit_apdu(card, &apdu);
		sc_ctx_suppress_errors_off(card->ctx);
		SC_TEST_RET(card->ctx, r, "APDU transmit failed");
		if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
			ex_data->fix_digestInfo = 0;
			ex_data->sec_ops        = SC_SEC_OPERATION_SIGN;
			return SC_SUCCESS;
		}
		/* reset pointer */
		p = pp;
		/* doesn't work => try next op */
		operation = SC_SEC_OPERATION_AUTHENTICATE;
	}
try_authenticate:
	/* try INTERNAL AUTHENTICATE */
	if (operation == SC_SEC_OPERATION_AUTHENTICATE && 
	    env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
		*p++ = 0x80;
		*p++ = 0x01;
		*p++ = 0x01;
		
		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xa4);
		apdu.data    = sbuf;
		apdu.datalen = p - sbuf;
		apdu.lc      = p - sbuf;
		apdu.le      = 0;
		r = sc_transmit_apdu(card, &apdu);
		SC_TEST_RET(card->ctx, r, "APDU transmit failed");
		if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
			SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
		ex_data->fix_digestInfo = env->algorithm_flags;
		ex_data->sec_ops        = SC_SEC_OPERATION_AUTHENTICATE;
		return SC_SUCCESS;
	}

	return SC_ERROR_INVALID_ARGUMENTS;
}
コード例 #10
0
static int
gpk_pkfile_update_public(struct sc_profile *profile,
                         sc_card_t *card, struct pkpart *part)
{
    struct pkcomp	*pe;
    unsigned char	buffer[256];
    unsigned int	m, n, tag;
    int		r = 0, found;

    if (card->ctx->debug > 1)
        sc_debug(card->ctx, "Updating public key elements\n");

    /* If we've been given a key with public parts, write them now */
    for (n = 2; n < 256; n++) {
        sc_ctx_suppress_errors_on(card->ctx);
        r = sc_read_record(card, n, buffer, sizeof(buffer),
                           SC_RECORD_BY_REC_NR);
        sc_ctx_suppress_errors_off(card->ctx);
        if (r < 0) {
            r = 0;
            break;
        }

        /* Check for bad record */
        if (r < 2) {
            sc_error(card->ctx,
                     "key file format error: "
                     "record %u too small (%u bytes)\n",
                     n, r);
            return SC_ERROR_OBJECT_NOT_VALID;
        }

        tag = buffer[0];

        for (m = 0, found = 0; m < part->count; m++) {
            pe = part->components + m;
            if (pe->tag == tag) {
                r = sc_update_record(card, n,
                                     pe->data, pe->size,
                                     SC_RECORD_BY_REC_NR);
                if (r < 0)
                    return r;
                pe->tag = 0; /* mark as stored */
                found++;
                break;
            }
        }

        if (!found && card->ctx->debug)
            sc_debug(card->ctx, "GPK unknown PK tag %u\n", tag);
    }

    /* Write all remaining elements */
    for (m = 0; r >= 0 && m < part->count; m++) {
        pe = part->components + m;
        if (pe->tag != 0)
            r = sc_append_record(card, pe->data, pe->size, 0);
    }

    return r;
}
コード例 #11
0
/*
 * Set up the public key record for a signature only public key
 */
static int
gpk_pkfile_init_public(sc_profile_t *profile, sc_card_t *card, sc_file_t *file,
                       unsigned int algo, unsigned int bits,
                       unsigned int usage)
{
    const sc_acl_entry_t *acl;
    sc_file_t	*tmp = NULL;
    u8		sysrec[7], buffer[256];
    unsigned int	n, npins;
    int		r, card_type;

    /* Find out what sort of GPK we're using */
    if ((r = sc_card_ctl(card, SC_CARDCTL_GPK_VARIANT, &card_type)) < 0)
        return r;

    /* Set up the system record */
    memset(sysrec, 0, sizeof(sysrec));

    /* Mapping keyUsage to sysrec[2]:
     * 	0x00	sign & unwrap
     * 	0x10	sign only
     * 	0x20	unwrap only
     * 	0x30	CA key
     *
     * We start with a value of 0x30.
     * If the key allows decryption, clear the sign only bit.
     * Likewise, if it allows signing, clear the unwrap only bit.
     */
    sysrec[2] = 0x30;
    if (usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP))
        sysrec[2] &= ~0x10;
    if (usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))
        sysrec[2] &= ~0x20;
    if (sysrec[2] == 0x30) {
        sc_error(card->ctx, "Key usage should specify at least one of sign or decipher");
        return SC_ERROR_INVALID_ARGUMENTS;
    }

    /* Set the key size and algorithm */
    if ((r = gpk_pkfile_keybits(bits, &sysrec[1])) < 0
            || (r = gpk_pkfile_keyalgo(algo, &sysrec[5])) < 0)
        return r;

    /* Set PIN protection if requested.
     * As the crypto ACLs are stored inside the file,
     * we have to get them from the profile here. */
    r = sc_profile_get_file_by_path(profile, &file->path, &tmp);
    if (r < 0)
        return r;
    /* Fix up PIN references in file ACL */
    if ((r = sc_pkcs15init_fixup_file(profile, tmp)) < 0)
        goto out;

    acl = sc_file_get_acl_entry(tmp, SC_AC_OP_CRYPTO);
    for (npins = 0; acl; acl = acl->next) {
        if (acl->method == SC_AC_NONE
                || acl->method == SC_AC_NEVER)
            continue;
        if (acl->method != SC_AC_CHV) {
            sc_error(card->ctx,
                     "Authentication method not "
                     "supported for private key files.\n");
            r = SC_ERROR_NOT_SUPPORTED;
            goto out;
        }
        if (++npins >= 2) {
            sc_error(card->ctx,
                     "Too many pins for PrKEY file!\n");
            r = SC_ERROR_NOT_SUPPORTED;
            goto out;
        }
        sysrec[2] += 0x40;
        sysrec[3] >>= 4;
        sysrec[3] |= acl->key_ref << 4;
    }

    /* compute checksum - yet another slightly different
     * checksum algorithm courtesy of Gemplus */
    if (card_type >= SC_CARD_TYPE_GPK_GPK8000) {
        /* This is according to the gpk reference manual */
        sysrec[6] = 0xA5;
    } else {
        /* And this is what you have to use for the GPK4000 */
        sysrec[6] = 0xFF;
    }
    for (n = 0; n < 6; n++)
        sysrec[6] ^= sysrec[n];

    sc_ctx_suppress_errors_on(card->ctx);
    r = sc_read_record(card, 1, buffer, sizeof(buffer),
                       SC_RECORD_BY_REC_NR);
    sc_ctx_suppress_errors_off(card->ctx);
    if (r >= 0) {
        if (r != 7 || buffer[0] != 0) {
            sc_error(card->ctx,
                     "first record of public key file is not Lsys0");
            return SC_ERROR_OBJECT_NOT_VALID;
        }

        r = sc_update_record(card, 1, sysrec, sizeof(sysrec),
                             SC_RECORD_BY_REC_NR);
    } else {
        r = sc_append_record(card, sysrec, sizeof(sysrec), 0);
    }

out:
    if (tmp)
        sc_file_free(tmp);
    return r;
}
コード例 #12
0
int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card,
                              sc_pkcs15emu_opt_t *opts)
{
    static const struct {
        const char *card, *manufacturer;
    } cardlist[]= {
        {"Netkey E4 Card", "TeleSec GmbH"},
        {"SignTrust Card", "Deutsche Post"},
        {"DATEV classic", "DATEV"},
        {"Smartkey Card TypA", "Kobil GmbH"},
        {"Smartkey Card TypB", "Kobil GmbH"},
        {"Chipkarte JLU Giessen", "Kobil GmbH"}
    };
    static struct {
        int         flags;
        const int   type, id, writable;
        const char *path;
        const char *label;
    } certlist[]= {
        {0, 1, 0x45, 0, "DF01C000",     "Telesec Signatur Zertifikat"},
        {3, 1, 0x45, 1, "DF014331",     "Signatur Zertifikat 1"},
        {3, 1, 0x45, 1, "DF014332",     "Signatur Zertifikat 2"},
        {1, 1, 0x46, 0, "DF01C100",     "Telesec Authentifizierungs Zertifikat"},
        {3, 1, 0x46, 1, "DF014371",     "Authentifizierungs Zertifikat 1"},
        {3, 1, 0x46, 1, "DF014372",     "Authentifizierungs Zertifikat 2"},
        {1, 1, 0x47, 0, "DF01C200",     "Telesec Verschluesselungs Zertifikat"},
        {3, 1, 0x47, 1, "DF0143B1",     "Verschluesselungs Zertifikat 1"},
        {3, 1, 0x47, 1, "DF0143B2",     "Verschluesselungs Zertifikat 2"},
        {1, 1, 0x48, 1, "DF06C000",     "SigG Zertifikat 1"},
        {1, 1, 0x48, 1, "DF064331",     "SigG Zertifikat 2"},
        {1, 1, 0x48, 1, "DF064332",     "SigG Zertifikat 3"},
        {1, 1, 0x49, 1, "41014352",     "W2K Logon Zertifikat"},
        {0, 2, 0x45, 1, "8000DF01C000", "SignTrust Signatur Zertifikat"},
        {1, 2, 0x46, 1, "800082008220", "SignTrust Verschluesselungs Zertifikat"},
        {1, 2, 0x47, 1, "800083008320", "SignTrust Authentifizierungs Zertifikat"},
        {0, 3, 0x45, 0, "3000C500",     "DATEV Signatur Zertifikat"},
        {1, 3, 0x46, 0, "DF02C200",     "DATEV Verschluesselungs Zertifikat"},
        {1, 3, 0x47, 0, "DF02C500",     "DATEV Authentifizierungs Zertifikat"},
        {0, 4, 0x45, 1, "41004352",     "Smartkey Zertifikat 1"},
        {0, 4, 0x46, 1, "41004353",     "Smartkey Zertifikat 2"},
        {0, 5, 0x45, 1, "41014352",     "Smartkey Zertifikat 1"},
        {0, 5, 0x46, 1, "41014353",     "Smartkey Zertifikat 2"},
        {0, 6, 0x45, 1, "41004352",     "UniCard Giessen Zertifikat"},
        {0, 0, 0, 0, NULL, NULL}
    };
    static const struct {
        int           type, id, auth_id;
        const char   *path;
        unsigned char key_reference;
        const char   *label;
    } keylist[]= {
        {1, 0x45, 4, "DF015331",     0x80, "Signatur Schluessel"},
        {1, 0x46, 3, "DF015371",     0x82, "Authentifizierungs Schluessel"},
        {1, 0x47, 3, "DF0153B1",     0x81, "Verschluesselungs Schluessel"},
        {1, 0x48, 5, "DF065331",     0x80, "SigG Schluessel"},
        {1, 0x49, 1, "41015103",     0x83, "W2K Logon Schluessel"},
        {2, 0x45, 1, "8000DF015331", 0x80, "Signatur Schluessel"},
        {2, 0x46, 2, "800082008210", 0x80, "Verschluesselungs Schluessel"},
        {2, 0x47, 3, "800083008310", 0x80, "Authentifizierungs Schluessel"},
        {3, 0x45, 1, "30005371",     0x82, "Signatur Schluessel"},
        {3, 0x46, 1, "DF0253B1",     0x81, "Verschluesselungs Schluessel"},
        {3, 0x47, 1, "DF025371",     0x82, "Authentifizierung Schluessel"},
        {4, 0x45, 1, "41005103",     0x83, "Smartkey Schluessel 1"},
        {4, 0x46, 1, "41005104",     0x84, "Smartkey Schluessel 2"},
        {5, 0x45, 1, "41015103",     0x83, "Smartkey Schluessel 1"},
        {5, 0x46, 1, "41015104",     0x84, "Smartkey Schluessel 2"},
        {6, 0x45, 1, "3F004100",     0x83, "UniCard Giessen Schluessel"},
        {0, 0, 0, NULL, 0, NULL}
    };
    static const struct {
        int           type, id, auth_id, min_length;
        unsigned char reference;
        const char   *path;
        const char   *label;
        int           flags;
    } pinlist[]= {
        {   1, 1, 2, 6, 0x00, "5000", "globale PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
        },
        {   1, 2, 0, 8, 0x01, "5001", "globale PUK",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN
        },
        {   1, 3, 1, 6, 0x80, "DF015080", "Netkey PIN0",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   1, 4, 1, 6, 0x81, "DF015081", "Netkey PIN1",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   1, 5, 0, 6, 0x81, "DF065081", "SigG PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   2, 1, 0, 6, 0x81, "8000DF010000", "Signatur PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   2, 2, 0, 6, 0x81, "800082000040", "Verschluesselungs PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   2, 3, 0, 6, 0x81, "800083000040", "Authentifizierungs PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL |
            SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {   3, 1, 0, 6, 0x01, "5001", "globale PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
        },
        {   4, 1, 2, 6, 0x00, "5000", "globale PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
        },
        {   4, 2, 0, 8, 0x01, "5008", "globale PUK",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN
        },
        {   5, 1, 2, 6, 0x00, "5000", "globale PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
        },
        {   5, 2, 0, 8, 0x01, "5008", "globale PUK",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED |
            SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN
        },
        {   6, 1, 0, 6, 0x00, "4100", "globale PIN",
            SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED
        },
        {0, 0, 0, 0, 0, NULL, NULL, 0}
    };
    sc_card_t         *card = p15card->card;
    sc_context_t      *ctx = p15card->card->ctx;
    sc_path_t          path;
    sc_file_t         *file;
    sc_serial_number_t serialnr;
    char               serial[30];
    int                i, j, found, r, usage, cardtype;

    /* check if we have the correct card OS unless SC_PKCS15EMU_FLAGS_NO_CHECK */
    i=(opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK);
    if (!i && strcmp(card->name, "TCOS")) return SC_ERROR_WRONG_CARD;

    /* get the card serial number */
    r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr);
    if (r < 0) {
        sc_debug(ctx, "unable to get ICCSN\n");
        r = SC_ERROR_WRONG_CARD;
        goto failed;
    }
    sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0);
    serial[19] = '\0';
    set_string(&p15card->serial_number, serial);

    /* detect cardtype and certificates */
    cardtype=0;
    for(i=0; certlist[i].id; ++i) {
        if(cardtype && certlist[i].type!=cardtype) continue;
        if(!cardtype && (certlist[i].flags&1)) continue;
        if(!cardtype && ctx->debug>=2) sc_debug(ctx, "Testing %s\n",cardlist[certlist[i].type-1].card);
        if(ctx->debug>=2) sc_debug(ctx, "Testing Cert %s, %s\n", certlist[i].path, certlist[i].label);

        sc_format_path(certlist[i].path, &path);
        sc_ctx_suppress_errors_on(ctx);
        r = sc_select_file(card, &path, NULL);
        sc_ctx_suppress_errors_off(ctx);
        if(r<0) continue;
        cardtype=certlist[i].type;
        certlist[i].flags |= 4;
    }
    if(ctx->debug >= 1) sc_debug(ctx, "Cardtype=%d, %s\n", cardtype, cardlist[cardtype-1].card);
    if(cardtype<1 || cardtype>(int)(sizeof(cardlist)/sizeof(cardlist[0]))) {
        r = SC_ERROR_WRONG_CARD;
        goto failed;
    }
    set_string(&p15card->label, cardlist[cardtype-1].card);
    set_string(&p15card->manufacturer_id, cardlist[cardtype-1].manufacturer);

    /* insert certificates */
    for(found=1; found;) {
        for(i=found=0; certlist[i].id && !found; ++i) if(certlist[i].flags&4) found=certlist[i].id;
        for(j=0; j<2; ++j) for(i=0; certlist[i].id; ++i) {
                struct sc_pkcs15_cert_info cert_info;
                struct sc_pkcs15_object    cert_obj;
                unsigned char cert[20];

                if(certlist[i].id!=found) continue;
                if((certlist[i].flags&2) == 2*j) continue;
                if(!(certlist[i].flags&4)) continue;
                certlist[i].flags-=4;

                sc_format_path(certlist[i].path, &path);
                if(sc_select_file(card, &path, NULL)<0) continue;

                /* read first 20 bytes of certificate, first two bytes
                * must be 0x30 0x82, otherwise this is an empty cert-file
                */
                r = sc_read_binary(card, 0, cert, sizeof(cert), 0);
                if(r<0 || cert[0]!=0x30 || cert[1]!=0x82) continue;

                if(ctx->debug>=1) {
                    sc_debug(ctx,"Cert %02X %s, %s\n",certlist[i].id,certlist[i].path,certlist[i].label);
                }

                /* Telesec-Certificates are prefixed by an OID,
                * for example 06:03:55:04:24. so use appropriate offset
                */
                if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82) {
                    path.index=6+cert[5];
                    path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4;
                } else {
                    path.index=0;
                    path.count=(cert[2]<<8) + cert[3] + 4;
                }

                memset(&cert_info, 0, sizeof(cert_info));
                cert_info.id.len      = 1;
                cert_info.id.value[0] = certlist[i].id;
                cert_info.authority   = 0;
                cert_info.path        = path;

                memset(&cert_obj, 0, sizeof(cert_obj));
                strlcpy(cert_obj.label, certlist[i].label, sizeof(cert_obj.label));
                cert_obj.flags = certlist[i].writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0;

                r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
                if (r < 0) {
                    sc_debug(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", certlist[i].path);
                    r = SC_ERROR_INTERNAL;
                    goto failed;
                }
            }
    }

    for(i=0; keylist[i].id; ++i) {
        struct sc_pkcs15_prkey_info prkey_info;
        struct sc_pkcs15_object     prkey_obj;

        if(keylist[i].type!=cardtype) continue;

        sc_format_path(keylist[i].path, &path);
        sc_ctx_suppress_errors_on(ctx);
        r = sc_select_file(card, &path, &file);
        sc_ctx_suppress_errors_off(ctx);
        if (r < 0) continue;
        if(ctx->debug >= 1) sc_debug(ctx,"Key %02X %s, %s\n",keylist[i].id,keylist[i].path,keylist[i].label);

        usage = SC_PKCS15_PRKEY_USAGE_SIGN;
        if (file->prop_attr[1] & 0x04) usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT;
        if (file->prop_attr[1] & 0x08) usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;

        memset(&prkey_info, 0, sizeof(prkey_info));
        prkey_info.id.len         = 1;
        prkey_info.id.value[0]    = keylist[i].id;
        prkey_info.usage          = usage;
        prkey_info.native         = 1;
        prkey_info.key_reference  = keylist[i].key_reference;
        prkey_info.modulus_length = 1024;
        sc_format_path(keylist[i].path, &prkey_info.path);

        memset(&prkey_obj, 0, sizeof(prkey_obj));
        strlcpy(prkey_obj.label, keylist[i].label, sizeof(prkey_obj.label));
        prkey_obj.flags            = SC_PKCS15_CO_FLAG_PRIVATE;
        prkey_obj.auth_id.len      = 1;
        prkey_obj.auth_id.value[0] = keylist[i].auth_id;

        r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
        sc_file_free(file);
        if (r < 0) {
            sc_debug(ctx, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", keylist[i].path);
            r = SC_ERROR_INTERNAL;
            goto failed;
        }
    }

    for(i=0; pinlist[i].id; ++i) {
        struct sc_pkcs15_pin_info pin_info;
        struct sc_pkcs15_object   pin_obj;

        if(pinlist[i].type && pinlist[i].type!=cardtype) continue;

        sc_format_path(pinlist[i].path, &path);
        sc_ctx_suppress_errors_on(ctx);
        r = sc_select_file(card, &path, &file);
        sc_ctx_suppress_errors_off(ctx);
        if (r < 0) continue;
        if(ctx->debug >= 1) sc_debug(ctx, "PIN %02X %s, %s\n", pinlist[i].id,pinlist[i].path,pinlist[i].label);

        memset(&pin_info, 0, sizeof(pin_info));
        pin_info.auth_id.len      = 1;
        pin_info.auth_id.value[0] = pinlist[i].id;
        pin_info.reference        = pinlist[i].reference;
        pin_info.flags            = pinlist[i].flags;
        pin_info.type             = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
        pin_info.min_length       = pinlist[i].min_length;
        pin_info.stored_length    = 16;
        pin_info.max_length       = 16;
        pin_info.pad_char         = '\0';
        pin_info.tries_left       = file->prop_attr[3];
        sc_format_path(pinlist[i].path, &pin_info.path);

        memset(&pin_obj, 0, sizeof(pin_obj));
        strlcpy(pin_obj.label, pinlist[i].label, sizeof(pin_obj.label));
        pin_obj.flags            = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
        pin_obj.auth_id.len      = pinlist[i].auth_id ? 0 : 1;
        pin_obj.auth_id.value[0] = pinlist[i].auth_id;

        r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
        sc_file_free(file);
        if (r < 0) {
            sc_debug(ctx, "sc_pkcs15emu_add_pin_obj(%s) failed\n", pinlist[i].path);
            r = SC_ERROR_INTERNAL;
            goto failed;
        }
    }

    /* return to MF */
    sc_format_path("3F00", &path);
    r = sc_select_file(card, &path, NULL);

failed:
    if (r < 0)
        sc_debug(ctx, "PKCS15-emulation for TCOS based preformatted failed: %s\n", sc_strerror(r));
    return r;
}
コード例 #13
0
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{

	/* The cert objects will return all the data */
const objdata objects[] = {
	{"1", "Card Capability Container", 
			"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
	{"2", "Card Holder Unique Identifier",
			"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
	{"3", "Unsigned Card Holder Unique Identifier",
			"2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0},
	{"4", "X.509 Certificate for PIV Authentication",
			"2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0},
	{"5", "Card Holder Fingerprints",
			"2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
	{"6", "Printed Information",
			"2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
	{"7", "Card Holder Facial Image", 
			"2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
	{"8", "X.509 Certificate for Digital Signature",
			"2.16.840.1.101.3.7.2.1.0",  NULL, "0100", 0},
	{"9", "X.509 Certificate for Key Management", 
			"2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
	{"10","X.509 Certificate for Card Authentication",
			"2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
	{"11", "Security Object",
			"2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0},
	{NULL, NULL, NULL, NULL, NULL, 0}
};
	/* 
	 * NIST 800-73-1 is proposing to lift the restriction on 
	 * requering pin protected certs. Thus the default will be to 
	 * not require this. But there are a number of test cards 
	 * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
	 * to be set. 
	 */
	/* certs will be pulled out from the cert objects */
	cdata certs[] = {
		{"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0},

		{"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0},
		{"3", "Certificate for Key Management", 0, "0102cece", 0, 0},
		{"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0},
		{NULL, NULL, 0, NULL, 0, 0}
	};

	const pindata pins[] = {
		{ "1", "PIV Card Holder pin", "", 0x80,
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  8, 4, 8, 
		  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL, 
		  -1, 0xFF,
		  SC_PKCS15_CO_FLAG_PRIVATE },
		{ "2", "PIV PUK", "", 0x81, 
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  8, 4, 8, 
		  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
		  SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, 
		  -1, 0xFF, 
		  SC_PKCS15_CO_FLAG_PRIVATE },
		/* there are some more key, but dont need for now */
		/* The admin 9b might fall in here */
		{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	};


	/*
	 * The size of the key or the algid is not really known
	 * but can be derived from the certificates. 
	 * the cert, pubkey and privkey are a set. 
	 * Key usages bits taken from pkcs15v1_1 Table 2
	 */
	pubdata pubkeys[] = {

		{ "1", "PIV AUTH pubkey", 0000, 
			 	SC_PKCS15_PRKEY_USAGE_ENCRYPT |
			 	SC_PKCS15_PRKEY_USAGE_WRAP |
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
			"9A06", 0x9A, "1", 0, 0},
		{ "2", "SIGN pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_ENCRYPT |
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
				SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
			"9C06", 0x9C, "1", 0, 0},
		{ "3", "KEY MAN pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_WRAP,
			"9D06", 0x9D, "1", 0, 0},
		{ "4", "CARD AUTH pubkey", 0000, 
				SC_PKCS15_PRKEY_USAGE_VERIFY |
				SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, 
			"9E06", 0x9E, "0", 0, 0},  /* no pin, and avail in contactless */
		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0}
		
	};

	prdata prkeys[] = {
		{ "1", "PIV AUTH key", 0000, 
				SC_PKCS15_PRKEY_USAGE_DECRYPT |
				SC_PKCS15_PRKEY_USAGE_UNWRAP |
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
			"", 0x9A, "1", 0},
		{ "2", "SIGN key", 0000, 
				SC_PKCS15_PRKEY_USAGE_DECRYPT |
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
				SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
			"", 0x9C, "1", 0},
		{ "3", "KEY MAN key", 0000, 
				SC_PKCS15_PRKEY_USAGE_UNWRAP,
			"", 0x9D, "1", 0},
		{ "4", "CARD AUTH key", 0000, 
				SC_PKCS15_PRKEY_USAGE_SIGN |
				SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
			"", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */
		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
	};

	int    r, i;
	sc_card_t *card = p15card->card;
	sc_file_t *file_out = NULL;
	int exposed_cert[4] = {1, 0, 0, 0};
	sc_serial_number_t serial;
	char buf[SC_MAX_SERIALNR * 2 + 1];

	SC_FUNC_CALLED(card->ctx, 1);

	/* could read this off card if needed */

	/* CSP does not like a - in the name */
	p15card->label = strdup("PIV_II");
	p15card->manufacturer_id = strdup(MANU_ID);

	/*
	 * get serial number 
	 * We will use the FASC-N from the CHUID
	 * Note we are not verifying CHUID, belongs to this card
	 * but need serial number for Mac tokend 
	 */

	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
	sc_ctx_suppress_errors_off(card->ctx);
	if (r < 0) {
		sc_debug(card->ctx,"sc_card_ctl rc=%d",r);
		p15card->serial_number = strdup("00000000");
	} else {
		sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
		p15card->serial_number = strdup(buf);
	}

	sc_debug(card->ctx, "PIV-II adding objects...");

	/* set other objects */
	for (i = 0; objects[i].label; i++) {
		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(objects[i].id, &obj_info.id);
		sc_format_path(objects[i].path, &obj_info.path);

		/* We could make sure the object is on the card */
		/* But really don't need to do this now */
//		sc_ctx_suppress_errors_on(card->ctx);
//		r = sc_select_file(card, &obj_info.path, NULL);
//		sc_ctx_suppress_errors_off(card->ctx);
//		if (r == SC_ERROR_FILE_NOT_FOUND)
//			continue; 
			
		strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
		if (r != SC_SUCCESS)
			return r;

		if (objects[i].auth_id)
			sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id);

		strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		obj_obj.flags = objects[i].obj_flags;
		
		r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, 
			&obj_obj, &obj_info); 
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r);
	}

	/*
	 * certs, pubkeys and priv keys are related and we assume
	 * they are in order 
	 * We need to read the cert, get modulus and keylen 
	 * We use those for the pubkey, and priv key objects. 
	 * If no cert, then see if pubkey (i.e. we are initilizing,
	 * and the pubkey is in a file,) then add pubkey and privkey
	 * If no cert and no pubkey, skip adding them. 
 
	 */
	/* set certs */
	sc_debug(card->ctx, "PIV-II adding certs...");
	for (i = 0; certs[i].label; i++) {
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object    cert_obj;
		sc_pkcs15_der_t   cert_der;
		sc_pkcs15_cert_t *cert_out;
		
		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj,  0, sizeof(cert_obj));
	
		sc_pkcs15_format_id(certs[i].id, &cert_info.id);
		cert_info.authority = certs[i].authority;
		sc_format_path(certs[i].path, &cert_info.path);

		strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		cert_obj.flags = certs[i].obj_flags;

		/* see if we have a cert */

		/* use a &file_out so card-piv will read cert if present */
		sc_ctx_suppress_errors_on(card->ctx);
		r = sc_pkcs15_read_file(p15card, &cert_info.path, 
				&cert_der.value, &cert_der.len, &file_out);
		sc_ctx_suppress_errors_off(card->ctx);
		if (file_out) {
			sc_file_free(file_out);
			file_out = NULL;
		}

		if (r) { 
			sc_debug(card->ctx, "No cert found,i=%d", i);
			continue;
		}

		certs[i].found = 1;
		/* cache it using the PKCS15 emulation objects */
		/* as it does not change */
               	if (cert_der.value) {
               	 	cert_info.value.value = cert_der.value;
                       	cert_info.value.len = cert_der.len;
                       	cert_info.path.len = 0; /* use in mem cert from now on */
               	}
		/* following will find the cached cert in cert_info */
		r =  sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out);
		if (r < 0) {
			sc_debug(card->ctx, "Failed to read/parse the certificate r=%d",r);
			continue;
		}
		/* TODO support DSA keys */
		if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
			/* save modulus_len in pub and priv */
			pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
			prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
		}
		sc_pkcs15_free_certificate(cert_out);

		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		if (r < 0) {
			sc_error(card->ctx, " Failed to add cert obj r=%d",r);
			continue;
		}
	}

	/* set pins */
	sc_debug(card->ctx, "PIV-II adding pins...");
	for (i = 0; pins[i].label; i++) {
		struct sc_pkcs15_pin_info pin_info;
		struct sc_pkcs15_object   pin_obj;

		memset(&pin_info, 0, sizeof(pin_info));
		memset(&pin_obj,  0, sizeof(pin_obj));

		sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
		pin_info.reference     = pins[i].ref;
		pin_info.flags         = pins[i].flags;
		pin_info.type          = pins[i].type;
		pin_info.min_length    = pins[i].minlen;
		pin_info.stored_length = pins[i].storedlen;
		pin_info.max_length    = pins[i].maxlen;
		pin_info.pad_char      = pins[i].pad_char;
		sc_format_path(pins[i].path, &pin_info.path);
		pin_info.tries_left    = -1;

		strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
		pin_obj.flags = pins[i].obj_flags;

		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r);
	}



	/* set public keys */
	/* We may only need this during initialzation when genkey
	 * gets the pubkey, but it can not be read from the card 
	 * at a later time. The piv-tool can stach in file 
	 */ 
	sc_debug(card->ctx, "PIV-II adding pub keys...");
	for (i = 0; pubkeys[i].label; i++) {
		struct sc_pkcs15_pubkey_info pubkey_info;
		struct sc_pkcs15_object     pubkey_obj;
		struct sc_pkcs15_pubkey *p15_key;

		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

		memset(&pubkey_info, 0, sizeof(pubkey_info));
		memset(&pubkey_obj,  0, sizeof(pubkey_obj));


		sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id);
		pubkey_info.usage         = pubkeys[i].usage;
		pubkey_info.native        = 1;
		pubkey_info.key_reference = pubkeys[i].ref;

		sc_format_path(pubkeys[i].path, &pubkey_info.path);

		strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		pubkey_obj.flags = pubkeys[i].obj_flags;
		

		if (pubkeys[i].auth_id)
			sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);

		if (certs[i].found == 0) { /*  no cert found */
			sc_debug(card->ctx,"No cert for this pub key i=%d",i);
			/* TODO DSA */
			pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
			pubkey_obj.data = &pubkey_info;
			sc_ctx_suppress_errors_on(card->ctx);
			r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
			sc_ctx_suppress_errors_off(card->ctx);
				pubkey_obj.data = NULL;
				sc_debug(card->ctx," READING PUB KEY r=%d",r);
			if (r < 0 ) {
				continue;
			}
			/* Only get here if no cert, and the card-piv.c found 
			 * there is a pub key file. This only happens when trying
			 * initializing a card and have set env to point at file  
			 */
			if (p15_key->algorithm == SC_ALGORITHM_RSA) {
			/* save modulus_len in pub and priv */
			pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
			prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
			pubkeys[i].found = 1;
			}

		}
		pubkey_info.modulus_length = pubkeys[i].modulus_len;
		strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		/* TODO DSA keys */
		r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r); /* should not fail */

		pubkeys[i].found = 1;
	}


	/* set private keys */
	sc_debug(card->ctx, "PIV-II adding private keys...");
	for (i = 0; prkeys[i].label; i++) {
		struct sc_pkcs15_prkey_info prkey_info;
		struct sc_pkcs15_object     prkey_obj;

		if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
			continue;

		memset(&prkey_info, 0, sizeof(prkey_info));
		memset(&prkey_obj,  0, sizeof(prkey_obj));

		if (certs[i].found == 0 && pubkeys[i].found == 0)
			continue; /* i.e. no cert or pubkey */
		
		sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
		prkey_info.usage         = prkeys[i].usage;
		prkey_info.native        = 1;
		prkey_info.key_reference = prkeys[i].ref;
		prkey_info.modulus_length= prkeys[i].modulus_len;
		/* The cert or pubkey should have filled modulus_len */
		/* TODO DSA keys */
		sc_format_path(prkeys[i].path, &prkey_info.path);

		strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

		prkey_obj.flags = prkeys[i].obj_flags;

		if (prkeys[i].auth_id)
			sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);

		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
		if (r < 0)
			SC_FUNC_RETURN(card->ctx, 1, r);
	}

	SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
}
コード例 #14
0
static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card)
{
	const cdata certs[] = {
		{"C.CH.EKEY", 0, "DF71C001","1", 0},/* Decryption Certificate */
#if 0
		{"C.CH.DS",   0, "DF70C002","2", 0},/* Signature Certificate */
#endif
		{NULL, 0, NULL, NULL, 0}
	};

	const pindata pins[] = {
		{ "01", "PIN.DEC", "3F00DF71", 0x81, /* Decryption PIN */
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  4, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00,
		  SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
#if 0
		{ "02", "PIN.SIG", "3F00DF70", 0x81, /* Signature PIN */
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  6, 6, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00,
		  SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, 
		{ "03", "PIN.INF", "3F00DF71", 0x83, /* Infobox PIN */
		  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
		  4, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
		  SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00,
		  SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
#endif
		{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} 
	};

	const prdata prkeys[] = {
		{ "1", "SK.CH.EKEY", 1536,
			SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP,
		  "", /* do not specify file here to prevent reset of security state */
		  0x88, "01", SC_PKCS15_CO_FLAG_PRIVATE},
#if 0
		{ "2", "SK.CH.DS", 192,
			SC_PKCS15_PRKEY_USAGE_SIGN,
		  "", /* do not specify file here to prevent reset of security state */
		  0x88, "02", SC_PKCS15_CO_FLAG_PRIVATE},
#endif
		{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
	};

	int    r, i;
	u8     buf[256];
	char   buf2[256];
	sc_path_t path;
	sc_file_t *file = NULL;
	sc_card_t *card = p15card->card;

	/* get serial number */

	/* read EF_CIN_CSN file */
	sc_format_path("DF71D001", &path);
	sc_ctx_suppress_errors_on(card->ctx);
	r = sc_select_file(card, &path, NULL);
	sc_ctx_suppress_errors_off(card->ctx);
	if (r != SC_SUCCESS)
		return SC_ERROR_INTERNAL;
	r = sc_read_binary(card, 0, buf, 8, 0);
	if (r != 8)
		return SC_ERROR_INTERNAL;
	r = sc_bin_to_hex(buf, 8, buf2, sizeof(buf2), 0);
	if (r != SC_SUCCESS)
		return SC_ERROR_INTERNAL;
	if (p15card->serial_number)
		free(p15card->serial_number);
	p15card->serial_number = (char *) malloc(strlen(buf2) + 1);
	if (!p15card->serial_number)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->serial_number, buf2);

	/* the TokenInfo version number */
	p15card->version = 0;

	/* manufacturer ID */
	if (p15card->manufacturer_id)
		free(p15card->manufacturer_id);
	p15card->manufacturer_id = (char *) malloc(strlen(MANU_ID) + 1);
	if (!p15card->manufacturer_id)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->manufacturer_id, MANU_ID);

	/* card label */
	if (p15card->label)
		free(p15card->label);
	p15card->label = (char *) malloc(strlen(CARD_LABEL) + 1);
	if (!p15card->label)
		return SC_ERROR_INTERNAL;
	strcpy(p15card->label, CARD_LABEL);

	/* set certs */
	for (i = 0; certs[i].label; i++) {
		struct sc_pkcs15_cert_info cert_info;
		struct sc_pkcs15_object    cert_obj;

		memset(&cert_info, 0, sizeof(cert_info));
		memset(&cert_obj,  0, sizeof(cert_obj));

		sc_pkcs15_format_id(certs[i].id, &cert_info.id);
		cert_info.authority = certs[i].authority;
		sc_format_path(certs[i].path, &cert_info.path);
		if (!get_cert_len(card, &cert_info.path))
			/* skip errors */
			continue;

		strlcpy(cert_obj.label, certs[i].label, sizeof(cert_obj.label));
		cert_obj.flags = certs[i].obj_flags;

		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
	}
	/* set pins */
	for (i = 0; pins[i].label; i++) {
		struct sc_pkcs15_pin_info pin_info;
		struct sc_pkcs15_object   pin_obj;

		memset(&pin_info, 0, sizeof(pin_info));
		memset(&pin_obj,  0, sizeof(pin_obj));

		sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
		pin_info.reference     = pins[i].ref;
		pin_info.flags         = pins[i].flags;
		pin_info.type          = pins[i].type;
		pin_info.min_length    = pins[i].minlen;
		pin_info.stored_length = pins[i].storedlen;
		pin_info.max_length    = pins[i].maxlen;
		pin_info.pad_char      = pins[i].pad_char;
		sc_format_path(pins[i].path, &pin_info.path);
		pin_info.tries_left    = -1;

		strlcpy(pin_obj.label, pins[i].label, sizeof(pin_obj.label));
		pin_obj.flags = pins[i].obj_flags;

		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
	}
	/* set private keys */
	for (i = 0; prkeys[i].label; i++) {
		struct sc_pkcs15_prkey_info prkey_info;
		struct sc_pkcs15_object     prkey_obj;

		memset(&prkey_info, 0, sizeof(prkey_info));
		memset(&prkey_obj,  0, sizeof(prkey_obj));

		sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
		prkey_info.usage         = prkeys[i].usage;
		prkey_info.native        = 1;
		prkey_info.key_reference = prkeys[i].ref;
		prkey_info.modulus_length= prkeys[i].modulus_len;
		sc_format_path(prkeys[i].path, &prkey_info.path);

		strlcpy(prkey_obj.label, prkeys[i].label, sizeof(prkey_obj.label));
		prkey_obj.flags = prkeys[i].obj_flags;
		if (prkeys[i].auth_id)
			sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);

		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
		if (r < 0)
			return SC_ERROR_INTERNAL;
	}
		
	/* select the application DF */
	sc_format_path("DF71", &path);
	r = sc_select_file(card, &path, &file);
	if (r != SC_SUCCESS || !file)
		return SC_ERROR_INTERNAL;
	/* set the application DF */
	if (p15card->file_app)
		free(p15card->file_app);
	p15card->file_app = file;

	return SC_SUCCESS;
}