Ejemplo n.º 1
0
static int do_change(int argc, char **argv)
{
	int ref, r, tries_left = -1;
	u8 oldpin[30];
	u8 newpin[30];
	size_t oldpinlen = 0;
	size_t newpinlen = 0;

	if (argc < 1 || argc > 3)
		goto usage;
	if (strncasecmp(argv[0], "CHV", 3)) {
		printf("Invalid type.\n");
		goto usage;
	}
	if (sscanf(argv[0] + 3, "%d", &ref) != 1) {
		printf("Invalid key reference.\n");
		goto usage;
	}

	if (argc == 3) {
		oldpinlen = sizeof(oldpin);
		if (parse_string_or_hexdata(argv[1], oldpin, &oldpinlen) != 0) {
			printf("Invalid key value.\n");
			goto usage;
		}
	}

	if (argc >= 2) {
		newpinlen = sizeof(newpin);
		if (parse_string_or_hexdata(argv[argc-1], newpin, &newpinlen) != 0) {
			printf("Invalid key value.\n");
			goto usage;
		}
	}

	r = sc_change_reference_data (card, SC_AC_CHV, ref,
                                      oldpinlen ? oldpin : NULL, oldpinlen,
                                      newpinlen ? newpin : NULL, newpinlen,
                                      &tries_left);
	if (r) {
		if (r == SC_ERROR_PIN_CODE_INCORRECT) {
			if (tries_left >= 0) 
				printf("Incorrect code, %d tries left.\n", tries_left);
			else
				printf("Incorrect code.\n");
		}
		printf("Unable to change PIN code: %s\n", sc_strerror(r));
		return -1;
	}
	printf("PIN changed.\n");
	return 0;
usage:
	printf("Usage: change CHV<pin ref> [[<old pin>] <new pin>]\n");
	printf("Examples: \n");
	printf("\tChange PIN: change CHV2 00:00:00:00:00:00 \"foobar\"\n");
	printf("\tSet PIN: change CHV2 \"foobar\"\n");
	printf("\tChange PIN with pinpad': change CHV2\n");
	return -1;
}
/*
 * 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;
}
Ejemplo n.º 3
0
/*
 * Store a PIN
 */
static int
jcop_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_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data;
	struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin;
        unsigned char   nulpin[16];
        unsigned char   padpin[16];
        int             r;

	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_OBJECT_NOT_VALID;

        if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
                /* SO PIN reference must be 0 */
                if (pin_attrs->reference != 3)
                        return SC_ERROR_INVALID_ARGUMENTS;
        } else {
                if (pin_attrs->reference >= 3)
                        return SC_ERROR_TOO_MANY_OBJECTS;
        }
        if (puk != NULL && puk_len > 0) {
	     return SC_ERROR_NOT_SUPPORTED;
	}
	r = sc_select_file(p15card->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(p15card->card, SC_AC_CHV,
                        pin_attrs->reference,
                        nulpin, sizeof(nulpin),
                        padpin, sizeof(padpin), NULL);
        if (r < 0)
                return r;

	pin_attrs->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
        return r;
}
Ejemplo n.º 4
0
/*
 * Store a PIN
 */
static int
gpk_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, 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_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data;
	struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin;
	u8	nulpin[8];
	int	r;

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

	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_OBJECT_NOT_VALID;

	if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
		/* SO PIN reference must be 0 */
		if (pin_attrs->reference != (GPK_PIN_SCOPE | 0))
			return SC_ERROR_INVALID_ARGUMENTS;
	} else {
		/* 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_attrs->reference & 1) || !(pin_attrs->reference & GPK_PIN_SCOPE))
			return SC_ERROR_INVALID_PIN_REFERENCE;
		if (pin_attrs->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(p15card->card, &df->path, NULL);
	sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "select df path: %i", r);
	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(p15card->card, SC_AC_CHV,
			pin_attrs->reference,
			nulpin, sizeof(nulpin),
			pin, pin_len, NULL);
	sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "change  CHV %i", r);
	if (r < 0)
		return r;

	/* Current PUK is 00:00:00:00:00:00:00:00 */
	r = sc_change_reference_data(p15card->card, SC_AC_CHV,
			pin_attrs->reference + 1,
			nulpin, sizeof(nulpin),
			puk, puk_len, NULL);
	sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "change  CHV+1 %i", r);
	if (r < 0)
		return r;

	SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
Ejemplo n.º 5
0
/*
 * Store a key on the card
 */
static int rtecp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
		sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key)
{
	sc_card_t *card;
	sc_pkcs15_prkey_info_t *key_info;
	sc_file_t *pukey_df;
	sc_path_t path;
	unsigned char *buf;
	size_t buf_len, key_len, len, i;
	int r;

	if (!profile || !p15card || !p15card->card || !p15card->card->ctx
			|| !obj || !obj->data || !key)
		return SC_ERROR_INVALID_ARGUMENTS;

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

	if ((obj->type != SC_PKCS15_TYPE_PRKEY_RSA || key->algorithm != SC_ALGORITHM_RSA)
			&& (obj->type != SC_PKCS15_TYPE_PRKEY_GOSTR3410
				|| key->algorithm != SC_ALGORITHM_GOSTR3410))
		return SC_ERROR_NOT_SUPPORTED;

	key_info = (sc_pkcs15_prkey_info_t *)obj->data;
	assert(key_info);

	if (key->algorithm == SC_ALGORITHM_RSA)
	{
		assert(key_info->modulus_length % 128 == 0);
		len = key_info->modulus_length / 8 / 2;
		key_len = len * 5 + 8;
		buf_len = key_len;
	}
	else
	{
		assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE);
		len = key_info->modulus_length / 8;
		key_len = len;
		buf_len = len;
	}
	if (key->algorithm == SC_ALGORITHM_RSA && (!key->u.rsa.p.data
			|| !key->u.rsa.q.data || !key->u.rsa.iqmp.data
			|| !key->u.rsa.dmp1.data || !key->u.rsa.dmq1.data
			|| !key->u.rsa.modulus.data || !key->u.rsa.exponent.data
			|| key->u.rsa.p.len != len || key->u.rsa.q.len != len
			|| key->u.rsa.iqmp.len != len || key->u.rsa.dmp1.len != len
			|| key->u.rsa.dmq1.len != len || key->u.rsa.modulus.len != 2*len
			|| key->u.rsa.exponent.len > len || key->u.rsa.exponent.len == 0))
		return SC_ERROR_INVALID_ARGUMENTS;
	if (key->algorithm == SC_ALGORITHM_GOSTR3410 && (!key->u.gostr3410.d.data
			|| key->u.gostr3410.d.len != len))
		return SC_ERROR_INVALID_ARGUMENTS;
	buf = calloc(1, buf_len);
	if (!buf)
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
	assert(key_len <= buf_len);
	if (key->algorithm == SC_ALGORITHM_RSA)
	{
		/* p */
		for (i = 0; i < len; ++i)
			buf[i] = key->u.rsa.p.data[len - 1 - i];
		/* q */
		for (i = 0; i < len; ++i)
			buf[len + 4 + i] = key->u.rsa.q.data[len - 1 - i];
		/* iqmp */
		for (i = 0; i < len; ++i)
			buf[len + 4 + len + 4 + i] = key->u.rsa.iqmp.data[len - 1 - i];
		/* dmp1 */
		for (i = 0; i < len; ++i)
			buf[len + 4 + len + 4 + len + i] =
				key->u.rsa.dmp1.data[len - 1 - i];
		/* dmq1 */
		for (i = 0; i < len; ++i)
			buf[len * 4 + 8 + i] = key->u.rsa.dmq1.data[len - 1 - i];
	}
	else
	{
		/* d */
		for (i = 0; i < len; ++i)
			buf[i] = key->u.gostr3410.d.data[len - 1 - i];
	}
	path = key_info->path;
	r = sc_select_file(card, &path, NULL);
	if (r == SC_SUCCESS)
		r = sc_change_reference_data(card, 0, 0, NULL, 0, buf, key_len, NULL);
	assert(buf);
	sc_mem_clear(buf, key_len);
	/* store public key */
	if (key->algorithm == SC_ALGORITHM_RSA)
		key_len = len * 3;
	else
		goto end;
	assert(key_len <= buf_len);
	if (key->algorithm == SC_ALGORITHM_RSA)
	{
		/* modulus */
		for (i = 0; i < 2*len; ++i)
			buf[i] = key->u.rsa.modulus.data[2*len - 1 - i];
		/* exponent */
		for (i = 0; i < key->u.rsa.exponent.len && i < len; ++i)
			buf[2 * len + i] = key->u.rsa.exponent.data[
				key->u.rsa.exponent.len - 1 - i];
	}
	if (r == SC_SUCCESS)
	{
		r = sc_profile_get_file(profile, "PuKey-DF", &pukey_df);
		if (r == SC_SUCCESS)
		{
			assert(pukey_df);
			path = pukey_df->path;
			r = sc_append_file_id(&path, key_info->key_reference);
			sc_file_free(pukey_df);
		}
		else if (card->ctx->debug >= 2)
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s\n", "Get PuKey-DF info failed");
	}
	if (r == SC_SUCCESS)
	{
		r = sc_select_file(card, &path, NULL);
		if (r == SC_SUCCESS)
			r = sc_change_reference_data(card, 0, 0, NULL, 0,
					buf, key_len, NULL);
		if (r && card->ctx->debug >= 2)
			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s\n", "Store public key failed");
	}
end:
	assert(buf);
	free(buf);
	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
Ejemplo n.º 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);
}
Ejemplo n.º 7
0
/*
 * 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;
}
Ejemplo n.º 8
0
static int do_change(int argc, char **argv)
{
	int ref, r, tries_left = -1;
	u8 oldpin[30];
	u8 newpin[30];
	const char *s;
	size_t oldpinlen = sizeof(oldpin), i;
	size_t newpinlen = sizeof(newpin);
	
	if (argc < 1 || argc > 3)
		goto usage;
	if (strncasecmp(argv[0], "CHV", 3)) {
		printf("Invalid type.\n");
		goto usage;
	}
	if (sscanf(argv[0] + 3, "%d", &ref) != 1) {
		printf("Invalid key reference.\n");
		goto usage;
	}
	argc--;
	argv++;

	if (argc == 0) {
		/* set without verification */
		oldpinlen = 0;
		newpinlen = 0;
	} else if (argc == 1) {
		/* set without verification */
		oldpinlen = 0;
	} else {
		if (argv[0][0] == '"') {
			for (s = argv[0] + 1, i = 0;
			     i < sizeof(oldpin) && *s && *s != '"'; i++) 
				oldpin[i] = *s++;
			oldpinlen = i;
		} else if (sc_hex_to_bin(argv[0], oldpin, &oldpinlen) != 0) {
			printf("Invalid key value.\n");
			goto usage;
		}
		argc--;
		argv++;
	}

	if (argc)   {
		if (argv[0][0] == '"') {
			for (s = argv[0] + 1, i = 0;
			     i < sizeof(newpin) && *s && *s != '"'; i++) 
				newpin[i] = *s++;
			newpinlen = i;
		} else if (sc_hex_to_bin(argv[0], newpin, &newpinlen) != 0) {
			printf("Invalid key value.\n");
			goto usage;
		}
	}

	r = sc_change_reference_data (card, SC_AC_CHV, ref,
                                      oldpinlen ? oldpin : NULL, oldpinlen,
                                      newpinlen ? newpin : NULL, newpinlen,
                                      &tries_left);
	if (r) {
		if (r == SC_ERROR_PIN_CODE_INCORRECT) {
			if (tries_left >= 0) 
				printf("Incorrect code, %d tries left.\n", tries_left);
			else
				printf("Incorrect code.\n");
		}
		printf("Unable to change PIN code: %s\n", sc_strerror(r));
		return -1;
	}
	printf("PIN changed.\n");
	return 0;
usage:
	printf("Usage: change CHV<pin ref> [[<old pin>] <new pin>]\n");
	printf("Examples: \n");
	printf("\tChange PIN: change CHV2 00:00:00:00:00:00 \"foobar\"\n");
	printf("\tSet PIN: change CHV2 \"foobar\"\n");
	printf("\tChange PIN with pinpad': change CHV2\n");
	return -1;
}
Ejemplo n.º 9
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_pin_info_t *pin_info;
	sc_file_t *file;
	/*                        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 };
	int r;

	(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;
	}
	pin_info = (sc_pkcs15_pin_info_t *)pin_obj->data;
	if (pin_info->reference != RTECP_SO_PIN_REF
			&& pin_info->reference != RTECP_USER_PIN_REF)
	{
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN reference %i not found in standard"
				" (Rutoken ECP) PINs\n", pin_info->reference);
		return SC_ERROR_NOT_SUPPORTED;
	}
	file = sc_file_new();
	if (!file)
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
	file->id = pin_info->reference;
	file->size = pin_len;
	assert(sizeof(sec)/sizeof(sec[0]) > 2);
	sec[1] = (pin_info->reference == RTECP_SO_PIN_REF) ? 0xFF : RTECP_SO_PIN_REF;
	sec[2] = (unsigned char)pin_info->reference;
	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)pin_info->min_length;
		prop[3] = 0x11 * (unsigned char)(pin_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,
				pin_info->reference, NULL, 0, pin, pin_len, NULL);
	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r);
}