/*************************************************************************** $RCSfile: hbcicard.h,v $ ------------------- cvs : $Id: hbcicard.h,v 1.8 2003/05/06 15:05:41 aquamaniac Exp $ begin : Tue Aug 28 2001 copyright : (C) 2001 by Martin Preuss email : martin@libchipcard.de *************************************************************************** * * * 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 * * * ***************************************************************************/ #ifndef HBCICARD_H #define HBCICARD_H struct s_card_id; class HBCICard; #define k_HBCICARD_TYPE_UNKNOWN 0 #define k_HBCICARD_TYPE_0 1 #define k_HBCICARD_TYPE_1 2 #include #include /** * This class provides easy access to HBCI cards. * You may read and write from/to those cards. * DDV cards of type 0 and of type 1 are supported. This class does not * support RSA cards (like G&D cards). * @author Martin Preuss * @ingroup scards * @short Special class for HBCI (German Home Banking Computer Interface) cards */ class CHIPCARD_API HBCICard : public CTProcessorCard { private: int _type; string _cid; string _cmdPutInstData; string _cmdVerifyPin; string _cmdSecureVerifyPin; s_card_id *_make_card_id(string &data); /** * Selects DF_BANKING/DF_BANKING_20 and checks whether it is a type 0 * or type 1 card. */ CTError _checkType(); /** For type 0 cards */ bool _hash2mac0(string &hash, string &mac); /** For type 1 cards */ bool _hash2mac1(string &hash, string &mac); bool _getKeyVersion0(int key,int &kv); bool _getKeyVersion1(int key,int &kv); CTError _getCID(string &cid); public: /** * This class describes a HBCI card. * @author Martin Preuss */ class CHIPCARD_API CardData { private: unsigned char _cardtype; unsigned char _industrialkey; unsigned int _shortinstcode; string _cardnumber; unsigned char _bestuntil_year; unsigned char _bestuntil_month; unsigned char _active_year; unsigned char _active_month; unsigned char _active_day; unsigned short _countrycode; string _currency; public: CardData(); CardData(const string &s, int cardtype); ~CardData(); /** * The type of the card: k_HBCICARD_TYPE_0, k_HBCICARD_TYPE_1 * or k_HBCICARD_TYPE_UNKNOWN. */ int cardType() const { return _cardtype;}; /** * "Branchenhauptschluessel", dont know what that means but it has * always value 67. */ int industrialKey() const { return _industrialkey;}; /** * Short institute code of card delivering institute. */ unsigned int shortInstituteCode() const { return _shortinstcode;}; /** * ASCII-String cardnumber. */ const string &cardNumber() const { return _cardnumber;}; /** * Card is valid until THIS year. */ int bestuntil_year() const { return _bestuntil_year;}; /** * Card is valid until THIS month. */ int bestuntil_month() const { return _bestuntil_month;}; /** * Year of the card's activation. */ int active_year() const { return _active_year;}; /** * Month of the card's activation. */ int active_month() const { return _active_month;}; /** * Day of the card's activation. */ int active_day() const { return _active_day;}; /** * Country code (280 stands for Germany). */ int countryCode() const { return _countrycode;}; /** * Currency string ("DEM", "EUR"). */ const string ¤cy() const { return _currency;}; }; /** * This class describes a user at a credit institute. * @author Martin Preuss */ class CHIPCARD_API instituteData { private: string _name; string _code; char _service; string _addr; string _addr_suffix; int _country; string _user; public: /** * Name of the credit institute. */ const string &name() const { return _name;}; /** * ASCII institute code ("Bankleitzahl"). */ const string &code() const { return _code;}; void setCode(const string &c) { _code=c;}; /** * Service type (2=TCP, 1=CEPT). */ char service() const { return _service;}; void setService(char s) { _service=s;}; /** * ASCII comunication address (for tcp: server address). */ const string &address() const { return _addr;}; void setAddress(const string &a) { _addr=a;}; /** * Address suffix (unused with tcp). */ const string &addressSuffix() const { return _addr_suffix;}; void setAddrSuffix(const string &s) { _addr_suffix=s;}; /** * country code ("280" for Germany). */ int country() const { return _country;}; void setCountry(int i) { _country=i;}; /** * Your user id for that credit institute. */ const string &user() const { return _user;}; void setUser(const string &u) { _user=u;}; instituteData(const string &data); instituteData(); ~instituteData(); CTError fromString(const string &data); string toString() const; string dump(); }; /** @name Constructors/Destructor * * Methods to retrieve the private members of this class. */ //@{ HBCICard(const CTCard &c); ~HBCICard(); //@} /** @name Opening and closing operations * * Methods to connect and disconnect the card. Most other methods * only work if the card is open. */ //@{ /** * When this method is called normally the card is already opened by * means of @ref openCard(). However, it is likely that openCard() has * been called assuming this card is only a CTCard() object, nothing * special. You may then call THIS method here on all known card classes * to check for the type of this card. * This method must assume that any file on the card is already selected, * so it is in most cases a good idea to select the MF as the first action * of this method. * If the executing class finds that the card inserted is not of a type * it can handle then it MUST return an error. */ virtual CTError reopenCard(); /** * Opens the card for usage. * This way the card is powered on. * This method does some basic checks and retrieves basic information * about the card (whether it is a memory card or a processor card, * the size of the memory etc). * When this method successfully returns the card may be used. * @author Martin Preuss * @return CTError object that holds the result (call isOk() to see if * there was an error) */ virtual CTError openCard(); /** * Call this if you have finished working with the card. After this * method is called you may safely remove the card from the reader. * @author Martin Preuss * @return CTError object that holds the result (call isOk() to see if * there was an error) */ virtual CTError closeCard(bool force=false); //@} /** @name Informational methods * * These methods tell you about the type and the status of the card. */ //@{ /** * This method returns a short name of the class which handles this card. * A HBCI card for example returns "HBCICard". So you can use this method * to check for the type of the card. */ virtual string cardType(); /** * This method returns a comma separated list of all card types this card * inherits including the type of this card, e.g. a HBCI card would * return "CTProcessorCard, HBCICard". If you overload this method in your * own class (you SHOULD) you simply have to call this method of the * class it directly inherits. That class will then do the same, so that * there is a list upon return. */ virtual string cardTypes(); /** * This method returns the cardnumber. This number is quite unique. * @author Martin Preuss * @return on error en empty string will be returned */ string cardNumber(); //@} /** @name Card Data Methods * * These methods return information about the HBCI card. */ //@{ /** * Gets the card's id struct and selects the appropriate * DF_BANKING or DF_BANKING_20 DF. May throw an CTError. * @author Martin Preuss * @return new CardData object * null on error */ CardData getCardId(); /** * Reads the full EF_ID file from the MF of the chip card. * Is needed by HBCI. * @author Martin Preuss * @return CTError object that holds the result (call isOk() to see if * there was an error) */ CTError getCID(string &cid); //@} /** @name Institute Data Methods * * These methods return information about institutes stored on the card. */ //@{ /** * Gets you the institute data struct for the given entry. The HBCI card * stores up to 5 entries with number 1 being the first. * You have to VERIFY your pin prior to calling this method ! * @author Martin Preuss * @return object containing the institute data. If an error occurs * it will be thrown. */ instituteData getInstituteData(int num); /** * This is a non-exception version, it is temporarily used be OpenHBCI. */ CTError getInstituteData(int num, instituteData &idata); /** * This writes the given institute data to the card. Of course it has to * be open for this and you have to have verified your pin with the * card. * @author Martin Preuss * @return error object */ CTError putInstituteData(int num, const instituteData &d); //@} /** @name Pin Verification Methods * * These methods let you verify the pin with the card. */ //@{ /** * Verifies your pin with the ec card. * @author Martin Preuss * @return CTError object that holds the result (call isOk() to see if * there was an error) * @param pin the PIN to verify */ CTError verifyPin(const string &pin); /** * This method lets the user enter the pin via the pin pad. * @author Martin Preuss */ CTError verifyPin(); //@} /** @name Key Information Methods * * These methods return information about the keys stored on the card. */ //@{ /** * Returns the version of a the local EF_KEY (that is that EF_KEY * which resides in the currently selected DF). * @author Martin Preuss * @return true if version could be retrieved, false on error * @param key key number (starting with 1) * @param kv reference to a variable which receives the key version */ bool getKeyVersion(int key, int &kv); /** * Returns the key number of the crypt key (with 1 being the first) * @author Martin Preuss * @return false on error */ bool getCryptKeyNumber(int &kn); /** * Returns the key number of the sign key (with 1 being the first) * @author Martin Preuss * @return false on error */ bool getSignKeyNumber(int &kn); //@} /** @name Cryptographic Methods * * These methods are involved in en-/decryption. */ //@{ /** * Creates a MAC from a 20 byte hash. * According to HBCI standard this has to be a RIPEMD-160 hash. * @author Martin Preuss * @return true if mac contains valid MAC, false on error * @param hash reference to a string containing the 20 bytes RIPEMD-160 * hash * @param mac reference to a string that receives the 8 byte MAC. */ bool hash2MAC(string &hash, string &mac); /** * Creates random data (8 bytes). * @author Martin Preuss * @return false on error */ bool getRandom(string &d); /** * Crypts a block of 8 bytes. * It uses the encrypting function of the chip card. That means if * you crypt a block twice with this method here you do NOT get the * clear text again ! * @author Martin Preuss * @param src reference to a string containing the 8 bytes source * @param dst reference to a string to receive the decoded 8 bytes */ bool cryptBlock(string &src, string &dst); //@} /** @name Sequence Counter Methods * * These methods allow reading and writing of the cards sequence counter. * This counter is to be incremented after signing a HBCI message. */ //@{ /** * Reads the sequence counter from the chipcard. * This counter should be incremented before signing a HBCI message. * This method is only available to call after inserting the card. * @author Martin Preuss * @return true if value is read, false on error */ bool readSEQ(unsigned int &d); /** * Stores the value of the sequence counter which is stored in this * class at this moment. Call this after incrementing this value ! * @author Martin Preuss * @return false on error */ bool writeSEQ(unsigned int d); //@} }; #endif