taler-xotp_fw

xOTP generator firmware
Log | Files | Refs | Submodules | README

xtotpCryptoHandler.c (5398B)


      1 /**
      2  * @file xtotpCryptoHandler.c
      3  * @author Adrian STEINER (steia19@bfh.ch)
      4  * @brief Handler the (x)TOTP crypto data and generates the current codes
      5  * @version 0.1
      6  * @date 03-08-2025
      7  *
      8  * @copyright (C) 2025 Adrian STEINER
      9  * This program is free software: you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation, either version 3 of the License, or
     12  * (at your option) any later version.
     13  *
     14  * This program is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  * GNU General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU General Public License
     20  * along with this program.  If not, see <https: //www.gnu.org/licenses/>.
     21  *
     22  */
     23 #include "xtotpCryptoHandler.h"
     24 
     25 #include <stdlib.h>
     26 #include <string.h>
     27 
     28 #include "base32_converter.h"
     29 #include "base8_converter.h"
     30 
     31 /**
     32  * @brief Saves the algorithm names
     33  * To save storage, the algorithms for base TOTP are not stored.
     34  * THey use the same index as for the xTOTP and begin the string without the x
     35  *
     36  */
     37 const char *algNames[] = {
     38     [ALG_NONE] = "Not defined", [ALG_TOTP_SHA1] = "xTOTP-SHA1"};
     39 
     40 crypto_algoInfo crypto_getAlgoInfo(xtotpAlgoSettingsType *algoSettings)
     41 {
     42   if (NULL == algoSettings || ALG_NONE == algoSettings->algorithm) {
     43     return ALGO_UNINITIALIZED;
     44   }
     45   if (algoSettings->algorithm > ALG_CHANGE_VALUE &&
     46       algoSettings->algorithm < ALG_MAX_XTOTP_ALGORITHM) {
     47     return ALGO_XTOTP;
     48   } else if (algoSettings->algorithm > ALG_NONE &&
     49              algoSettings->algorithm < ALG_MAX_TOTP_ALGORITHM) {
     50     return ALGO_TOTP;
     51   } else {
     52     return ALGO_UNINITIALIZED;
     53   }
     54 }
     55 
     56 const char *crypto_getAlgoName(xtotpAlgoSettingsType *algoSettings)
     57 {
     58   if (NULL == algoSettings) {
     59     return NULL;
     60   }
     61   switch (crypto_getAlgoInfo(algoSettings)) {
     62   case ALGO_UNINITIALIZED:
     63     break;
     64   case ALGO_TOTP:
     65     if (algoSettings->algorithm < XTOTP_ARRAY_SIZE(algNames)) {
     66       return (algNames[algoSettings->algorithm] + 1);
     67     }
     68     break;
     69   case ALGO_XTOTP:
     70     if ((algoSettings->algorithm & 0x0F) < XTOTP_ARRAY_SIZE(algNames)) {
     71       return algNames[(algoSettings->algorithm & 0x0F)];
     72     }
     73     break;
     74   default:
     75     break;
     76   }
     77   return algNames[ALG_NONE];
     78 }
     79 
     80 crypto_algoInfo crypto_initAlgoSettings(xtotpAlgoSettingsType *algoSettings,
     81                                         const uint8_t *secret,
     82                                         uint8_t secretLen,
     83                                         crypto_secretBase secretBase,
     84                                         uint8_t interval,
     85                                         uint8_t passcodeDigits,
     86                                         crypto_algorithms algorithm,
     87                                         const uint8_t *currency,
     88                                         uint32_t fraction,
     89                                         const uint8_t *merchantTemplate)
     90 {
     91   if (NULL == algoSettings || ALG_NONE == algorithm) {
     92     return ALGO_UNINITIALIZED;
     93   }
     94   algoSettings->algorithm = ALG_NONE;
     95   if (NULL == secret || 0 == secretLen) {
     96     return ALGO_UNINITIALIZED;
     97   }
     98   switch (secretBase) {
     99   case SECRET_BASE_BYTE:
    100     if (TALER_SECRET_LEN < secretLen) {
    101       return ALGO_UNINITIALIZED;
    102     } else {
    103       memcpy(algoSettings->secret, secret, secretLen);
    104       algoSettings->secretLen = secretLen;
    105     }
    106     break;
    107   case SECRET_BASE_8:
    108     if (base8_decodeNum(algoSettings->secret,
    109                         (uint32_t *)&algoSettings->secretLen, TALER_SECRET_LEN,
    110                         secret, secretLen) != BASEX_OK) {
    111       return ALGO_UNINITIALIZED;
    112     }
    113     break;
    114   case SECRET_BASE_32:
    115     if (base32_decodeString(
    116             algoSettings->secret, (uint32_t *)&algoSettings->secretLen,
    117             TALER_SECRET_LEN, (const char *)secret) != BASEX_OK) {
    118       return ALGO_UNINITIALIZED;
    119     }
    120     break;
    121   default:
    122     return ALGO_UNINITIALIZED;
    123     break;
    124   }
    125   algoSettings->digits = (passcodeDigits < MAX_PASSCODE_LENGTH_DIGITS)
    126                              ? passcodeDigits
    127                              : MAX_PASSCODE_LENGTH_DIGITS;
    128   algoSettings->interval = interval;
    129 
    130   // Check if the currency must be copied
    131   if (algorithm > ALG_CHANGE_VALUE && algorithm < ALG_MAX_XTOTP_ALGORITHM) {
    132     if (currency) {
    133       TALER_xDataInit(&algoSettings->xTalerData, currency, fraction,
    134                       merchantTemplate);
    135       algoSettings->algorithm = algorithm;
    136       return ALGO_XTOTP;
    137     } else {
    138       return ALGO_UNINITIALIZED;
    139     }
    140   } else if (algorithm < ALG_MAX_TOTP_ALGORITHM) {
    141     algoSettings->algorithm = algorithm;
    142     return ALGO_TOTP;
    143   } else {
    144     return ALGO_UNINITIALIZED;
    145   }
    146 }
    147 
    148 void crypto_setMerchantData(xtotpCryptoHandler *cryptoHandler,
    149                             const char *deviceID,
    150                             const char *merchantBackend)
    151 {
    152   if (NULL == cryptoHandler) {
    153     return;
    154   }
    155   if (deviceID) {
    156     strncpy(cryptoHandler->deviceID, deviceID, XTOTP_DEVICE_ID_SIZE);
    157   }
    158   if (merchantBackend) {
    159     strncpy(cryptoHandler->merchandBackend, merchantBackend,
    160             XTOTP_MERCHANT_BACKEND_SIZE);
    161   }
    162 }
    163 
    164 xtotpAlgoSettingsType *
    165 crypto_getCurrentAlgorithm(xtotpCryptoHandler *cryptoHandler)
    166 {
    167   return &cryptoHandler->algorithms[cryptoHandler->usedAlgorithm];
    168 }