Example #1
0
File: dir.c Project: AktivCo/OpenSC
static int update_single_record(sc_card_t *card, sc_app_info_t *app)
{
	u8 *rec;
	size_t rec_size;
	int r;

	r = encode_dir_record(card->ctx, app, &rec, &rec_size);
	if (r)
		return r;
	if (app->rec_nr > 0)
		r = sc_update_record(card, (unsigned int)app->rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
	else if (app->rec_nr == 0) {
		/* create new record entry */
		r = sc_append_record(card, rec, rec_size, 0);
		if (r == SC_ERROR_NOT_SUPPORTED) {
			/* if the card doesn't support APPEND RECORD we try a
			 * UPDATE RECORD on the next unused record (and hope
			 * that there is a record with this index).
			 */
			int rec_nr = 0, i;
			for(i = 0; i < card->app_count; i++)
				if (card->app[i]->rec_nr > rec_nr)
					rec_nr = card->app[i]->rec_nr;
			rec_nr++;
			r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR);
		}
	} else {
		sc_log(card->ctx, "invalid record number\n");
		r = SC_ERROR_INTERNAL;
	}
	free(rec);
	LOG_TEST_RET(card->ctx, r, "Unable to update EF(DIR) record");
	return 0;
}
static int do_update_record(int argc, char **argv)
{
	u8 buf[240];
	size_t buflen;
	int r, i, err = 1;
	int rec, offs;
	sc_path_t path;
	sc_file_t *file;

	if (argc != 4)
		return usage(do_update_record);
	if (arg_to_path(argv[0], &path, 0) != 0)
		return usage(do_update_record);
	rec  = strtol(argv[1],NULL,10);
	offs = strtol(argv[2],NULL,10);

	printf("in: %i; %i; %s\n", rec, offs, argv[3]);

	r = sc_select_file(card, &path, &file);
	if (r) {
		check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
		return -1;
	}

	if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE)   {
		printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n");
		goto err;
	} else if (rec < 1 || rec > file->record_count)   {
		printf("Invalid record number %i\n", rec);
		goto err;
	}

	r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
	if (r<0)   {
		printf("Cannot read record %i; return %i\n", rec, r);
		goto err;;
	}

	buflen = sizeof(buf) - offs;
	i = parse_string_or_hexdata(argv[3], buf + offs, &buflen);
	if (!i) {
		printf("unable to parse data\n");
		goto err;
	}

	r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR);
	if (r<0)   {
		printf("Cannot update record %i; return %i\n", rec, r);
		goto err;
	}

	printf("Total of %d bytes written to record %i at %i offset.\n", 
	       i, rec, offs);

	err = 0;
err:
	sc_file_free(file);
	select_current_path_or_die();
	return -err;
}
Example #3
0
static int
gpk_pkfile_update_public(struct sc_profile *profile,
		sc_pkcs15_card_t *p15card, struct pkpart *part)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct pkcomp	*pe;
	unsigned char	buffer[256];
	unsigned int	m, n, tag;
	int		r = 0, found;

	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Updating public key elements\n");

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

		/* Check for bad record */
		if (r < 2) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "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(p15card->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)
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "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(p15card->card, pe->data, pe->size, 0);
	}

	return r;
}
Example #4
0
/*
 * Set up the public key record for a signature only public key
 */
static int
gpk_pkfile_init_public(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *file,
		unsigned int algo, unsigned int bits,
		unsigned int usage)
{
	struct sc_context *ctx = p15card->card->ctx;
	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(p15card->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_debug(ctx, SC_LOG_DEBUG_NORMAL, "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, p15card, 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_debug(ctx, SC_LOG_DEBUG_NORMAL, "Authentication method not "
				"supported for private key files.\n");
			r = SC_ERROR_NOT_SUPPORTED;
			goto out;
		}
		if (++npins >= 2) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "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];

	r = sc_read_record(p15card->card, 1, buffer, sizeof(buffer),
			SC_RECORD_BY_REC_NR);
	if (r >= 0) {
		if (r != 7 || buffer[0] != 0) {
			sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "first record of public key file is not Lsys0");
			r = SC_ERROR_OBJECT_NOT_VALID;
			goto out;
		}

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

out:	if (tmp)
		sc_file_free(tmp);
	return r;
}
Example #5
0
static int do_update_record(int argc, char **argv)
{
	u8 buf[240];
	int r, i, err = 1;
	int rec, offs;
	sc_path_t path;
	sc_file_t *file;
	char *in_str;
	
	if (argc < 3 || argc > 4)
		goto usage;
	if (arg_to_path(argv[0], &path, 0) != 0)
		goto usage;
	rec  = strtol(argv[1],NULL,10);
	offs = strtol(argv[2],NULL,10);

	in_str = argv[3];
	printf("in: %i; %i; %s\n", rec, offs, in_str);

	r = sc_select_file(card, &path, &file);
	if (r) {
		check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file);
		return -1;
	}

	if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE)   {
		printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n");
		goto err;
	} else if (rec < 1 || rec > file->record_count)   {
		printf("Invalid record number %i\n", rec);
		goto err;
	}
	
	r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR);
	if (r<0)   {
		printf("Cannot read record %i; return %i\n", rec, r);
		goto err;;
	}

	i = hex2binary(buf + offs, sizeof(buf) - offs, in_str);
	if (!i) {
		printf("unable to parse hex value\n");
		goto err;
	}

	r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR);
	if (r<0)   {
		printf("Cannot update record %i; return %i\n", rec, r);
		goto err;
	}

	printf("Total of %d bytes written to record %i at %i offset.\n", 
	       i, rec, offs);
	err = 0;

err:
	sc_file_free(file);
	select_current_path_or_die();
	return -err;
usage:
	printf("Usage: update_record <file id> rec_nr rec_offs <hex value>\n");
	return -1;
}