コード例 #1
0
ファイル: pkcs15-cflex.c プロジェクト: CendioOssman/OpenSC
/*
 * Get private and public key file
 */
static int cflex_get_keyfiles(sc_profile_t *profile, sc_card_t *card,
			const sc_path_t *df_path,
			sc_file_t **prkf, sc_file_t **pukf)
{
	sc_path_t	path = *df_path;
	int		r;

	/* Get the private key file */
	r = sc_profile_get_file_by_path(profile, &path, prkf);
	if (r < 0) {
		char pbuf[SC_MAX_PATH_STRING_SIZE];

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

		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cannot find private key file info "
				"in profile (path=%s).", pbuf);
		return r;
	}

	/* Get the public key file */
	path.len -= 2;
	sc_append_file_id(&path, 0x1012);
	r = sc_profile_get_file_by_path(profile, &path, pukf);
	if (r < 0) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cannot find public key file info in profile.");
		sc_file_free(*prkf);
		return r;
	}

	return 0;
}
コード例 #2
0
ファイル: pkcs15-jcop.c プロジェクト: CendioOssman/OpenSC
/*
 * Store a private key
 * Private key file formats: (transparent file)
 * Non-CRT:
 * byte 0     0x05
 * byte 1     Modulus length (in byte/4)
 * byte 2     Modulus (n)
 * byte 2+x   private exponent (d)
 *
 * CRT:
 * byte 0     0x06
 * byte 1     component length (in byte/2; component length is half
 *            of modulus length
 * byte 2     Prime (p)
 * byte 2+x   Prime (q)
 * byte 2+2*x Exponent 1 (d mod (p-1))
 * byte 2+3*x Exponent 2 (d mod (q-1))
 * byte 2+4*x Coefficient ((p ^ -1) mod q
 *
 * We use the CRT format, since that's what key generation does.
 *
 * Numbers are stored big endian.
 */
static int
jcop_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
                sc_pkcs15_object_t *obj,
                sc_pkcs15_prkey_t *key)
{
        sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
        sc_file_t       *keyfile;
        unsigned char   keybuf[1024];
        size_t          size,base;
        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;
        }
        r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile);
        if (r < 0)
                return r;
	base=key_info->modulus_length / 16;
	size=2+5*base;
	keybuf[0]=6;
	keybuf[1]=base/4;
	jcop_bn2bin(&keybuf[2 + 0 * base], &key->u.rsa.p, base);
	jcop_bn2bin(&keybuf[2 + 1 * base], &key->u.rsa.q, base);
	jcop_bn2bin(&keybuf[2 + 2 * base], &key->u.rsa.dmp1, base);
	jcop_bn2bin(&keybuf[2 + 3 * base], &key->u.rsa.dmq1, base);
	jcop_bn2bin(&keybuf[2 + 4 * base], &key->u.rsa.iqmp, base);
        r = sc_pkcs15init_update_file(profile, p15card, keyfile, keybuf, size);

	sc_file_free(keyfile);
	return r;
}
コード例 #3
0
ファイル: pkcs15-jcop.c プロジェクト: Hubitronic/OpenSC
/*
 * 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;
}
コード例 #4
0
ファイル: pkcs15-muscle.c プロジェクト: securez/opendnie
/*
 * Store a private key object.
 */
static int
muscle_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
			sc_pkcs15_object_t *obj,
			sc_pkcs15_prkey_t *key)
{
	struct sc_context *ctx = p15card->card->ctx;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	sc_file_t* prkf;
	struct sc_pkcs15_prkey_rsa *rsa;
	sc_cardctl_muscle_key_info_t info;
	int		r;
	
	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Muscle supports RSA keys only.");
		return SC_ERROR_NOT_SUPPORTED;
	}
	/* Verification stuff */
	/* Used for verification AND for obtaining private key acls */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
	if(!prkf) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_NOT_SUPPORTED);
	r = sc_pkcs15init_authenticate(profile, p15card, prkf, SC_AC_OP_CRYPTO);
	if (r < 0) {
		sc_file_free(prkf);
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_NOT_SUPPORTED);
	}
	sc_file_free(prkf);
	r = muscle_select_key_reference(profile, p15card, key_info);
	if (r < 0) {
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,r);
	}
	rsa = &key->u.rsa;
	
	info.keySize = rsa->modulus.len << 3;
	info.keyType = 0x03; /* CRT type */
	info.keyLocation = key_info->key_reference * 2; /* Mult by 2 to preserve even/odd keynumber structure */
	
	info.pLength = rsa->p.len;
	info.pValue = rsa->p.data;
	info.qLength = rsa->q.len;
	info.qValue = rsa->q.data;
	
	info.pqLength = rsa->iqmp.len;
	info.pqValue = rsa->iqmp.data;
	
	info.dp1Length = rsa->dmp1.len;
	info.dp1Value = rsa->dmp1.data;
	info.dq1Length = rsa->dmq1.len;
	info.dq1Value = rsa->dmq1.data;
	
	r = sc_card_ctl(p15card->card, SC_CARDCTL_MUSCLE_IMPORT_KEY, &info);
	if (r < 0) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to import key");
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,r);
	}
	return r;
}
コード例 #5
0
ファイル: pkcs15-gpk.c プロジェクト: Hubitronic/OpenSC
/*
 * 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;
}
コード例 #6
0
ファイル: pkcs15-gpk.c プロジェクト: Hubitronic/OpenSC
/*
 * 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;
}
コード例 #7
0
ファイル: pkcs15-westcos.c プロジェクト: exciler/OpenSC
/*
 * Generate key
 */
static int westcos_pkcs15init_generate_key(sc_profile_t *profile,
						sc_pkcs15_card_t *p15card,
						sc_pkcs15_object_t *obj,
						sc_pkcs15_pubkey_t *pubkey)
{
#ifndef ENABLE_OPENSSL
	return SC_ERROR_NOT_SUPPORTED;
#else
	int r = SC_ERROR_UNKNOWN;
	long lg;
	u8 *p;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	RSA *rsa = NULL;
	BIGNUM *bn = NULL;
	BIO *mem = NULL;

	sc_file_t *prkf = NULL;

	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		return SC_ERROR_NOT_SUPPORTED;
	}

#if OPENSSL_VERSION_NUMBER>=0x00908000L
	rsa = RSA_new();
	bn = BN_new();
	mem = BIO_new(BIO_s_mem());

	if(rsa == NULL || bn == NULL || mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	if(!BN_set_word(bn, RSA_F4) ||
		!RSA_generate_key_ex(rsa, key_info->modulus_length, bn, NULL))
#else
	mem = BIO_new(BIO_s_mem());

	if(mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	rsa = RSA_generate_key(key_info->modulus_length, RSA_F4, NULL, NULL);
	if (!rsa)
#endif
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	rsa->meth = RSA_PKCS1_SSLeay();

	if(pubkey != NULL)
	{
		if(!i2d_RSAPublicKey_bio(mem, rsa))
		{
			r = SC_ERROR_UNKNOWN;
			goto out;
		}

		lg = BIO_get_mem_data(mem, &p);

		pubkey->algorithm = SC_ALGORITHM_RSA;

		r = sc_pkcs15_decode_pubkey(p15card->card->ctx, pubkey, p, lg);
	}

	(void) BIO_reset(mem);

	if(!i2d_RSAPrivateKey_bio(mem, rsa))
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	lg = BIO_get_mem_data(mem, &p);

	/* Get the private key file */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
	if (r < 0)
	{
		char pbuf[SC_MAX_PATH_STRING_SIZE];

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

		goto out;
	}

	prkf->size = lg;

	r = sc_pkcs15init_create_file(profile, p15card, prkf);
	if(r) goto out;

	r = sc_pkcs15init_update_file(profile, p15card, prkf, p, lg);
	if(r) goto out;

out:
	if(mem)
		BIO_free(mem);
	if(bn)
		BN_free(bn);
	if(rsa)
		RSA_free(rsa);
	if(prkf)
		sc_file_free(prkf);

	return r;
#endif
}
コード例 #8
0
static int
muscle_generate_key(sc_profile_t *profile, sc_card_t *card,
			sc_pkcs15_object_t *obj,
			sc_pkcs15_pubkey_t *pubkey)
{
	sc_cardctl_muscle_gen_key_info_t args;
	sc_cardctl_muscle_key_info_t extArgs;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	sc_file_t* prkf;
	unsigned int	keybits;
	int		r;
	
	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		sc_error(card->ctx, "Muscle supports only RSA keys (for now).");
		SC_FUNC_RETURN(card->ctx, 2,SC_ERROR_NOT_SUPPORTED);
	}
	keybits = key_info->modulus_length & ~7UL;
	if (keybits > 2048) {
		sc_error(card->ctx, "Unable to generate key, max size is %d",
				2048);
		SC_FUNC_RETURN(card->ctx, 2,SC_ERROR_INVALID_ARGUMENTS);
	}
	/* Verification stuff */
	/* Used for verification AND for obtaining private key acls */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
	if(!prkf) SC_FUNC_RETURN(card->ctx, 2,SC_ERROR_NOT_SUPPORTED);
	r = sc_pkcs15init_authenticate(profile, card, prkf, SC_AC_OP_CRYPTO);
	if (r < 0) {
		sc_file_free(prkf);
		SC_FUNC_RETURN(card->ctx, 2,SC_ERROR_NOT_SUPPORTED);
	}
	sc_file_free(prkf);
	
	/* END VERIFICATION STUFF */
	
	/* Public key acls... get_file_by_path as well? */
	
	memset(&args, 0, sizeof(args));
	args.keyType = 0x01; // RSA forced
	args.privateKeyLocation = key_info->key_reference * 2;
	args.publicKeyLocation = key_info->key_reference * 2 + 1;
	
	args.keySize = keybits;
	
	r = sc_card_ctl(card, SC_CARDCTL_MUSCLE_GENERATE_KEY, &args);
	if (r < 0) {
		sc_error(card->ctx, "Unable to generate key");
		SC_FUNC_RETURN(card->ctx, 2,r);
	}
	
	memset(&extArgs, 0, sizeof(extArgs));
	memset(pubkey, 0, sizeof(*pubkey));
	
	extArgs.keyType = 0x01;
	extArgs.keyLocation = args.publicKeyLocation;
	r = sc_card_ctl(card, SC_CARDCTL_MUSCLE_EXTRACT_KEY, &extArgs);
	if (r < 0) {
		sc_error(card->ctx, "Unable to extract the public key");
		SC_FUNC_RETURN(card->ctx, 2,r);
	}
	
	pubkey->algorithm = SC_ALGORITHM_RSA;
	pubkey->u.rsa.modulus.len   = extArgs.modLength;
	pubkey->u.rsa.modulus.data  = extArgs.modValue;
	pubkey->u.rsa.exponent.len  = extArgs.expLength;
	pubkey->u.rsa.exponent.data = extArgs.expValue;
	
	if (r < 0) {
		if (pubkey->u.rsa.modulus.data)
			free (pubkey->u.rsa.modulus.data);
		if (pubkey->u.rsa.exponent.data)
			free (pubkey->u.rsa.exponent.data);
	}
	return r;	
}
コード例 #9
0
ファイル: pkcs15-cflex.c プロジェクト: CendioOssman/OpenSC
static int
cflex_create_pin_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
			sc_path_t *df_path, int ref,
			const u8 *pin, size_t pin_len, int pin_tries,
			const u8 *puk, size_t puk_len, int puk_tries,
			sc_file_t **file_ret, int unprotected)
{
	struct sc_context *ctx = p15card->card->ctx;
	struct sc_pkcs15_object *pin_obj = NULL;
	unsigned char	buffer[23];
	sc_path_t	path;
	sc_file_t	*dummies[2], *file;
	int		r, ndummies;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
	if (file_ret)
		*file_ret = NULL;

	/* Build the CHV path */
	path = *df_path;
	path.value[path.len++] = ref - 1;
	path.value[path.len++] = 0;

	/* See if the CHV already exists */
	r = sc_select_file(p15card->card, &path, NULL);
	if (r >= 0)
		return SC_ERROR_FILE_ALREADY_EXISTS;

	/* Get the file definition from the profile */
	if (sc_profile_get_file_by_path(profile, &path, &file) < 0
			&& sc_profile_get_file(profile, (ref == 1)? "CHV1" : "CHV2", &file) < 0
			&& sc_profile_get_file(profile, "CHV", &file) < 0)
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND, "profile does not define pin file ACLs");

	file->path = path;
	file->size = 23;
	file->id = (ref == 1)? 0x0000 : 0x0100;

	if (unprotected)   {
		sc_file_add_acl_entry(file, SC_AC_OP_UPDATE,
				SC_AC_NONE, SC_AC_KEY_REF_NONE);
	}

	/* Build the contents of the file */
	buffer[0] = buffer[1] = buffer[2] = 0xFF;
	put_pin(profile, buffer + 3, pin, pin_len, pin_tries);
	put_pin(profile, buffer + 13, puk, puk_len, puk_tries);

	/* For updating the file, create a dummy CHV files if
	 * necessary */
	ndummies = cflex_create_dummy_chvs(profile, p15card,
				file, SC_AC_OP_UPDATE, dummies);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, ndummies, "Unable to create dummy CHV file");

	if (!unprotected)   {
		struct sc_pin_cmd_data pin_cmd;

		memset(&pin_cmd, 0, sizeof(pin_cmd));
		pin_cmd.cmd = SC_PIN_CMD_VERIFY;
		pin_cmd.pin_type = SC_AC_CHV;
		pin_cmd.pin_reference = ref;
		pin_cmd.pin1.data = dummy_pin_value;
		pin_cmd.pin1.len = sizeof(dummy_pin_value);

		r = sc_pin_cmd(p15card->card, &pin_cmd, NULL);
		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot verify dummy PIN");

	};

	if (ref == 2)   {
		/* Cache dummy SOPIN value */
		r = sc_pkcs15_find_pin_by_type_and_reference(p15card, NULL, SC_AC_CHV, ref, &pin_obj);
		if (!r && pin_obj)
			sc_pkcs15_pincache_add(p15card, pin_obj, dummy_pin_value, sizeof(dummy_pin_value));
	}

	r = sc_pkcs15init_create_file(profile, p15card, file);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Failed to create PIN file");

	r = sc_update_binary(p15card->card, 0, buffer, 23, 0);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Failed to update PIN file");

	if (r < 0 || file_ret == NULL)
		sc_file_free(file);
	else
		*file_ret = file;

	/* Delete the dummy CHV files */
	cflex_delete_dummy_chvs(profile, p15card, ndummies, dummies);

	if (pin_obj)   {
		/* Cache new SOPIN value */
		sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len);
	}

	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
}