Example #1
0
/*
 * Create the MF and global pin file if they don't exist.
 */
static int
setcos_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card)
{
	struct sc_context *ctx = p15card->card->ctx;
	sc_file_t *mf = profile->mf_info->file;
	sc_file_t *pinfile;
	int r;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	/* Create the MF if it doesn't exist yet */
	r = sc_select_file(p15card->card, &mf->path, NULL);
	if (r == SC_ERROR_FILE_NOT_FOUND) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "MF doesn't exist, creating now");

		/* Fix up the file's ACLs */
		r = sc_pkcs15init_fixup_file(profile, p15card, mf);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "MF fixup failed");

		mf->status = SC_FILE_STATUS_CREATION;
		r = sc_create_file(p15card->card, mf);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "MF creation failed");
	}
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select MF");

	/* Create the global pin file if it doesn't exist yet */
	r = sc_profile_get_file(profile, "pinfile", &pinfile);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get 'pinfile' from profile");

	r = sc_select_file(p15card->card, &pinfile->path, NULL);
	if (r == SC_ERROR_FILE_NOT_FOUND) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Global pin file doesn't exist, creating now");

		/* Fix up the file's ACLs */
		r = sc_pkcs15init_fixup_file(profile, p15card, pinfile);
		if (r < 0)
			sc_file_free(pinfile);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile fixup failed");

		/* Set life cycle state to SC_FILE_STATUS_CREATION,
		 * which means that all ACs are ignored. */
		pinfile->status = SC_FILE_STATUS_CREATION;
		r = sc_create_file(p15card->card, pinfile);
		if (r < 0)
			sc_file_free(pinfile);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile creation failed");
	}
	sc_file_free(pinfile);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Select pinfile failed");

	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}
Example #2
0
/*
 * Create a new key file
 */
static int
jcop_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj)
{
        sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
        sc_file_t  *keyfile = NULL;
        size_t          bytes, mod_len, prv_len;
        int             r;

        if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
                sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys.");
                return SC_ERROR_NOT_SUPPORTED;
        }
        /* The caller is supposed to have chosen a key file path for us */
        if (key_info->path.len == 0 || key_info->modulus_length == 0)
                return SC_ERROR_INVALID_ARGUMENTS;

        /* Get the file we're supposed to create */
        r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile);
        if (r < 0)
                return r;

        mod_len = key_info->modulus_length / 8;
        bytes   = mod_len / 2;
        prv_len = 2 + 5 * bytes;
        keyfile->size = prv_len;

        /* Fix up PIN references in file ACL */
        r = sc_pkcs15init_fixup_file(profile, p15card, keyfile);

        if (r >= 0)
                r = sc_pkcs15init_create_file(profile, p15card, keyfile);

        sc_file_free(keyfile);
        return r;
}
Example #3
0
/*
 * Create a DF
 */
static int
setcos_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df)
{
	struct sc_context *ctx = p15card->card->ctx;
	int r;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

        r = sc_pkcs15init_fixup_file(profile, p15card, df);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "SetCOS file ACL fixup failed");

	r = sc_create_file(p15card->card, df);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "SetCOS create file failed");

	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 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
/*
 * Create a key file
 */
static int
gpk_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj)
{
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	struct sc_file	*keyfile = NULL;
	size_t		bytes, mod_len, exp_len, prv_len, pub_len;
	int		r, algo;

	/* The caller is supposed to have chosen a key file path for us */
	if (key_info->path.len == 0 || key_info->modulus_length == 0)
		return SC_ERROR_INVALID_ARGUMENTS;

	/* Get the file we're supposed to create */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile);
	if (r < 0)
		return r;

	/* Compute the file size.
	 * We assume private keys are stored as CRT elements.
	 *  -	512, 768 bit keys: all CRT elements fit into one record
	 *  -	>= 1024: each CRT element into a record of its own
	 *
	 * We also assume the public exponent is 32bit max
	 *
	 * Rules
	 *  -	private key records must have a length divisible by 8
	 */
	mod_len = key_info->modulus_length / 8;
	exp_len = 4;
	bytes   = mod_len / 2;
	pub_len = 8 + ((3 + mod_len + 3 + exp_len + 3) & ~3UL);
	if (5 * bytes < 256) {
		prv_len = 8 + ((3 + 5 * bytes + 7) & ~7UL);
	} else {
		prv_len = 8 + 5 * ((3 + bytes + 7) & ~7UL);
	}
	keyfile->size = pub_len + prv_len;

	switch (obj->type) {
	case SC_PKCS15_TYPE_PRKEY_RSA:
		algo = SC_ALGORITHM_RSA; break;
	case SC_PKCS15_TYPE_PRKEY_DSA:
		algo = SC_ALGORITHM_DSA; break;
	default:
		sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key algorithm");
		return SC_ERROR_NOT_SUPPORTED;
	}

	/* Fix up PIN references in file ACL and create the PK file */
	if ((r = sc_pkcs15init_fixup_file(profile, p15card, keyfile)) < 0
	 || (r = gpk_pkfile_create(profile, p15card, keyfile)) < 0)
		goto done;

#ifdef PK_INIT_IMMEDIATELY
	/* Initialize the public key header */
	r = gpk_pkfile_init_public(profile, p15card, keyfile, algo,
			key_info->modulus_length,
			key_info->usage);
	if (r < 0)
		goto done;

	/* Create the private key portion */
	r = gpk_pkfile_init_private(p15card->card, keyfile, prv_len);
#endif

done:
	sc_file_free(keyfile);
	return r;
}
Example #6
0
/*
 * Create a PIN object within the given DF
 */
static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
		sc_file_t *df, sc_pkcs15_object_t *pin_obj,
		const unsigned char *pin, size_t pin_len,
		const unsigned char *puk, size_t puk_len)
{
	sc_context_t *ctx;
	sc_pkcs15_auth_info_t *auth_info;
	sc_file_t *file = NULL;
	/*                        GCHV min-length Flags Attempts  Reserve */
	unsigned char prop[]  = { 0x01,       '?', 0x01,     '?', 0, 0 };
	/*                  AccessMode Unblock Change             Delete */
	unsigned char sec[15] = { 0x43,    '?',   '?', 0, 0, 0, 0,  0xFF };
	char pin_sname[0x10];
	int r, reset_by_sopin = 0;

	(void)puk; /* no warning */
	if (!profile || !p15card || !p15card->card || !p15card->card->ctx || !df
			|| !pin_obj || !pin_obj->data || !pin || !pin_len)
		return SC_ERROR_INVALID_ARGUMENTS;

	ctx = p15card->card->ctx;
	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	if (puk_len != 0)
	{
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Do not enter User unblocking PIN (PUK): %s\n",
				sc_strerror(SC_ERROR_NOT_SUPPORTED));
		return SC_ERROR_NOT_SUPPORTED;
	}

	auth_info = (sc_pkcs15_auth_info_t *)pin_obj->data;
	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_OBJECT_NOT_VALID;

	if (auth_info->attrs.pin.reference != RTECP_SO_PIN_REF
			&& auth_info->attrs.pin.reference != RTECP_USER_PIN_REF)
	{
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN reference %i not found in standard"
				" (Rutoken ECP) PINs\n", auth_info->attrs.pin.reference);
		return SC_ERROR_NOT_SUPPORTED;
	}

	snprintf(pin_sname, sizeof(pin_sname), "CHV%i", auth_info->attrs.pin.reference);
	if (auth_info->attrs.pin.reference == RTECP_USER_PIN_REF)   {
		r = sc_profile_get_file(profile, pin_sname, &file);
		if (!r)   {
			const struct sc_acl_entry *acl = NULL;

			r = sc_pkcs15init_fixup_file(profile, p15card, file);
			if (r < 0)
				sc_file_free(file);
			SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot fixup the ACLs of PIN file");

			acl = sc_file_get_acl_entry(file, SC_AC_OP_PIN_RESET);
			if (acl && acl->method == SC_AC_CHV && acl->key_ref == RTECP_SO_PIN_REF)   {
				sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Allow reset of User PIN with SoPIN\n");
				reset_by_sopin = 1;
			}
			sc_file_free(file);
		}
	}

	file = sc_file_new();
	if (!file)
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
	file->id = auth_info->attrs.pin.reference;
	file->size = pin_len;
	assert(sizeof(sec)/sizeof(sec[0]) > 2);
	sec[1] = (auth_info->attrs.pin.reference == RTECP_SO_PIN_REF) ? 0xFF : RTECP_SO_PIN_REF;
	sec[2] = (unsigned char)auth_info->attrs.pin.reference | (reset_by_sopin ? RTECP_SO_PIN_REF : 0);
	r = sc_file_set_sec_attr(file, sec, sizeof(sec));
	if (r == SC_SUCCESS)
	{
		assert(sizeof(prop)/sizeof(prop[0]) > 3);
		prop[1] = (unsigned char)auth_info->attrs.pin.min_length;
		prop[3] = 0x11 * (unsigned char)(auth_info->tries_left & 0x0F);
		r = sc_file_set_prop_attr(file, prop, sizeof(prop));
	}
	if (r == SC_SUCCESS)
		r = sc_file_set_type_attr(file, (const u8*)"\x10\x00", 2);
	if (r == SC_SUCCESS)
		r = sc_create_file(p15card->card, file);
	sc_file_free(file);

	if (r == SC_SUCCESS)
		r = sc_change_reference_data(p15card->card, SC_AC_CHV,
				auth_info->attrs.pin.reference, NULL, 0, pin, pin_len, NULL);
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}
/*
 * Get 'Initialize Applet' data
 * 	using the ACLs defined in card profile.
 */
static int
myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
		unsigned char *data, size_t data_len) {
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_file *tmp_file = NULL;
	const struct sc_acl_entry *entry = NULL;
	int r;

	LOG_FUNC_CALLED(ctx);

	if (data_len < 8)
		LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "Cannot get init applet data");

	*(data + 0) = 0xFF;
	*(data + 1) = 0xFF;

	/* MF acls */
	sc_file_dup(&tmp_file, profile->mf_info->file);
	if (tmp_file == NULL)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate MF file");
	r = sc_pkcs15init_fixup_file(profile, p15card, tmp_file);
	LOG_TEST_RET(ctx, r, "MF fixup failed");

	/* AC 'Create DF' and 'Create EF' */
	*(data + 2) = 0x00; /* 'NONE' */
	entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
	if (entry->method == SC_AC_CHV)
		*(data + 2) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx'. */
	else if (entry->method == SC_AC_NEVER)
		*(data + 2) = 0xFF; /* 'NEVER'. */

	/* AC 'INITIALISE APPLET'. */
	*(data + 3) = 0x0F; /* 'NONE' */
#ifndef KEEP_AC_NONE_FOR_INIT_APPLET
	entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
	if (entry->method == SC_AC_CHV)
		*(data + 3) = (entry->key_ref << 4) | 0xF;
	else if (entry->method == SC_AC_NEVER)
		*(data + 3) = 0xFF;
#endif
	*(data + 4) = 0xFF;

	sc_file_free(tmp_file);
	tmp_file = NULL;

	/* Application DF (5015) acls */
	sc_file_dup(&tmp_file, profile->df_info->file);
	if (tmp_file == NULL)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate Application DF file");
	r = sc_pkcs15init_fixup_file(profile, p15card, tmp_file);
	LOG_TEST_RET(ctx, r, "Application DF fixup failed");

	/* AC 'Create DF' and 'Create EF' */
	*(data + 5) = 0x00; /* 'NONE' */
	entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_CREATE);
	if (entry->method == SC_AC_CHV)
		*(data + 5) = entry->key_ref | (entry->key_ref << 4); /* 'CHVx' */
	else if (entry->method == SC_AC_NEVER)
		*(data + 5) = 0xFF; /* 'NEVER'. */

	/* AC 'Self delete' */
	*(data + 6) = 0x0F; /* 'NONE' */
	entry = sc_file_get_acl_entry(tmp_file, SC_AC_OP_DELETE);
	if (entry->method == SC_AC_CHV)
		*(data + 6) = (entry->key_ref << 4) | 0xF; /* 'CHVx' */
	else if (entry->method == SC_AC_NEVER)
		*(data + 6) = 0xFF; /* 'NEVER'. */
	*(data + 7) = 0xFF;
	sc_file_free(tmp_file);

	LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
Example #8
0
/*
 * Generate a keypair
 */
static int
jcop_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
		  sc_pkcs15_object_t *obj,
		  sc_pkcs15_pubkey_t *pubkey)
{
     sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
     struct sc_cardctl_jcop_genkey args;
     sc_file_t       *temppubfile=NULL, *keyfile=NULL;
     unsigned char   *keybuf=NULL;
     size_t          mod_len, exp_len, pub_len, keybits;
     int             r,delete_ok=0;

     if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
	  sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys.");
	  return SC_ERROR_NOT_SUPPORTED;
     }

     r=sc_profile_get_file(profile, "temp-pubkey", &temppubfile);
     if (r < 0)
	  goto out;

     r = sc_select_file(p15card->card, &key_info->path, &keyfile);
     if (r < 0)
	  goto out;

     mod_len = key_info->modulus_length / 8;
     exp_len = 4;
     pub_len = 2 + mod_len + exp_len;
     temppubfile->size = pub_len;

     r = sc_pkcs15init_fixup_file(profile, p15card, temppubfile);
     if (r < 0)
	  goto out;

     r = sc_pkcs15init_create_file(profile, p15card, temppubfile);
     if (r < 0)
	  goto out;

     delete_ok=1;
     r = sc_pkcs15init_authenticate(profile, p15card, temppubfile, SC_AC_OP_UPDATE);
     if (r < 0)
	  goto out;
     r = sc_pkcs15init_authenticate(profile, p15card, keyfile, SC_AC_OP_UPDATE);
     if (r < 0)
	  goto out;

     keybits = key_info->modulus_length;

     /* generate key */
     /* keysize is _not_ passed to the card at any point. it appears to
	infer it from the file size */
     memset(&args, 0, sizeof(args));
     args.exponent = 0x10001;
     sc_append_file_id(&args.pub_file_ref, temppubfile->id);
     sc_append_file_id(&args.pri_file_ref, keyfile->id);
     keybuf = malloc(keybits / 8);
     if (!keybuf) {
	  r=SC_ERROR_OUT_OF_MEMORY;
	  goto out;
     }
     args.pubkey = keybuf;
     args.pubkey_len = keybits / 8;

     r = sc_card_ctl(p15card->card, SC_CARDCTL_JCOP_GENERATE_KEY, (void *)&args);
     if (r < 0)
	  goto out;

     /* extract public key */
     pubkey->algorithm = SC_ALGORITHM_RSA;
     pubkey->u.rsa.modulus.len   = keybits / 8;
     pubkey->u.rsa.modulus.data  = keybuf;
     pubkey->u.rsa.exponent.len  = 3;
     pubkey->u.rsa.exponent.data = malloc(3);
     if (!pubkey->u.rsa.exponent.data) {
	  pubkey->u.rsa.modulus.data = NULL;
	  r=SC_ERROR_OUT_OF_MEMORY;
	  goto out;
     }
     memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);

 out:
     if (r < 0 && keybuf)
	  free(keybuf);
     if (delete_ok)
	  sc_pkcs15init_rmdir(p15card, profile, temppubfile);
     if (keyfile)
	  sc_file_free(keyfile);
     if (temppubfile)
	  sc_file_free(temppubfile);
     return r;
}