/*
 *  Copyright (c) 2010-2026, Karsten Ohme
 *  This file is part of GlobalPlatform.
 *
 *  GlobalPlatform 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  GlobalPlatform 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 GlobalPlatform.  If not, see <https://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 * You must obey the GNU Lesser General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.
 */

/*! \file
 * This file contains all GlobalPlatform related functionality.
*/

#ifndef OPGP_GLOBALPLATFORM_H
#define OPGP_GLOBALPLATFORM_H

#ifdef __cplusplus
extern "C"
{
#endif

#ifndef max
#define max(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef min
#define min(a,b) (((a)>(b))?(b):(a))
#endif

#include <stdio.h>
#include "types.h"
#include "unicode.h"
#include "error.h"
#include "errorcodes.h"
#include "library.h"
#include "connection.h"
#include "security.h"
#include "stringify.h"

#define APDU_COMMAND_LEN 261 //!< The APDU command length: 5 bytes header + 255 body + Le
#define APDU_RESPONSE_LEN 258 //!< The APDU response length: 256 data + 2 bytes SW

/** The default key value for new cards defined in a VISA specification. */
static const BYTE OPGP_VISA_DEFAULT_KEY[16] = { 0x40, 0x41, 0x42, 0x43, 0x44,
		0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F };

/** The default mother key value for new GemXpresso cards. */
static const BYTE OPGP_GEMXPRESSO_DEFAULT_KEY[16] = { 0x47, 0x45, 0x4d, 0x58,
		0x50, 0x52, 0x45, 0x53, 0x53, 0x4f, 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45 };

static const BYTE GP211_CARD_MANAGER_AID[7] = { 0xA0, 0x00, 0x00, 0x01, 0x51,
		0x00, 0x00 }; //!< The AID of the Issuer Security Domain defined by GlobalPlatform 2.1.1 specification.

/** The AID of the Issuer Security Domain defined by GlobalPlatform 2.3.1 specification. */

static const BYTE GP231_ISD_AID[8] = { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00,
		0x00 };

static const BYTE GP211_CARD_MANAGER_AID_ALT1[8] = { 0xA0, 0x00, 0x00, 0x00,
		0x03, 0x00, 0x00, 0x00 }; //!< This AID is also used for the Issuer Security Domain, e.g. by JCOP 41 cards.

static const BYTE GP211_CARD_MANAGER_AID_ALT2[7] = { 0xA0, 0x00, 0x00, 0x00,
		0x03, 0x00, 0x00 }; //!< This AID is also used for the Issuer Security Domain old older OP2.0.1 cards, e.g., cyberflex cards

	static const BYTE GP211_CARD_MANAGER_AID_GEMPLUS[8] = { 0xA0, 0x00, 0x00, 0x00, 0x18, 0x43, 0x4D, 0x00 }; //!< This AID is uses for Gemplus cards

#define GP211_LIFE_CYCLE_LOAD_FILE_LOADED 0x01 //!< Executable Load File is loaded.
#define GP211_LIFE_CYCLE_CARD_OP_READY 0x01 //!< Card is OP ready.
#define GP211_LIFE_CYCLE_CARD_INITIALIZED 0x07 //!< Card is initialized.
#define GP211_LIFE_CYCLE_CARD_SECURED 0x0f //!< Card is in secured state.
#define GP211_LIFE_CYCLE_CARD_LOCKED 0x7f //!< Card is locked.
#define GP211_LIFE_CYCLE_CARD_TERMINATED 0xff //!< Card is terminated.
#define GP211_LIFE_CYCLE_APPLICATION_INSTALLED 0x03 //!< Application is installed
#define GP211_LIFE_CYCLE_APPLICATION_SELECTABLE 0x07 //!< Application is selectable.
#define GP211_LIFE_CYCLE_APPLICATION_LOCKED 0x83 //!< Application is locked.
#define GP211_LIFE_CYCLE_SECURITY_DOMAIN_INSTALLED 0x03 //!< Application is installed
#define GP211_LIFE_CYCLE_SECURITY_DOMAIN_SELECTABLE 0x07 //!< Application is selectable.
#define GP211_LIFE_CYCLE_SECURITY_DOMAIN_PERSONALIZED 0x0f //!< Application is personalized.
#define GP211_LIFE_CYCLE_SECURITY_DOMAIN_LOCKED 0x83 //!< Application is locked.

/* consts for MANAGE CHANNEL */

#define GP211_MANAGE_CHANNEL_OPEN 0x00 //!< Open the next available Supplementary Logical Channel.
#define GP211_MANAGE_CHANNEL_CLOSE 0x80 //!< Close the Supplementary Logical Channel.

/**
 * \brief Application privileges.
 */
typedef enum {
	GP211_SECURITY_DOMAIN = 1u << (7 + 16), //!< Application is security domain.
	GP211_DAP_VERIFICATION = 0xC0 << 16, //!< Application can require DAP verification for loading and installing applications.
	GP211_DELEGATED_MANAGEMENT = 0xA0 << 16, //!< Security domain has delegated management right.
	GP211_CARD_MANAGER_LOCK_PRIVILEGE = 1u << (4 + 16), //!< Application can lock the Card Manager.
	GP211_CARD_MANAGER_TERMINATE_PRIVILEGE = 1u << (3 + 16), //!< Application can terminate the card.
	GP211_DEFAULT_SELECTED_CARD_RESET_PRIVILEGE = 1u << (2 + 16), //!< Application is default selected. In GlobalPlatform 2.3.1 this was redefined as Card Reset privilege.
	GP211_PIN_CHANGE_PRIVILEGE = 1u << (1 + 16), //!< Application can change global PIN.
	GP211_MANDATED_DAP_VERIFICATION = 0xD0 << 16, //!< Security domain requires DAP verification for loading and installing applications.

	GP211_TRUSTED_PATH = 1u << (7 + 8), //!< Application is a Trusted Path for inter-application communication.
	GP211_AUTHORIZED_MANAGEMENT = 1u << (6 + 8), //!< Application is capable of Card Content Management; Security Domain privilege shall also be set.
	GP211_TOKEN_VERIFICATION = 1u << (5 + 8), //!< Application is capable of verifying a token for Delegated Card Content Management.
	GP211_GLOBAL_DELETE = 1u << (4 + 8), //!< Application may delete any Card Content.
	GP211_GLOBAL_LOCK = 1u << (3 + 8), //!< Application may lock or unlock any Application.
	GP211_GLOBAL_REGISTRY = 1u << (2 + 8), //!< Application may access any entry in the GlobalPlatform Registry.
	GP211_FINAL_APPLICATION = 1u << (1 + 8), //!< The only Application selectable in card Life Cycle State CARD_LOCKED and TERMINATED.
	GP211_GLOBAL_SERVICE = 1u << (0 + 8), //!< Application provides services to other Applications on the card.

	GP211_RECEIPT_GENERATION = 1u << 7, //!< Application is capable of generating a receipt for Delegated Card Content Management.
	GP211_CIPHERED_LOAD_FILE_DATA_BLOCK = 1u << 6, //!< The Security Domain requires that the Load File being associated with it is to be loaded ciphered.
	GP211_CONTACTLESS_ACTIVATION = 1u << 5, //!< Application is capable of activating and deactivating any Application on the contactless interface.
	GP211_CONTACTLESS_SELF_ACTIVATION = 1u << 4 //!< Application is capable of activating itself on the contactless interface without a prior request to the Application with the Contactless Activation privilege.
} GP211_APPLICATION_PRIVILEGES;

#define GP211_STATUS_APPLICATIONS 0x40 //!< Indicate Applications or Security Domains in GP211_get_status().
#define GP211_STATUS_ISSUER_SECURITY_DOMAIN 0x80 //!< Indicate Issuer Security Domain in GP211_get_status().
#define GP211_STATUS_LOAD_FILES 0x20 //!< Request GP211_APPLICATION_DATA for Executable Load Files in GP211_get_status().
#define GP211_STATUS_LOAD_FILES_AND_EXECUTABLE_MODULES 0x10 //!< Request GP211_EXECUTABLE_MODULES_DATA for Executable Load Files and their Executable Modules in GP211_get_status().

#define GP211_STATUS_TYPE_APPLICATIONS 0x40 //!< Indicate Applications or supplementary Security Domains in GP211_set_status().
#define GP211_STATUS_TYPE_ISSUER_SECURITY_DOMAIN 0x80 //!< Indicate Issuer Security Domain in GP211_set_status().
#define GP211_STATUS_TYPE_SECURITY_DOMAIN_AND_APPLICATIONS 0x60 //!< Indicate Security Domain and its associated Applications in GP211_set_status().

#define GP211_STATUS_FORMAT_NEW 0x02 //!< New GP2.1.1 GET STATUS format
#define GP211_STATUS_FORMAT_DEPRECATED 0x00 //!< New GP2.1.1 GET STATUS deprecated format

/* Key Access Condition for STORE DATA */
#define GP211_KEY_ACCESS_SD_AND_APPS 0x00 //!< Key may be used by the Security Domain and any associated Application
#define GP211_KEY_ACCESS_SD_ONLY 0x01 //!< Key may only be used by the Security Domain
#define GP211_KEY_ACCESS_APPS_ONLY 0x02 //!< Key may be used by any Application associated with the Security Domain but not by the Security Domain itself

/* Key Purpose for STORE DATA */
#define GP211_KEY_PURPOSE_SCP03 0x0003 //!< Key purpose for SCP03
#define GP211_KEY_PURPOSE_SCP04 0x0004 //!< Key purpose for SCP04
#define GP211_KEY_PURPOSE_SCP10 0x0010 //!< Key purpose for SCP10
#define GP211_KEY_PURPOSE_SCP11 0x0011 //!< Key purpose for SCP11
#define GP211_KEY_PURPOSE_TOKEN_VERIFICATION 0x7000 //!< Token Verification
#define GP211_KEY_PURPOSE_RECEIPT_GENERATION 0x7001 //!< Receipt Generation
#define GP211_KEY_PURPOSE_DAP_VERIFICATION 0x7003 //!< DAP Verification
#define GP211_KEY_PURPOSE_CASD_AND_CONFIDENTIAL_SETUP 0x7004 //!< CASD and Confidential Setup of Secure Channel Keys
#define GP211_KEY_PURPOSE_CIPHERED_LOAD_FILE 0x7005 //!< Ciphered Load File Data Block Key

// flags for STORE DATA

#define STORE_DATA_ENCRYPTION_NO_INFORMATION 0x00 //!< No general encryption information or non - encrypted data
#define STORE_DATA_ENCRYPTION_APPLICATION_DEPENDENT 0x20 //!< Application dependent encryption of the data
#define STORE_DATA_ENCRYPTION_RFU 0x40 //!< RFU(encryption indicator)
#define STORE_DATA_ENCRYPTION_ENCRYPTED 0x60 //!< Encrypted data. Must be encrypted with data encryption key.

#define STORE_DATA_FORMAT_NO_INFORMATION 0x00 //!< No general data structure information
#define STORE_DATA_FORMAT_DGI 0x08 //!< DGI format of the command data field
#define STORE_DATA_FORMAT_BER_TLV 0x10 //!< BER-TLV format of the command data field
#define STORE_DATA_FORMAT_RFU 0x18 //!< RFU (data structure information)


// Some possible identifiers to retrieve card data with get_data() and put_data().

static const BYTE GP211_GET_DATA_ISSUER_IDENTIFICATION_NUMBER[2] = {0x00, 0x42}; //!< Issuer Identification Number, if Card Manager selected.
static const BYTE GP211_GET_DATA_APPLICATION_PROVIDER_IDENTIFICATION_NUMBER[2] = {0x00, 0x42}; //!< Application Provider Identification Number, if Security Domain selected.
static const BYTE GP211_GET_DATA_ECKA_CERTIFICATE[2] = {0xBF, 0x21}; //!< SCP11: ECKA certificate store.
static const BYTE GP211_GET_DATA_CA_KLOC_KID_KVN[2] = {0x00, 0x83}; //!< SCP11: CA-KLOC Identifier to KID/KVN mapping.
static const BYTE GP211_GET_DATA_SUPPORTED_CA_KLOC_IDENTIFIERS[2] = {0xFF, 0x33}; //!< SCP11: Supported CA-KLOC identifiers.
static const BYTE GP211_GET_DATA_SUPPORTED_CA_KLCC_IDENTIFIERS[2] = {0xFF, 0x34}; //!< SCP11: Supported CA-KLCC identifiers.

static const BYTE GP211_GET_DATA_CARD_IMAGE_NUMBER[2] = {0x00, 0x45}; //!< Card Image Number, if Card Manager selected.
static const BYTE GP211_GET_DATA_SECURITY_DOMAIN_IMAGE_NUMBER[2] = {0x00, 0x45}; //!< Security Domain Image Number, if Security Domain selected.

static const BYTE GP211_GET_DATA_ISSUER_SECURITY_DOMAIN_AID[2] = {0x00, 0x4F}; //!< Issuer Security Domain AID, if Issuer Security Domain selected.
static const BYTE GP211_GET_DATA_SECURITY_DOMAIN_AID[2] = {0x00, 0x4F}; //!< Security Domain AID, if Security Domain selected.
static const BYTE GP211_GET_DATA_LIST_OF_APPLICATIONS[2] = {0x2F, 0x00}; //!< List of applications present on the card.
static const BYTE GP211_GET_DATA_EXTENDED_CARD_RESOURCES[2] = {0xFF, 0x21}; //!< Extended card resources according TS 102 226.

static const BYTE GP211_GET_DATA_CARD_DATA[2] = {0x00, 0x66}; //!< Card Data.
static const BYTE GP211_GET_DATA_SECURITY_DOMAIN_MANAGEMENT_DATA[2] = {0x00, 0x66}; //!< Security Domain Management Data if Security Domain is selected.
static const BYTE GP211_GET_DATA_CARD_CAPABILITY_INFORMATION[2] = {0x00, 0x67}; //!< Card Capability Information.
static const BYTE GP211_GET_DATA_SEQUENCE_COUNTER_DEFAULT_KEY_VERSION[2] = {0x00, 0xC1}; //!< Sequence Counter of the default Key Version Number.
static const BYTE GP211_GET_DATA_CONFIRMATION_COUNTER[2] = {0x00, 0xC2}; //!< Confirmation Counter for generating receipts.
static const BYTE GP211_GET_DATA_FREE_EEPROM_MEMORY_SPACE[2] = {0x00, 0xC6}; //!< Free EEPROM memory space.
static const BYTE GP211_GET_DATA_FREE_COR_RAM[2] = {0x00, 0xC7}; //!< Free transient Clear on Reset memory space (COR RAM).
static const BYTE GP211_GET_DATA_DIVERSIFICATION_DATA[2] = {0x00, 0xCF}; //!< Diversification data.

/**
 * Key Information Template of first 31 keys.
 * Next templates can be obtained with the tag 0x0x 0xE0, where x > 0.
 */
static const BYTE GP211_GET_DATA_KEY_INFORMATION_TEMPLATE[2] = {0x00, 0xE0};

static const BYTE GP211_GET_DATA_CPLC_PERSONALIZATION_DATE[2] = {0x9F, 0x66}; //!< CPLC personalization date.
static const BYTE GP211_GET_DATA_CPLC_PRE_PERSONALIZATION_DATE[2] = {0x9F, 0x67}; //!< CPLC pre-personalization date.
static const BYTE GP211_GET_DATA_CPLC_ICC_MANUFACTURER_EMBEDDING_DATE[2] = {0x9F, 0x68}; //!< CPLC ICC manufacturer, embedding date.
static const BYTE GP211_GET_DATA_CPLC_MODULE_FABRICATOR_PACKAGING_DATE[2] = {0x9F, 0x69}; //!< CPLC module fabricator, module packaging date.
static const BYTE GP211_GET_DATA_CPLC_FABRICATION_DATE_SERIAL_NUMBER_BATCH_IDENTIFIER[2] = {0x9F, 0x6A}; //!< CPLC fabrication date, serial number, batch identifier.
/**
 * Whole CPLC data from ROM and EEPROM.
 * 9F7F // TAG
 * 2A // Length of data
 * ////////////////Data /////////////
 * 4250 // ic fabricator
 * 3272 // ic type
 * 1291 // os id
 * 6181 // os date
 * 0700 // os level
 * 8039 // fabrication date
 * 0106D0BB // ic serial
 * 1D3C // ic batch
 * 0000 // module fabricator
 * 8148 // packing date
 * 0000// icc manufacturer
 * 8148 // ic embedding date
 * 0000 // pre - personalizer
 * 0000 // IC Pre-Personalization Date
 * 00000000 //IC Pre-Personalization Equipment Identifier
 * 0000// IC Personalizer
 * 0000 // IC Personalization Date
 * 00000000 // IC Personalization Equipment Identifier
 */
static const BYTE GP211_GET_DATA_CPLC_WHOLE_CPLC[2] = {0x9F, 0x7F};

static const BYTE GP211_GET_DATA_FCI_DATA[2] = {0xBF, 0x0C}; //!< File Control Information (FCI) discretionary data.

static const BYTE GP211_GET_DATA_PROTOCOL[2] = {0xDF, 0x70}; //!< Data for protocol change.
static const BYTE GP211_GET_DATA_ATR_HISTRORICAL_BYTES[2] = {0xDF, 0x71}; //!< Change ATR historical bytes.

static const BYTE GP211_GET_DATA_EF_PROD_DATA_INITIALIZATION_FINGERPRINT[2] = {0xDF, 0x76}; //!< EF<sub>prod</sub> data initialization fingerprint.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_INITIALIZATION_DATA[2] = {0xDF, 0x77}; //!< EF<sub>prod</sub> data initialization data.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_PRODUCTION_KEY_INDEX[2] = {0xDF, 0x78}; //!< EF<sub>prod</sub> data production key index.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_PROTOCOL_VERSION[2] = {0xDF, 0x79}; //!< EF<sub>prod</sub> data protocol version.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_CHECKSUM[2] = {0xDF, 0x7A}; //!< EF<sub>prod</sub> data checksum.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_SOFTWARE_VERSION[2] = {0xDF, 0x7B}; //!< EF<sub>prod</sub> data software version.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_RFU[2] = {0xDF, 0x7C}; //!< EF<sub>prod</sub> data RFU.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_PROFILE_WITH_PROFILE_VERSION[2] = {0xDF, 0x7D}; //!< EF<sub>prod</sub> data profile with profile version.
static const BYTE GP211_GET_DATA_EF_PROD_DATA_LOCATION_MACHINE_DATE_TIME[2] = {0xDF, 0x7E}; //!< EF<sub>prod</sub> data location, machine number, date, time.

static const BYTE GP211_GET_DATA_WHOLE_EF_PROD[2] = {0xDF, 0x7F}; //!< Whole EF<sub>prod</sub> data block (39 Byte).

static const BYTE GP211_GET_DATA_KEY_DIVERSIFICATION[2] = {0x00, 0xCF}; //!< Key diversification data. KMC_ID (6 bytes) + CSN (4 bytes). KMC_ID is usually the IIN (Issuer identification number). CSN is the card serial number.

// OP 2.0.1' specifific

static const BYTE OP201_CARD_MANAGER_AID[7] = {0xA0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}; //!< The AID of the Card Manager defined by Open Platform specification.

#define OP201_LIFE_CYCLE_LOAD_FILE_LOGICALLY_DELETED 0x00 //!< Executable Load File is logically deleted.
#define OP201_LIFE_CYCLE_LOAD_FILE_LOADED 0x01 //!< Executable Load File is loaded.
#define OP201_LIFE_CYCLE_CARD_MANAGER_OP_READY 0x01 //!< Card is OP ready.
#define OP201_LIFE_CYCLE_CARD_MANAGER_INITIALIZED 0x07 //!< Card is initialized.
#define OP201_LIFE_CYCLE_CARD_MANAGER_SECURED 0x0f //!< Card is in secured state.
#define OP201_LIFE_CYCLE_CARD_MANAGER_CM_LOCKED 0x7f //!< Card is locked.
#define OP201_LIFE_CYCLE_CARD_MANAGER_TERMINATED 0xff //!< Card is terminated.
#define OP201_LIFE_CYCLE_APPLICATION_LOGICALLY_DELETED 0x00 //!< Application is logically deleted.
#define OP201_LIFE_CYCLE_APPLICATION_INSTALLED 0x03 //!< Application is installed
#define OP201_LIFE_CYCLE_APPLICATION_SELECTABLE 0x07 //!< Application is selectable.
#define OP201_LIFE_CYCLE_APPLICATION_PERSONALIZED 0x0f //!< Application is personalized.
#define OP201_LIFE_CYCLE_APPLICATION_BLOCKED 0x7f //!< Application is blocked.
#define OP201_LIFE_CYCLE_APPLICATION_LOCKED 0xff //!< Application is locked.

/**
 * \brief Application privileges.
 */
typedef enum {
	OP201_SECURITY_DOMAIN = 1u << 7, //!< Application is security domain.
	OP201_DAP_VERIFICATION = 0xC0, //!< Application can require DAP verification for loading and installing applications.
	OP201_DELEGATED_MANAGEMENT = 0xA0, //!< Security domain has delegated management right.
	OP201_CARD_MANAGER_LOCK_PRIVILEGE = 1u << 4, //!< Application can lock the Card Manager.
	OP201_CARD_MANAGER_TERMINATE_PRIVILEGE = 1u << 3, //!< Application can terminate the card.
	OP201_DEFAULT_SELECTED = 1u << 2, //!< Application is default selected.
	OP201_PIN_CHANGE_PRIVILEGE = 1u << 1, //!< Application can change global PIN.
	OP201_MANDATED_DAP_VERIFICATION = 0xD0, //!< Security domain requires DAP verification for loading and installing applications.
} OP201_APPLICATION_PRIVILEGES;

#define OP201_STATUS_APPLICATIONS 0x40 //!< Indicate Applications or Security Domains in OP201_get_status() or OP201_set_status().
#define OP201_STATUS_CARD_MANAGER 0x80 //!< Indicate Card Manager in OP201_get_status() or OP201_set_status().
#define OP201_STATUS_LOAD_FILES 0x20 //!< Request OP201_APPLICATION_DATA for Executable Load Files in OP201_get_status().


// Some possible identifiers to retrieve card data with get_data() and put_data().
static const BYTE OP201_GET_DATA_ISSUER_BIN[2] = {0x00, 0x42}; //!< Issuer BIN, if Card Manager selected.
static const BYTE OP201_GET_DATA_APPLICATION_PROVIDER_IDENTIFICATION_NUMBER[2] = {0x00, 0x42}; //!< Application provider identification number, if Security Domain selected.

static const BYTE OP201_GET_DATA_ISSUER_DATA[2] = {0x00, 0x45}; //!< Card issuer data, if Card Manager selected.
static const BYTE OP201_GET_DATA_SECURITY_DOMAIN_IMAGE_NUMBER[2] = {0x00, 0x45}; //!< Security domain image number, if Security Domain selected.

static const BYTE OP201_GET_DATA_CARD_MANAGER_AID[2] = {0x00, 0x4F}; //!< Change Card Manager AID, if Card Manager selected.
static const BYTE OP201_GET_DATA_SECURITY_DOMAIN_AID[2] = {0x00, 0x4F}; //!< Change Security Domain AID, if Security Domain selected.

static const BYTE OP201_GET_DATA_CARD_RECOGNITION_DATA[2] = {0x00, 0x66}; //!< Card recognition data.
static const BYTE OP201_GET_DATA_SEQUENCE_COUNTER_DEFAULT_KEY_VERSION[2] = {0x00, 0xC1}; //!< Sequence Counter of the default Key Version Number.
static const BYTE OP201_GET_DATA_CONFIRMATION_COUNTER[2] = {0x00, 0xC2}; //!< Confirmation Counter.
static const BYTE OP201_GET_DATA_FREE_EEPROM_MEMORY_SPACE[2] = {0x00, 0xC6}; //!< Free EEPROM memory space.
static const BYTE OP201_GET_DATA_FREE_COR_RAM[2] = {0x00, 0xC7}; //!< Free transient Clear on Reset memory space (COR RAM).
static const BYTE OP201_GET_DATA_DIVERSIFICATION_DATA[2] = {0x00, 0xCF}; //!< Diversification data.

/**
 * Key Information Template of first 31 keys.
 * Next templates can be obtained with the tag 0x0x 0xE0, where x > 0.
 */
static const BYTE OP201_GET_DATA_KEY_INFORMATION_TEMPLATE[2] = {0x00, 0xE0};

static const BYTE OP201_GET_DATA_CPLC_PERSONALIZATION_DATE[2] = {0x9F, 0x66}; //!< CPLC personalization date.
static const BYTE OP201_GET_DATA_CPLC_PRE_PERSONALIZATION_DATE[2] = {0x9F, 0x67}; //!< CPLC pre-personalization date.
static const BYTE OP201_GET_DATA_CPLC_ICC_MANUFACTURER_EMBEDDING_DATE[2] = {0x9F, 0x68}; //!< CPLC ICC manufacturer, embedding date.
static const BYTE OP201_GET_DATA_CPLC_MODULE_FABRICATOR_PACKAGING_DATE[2] = {0x9F, 0x69}; //!< CPLC module fabricator, module packaging date.
static const BYTE OP201_GET_DATA_CPLC_FABRICATION_DATE_SERIAL_NUMBER_BATCH_IDENTIFIER[2] = {0x9F, 0x6A}; //!< CPLC fabrication date, serial number, batch identifier.
static const BYTE OP201_GET_DATA_CPLC_WHOLE_CPLC[2] = {0x9F, 0x7F}; //!< Whole CPLC data from ROM and EEPROM.

static const BYTE OP201_GET_DATA_FCI_DATA[2] = {0xBF, 0x0C}; //!< File Control Information (FCI) discretionary data.

static const BYTE OP201_GET_DATA_PROTOCOL[2] = {0xDF, 0x70}; //!< Data for protocol change.
static const BYTE OP201_GET_DATA_ATR_HISTRORICAL_BYTES[2] = {0xDF, 0x71}; //!< Change ATR historical bytes.

static const BYTE OP201_GET_DATA_EF_PROD_DATA_INITIALIZATION_FINGERPRINT[2] = {0xDF, 0x76}; //!< EF<sub>prod</sub> data initialization fingerprint.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_INITIALIZATION_DATA[2] = {0xDF, 0x77}; //!< EF<sub>prod</sub> data initialization data.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_PRODUCTION_KEY_INDEX[2] = {0xDF, 0x78}; //!< EF<sub>prod</sub> data production key index.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_PROTOCOL_VERSION[2] = {0xDF, 0x79}; //!< EF<sub>prod</sub> data protocol version.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_CHECKSUM[2] = {0xDF, 0x7A}; //!< EF<sub>prod</sub> data checksum.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_SOFTWARE_VERSION[2] = {0xDF, 0x7B}; //!< EF<sub>prod</sub> data software version.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_RFU[2] = {0xDF, 0x7C}; //!< EF<sub>prod</sub> data RFU.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_PROFILE_WITH_PROFILE_VERSION[2] = {0xDF, 0x7D}; //!< EF<sub>prod</sub> data profile with profile version.
static const BYTE OP201_GET_DATA_EF_PROD_DATA_LOCATION_MACHINE_DATE_TIME[2] = {0xDF, 0x7E}; //!< EF<sub>prod</sub> data location, machine number, date, time.

static const BYTE OP201_GET_DATA_WHOLE_EF_PROD[2] = {0xDF, 0x7F}; //!< Whole EF<sub>prod</sub> data block (39 Byte).

#define OPGP_DERIVATION_METHOD_NONE 0 //!< No key derivation is used during mutual authentication.
#define OPGP_DERIVATION_METHOD_VISA2 1 //!< The VISA2 key derivation is used during mutual authentication.
#define OPGP_DERIVATION_METHOD_EMV_CPS11 2 //!< The EMV CPS 11 derivation is used during mutual authentication.
#define OPGP_DERIVATION_METHOD_VISA1 3 //!< The VISA1 key derivation is used during mutual authentication.

#define GP211_HASH_SHA1 1 //!< SHA-1
#define GP211_HASH_SHA256 2 //!< SHA2-256
#define GP211_HASH_SHA384 3 //!< SHA2-384
#define GP211_HASH_SHA512 4 //!< SHA2-512
#define GP211_HASH_SM3 5 //!< SM3

#define GP211_KEY_VERSION_TOKEN_VERIFICATION 0x70 //!< Token Verification
#define GP211_KEY_VERSION_RECEIPT_GENERATION 0x71 //!< Receipt Generation
#define GP211_KEY_VERSION_DAP_VERIFICATION 0x73 //!< DAP Verification
#define GP211_KEY_VERSION_CASD_AND_CONFIDENTIAL_SETUP 0x74 //!< CASD and Confidential Setup of Secure Channel Keys
#define GP211_KEY_VERSION_CIPHERED_LOAD_FILE 0x75 //!< Ciphered Load File Data Block Key

#define OPGP_WORK_UNKNOWN -1 //!< The amount of work is not known.
#define OPGP_TASK_FINISHED 1 //!< The task is finished.

#define INIT_PROGRESS_CALLBACK_PARAMETERS(callbackParameters, callback) 	if (callback != NULL) {callbackParameters.parameters = callback->parameters; \
	callbackParameters.finished = !OPGP_TASK_FINISHED;}

/**
 * The structure measures the progress of a task. This structure is passed to the callback function.
 */
typedef struct {
	DWORD currentWork; //!< The current work which is done. If not known this contains #OPGP_WORK_UNKNOWN
	DWORD totalWork; //!< The total work which needs to be done. If not known this contains #OPGP_WORK_UNKNOWN
	DWORD finished; //!< Task is finished. If finished contains #OPGP_TASK_FINISHED.
	PVOID parameters; //!< Proprietary parameters for the function passed in with #OPGP_PROGRESS_CALLBACK.
} OPGP_PROGRESS_CALLBACK_PARAMETERS;

/**
 * The structure is used when the progress for a task changes in functions supporting callbacks.
 */
typedef struct {
	void (*callback)(OPGP_PROGRESS_CALLBACK_PARAMETERS); //!< The callback function. The must accept a #OPGP_PROGRESS_CALLBACK_PARAMETERS parameter and return void.
	PVOID parameters; //!< Proprietary parameters for the callback function. Passed in when the function is called.
} OPGP_PROGRESS_CALLBACK;

/**
 * A structure describing an AID.
 */
typedef struct {
	BYTE AIDLength; //!< The length of the AID.
	BYTE AID[16]; //!< The AID.
} OPGP_AID;


/**
 * The structure containing Card Manager, Executable Load File and application life cycle states and privileges returned by get_status().
 */
typedef struct {
	OPGP_AID aid; //!< The AID.
	BYTE lifeCycleState; //!< The Card Manager, Executable Load File or application life cycle state.
	OP201_APPLICATION_PRIVILEGES privileges; //!< The Card Manager or application privileges.
} OP201_APPLICATION_DATA;

/**
 * A structure describing an Executable Load File.
 * This structure is limited to 32 applets in the Load File.
 */
typedef struct {
	DWORD loadFileSize; //!< The size of the Load File.
	OPGP_AID loadFileAID; //!< The AID of the Load File.
	BYTE numAppletAIDs; //!< The number of applets contained in the Load File.
	OPGP_AID appletAIDs[32]; //!< The contained applets in the Load File.
} OPGP_LOAD_FILE_PARAMETERS;


/**
 * The structure containing Issuer Security Domain, Security Domains, Executable Load Files
 * and Application life cycle states and privileges returned by get_status().
 */
typedef struct {
	OPGP_AID aid; //!< The AID.
	BYTE lifeCycleState; //!< The Issuer Security Domain, Security Domains, Executable Load Files and Application life cycle state.
	GP211_APPLICATION_PRIVILEGES privileges; //!< The Issuer Security Domain, Security Domains or Application privileges. Has no meaning for Executable Load Files.
	BYTE versionNumber[2]; //!< On a Java Card based card, this is a 2-byte version number reflecting the major and minor version attributes (in this order) of the Java Card CAP file. Shorted if longer.
	OPGP_AID associatedSecurityDomainAID; //!< The associated Security Domain's AID.
} GP211_APPLICATION_DATA;

/**
 * The structure containing Executable Load Files and their Executable Module returned by get_status().
 */
typedef struct {
	OPGP_AID aid; //!< The Executable Load File AID.
	BYTE lifeCycleState; //!< The Executable Load File life cycle state.
	BYTE versionNumber[2]; //!< On a Java Card based card, this is a 2-byte version number reflecting the major and minor version attributes (in this order) of the Java Card CAP file. Shorted if longer.
	BYTE numExecutableModules; //!< Number of associated Executable Modules.
	OPGP_AID executableModules[64]; //!< Array for the maximum possible associated Executable Modules.
	OPGP_AID associatedSecurityDomainAID; //!< The associated Security Domain's AID.
} GP211_EXECUTABLE_MODULES_DATA;

/**
 * The structure containing the extended card resource information according ETSI TS 102 226, sect. 8.2.1.7.2.
 */
typedef struct {
	DWORD numInstalledApplications; //!< The number of the installed applications.
	DWORD freeVolatileMemory; //!< Free volatile memory.
	DWORD freeNonVolatileMemory; //!< Free non volatile memory.
} OPGP_EXTENDED_CARD_RESOURCE_INFORMATION;

/**
 * The structure containing the Card Production Life Cycle (CPLC) data (raw values).
 */
typedef struct {
	USHORT icFabricator; //!< IC Fabricator.
	USHORT icType; //!< IC Type.
	USHORT operatingSystemId; //!< Operating System ID.
	USHORT operatingSystemReleaseDate; //!< Operating System release date (raw).
	USHORT operatingSystemReleaseLevel; //!< Operating System release level.
	USHORT icFabricationDate; //!< IC fabrication date (raw).
	USHORT icSerialNumberHigh; //!< IC serial number (high).
	USHORT icSerialNumberLow; //!< IC serial number (low).
	USHORT icBatchIdentifier; //!< IC batch identifier.
	USHORT icModuleFabricator; //!< IC module fabricator.
	USHORT icModulePackagingDate; //!< IC module packaging date (raw).
	USHORT iccManufacturer; //!< ICC manufacturer.
	USHORT icEmbeddingDate; //!< IC embedding date (raw).
	USHORT icPrePersonalizer; //!< IC pre-personalizer.
	USHORT icPrePersonalizationEquipmentDate; //!< IC pre-personalization equipment date (raw).
	DWORD icPrePersonalizationEquipmentId; //!< IC pre-personalization equipment ID.
	USHORT icPersonalizer; //!< IC personalizer.
	USHORT icPersonalizationDate; //!< IC personalization date (raw).
	DWORD icPersonalizationEquipmentId; //!< IC personalization equipment ID.
} OPGP_CPLC;

/**
 * The Card Recognition Data returned for tag 0x66 with GET DATA.
 */
#define GP211_MAX_CARD_RECOGNITION_SCP_INFOS 16
#define GP211_MAX_CARD_RECOGNITION_SCP_IMPL_OID_BYTES 8

/* SCPi bit flags for card-recognition-data SCP implementation options. */
#define GP211_SCP02_SCPI_THREE_KEYS 0x01 //!< SCP02: 1=3 static keys, 0=1 base key.
#define GP211_SCP02_SCPI_MODE_MASK 0x0E //!< SCP02: initiation/ICV mode selector.
#define GP211_SCP02_SCPI_MODE_EXPLICIT 0x04 //!< SCP02: explicit initiation, C-MAC on modified APDU, ICV=0.
#define GP211_SCP02_SCPI_MODE_IMPLICIT 0x0A //!< SCP02: implicit initiation, C-MAC on unmodified APDU, ICV=MAC(AID).
#define GP211_SCP02_SCPI_CMAC_ICV_ENCRYPTION 0x10 //!< SCP02: C-MAC ICV encryption enabled.
#define GP211_SCP02_SCPI_PSEUDO_RANDOM_CARD_CHALLENGE 0x40 //!< SCP02: pseudo-random card challenge algorithm.

#define GP211_SCP03_SCPI_PSEUDO_RANDOM_CARD_CHALLENGE 0x10 //!< SCP03: 1=pseudo-random card challenge, 0=random.
#define GP211_SCP03_SCPI_RESPONSE_MASK 0x60 //!< SCP03: response protection coding mask.
#define GP211_SCP03_SCPI_RESPONSE_NONE 0x00 //!< SCP03: no R-MAC / no R-ENC.
#define GP211_SCP03_SCPI_RESPONSE_R_MAC 0x20 //!< SCP03: R-MAC / no R-ENC.
#define GP211_SCP03_SCPI_RESPONSE_R_ENC_R_MAC 0x60 //!< SCP03: R-MAC and R-ENC.

#define GP211_SCP11_SCPI_B1_SECOND_BYTE_PRESENT 0x80 //!< SCP11 byte 1: second byte present.
#define GP211_SCP11_SCPI_B1_S16_MODE 0x40 //!< SCP11 byte 1: 1=S16 secure messaging, 0=S8.
#define GP211_SCP11_SCPI_B1_SCP11C_AUTH_BF20 0x20 //!< SCP11 byte 1: SCP11c authorization mechanism supported.
#define GP211_SCP11_SCPI_B1_SCP11C_SUPPORTED 0x10 //!< SCP11 byte 1: SCP11c supported.
#define GP211_SCP11_SCPI_B1_CERT_CHAIN_SUPPORTED 0x08 //!< SCP11 byte 1: certificate chain supported.
#define GP211_SCP11_SCPI_B1_SD_PERSISTENT_PK_OCE_ECKA 0x04 //!< SCP11 byte 1: SD persistently stores PK.OCE.ECKA.
#define GP211_SCP11_SCPI_B1_SCP11B_SUPPORTED 0x02 //!< SCP11 byte 1: SCP11b supported.
#define GP211_SCP11_SCPI_B1_SCP11A_SUPPORTED 0x01 //!< SCP11 byte 1: SCP11a supported.

#define GP211_SCP11_SCPI_B2_GP_LEGACY_CERT_NOT_SUPPORTED 0x04 //!< SCP11 byte 2: GP legacy format certificates not supported.
#define GP211_SCP11_SCPI_B2_X509_CERT_SUPPORTED 0x02 //!< SCP11 byte 2: X.509 certificates supported.
#define GP211_SCP11_SCPI_B2_SCP11A_AUTH_BF20 0x01 //!< SCP11 byte 2: SCP11a authorization mechanism supported.

typedef struct {
	char version[16]; //!< The GlobalPlatform version string (e.g. "2.1.1").
	BYTE scp[GP211_MAX_CARD_RECOGNITION_SCP_INFOS]; //!< The secure channel protocols.
	BYTE scpImpl[GP211_MAX_CARD_RECOGNITION_SCP_INFOS]; //!< The SCP implementation trailing byte (backward compatible for one-byte 'i').
	DWORD scpImplValue[GP211_MAX_CARD_RECOGNITION_SCP_INFOS]; //!< The numeric SCP implementation OID subidentifier value.
	BYTE scpImplOidBytes[GP211_MAX_CARD_RECOGNITION_SCP_INFOS][GP211_MAX_CARD_RECOGNITION_SCP_IMPL_OID_BYTES]; //!< BER-encoded SCP implementation OID subidentifier bytes.
	BYTE scpImplOidBytesLength[GP211_MAX_CARD_RECOGNITION_SCP_INFOS]; //!< Length of BER-encoded SCP implementation OID subidentifier bytes.
	DWORD scpLength; //!< The length of the SCP.
	char cardConfigurationDetailsOid[128]; //!< Card configuration details OID as numeric string.
	DWORD cardConfigurationDetailsOidLength; //!< Card configuration details OID length.
	BYTE cardConfigurationDetails[64]; //!< Card configuration details.
	DWORD cardConfigurationDetailsLength; //!< Card configuration details length.
	char cardChipDetailsOid[128]; //!< Card / chip details OID as numeric string.
	DWORD cardChipDetailsOidLength; //!< Card / chip details OID length.
	BYTE cardChipDetails[64]; //!< Card configuration details.
	DWORD cardChipDetailsLength; //!< Card configuration details length.
	char issuerSecurityDomainsTrustPointCertificateInformationOid[128]; //!< Issuer Security Domain’s Trust Point certificate information OID as numeric string.
	DWORD issuerSecurityDomainsTrustPointCertificateInformationOidLength; //!< Issuer Security Domain’s Trust Point certificate information OID length.
	BYTE issuerSecurityDomainsTrustPointCertificateInformation[64]; //!< Issuer Security Domain’s Trust Point certificate information.
	DWORD issuerSecurityDomainsTrustPointCertificateInformationLength; //!< Issuer Security Domain’s Trust Point certificate information length.
	char issuerSecurityDomainCertificateInformationOid[128]; //!< Issuer Security Domain certificate information OID as numeric string.
	DWORD issuerSecurityDomainCertificateInformationOidLength; //!< Issuer Security Domain certificate information OID length.
	BYTE issuerSecurityDomainCertificateInformation[64]; //!< Issuer Security Domain certificate information.
	DWORD issuerSecurityDomainCertificateInformationLength; //!< Issuer Security Domain certificate information length.
} GP211_CARD_RECOGNITION_DATA;

#define GP211_MAX_CARD_CAPABILITY_SCP_INFOS 16
#define GP211_MAX_CARD_CAPABILITY_SCP_OPTIONS 16
#define GP211_MAX_CARD_CAPABILITY_TLS_CIPHER_SUITES 16
#define GP211_MAX_CARD_CAPABILITY_LFDBH_ALGORITHMS 8
#define GP211_MAX_CARD_CAPABILITY_CIPHER_SUITES 32
#define GP211_MAX_CARD_CAPABILITY_KEY_PARAMETER_REFERENCES 128
#define GP211_MAX_CARD_CAPABILITY_ELF_UPGRADE 32

#define GP211_SCP_SUPPORTED_KEY_SIZE_128 0x01
#define GP211_SCP_SUPPORTED_KEY_SIZE_192 0x02
#define GP211_SCP_SUPPORTED_KEY_SIZE_256 0x04

#define GP211_LFDB_ENCRYPTION_3DES_16B_KEY 0x01
#define GP211_LFDB_ENCRYPTION_AES_128 0x02
#define GP211_LFDB_ENCRYPTION_AES_192 0x04
#define GP211_LFDB_ENCRYPTION_AES_256 0x08
#define GP211_LFDB_ENCRYPTION_SM4 0x10
#define GP211_LFDB_ENCRYPTION_ICV_SUPPORTED 0x80

#define GP211_SIGNATURE_CS_RSA_1024_SHA1 0x0100
#define GP211_SIGNATURE_CS_RSA_PSS_SHA256 0x0200
#define GP211_SIGNATURE_CS_DES_MAC_16B 0x0400
#define GP211_SIGNATURE_CS_CMAC_AES_128 0x0800
#define GP211_SIGNATURE_CS_CMAC_AES_192 0x1000
#define GP211_SIGNATURE_CS_CMAC_AES_256 0x2000
#define GP211_SIGNATURE_CS_ECDSA_256_SHA256 0x4000
#define GP211_SIGNATURE_CS_ECDSA_384_SHA384 0x8000

#define GP211_SIGNATURE_CS_ECDSA_512_SHA512 0x0001
#define GP211_SIGNATURE_CS_ECDSA_521_SHA512 0x0002
#define GP211_SIGNATURE_CS_SM2 0x0004

#define GP211_SCP11_CERTIFICATE_MAX_ID_LENGTH 16
#define GP211_SCP11_CERTIFICATE_MAX_DATE_LENGTH 4
#define GP211_SCP11_CERTIFICATE_MAX_PUBLIC_KEY_LENGTH 160
#define GP211_SCP11_CERTIFICATE_MAX_KEY_PARAMETER_REFERENCE_LENGTH 2
#define GP211_SCP11_CERTIFICATE_MAX_SIGNATURE_LENGTH 160
#define GP211_SCP11_CERTIFICATE_MAX_DISCRETIONARY_DATA_LENGTH 127
#define GP211_SCP11_CERTIFICATE_MAX_AUTHORIZATIONS_LENGTH 1024

static const BYTE GP211_SCP11_KEY_USAGE_DIGITAL_SIGNATURE_VERIFICATION[1] = {0x82}; //!< SCP11 certificate key usage for CERT.KA-KLOC.ECDSA.
static const BYTE GP211_SCP11_KEY_USAGE_KEY_AGREEMENT[2] = {0x00, 0x80}; //!< SCP11 certificate key usage for CERT.OCE.ECKA.

#define GP211_ELF_UPGRADE_SINGLE 0x00
#define GP211_ELF_UPGRADE_MULTI 0x01

/**
 * SCP11 certificate (tag '7F21') fields.
 */
typedef struct {
	BYTE certificateSerialNumber[GP211_SCP11_CERTIFICATE_MAX_ID_LENGTH]; //!< Certificate Serial Number (tag '93').
	DWORD certificateSerialNumberLength; //!< Certificate Serial Number length.
	BYTE authorityIdentifier[GP211_SCP11_CERTIFICATE_MAX_ID_LENGTH]; //!< CA-KLOC or KA-KLOC Identifier (tag '42').
	DWORD authorityIdentifierLength; //!< CA-KLOC or KA-KLOC Identifier length.
	BYTE subjectIdentifier[GP211_SCP11_CERTIFICATE_MAX_ID_LENGTH]; //!< Subject Identifier (tag '5F20').
	DWORD subjectIdentifierLength; //!< Subject Identifier length.
	BYTE keyUsage[2]; //!< Key Usage (tag '95').
	DWORD keyUsageLength; //!< Key Usage length.
	BOOL effectiveDatePresent; //!< TRUE if Effective Date (tag '5F25') is present.
	BYTE effectiveDate[GP211_SCP11_CERTIFICATE_MAX_DATE_LENGTH]; //!< Effective Date in YYYYMMDD BCD format.
	BYTE expirationDate[GP211_SCP11_CERTIFICATE_MAX_DATE_LENGTH]; //!< Expiration Date (tag '5F24') in YYYYMMDD BCD format.
	DWORD expirationDateLength; //!< Expiration Date length.
	USHORT discretionaryDataTag; //!< Optional discretionary data tag: 0x53 or 0x73.
	BYTE discretionaryData[GP211_SCP11_CERTIFICATE_MAX_DISCRETIONARY_DATA_LENGTH]; //!< Optional discretionary data.
	DWORD discretionaryDataLength; //!< Optional discretionary data length.
	BOOL authorizationsPresent; //!< TRUE if SCP11c authorizations (tag 'BF20') are present.
	BYTE authorizations[GP211_SCP11_CERTIFICATE_MAX_AUTHORIZATIONS_LENGTH]; //!< SCP11c authorizations value.
	DWORD authorizationsLength; //!< SCP11c authorizations value length.
	BYTE publicKey[GP211_SCP11_CERTIFICATE_MAX_PUBLIC_KEY_LENGTH]; //!< Public Key Q (tag 'B0').
	DWORD publicKeyLength; //!< Public Key Q length.
	BYTE keyParameterReference[GP211_SCP11_CERTIFICATE_MAX_KEY_PARAMETER_REFERENCE_LENGTH]; //!< Key Parameter Reference (tag 'F0').
	DWORD keyParameterReferenceLength; //!< Key Parameter Reference length.
	BYTE signature[GP211_SCP11_CERTIFICATE_MAX_SIGNATURE_LENGTH]; //!< Certificate signature (tag '5F37').
	DWORD signatureLength; //!< Certificate signature length.
} GP211_SCP11_CERTIFICATE;

/**
 * SCP Information inside Card Capability Information (Tag 'A0').
 */
typedef struct {
	BYTE scpIdentifier; //!< SCP Identifier (tag '80').
	BYTE scpOptions[GP211_MAX_CARD_CAPABILITY_SCP_OPTIONS]; //!< SCP Options list (tag '81').
	DWORD scpOptionsLength; //!< SCP Options list length.
	BYTE scpOptionsMask[GP211_MAX_CARD_CAPABILITY_SCP_OPTIONS]; //!< SCP Options mask (tag '91').
	DWORD scpOptionsMaskLength; //!< SCP Options mask length.
	BYTE supportedKeySizes; //!< Supported key sizes (tag '82').
	BYTE tlsCipherSuites[GP211_MAX_CARD_CAPABILITY_TLS_CIPHER_SUITES]; //!< Supported TLS cipher suites (tag '83').
	DWORD tlsCipherSuitesLength; //!< Supported TLS cipher suites length.
	BYTE maxPskLength; //!< Max length of PSK in bytes (tag '84').
} GP211_SCP_INFORMATION;

/**
 * The Card Capability Information returned for tag 0x67 with GET DATA.
 */
typedef struct {
	GP211_SCP_INFORMATION scpInformation[GP211_MAX_CARD_CAPABILITY_SCP_INFOS]; //!< SCP information entries.
	DWORD scpInformationLength; //!< Number of SCP information entries.
	BYTE ssdPrivileges[3]; //!< Privileges assignable to SSDs (tag '81').
	BYTE appPrivileges[3]; //!< Privileges assignable to applications (tag '82').
	BYTE lfdbhAlgorithms[GP211_MAX_CARD_CAPABILITY_LFDBH_ALGORITHMS]; //!< Supported LFDBH algorithms (tag '83'). See GP211_HASH_SHA256.
	DWORD lfdbhAlgorithmsLength; //!< Supported LFDBH algorithms length
	BYTE lfdbencryptionCipherSuites; //!< LFDB encryption cipher suites (tag '84').
	USHORT tokenCipherSuites; //!< Cipher suites supported for tokens (tag '85'). See GP211_CIPHER_SUITE_AES_128_CBC.
	USHORT receiptCipherSuites; //!< Cipher suites supported for receipts (tag '86').
	USHORT dapCipherSuites; //!< Cipher suites supported for DAPs (tag '87').
	BYTE keyParameterReferenceList[GP211_MAX_CARD_CAPABILITY_KEY_PARAMETER_REFERENCES]; //!< Key Parameter Reference List (tag '88').
	DWORD keyParameterReferenceListLength; //!< Key Parameter Reference List length.
	BYTE elfUpgrade; //!< Supported ELF upgrade process & options (tag '89').
	BOOL tokenIdentifierDenyList; //!< Support for Token Identifier Deny List (tag '8A').
	BOOL securityDomainSelfRemoval; //!< Support for Security Domain Self-Removal (tag '8B').
} GP211_CARD_CAPABILITY_INFORMATION;

// UICC System Specific Parameters (ETSI TS 102 226, sect. 8.2.1.3.2.2).
#define GP211_UICC_ACCESS_DOMAIN_FULL_ACCESS 0x00 //!< Access Domain Parameter: Full access to the File System.
#define GP211_UICC_ACCESS_DOMAIN_UICC_ACCESS 0x02 //!< Access Domain Parameter: UICC access mechanism (3-byte ADD).
#define GP211_UICC_ACCESS_DOMAIN_NO_ACCESS 0xFF //!< Access Domain Parameter: No access to the File System.
#define GP211_UICC_MSL_PARAMETER_MINIMUM_SPI1 0x01 //!< Minimum Security Level parameter: Minimum SPI1.
#define GP211_UICC_TOOLKIT_MAX_TIMERS 0x08 //!< Max number of timers per ETSI TS 102 223.
#define GP211_UICC_TOOLKIT_MAX_CHANNELS 0x07 //!< Max number of channels per ETSI TS 102 223.
#define GP211_UICC_TOOLKIT_MAX_SERVICES 0x08 //!< Max number of services per ETSI TS 102 223.
#define GP211_UICC_MAX_MENU_ENTRIES 8 //!< Maximum menu entries supported by the helper structures.
#define GP211_UICC_MAX_ACCESS_RULES 4 //!< Maximum access rules supported by the helper structures.
#define GP211_UICC_MAX_TAR_VALUES 4 //!< Maximum TAR values supported by the helper structures.
#define GP211_UICC_TOOLKIT_DAP_MAX_LENGTH 16 //!< Maximum toolkit parameters DAP length supported.
#define GP211_UICC_ACCESS_DOMAIN_DAP_MAX_LENGTH 16 //!< Maximum access domain DAP length supported.
#define GP211_SPI1_RC_CC_DS_MASK 0x03 //!< SPI1 RC/CC/DS mask (b2..b1).
#define GP211_SPI1_RC_CC_DS_NONE 0x00 //!< SPI1 RC/CC/DS: none.
#define GP211_SPI1_RC_CC_DS_RC 0x01 //!< SPI1 RC/CC/DS: Redundancy Check.
#define GP211_SPI1_RC_CC_DS_CC 0x02 //!< SPI1 RC/CC/DS: Cryptographic Checksum.
#define GP211_SPI1_RC_CC_DS_DS 0x03 //!< SPI1 RC/CC/DS: Digital Signature (reserved).
#define GP211_SPI1_CIPHERING 0x04 //!< SPI1 ciphering bit (b3).
#define GP211_SPI1_COUNTER_MASK 0x18 //!< SPI1 counter mask (b5..b4).
#define GP211_SPI1_COUNTER_NONE 0x00 //!< SPI1 counter: no counter.
#define GP211_SPI1_COUNTER_AVAILABLE 0x08 //!< SPI1 counter: available, no replay/sequence check.
#define GP211_SPI1_COUNTER_HIGHER_THAN_RE 0x10 //!< SPI1 counter: process if counter higher than RE.
#define GP211_SPI1_COUNTER_INCREMENT_RE 0x18 //!< SPI1 counter: process if counter is one higher than RE.
#define GP211_SPI1_RFU_MASK 0xE0 //!< SPI1 RFU mask (b8..b6).
#define GP211_SD_MAX_SCP 8 //!< Maximum SCP entries supported by the helper structures.
#define GP211_SD_PARAM_TAG_SCP 0x81 //!< SD install param tag for SCP (tag '81').
#define GP211_SD_PARAM_TAG_ACCEPT_EXTRACTION 0x82 //!< SD install param tag for accept extraction (tag '82').
#define GP211_SD_PARAM_TAG_ACCEPT_DELETE 0x83 //!< SD install param tag for accept deletion (tag '83').
#define GP211_SD_PARAM_TAG_PERSONALIZED 0x84 //!< SD install param tag for personalized state (tag '84').
#define GP211_SD_PARAM_TAG_CASD_CAPABILITY 0x86 //!< SD install param tag for CASD capability (tag '86').
#define GP211_SD_PARAM_TAG_ACCEPT_GLOBAL_DELETE 0x87 //!< SD install param tag for accept global delete (tag '87').
#define GP211_SD_PARAM_LEN_SCP 0x02 //!< SD install param length for SCP (tag '81').
#define GP211_SD_PARAM_LEN_ACCEPT_DELETE 0x01 //!< SD install param length for accept deletion (tag '83').
#define GP211_SD_PARAM_LEN_CASD_CAPABILITY 0x02 //!< SD install param length for CASD capability (tag '86').
#define GP211_SD_PARAM_LEN_PERSONALIZED 0x00 //!< SD install param length for personalized state (tag '84').
#define GP211_SD_PARAM_LEN_ACCEPT_MIN 0x01 //!< SD install param minimum length for accept policies (tags '82','87').
#define GP211_SD_PARAM_LEN_ACCEPT_MAX 0x02 //!< SD install param maximum length for accept policies (tags '82','87').
#define GP211_SD_ACCEPT_NONE 0x00 //!< Accept policy: no acceptance (default).
#define GP211_SD_ACCEPT_ANCESTOR_AM 0x80 //!< Accept policy: from ancestor SD with AM privilege.
#define GP211_SD_ACCEPT_HIERARCHY_AM 0xC0 //!< Accept policy: from any SD in hierarchy with AM privilege.
#define GP211_SD_ACCEPT_ISD 0x20 //!< Accept policy: from Issuer Security Domain.
#define GP211_SD_ACCEPT_DM_UNDER_ANCESTOR_AM 0x08 //!< Accept policy: from any SD with DM under ancestor SD with AM.
#define GP211_SD_ACCEPT_ALL_AM 0xF0 //!< Accept policy: from every SD with AM privilege (RFU bits set to 0).

/**
 * Toolkit menu entry definition.
 */
typedef struct {
	BYTE position; //!< Position of the menu entry.
	BYTE identifier; //!< Identifier of the menu entry ('00' means do not care).
} GP211_UICC_TOOLKIT_MENU_ENTRY;

/**
 * UICC Toolkit Application specific parameters (tag '80' value).
 */
typedef struct {
	BYTE priority; //!< Priority level of the Toolkit application instance.
	BYTE maxTimers; //!< Maximum number of timers allowed.
	BYTE maxTextLength; //!< Maximum text length for a menu entry.
	BYTE maxMenuEntries; //!< Maximum number of menu entries (m).
	GP211_UICC_TOOLKIT_MENU_ENTRY menuEntries[GP211_UICC_MAX_MENU_ENTRIES]; //!< Array with m entries.
	BYTE maxChannels; //!< Maximum number of channels allowed.
	BYTE mslData; //!< Minimum Security Level Data (MSLD) for Minimum SPI1 parameter (SPI1 first octet coding).
	BYTE tarValues[GP211_UICC_MAX_TAR_VALUES * 3]; //!< TAR Value(s) field.
	BYTE tarValuesLength; //!< Length of TAR Value(s) field in bytes (0 or multiple of 3).
	BYTE maxServices; //!< Maximum number of services allowed.
} GP211_UICC_TOOLKIT_APP_PARAMS;

/**
 * UICC Access Rule for one ADF or the shared file system.
 */
typedef struct {
	BYTE aidLength; //!< Length of AID (0 for shared UICC file system, or 5..16 for ADF).
	BYTE aid[16]; //!< AID value.
	BYTE accessDomainParameter; //!< Access Domain Parameter (0x00, 0x02, 0xFF).
	BYTE accessDomainData[3]; //!< Access Domain Data for parameter 0x02.
	BYTE accessDomainDap[GP211_UICC_ACCESS_DOMAIN_DAP_MAX_LENGTH]; //!< Access Domain DAP value.
	BYTE accessDomainDapLength; //!< Access Domain DAP length in bytes.
} GP211_UICC_ACCESS_RULE;

/**
 * UICC Access Application specific parameters (tag '81' / '82' value).
 */
typedef struct {
	GP211_UICC_ACCESS_RULE rules[GP211_UICC_MAX_ACCESS_RULES]; //!< Array of access rules.
	BYTE rulesLength; //!< Number of access rules.
} GP211_UICC_ACCESS_PARAMS;

/**
 * UICC System Specific Parameters (tag 'EA' value without the tag and length).
 */
typedef struct {
	BOOL toolkitParamsPresent; //!< TRUE to include toolkit application parameters (tag '80').
	GP211_UICC_TOOLKIT_APP_PARAMS toolkitParams; //!< Toolkit application parameters (tag '80').
	BYTE toolkitParametersDap[GP211_UICC_TOOLKIT_DAP_MAX_LENGTH]; //!< Toolkit parameters DAP (tag 'C3').
	BYTE toolkitParametersDapLength; //!< Toolkit parameters DAP length in bytes.
	BOOL accessParamsPresent; //!< TRUE to include access application parameters (tag '81').
	GP211_UICC_ACCESS_PARAMS accessParams; //!< Access application parameters (tag '81').
	BOOL adminAccessParamsPresent; //!< TRUE to include administrative access parameters (tag '82').
	GP211_UICC_ACCESS_PARAMS adminAccessParams; //!< Administrative access parameters (tag '82').
} GP211_UICC_SYSTEM_SPECIFIC_PARAMS;

/**
 * SIM Toolkit application specific parameters (part of tag 'CA' value).
 */
typedef struct {
	BYTE priority; //!< Priority level of the Toolkit application instance.
	BYTE maxTimers; //!< Maximum number of timers allowed.
	BYTE maxTextLength; //!< Maximum text length for a menu entry.
	BYTE maxMenuEntries; //!< Maximum number of menu entries (m).
	GP211_UICC_TOOLKIT_MENU_ENTRY menuEntries[GP211_UICC_MAX_MENU_ENTRIES]; //!< Array with m entries.
	BYTE maxChannels; //!< Maximum number of channels allowed.
	BYTE mslData; //!< Minimum Security Level Data (MSLD) for Minimum SPI1 parameter (SPI1 first octet coding).
	BYTE tarValues[GP211_UICC_MAX_TAR_VALUES * 3]; //!< TAR Value(s) field.
	BYTE tarValuesLength; //!< Length of TAR Value(s) field in bytes (0 or multiple of 3).
} GP211_SIM_TOOLKIT_PARAMS;

/**
 * SIM File Access and Toolkit Application Specific Parameters (tag 'CA' value without the tag and length).
 */
typedef struct {
	BYTE accessDomainParameter; //!< Access Domain Parameter (0x00, 0x02, 0xFF).
	BYTE accessDomainData[3]; //!< Access Domain Data for parameter 0x02.
	GP211_SIM_TOOLKIT_PARAMS toolkitParams; //!< Toolkit application parameters.
} GP211_SIM_SPECIFIC_PARAMS;

/**
 * Security Domain SCP entry (tag '81').
 */
typedef struct {
	BYTE scpIdentifier; //!< Secure Channel Protocol Identifier.
	BYTE scpImpl; //!< Secure Channel Implementation Option 'T'.
} GP211_SD_SCP_ENTRY;

/**
 * Security Domain install parameters (tag 'C1' value).
 */
typedef struct {
	GP211_SD_SCP_ENTRY scpEntries[GP211_SD_MAX_SCP]; //!< SCP entries (tag '81').
	BYTE scpEntriesLength; //!< Number of SCP entries.
	BYTE acceptExtraditionHere[2]; //!< Acceptance policy for extradition to this security domain (tag '82'). See GP211_SD_ACCEPT_ALL_AM.
	BYTE acceptExtraditionHereLength; //!< Length of tag '82' value (1 or 2).
	BYTE acceptDeletion; //!< Acceptance policy for deletion (tag '83'). See GP211_SD_ACCEPT_ALL_AM.
	BYTE acceptDeletionLength; //!< Length of tag '83' value (0 or 1).
	BOOL personalizedStatePresent; //!< TRUE to include tag '84' (length 0). If set an explicit SET STATUS or STORE DATA command is needed to set the personalized state.
	BYTE casdCapabilityInfo[2]; //!< CASD capability information (tag '86').
	BYTE acceptExtraditionAway[2]; //!<  Acceptance policy for extradition from this security domain away (tag '87'). See GP211_SD_ACCEPT_ALL_AM.
	BYTE acceptExtraditionAwayLength; //!< Length of tag '87' value (1 or 2).
} GP211_SD_INSTALL_PARAMS;

//! \brief GlobalPlatform2.1.1: Selects an application on a card by AID and resets secure channel state.
OPGP_API
OPGP_ERROR_STATUS OPGP_select_application(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, PBYTE AID, DWORD AIDLength);

//! \brief Reads the extended card resource information (number of applications + free memory).
OPGP_API
OPGP_ERROR_STATUS OPGP_get_extended_card_resources_information(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								   OPGP_EXTENDED_CARD_RESOURCE_INFORMATION *extendedCardResourceInformation);

//! \brief Reads and parses the CPLC data.
OPGP_API
OPGP_ERROR_STATUS OPGP_get_cplc(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				OPGP_CPLC *cplc);

//! \brief Parses the CPLC data response.
OPGP_API
OPGP_ERROR_STATUS OPGP_parse_cplc(const BYTE *data, DWORD dataLength, OPGP_CPLC *cplc);

//! \brief Parses the extended card resources information response.
OPGP_API
OPGP_ERROR_STATUS OPGP_parse_extended_card_resources_information(const BYTE *data, DWORD dataLength,
								  OPGP_EXTENDED_CARD_RESOURCE_INFORMATION *extendedCardResourceInformation);

/** \brief GlobalPlatform2.1.1: Gets the life cycle status of Applications, the Issuer Security
 * Domains, Security Domains and Executable Load Files and their privileges or information about
 * Executable Modules of the Executable Load Files.
 */
OPGP_API
OPGP_ERROR_STATUS GP211_get_status(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				BYTE cardElement, BYTE format, GP211_APPLICATION_DATA *applData,
				GP211_EXECUTABLE_MODULES_DATA *executableData, PDWORD dataLength);

//! \brief GlobalPlatform2.1.1: Sets the life cycle status of Applications, Security Domains or the Card Manager.
OPGP_API
OPGP_ERROR_STATUS GP211_set_status(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, BYTE statusType, PBYTE AID, DWORD AIDLength, BYTE lifeCycleState);

/**
 * \brief GlobalPlatform2.1.1: Mutual authentication.
 *
 * For SCP01, SCP02 and SCP03 the \p baseKeyOrStaticOcePrivateKey parameter is
 * the Secure Channel base key, or the master key used by the selected key
 * derivation method. Pass it as NULL when the selected protocol implementation
 * uses separate Secure Channel keys via \p S_ENC, \p S_MAC and \p DEK.
 *
 * For SCP11a the same parameter is the raw static OCE ECKA private key
 * (SK.OCE.ECKA) used with the card SD ECKA public key from CERT.SD.ECKA during
 * key agreement. The SCP11a private key length is determined from the card
 * certificate key parameter reference; \p keyLength remains the requested AES
 * session key length (16, 24 or 32 bytes). \p S_ENC, \p S_MAC and \p DEK are not
 * used for SCP11a.
 *
 * \param cardContext [in] The valid OPGP_CARD_CONTEXT returned by OPGP_establish_context().
 * \param cardInfo [in] The OPGP_CARD_INFO structure returned by OPGP_card_connect().
 * \param baseKeyOrStaticOcePrivateKey [in] SCP01/SCP02/SCP03 base or master key, or SCP11a static OCE ECKA private key.
 * \param S_ENC [in] Secure Channel Encryption Key for SCP01/SCP02/SCP03 implementations with separate static keys.
 * \param S_MAC [in] Secure Channel Message Authentication Code Key for SCP01/SCP02/SCP03 implementations with separate static keys.
 * \param DEK [in] Data Encryption Key for SCP01/SCP02/SCP03 implementations with separate static keys.
 * \param keyLength [in] Symmetric key length. 16, 24 or 32 bytes.
 * \param keySetVersion [in] The key set version on the card to use for mutual authentication.
 * \param keyIndex [in] The key index in the key set version on the card to use for mutual authentication.
 * \param secureChannelProtocol [in] The Secure Channel Protocol. Use GP211_SCP11 explicitly for SCP11a. Passing 0 only auto-detects SCP01/SCP02/SCP03 via INITIALIZE UPDATE; callers may use GP211_get_secure_channel_protocol_details() before authentication for card-recognition based discovery.
 * \param secureChannelProtocolImpl [in] The Secure Channel Protocol implementation. For SCP11a this is the SCP parameter byte; the SCP11a variant bits are applied by this function.
 * \param securityLevel [in] The requested security level. See GP211_SCP01_SECURITY_LEVEL_C_DEC_C_MAC and others.
 * \param derivationMethod [in] The derivation method to use. See OPGP_DERIVATION_METHOD_VISA2.
 * \param certOceEcka [in] Optional SCP11 certificate chain data to submit before mutual authentication. The data must contain one or more 7F21 or X.509 DER certificates, optionally wrapped in BF21, and must end with CERT.OCE.ECKA.
 * \param certOceEckaLength [in] Length of \p certOceEcka.
 * \param sdPublicKeyOverride [in] Optional SCP11 PK.SD.ECKA public key as raw uncompressed EC point or B0-wrapped point.
 * \param sdPublicKeyOverrideLength [in] Length of \p sdPublicKeyOverride.
 * \param sdPublicKeyFileName [in] Optional PEM file containing PK.SD.ECKA. If set, this takes precedence over \p sdPublicKeyOverride.
 * \param secInfo [out] The returned GP211_SECURITY_INFO structure.
 * \return OPGP_ERROR_STATUS struct with error status OPGP_ERROR_STATUS_SUCCESS if no error occurs, otherwise error code and error message are contained in the OPGP_ERROR_STATUS struct.
 */
OPGP_API
OPGP_ERROR_STATUS GP211_mutual_authentication(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
                           PBYTE baseKeyOrStaticOcePrivateKey, PBYTE S_ENC, PBYTE S_MAC,
                           PBYTE DEK, DWORD keyLength, BYTE keySetVersion,
                           BYTE keyIndex, BYTE secureChannelProtocol,
                           BYTE secureChannelProtocolImpl,
                           BYTE securityLevel, BYTE derivationMethod,
                           PBYTE certOceEcka, DWORD certOceEckaLength,
                           PBYTE sdPublicKeyOverride, DWORD sdPublicKeyOverrideLength,
                           OPGP_STRING sdPublicKeyFileName,
                           GP211_SECURITY_INFO *secInfo);

//! \brief GlobalPlatform2.1.1: Inits a Secure Channel implicitly.
OPGP_API
OPGP_ERROR_STATUS GP211_init_implicit_secure_channel(PBYTE AID, DWORD AIDLength, BYTE baseKey[16],
								  BYTE S_ENC[16], BYTE S_MAC[16], BYTE DEK[16],
								  BYTE secureChannelProtocolImpl, BYTE sequenceCounter[2],
								  GP211_SECURITY_INFO *secInfo);

//! \brief GlobalPlatform2.1.1: Closes a Secure Channel implicitly.
OPGP_API
OPGP_ERROR_STATUS GP211_close_implicit_secure_channel(GP211_SECURITY_INFO *secInfo);

//! \brief GlobalPlatform2.1.1: Retrieve card data.
OPGP_API
OPGP_ERROR_STATUS GP211_get_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  BYTE identifier[2], PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief SCP11: Retrieves the ECKA certificate store (GET DATA with tag BF21).
OPGP_API
OPGP_ERROR_STATUS GP211_get_ecka_certificate(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  BYTE keyVersionNumber, BYTE keyIdentifier, PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief SCP11: Resolves KID/KVN from a CA-KLOC Identifier (GET DATA with tag 0083).
OPGP_API
OPGP_ERROR_STATUS GP211_ca_kloc_kid_kvn(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  PBYTE caKlocIdentifier, DWORD caKlocIdentifierLength,
			  BYTE *keyIdentifier, BYTE *keyVersionNumber);

//! \brief SCP11: Retrieves supported CA identifiers (GET DATA with tag FF33 or FF34).
OPGP_API
OPGP_ERROR_STATUS GP211_get_supported_ca_identifiers(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
			  GP211_SECURITY_INFO *secInfo, BOOL returnCaKlccIdentifiers,
			  PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief SCP11: Submits CERT.OCE.ECKA (PERFORM SECURITY OPERATION, INS 2A).
OPGP_API
OPGP_ERROR_STATUS GP211_perform_security_operation(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  BYTE caKlocKeyVersionNumber, BYTE caKlocKeyIdentifier,
			  PBYTE certificateData, DWORD certificateDataLength,
			  BOOL moreCertificatesExpected);

//! \brief SCP11: Submits a certificate chain ending in CERT.OCE.ECKA with PERFORM SECURITY OPERATION.
OPGP_API
OPGP_ERROR_STATUS GP211_perform_security_operation_certificate_chain(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
			  GP211_SECURITY_INFO *secInfo,
			  BYTE caKlocKeyVersionNumber, BYTE caKlocKeyIdentifier,
			  PBYTE certificateChainData, DWORD certificateChainDataLength);

//! \brief GlobalPlatform2.1.1: Retrieve diversification data (tag 0xCF).
OPGP_API
OPGP_ERROR_STATUS GP211_get_diversification_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief Retrieve card data according ISO/IEC 7816-4 command not within a secure channel.
OPGP_API
OPGP_ERROR_STATUS GP211_get_data_iso7816_4(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, BYTE identifier[2], PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief GlobalPlatform2.1.1: Return the card recognition data.
OPGP_API
OPGP_ERROR_STATUS GP211_get_card_recognition_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, GP211_CARD_RECOGNITION_DATA *cardData);

//! \brief Parses the card recognition data response.
OPGP_API
OPGP_ERROR_STATUS GP211_parse_card_recognition_data(const BYTE *data, DWORD dataLength, GP211_CARD_RECOGNITION_DATA *cardData);

//! \brief SCP11: Parses a certificate encoded according to table 6-12.
OPGP_API
OPGP_ERROR_STATUS GP211_parse_scp11_certificate(PBYTE certificateData, DWORD certificateDataLength,
			  GP211_SCP11_CERTIFICATE *certificate);

//! \brief SCP11: Parses a BF21 certificate store.
//! For legacy GP certificates (tag '7F21') the output contains a contiguous array of GP211_SCP11_CERTIFICATE structures.
//! For X.509 DER certificates (tag '30') the output contains PEM encoded CERTIFICATE blocks.
OPGP_API
OPGP_ERROR_STATUS GP211_parse_certificate_store(const BYTE *certificateStoreData, DWORD certificateStoreDataLength,
			  PBYTE parsedCertificateStore, PDWORD parsedCertificateStoreLength);

//! \brief SCP11: Builds and signs a certificate encoded according to table 6-12.
OPGP_API
OPGP_ERROR_STATUS GP211_build_scp11_certificate(GP211_SCP11_CERTIFICATE *certificate,
			  OPGP_STRING subjectPublicKeyFileName, char *subjectPublicKeyPassPhrase,
			  OPGP_STRING signingPrivateKeyFileName, char *signingPrivateKeyPassPhrase,
			  PBYTE certificateData, PDWORD certificateDataLength);

//! \brief GlobalPlatform2.3.1: Return the card capability information.
OPGP_API
OPGP_ERROR_STATUS GP211_get_card_capability_information(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, GP211_CARD_CAPABILITY_INFORMATION *cardCapabilityInfo);

//! \brief Parses the card capability information response.
OPGP_API
OPGP_ERROR_STATUS GP211_parse_card_capability_information(const BYTE *data, DWORD dataLength,
							  GP211_CARD_CAPABILITY_INFORMATION *cardCapabilityInfo);

//! \brief Builds the card recognition data response.
OPGP_API
OPGP_ERROR_STATUS GP211_build_card_recognition_data(const GP211_CARD_RECOGNITION_DATA *cardData,
							 PBYTE data, PDWORD dataLength);

//! \brief BCD encodes a numeric string.
OPGP_API
OPGP_ERROR_STATUS OPGP_build_bcd_encoding(const char *numericString, PBYTE bcdData, PDWORD bcdDataLength);

//! \brief GlobalPlatform2.1.1: This returns the Secure Channel Protocol and the Secure Channel Protocol implementation.
OPGP_API
OPGP_ERROR_STATUS GP211_get_secure_channel_protocol_details(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
										 BYTE *secureChannelProtocol, BYTE *secureChannelProtocolImpl);

//! \brief GlobalPlatform2.1.1: This returns the current Sequence Counter.
OPGP_API
OPGP_ERROR_STATUS GP211_get_sequence_counter(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
						  GP211_SECURITY_INFO *secInfo, DWORD *sequenceCounter);

//! \brief GlobalPlatform2.1.1: This returns the confirmation counter.
OPGP_API
OPGP_ERROR_STATUS GP211_get_confirmation_counter(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
						  GP211_SECURITY_INFO *secInfo, DWORD *confirmationCounter);

//! \brief GlobalPlatform2.1.1: Put card data.
OPGP_API
OPGP_ERROR_STATUS GP211_put_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			  BYTE identifier[2], PBYTE dataObject, DWORD dataObjectLength);

//! \brief GlobalPlatform2.1.1: Changes or unblocks the global PIN.
OPGP_API
OPGP_ERROR_STATUS GP211_pin_change(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				BYTE tryLimit, PBYTE newPIN, DWORD newPINLength);

//! \brief GlobalPlatform2.1.1: replaces a single symmetric key in a key set or adds a new key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_symmetric_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				  BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, BYTE key[32], DWORD keyLength, BYTE keyType);

//! \brief GlobalPlatform2.1.1: replaces a single AES key in a key set or adds a new AES key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_aes_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				  BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, BYTE aesKey[32], DWORD keyLength);

//! \brief GlobalPlatform2.1.1: replaces a single 3DES key in a key set or adds a new 3DES key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_3des_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				  BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, BYTE _3DESKey[16]);

//! \brief GlobalPlatform2.1.1: replaces a single public RSA key in a key set or adds a new public RSA key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_rsa_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: replaces a single public ECC key in a key set or adds a new public ECC key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_ecc_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: replaces or adds a public ECC key using a curve parameter reference.
OPGP_API
OPGP_ERROR_STATUS GP211_put_ecc_key_with_curve_parameter_reference(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
				 GP211_SECURITY_INFO *secInfo, BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion,
				 OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: replaces or adds a raw private ECC key using a curve parameter reference.
OPGP_API
OPGP_ERROR_STATUS GP211_put_ecc_private_key_with_curve_parameter_reference(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
				 GP211_SECURITY_INFO *secInfo, BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion,
				 BYTE privateKey[32], DWORD privateKeyLength);

//! \brief GlobalPlatform2.3.1: replaces a single public asymmetric key in a key set or adds a new public asymmetric key.
OPGP_API
OPGP_ERROR_STATUS GP211_put_asymmetric_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, OPGP_STRING PEMKeyFileName, char *passPhrase, BYTE keyType);

//! \brief GlobalPlatform2.1.1: replaces or adds a secure channel key set consisting of S-ENC, S-MAC and DEK.
OPGP_API
OPGP_ERROR_STATUS GP211_put_secure_channel_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
							 BYTE keySetVersion, BYTE newKeySetVersion, PBYTE baseKey,
							 PBYTE newS_ENC, PBYTE newS_MAC, PBYTE newDEK, DWORD keyLength, BYTE keyType);

//! \brief GlobalPlatform2.1.1: deletes a key or multiple keys.
OPGP_API
OPGP_ERROR_STATUS GP211_delete_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				BYTE keySetVersion, BYTE keyIndex);

//! \brief GlobalPlatform2.1.1: Retrieves key information of keys on the card.
OPGP_API
OPGP_ERROR_STATUS GP211_get_key_information_templates(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								   BYTE keyInformationTemplate,
								   GP211_KEY_INFORMATION *keyInformation, PDWORD keyInformationLength);

//! \brief GlobalPlatform2.1.1: Deletes a Executable Load File or an application.
OPGP_API
OPGP_ERROR_STATUS GP211_delete_application(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				   OPGP_AID *AIDs, DWORD AIDsLength,
				   GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable,
				   PBYTE deleteToken, DWORD deleteTokenLength);

//! \brief GlobalPlatform2.1.1: Prepares the card for loading an application.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_load(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
					  PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
					  PBYTE securityDomainAID,
					  DWORD securityDomainAIDLength, PBYTE loadFileDataBlockHash, DWORD loadFileDataBlockHashLength,
					  PBYTE loadToken, DWORD loadTokenLength,
					  DWORD nonVolatileCodeSpaceLimit, DWORD volatileDataSpaceLimit,
					  DWORD nonVolatileDataSpaceLimit);

//! \brief GlobalPlatform2.1.1: Function to retrieve the data to sign by the Card Issuer in an Extradition Token.
OPGP_API
OPGP_ERROR_STATUS GP211_get_extradition_token_signature_data(PBYTE securityDomainAID,
										  DWORD securityDomainAIDLength,
										  PBYTE applicationAID, DWORD applicationAIDLength,
										  PBYTE extraditionTokenSignatureData,
										  PDWORD extraditionTokenSignatureDataLength);

//! \brief GlobalPlatform2.1.1: Function to retrieve the data to sign by the Card Issuer in a Load Token.
OPGP_API
OPGP_ERROR_STATUS GP211_get_load_token_signature_data(PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
								   PBYTE securityDomainAID,
								   DWORD securityDomainAIDLength, PBYTE loadFileDataBlockHash,
								   DWORD loadFileDataBlockHashLength,
								   DWORD nonVolatileCodeSpaceLimit, DWORD volatileDataSpaceLimit,
								   DWORD nonVolatileDataSpaceLimit, PBYTE loadTokenSignatureData,
								   PDWORD loadTokenSignatureDataLength);

//! \brief GlobalPlatform2.1.1: Function to retrieve the data to sign by the Card Issuer in an Install Token.
OPGP_API
OPGP_ERROR_STATUS GP211_get_install_token_signature_data(BYTE P1, PBYTE executableLoadFileAID,
									  DWORD executableLoadFileAIDLength,
									  PBYTE executableModuleAID, DWORD executableModuleAIDLength,
									  PBYTE applicationAID, DWORD applicationAIDLength,
									  DWORD applicationPrivileges, DWORD volatileDataSpaceLimit,
									  DWORD nonVolatileDataSpaceLimit,
									  PBYTE installParameters, DWORD installParametersLength,
									  PBYTE sdParameters, DWORD sdParametersLength,
									  PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
									  PBYTE simSpecParams, DWORD simSpecParamsLength,
									  PBYTE installTokenSignatureData, PDWORD installTokenSignatureDataLength);

//! \brief GlobalPlatform2.3.1: Function to retrieve the data to sign for delegated management in a Registry Update Token.
OPGP_API
OPGP_ERROR_STATUS GP211_get_registry_update_token_signature_data(PBYTE securityDomainAID,
										  DWORD securityDomainAIDLength,
										  PBYTE applicationAID, DWORD applicationAIDLength,
										  DWORD applicationPrivileges,
										  PBYTE registryUpdateParameters, DWORD registryUpdateParametersLength,
										  PBYTE tokenSignatureData,
										  PDWORD tokenSignatureDataLength);

//! \brief GlobalPlatform2.3.1: Function to retrieve the data to sign for delegated management in a Delete Token.
OPGP_API
OPGP_ERROR_STATUS GP211_get_delete_token_signature_data(OPGP_AID *AIDs, DWORD AIDsLength,
										  PBYTE deleteTokenSignatureData,
										  PDWORD deleteTokenSignatureDataLength);

//! \brief GlobalPlatform2.1.1: Calculates a Load Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_load_token(PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
						  PBYTE securityDomainAID,
						  DWORD securityDomainAIDLength, PBYTE loadFileDataBlockHash,
						  DWORD loadFileDataBlockHashLength,
						  DWORD nonVolatileCodeSpaceLimit, DWORD volatileDataSpaceLimit,
						  DWORD nonVolatileDataSpaceLimit, PBYTE loadToken, PDWORD loadTokenLength,
						  OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.1.1: Calculates an Install Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_install_token(BYTE P1, PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
							 PBYTE executableModuleAID,
							 DWORD executableModuleAIDLength, PBYTE applicationAID,
							 DWORD applicationAIDLength, DWORD applicationPrivileges,
							 DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
							 PBYTE installParameters, DWORD installParametersLength,
							 PBYTE sdParameters, DWORD sdParametersLength,
							 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
							 PBYTE simSpecParams, DWORD simSpecParamsLength,
							 PBYTE installToken, PDWORD installTokenLength,
							 OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.1.1: Calculates an Extradition Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_extradition_token(PBYTE securityDomainAID,
										  DWORD securityDomainAIDLength,
										  PBYTE applicationAID, DWORD applicationAIDLength,
										  PBYTE extraditionToken, PDWORD extraditionTokenLength,
										  OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Calculates a Registry Update Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_update_registry_token(PBYTE securityDomainAID,
										  DWORD securityDomainAIDLength,
										  PBYTE applicationAID, DWORD applicationAIDLength,
										  DWORD applicationPrivileges,
										  PBYTE registryUpdateParameters, DWORD registryUpdateParametersLength,
										  PBYTE registryUpdateToken, PDWORD registryUpdateTokenLength,
										  OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Calculates a Delete Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_delete_token(PBYTE applicationOrExecutableLoadFileAID,
										  DWORD applicationOrExecutableLoadFileAIDLength,
										  PBYTE deleteToken, PDWORD deleteTokenLength,
										  OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.1.1: Builds the UICC System Specific Parameters (tag 'EA' value without the tag and length).
OPGP_API
OPGP_ERROR_STATUS GP211_build_uicc_system_specific_params(GP211_UICC_SYSTEM_SPECIFIC_PARAMS *params,
							  PBYTE uiccSystemSpecParams, PDWORD uiccSystemSpecParamsLength);

//! \brief GlobalPlatform2.1.1: Builds the SIM File Access and Toolkit Application Specific Parameters (tag 'CA' value without the tag and length).
OPGP_API
OPGP_ERROR_STATUS GP211_build_sim_specific_params(GP211_SIM_SPECIFIC_PARAMS *params,
						  PBYTE simSpecParams, PDWORD simSpecParamsLength);

//! \brief GlobalPlatform2.1.1: Builds the Security Domain install parameters (tag 'C1' with tag and length).
OPGP_API
OPGP_ERROR_STATUS GP211_build_sd_parameters(GP211_SD_INSTALL_PARAMS *params,
						  PBYTE sdParameters, PDWORD sdParametersLength);

//! \brief GlobalPlatform2.1.1: Calculates a Load File Data Block Hash.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_load_file_data_block_hash(OPGP_STRING executableLoadFileName,
                                                            PBYTE hash, DWORD hashLength, BYTE hashType);

//! \brief GlobalPlatform2.1.1: Loads a Executable Load File (containing an application) to the card.
OPGP_API
OPGP_ERROR_STATUS GP211_load(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 GP211_DAP_BLOCK *dapBlock, DWORD dapBlockLength, OPGP_STRING executableLoadFileName,
				 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable, OPGP_PROGRESS_CALLBACK *callback);

//! \brief GlobalPlatform2.1.1: Loads a Executable Load File (containing an application) from a buffer to the card.
OPGP_API
OPGP_ERROR_STATUS GP211_load_from_buffer(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 GP211_DAP_BLOCK *dapBlock, DWORD dapBlockLength,
				 PBYTE loadFileBuffer, DWORD loadFileBufSize,
				 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable, OPGP_PROGRESS_CALLBACK *callback);

//! \brief GlobalPlatform2.1.1: Installs an application on the card.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_install(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
						 PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE executableModuleAID,
						 DWORD executableModuleAIDLength, PBYTE applicationAID, DWORD applicationAIDLength,
						 DWORD applicationPrivileges, DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
						 PBYTE installParameters, DWORD installParametersLength,
						 PBYTE sdParameters, DWORD sdParametersLength,
						 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
						 PBYTE simSpecParams, DWORD simSpecParamsLength,
						 PBYTE installToken, DWORD installTokenLength,
						 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief GlobalPlatform2.1.1: Makes an installed application selectable.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_make_selectable(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								 PBYTE applicationAID, DWORD applicationAIDLength,
								 DWORD applicationPrivileges, PBYTE installToken, DWORD installTokenLength,
								 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief GlobalPlatform2.1.1: Installs and makes an installed application selectable.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_install_and_make_selectable(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
						 PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE executableModuleAID,
						 DWORD executableModuleAIDLength, PBYTE applicationAID,
						 DWORD applicationAIDLength, DWORD applicationPrivileges,
						 DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
						 PBYTE installParameters, DWORD installParametersLength,
						 PBYTE sdParameters, DWORD sdParametersLength,
						 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
						 PBYTE simSpecParams, DWORD simSpecParamsLength,
						 PBYTE installToken, DWORD installTokenLength,
						 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief GlobalPlatform2.3.1: Updates the registry of an application or Security Domain.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_registry_update(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
						 PBYTE securityDomainAID, DWORD securityDomainAIDLength,
						 PBYTE applicationAID, DWORD applicationAIDLength,
						 DWORD applicationPrivileges,
						 PBYTE registryUpdateParameters, DWORD registryUpdateParametersLength,
						 PBYTE registryUpdateToken, DWORD registryUpdateTokenLength,
						 GP211_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief GlobalPlatform2.1.1: Informs a Security Domain that a associated application will retrieve personalization data.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_personalization(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo,
											 GP211_SECURITY_INFO *secInfo,
						 PBYTE applicationAID,
						 DWORD applicationAIDLength);

//! \brief GlobalPlatform2.1.1: Associates an application with another Security Domain.
OPGP_API
OPGP_ERROR_STATUS GP211_install_for_extradition(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
							  PBYTE securityDomainAID,
						 DWORD securityDomainAIDLength, PBYTE applicationAID,
						 DWORD applicationAIDLength,
						 PBYTE extraditionToken, DWORD extraditionTokenLength, GP211_RECEIPT_DATA *receiptData,
						 PDWORD receiptDataAvailable);


//! \brief GlobalPlatform2.1.1: Adds a token verification key set for Delegated Management.
OPGP_API
OPGP_ERROR_STATUS GP211_put_delegated_management_token_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								   BYTE keySetVersion,
								   BYTE newKeySetVersion,
								   OPGP_STRING PEMKeyFileName, char *passPhrase,
								   BYTE tokenKeyType);

//! \brief GlobalPlatform2.3.1: Adds a DAP verification key set (asymmetric or symmetric).
OPGP_API
OPGP_ERROR_STATUS GP211_put_dap_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								   BYTE keySetVersion,
								   BYTE newKeySetVersion,
								   OPGP_STRING PEMKeyFileName, char *passPhrase,
								   BYTE keyType, BYTE key[32], DWORD keyLength);

//! \brief GlobalPlatform2.1.1: Adds a receipt generation key set for Delegated Management.
OPGP_API
OPGP_ERROR_STATUS GP211_put_delegated_management_receipt_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
								   BYTE keySetVersion,
								   BYTE newKeySetVersion,
								   BYTE receiptKey[32], DWORD keyLength, BYTE receiptKeyType);

//! \brief Sends an application protocol data unit.
OPGP_API
OPGP_ERROR_STATUS GP211_send_APDU(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
			   PBYTE capdu, DWORD capduLength, PBYTE rapdu,
			   PDWORD rapduLength);

//! \brief GlobalPlatform2.1.1: Calculates a Load File Data Block Signature using AES or 3DES.
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_DAP(BYTE loadFileDataBlockHash[64], BYTE hashLength,
		BYTE DAPCalculationKey[32], DWORD keyLength,
		PBYTE signature, PDWORD signatureLength, BYTE secureChannelProtocol);

//! \brief GlobalPlatform2.1.1: Calculates a Load File Data Block Signature using SHA-1 and PKCS#1 (RSA).
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_rsa_DAP(BYTE loadFileDataBlockHash[20], PBYTE securityDomainAID,
					   DWORD securityDomainAIDLength, OPGP_STRING PEMKeyFileName,
					   char *passPhrase, GP211_DAP_BLOCK *loadFileDataBlockSignature);

//! \brief GlobalPlatform2.1.1: Calculates a Load File Data Block Signature using SHA-256/SHA-512 and RSA-PSS (Scheme 2).
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_rsa_schemeX_DAP(PBYTE loadFileDataBlockHash, DWORD loadFileDataBlockHashLength,
				   OPGP_STRING PEMKeyFileName, char *passPhrase,
				   PBYTE signature, PDWORD signatureLength);

//! \brief GlobalPlatform2.3.1: Calculates an ECC Load File Data Block Signature in plain format (TR-03111 r||s).
OPGP_API
OPGP_ERROR_STATUS GP211_calculate_ecc_DAP(PBYTE loadFileDataBlockHash, DWORD loadFileDataBlockHashLength,
				   OPGP_STRING PEMKeyFileName, char *passPhrase,
				   PBYTE signature, PDWORD signatureLength);

//! \brief GlobalPlatform2.3.1: Validates a Delete Receipt with symmetric (DES/AES) or asymmetric (RSA/ECC) receipt keys.
OPGP_API
OPGP_ERROR_STATUS GP211_validate_delete_receipt(PBYTE receiptKey, DWORD keyLength, GP211_RECEIPT_DATA receiptData,
						  PBYTE AID, DWORD AIDLength,
						  BYTE receiptKeyType, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Validates an Install Receipt with symmetric (DES/AES) or asymmetric (RSA/ECC) receipt keys.
OPGP_API
OPGP_ERROR_STATUS GP211_validate_install_receipt(PBYTE receiptKey, DWORD keyLength, GP211_RECEIPT_DATA receiptData,
						   PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
						   PBYTE applicationAID, DWORD applicationAIDLength,
						   BYTE receiptKeyType, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Validates a Load Receipt with symmetric (DES/AES) or asymmetric (RSA/ECC) receipt keys.
OPGP_API
OPGP_ERROR_STATUS GP211_validate_load_receipt(PBYTE receiptKey, DWORD keyLength, GP211_RECEIPT_DATA receiptData,
						PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
						PBYTE securityDomainAID, DWORD securityDomainAIDLength,
						BYTE receiptKeyType, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Validates an Extradition Receipt with symmetric (DES/AES) or asymmetric (RSA/ECC) receipt keys.
OPGP_API
OPGP_ERROR_STATUS GP211_validate_extradition_receipt(PBYTE receiptKey, DWORD keyLength, GP211_RECEIPT_DATA receiptData,
							   PBYTE oldSecurityDomainAID, DWORD oldSecurityDomainAIDLength,
							   PBYTE newSecurityDomainAID, DWORD newSecurityDomainAIDLength,
							   PBYTE applicationOrExecutableLoadFileAID,
							   DWORD applicationOrExecutableLoadFileAIDLength,
							   BYTE receiptKeyType, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief GlobalPlatform2.3.1: Validates a Registry Update Receipt with symmetric (DES/AES) or asymmetric (RSA/ECC) receipt keys.
OPGP_API
OPGP_ERROR_STATUS GP211_validate_registry_update_receipt(PBYTE receiptKey, DWORD keyLength, GP211_RECEIPT_DATA receiptData,
								  PBYTE oldSecurityDomainAID, DWORD oldSecurityDomainAIDLength,
								  PBYTE applicationAID, DWORD applicationAIDLength,
								  PBYTE newSecurityDomainAID, DWORD newSecurityDomainAIDLength,
								  DWORD applicationPrivileges,
								  PBYTE registryUpdateParameters, DWORD registryUpdateParametersLength,
								  BYTE receiptKeyType, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief ISO 7816-4 / GlobalPlatform2.1.1: Opens or closes a Logical Channel.
OPGP_API
OPGP_ERROR_STATUS OPGP_manage_channel(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO *cardInfo, GP211_SECURITY_INFO *secInfo,
					BYTE openClose, BYTE channelNumberToClose,
					BYTE *channelNumberOpened);

//! \brief ISO 7816-4 / GlobalPlatform2.1.1: If multiple Logical Channels are open or a new Logical Channel is opened with select_application(), selects the Logical Channel.
OPGP_API
OPGP_ERROR_STATUS OPGP_select_channel(OPGP_CARD_INFO *cardInfo, BYTE channelNumber);

//! \brief Calculates the key check value of a key.
OPGP_ERROR_STATUS OPGP_calculate_key_check_value(GP211_SECURITY_INFO *secInfo,
	BYTE keyType, PBYTE keyData, DWORD keyDataLength, BYTE keyCheckValue[3]);

//! \brief Encrypts sensitive data like keys or other data which is used in STORE DATA.
OPGP_ERROR_STATUS OPGP_encrypt_sensitive_data(GP211_SECURITY_INFO *secInfo,
	PBYTE data, DWORD dataLength,
	PBYTE encryptedData, PDWORD encryptedDataLength);

//! \brief GlobalPlatform2.1.1: The STORE DATA command is used to transfer data to an Application or the Security Domain processing the command.
OPGP_API
OPGP_ERROR_STATUS GP211_store_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE encryptionFlags, BYTE formatFlags, BOOL responseDataExpected, PBYTE data, DWORD dataLength);

//! \brief SCP11: STORE DATA for the ECKA certificate store (section 6.7).
OPGP_API
OPGP_ERROR_STATUS GP211_store_data_ecka_certificate(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE keyVersionNumber, BYTE keyIdentifier,
				 OPGP_STRING certificateStoreFileName);

//! \brief SCP11: STORE DATA for a whitelist linked to a PK.CA-KLOC.ECDSA (section 6.8).
OPGP_API
OPGP_ERROR_STATUS GP211_store_data_whitelist(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 BYTE keyVersionNumber, BYTE keyIdentifier,
				 BOOL whitelistCounterPresent, USHORT whitelistCounter,
				 PBYTE *certificateSerialNumbers, PDWORD certificateSerialNumberLengths,
				 DWORD certificateSerialNumberCount);

//! \brief SCP11: STORE DATA for a CA-KLOC Identifier to PK.CA-KLOC.ECDSA mapping (section 6.9).
OPGP_API
OPGP_ERROR_STATUS GP211_store_data_ca_kloc_kid_kvn(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 PBYTE caKlocIdentifier, DWORD caKlocIdentifierLength,
				 BYTE keyIdentifier, BYTE keyVersionNumber);

//! \brief GlobalPlatform2.3.1: Builds STORE DATA encoding for symmetric keys according to section 11.11.4.
OPGP_API
OPGP_ERROR_STATUS GP211_build_store_data_keys(BYTE scp, BYTE scpImpl, PBYTE dataEncryptionKey, DWORD dataEncryptionKeyLength,
				 BYTE keyType, USHORT keyPurpose, PBYTE keys[], BYTE keyIds[], DWORD numKeys,
				 DWORD keyLength, BYTE keyVersion, BYTE keyAccessCondition, PBYTE output, PDWORD outputLength);

//! \brief GlobalPlatform2.3.1: STORE DATA command for storing secure channel keys using the symmetric key format.
OPGP_API
OPGP_ERROR_STATUS GP211_store_secure_channel_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo,
				 PBYTE AID, DWORD AIDLength,
				 BYTE keyType, PBYTE baseKey, PBYTE newS_ENC, PBYTE newS_MAC, PBYTE newDEK,
				 DWORD keyLength, BYTE keySetVersion, BYTE keyAccessCondition);

//! \brief Open Platform: Gets the life cycle status of Applications, the Card Manager and Executable Load Files and their privileges.
OPGP_API
OPGP_ERROR_STATUS OP201_get_status(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, BYTE cardElement, OP201_APPLICATION_DATA *applData, PDWORD applDataLength);

//! \brief Open Platform: Sets the life cycle status of Applications, Security Domains or the Card Manager.
OPGP_API
OPGP_ERROR_STATUS OP201_set_status(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, BYTE statusType, PBYTE AID, DWORD AIDLength, BYTE lifeCycleState);


//! \brief Open Platform: Mutual authentication.
OPGP_API
OPGP_ERROR_STATUS OP201_mutual_authentication(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, PBYTE baseKey, PBYTE encKey, PBYTE macKey,
								 PBYTE kekKey, BYTE keySetVersion,
						   BYTE keyIndex, BYTE securityLevel, BYTE derivationMethod,
						   OP201_SECURITY_INFO *secInfo);

//! \brief Open Platform: Retrieve card data.
OPGP_API
OPGP_ERROR_STATUS OP201_get_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
					BYTE identifier[2], PBYTE recvBuffer, PDWORD recvBufferLength);

//! \brief Open Platform: Put card data.
OPGP_API
OPGP_ERROR_STATUS OP201_put_data(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
					BYTE identifier[2], PBYTE dataObject, DWORD dataObjectLength);

//! \brief Open Platform: Changes or unblocks the global PIN.
OPGP_API
OPGP_ERROR_STATUS OP201_pin_change(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				BYTE tryLimit, PBYTE newPIN, DWORD newPINLength, BYTE KEK[16]);

//! \brief Open Platform: replaces a single 3DES key in a key set or adds a new 3DES key.
OPGP_API
OPGP_ERROR_STATUS OP201_put_3desKey(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				  BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, BYTE _3desKey[16]);

//! \brief Open Platform: replaces a single public RSA key in a key set or adds a new public RSA key.
OPGP_API
OPGP_ERROR_STATUS OP201_put_rsa_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				 BYTE keySetVersion, BYTE keyIndex, BYTE newKeySetVersion, OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief Open Platform: replaces or adds a secure channel key set consisting of encryption key, MAC key and key encryption.
OPGP_API
OPGP_ERROR_STATUS OP201_put_secure_channel_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
							 BYTE keySetVersion, BYTE newKeySetVersion,
							 BYTE new_encKey[16], BYTE new_macKey[16], BYTE new_KEK[16]);

//! \brief Open Platform: deletes a key or multiple keys.
OPGP_API
OPGP_ERROR_STATUS OP201_delete_key(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				BYTE keySetVersion, BYTE keyIndex);

//! \brief Open Platform: Retrieves key information of keys on the card.
OPGP_API
OPGP_ERROR_STATUS OP201_get_key_information_templates(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
								   BYTE keyInformationTemplate,
								   OP201_KEY_INFORMATION *keyInformation, PDWORD keyInformationLength);

//! \brief Open Platform: Deletes a Executable Load File or an application.
OPGP_API
OPGP_ERROR_STATUS OP201_delete_application(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				   OPGP_AID *AIDs, DWORD AIDsLength,
				   OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataLength);

//! \brief Open Platform: Prepares the card for loading an application.
OPGP_API
OPGP_ERROR_STATUS OP201_install_for_load(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
					  PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE securityDomainAID,
					  DWORD securityDomainAIDLength, PBYTE loadFileDataBlockHash,
					  DWORD loadFileDataBlockHashLength, PBYTE loadToken, DWORD loadTokenLength,
					  DWORD nonVolatileCodeSpaceLimit, DWORD volatileDataSpaceLimit,
					  DWORD nonVolatileDataSpaceLimit);

//! \brief Open Platform: Function to retrieve the data to sign for delegated management in a Load Token.
OPGP_API
OPGP_ERROR_STATUS OP201_get_load_token_signature_data(PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
								   PBYTE securityDomainAID, DWORD securityDomainAIDLength,
								   PBYTE loadFileDataBlockHash, DWORD loadFileDataBlockHashLength,
								   DWORD nonVolatileCodeSpaceLimit,
								   DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
								   PBYTE loadTokenSignatureData, PDWORD loadTokenSignatureDataLength);

//! \brief Open Platform: Function to retrieve the data to sign for delegated management in an Install Token.
OPGP_API
OPGP_ERROR_STATUS OP201_get_install_token_signature_data(BYTE P1, PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
									  PBYTE AIDWithinLoadFileAID, DWORD AIDWithinLoadFileAIDLength,
									  PBYTE applicationInstanceAID, DWORD applicationInstanceAIDLength,
									  DWORD applicationPrivileges, DWORD volatileDataSpaceLimit,
									  DWORD nonVolatileDataSpaceLimit,
									  PBYTE applicationInstallParameters, DWORD applicationInstallParametersLength,
									  PBYTE sdParameters, DWORD sdParametersLength,
									  PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
									  PBYTE simSpecParams, DWORD simSpecParamsLength,
									  PBYTE installTokenSignatureData, PDWORD installTokenSignatureDataLength);

//! \brief Open Platform: Calculates a Load Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS OP201_calculate_load_token(PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE securityDomainAID,
						  DWORD securityDomainAIDLength, PBYTE loadFileDAP, DWORD loadFileDAPLength,
						  DWORD nonVolatileCodeSpaceLimit, DWORD volatileDataSpaceLimit,
						  DWORD nonVolatileDataSpaceLimit, PBYTE loadToken, PDWORD loadTokenLength,
						  OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief Open Platform: Calculates an Install Token using PKCS#1.
OPGP_API
OPGP_ERROR_STATUS OP201_calculate_install_token(BYTE P1, PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE AIDWithinLoadFileAID,
							 DWORD AIDWithinLoadFileAIDLength, PBYTE applicationInstanceAID,
							 DWORD applicationInstanceAIDLength, DWORD applicationPrivileges,
							 DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
							 PBYTE applicationInstallParameters, DWORD applicationInstallParametersLength,
							 PBYTE sdParameters, DWORD sdParametersLength,
							 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
							 PBYTE simSpecParams, DWORD simSpecParamsLength,
							 PBYTE installToken, PDWORD installTokenLength,
							 OPGP_STRING PEMKeyFileName, char *passPhrase);

//! \brief Open Platform: Calculates a Load File DAP.
OPGP_API
OPGP_ERROR_STATUS OP201_calculate_load_file_DAP(OP201_DAP_BLOCK *dapBlock, DWORD dapBlockLength,
							 OPGP_STRING executableLoadFileName, BYTE hash[20]);

//! \brief Open Platform: Loads a Executable Load File (containing an application) to the card.
OPGP_API
OPGP_ERROR_STATUS OP201_load(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				 OP201_DAP_BLOCK *dapBlock, DWORD dapBlockLength, OPGP_STRING executableLoadFileName,
				 OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable, OPGP_PROGRESS_CALLBACK *callback);

//! \brief Open Platform: Loads a Executable Load File (containing an application) from a buffer to the card.
OPGP_API
OPGP_ERROR_STATUS OP201_load_from_buffer(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
				 OP201_DAP_BLOCK *dapBlock, DWORD dapBlockLength,
				 PBYTE loadFilebuf, DWORD loadFileBufSize,
				 OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable, OPGP_PROGRESS_CALLBACK *callback);

//! \brief Open Platform: Installs an application on the card.
OPGP_API
OPGP_ERROR_STATUS OP201_install_for_install(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
						 PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE AIDWithinLoadFileAID,
						 DWORD AIDWithinLoadFileAIDLength, PBYTE applicationInstanceAID, DWORD applicationInstanceAIDLength,
						 DWORD applicationPrivileges, DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
						 PBYTE applicationInstallParameters, DWORD applicationInstallParametersLength,
						 PBYTE sdParameters, DWORD sdParametersLength,
						 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
						 PBYTE simSpecParams, DWORD simSpecParamsLength,
						 PBYTE installToken, DWORD installTokenLength,
						 OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief Open Platform: Makes an installed application selectable.
OPGP_API
OPGP_ERROR_STATUS OP201_install_for_make_selectable(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
								 PBYTE applicationInstanceAID, DWORD applicationInstanceAIDLength,
								 DWORD applicationPrivileges, PBYTE installToken, DWORD installTokenLength,
								 OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief Open Platform: Installs and makes an installed application selectable.
OPGP_API
OPGP_ERROR_STATUS OP201_install_for_install_and_make_selectable(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, 						 PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength, PBYTE AIDWithinLoadFileAID,
						 DWORD AIDWithinLoadFileAIDLength, PBYTE applicationInstanceAID,
						 DWORD applicationInstanceAIDLength, DWORD applicationPrivileges,
						 DWORD volatileDataSpaceLimit, DWORD nonVolatileDataSpaceLimit,
						 PBYTE applicationInstallParameters, DWORD applicationInstallParametersLength,
						 PBYTE sdParameters, DWORD sdParametersLength,
						 PBYTE uiccSystemSpecParams, DWORD uiccSystemSpecParamsLength,
						 PBYTE simSpecParams, DWORD simSpecParamsLength,
						 PBYTE installToken, DWORD installTokenLength,
						 OP201_RECEIPT_DATA *receiptData, PDWORD receiptDataAvailable);

//! \brief Open Platform: Adds a key set for Delegated Management.
OPGP_API
OPGP_ERROR_STATUS OP201_put_delegated_management_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
								   BYTE keySetVersion,
								   BYTE newKeySetVersion,
								   OPGP_STRING PEMKeyFileName, char *passPhrase,
								   BYTE receiptGenerationKey[16]);

//! \brief Sends an application protocol data unit.
OPGP_API
OPGP_ERROR_STATUS OP201_send_APDU(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo,
					 PBYTE capdu, DWORD capduLength, PBYTE rapdu,
			   PDWORD rapduLength);

//! \brief Open Platform: Calculates a Load File Data Block DAP using 3DES.
OPGP_API
OPGP_ERROR_STATUS OP201_calculate_3des_DAP(PBYTE securityDomainAID, DWORD securityDomainAIDLength, OPGP_STRING executableLoadFileName,
						BYTE DAP_verification_key[16], OP201_DAP_BLOCK *dapBlock);

//! \brief Open Platform: Calculates a Load File Data Block DAP using SHA-1 and PKCS#1 (RSA).
OPGP_API
OPGP_ERROR_STATUS OP201_calculate_rsa_DAP(PBYTE securityDomainAID, DWORD securityDomainAIDLength, OPGP_STRING executableLoadFileName,
					   OPGP_STRING PEMKeyFileName, char *passPhrase, OP201_DAP_BLOCK *dapBlock);

//! \brief Open Platform: Validates a Load Receipt.
OPGP_API
OPGP_ERROR_STATUS OP201_validate_delete_receipt(DWORD confirmationCounter, BYTE cardUniqueData[10],
						   BYTE receiptGenerationKey[16], OP201_RECEIPT_DATA receiptData,
						   PBYTE AID, DWORD AIDLength);

//! \brief Open Platform: Validates an Install Receipt.
OPGP_API
OPGP_ERROR_STATUS OP201_validate_install_receipt(DWORD confirmationCounter, BYTE cardUniqueData[10],
						   BYTE receiptGenerationKey[16], OP201_RECEIPT_DATA receiptData,
						   PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
						   PBYTE applicationInstanceAID, DWORD applicationInstanceAIDLength);

//! \brief Open Platform: Validates a Load Receipt.
OPGP_API
OPGP_ERROR_STATUS OP201_validate_load_receipt(DWORD confirmationCounter, BYTE cardUniqueData[10],
						   BYTE receiptGenerationKey[16], OP201_RECEIPT_DATA receiptData,
						   PBYTE executableLoadFileAID, DWORD executableLoadFileAIDLength,
						   PBYTE securityDomainAID, DWORD securityDomainAIDLength);


//! \brief Initiates a R-MAC session.
OPGP_API
OPGP_ERROR_STATUS GP211_begin_R_MAC(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, BYTE securityLevel, PBYTE data, DWORD dataLength);

//! \brief Terminates a R-MAC session.
OPGP_API
OPGP_ERROR_STATUS GP211_end_R_MAC(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, BYTE secureChannelProtocol);

//! \brief Reads the parameters of an Executable Load File.
OPGP_API
OPGP_ERROR_STATUS OPGP_read_executable_load_file_parameters(OPGP_STRING loadFileName, OPGP_LOAD_FILE_PARAMETERS *loadFileParams);

//! \brief Converts a CAP file to an IJC file (Executable Load File).
OPGP_API
OPGP_ERROR_STATUS OPGP_cap_to_ijc(OPGP_CSTRING capFileName, OPGP_STRING ijcFileName);

//! \brief Extracts a CAP file into a buffer.
OPGP_API
OPGP_ERROR_STATUS OPGP_extract_cap_file(OPGP_CSTRING fileName, PBYTE loadFileBuf, PDWORD loadFileBufSize);

//! \brief Receives Executable Load File as a buffer instead of a FILE.
OPGP_API
OPGP_ERROR_STATUS OPGP_read_executable_load_file_parameters_from_buffer(PBYTE loadFileBuf, DWORD loadFileBufSize, OPGP_LOAD_FILE_PARAMETERS *loadFileParams);

//! \brief Derives the static keys from a master key according the EMV CPS 1.1 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS GP211_EMV_CPS11_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, PBYTE masterKey,
							PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 2 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS GP211_VISA2_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, PBYTE AID, DWORD AIDLength, PBYTE masterKey,
								 PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 1 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS GP211_VISA1_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, GP211_SECURITY_INFO *secInfo, PBYTE masterKey,
								 PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the EMV CPS 1.1 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS OP201_EMV_CPS11_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, PBYTE masterKey,
							PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 2 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS OP201_VISA2_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, PBYTE AID, DWORD AIDLength, PBYTE masterKey,
								 PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 1 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS OP201_VISA1_derive_keys(OPGP_CARD_CONTEXT cardContext, OPGP_CARD_INFO cardInfo, OP201_SECURITY_INFO *secInfo, PBYTE masterKey,
								 PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 2 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS VISA2_derive_keys(BYTE baseKeyDiversificationData[10], PBYTE masterKey,
							PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the VISA 1 key derivation scheme.
OPGP_API
OPGP_ERROR_STATUS VISA1_derive_keys(BYTE cardSerialNumber[8], PBYTE masterKey,
							PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

//! \brief Derives the static keys from a master key according the EMV CPS11 derivation scheme.
OPGP_API
OPGP_ERROR_STATUS EMV_CPS11_derive_keys(BYTE baseKeyDiversificationData[10], PBYTE masterKey,
							PBYTE S_ENC, PBYTE S_MAC, PBYTE DEK);

#ifdef __cplusplus
}
#endif
#endif
