Implemented RFC 4226 - HOTP: An HMAC based One-Time-Password Algorithm for BlackBerry 10 running QNX 6. Uses BlackBerry Cryptographic Kernel version 5.6 (SB-GSE-56). UI is pending and the app in the current state can be found at GitHub called QAuthenticator. I must say, BlackBerry cryptography library is just fantastic.

A reference implementation of the algorithm in Groovy follows.

/**
 * [RFC 4226] HOTP Algorithm - Reference Implementation
 * @author Jaseem V V
 * @date Sunday 03 September 2017
 */

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

byte[] hmac_sha1(byte[] keyBytes, byte[] text) {
    Mac hmacSha1 = Mac.getInstance("HmacSHA1");
    SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
    hmacSha1.init(macKey);
    return hmacSha1.doFinal(text);
}

doubleDigits = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]

int calcChecksum(long num, int digits) {
   doubleDigit = true;
   total = 0;
   while (0 < digits--) {
       digit = (int) (num % 10);
       num /= 10;
       if (doubleDigit) {
           digit = doubleDigits[digit];
       }
       total += digit;
       doubleDigit = !doubleDigit;
   }
   result = total % 10;
   if (result > 0) {
       result = 10 - result;
   }
   return result;
}

def getMovingFactor(long counter) {
    byte[] text = new byte[8];
    for (int i = text.length - 1; i >= 0; i--) {
        text[i] = (byte) (counter & 0xff);
        counter >>= 8;
    }
    text
}

def baToHex(ba) {
    String digest = ""
    ba.each {
        digest += String.format("%02x", it)
    }
    digest
}

def truncate(digest_ba, truncationOffset) {
    offset = digest_ba[digest_ba.size() - 1] & 0xf
    if ((0<=truncationOffset) && (truncationOffset < (digest_ba.length-4))) {
        offset = truncationOffset;
    }
    (digest_ba[offset] & 0x7f) << 24 | (digest_ba[offset+1] & 0xff) << 16 | (digest_ba[offset+2] & 0xff) << 8 | (digest_ba[offset+3] & 0xff)
}

def getOtp(key, counter, codeDigits, addChecksum, truncationOffset) {
                   // 0 1  2   3    4     5      6       7        8
    DIGITS_POWER = [1,10,100,1000,10000,100000,1000000,10000000,100000000];
    digest_ba = hmac_sha1(key.getBytes(), getMovingFactor(counter));
    println "Digest: ${baToHex(digest_ba)}"
    snum = truncate(digest_ba, truncationOffset)
    println "Decimal ${snum}"
    otp = snum % DIGITS_POWER[codeDigits]
    (addChecksum) ? (otp * 10) + calcChecksum(otp, codeDigits) : otp
}

key = "12345678901234567890"
counter = 1
codeDigits = 6
truncationOffset = -1
println "HOTP: ${getOtp(key, counter, codeDigits, false, truncationOffset)}"