/***************************************************************************
 $RCSfile: mediumrsacard.h,v $
 -------------------
 cvs         : $Id: mediumrsacard.h,v 1.5 2003/02/10 13:23:15 cstim Exp $
 begin       : Sun Dec 15 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                                                   *
 *                                                                         *
 ***************************************************************************/

/** @file mediumrsacard.h
 *
 */

#ifndef MEDIUMSACARD_H
#define MEDIUMSACARD_H "$Id"


#ifdef HAS_LIBCHIPCARD
#ifdef __cplusplus
#include <chipcard.h>
#endif /* __cplusplus */

/* Only continue if sufficiently new libchipcard version is available */
#if (k_CHIPCARD_VERSION_MAJOR>0 || k_CHIPCARD_VERSION_MINOR>6)

#ifdef __cplusplus
#include <chipcard/rsacard.h>

#include <string>
#endif /* __cplusplus */
#include <openhbci/mediumrdhbase.h>
#ifdef __cplusplus
#include <openhbci/cryptkey.h>
#include <openhbci/rsakey.h>
#include <list>
using namespace std;

namespace HBCI {

/**
 * @short Medium for RSA cards.
 *
 * @author Martin Preuss<martin@aquamaniac.de> */
class DLLIMPORT MediumRSACard: public MediumRDHBase, public RSACard {
private:
  int _mountCount;
  string _cardNumber;
  int _context;
  BankDescription _descr;

  Pointer<RSAKey> _userPubSignKey;
  Pointer<RSAKey> _userPubCryptKey;
  Pointer<RSAKey> _instPubSignKey;
  Pointer<RSAKey> _instPubCryptKey;
  Pointer<RSAKey> _tempCryptKey;
  Pointer<RSAKey> _tempSignKey;

  Pointer<RSAKey> _makeRSAKey(bool sign,
			      int num, int ver,
			      const string &modulus);
  Pointer<RSAKey> _readKey(bool bank, bool sign);
  Pointer<RSAKey> _getInstPubCryptKey() const;
  Pointer<RSAKey> _getInstPubSignKey() const;

protected:
#if k_CHIPCARD_VERSION_MAJOR>0 || k_CHIPCARD_VERSION_MINOR>6
  virtual CallBackResult doCallBack(bool first);
#endif

public:
  /**
   * Constructor.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @param hbci pointer to the HBCI object your program uses.
   */
  MediumRSACard(const Hbci *hbci, const string &cardNumber);

  virtual ~MediumRSACard();

  /** @name Medium management */
  /*@{*/
  /**
   * Since some media (like hbci chip cards) are able to store multiple
   * account entries you have to select one.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual bool selectContext(int country,
			     const string &instcode,
			     const string &userid);

  /**
   * Creates a context in your medium. A context is just the combination of a userid and the
   * institute code (+ country code).
   * IMPORTANT: If you want to add a context to an already existing
   * medium you MUST call this method with the medium MOUNTED !!
   * Otherwise the keys on that medium will be LOST !!
   * Well, of course, if that medium does not exist you have to this method
   * without prior mounting (since there is nothing to mount).
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual bool createMedium(int country,
			    const string &instcode,
			    const string &userid,
			    const string &pin="");

  /**
   * Mounts a medium and makes its crypto methods available.
   *
   * @param user Pointer to the user that wants to mount this
   * medium. Used only for information purposes in the
   * HBCI::Interactor. May be an invalid (NULL) pointer .
   *
   * @param pin The secret PIN that is needed to actually mount this
   * medium. If omitted the user will be asked for it when needed.
   *
   * @author Martin Preuss<openhbci@aquamaniac.de>
   *
   * @return An HBCI::Error, where Error.isOk()==true if medium mounted
   */
  virtual Error mountMedium(Pointer<User> user = 0, const string &pin="");

  /**
   * Unmounts a medium so that it may be removed.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if medium unmounted
   */
  virtual void unmountMedium(const string &pin="");

  virtual unsigned int nextSEQ();

  /**
   * Sets the seq counter to 1
   */
  virtual void resetSEQ();

  /*@}*/

  /** @name Medium Information */
  /*@{*/
  /**
   * Checks whether the medium is mounted.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if medium unmounted, false if not (or on error)
   */
  virtual bool isMounted();

  /**
   * Returns the id of the medium. For DDV this is the CID of the chip
   * card, for RDH this is the system ID assigned to us by an institute.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual string mediumId() const ;

  /**
   * Returns the id of the medium.
   * For DDV this is the card number, for RDH this is the name of the file.
   * In this case it is the serial number of the card.
   */
  virtual const string& mediumName() const ;

  /**
   * Returns the type this medium is of.
   *
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual MediumType mediumType() const { return MediumRDHCard; };

  /**
   * Returns the number of the sign key. RDH-media should return
   * the number of the users private sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual int signKeyNumber() const ;

  /**
   * Returns the version of the crypt key. RDH-media should return
   * the version of the users private sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual int signKeyVersion() const ;

  /**
   * Returns the number of the crypt key. RDH-media should return
   * the number of the institutes public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual int cryptKeyNumber() const ;

  /**
   * Returns the version of the crypt key. RDH-media should return
   * the version of the institutes public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual int cryptKeyVersion() const ;

  /**
   * Returns the user ID of the owner of the crypt key. RDH-media
   * should return the owner of the institutes public crypt
   * key. This is retrieved from HIISA segments.
   *
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual const string &cryptKeyOwner() const ;

  /**
   * Returns the context with the given number.
   * Some media are able of storing multiple contexts (like chip cards).
   * Please note that the medium has to be mounted prior to calling this
   * method.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if a context with that number exists, false on error
   * @param num number of the context (starting with 1)
   * @param countrycode reference to an int var to receive the country code
   * of the context (280 for Germany)
   * @param instcode reference to a string variable to receive the institute
   * code of that context (German "Bankleitzahl")
   * @param userid reference to a string variable to receive the user id of
   * the context (assigned to you by the institute)
   * @param server reference to a string to receive the server address
   */
  virtual bool getContext(int num,
			  int &countrycode,
			  string &instcode,
			  string &userid,
			  string &server) const ;
  /*@}*/

  /** @name Cryptographic Methods */
  /*@{*/
  /**
   * Creates a key for encryption of data.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   */
  virtual string createMessageKey() const ;

  /**
   * Lets the card encrypt the key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param srckey the key to encode
   */
  virtual string encryptKey(const string &srckey) ;

  /**
   * Lets the card decrypt the key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param srckey the key to decode
   */
  virtual string decryptKey(const string &srckey) ;

  /**
   * Verify the signature of given data
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param data data whose signatur is to be verified
   * @param signature signature to compare against
   */
  virtual bool verify(const string &data, const string &signature) ;

  /**
   * sign data
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param data data whose signatur is to be created
   */
  virtual string sign(const string &data) ;

  /*@}*/

  /** @name Key Generation and management */
  /*@{*/
  /**
   * Generates the users sign and crypt keys.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @param activate if true then the key will be activated immediately.
   *  Otherwise just a temporary key will be created which must be activated
   *  by calling @ref activateKey(). If the key is not activated you can get
   * it by calling @ref getTempSignKey() and @ref getTempCryptKey().
   */
  virtual bool createUserKeys(bool activate=true) ;

  /**
   * Activates the previously created keys. This is <b>required</b> if
   * you specified "false" as arguement to @ref createUserKeys().
   * This will finally store the created keys to their destination, so that
   * they are usable for further signing/crypting.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual bool activateKeys();

  /**
   * This returns the temporary sign key which has been created by
   * @ref createUserKeys(). You'll need this in a key change protocol.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  Pointer<RSAKey> getTempSignKey();

  /**
   * This returns the temporary crypt key which has been created by
   * @ref createUserKeys(). You'll need this in a key change protocol.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  Pointer<RSAKey> getTempCryptKey();

  /**
   * Sets the institutes public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual bool setInstituteCryptKey(Pointer<RSAKey> cryptkey) ;

  /**
   * Sets the institutes public sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual bool setInstituteSignKey(Pointer<RSAKey> signkey) ;

  /**
   * Sets the SystemId.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual void setSystemId(const string &newid) ;
  /*@}*/

  /** @name Key Information */
  /*@{*/
  /** Returns true, if the institute/bank of this MediumRDH uses a
   * public signature key. */
  virtual bool hasInstSignKey() const ;

  /**
   * Returns the users public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual Pointer<RSAKey> userPubCryptKey() const ;

  /**
   * Returns the users public sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  virtual Pointer<RSAKey> userPubSignKey() const ;
  /*@}*/

  /** @name Ini-Letter Information */
  /*@{*/
  /** Returns the modulus of the institute key that is needed to
   * print the ini-letter.
   *
   * @param crypt If true, then the data of <i>crypt</i> key is read
   * instead of that of the <i>sign</i> key. This exists for the
   * case when your institute does not sign its messages. In that
   * not-so-good case, MediumRDH::hasInstSignKey returned false (the
   * inverse of this argument). If unsure, leave it to the default
   * value <code>false</code>.  */
  virtual string getInstIniLetterModulus(bool crypt=false) const ;

  /**
   * return the ini-letter-exponent that is needed to print the ini-letter
   *
   * @param crypt If true, then the data of <i>crypt</i> key is read
   * instead of that of the <i>sign</i> key. This exists for the
   * case when your institute does not sign its messages. In that
   * not-so-good case, MediumRDH::hasInstSignKey returned false (the
   * inverse of this argument). If unsure, leave it to the default
   * value <code>false</code>.  */
  virtual string getInstIniLetterExponent(bool crypt=false) const ;

  /**
   * return the ini-letter-hash that is needed to print the ini-letter
   *
   * @param crypt If true, then the data of <i>crypt</i> key is read
   * instead of that of the <i>sign</i> key. This exists for the
   * case when your institute does not sign its messages. In that
   * not-so-good case, MediumRDH::hasInstSignKey returned false (the
   * inverse of this argument). If unsure, leave it to the default
   * value <code>false</code>.
   */
  virtual string getInstIniLetterHash(bool crypt=false) const ;

  /**
   * Returns the number of the institute key.
   *
   * @param usecrypt If true, then the data of <i>crypt</i> key is read
   * instead of that of the <i>sign</i> key. This exists for the
   * case when your institute does not sign its messages. In that
   * not-so-good case, MediumRDH::hasInstSignKey returned false (the
   * inverse of this argument). If unsure, leave it to the default
   * value <code>false</code>.
   */
  virtual int getInstKeyNumber(bool usecrypt = false) const ;
  /**
   * Returns the version of the institute key.
   *
   * @param usecrypt If true, then the data of <i>crypt</i> key is read
   * instead of that of the <i>sign</i> key. This exists for the
   * case when your institute does not sign its messages. In that
   * not-so-good case, MediumRDH::hasInstSignKey returned false (the
   * inverse of this argument). If unsure, leave it to the default
   * value <code>false</code>.
   */
  virtual int getInstKeyVersion(bool usecrypt = false) const ;

  /**
   * return the ini-letter-modulus that is needed to print the ini-letter
   */
  virtual string getUserIniLetterModulus() const ;

  /**
   * return the ini-letter-exponent that is needed to print the ini-letter
   */
  virtual string getUserIniLetterExponent() const ;

  /**
   * return the ini-letter-hash that is needed to print the ini-letter
   */
  virtual string getUserIniLetterHash() const ;

  /**
   * This method is needed when generating the users ini letter.
   * @return the number of the user's public crypt key
   */
  virtual int getUserKeyNumber() const ;

  /**
   * This method is needed when generating the users ini letter.
   * @return the version of the user's public crypt key
   */
  virtual int getUserKeyVersion() const ;
  /*@}*/

};

} /* namespace HBCI */


#endif // __cplusplus

#endif // correct LibChipCard version
#endif // HAS_LIBCHIPCARD
#endif // MEDIUMSACARD_H
