+++ /dev/null
-MIT License
-
-Copyright (c) 2019 Weravech
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+++ /dev/null
-TOTP Pure C Library for ALL MCU
-====================
-
-Library to generate Time-based One-Time Passwords.
-
-Implements the Time-based One-Time Password algorithm specified in [RFC 6238](https://tools.ietf.org/html/rfc6238).
-Supports different time steps and is compatible with tokens that use the same standard (including software ones, like the Google Authenticator app).
-
-Tested on MCUs: MSP430, RP2040
-
-Installation & usage:
---------------------
-First include header to your file
-```
-#include <totp.h>
-```
-After included, define key ex. Key is ```MyLegoDoor```
-- Note: The format of hmacKey is array of hexadecimal bytes.
-- Most websites provide the key encoded in base32 - RFC3548/RFC4648, either upper or lower case. You can use [this site](https://cryptii.com/pipes/base32-to-hex) to convert the base32 string to hex (make sure you upcase it first if it's lowercase and remove all whitespaces).
-```
-uint8_t hmacKey[] = {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72}; // Secret key
-```
-Instantiate the TOTP class by providing the secret hmacKey, the length of the hmacKey and the Timestep between codes.
-```
-TOTP(hmacKey, 10, 30); // Secret key, Secret key length, Timestep (30s)
-```
-Use the ```getCodeFromTimestamp()``` function to get a TOTP from a unix epoch timestamp
-```
-uint32_t newCode = getCodeFromTimestamp(1557414000); // Current timestamp since Unix epoch in seconds
-```
-Or ```getCodeFromTimeStruct()``` if you want to get a TOTP from a tm struct (Time Struct in C),
-```
-struct tm datetime;
-datetime.tm_hour = 9;
-datetime.tm_min = 0;
-datetime.tm_sec = 0;
-datetime.tm_mday = 13;
-datetime.tm_mon = 5;
-datetime.tm_year = 2019;
-uint32_t newCode = getCodeFromTimeStruct(datetime);
-```
-
-If the provided unix timestamp isn't in UTC±0, use ```setTimezone()``` before ```getCodeFromTimestamp()``` or ```getCodeFromTimeStruct()``` to offset the time.
-
-```
-setTimezone(9); // Set timezone +9 Japan
-```
-
-You can see an example in blink.c
-
-Thanks to:
-----------
-
-* Jose Damico, https://github.com/damico/ARDUINO-OATH-TOKEN
-* Peter Knight, https://github.com/Cathedrow/Cryptosuite
-* Maniacbug, https://github.com/maniacbug/Cryptosuite
-* lucadentella, https://github.com/lucadentella/TOTP-Arduino
+++ /dev/null
-#include "TOTP.h"\r
-#include "sha1.h"\r
-\r
-uint8_t* _hmacKey;\r
-uint8_t _keyLength;\r
-uint8_t _timeZoneOffset;\r
-uint32_t _timeStep;\r
-\r
-// Init the library with the private key, its length and the timeStep duration\r
-void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep) {\r
- _hmacKey = hmacKey;\r
- _keyLength = keyLength;\r
- _timeStep = timeStep;\r
-}\r
-\r
-void setTimezone(uint8_t timezone){\r
- _timeZoneOffset = timezone;\r
-}\r
-\r
-static uint32_t TimeStruct2Timestamp(struct tm time){\r
- //time.tm_mon -= 1;\r
- //time.tm_year -= 1900;\r
- return mktime(&(time)) - (_timeZoneOffset * 3600) - 2208988800;\r
-}\r
-\r
-// Generate a code, using the timestamp provided\r
-uint32_t getCodeFromTimestamp(uint32_t timeStamp) {\r
- uint32_t steps = timeStamp / _timeStep;\r
- return getCodeFromSteps(steps);\r
-}\r
-\r
-// Generate a code, using the timestamp provided\r
-uint32_t getCodeFromTimeStruct(struct tm time) {\r
- return getCodeFromTimestamp(TimeStruct2Timestamp(time));\r
-}\r
-\r
-// Generate a code, using the number of steps provided\r
-uint32_t getCodeFromSteps(uint32_t steps) {\r
- // STEP 0, map the number of steps in a 8-bytes array (counter value)\r
- uint8_t _byteArray[8];\r
- _byteArray[0] = 0x00;\r
- _byteArray[1] = 0x00;\r
- _byteArray[2] = 0x00;\r
- _byteArray[3] = 0x00;\r
- _byteArray[4] = (uint8_t)((steps >> 24) & 0xFF);\r
- _byteArray[5] = (uint8_t)((steps >> 16) & 0xFF);\r
- _byteArray[6] = (uint8_t)((steps >> 8) & 0XFF);\r
- _byteArray[7] = (uint8_t)((steps & 0XFF));\r
-\r
- // STEP 1, get the HMAC-SHA1 hash from counter and key\r
- initHmac(_hmacKey, _keyLength);\r
- writeArray(_byteArray, 8);\r
- uint8_t* _hash = resultHmac();\r
-\r
- // STEP 2, apply dynamic truncation to obtain a 4-bytes string\r
- uint32_t _truncatedHash = 0;\r
- uint8_t _offset = _hash[20 - 1] & 0xF;\r
- uint8_t j;\r
- for (j = 0; j < 4; ++j) {\r
- _truncatedHash <<= 8;\r
- _truncatedHash |= _hash[_offset + j];\r
- }\r
-\r
- // STEP 3, compute the OTP value\r
- _truncatedHash &= 0x7FFFFFFF; //Disabled\r
- _truncatedHash %= 1000000;\r
-\r
- return _truncatedHash;\r
-}\r
+++ /dev/null
-#ifndef TOTP_H_\r
-#define TOTP_H_\r
-\r
-#include <inttypes.h>\r
-#include "time.h"\r
-\r
-void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep);\r
-void setTimezone(uint8_t timezone);\r
-uint32_t getCodeFromTimestamp(uint32_t timeStamp);\r
-uint32_t getCodeFromTimeStruct(struct tm time);\r
-uint32_t getCodeFromSteps(uint32_t steps);\r
-\r
-#endif // TOTP_H_\r
+++ /dev/null
-#include <msp430.h> \r
-#include <totp.h>\r
-#include <stdint.h>\r
-\r
-/**\r
- * blink.c\r
- */\r
-void main(void)\r
-{\r
- WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer\r
- P1DIR |= 0x01; // configure P1.0 as output\r
-\r
- uint8_t hmacKey[] = {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72}; // Secret key\r
- TOTP(hmacKey, 10, 7200); // Secret key, Key length, Timestep (7200s - 2hours)\r
-\r
- setTimezone(9); // Set timezone\r
- uint32_t newCode = getCodeFromTimestamp(1557414000); // Timestamp Now\r
-\r
- ///////////////// For struct tm //////////////////\r
- // struct tm datetime;\r
- // datetime.tm_hour = 9;\r
- // datetime.tm_min = 0;\r
- // datetime.tm_sec = 0;\r
- // datetime.tm_mday = 13;\r
- // datetime.tm_mon = 5;\r
- // datetime.tm_year = 2019;\r
- // uint32_t newCode = getCodeFromTimeStruct(datetime);\r
- ///////////////////////////////////////////////////\r
-\r
- volatile unsigned int i; // volatile to prevent optimization\r
-\r
- while(1)\r
- {\r
- if (newCode == 0){ // 0 = INPUT HERE\r
- P1OUT ^= 0x01; // toggle P1.0\r
- }\r
- for(i=10000; i>0; i--); // delay\r
- }\r
-}\r
+++ /dev/null
-#include <string.h>\r
-#include "sha1.h"\r
-\r
-#define SHA1_K0 0x5a827999\r
-#define SHA1_K20 0x6ed9eba1\r
-#define SHA1_K40 0x8f1bbcdc\r
-#define SHA1_K60 0xca62c1d6\r
-\r
-uint8_t sha1InitState[] = {\r
- 0x01,0x23,0x45,0x67, // H0\r
- 0x89,0xab,0xcd,0xef, // H1\r
- 0xfe,0xdc,0xba,0x98, // H2\r
- 0x76,0x54,0x32,0x10, // H3\r
- 0xf0,0xe1,0xd2,0xc3 // H4\r
-};\r
-\r
-union _buffer {\r
- uint8_t b[BLOCK_LENGTH];\r
- uint32_t w[BLOCK_LENGTH/4];\r
-} buffer;\r
-union _state {\r
- uint8_t b[HASH_LENGTH];\r
- uint32_t w[HASH_LENGTH/4];\r
-} state;\r
-\r
-uint8_t bufferOffset;\r
-uint32_t byteCount;\r
-uint8_t keyBuffer[BLOCK_LENGTH];\r
-uint8_t innerHash[HASH_LENGTH];\r
-\r
-void init(void) {\r
- memcpy(state.b,sha1InitState,HASH_LENGTH);\r
- byteCount = 0;\r
- bufferOffset = 0;\r
-}\r
-\r
-static uint32_t rol32(uint32_t number, uint8_t bits) {\r
- return ((number << bits) | (uint32_t)(number >> (32-bits)));\r
-}\r
-\r
-static void hashBlock(void) {\r
- uint8_t i;\r
- uint32_t a,b,c,d,e,t;\r
-\r
- a=state.w[0];\r
- b=state.w[1];\r
- c=state.w[2];\r
- d=state.w[3];\r
- e=state.w[4];\r
- for (i=0; i<80; i++) {\r
- if (i>=16) {\r
- t = buffer.w[(i+13)&15] ^ buffer.w[(i+8)&15] ^ buffer.w[(i+2)&15] ^ buffer.w[i&15];\r
- buffer.w[i&15] = rol32(t,1);\r
- }\r
- if (i<20) {\r
- t = (d ^ (b & (c ^ d))) + SHA1_K0;\r
- } else if (i<40) {\r
- t = (b ^ c ^ d) + SHA1_K20;\r
- } else if (i<60) {\r
- t = ((b & c) | (d & (b | c))) + SHA1_K40;\r
- } else {\r
- t = (b ^ c ^ d) + SHA1_K60;\r
- }\r
- t+=rol32(a,5) + e + buffer.w[i&15];\r
- e=d;\r
- d=c;\r
- c=rol32(b,30);\r
- b=a;\r
- a=t;\r
- }\r
- state.w[0] += a;\r
- state.w[1] += b;\r
- state.w[2] += c;\r
- state.w[3] += d;\r
- state.w[4] += e;\r
-}\r
-\r
-static void addUncounted(uint8_t data) {\r
- buffer.b[bufferOffset ^ 3] = data;\r
- bufferOffset++;\r
- if (bufferOffset == BLOCK_LENGTH) {\r
- hashBlock();\r
- bufferOffset = 0;\r
- }\r
-}\r
-\r
-static void __write(uint8_t data) {\r
- ++byteCount;\r
- addUncounted(data);\r
-\r
- return;\r
-}\r
-\r
-void writeArray(uint8_t *buffer, uint8_t size){\r
- while (size--) {\r
- __write(*buffer++);\r
- }\r
-}\r
-\r
-static void pad(void) {\r
- // Implement SHA-1 padding (fips180-2 ��5.1.1)\r
-\r
- // Pad with 0x80 followed by 0x00 until the end of the block\r
- addUncounted(0x80);\r
- while (bufferOffset != 56) addUncounted(0x00);\r
-\r
- // Append length in the last 8 bytes\r
- addUncounted(0); // We're only using 32 bit lengths\r
- addUncounted(0); // But SHA-1 supports 64 bit lengths\r
- addUncounted(0); // So zero pad the top bits\r
- addUncounted(byteCount >> 29); // Shifting to multiply by 8\r
- addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as\r
- addUncounted(byteCount >> 13); // byte.\r
- addUncounted(byteCount >> 5);\r
- addUncounted(byteCount << 3);\r
-}\r
-\r
-uint8_t* result(void) {\r
- // Pad to complete the last block\r
- pad();\r
-\r
- // Swap byte order back\r
- uint8_t i;\r
- for (i=0; i<5; i++) {\r
- uint32_t a,b;\r
- a=state.w[i];\r
- b=a<<24;\r
- b|=(a<<8) & 0x00ff0000;\r
- b|=(a>>8) & 0x0000ff00;\r
- b|=a>>24;\r
- state.w[i]=b;\r
- }\r
-\r
- // Return pointer to hash (20 characters)\r
- return state.b;\r
-}\r
-\r
-#define HMAC_IPAD 0x36\r
-#define HMAC_OPAD 0x5c\r
-\r
-void initHmac(const uint8_t* key, uint8_t keyLength) {\r
- uint8_t i;\r
- memset(keyBuffer,0,BLOCK_LENGTH);\r
- if (keyLength > BLOCK_LENGTH) {\r
- // Hash long keys\r
- init();\r
- for (;keyLength--;) __write(*key++);\r
- memcpy(keyBuffer,result(),HASH_LENGTH);\r
- } else {\r
- // Block length keys are used as is\r
- memcpy(keyBuffer,key,keyLength);\r
- }\r
- // Start inner hash\r
- init();\r
- for (i=0; i<BLOCK_LENGTH; i++) {\r
- __write(keyBuffer[i] ^ HMAC_IPAD);\r
- }\r
-}\r
-\r
-uint8_t* resultHmac(void) {\r
- uint8_t i;\r
- // Complete inner hash\r
- memcpy(innerHash,result(),HASH_LENGTH);\r
- // Calculate outer hash\r
- init();\r
- for (i=0; i<BLOCK_LENGTH; i++) __write(keyBuffer[i] ^ HMAC_OPAD);\r
- for (i=0; i<HASH_LENGTH; i++) __write(innerHash[i]);\r
- return result();\r
-}\r
+++ /dev/null
-#ifndef SHA1_H_\r
-#define SHA1_H_\r
-\r
-#include <inttypes.h>\r
-\r
-#define HASH_LENGTH 20\r
-#define BLOCK_LENGTH 64\r
-\r
-void init(void);\r
-void initHmac(const uint8_t* secret, uint8_t secretLength);\r
-uint8_t* result(void);\r
-uint8_t* resultHmac(void);\r
-void writeArray(uint8_t *buffer, uint8_t size);\r
-\r
-#endif // SHA1_H\r
--- /dev/null
+MIT License
+
+Copyright (c) 2019 Weravech
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+TOTP Pure C Library
+====================
+
+Library to generate Time-based One-Time Passwords.
+
+Implements the Time-based One-Time Password algorithm specified in [RFC 6238](https://tools.ietf.org/html/rfc6238).
+
+Supports different time steps and is compatible with tokens that use the same standard (including software ones, like the Google Authenticator app).
+
+The code is made of :
+
+- [TOTP-MCU](https://github.com/Netthaw/TOTP-MCU) for `TimeStruct2Timestamp`, `getCodeFromTimestamp`, `getCodeFromTimeStruct`, part of `getCodeFromSteps` and `TOTP_HMAC_SHA*` functions
+- [mbedtls](https://github.com/Mbed-TLS/mbedtls) for SHA1/SHA224/SHA256/SHA384/SHA512 implementations
+- [this project](https://github.com/mygityf/cipher/blob/master/cipher/hmac.c) as an inspiration for writing the code to compute the TOTP using the key and the text to hash
+
+
+
+Supported algorithms are SHA1/SHA224/SHA256/SHA384/SHA512.
+
+
+
+Installation & usage:
+--------------------
+First include header to your file
+```c
+#include "TOTP.h"
+```
+After included, define key ex. Key is ```MyLegoDoor```
+- Note: The format of hmacKey is array of hexadecimal bytes.
+- Most websites provide the key encoded in base32 - RFC3548/RFC4648, either upper or lower case. You can use [this site](https://cryptii.com/pipes/base32-to-hex) to convert the base32 string to hex (make sure you upcase it first if it's lowercase and remove all whitespaces).
+```c
+uint8_t hmacKey[] = {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72}; // Secret key
+```
+Instantiate the TOTP class by providing the secret hmacKey, the length of the hmacKey, the Timestep between codes and the algorithm used (most of the time, `SHA1`).
+```c
+TOTP(hmacKey, 10, 30, SHA1); // Secret key, Secret key length, Timestep (30s), Algorithm
+```
+Use the ```getCodeFromTimestamp()``` function to get a TOTP from a unix epoch timestamp
+```c
+uint32_t newCode = getCodeFromTimestamp(1557414000); // Current timestamp since Unix epoch in seconds
+```
+Or ```getCodeFromTimeStruct()``` if you want to get a TOTP from a tm struct (Time Struct in C),
+```c
+struct tm datetime;
+datetime.tm_hour = 9;
+datetime.tm_min = 0;
+datetime.tm_sec = 0;
+datetime.tm_mday = 13;
+datetime.tm_mon = 5;
+datetime.tm_year = 2019;
+uint32_t newCode = getCodeFromTimeStruct(datetime);
+```
+
+If the provided unix timestamp isn't in UTC±0, use ```setTimezone()``` before ```getCodeFromTimestamp()``` or ```getCodeFromTimeStruct()``` to offset the time.
+
+```c
+setTimezone(9); // Set timezone +9 Japan
+```
+
+You can see an example in example.c (compile it with `gcc -o example example.c sha1.c sha256.c sha512.c TOTP.c -I.`)
+
+Thanks to:
+----------
+
+* Netthaw, https://github.com/Netthaw/TOTP-MCU
+* Mbed-TLS, https://github.com/Mbed-TLS/mbedtls
+* mygityf, https://github.com/mygityf/cipher/blob/master/cipher/hmac.c
+* susam, https://github.com/susam/mintotp
--- /dev/null
+#include "TOTP.h"\r
+#include "sha1.h"\r
+#include "sha256.h"\r
+#include "sha512.h"\r
+#include <stdio.h>\r
+\r
+uint8_t* _hmacKey;\r
+uint8_t _keyLength;\r
+uint8_t _timeZoneOffset;\r
+uint32_t _timeStep;\r
+hmac_alg _algorithm;\r
+\r
+// Init the library with the private key, its length, the timeStep duration and the algorithm that should be used\r
+void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep, hmac_alg algorithm) {\r
+ _hmacKey = hmacKey;\r
+ _keyLength = keyLength;\r
+ _timeStep = timeStep;\r
+ _algorithm = algorithm;\r
+}\r
+\r
+void setTimezone(uint8_t timezone){\r
+ _timeZoneOffset = timezone;\r
+}\r
+\r
+static uint32_t TimeStruct2Timestamp(struct tm time){\r
+ //time.tm_mon -= 1;\r
+ //time.tm_year -= 1900;\r
+ return mktime(&(time)) - (_timeZoneOffset * 3600) - 2208988800;\r
+}\r
+\r
+// Generate a code, using the timestamp provided\r
+uint32_t getCodeFromTimestamp(uint32_t timeStamp) {\r
+ uint32_t steps = timeStamp / _timeStep;\r
+ return getCodeFromSteps(steps);\r
+}\r
+\r
+// Generate a code, using the timestamp provided\r
+uint32_t getCodeFromTimeStruct(struct tm time) {\r
+ return getCodeFromTimestamp(TimeStruct2Timestamp(time));\r
+}\r
+\r
+// Generate a code, using the number of steps provided\r
+uint32_t getCodeFromSteps(uint32_t steps) {\r
+ // STEP 0, map the number of steps in a 8-bytes array (counter value)\r
+ uint8_t _byteArray[8];\r
+ _byteArray[0] = 0x00;\r
+ _byteArray[1] = 0x00;\r
+ _byteArray[2] = 0x00;\r
+ _byteArray[3] = 0x00;\r
+ _byteArray[4] = (uint8_t)((steps >> 24) & 0xFF);\r
+ _byteArray[5] = (uint8_t)((steps >> 16) & 0xFF);\r
+ _byteArray[6] = (uint8_t)((steps >> 8) & 0XFF);\r
+ _byteArray[7] = (uint8_t)((steps & 0XFF));\r
+\r
+ switch(_algorithm){\r
+ case SHA1:\r
+ return(TOTP_HMAC_SHA1(_hmacKey, _keyLength, _byteArray, 8));\r
+ case SHA224:\r
+ return(TOTP_HMAC_SHA256(_hmacKey, _keyLength, _byteArray, 8, 1));\r
+ case SHA256:\r
+ return(TOTP_HMAC_SHA256(_hmacKey, _keyLength, _byteArray, 8, 0));\r
+ case SHA384:\r
+ return(TOTP_HMAC_SHA512(_hmacKey, _keyLength, _byteArray, 8, 1));\r
+ case SHA512:\r
+ return(TOTP_HMAC_SHA512(_hmacKey, _keyLength, _byteArray, 8, 0));\r
+ default:\r
+ return(0);\r
+ }\r
+}\r
--- /dev/null
+#ifndef TOTP_H_\r
+#define TOTP_H_\r
+\r
+#include <inttypes.h>\r
+#include "time.h"\r
+\r
+typedef enum {\r
+ SHA1,\r
+ SHA224,\r
+ SHA256,\r
+ SHA384,\r
+ SHA512\r
+} hmac_alg;\r
+\r
+void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep, hmac_alg algorithm);\r
+void setTimezone(uint8_t timezone);\r
+uint32_t getCodeFromTimestamp(uint32_t timeStamp);\r
+uint32_t getCodeFromTimeStruct(struct tm time);\r
+uint32_t getCodeFromSteps(uint32_t steps);\r
+\r
+#endif // TOTP_H_\r
--- /dev/null
+#include "TOTP.h"\r
+#include <stdio.h>\r
+\r
+/**\r
+ * example.c\r
+ */\r
+void main(void)\r
+{\r
+ uint8_t hmacKey[] = {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72}; // Secret key\r
+ TOTP(hmacKey, 10, 7200, SHA1); // Secret key, Key length, Timestep (7200s - 2hours)\r
+\r
+ setTimezone(9); // Set timezone\r
+ uint32_t newCode = getCodeFromTimestamp(1557414000); // Timestamp Now\r
+\r
+ ///////////////// For struct tm //////////////////\r
+ // struct tm datetime;\r
+ // datetime.tm_hour = 9;\r
+ // datetime.tm_min = 0;\r
+ // datetime.tm_sec = 0;\r
+ // datetime.tm_mday = 13;\r
+ // datetime.tm_mon = 5;\r
+ // datetime.tm_year = 2019;\r
+ // uint32_t newCode = getCodeFromTimeStruct(datetime);\r
+ ///////////////////////////////////////////////////\r
+\r
+ printf("Code : %06u\n",newCode);\r
+}\r
--- /dev/null
+/*\r
+ * FIPS-180-1 compliant SHA-1 implementation\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+/*\r
+ * The SHA-1 standard was published by NIST in 1993.\r
+ *\r
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm\r
+ */\r
+\r
+#include "sha1.h"\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+/* Implementation that should never be optimized out by the compiler */\r
+static void mbedtls_zeroize( void *v, size_t n ) {\r
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;\r
+}\r
+\r
+/*\r
+ * 32-bit integer manipulation macros (big endian)\r
+ */\r
+#ifndef GET_UINT32_BE\r
+#define GET_UINT32_BE(n,b,i) \\r
+{ \\r
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \\r
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \\r
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \\r
+ | ( (uint32_t) (b)[(i) + 3] ); \\r
+}\r
+#endif\r
+\r
+#ifndef PUT_UINT32_BE\r
+#define PUT_UINT32_BE(n,b,i) \\r
+{ \\r
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \\r
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \\r
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \\r
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \\r
+}\r
+#endif\r
+\r
+void mbedtls_sha1_init( mbedtls_sha1_context *ctx )\r
+{\r
+ memset( ctx, 0, sizeof( mbedtls_sha1_context ) );\r
+}\r
+\r
+void mbedtls_sha1_free( mbedtls_sha1_context *ctx )\r
+{\r
+ if( ctx == NULL )\r
+ return;\r
+\r
+ mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );\r
+}\r
+\r
+/*\r
+ * SHA-1 context setup\r
+ */\r
+void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )\r
+{\r
+ ctx->total[0] = 0;\r
+ ctx->total[1] = 0;\r
+\r
+ ctx->state[0] = 0x67452301;\r
+ ctx->state[1] = 0xEFCDAB89;\r
+ ctx->state[2] = 0x98BADCFE;\r
+ ctx->state[3] = 0x10325476;\r
+ ctx->state[4] = 0xC3D2E1F0;\r
+}\r
+\r
+void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[SHA1_BLOCK_LENGTH] )\r
+{\r
+ uint32_t temp, W[16], A, B, C, D, E;\r
+\r
+ GET_UINT32_BE( W[ 0], data, 0 );\r
+ GET_UINT32_BE( W[ 1], data, 4 );\r
+ GET_UINT32_BE( W[ 2], data, 8 );\r
+ GET_UINT32_BE( W[ 3], data, 12 );\r
+ GET_UINT32_BE( W[ 4], data, 16 );\r
+ GET_UINT32_BE( W[ 5], data, 20 );\r
+ GET_UINT32_BE( W[ 6], data, 24 );\r
+ GET_UINT32_BE( W[ 7], data, 28 );\r
+ GET_UINT32_BE( W[ 8], data, 32 );\r
+ GET_UINT32_BE( W[ 9], data, 36 );\r
+ GET_UINT32_BE( W[10], data, 40 );\r
+ GET_UINT32_BE( W[11], data, 44 );\r
+ GET_UINT32_BE( W[12], data, 48 );\r
+ GET_UINT32_BE( W[13], data, 52 );\r
+ GET_UINT32_BE( W[14], data, 56 );\r
+ GET_UINT32_BE( W[15], data, 60 );\r
+\r
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\r
+\r
+#define R(t) \\r
+( \\r
+ temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \\r
+ W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \\r
+ ( W[t & 0x0F] = S(temp,1) ) \\r
+)\r
+\r
+#define P(a,b,c,d,e,x) \\r
+{ \\r
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \\r
+}\r
+\r
+ A = ctx->state[0];\r
+ B = ctx->state[1];\r
+ C = ctx->state[2];\r
+ D = ctx->state[3];\r
+ E = ctx->state[4];\r
+\r
+#define F(x,y,z) (z ^ (x & (y ^ z)))\r
+#define K 0x5A827999\r
+\r
+ P( A, B, C, D, E, W[0] );\r
+ P( E, A, B, C, D, W[1] );\r
+ P( D, E, A, B, C, W[2] );\r
+ P( C, D, E, A, B, W[3] );\r
+ P( B, C, D, E, A, W[4] );\r
+ P( A, B, C, D, E, W[5] );\r
+ P( E, A, B, C, D, W[6] );\r
+ P( D, E, A, B, C, W[7] );\r
+ P( C, D, E, A, B, W[8] );\r
+ P( B, C, D, E, A, W[9] );\r
+ P( A, B, C, D, E, W[10] );\r
+ P( E, A, B, C, D, W[11] );\r
+ P( D, E, A, B, C, W[12] );\r
+ P( C, D, E, A, B, W[13] );\r
+ P( B, C, D, E, A, W[14] );\r
+ P( A, B, C, D, E, W[15] );\r
+ P( E, A, B, C, D, R(16) );\r
+ P( D, E, A, B, C, R(17) );\r
+ P( C, D, E, A, B, R(18) );\r
+ P( B, C, D, E, A, R(19) );\r
+\r
+#undef K\r
+#undef F\r
+\r
+#define F(x,y,z) (x ^ y ^ z)\r
+#define K 0x6ED9EBA1\r
+\r
+ P( A, B, C, D, E, R(20) );\r
+ P( E, A, B, C, D, R(21) );\r
+ P( D, E, A, B, C, R(22) );\r
+ P( C, D, E, A, B, R(23) );\r
+ P( B, C, D, E, A, R(24) );\r
+ P( A, B, C, D, E, R(25) );\r
+ P( E, A, B, C, D, R(26) );\r
+ P( D, E, A, B, C, R(27) );\r
+ P( C, D, E, A, B, R(28) );\r
+ P( B, C, D, E, A, R(29) );\r
+ P( A, B, C, D, E, R(30) );\r
+ P( E, A, B, C, D, R(31) );\r
+ P( D, E, A, B, C, R(32) );\r
+ P( C, D, E, A, B, R(33) );\r
+ P( B, C, D, E, A, R(34) );\r
+ P( A, B, C, D, E, R(35) );\r
+ P( E, A, B, C, D, R(36) );\r
+ P( D, E, A, B, C, R(37) );\r
+ P( C, D, E, A, B, R(38) );\r
+ P( B, C, D, E, A, R(39) );\r
+\r
+#undef K\r
+#undef F\r
+\r
+#define F(x,y,z) ((x & y) | (z & (x | y)))\r
+#define K 0x8F1BBCDC\r
+\r
+ P( A, B, C, D, E, R(40) );\r
+ P( E, A, B, C, D, R(41) );\r
+ P( D, E, A, B, C, R(42) );\r
+ P( C, D, E, A, B, R(43) );\r
+ P( B, C, D, E, A, R(44) );\r
+ P( A, B, C, D, E, R(45) );\r
+ P( E, A, B, C, D, R(46) );\r
+ P( D, E, A, B, C, R(47) );\r
+ P( C, D, E, A, B, R(48) );\r
+ P( B, C, D, E, A, R(49) );\r
+ P( A, B, C, D, E, R(50) );\r
+ P( E, A, B, C, D, R(51) );\r
+ P( D, E, A, B, C, R(52) );\r
+ P( C, D, E, A, B, R(53) );\r
+ P( B, C, D, E, A, R(54) );\r
+ P( A, B, C, D, E, R(55) );\r
+ P( E, A, B, C, D, R(56) );\r
+ P( D, E, A, B, C, R(57) );\r
+ P( C, D, E, A, B, R(58) );\r
+ P( B, C, D, E, A, R(59) );\r
+\r
+#undef K\r
+#undef F\r
+\r
+#define F(x,y,z) (x ^ y ^ z)\r
+#define K 0xCA62C1D6\r
+\r
+ P( A, B, C, D, E, R(60) );\r
+ P( E, A, B, C, D, R(61) );\r
+ P( D, E, A, B, C, R(62) );\r
+ P( C, D, E, A, B, R(63) );\r
+ P( B, C, D, E, A, R(64) );\r
+ P( A, B, C, D, E, R(65) );\r
+ P( E, A, B, C, D, R(66) );\r
+ P( D, E, A, B, C, R(67) );\r
+ P( C, D, E, A, B, R(68) );\r
+ P( B, C, D, E, A, R(69) );\r
+ P( A, B, C, D, E, R(70) );\r
+ P( E, A, B, C, D, R(71) );\r
+ P( D, E, A, B, C, R(72) );\r
+ P( C, D, E, A, B, R(73) );\r
+ P( B, C, D, E, A, R(74) );\r
+ P( A, B, C, D, E, R(75) );\r
+ P( E, A, B, C, D, R(76) );\r
+ P( D, E, A, B, C, R(77) );\r
+ P( C, D, E, A, B, R(78) );\r
+ P( B, C, D, E, A, R(79) );\r
+\r
+#undef K\r
+#undef F\r
+\r
+ ctx->state[0] += A;\r
+ ctx->state[1] += B;\r
+ ctx->state[2] += C;\r
+ ctx->state[3] += D;\r
+ ctx->state[4] += E;\r
+}\r
+\r
+/*\r
+ * SHA-1 process buffer\r
+ */\r
+void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )\r
+{\r
+ size_t fill;\r
+ uint32_t left;\r
+\r
+ if( ilen == 0 )\r
+ return;\r
+\r
+ left = ctx->total[0] & 0x3F;\r
+ fill = 64 - left;\r
+\r
+ ctx->total[0] += (uint32_t) ilen;\r
+ ctx->total[0] &= 0xFFFFFFFF;\r
+\r
+ if( ctx->total[0] < (uint32_t) ilen )\r
+ ctx->total[1]++;\r
+\r
+ if( left && ilen >= fill )\r
+ {\r
+ memcpy( (void *) (ctx->buffer + left), input, fill );\r
+ mbedtls_sha1_process( ctx, ctx->buffer );\r
+ input += fill;\r
+ ilen -= fill;\r
+ left = 0;\r
+ }\r
+\r
+ while( ilen >= 64 )\r
+ {\r
+ mbedtls_sha1_process( ctx, input );\r
+ input += 64;\r
+ ilen -= 64;\r
+ }\r
+\r
+ if( ilen > 0 )\r
+ memcpy( (void *) (ctx->buffer + left), input, ilen );\r
+}\r
+\r
+static const unsigned char sha1_padding[SHA1_BLOCK_LENGTH] =\r
+{\r
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+/*\r
+ * SHA-1 final digest\r
+ */\r
+void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[SHA1_DIGEST_LENGTH] )\r
+{\r
+ uint32_t last, padn;\r
+ uint32_t high, low;\r
+ unsigned char msglen[8];\r
+\r
+ high = ( ctx->total[0] >> 29 )\r
+ | ( ctx->total[1] << 3 );\r
+ low = ( ctx->total[0] << 3 );\r
+\r
+ PUT_UINT32_BE( high, msglen, 0 );\r
+ PUT_UINT32_BE( low, msglen, 4 );\r
+\r
+ last = ctx->total[0] & 0x3F;\r
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\r
+\r
+ mbedtls_sha1_update( ctx, sha1_padding, padn );\r
+ mbedtls_sha1_update( ctx, msglen, 8 );\r
+\r
+ PUT_UINT32_BE( ctx->state[0], output, 0 );\r
+ PUT_UINT32_BE( ctx->state[1], output, 4 );\r
+ PUT_UINT32_BE( ctx->state[2], output, 8 );\r
+ PUT_UINT32_BE( ctx->state[3], output, 12 );\r
+ PUT_UINT32_BE( ctx->state[4], output, 16 );\r
+}\r
+\r
+/*\r
+ * output = SHA-1( input buffer )\r
+ */\r
+void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[SHA1_DIGEST_LENGTH] )\r
+{\r
+ mbedtls_sha1_context ctx;\r
+\r
+ mbedtls_sha1_init( &ctx );\r
+ mbedtls_sha1_starts( &ctx );\r
+ mbedtls_sha1_update( &ctx, input, ilen );\r
+ mbedtls_sha1_finish( &ctx, output );\r
+ mbedtls_sha1_free( &ctx );\r
+}\r
+\r
+/*\r
+* Compute HMAC_SHA1 using key, key length, text to hash, size of the text, and output buffer\r
+*/\r
+void HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t out[SHA1_DIGEST_LENGTH]){\r
+\r
+ uint8_t i;\r
+ uint8_t k_ipad[SHA1_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */\r
+ uint8_t k_opad[SHA1_BLOCK_LENGTH]; /* outer padding - key XORd with opad */\r
+ uint8_t buffer[SHA1_BLOCK_LENGTH + SHA1_DIGEST_LENGTH];\r
+\r
+ /* start out by storing key in pads */\r
+ memset(k_ipad, 0, sizeof(k_ipad));\r
+ memset(k_opad, 0, sizeof(k_opad));\r
+\r
+ if (key_length <= SHA1_BLOCK_LENGTH) {\r
+ memcpy(k_ipad, key, key_length);\r
+ memcpy(k_opad, key, key_length);\r
+ }\r
+\r
+ else {\r
+ mbedtls_sha1(key, key_length, k_ipad);\r
+ memcpy(k_opad, k_ipad, SHA1_BLOCK_LENGTH);\r
+ }\r
+\r
+ /* XOR key with ipad and opad values */\r
+ for (i = 0; i < SHA1_BLOCK_LENGTH; i++) {\r
+ k_ipad[i] ^= HMAC_IPAD;\r
+ k_opad[i] ^= HMAC_OPAD;\r
+ }\r
+ \r
+ // perform inner SHA1\r
+ memcpy(buffer, k_ipad, SHA1_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA1_BLOCK_LENGTH, in, n);\r
+ mbedtls_sha1(buffer, SHA1_BLOCK_LENGTH + n, out);\r
+ \r
+ memset(buffer, 0, SHA1_BLOCK_LENGTH + n);\r
+\r
+ // perform outer SHA1\r
+ memcpy(buffer, k_opad, SHA1_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA1_BLOCK_LENGTH, out, SHA1_DIGEST_LENGTH);\r
+ mbedtls_sha1(buffer, SHA1_BLOCK_LENGTH + SHA1_DIGEST_LENGTH, out);\r
+}\r
+/*\r
+* Compute TOTP_HMAC_SHA1 using key, key length, text to hash, size of the text\r
+*/\r
+uint32_t TOTP_HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n){\r
+ // STEP 1, get the HMAC-SHA1 hash from counter and key\r
+ uint8_t hash[SHA1_DIGEST_LENGTH];\r
+ HMAC_SHA1(key, key_length, in, n, hash);\r
+\r
+ // STEP 2, apply dynamic truncation to obtain a 4-bytes string\r
+ uint32_t truncated_hash = 0;\r
+ uint8_t _offset = hash[SHA1_DIGEST_LENGTH - 1] & 0xF;\r
+ uint8_t j;\r
+ for (j = 0; j < 4; ++j) {\r
+ truncated_hash <<= 8;\r
+ truncated_hash |= hash[_offset + j];\r
+ }\r
+\r
+ // STEP 3, compute the OTP value\r
+ truncated_hash &= 0x7FFFFFFF; //Disabled\r
+ truncated_hash %= 1000000;\r
+\r
+ return truncated_hash;\r
+}\r
--- /dev/null
+/**\r
+ * \file sha1.h\r
+ *\r
+ * \brief SHA-1 cryptographic hash function\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+#ifndef MBEDTLS_SHA1_H\r
+#define MBEDTLS_SHA1_H\r
+\r
+#define SHA1_DIGEST_LENGTH 20\r
+#define SHA1_BLOCK_LENGTH 64\r
+#define HMAC_IPAD 0x36\r
+#define HMAC_OPAD 0x5c\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * \brief SHA-1 context structure\r
+ */\r
+typedef struct\r
+{\r
+ uint32_t total[2]; /*!< number of bytes processed */\r
+ uint32_t state[5]; /*!< intermediate digest state */\r
+ unsigned char buffer[SHA1_BLOCK_LENGTH]; /*!< data block being processed */\r
+}\r
+mbedtls_sha1_context;\r
+\r
+/**\r
+ * \brief Initialize SHA-1 context\r
+ *\r
+ * \param ctx SHA-1 context to be initialized\r
+ */\r
+void mbedtls_sha1_init( mbedtls_sha1_context *ctx );\r
+\r
+/**\r
+ * \brief Clear SHA-1 context\r
+ *\r
+ * \param ctx SHA-1 context to be cleared\r
+ */\r
+void mbedtls_sha1_free( mbedtls_sha1_context *ctx );\r
+\r
+/**\r
+ * \brief SHA-1 context setup\r
+ *\r
+ * \param ctx context to be initialized\r
+ */\r
+void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );\r
+\r
+/**\r
+ * \brief SHA-1 process buffer\r
+ *\r
+ * \param ctx SHA-1 context\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ */\r
+void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );\r
+\r
+/**\r
+ * \brief SHA-1 final digest\r
+ *\r
+ * \param ctx SHA-1 context\r
+ * \param output SHA-1 checksum result\r
+ */\r
+void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[SHA1_DIGEST_LENGTH] );\r
+\r
+/* Internal use */\r
+void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[SHA1_BLOCK_LENGTH] );\r
+\r
+/**\r
+ * \brief Output = SHA-1( input buffer )\r
+ *\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ * \param output SHA-1 checksum result\r
+ */\r
+void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[SHA1_DIGEST_LENGTH] );\r
+void HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t out[SHA1_DIGEST_LENGTH]);\r
+uint32_t TOTP_HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n);\r
+\r
+\r
+#endif /* mbedtls_sha1.h */\r
--- /dev/null
+/*\r
+ * FIPS-180-2 compliant SHA-256 implementation\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+/*\r
+ * The SHA-256 Secure Hash Standard was published by NIST in 2002.\r
+ *\r
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\r
+ */\r
+\r
+#include "sha256.h"\r
+\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+/* Implementation that should never be optimized out by the compiler */\r
+static void mbedtls_zeroize( void *v, size_t n ) {\r
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;\r
+}\r
+\r
+/*\r
+ * 32-bit integer manipulation macros (big endian)\r
+ */\r
+#ifndef GET_UINT32_BE\r
+#define GET_UINT32_BE(n,b,i) \\r
+do { \\r
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \\r
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \\r
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \\r
+ | ( (uint32_t) (b)[(i) + 3] ); \\r
+} while( 0 )\r
+#endif\r
+\r
+#ifndef PUT_UINT32_BE\r
+#define PUT_UINT32_BE(n,b,i) \\r
+do { \\r
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \\r
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \\r
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \\r
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \\r
+} while( 0 )\r
+#endif\r
+\r
+void mbedtls_sha256_init( mbedtls_sha256_context *ctx )\r
+{\r
+ memset( ctx, 0, sizeof( mbedtls_sha256_context ) );\r
+}\r
+\r
+void mbedtls_sha256_free( mbedtls_sha256_context *ctx )\r
+{\r
+ if( ctx == NULL )\r
+ return;\r
+\r
+ mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );\r
+}\r
+\r
+void mbedtls_sha256_clone( mbedtls_sha256_context *dst,\r
+ const mbedtls_sha256_context *src )\r
+{\r
+ *dst = *src;\r
+}\r
+\r
+/*\r
+ * SHA-256 context setup\r
+ */\r
+void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )\r
+{\r
+ ctx->total[0] = 0;\r
+ ctx->total[1] = 0;\r
+\r
+ if( is224 == 0 )\r
+ {\r
+ /* SHA-256 */\r
+ ctx->state[0] = 0x6A09E667;\r
+ ctx->state[1] = 0xBB67AE85;\r
+ ctx->state[2] = 0x3C6EF372;\r
+ ctx->state[3] = 0xA54FF53A;\r
+ ctx->state[4] = 0x510E527F;\r
+ ctx->state[5] = 0x9B05688C;\r
+ ctx->state[6] = 0x1F83D9AB;\r
+ ctx->state[7] = 0x5BE0CD19;\r
+ }\r
+ else\r
+ {\r
+ /* SHA-224 */\r
+ ctx->state[0] = 0xC1059ED8;\r
+ ctx->state[1] = 0x367CD507;\r
+ ctx->state[2] = 0x3070DD17;\r
+ ctx->state[3] = 0xF70E5939;\r
+ ctx->state[4] = 0xFFC00B31;\r
+ ctx->state[5] = 0x68581511;\r
+ ctx->state[6] = 0x64F98FA7;\r
+ ctx->state[7] = 0xBEFA4FA4;\r
+ }\r
+\r
+ ctx->is224 = is224;\r
+}\r
+\r
+static const uint32_t K[] =\r
+{\r
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,\r
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,\r
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,\r
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,\r
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,\r
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,\r
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,\r
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,\r
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,\r
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,\r
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,\r
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,\r
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,\r
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,\r
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,\r
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,\r
+};\r
+\r
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)\r
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))\r
+\r
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))\r
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))\r
+\r
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))\r
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))\r
+\r
+#define F0(x,y,z) ((x & y) | (z & (x | y)))\r
+#define F1(x,y,z) (z ^ (x & (y ^ z)))\r
+\r
+#define R(t) \\r
+( \\r
+ W[t] = S1(W[t - 2]) + W[t - 7] + \\r
+ S0(W[t - 15]) + W[t - 16] \\r
+)\r
+\r
+#define P(a,b,c,d,e,f,g,h,x,K) \\r
+{ \\r
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \\r
+ temp2 = S2(a) + F0(a,b,c); \\r
+ d += temp1; h = temp1 + temp2; \\r
+}\r
+\r
+void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_LENGTH] )\r
+{\r
+ uint32_t temp1, temp2, W[64];\r
+ uint32_t A[8];\r
+ unsigned int i;\r
+\r
+ for( i = 0; i < 8; i++ )\r
+ A[i] = ctx->state[i];\r
+\r
+ for( i = 0; i < 16; i++ )\r
+ GET_UINT32_BE( W[i], data, 4 * i );\r
+\r
+ for( i = 0; i < 16; i += 8 )\r
+ {\r
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );\r
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );\r
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );\r
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );\r
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );\r
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );\r
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );\r
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );\r
+ }\r
+\r
+ for( i = 16; i < 64; i += 8 )\r
+ {\r
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );\r
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );\r
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );\r
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );\r
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );\r
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );\r
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );\r
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );\r
+ }\r
+\r
+ for( i = 0; i < 8; i++ )\r
+ ctx->state[i] += A[i];\r
+}\r
+\r
+/*\r
+ * SHA-256 process buffer\r
+ */\r
+void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,\r
+ size_t ilen )\r
+{\r
+ size_t fill;\r
+ uint32_t left;\r
+\r
+ if( ilen == 0 )\r
+ return;\r
+\r
+ left = ctx->total[0] & 0x3F;\r
+ fill = 64 - left;\r
+\r
+ ctx->total[0] += (uint32_t) ilen;\r
+ ctx->total[0] &= 0xFFFFFFFF;\r
+\r
+ if( ctx->total[0] < (uint32_t) ilen )\r
+ ctx->total[1]++;\r
+\r
+ if( left && ilen >= fill )\r
+ {\r
+ memcpy( (void *) (ctx->buffer + left), input, fill );\r
+ mbedtls_sha256_process( ctx, ctx->buffer );\r
+ input += fill;\r
+ ilen -= fill;\r
+ left = 0;\r
+ }\r
+\r
+ while( ilen >= 64 )\r
+ {\r
+ mbedtls_sha256_process( ctx, input );\r
+ input += 64;\r
+ ilen -= 64;\r
+ }\r
+\r
+ if( ilen > 0 )\r
+ memcpy( (void *) (ctx->buffer + left), input, ilen );\r
+}\r
+\r
+static const unsigned char sha256_padding[SHA256_BLOCK_LENGTH] =\r
+{\r
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+/*\r
+ * SHA-256 final digest\r
+ */\r
+void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char* output )\r
+{\r
+ uint32_t last, padn;\r
+ uint32_t high, low;\r
+ unsigned char msglen[8];\r
+\r
+ high = ( ctx->total[0] >> 29 )\r
+ | ( ctx->total[1] << 3 );\r
+ low = ( ctx->total[0] << 3 );\r
+\r
+ PUT_UINT32_BE( high, msglen, 0 );\r
+ PUT_UINT32_BE( low, msglen, 4 );\r
+\r
+ last = ctx->total[0] & 0x3F;\r
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\r
+\r
+ mbedtls_sha256_update( ctx, sha256_padding, padn );\r
+ mbedtls_sha256_update( ctx, msglen, 8 );\r
+\r
+ PUT_UINT32_BE( ctx->state[0], output, 0 );\r
+ PUT_UINT32_BE( ctx->state[1], output, 4 );\r
+ PUT_UINT32_BE( ctx->state[2], output, 8 );\r
+ PUT_UINT32_BE( ctx->state[3], output, 12 );\r
+ PUT_UINT32_BE( ctx->state[4], output, 16 );\r
+ PUT_UINT32_BE( ctx->state[5], output, 20 );\r
+ PUT_UINT32_BE( ctx->state[6], output, 24 );\r
+\r
+ if( ctx->is224 == 0 )\r
+ PUT_UINT32_BE( ctx->state[7], output, 28 );\r
+}\r
+\r
+/*\r
+ * output = SHA-256( input buffer )\r
+ */\r
+void mbedtls_sha256( const unsigned char *input, size_t ilen,\r
+ unsigned char* output, int is224 )\r
+{\r
+ mbedtls_sha256_context ctx;\r
+\r
+ mbedtls_sha256_init( &ctx );\r
+ mbedtls_sha256_starts( &ctx, is224 );\r
+ mbedtls_sha256_update( &ctx, input, ilen );\r
+ mbedtls_sha256_finish( &ctx, output );\r
+ mbedtls_sha256_free( &ctx );\r
+}\r
+\r
+/*\r
+* Compute HMAC_SHA224/256 using key, key length, text to hash, size of the text, output buffer and a switch for SHA224\r
+*/\r
+void HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is224){\r
+ int digest_length = SHA256_DIGEST_LENGTH;\r
+ if (is224 == 1) {\r
+ digest_length = SHA224_DIGEST_LENGTH;\r
+ }\r
+ \r
+ uint8_t i;\r
+ uint8_t k_ipad[SHA256_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */\r
+ uint8_t k_opad[SHA256_BLOCK_LENGTH]; /* outer padding - key XORd with opad */\r
+ uint8_t buffer[SHA256_BLOCK_LENGTH + digest_length];\r
+\r
+ /* start out by storing key in pads */\r
+ memset(k_ipad, 0, sizeof(k_ipad));\r
+ memset(k_opad, 0, sizeof(k_opad));\r
+\r
+ if (key_length <= SHA256_BLOCK_LENGTH) {\r
+ memcpy(k_ipad, key, key_length);\r
+ memcpy(k_opad, key, key_length);\r
+ }\r
+\r
+ else {\r
+ mbedtls_sha256(key, key_length, k_ipad, is224);\r
+ memcpy(k_opad, k_ipad, SHA256_BLOCK_LENGTH);\r
+ }\r
+\r
+ /* XOR key with ipad and opad values */\r
+ for (i = 0; i < SHA256_BLOCK_LENGTH; i++) {\r
+ k_ipad[i] ^= HMAC_IPAD;\r
+ k_opad[i] ^= HMAC_OPAD;\r
+ }\r
+ \r
+ // perform inner SHA256\r
+ memcpy(buffer, k_ipad, SHA256_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA256_BLOCK_LENGTH, in, n);\r
+ mbedtls_sha256(buffer, SHA256_BLOCK_LENGTH + n, out, is224);\r
+ \r
+ memset(buffer, 0, SHA256_BLOCK_LENGTH + n);\r
+\r
+ // perform outer SHA256\r
+ memcpy(buffer, k_opad, SHA256_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA256_BLOCK_LENGTH, out, digest_length);\r
+ mbedtls_sha256(buffer, SHA256_BLOCK_LENGTH + digest_length, out, is224);\r
+}\r
+\r
+/*\r
+* Compute TOTP_HMAC_SHA224/256 using key, key length, text to hash, size of the text and a switch for SHA224\r
+*/\r
+uint32_t TOTP_HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is224){\r
+ int digest_length = SHA256_DIGEST_LENGTH;\r
+ if (is224 == 1) {\r
+ digest_length = SHA224_DIGEST_LENGTH;\r
+ }\r
+\r
+ // STEP 1, get the HMAC-SHA256 hash from counter and key\r
+ uint8_t hash[digest_length];\r
+ HMAC_SHA256(key, key_length, in, n, hash, is224);\r
+\r
+ // STEP 2, apply dynamic truncation to obtain a 4-bytes string\r
+ uint32_t truncated_hash = 0;\r
+ uint8_t _offset = hash[digest_length - 1] & 0xF;\r
+ uint8_t j;\r
+ for (j = 0; j < 4; ++j) {\r
+ truncated_hash <<= 8;\r
+ truncated_hash |= hash[_offset + j];\r
+ }\r
+\r
+ // STEP 3, compute the OTP value\r
+ truncated_hash &= 0x7FFFFFFF; //Disabled\r
+ truncated_hash %= 1000000;\r
+\r
+ return truncated_hash;\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * \file sha256.h\r
+ *\r
+ * \brief SHA-224 and SHA-256 cryptographic hash function\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+#ifndef MBEDTLS_SHA256_H\r
+#define MBEDTLS_SHA256_H\r
+\r
+#define SHA224_DIGEST_LENGTH 28\r
+#define SHA256_DIGEST_LENGTH 32\r
+#define SHA256_BLOCK_LENGTH 64\r
+#define HMAC_IPAD 0x36\r
+#define HMAC_OPAD 0x5c\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * \brief SHA-256 context structure\r
+ */\r
+typedef struct\r
+{\r
+ uint32_t total[2]; /*!< number of bytes processed */\r
+ uint32_t state[8]; /*!< intermediate digest state */\r
+ unsigned char buffer[SHA256_BLOCK_LENGTH]; /*!< data block being processed */\r
+ int is224; /*!< 0 => SHA-256, else SHA-224 */\r
+}\r
+mbedtls_sha256_context;\r
+\r
+/**\r
+ * \brief Initialize SHA-256 context\r
+ *\r
+ * \param ctx SHA-256 context to be initialized\r
+ */\r
+void mbedtls_sha256_init( mbedtls_sha256_context *ctx );\r
+\r
+/**\r
+ * \brief Clear SHA-256 context\r
+ *\r
+ * \param ctx SHA-256 context to be cleared\r
+ */\r
+void mbedtls_sha256_free( mbedtls_sha256_context *ctx );\r
+\r
+/**\r
+ * \brief Clone (the state of) a SHA-256 context\r
+ *\r
+ * \param dst The destination context\r
+ * \param src The context to be cloned\r
+ */\r
+void mbedtls_sha256_clone( mbedtls_sha256_context *dst,\r
+ const mbedtls_sha256_context *src );\r
+\r
+/**\r
+ * \brief SHA-256 context setup\r
+ *\r
+ * \param ctx context to be initialized\r
+ * \param is224 0 = use SHA256, 1 = use SHA224\r
+ */\r
+void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );\r
+\r
+/**\r
+ * \brief SHA-256 process buffer\r
+ *\r
+ * \param ctx SHA-256 context\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ */\r
+void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,\r
+ size_t ilen );\r
+\r
+/**\r
+ * \brief SHA-256 final digest\r
+ *\r
+ * \param ctx SHA-256 context\r
+ * \param output SHA-224/256 checksum result\r
+ */\r
+void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char* output );\r
+\r
+/* Internal use */\r
+void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_LENGTH] );\r
+\r
+/**\r
+ * \brief Output = SHA-256( input buffer )\r
+ *\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ * \param output SHA-224/256 checksum result\r
+ * \param is224 0 = use SHA256, 1 = use SHA224\r
+ */\r
+void mbedtls_sha256( const unsigned char *input, size_t ilen,\r
+ unsigned char* output, int is224 );\r
+void HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is224);\r
+uint32_t TOTP_HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is224);\r
+\r
+#endif /* mbedtls_sha256.h */\r
--- /dev/null
+/*\r
+ * FIPS-180-2 compliant SHA-384/512 implementation\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+/*\r
+ * The SHA-512 Secure Hash Standard was published by NIST in 2002.\r
+ *\r
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\r
+ */\r
+\r
+#include "sha512.h"\r
+\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+#if defined(_MSC_VER) || defined(__WATCOMC__)\r
+ #define UL64(x) x##ui64\r
+#else\r
+ #define UL64(x) x##ULL\r
+#endif\r
+\r
+/* Implementation that should never be optimized out by the compiler */\r
+static void mbedtls_zeroize( void *v, size_t n ) {\r
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;\r
+}\r
+\r
+/*\r
+ * 64-bit integer manipulation macros (big endian)\r
+ */\r
+#ifndef GET_UINT64_BE\r
+#define GET_UINT64_BE(n,b,i) \\r
+{ \\r
+ (n) = ( (uint64_t) (b)[(i) ] << 56 ) \\r
+ | ( (uint64_t) (b)[(i) + 1] << 48 ) \\r
+ | ( (uint64_t) (b)[(i) + 2] << 40 ) \\r
+ | ( (uint64_t) (b)[(i) + 3] << 32 ) \\r
+ | ( (uint64_t) (b)[(i) + 4] << 24 ) \\r
+ | ( (uint64_t) (b)[(i) + 5] << 16 ) \\r
+ | ( (uint64_t) (b)[(i) + 6] << 8 ) \\r
+ | ( (uint64_t) (b)[(i) + 7] ); \\r
+}\r
+#endif /* GET_UINT64_BE */\r
+\r
+#ifndef PUT_UINT64_BE\r
+#define PUT_UINT64_BE(n,b,i) \\r
+{ \\r
+ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \\r
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \\r
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \\r
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \\r
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \\r
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \\r
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \\r
+ (b)[(i) + 7] = (unsigned char) ( (n) ); \\r
+}\r
+#endif /* PUT_UINT64_BE */\r
+\r
+/*\r
+ * Round constants\r
+ */\r
+static const uint64_t K[80] =\r
+{\r
+ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),\r
+ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),\r
+ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),\r
+ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),\r
+ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),\r
+ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),\r
+ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),\r
+ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),\r
+ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),\r
+ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),\r
+ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),\r
+ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),\r
+ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),\r
+ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),\r
+ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),\r
+ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),\r
+ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),\r
+ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),\r
+ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),\r
+ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),\r
+ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),\r
+ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),\r
+ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),\r
+ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),\r
+ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),\r
+ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),\r
+ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),\r
+ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),\r
+ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),\r
+ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),\r
+ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),\r
+ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),\r
+ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),\r
+ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),\r
+ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),\r
+ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),\r
+ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),\r
+ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),\r
+ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),\r
+ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)\r
+};\r
+\r
+void mbedtls_sha512_init( mbedtls_sha512_context *ctx )\r
+{\r
+ memset( ctx, 0, sizeof( mbedtls_sha512_context ) );\r
+}\r
+\r
+void mbedtls_sha512_free( mbedtls_sha512_context *ctx )\r
+{\r
+ if( ctx == NULL )\r
+ return;\r
+\r
+ mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );\r
+}\r
+\r
+void mbedtls_sha512_clone( mbedtls_sha512_context *dst,\r
+ const mbedtls_sha512_context *src )\r
+{\r
+ *dst = *src;\r
+}\r
+\r
+/*\r
+ * SHA-512 context setup\r
+ */\r
+void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )\r
+{\r
+ ctx->total[0] = 0;\r
+ ctx->total[1] = 0;\r
+\r
+ if( is384 == 0 )\r
+ {\r
+ /* SHA-512 */\r
+ ctx->state[0] = UL64(0x6A09E667F3BCC908);\r
+ ctx->state[1] = UL64(0xBB67AE8584CAA73B);\r
+ ctx->state[2] = UL64(0x3C6EF372FE94F82B);\r
+ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);\r
+ ctx->state[4] = UL64(0x510E527FADE682D1);\r
+ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);\r
+ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);\r
+ ctx->state[7] = UL64(0x5BE0CD19137E2179);\r
+ }\r
+ else\r
+ {\r
+ /* SHA-384 */\r
+ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);\r
+ ctx->state[1] = UL64(0x629A292A367CD507);\r
+ ctx->state[2] = UL64(0x9159015A3070DD17);\r
+ ctx->state[3] = UL64(0x152FECD8F70E5939);\r
+ ctx->state[4] = UL64(0x67332667FFC00B31);\r
+ ctx->state[5] = UL64(0x8EB44A8768581511);\r
+ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);\r
+ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);\r
+ }\r
+\r
+ ctx->is384 = is384;\r
+}\r
+\r
+void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_LENGTH] )\r
+{\r
+ int i;\r
+ uint64_t temp1, temp2, W[80];\r
+ uint64_t A, B, C, D, E, F, G, H;\r
+\r
+#define SHR(x,n) (x >> n)\r
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))\r
+\r
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))\r
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))\r
+\r
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))\r
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))\r
+\r
+#define F0(x,y,z) ((x & y) | (z & (x | y)))\r
+#define F1(x,y,z) (z ^ (x & (y ^ z)))\r
+\r
+#define P(a,b,c,d,e,f,g,h,x,K) \\r
+{ \\r
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \\r
+ temp2 = S2(a) + F0(a,b,c); \\r
+ d += temp1; h = temp1 + temp2; \\r
+}\r
+\r
+ for( i = 0; i < 16; i++ )\r
+ {\r
+ GET_UINT64_BE( W[i], data, i << 3 );\r
+ }\r
+\r
+ for( ; i < 80; i++ )\r
+ {\r
+ W[i] = S1(W[i - 2]) + W[i - 7] +\r
+ S0(W[i - 15]) + W[i - 16];\r
+ }\r
+\r
+ A = ctx->state[0];\r
+ B = ctx->state[1];\r
+ C = ctx->state[2];\r
+ D = ctx->state[3];\r
+ E = ctx->state[4];\r
+ F = ctx->state[5];\r
+ G = ctx->state[6];\r
+ H = ctx->state[7];\r
+ i = 0;\r
+\r
+ do\r
+ {\r
+ P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;\r
+ P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;\r
+ P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;\r
+ P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;\r
+ P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;\r
+ P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;\r
+ P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;\r
+ P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;\r
+ }\r
+ while( i < 80 );\r
+\r
+ ctx->state[0] += A;\r
+ ctx->state[1] += B;\r
+ ctx->state[2] += C;\r
+ ctx->state[3] += D;\r
+ ctx->state[4] += E;\r
+ ctx->state[5] += F;\r
+ ctx->state[6] += G;\r
+ ctx->state[7] += H;\r
+}\r
+\r
+/*\r
+ * SHA-512 process buffer\r
+ */\r
+void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,\r
+ size_t ilen )\r
+{\r
+ size_t fill;\r
+ unsigned int left;\r
+\r
+ if( ilen == 0 )\r
+ return;\r
+\r
+ left = (unsigned int) (ctx->total[0] & 0x7F);\r
+ fill = 128 - left;\r
+\r
+ ctx->total[0] += (uint64_t) ilen;\r
+\r
+ if( ctx->total[0] < (uint64_t) ilen )\r
+ ctx->total[1]++;\r
+\r
+ if( left && ilen >= fill )\r
+ {\r
+ memcpy( (void *) (ctx->buffer + left), input, fill );\r
+ mbedtls_sha512_process( ctx, ctx->buffer );\r
+ input += fill;\r
+ ilen -= fill;\r
+ left = 0;\r
+ }\r
+\r
+ while( ilen >= 128 )\r
+ {\r
+ mbedtls_sha512_process( ctx, input );\r
+ input += 128;\r
+ ilen -= 128;\r
+ }\r
+\r
+ if( ilen > 0 )\r
+ memcpy( (void *) (ctx->buffer + left), input, ilen );\r
+}\r
+\r
+static const unsigned char sha512_padding[SHA512_BLOCK_LENGTH] =\r
+{\r
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+/*\r
+ * SHA-512 final digest\r
+ */\r
+void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char* output )\r
+{\r
+ size_t last, padn;\r
+ uint64_t high, low;\r
+ unsigned char msglen[16];\r
+\r
+ high = ( ctx->total[0] >> 61 )\r
+ | ( ctx->total[1] << 3 );\r
+ low = ( ctx->total[0] << 3 );\r
+\r
+ PUT_UINT64_BE( high, msglen, 0 );\r
+ PUT_UINT64_BE( low, msglen, 8 );\r
+\r
+ last = (size_t)( ctx->total[0] & 0x7F );\r
+ padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );\r
+\r
+ mbedtls_sha512_update( ctx, sha512_padding, padn );\r
+ mbedtls_sha512_update( ctx, msglen, 16 );\r
+\r
+ PUT_UINT64_BE( ctx->state[0], output, 0 );\r
+ PUT_UINT64_BE( ctx->state[1], output, 8 );\r
+ PUT_UINT64_BE( ctx->state[2], output, 16 );\r
+ PUT_UINT64_BE( ctx->state[3], output, 24 );\r
+ PUT_UINT64_BE( ctx->state[4], output, 32 );\r
+ PUT_UINT64_BE( ctx->state[5], output, 40 );\r
+\r
+ if( ctx->is384 == 0 )\r
+ {\r
+ PUT_UINT64_BE( ctx->state[6], output, 48 );\r
+ PUT_UINT64_BE( ctx->state[7], output, 56 );\r
+ }\r
+}\r
+\r
+/*\r
+ * output = SHA-512( input buffer )\r
+ */\r
+void mbedtls_sha512( const unsigned char *input, size_t ilen,\r
+ unsigned char* output, int is384 )\r
+{\r
+ mbedtls_sha512_context ctx;\r
+\r
+ mbedtls_sha512_init( &ctx );\r
+ mbedtls_sha512_starts( &ctx, is384 );\r
+ mbedtls_sha512_update( &ctx, input, ilen );\r
+ mbedtls_sha512_finish( &ctx, output );\r
+ mbedtls_sha512_free( &ctx );\r
+}\r
+\r
+/*\r
+* Compute HMAC_SHA384/512 using key, key length, text to hash, size of the text, output buffer and a switch for SHA384\r
+*/\r
+void HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is384){\r
+ int digest_length = SHA512_DIGEST_LENGTH;\r
+ if (is384 == 1) {\r
+ digest_length = SHA384_DIGEST_LENGTH;\r
+ }\r
+\r
+ uint8_t i;\r
+ uint8_t k_ipad[SHA512_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */\r
+ uint8_t k_opad[SHA512_BLOCK_LENGTH]; /* outer padding - key XORd with opad */\r
+ uint8_t buffer[SHA512_BLOCK_LENGTH + digest_length];\r
+\r
+ /* start out by storing key in pads */\r
+ memset(k_ipad, 0, sizeof(k_ipad));\r
+ memset(k_opad, 0, sizeof(k_opad));\r
+\r
+ if (key_length <= SHA512_BLOCK_LENGTH) {\r
+ memcpy(k_ipad, key, key_length);\r
+ memcpy(k_opad, key, key_length);\r
+ }\r
+\r
+ else {\r
+ mbedtls_sha512(key, key_length, k_ipad, is384);\r
+ memcpy(k_opad, k_ipad, SHA512_BLOCK_LENGTH);\r
+ }\r
+\r
+ /* XOR key with ipad and opad values */\r
+ for (i = 0; i < SHA512_BLOCK_LENGTH; i++) {\r
+ k_ipad[i] ^= HMAC_IPAD;\r
+ k_opad[i] ^= HMAC_OPAD;\r
+ }\r
+ \r
+ // perform inner SHA512\r
+ memcpy(buffer, k_ipad, SHA512_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA512_BLOCK_LENGTH, in, n);\r
+ mbedtls_sha512(buffer, SHA512_BLOCK_LENGTH + n, out, is384);\r
+ \r
+ memset(buffer, 0, SHA512_BLOCK_LENGTH + n);\r
+\r
+ // perform outer SHA512\r
+ memcpy(buffer, k_opad, SHA512_BLOCK_LENGTH);\r
+ memcpy(buffer + SHA512_BLOCK_LENGTH, out, digest_length);\r
+ mbedtls_sha512(buffer, SHA512_BLOCK_LENGTH + digest_length, out, is384);\r
+}\r
+\r
+/*\r
+* Compute TOTP_HMAC_SHA384/512 using key, key length, text to hash, size of the text and a switch for SHA384\r
+*/\r
+uint32_t TOTP_HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is384){\r
+ int digest_length = SHA512_DIGEST_LENGTH;\r
+ if (is384 == 1) {\r
+ digest_length = SHA384_DIGEST_LENGTH;\r
+ }\r
+\r
+ // STEP 1, get the HMAC-SHA512 hash from counter and key\r
+ uint8_t hash[digest_length];\r
+ HMAC_SHA512(key, key_length, in, n, hash, is384);\r
+\r
+ // STEP 2, apply dynamic truncation to obtain a 4-bytes string\r
+ uint32_t truncated_hash = 0;\r
+ uint8_t _offset = hash[digest_length - 1] & 0xF;\r
+ uint8_t j;\r
+ for (j = 0; j < 4; ++j) {\r
+ truncated_hash <<= 8;\r
+ truncated_hash |= hash[_offset + j];\r
+ }\r
+\r
+ // STEP 3, compute the OTP value\r
+ truncated_hash &= 0x7FFFFFFF; //Disabled\r
+ truncated_hash %= 1000000;\r
+\r
+ return truncated_hash;\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * \file sha512.h\r
+ *\r
+ * \brief SHA-384 and SHA-512 cryptographic hash function\r
+ *\r
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may\r
+ * not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * This file is part of mbed TLS (https://tls.mbed.org)\r
+ */\r
+#ifndef MBEDTLS_SHA512_H\r
+#define MBEDTLS_SHA512_H\r
+\r
+#define SHA384_DIGEST_LENGTH 48\r
+#define SHA512_DIGEST_LENGTH 64\r
+#define SHA512_BLOCK_LENGTH 128\r
+#define HMAC_IPAD 0x36\r
+#define HMAC_OPAD 0x5c\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * \brief SHA-512 context structure\r
+ */\r
+typedef struct\r
+{\r
+ uint64_t total[2]; /*!< number of bytes processed */\r
+ uint64_t state[8]; /*!< intermediate digest state */\r
+ unsigned char buffer[SHA512_BLOCK_LENGTH]; /*!< data block being processed */\r
+ int is384; /*!< 0 => SHA-512, else SHA-384 */\r
+}\r
+mbedtls_sha512_context;\r
+\r
+/**\r
+ * \brief Initialize SHA-512 context\r
+ *\r
+ * \param ctx SHA-512 context to be initialized\r
+ */\r
+void mbedtls_sha512_init( mbedtls_sha512_context *ctx );\r
+\r
+/**\r
+ * \brief Clear SHA-512 context\r
+ *\r
+ * \param ctx SHA-512 context to be cleared\r
+ */\r
+void mbedtls_sha512_free( mbedtls_sha512_context *ctx );\r
+\r
+/**\r
+ * \brief Clone (the state of) a SHA-512 context\r
+ *\r
+ * \param dst The destination context\r
+ * \param src The context to be cloned\r
+ */\r
+void mbedtls_sha512_clone( mbedtls_sha512_context *dst,\r
+ const mbedtls_sha512_context *src );\r
+\r
+/**\r
+ * \brief SHA-512 context setup\r
+ *\r
+ * \param ctx context to be initialized\r
+ * \param is384 0 = use SHA512, 1 = use SHA384\r
+ */\r
+void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 );\r
+\r
+/**\r
+ * \brief SHA-512 process buffer\r
+ *\r
+ * \param ctx SHA-512 context\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ */\r
+void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,\r
+ size_t ilen );\r
+\r
+/**\r
+ * \brief SHA-512 final digest\r
+ *\r
+ * \param ctx SHA-512 context\r
+ * \param output SHA-384/512 checksum result\r
+ */\r
+void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char* output );\r
+\r
+/**\r
+ * \brief Output = SHA-512( input buffer )\r
+ *\r
+ * \param input buffer holding the data\r
+ * \param ilen length of the input data\r
+ * \param output SHA-384/512 checksum result\r
+ * \param is384 0 = use SHA512, 1 = use SHA384\r
+ */\r
+void mbedtls_sha512( const unsigned char *input, size_t ilen,\r
+ unsigned char* output, int is384 );\r
+\r
+/**\r
+ * \brief Checkup routine\r
+ *\r
+ * \return 0 if successful, or 1 if the test failed\r
+ */\r
+int mbedtls_sha512_self_test( int verbose );\r
+\r
+/* Internal use */\r
+void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_LENGTH] );\r
+void HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is384);\r
+uint32_t TOTP_HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is384);\r
+\r
+#endif /* mbedtls_sha512.h */\r
-I../watch_faces/sensor/ \
-I../watch_faces/demo/ \
-I../../littlefs/ \
- -I../lib/TOTP-MCU/ \
+ -I../lib/TOTP/ \
-I../lib/base32/ \
-I../lib/sunriset/ \
-I../lib/vsop87/ \
# ../drivers/lis2dh.c \
# ../watch_faces/fitness/step_count_face.c
SRCS += \
- ../lib/TOTP-MCU/sha1.c \
- ../lib/TOTP-MCU/TOTP.c \
+ ../lib/TOTP/sha1.c \
+ ../lib/TOTP/sha256.c \
+ ../lib/TOTP/sha512.c \
+ ../lib/TOTP/TOTP.c \
../lib/base32/base32.c \
../lib/sunriset/sunriset.c \
../lib/vsop87/vsop87a_milli.c \
#include "TOTP.h"
// Use https://cryptii.com/pipes/base32-to-hex to convert base32 to hex
-// Use https://totp.danhersam.com/ to generate test codes for verification
+// Use https://github.com/susam/mintotp to generate test codes for verification
+// Available algorothms:
+// SHA1 (most TOTP codes use this)
+// SHA224
+// SHA256
+// SHA384
+// SHA512
+////////////////////////////////////////////////////////////////////////////////
+// Enter your TOTP key data below
static const uint8_t num_keys = 2;
static uint8_t keys[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe, 0xef, // 1 - JBSWY3DPEHPK3PXP
- 0x5c, 0x0d, 0x27, 0x6b, 0x6d, 0x9a, 0x01, 0x22, 0x20, 0x4f // 2 - E9M348K0ADIDFBC2
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe, 0xef, // 2 - JBSWY3DPEHPK3PXP
};
static const uint8_t key_sizes[] = {
10,
- 10
+ 10,
};
static const uint32_t timesteps[] = {
30,
- 30
+ 30,
};
static const char labels[][2] = {
- { 'a', 'b' },
- { 'c', 'd' }
+ { '2', 'F' },
+ { 'A', 'C' },
+};
+static const hmac_alg algorithms[] = {
+ SHA1,
+ SHA1,
};
+// END OF KEY DATA.
+////////////////////////////////////////////////////////////////////////////////
void totp_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
(void) settings;
(void) settings;
memset(context, 0, sizeof(totp_state_t));
totp_state_t *totp_state = (totp_state_t *)context;
- TOTP(keys, key_sizes[0], timesteps[0]);
+ TOTP(keys, key_sizes[0], timesteps[0], algorithms[0]);
totp_state->timestamp = watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60);
totp_state->current_code = getCodeFromTimestamp(totp_state->timestamp);
}
totp_state->current_key_offset = 0;
totp_state->current_index = 0;
}
- TOTP(keys + totp_state->current_key_offset, key_sizes[totp_state->current_index], timesteps[totp_state->current_index]);
+ TOTP(keys + totp_state->current_key_offset, key_sizes[totp_state->current_index], timesteps[totp_state->current_index], algorithms[totp_state->current_index]);
break;
case EVENT_ALARM_BUTTON_DOWN:
case EVENT_ALARM_LONG_PRESS:
size_t secret_size;
char label[2];
uint32_t period;
+ hmac_alg algorithm;
};
static struct totp_record totp_records[MAX_TOTP_RECORDS];
totp_record->label[0] = 'A';
totp_record->label[1] = 'A';
totp_record->period = 30;
+ totp_record->algorithm = SHA1;
}
static bool totp_face_lfs_read_param(struct totp_record *totp_record, char *param, char *value) {
return false;
}
} else if (!strcmp(param, "algorithm")) {
- if (!strcmp(param, "SHA1")) {
+ if (!strcmp(value, "SHA1")) {
+ totp_record->algorithm = SHA1;
+ }
+ else if (!strcmp(value, "SHA224")) {
+ totp_record->algorithm = SHA224;
+ }
+ else if (!strcmp(value, "SHA256")) {
+ totp_record->algorithm = SHA256;
+ }
+ else if (!strcmp(value, "SHA384")) {
+ totp_record->algorithm = SHA384;
+ }
+ else if (!strcmp(value, "SHA512")) {
+ totp_record->algorithm = SHA512;
+ }
+ else {
printf("TOTP ignored due to algorithm %s\n", value);
return false;
}
}
totp_state->current_index = i;
- TOTP(totp_records[i].secret, totp_records[i].secret_size, totp_records[i].period);
+ TOTP(totp_records[i].secret, totp_records[i].secret_size, totp_records[i].period, totp_records[i].algorithm);
totp_state->current_code = getCodeFromTimestamp(totp_state->timestamp);
totp_state->steps = totp_state->timestamp / totp_records[i].period;
}