/***************************************************************************
 $RCSfile: mediumrdhbase.h,v $
                             -------------------
    cvs         : $Id: mediumrdhbase.h,v 1.17 2003/05/16 15:40:57 aquamaniac Exp $
    begin       : Tue Aug 27 2002
    copyright   : (C) 2002 by Martin Preuss
    email       : openhbci@aquamaniac.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 mediumrdhbase.h 
 *
 * @short Base class for RDH media HBCI::MediumRDHBase and C wrapper
 * @ref HBCI_MediumRDHBase */

#ifndef MEDIUMRDHBASE_H
#define MEDIUMRDHBASE_H

#ifdef __cplusplus
#include <string>
#endif /* __cplusplus */
#include <openhbci/medium.h>
#ifdef __cplusplus
#include <openhbci/cryptkey.h>
#include <openhbci/rsakey.h>

namespace HBCI {

/**
 * @short Base class for all RDH based media.
 *
 * This is a base class for all RSA-DES-hybrid (RDH) media. RSA keys
 * are used for authentification and encryption of the session keys,
 * and Triple-DES-keys are used as session keys for the actual
 * encryption of messages.
 *
 * Currently only key files are supported, but in future RDH chip
 * cards might also be implemented.
 *
 * @author Martin Preuss<martin@aquamaniac.de> */
class DLLIMPORT MediumRDHBase: public Medium {
public:
    /**
     * Constructor.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @param hbci pointer to the HBCI object your program uses.
     */
    MediumRDHBase(const Hbci *hbci);

    virtual ~MediumRDHBase();

    /** @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 Error selectContext(int country,
				const string &instcode,
				const string &userid)=0;

    /**
     * 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 Error createMedium(int country,
			       const string &instcode,
			       const string &userid,
			       const string &pin="")=0;

    /**
     * Mounts a medium and makes its crypto methods available.
     *
     * @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(const string &pin="")=0;

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

    /**
     * Change the PIN that is used to protect the medium data.<br>
     * The old and new PIN is requested via the Hbci::interactor()
     */
    virtual Error changePIN();

    /**
     * Change data that is stored on the medium.<br>
     * Note: Each paramter you don't specify is <b>not</b> changed.<br>
     * @param context Medium supports multiple contexts, use this
     * parameter to select it (1..n)
     * @param country The new country code (280 for Germany)
     * @param instcode The new institute code
     * @param userid The new user id
     * @param custid The new customer id
     * @param server The new server address
     */
    virtual Error changeContext(int context, int country=0,
				const string instcode="",
				const string userid="",
				const string custid="",
				const string server="");

    virtual unsigned int nextSEQ()=0;

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

    /**
     * Directly set the seq counter
     */
    virtual void setSEQ(int seq)=0;

    /*@}*/

    /** @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()=0;

    /**
     * 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 =0;

    /**
     * Returns the security mode of this medium (DDV, RDH)
     * @author Martin Preuss<openhbci@aquamaniac.de>
     */
    virtual int securityMode() const { return HBCI_SECURITY_RDH;};

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

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

    /**
     * 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 =0;

    /**
     * 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 =0;

    /**
     * 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 =0;

    /**
     * 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 =0;

    /**
     * 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 =0;

    /**
     * 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 Error getContext(int num,
			     int &countrycode,
			     string &instcode,
			     string &userid,
			     string &server) const =0;
    /*@}*/
    
    /** @name Cryptographic Methods */
    /*@{*/
    /**
     * Creates a key for encryption of data.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return false on error
     */
    virtual string createMessageKey() const =0;

    /**
     * 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) =0;

    /**
     * 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) =0;

    /**
     * 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 Error verify(const string &data, const string &signature) =0;

    /**
     * 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) =0;

    /*@}*/

    /** @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 Error createUserKeys(bool activate=true)=0;

    /**
     * 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 Error activateKeys()=0;

    /**
     * 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>
     */
    virtual Pointer<RSAKey> getTempSignKey()=0;

    /**
     * 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>
     */
    virtual Pointer<RSAKey> getTempCryptKey()=0;

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

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

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

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

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

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

    /** @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 =0;

    /**
     * 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 =0;

    /**
     * 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 =0;

    /**
     * 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 =0;
    /**
     * 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 =0;

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

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

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

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

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

    /** The minimum size of a new PIN, otherwise it will not be
     * accepted and an Error will be thrown. */
    const static unsigned int minPinSize;
};

} /* namespace HBCI */

/** @ingroup HBCI_Mediumg */
typedef HBCI::MediumRDHBase HBCI_MediumRDHBase;
extern "C" {
#else /* __cplusplus */
    typedef struct HBCI_MediumRDHBase HBCI_MediumRDHBase;
#endif /* __cplusplus */
    /** @name HBCI_MediumRDHBase methods 
     * @ingroup HBCI_Mediumg */
    /*@{*/
    /** Upcast. */
    extern HBCI_Medium *HBCI_MediumRDHBase_Medium(HBCI_MediumRDHBase *h);
    /** Downcast. Returns NULL if this is not a MediumRDHBase. */
    extern HBCI_MediumRDHBase *HBCI_Medium_MediumRDHBase(HBCI_Medium *h);
    /** Returns true, if the institute/bank of this MediumRDH uses a
     * public signature key. */
    extern int 
    HBCI_MediumRDHBase_hasInstSignKey(const HBCI_MediumRDHBase *h);
    /**
     * Returns the version of the institute key.
     *
     * @param h The object to perform this action on.
     * @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>.  */
    extern char *
    HBCI_MediumRDHBase_getInstIniLetterExponent(const HBCI_MediumRDHBase *h, 
						int usecrypt);
    /**
     * Returns the version of the institute key.
     *
     * @param h The object to perform this action on.
     * @param usecrypt If true, then the data of <i>crypt</i> key is
     * read instead of that of the <i>sign</i> key. See
     * HBCI_MediumRDHBase_getInstIniLetterExponent().
     */
    extern char *
    HBCI_MediumRDHBase_getInstIniLetterHash(const HBCI_MediumRDHBase *h, 
					    int usecrypt);
    /**
     * Returns the version of the institute key.
     *
     * @param h The object to perform this action on.
     * @param usecrypt If true, then the data of <i>crypt</i> key is
     * read instead of that of the <i>sign</i> key. See
     * HBCI_MediumRDHBase_getInstIniLetterExponent().
     */
    extern char *
    HBCI_MediumRDHBase_getInstIniLetterModulus(const HBCI_MediumRDHBase *h, 
					       int usecrypt);
    /**
     * Returns the version of the institute key.
     *
     * @param h The object to perform this action on.
     * @param usecrypt If true, then the data of <i>crypt</i> key is
     * read instead of that of the <i>sign</i> key. See
     * HBCI_MediumRDHBase_getInstIniLetterExponent().
     */
    extern int 
    HBCI_MediumRDHBase_getInstKeyNumber(const HBCI_MediumRDHBase *h, 
					int usecrypt);
    /**
     * Returns the version of the institute key.
     *
     * @param h The object to perform this action on.
     * @param usecrypt If true, then the data of <i>crypt</i> key is
     * read instead of that of the <i>sign</i> key. See
     * HBCI_MediumRDHBase_getInstIniLetterExponent().
     */
    extern int 
    HBCI_MediumRDHBase_getInstKeyVersion(const HBCI_MediumRDHBase *h, 
					 int usecrypt);

    /**
     * return the ini-letter-exponent that is needed to print the ini-letter
     */
    extern char *
    HBCI_MediumRDHBase_getUserIniLetterExponent(const HBCI_MediumRDHBase *h);
    /**
     * return the ini-letter-hash that is needed to print the ini-letter
     */
    extern char *
    HBCI_MediumRDHBase_getUserIniLetterHash(const HBCI_MediumRDHBase *h);
    /**
     * return the ini-letter-modulus that is needed to print the ini-letter
     */
    extern char *
    HBCI_MediumRDHBase_getUserIniLetterModulus(const HBCI_MediumRDHBase *h);
    /**
     * This method is needed when generating the users ini letter.
     * @return the number of the user's public crypt key
     */
    extern int 
    HBCI_MediumRDHBase_getUserKeyNumber(const HBCI_MediumRDHBase *h);
    /**
     * This method is needed when generating the users ini letter.
     * @return the version of the user's public crypt key
     */
    extern int 
    HBCI_MediumRDHBase_getUserKeyVersion(const HBCI_MediumRDHBase *h);
    /*@}*/

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif

