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 }