static int
muscle_create_pin(sc_profile_t *profile, sc_card_t *card,
	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_file_t *file;
	sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
	int r;
	int type;
	if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
		type = SC_PKCS15INIT_SO_PIN;
	} else {
		type = SC_PKCS15INIT_USER_PIN;
	}
	if ((r = sc_select_file(card, &df->path, &file)) < 0)
		return r;
	if ((r = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_WRITE)) < 0)
		return r;
	sc_keycache_set_pin_name(&df->path,
		pin_info->reference,
		type);
	pin_info->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
	return 0;
}
/*
 * Store a PIN
 */
static int
jcop_create_pin(sc_profile_t *profile, sc_card_t *card, 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_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
        unsigned char   nulpin[16];
        unsigned char   padpin[16];
        int             r, type;

        if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
                type = SC_PKCS15INIT_SO_PIN;

                /* SO PIN reference must be 0 */
                if (pin_info->reference != 3)
                        return SC_ERROR_INVALID_ARGUMENTS;
        } else {
                type = SC_PKCS15INIT_USER_PIN;
                if (pin_info->reference >= 3)
                        return SC_ERROR_TOO_MANY_OBJECTS;
        }
        if (puk != NULL && puk_len > 0) {
	     return SC_ERROR_NOT_SUPPORTED;
	}
	r = sc_select_file(card, &df->path, NULL);
        if (r < 0)
	     return r;

	/* Current PIN is 00:00:00:00:00:00:00:00... */
        memset(nulpin, 0, sizeof(nulpin));
        memset(padpin, 0, sizeof(padpin));
	memcpy(padpin, pin, pin_len);
        r = sc_change_reference_data(card, SC_AC_CHV,
                        pin_info->reference,
                        nulpin, sizeof(nulpin),
                        padpin, sizeof(padpin), NULL);
        if (r < 0)
                return r;


	     
        sc_keycache_set_pin_name(&df->path,
                        pin_info->reference,
                        type);
	pin_info->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
        return r;
}
/*
 * Store a PIN
 */
static int
gpk_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
               sc_pkcs15_object_t *pin_obj,
               const u8 *pin, size_t pin_len,
               const u8 *puk, size_t puk_len)
{
    sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data;
    u8	nulpin[8];
    int	r, type;

    if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
        type = SC_PKCS15INIT_SO_PIN;

        /* SO PIN reference must be 0 */
        if (pin_info->reference != (GPK_PIN_SCOPE | 0))
            return SC_ERROR_INVALID_ARGUMENTS;
    } else {
        type = SC_PKCS15INIT_USER_PIN;

        /* PIN references must be even numbers
         * (the odd numbered PIN entries contain the
         * PUKs).
         * Returning SC_ERROR_INVALID_PIN_REFERENCE will
         * tell the caller to pick a different value.
         */
        if ((pin_info->reference & 1) || !(pin_info->reference & GPK_PIN_SCOPE))
            return SC_ERROR_INVALID_PIN_REFERENCE;
        if (pin_info->reference >= (GPK_PIN_SCOPE + GPK_MAX_PINS))
            return SC_ERROR_TOO_MANY_OBJECTS;
    }

    /* No PUK given, but the PIN file specifies an unblock
     * PIN for every PIN.
     * Use the same value for the PUK for now.
     * Alternatively, we could leave the unblock PIN at the default
     * value, but deliberately block it. */
    if (puk == NULL || puk_len == 0) {
        puk = pin;
        puk_len = pin_len;
    }

    r = sc_select_file(card, &df->path, NULL);
    if (r < 0)
        return r;

    /* Current PIN is 00:00:00:00:00:00:00:00 */
    memset(nulpin, 0, sizeof(nulpin));
    r = sc_change_reference_data(card, SC_AC_CHV,
                                 pin_info->reference,
                                 nulpin, sizeof(nulpin),
                                 pin, pin_len, NULL);
    if (r < 0)
        return r;

    /* Current PUK is 00:00:00:00:00:00:00:00 */
    r = sc_change_reference_data(card, SC_AC_CHV,
                                 pin_info->reference + 1,
                                 nulpin, sizeof(nulpin),
                                 puk, puk_len, NULL);
    if (r < 0)
        return r;

    sc_keycache_set_pin_name(&df->path,
                             pin_info->reference,
                             type);

    return r;
}