# 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](/t1c-js-guide/core/status-codes.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://t1t.gitbook.io/t1c-js-guide/containers/other/ocra-hotp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
