Esempio n. 1
0
/*
 * On-board key generation.
 */
static int
gpk_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
                        sc_pkcs15_object_t *obj,
                        sc_pkcs15_pubkey_t *pubkey)
{
	struct sc_cardctl_gpk_genkey args;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	unsigned int    keybits;
	sc_file_t	*keyfile;
	int             r, n;

	sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "path=%s, %d bits\n", sc_print_path(&key_info->path),
			key_info->modulus_length);

	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "GPK supports generating 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;
	keybits = key_info->modulus_length;

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

#ifndef PK_INIT_IMMEDIATELY
	r = gpk_pkfile_init_public(profile, p15card, keyfile, SC_ALGORITHM_RSA,
			keybits, key_info->usage);
	if (r < 0) {
		sc_file_free(keyfile);
		return r;
	}

	if ((r = gpk_pkfile_init_private(p15card->card, keyfile, 5 * ((3 + keybits / 16 + 7) & ~7UL))) < 0) {
		sc_file_free(keyfile);
		return r;
	}
#endif
	sc_file_free(keyfile);

	memset(&args, 0, sizeof(args));
	/*args.exponent = 0x10001;*/
	n = key_info->path.len;
	args.fid = (key_info->path.value[n-2] << 8) | key_info->path.value[n-1];
	args.privlen = keybits;

	r = sc_card_ctl(p15card->card, SC_CARDCTL_GPK_GENERATE_KEY, &args);
	if (r < 0)
		return r;

	/* This is fairly weird. The GENERATE RSA KEY command returns
	 * immediately, but obviously it needs more time to complete.
	 * This is why we sleep here. */
	sleep(20);

	pubkey->algorithm = SC_ALGORITHM_RSA;
	return gpk_read_rsa_key(p15card->card, &pubkey->u.rsa);
}
static int
gpk_store_pk(struct sc_profile *profile, sc_card_t *card,
             sc_file_t *file, struct pkdata *p)
{
    size_t	fsize;
    int	r;

    /* Compute length of private/public key parts */
    gpk_compute_publen(&p->_public);
    gpk_compute_privlen(&p->_private);

    if (card->ctx->debug)
        sc_debug(card->ctx,
                 "Storing pk: %u bits, pub %u bytes, priv %u bytes\n",
                 p->bits, p->_public.size, p->_private.size);

    fsize = p->_public.size + p->_private.size;
    if (fsize > file->size)
        return SC_ERROR_FILE_TOO_SMALL;

    /* Put the system record */
#ifndef PK_INIT_IMMEDIATELY
    r = gpk_pkfile_init_public(profile, card, file, p->algo,
                               p->bits, p->usage);
    if (r < 0)
        return r;
#endif

    /* Put the public key elements */
    r = gpk_pkfile_update_public(profile, card, &p->_public);
    if (r < 0)
        return r;

    /* Create the private key part */
#ifndef PK_INIT_IMMEDIATELY
    r = gpk_pkfile_init_private(card, file, p->_private.size);
    if (r < 0)
        return r;
#endif

    /* Now store the private key elements */
    r = gpk_pkfile_update_private(profile, card, file, &p->_private);

    return r;
}
Esempio n. 3
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;
}