/* * pkcs15-gids.c: Support for GIDS smart cards. * * Copyright (C) 2015 Vincent Le Toux (My Smart Logon) * * 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 #include #include #include #include #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; }