/***************************************************************************
 $RCSfile: rsacard.h,v $
 -------------------
 cvs         : $Id: rsacard.h,v 1.12 2003/01/10 20:02:31 aquamaniac Exp $
 begin       : Sat Dec 14 2002
 copyright   : (C) 2002 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                                                   *
 *                                                                         *
 ***************************************************************************/



/*___________________________________________________________________________
 *AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*
 *                            W A R N I N G ! !                             *
 *                                                                          *
 * This class is under heavy development, it might render your card         *
 * useless !!                                                               *
 * For now this class implements all methods I will need to add support for *
 * this previously unsupported card to OpenHBCI.                            *
 * YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY*
 */



#ifndef RSACARD_H
#define RSACARD_H

#include <chipcard/ctprocessorcard.h>
#include <chipcard/ctmisc.h>
#include <list>
using namespace std;


#define KEY_STATUS_ACTIVE            0x10
#define KEY_STATUS_INACTIVE_CERT     0x0a
#define KEY_STATUS_INACTIVE_FREE     0x08
#define KEY_STATUS_INACTIVE_NEW      0x07
#define KEY_STATUS_ACTIVE_NEW        0x02
#define KEY_STATUS_ACTIVE_INCOMPLETE 0x01
#define KEY_STATUS_ACTIVE_INILETTER  0x00
#define KEY_STATUS_INTERNAL_UNUSED   0xff



/**
 *
 * @ingroup scards
 */
class CHIPCARD_API RSACard: public CTProcessorCard {
public:
  class BankDescription {
  private:
    bool _chg;
    int _country;
    string _bankName;
    string _userId;
    char _service;
    string _address;
    string _addressSuffix;
    string _bankId;
    string _systemId;
  public:
    BankDescription();
    BankDescription(const string &data);
    ~BankDescription();
    int country() const { return _country;};
    void setCountry(int i) { _country=i;};
    const string &bankName() const { return _bankName;};
    void setBankName(const string &s) { _chg=true; _bankName=s;};
    const string &userId() const { return _userId;};
    void setUserId(const string &s) { _chg=true; _userId=s;};
    char service() const { return _service;};
    void setService(char c) { _chg=true; _service=c;};
    const string &address() const { return _address;};
    void setAddress(const string &s) { _chg=true; _address=s;};
    const string &addressSuffix() const { return _addressSuffix;};
    void setAddressSuffix(const string &s) { _chg=true; _addressSuffix=s;};
    const string &bankId() const { return _bankId;};
    void setBankId(const string &s) { _chg=true; _bankId=s;};
    const string &systemId() const { return _systemId;};
    void setSystemId(const string &s) { _chg=true; _systemId=s;};
    string toString() const;
    bool changed() const {return _chg;};
    string dump();
  };

  struct KeyLogStatus {
    unsigned maxEntries : 3;
    unsigned oldENfree  : 1;
    unsigned entries    : 3;
    unsigned oldDSfree  : 1;
  };

public:
  class KeyDescriptor {
  private:
    bool _chg;
    unsigned int _status;
    bool _isSignKey;
    int _keynum;
    int _keyver;
  public:
    KeyDescriptor();
    KeyDescriptor(unsigned int st,
		  bool isSignKey,
		  int keynum,
		  int keyver);
    KeyDescriptor(const string &data);
    ~KeyDescriptor();
    string toString() const;
    unsigned int status() const { return _status;};
    void setStatus(unsigned int s) { _chg=true; _status=s;};
    bool isSignKey() const { return _isSignKey;};
    void setIsSignKey(bool b) { _chg=true; _isSignKey=b;};
    int keyNumber() const { return _keynum;};
    void setKeyNumber(int k) { _chg=true; _keynum=k;};
    int keyVersion() const { return _keyver;};
    void setKeyVersion(int k) { _chg=true; _keyver=k;};
    bool changed() const {return _chg;};
    string dump();
  };

private:
  string _cmdReadFile;
  string _cmdUpdateBinary;
  string _cmdUpdateRecord;
  string _cmdGenerateKeyPair;
  string _cmdManageSE;
  string _cmdSelectPubKey;
  string _cmdSelectPrivKey;
  string _cmdPutHash;
  string _cmdSign;
  string _cmdVerify;
  string _cmdChallenge;
  string _cmdEncipher;
  string _cmdDecipher;
  string _cmdActivateKey;
  string _cmdVerifyPin;
  string _cmdSecureVerifyPin;
  string _cmdChangePin;
  string _cmdSecureChangePin;
  string _firstPin;


  CTError _readFile(unsigned short fid, string &data);
  CTError _getInitialPin(string &pin);
  CTError _openCard();
  /**
   * @return -1 if not found, key index otherwise
   */
  int _findPublicKey(unsigned int kid);
  CTError _manageSE(int tmpl, int kids, int kidp, int ar);
  int _getKeyPos_EF_LOG(int kid);
  CTError _changePin(int pinid, const string &oldpin,
		     const string &newpin);
  CTError _changePin(int pinid);
  CTError _verifyPin(int pinid, const string &pin);
  CTError _verifyPin(int pinid);

public:
  /** @name Constructors and Destructors
   *
   * Methods to connect and disconnect the card. Most other methods
   * only work if the card is open.
   */
  //@{
  /**
   * Constructor. This one does no interaction with the terminal reader.
   * @author Martin Preuss<martin@libchipcard.de>
   */
  RSACard();

  RSACard(CTCard &c);

  ~RSACard();
  //@}

  /** @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<martin@libchipcard.de>
   * @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<martin@libchipcard.de>
   * @return CTError object that holds the result (call isOk() to see if
   * there was an error)
   */
  virtual CTError closeCard(bool force=false, bool eject=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();

  /**
   * Returns the initial pin of a pristine card.
   * On such a card verifying the pin does not work as long as you did not
   * change the pin using @ref changePin(). The initial pin (which MUST be
   * changed) is the serial number of the card stored in one of the files
   * on it. With this method here you get that number.
   * This method is only valid after @ref openCard() has been called
   * successfully.
   */
  const string &initialPin() const { return _firstPin;};

  /**
   * Returns the cards serial number.
   */
  string cardNumber() const { return CTMisc::bin2hex(_firstPin);};
  //@}

  /** @name Pin Verification and Changes
   *
   * These method allow verifying and changing the pin. There are methods
   * for terminals with keypads, too. On these you can enter the pin
   * directly into the card readers keypad (secure mode).
   */
  //@{
  /**
   * Verifies the pin without using the keypad. If your reader has a
   * key pad I recommend using the secure method !!
   * @return error code
   * @param kid key id (0x90 for Keyholder pin, 0x91 for device pin)
   * @param pin pin (ASCII)
   */
  CTError verifyPin(int kid, const string &pin);

  /**
   * Changes the pin without using the keypad. If your reader has a
   * keypad I recommend using the secure method !!
   * @return error code
   * @param kid key id (0x90 for Keyholder pin, 0x91 for device pin)
   * @param oldpin old pin (ASCII)
   * @param newpin new pin (ASCII)
   */
  CTError changePin(int kid,
		    const string &oldpin,
		    const string &newpin);

  /**
   * Changes the pin using the keypad of your reader. This is the recommended
   * method of changing the pin, since no trojan horse can spy out your
   * pin !
   * @return error code
   * @param kid key id (0x90 for Keyholder pin, 0x91 for device pin)
   */
  CTError changePin(int kid);

  /**
   * Verifies the pin using the keypad of your reader. This is the recommended
   * method of verifying the pin, since no trojan horse can spy out your
   * pin !
   * @return error code
   * @param kid key id (0x90 for Keyholder pin, 0x91 for device pin)
   */
  CTError verifyPin(int kid);
  //@}


  /**
   * @name Key Management
   *
   * This group contains methods to create, read, write, inspect and update
   * keys on the card.
   */
  //@{

  /**
   * Deletes a key descriptor. This allows overwriting a key stored on the
   * card.
   * @param kid key id
   */
  CTError deleteKeyDescriptor(int kid);

  /**
   * Reads the key status for the given key.
   */
  unsigned int readKeyStatus(int kid);

  /**
   * Updates the key status for the given key.
   */
  CTError writeKeyStatus(int kid, unsigned int st);

  /**
   * This method updates a full 8 byte key descriptor.
   */
  CTError writeKeyDescriptor(int kid, const string &kd);

  /**
   * Reads a fully 8 byte key descriptor.
   */
  string readKeyDescriptor(int kid);

  /**
   * Reads the modulus of a public key. The exponent is defined to be
   * always 0x010001.
   */
  string readPublicKey(int kid);

  /**
   * Updates the modulus of a public key. This is used to store the partners
   * public keys on the card (like the pulic keys of the bank).
   */
  CTError writePublicKey(int kid, const string &modulus);

  /**
   * Creates a keypair for the given key id. This can take some seconds
   * (up to a minute). The key pair created is not automatically activated.
   * @return modulus of the key created
   */
  string createKey(int kid,bool overwrite);

  /**
   * This activates a previously created key pair. After this method has been
   * called the new keys are stored at their final destination and used by
   * all subsequent calls to cryptographic methods with this key id.
   */
  CTError activateKey(int kid, int num, int ver);

  /**
   * Checks whether the given key id belongs to a partner of to us.
   */
  bool isBankKey(int kid);

  /**
   * Checks whether the given key id belongs to a signature key.
   */
  bool isSignKey(int kid);

  /**
   * Translates the given information about a key into a key id which can then
   * be used for the other methods of this class.
   */
  int getKeyId(int bank, bool pub, bool sign);

  /**
   * The keylog status contains information about how many bank descriptions
   * are in use and about whether there are newly generated but not yet
   * activated keys.
   */
  KeyLogStatus readKeyLogStatus();

  /**
   * Updates the keylog status.
   */
  CTError writeKeyLogStatus(KeyLogStatus st);
  //@}


  /**
   * @name Bank Descriptions
   *
   * Methods of this group read, delete and update bank descriptions on the
   * card.
   */
  //@{
  BankDescription readBankDescription(int idx);
  CTError writeBankDescription(int idx, const BankDescription &bd);
  CTError deleteBankDescription(int idx);
  int findFreeBankDescription();
  //@}

  /**
   * @name Cryptographic Methods
   *
   * Methods of this group allow signing, verifying a signature, encrypting
   * and decrypting data.
   */
  //@{
  string getRandom(int s);
  string sign(int kid, const string &data);
  CTError verify(int kid, const string &data,
		 const string &signature);
  string encrypt(int kid, const string &data);
  string decrypt(int kid, const string &data);
  //@}

  /**
   * @name Signature Sequence Counter
   *
   * This group contains methods concerning the signature sequence counter.
   * This can only be read (not written) and is updated automatically upon
   * @ref sign(). When creating keys for a bank context then this counter
   * is reset to 0.
   */
  //@{
  unsigned int readSeq(int bank);
  CTError writeSeq(int bank, unsigned int seq);
  //@}
};







#endif


