opensc/src/pkcs15init/pkcs15-gids.c

193 lines
6.5 KiB
C

/*
* pkcs15-gids.c: Support for GIDS smart cards.
*
* Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include "../libopensc/log.h"
#include "../libopensc/opensc.h"
#include "../libopensc/cardctl.h"
#include "../libopensc/asn1.h"
#include "pkcs15-init.h"
#include "profile.h"
#include "../libopensc/card-gids.h"
/*
* Select a key reference.
*/
static int
gids_select_key_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_prkey_info_t *key_info)
{
sc_card_t *card = p15card->card;
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_SELECT_KEY_REFERENCE, key_info));
}
/*
* Create a new key file.
*/
static int
gids_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj)
{
sc_card_t *card = p15card->card;
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_CREATE_KEY, obj));
}
/*
* Generate a new key.
*/
static int
gids_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_object_t *obj,
sc_pkcs15_pubkey_t *pubkey)
{
sc_card_t *card = p15card->card;
struct sc_cardctl_gids_genkey call = {obj, pubkey};
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_GENERATE_KEY, &call));
}
/*
* Store a usable private key on the card.
*/
static int
gids_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *object,
sc_pkcs15_prkey_t *key)
{
sc_card_t *card = p15card->card;
struct sc_cardctl_gids_importkey call = {object, key};
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_IMPORT_KEY, &call));
}
static int
gids_delete_object(struct sc_profile *profile, struct sc_pkcs15_card * p15card,
struct sc_pkcs15_object *object, const struct sc_path *path) {
sc_card_t *card = p15card->card;
switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) {
case SC_PKCS15_TYPE_PRKEY:
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_DELETE_KEY, object));
break;
case SC_PKCS15_TYPE_CERT:
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_DELETE_CERT, object));
break;
case SC_PKCS15_TYPE_PUBKEY:
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
default:
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
}
static int gids_emu_update_any_df(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
unsigned op, struct sc_pkcs15_object *object)
{
LOG_FUNC_CALLED(p15card->card->ctx);
/* After storing object, pkcs15init will call this function to update DF.
* But GIDS has no other DF than GIDS-Application, so we do nothing. */
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static int gids_save_certificate(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_path *path) {
int r;
sc_card_t *card = p15card->card;
struct sc_cardctl_gids_save_cert call = {object, NULL, path};
struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, &cert_info->id , &(call.privkeyobject));
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
//TODO save the certificate in the special file
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
LOG_TEST_RET(card->ctx, r, "unable to find the private key associated to the certificate");
LOG_FUNC_RETURN(card->ctx, sc_card_ctl(card, SC_CARDCTL_GIDS_SAVE_CERT, &call));
}
static int gids_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
struct sc_pkcs15_object *object, struct sc_pkcs15_der *content,
struct sc_path *path) {
sc_card_t *card = p15card->card;
int r;
LOG_FUNC_CALLED(card->ctx);
switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
case SC_PKCS15_TYPE_PRKEY:
case SC_PKCS15_TYPE_PUBKEY:
/* For these two type, store_data just don't need to do anything.
* All have been done already before this function is called */
r = SC_SUCCESS;
break;
case SC_PKCS15_TYPE_CERT:
r = gids_save_certificate(p15card, object, path);
break;
default:
r = SC_ERROR_NOT_IMPLEMENTED;
break;
}
LOG_FUNC_RETURN(card->ctx, r);
}
static int gids_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_tokeninfo_t *tokeninfo)
{
LOG_FUNC_CALLED(p15card->card->ctx);
/* When unbinding pkcs15init, this function will be called.
* But for GIDS, token info does not need to change, we do nothing. */
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static struct sc_pkcs15init_operations sc_pkcs15init_gids_operations =
{
NULL, /* erase_card */
NULL, /* init_card */
NULL, /* create_dir */
NULL, /* create_domain */
NULL, /* pin_reference*/
NULL, /* create_pin */
gids_select_key_reference, /* key_reference */
gids_create_key, /* create_key */
gids_store_key, /* store_key */
gids_generate_key, /* generate_key */
NULL, NULL, /* encode private/public key */
NULL, /* finalize */
gids_delete_object, /* delete_object */
NULL, /* pkcs15init emulation emu_update_dir */
gids_emu_update_any_df, /* pkcs15init emulation emu_update_any_df */
gids_emu_update_tokeninfo, /* pkcs15init emulation emu_update_tokeninfo */
NULL, /* pkcs15init emulation emu_write_info */
gids_emu_store_data, /* pkcs15init emulation emu_store_data */
NULL, /* sanity_check*/
};
struct
sc_pkcs15init_operations *sc_pkcs15init_get_gids_ops(void)
{
return &sc_pkcs15init_gids_operations;
}