# Ocra HOTP

The OCRA container facilitates communication with card readers with initialised OCRA applet. The T1C-JS client library provides function to communicate with the smart card and facilitates integration into a web or native application for the generation of HOTP challenges.\
This document describes the functionality provided by the OCRA - temporary documentation - on the T1C-GCL (Generic Connector Library).

## Refereces

The following standards must be taken into account:

* HOTP: An HMAC-Based One-Time Password Algorithm
  * <https://tools.ietf.org/html/rfc4226>
* OCRA: OATH Challenge-Response Algorithm
  * <https://tools.ietf.org/html/rfc6287>

## Generation of an HOTP Value

Additional reference upon the interpretation of the HOTP challenge received from the OCRA applet:

<https://tools.ietf.org/html/rfc4226#section-5.3>

## Resynchronization of the Counter

Additional reference upon the resynchronization of the counter:

<https://tools.ietf.org/html/rfc4226#section-7.4>

## Interface Summary

The Abstract LuxTrust smartcard interface is summarized in the following snippet:

```javascript
interface AbstractOcra{
    allDataFilters():Array<string>;
    challenge(body:any, callback:(error:CoreExceptions.RestException, data:any) => void):void;
    readCounter(body:any, callback:(error:CoreExceptions.RestException, data:any) => void):void;
    verifyPin(body:any, callback:(error:CoreExceptions.RestException, data:any) => void):void;
}
```

Each interface will be covered on this wiki, accompanied with example code and response objects.

## Get the OCRA container object

For more information on how to configure the T1C-JS client library see [Client Configuration](https://github.com/t1t/t1c-js-guide/tree/d4911732ca844433272e5bc8a397ac91e8313e25/containers/other/client_configuration.md).\
Initialize a gclClient:

```javascript
GCLLib.GCLClient.initialize(config, function(err, gclClient) {
    // gclClient ready to use
});
```

Get the Ocra container service:

```javascript
var ocra = gclClient.ocra(reader_id);
```

Call a function for the Ocra container:

```javascript
function callback(err,data) {
    if(err){console.log("Error:",JSON.stringify(err, null, '  '));}
    else {console.log(JSON.stringify(data, null, '  '));}
}

ocra.readCounter(callback);
```

### Obtain the Reader-ID

The constructor for the Ocra container expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see [Core Services](https://github.com/t1t/t1c-js-guide/tree/d4911732ca844433272e5bc8a397ac91e8313e25/containers/other/core_services.md).\
Core services responds with available card-readers, available card in a card-reader, etc.\
For example:\
In order to get all connected card-readers, with available cards:

```javascript
var coreService = gclClient.core();
core.readersCardAvailable(callback);
```

This function call returns:

```javascript
{
  "data": [
    {
      "card": {
        "atr": "3B7F94000080318065B0850300EF120FFF829000",
        "description": [
          "Gemalto Classic V4","Juridic Person's Token (PKI)"
        ]
      },
      "id": "707e7a6e449f2250",
      "name": "OMNIKEY CardMan 5321",
      "pinpad": false
    }
  ],
  "success": true
}
```

We notice that a card object is available in the response in the context of a detected reader.\
The reader in the example above is `VASCO DIGIPASS 870`, has pin-pad capabilities, and there is a card detected with given ATR and some descriptions.\
An ATR (**A**nswer **T**o **R**eset) identifies the type of a smart-card.\
The reader, has a unique ID, `reader_id`; this `reader_id` must be used in order to request functionalities for the Ocra card.\
This must be done upon instantiation of the Ocra container:

```javascript
var emv = gclClient.ocra(reader_id);
```

All methods for ocra will use the selected reader - identified by the `reader_id`.

## Reading data

### Counter

The counter on the card is incremented each time you generate a new otp with the challenge method.

```javascript
gclClient.ocra(reader_id).readCounter(callback);
```

An example callback:

```javascript
function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}
```

Response:

```javascript
{
  "counter": "12345678901234567",
  "success": true
}
```

## Data Filter

### Filter

All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:

```javascript
var filter = [];
gclClient.ocra().allData(filter,callback);
```

Response:

```javascript
{
  "data": {
    "counter": "zMzMzMzMzN4="
  },
  "success": true
}
```

The filter can be used to ask a list of custom data containers. At the moment only the 'counter' is supported:

```javascript
var filter = ['counter'];
gclClient.ocra().allData(filter,callback);
```

Response:

```javascript
{
  "data": {
    "counter": "zMzMzMzMzN4="
  },
  "success": true
}
```

## Verify PIN

When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:

```javascript
var data = {
    "pin":"..."
}
gclClient.ocra().verifyPin(data, callback);
```

Response:

```javascript
{
  "success": true
}
```

### Retries left

After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:

```javascript
  $("#buttonValidate").on('click', function () {
      var _body={};
      _body.pin = $("#psw").val(); //only when no pin-pad available
      var ocra = connector.ocra(reader_id);
      ocra.verifyPin(_body, validationCallback);
  });
```

The following error message will be returned when PIN is wrong:

```javascript
{
  "code": 103,
  "description": "Wrong pin, 2 tries remaining",
  "success": false
}
```

After a second wrong PIN verification:

```javascript
{
  "code": 104,
  "description": "Wrong pin, 1 try remaining",
  "success": false
}
```

Note that, when the user has at least one retry left, entering a correct PIN resets the `PIN retry status`.

| Code  | Description                                            |
| ----- | ------------------------------------------------------ |
| `103` | Warning: the user can try twice more to verify his PIN |
| `104` | Warning: the user has only 1 retry left                |
| `105` | Error: the PIN is blocked                              |
| 106   | Invalid PIN                                            |

## Challenge

To generate a new OTP value, the challenge method can be called. The request requires a valid PIN code and a challenge. The challenge is a base64 encoded bytestring .

```javascript
var data = {
    "pin": "...",
    "challenge": "kgg0MTQ4NTkzNZMA"
}
gclClient.ocra().challenge(data, callback);
```

Response:

```javascript
{
  "data": 50066323,
  "success": true
}
```

## Error Handling

### Error Object

The functions specified are asynchronous and always need a callback function.\
The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:

```javascript
function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}
```

The error object returned:

```javascript
{
  success: false,
  description: "some error description",
  code: "some error code"
}
```

For the error codes and description, see [Status codes](https://t1t.gitbook.io/t1c-js-guide/core/status-codes).
