@startuml
title
    <img:../assets/logo.svg{scale=0.2}>

    Terminal Calypso Card API 2.1.+ (2024-01-16)
end title

' == THEME ==

'Couleurs issues de : https://htmlcolorcodes.com/fr/tableau-de-couleur/tableau-de-couleur-design-plat/
!define C_GREY1 F8F9F9
!define C_GREY2 F2F3F4
!define C_GREY3 E5E7E9
!define C_GREY4 D7DBDD
!define C_GREY5 CACFD2
!define C_GREY6 BDC3C7
!define C_LINK 3498DB
!define C_USE 27AE60
!define C_THROW 2C3E50

' -- Styles that don't work with new version of plantuml --
skinparam stereotypeABorderColor #A9DCDF
skinparam stereotypeIBorderColor #B4A7E5
skinparam stereotypeCBorderColor #ADD1B2
skinparam stereotypeEBorderColor #EB93DF
' -- END --

skinparam ClassBorderThickness 2
skinparam ArrowThickness 2

' Yellow
skinparam ClassBackgroundColor #FEFECE
skinparam ClassBorderColor #D4AC0D
' Red
skinparam ClassBackgroundColor<<red>> #FDEDEC
skinparam ClassBorderColor<<red>> #E74C3C
hide <<red>> stereotype
' Purple
skinparam ClassBackgroundColor<<purple>> #F4ECF7
skinparam ClassBorderColor<<purple>> #8E44AD
hide <<purple>> stereotype
' blue
skinparam ClassBackgroundColor<<blue>> #EBF5FB
skinparam ClassBorderColor<<blue>> #3498DB
hide <<blue>> stereotype
' Green
skinparam ClassBackgroundColor<<green>> #E9F7EF
skinparam ClassBorderColor<<green>> #27AE60
hide <<green>> stereotype
' Grey
skinparam ClassBackgroundColor<<grey>> #EAECEE
skinparam ClassBorderColor<<grey>> #2C3E50
hide <<grey>> stereotype

' == CONTENT ==

legend top
    __Colors legend__ :
    * <color:grey>Work in progress...
    * __External public API references__ :
    ** <back:yellow>**Calypsonet Terminal Reader API**</back>
end legend

package "calypso.card" as calypsoCard {

+class "**final** CalypsoCardApiProperties" as ApiProperties <<green>> {
    +{static} **final** String VERSION
}
+interface "CalypsoCardApiFactory" as CalypsoCardApiFactory <<blue>> {
    +CalypsoCardSelectionExtension createCalypsoCardSelectionExtension ()

    +SymmetricCryptoSecuritySetting createSymmetricCryptoSecuritySetting (SymmetricCryptoCardTransactionManagerFactory cryptoCardTransactionManagerFactory)
    +<color:blue>AsymmetricCryptoSecuritySetting createAsymmetricCryptoSecuritySetting (AsymmetricCryptoCardTransactionManagerFactory cryptoCardTransactionManagerFactory)

    +FreeTransactionManager createFreeTransactionManager (<back:yellow>CardReader</back> cardReader, CalypsoCard card)
    +SecureRegularModeTransactionManager createSecureRegularModeTransactionManager (<back:yellow>CardReader</back> cardReader, CalypsoCard card, SymmetricCryptoSecuritySetting securitySetting)
    +SecureExtendedModeTransactionManager createSecureExtendedModeTransactionManager (<back:yellow>CardReader</back> cardReader, CalypsoCard card, SymmetricCryptoSecuritySetting securitySetting)
    +<color:blue>SecurePkiModeTransactionManager createSecurePkiModeTransactionManager (<back:yellow>CardReader</back> cardReader, CalypsoCard card, AsymmetricCryptoSecuritySetting securitySetting)

    +SearchCommandData createSearchCommandData ()
}
+enum WriteAccessLevel <<green>> {
    PERSONALIZATION
    LOAD
    DEBIT
}
+enum SelectFileControl <<green>> {
    FIRST_EF
    NEXT_EF
    CURRENT_DF
}
+enum GetDataTag <<green>> {
    FCP_FOR_CURRENT_FILE
    FCI_FOR_CURRENT_DF
    EF_LIST
    TRACEABILITY_INFORMATION
    <color:blue>CARD_PUBLIC_KEY
    <color:blue>CARD_CERTIFICATE
    <color:blue>CA_CERTIFICATE
}
+enum "<color:blue>PutDataTag" as PutDataTag <<green>> {
    <color:blue>CARD_KEY_PAIR
    <color:blue>CARD_CERTIFICATE
    <color:blue>CA_CERTIFICATE
}
package "card" as card {
    +interface "<<<back:yellow>CardSelectionExtension</back>>>\nCalypsoCardSelectionExtension" as CalypsoCardSelectionExtension <<blue>> {
        +CalypsoCardSelectionExtension acceptInvalidatedCard ()

        +CalypsoCardSelectionExtension prepareSelectFile (short lid)
        +CalypsoCardSelectionExtension prepareSelectFile (SelectFileControl selectControl)

        +CalypsoCardSelectionExtension prepareGetData (GetDataTag tag)

        +CalypsoCardSelectionExtension prepareReadRecord (byte sfi, int recordNumber)
        +CalypsoCardSelectionExtension prepareReadBinary (byte sfi, int offset, int nbBytesToRead)
        +CalypsoCardSelectionExtension prepareReadCounter (byte sfi, int nbCountersToRead)

        +CalypsoCardSelectionExtension preparePreOpenSecureSession (WriteAccessLevel writeAccessLevel)
    }
    +interface "<<<back:yellow>IsoSmartCard</back>>>\nCalypsoCard" as CalypsoCard {
        +ProductType getProductType ()
        +boolean isHce ()

        +boolean isDfInvalidated ()

        +byte[] getDfName ()
        +byte[] getApplicationSerialNumber ()

        +byte[] getStartupInfoRawData ()
        +byte getPlatform ()
        +byte getApplicationType ()
        +byte getApplicationSubtype ()
        +byte getSoftwareIssuer ()
        +byte getSoftwareVersion ()
        +byte getSoftwareRevision ()
        +byte getSessionModification ()

        +byte[] getTraceabilityInformation ()

        +<color:blue>byte[] getCardPublicKey ()
        +<color:blue>byte[] getCardCertificate ()
        +<color:blue>byte[] getCaCertificate ()

        +DirectoryHeader getDirectoryHeader ()
        +ElementaryFile getFileBySfi (byte sfi)
        +ElementaryFile getFileByLid (short lid)
        +Set<ElementaryFile> getFiles ()

        +boolean isDfRatified ()
        +int getTransactionCounter ()

        +boolean isPkiModeSupported ()
        +boolean isExtendedModeSupported ()
        +boolean isRatificationOnDeselectSupported ()

        +boolean isPinFeatureAvailable ()
        +boolean isPinBlocked ()
        +int getPinAttemptRemaining ()

        +boolean isSvFeatureAvailable ()
        +int getSvBalance ()
        +int getSvLastTNum ()
        +SvLoadLogRecord getSvLoadLogRecord ()
        +SvDebitLogRecord getSvDebitLogLastRecord ()
        +List<SvDebitLogRecord> getSvDebitLogAllRecords ()
    }
    +interface DirectoryHeader {
        +short getLid ()
        +Byte getDfStatus ()

        +byte[] getAccessConditions ()
        +byte[] getKeyIndexes ()

        +byte getKif (WriteAccessLevel writeAccessLevel)
        +byte getKvc (WriteAccessLevel writeAccessLevel)
    }
    +interface ElementaryFile {
        +byte getSfi ()
        +FileHeader getHeader ()
        +FileData getData ()
    }
    +interface FileHeader {
        +short getLid ()
        +byte getDfStatus ()
        +ElementaryFile.Type getEfType ()

        +int getRecordsNumber ()
        +int getRecordSize ()

        +byte[] getAccessConditions ()
        +byte[] getKeyIndexes ()

        +Short getSharedReference ()
    }
    +enum "Type" as FileType <<green>> {
        LINEAR
        BINARY
        CYCLIC
        COUNTERS
        SIMULATED_COUNTERS
    }
    +interface FileData {
        +byte[] getContent ()
        +byte[] getContent (int numRecord)
        +byte[] getContent (int numRecord, int dataOffset, int dataLength)
        +SortedMap<Integer, byte[]> getAllRecordsContent ()

        +Integer getContentAsCounterValue (int numCounter)
        +SortedMap<Integer, Integer> getAllCountersValue ()
    }
    +enum "ProductType" as CardProductType <<green>> {
        PRIME_REVISION_1
        PRIME_REVISION_2
        PRIME_REVISION_3
        LIGHT
        BASIC
        UNKNOWN
    }
    +interface SvLoadLogRecord {
        +byte[] getRawData ()

        +byte[] getLoadDate ()
        +byte[] getLoadTime ()

        +int getAmount ()
        +int getBalance ()
        +byte[] getFreeData ()

        +byte getKvc ()
        +byte[] getSamId ()
        +int getSamTNum ()
        +int getSvTNum ()
    }
    +interface SvDebitLogRecord {
        +byte[] getRawData ()

        +byte[] getDebitDate ()
        +byte[] getDebitTime ()

        +int getAmount ()
        +int getBalance ()

        +byte getKvc ()
        +byte[] getSamId ()
        +int getSamTNum ()
        +int getSvTNum ()
    }
}
package "transaction" as transaction {
    ' Card
    +interface "TransactionManager" as TransactionManager<T extends TransactionManager<T>> {
        +T prepareSelectFile (short lid)
        +T prepareSelectFile (SelectFileControl selectFileControl)

        +T prepareGetData (GetDataTag tag)
        +<color:blue>T preparePutData (PutDataTag tag, byte[] data)

        +T prepareReadRecord (byte sfi, int recordNumber)
        +T prepareReadRecords (byte sfi, int fromRecordNumber, int toRecordNumber, int recordSize)
        +T prepareReadRecordsPartially (byte sfi, int fromRecordNumber, int toRecordNumber, int offset, int nbBytesToRead)
        +T prepareReadBinary (byte sfi, int offset, int nbBytesToRead)
        +T prepareReadCounter (byte sfi, int nbCountersToRead)

        +T prepareSearchRecords (SearchCommandData data)

        +T prepareCheckPinStatus ()

        +T prepareAppendRecord (byte sfi, byte[] recordData)
        +T prepareUpdateRecord (byte sfi, int recordNumber, byte[] recordData)
        +T prepareWriteRecord (byte sfi, int recordNumber, byte[] recordData)

        +T prepareUpdateBinary (byte sfi, int offset, byte[] data)
        +T prepareWriteBinary (byte sfi, int offset, byte[] data)

        +T prepareIncreaseCounter (byte sfi, int counterNumber, int incValue)
        +T prepareIncreaseCounters (byte sfi, Map<Integer, Integer> counterNumberToIncValueMap)
        +T prepareDecreaseCounter (byte sfi, int counterNumber, int decValue)
        +T prepareDecreaseCounters (byte sfi, Map<Integer, Integer> counterNumberToDecValueMap)
        +T prepareSetCounter (byte sfi, int counterNumber, int newValue)

        +T prepareSvReadAllLogs ()

        +T prepareVerifyPin (byte[] pin)
        +T prepareChangePin (byte[] newPin)

        +<color:blue>T prepareGenerateAsymmetricKeyPair ()

        +T processCommands (ChannelControl channelControl)

        +List<byte[]> getTransactionAuditData ()
    }
    +enum "ChannelControl" as ChannelControl <<green>> {
        KEEP_OPEN
        CLOSE_AFTER
    }
    +interface "FreeTransactionManager" as FreeTransactionManager <<blue>> extends TransactionManager {
    }
    +interface "SecureTransactionManager" as SecureTransactionManager<T extends SecureTransactionManager<T>> extends TransactionManager {
        +<E extends CardTransactionCryptoExtension> E getCryptoExtension (Class<E> cryptoExtensionClass)

        +T prepareCloseSecureSession ()
        +T prepareCancelSecureSession ()
    }
    +interface "SecureSymmetricCryptoTransactionManager" as SecureSymmetricCryptoTransactionManager<T extends SecureSymmetricCryptoTransactionManager<T>> extends SecureTransactionManager {
        +T prepareOpenSecureSession (WriteAccessLevel writeAccessLevel)

        +T prepareSvGet (SvOperation svOperation, SvAction svAction)
        +T prepareSvReload (int amount, byte[] date, byte[] time, byte[] free)
        +T prepareSvReload (int amount)
        +T prepareSvDebit (int amount, byte[] date, byte[] time)
        +T prepareSvDebit (int amount)

        +T prepareInvalidate ()
        +T prepareRehabilitate ()

        +T prepareChangeKey (int keyIndex, byte newKif, byte newKvc, byte issuerKif, byte issuerKvc)
    }
    +interface "SecureRegularModeTransactionManager" as SecureRegularModeTransactionManager <<blue>> extends SecureSymmetricCryptoTransactionManager {
    }
    +interface "SecureExtendedModeTransactionManager" as SecureExtendedModeTransactionManager <<blue>> extends SecureSymmetricCryptoTransactionManager {
        +SecureExtendedModeTransactionManager prepareEarlyMutualAuthentication ()
        +SecureExtendedModeTransactionManager prepareActivateEncryption ()
        +SecureExtendedModeTransactionManager prepareDeactivateEncryption ()
    }
    +interface "<color:blue>SecurePkiModeTransactionManager" as SecurePkiModeTransactionManager <<blue>> extends SecureTransactionManager {
        +<color:blue>SecurePkiModeTransactionManager prepareOpenSecureSession ()
    }

    +enum SvOperation <<green>> {
        RELOAD
        DEBIT
    }
    +enum SvAction <<green>> {
        DO
        UNDO
    }
    +interface "<color:blue>AsymmetricCryptoSecuritySetting" as AsymmetricCryptoSecuritySetting <<blue>> {
        +<color:blue>AsymmetricCryptoSecuritySetting addPcaCertificate (PcaCertificate pcaCertificate)
        +<color:blue>AsymmetricCryptoSecuritySetting addCaCertificate (CaCertificate caCertificate)

        +<color:blue>AsymmetricCryptoSecuritySetting addCaCertificateFactory (CaCertificateFactory caCertificateFactory)
        +<color:blue>AsymmetricCryptoSecuritySetting addCardCertificateFactory (CardCertificateFactory cardCertificateFactory)
    }
    +interface "SymmetricCryptoSecuritySetting" as SymmetricCryptoSecuritySetting <<blue>> {
        +SymmetricCryptoSecuritySetting enableMultipleSession ()
        +SymmetricCryptoSecuritySetting enableRatificationMechanism ()
        +SymmetricCryptoSecuritySetting enablePinPlainTransmission ()
        +SymmetricCryptoSecuritySetting enableSvLoadAndDebitLog ()
        +SymmetricCryptoSecuritySetting authorizeSvNegativeBalance ()
        +SymmetricCryptoSecuritySetting disableReadOnSessionOpening ()

        +SymmetricCryptoSecuritySetting assignKif (WriteAccessLevel writeAccessLevel, byte kvc, byte kif)
        +SymmetricCryptoSecuritySetting assignDefaultKif (WriteAccessLevel writeAccessLevel, byte kif)
        +SymmetricCryptoSecuritySetting assignDefaultKvc (WriteAccessLevel writeAccessLevel, byte kvc)

        +SymmetricCryptoSecuritySetting addAuthorizedSessionKey (byte kif, byte kvc)
        +SymmetricCryptoSecuritySetting addAuthorizedSvKey (byte kif, byte kvc)

        +SymmetricCryptoSecuritySetting setPinVerificationCipheringKey (byte kif, byte kvc)
        +SymmetricCryptoSecuritySetting setPinModificationCipheringKey (byte kif, byte kvc)

        +void initCryptoContextForNextTransaction ()
    }
    +interface SearchCommandData <<blue>> {
        +SearchCommandData setSfi (byte sfi)
        +SearchCommandData startAtRecord (int recordNumber)
        +SearchCommandData setOffset (int offset)
        +SearchCommandData enableRepeatedOffset ()
        +SearchCommandData setSearchData (byte[] data)
        +SearchCommandData setMask (byte[] mask)
        +SearchCommandData fetchFirstMatchingResult ()

        +List<Integer> getMatchingRecordNumbers ()
    }
    ' Exceptions
    +class "<<RuntimeException>>" as RuntimeException <<green>> {
        +**SessionBufferOverflowException**: Session buffer would overflow for atomic session.
        +**UnauthorizedKeyException**
        +**InvalidPinException**
        +<color:blue>**InvalidCertificateException**
        +**InconsistentDataException**: Number of R-APDUs != number of C-APDUs **or** data read in session != data read outside session.
        +**InvalidCardSignatureException**
        +**CardSignatureNotVerifiableException**: CloseSecureSession is successful but crypto resource is no more available to check the card MAC.
        +**SelectFileException**
        +**UnexpectedCommandStatusException**
        +**ReaderIOException**: Card reader and/or Crypto reader communication is broken.
        +**CardIOException**
        +**CryptoException**
        +**CryptoIOException**
    }
    package "spi" as spi {
        +interface "AsymmetricCryptoCardTransactionManagerFactory" as AsymmetricCryptoCardTransactionManagerFactory <<red>> {
        }
        +interface "CaCertificateFactory" as CaCertificateFactory <<red>> {
        }
        +interface "CardCertificateFactory" as CardCertificateFactory <<red>> {
        }
        +interface "PcaCertificate" as PcaCertificate <<red>> {
        }
        +interface "CaCertificate" as CaCertificate <<red>> {
        }
        +interface "SymmetricCryptoCardTransactionManagerFactory" as SymmetricCryptoCardTransactionManagerFactory <<red>> {
        }
        +interface "CardTransactionCryptoExtension" as CardTransactionCryptoExtension <<red>> {
        }
    }
}

}

' Associations

TransactionManager .up.> SelectFileControl #C_USE : use >
TransactionManager .up.> GetDataTag #C_USE : use >
TransactionManager .up.> PutDataTag #C_USE : use >
TransactionManager .left.> ChannelControl #C_USE : use >
TransactionManager .right.> SearchCommandData #C_USE : use >

SecureTransactionManager .....> CardTransactionCryptoExtension #C_LINK : provide >

SecureSymmetricCryptoTransactionManager .up.> WriteAccessLevel #C_USE : use >
SecureSymmetricCryptoTransactionManager .right.> SvOperation #C_USE : use >
SecureSymmetricCryptoTransactionManager .right.> SvAction #C_USE : use >

SymmetricCryptoSecuritySetting .up.> WriteAccessLevel #C_USE : use >

AsymmetricCryptoSecuritySetting .up.> PcaCertificate #C_USE : use >
AsymmetricCryptoSecuritySetting .up.> CaCertificate #C_USE : use >
AsymmetricCryptoSecuritySetting .up.> CaCertificateFactory #C_USE : use >
AsymmetricCryptoSecuritySetting .up.> CardCertificateFactory #C_USE : use >

CalypsoCardSelectionExtension .up.> SelectFileControl #C_USE : use >
CalypsoCardSelectionExtension .up.> GetDataTag #C_USE : use >
CalypsoCardSelectionExtension .up.> WriteAccessLevel #C_USE : use >

CalypsoCard ..> DirectoryHeader #C_LINK : provide >
CalypsoCard ..> ElementaryFile #C_LINK : provide >
CalypsoCard +-right- CardProductType
CalypsoCard .right.> CardProductType #C_LINK : provide >
CalypsoCard ..> SvLoadLogRecord #C_LINK : provide >
CalypsoCard ..> SvDebitLogRecord #C_LINK : provide >

DirectoryHeader ..> WriteAccessLevel #C_USE : use >

ElementaryFile +-- FileType
ElementaryFile ...> FileHeader #C_LINK : provide >
ElementaryFile ...> FileData #C_LINK : provide >

FileHeader .up.> FileType #C_LINK : provide >

' == LAYOUT ==

'SymmetricCryptoSecuritySetting -[hidden]- AsymmetricCryptoSecuritySetting
AsymmetricCryptoSecuritySetting -[hidden]left- RuntimeException

AsymmetricCryptoCardTransactionManagerFactory -[hidden]- PcaCertificate
PcaCertificate -[hidden]right- CaCertificate
CaCertificate -[hidden]right- CaCertificateFactory
CaCertificateFactory -[hidden]right- CardCertificateFactory

' == STYLE ==

package calypsoCard #C_GREY1 {}
package calypsoCard.card #C_GREY2 {}
package calypsoCard.transaction #C_GREY2 {}
package calypsoCard.transaction.spi #C_GREY3 {}

@enduml