-I./filesystem \
-I./shell \
-I./lib/sunriset \
+ -I./lib/sha1 \
+ -I./lib/sha256 \
+ -I./lib/sha512 \
+ -I./lib/base32 \
+ -I./lib/TOTP \
-I./lib/chirpy_tx \
-I./lib/base64 \
-I./watch-library/shared/watch \
./shell/shell.c \
./shell/shell_cmd_list.c \
./lib/sunriset/sunriset.c \
+ ./lib/base32/base32.c \
+ ./lib/TOTP/sha1.c \
+ ./lib/TOTP/sha256.c \
+ ./lib/TOTP/sha512.c \
+ ./lib/TOTP/TOTP.c \
./lib/chirpy_tx/chirpy_tx.c \
./lib/base64/base64.c \
./watch-library/shared/driver/thermistor_driver.c \
+++ /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 __attribute__ ((__packed__)) {\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
+++ /dev/null
-/**
- * base32 (de)coder implementation as specified by RFC4648.
- *
- * Copyright (c) 2010 Adrien Kunysz
- *
- * 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.
- **/
-
-#include <assert.h> // assert()
-#include <limits.h> // CHAR_BIT
-
-#include "base32.h"
-
-/**
- * Let this be a sequence of plain data before encoding:
- *
- * 01234567 01234567 01234567 01234567 01234567
- * +--------+--------+--------+--------+--------+
- * |< 0 >< 1| >< 2 ><|.3 >< 4.|>< 5 ><.|6 >< 7 >|
- * +--------+--------+--------+--------+--------+
- *
- * There are 5 octets of 8 bits each in each sequence.
- * There are 8 blocks of 5 bits each in each sequence.
- *
- * You probably want to refer to that graph when reading the algorithms in this
- * file. We use "octet" instead of "byte" intentionnaly as we really work with
- * 8 bits quantities. This implementation will probably not work properly on
- * systems that don't have exactly 8 bits per (unsigned) char.
- **/
-
-static size_t min(size_t x, size_t y)
-{
- return x < y ? x : y;
-}
-
-static const unsigned char PADDING_CHAR = '=';
-
-/**
- * Pad the given buffer with len padding characters.
- */
-static void pad(unsigned char *buf, int len)
-{
- for (int i = 0; i < len; i++)
- buf[i] = PADDING_CHAR;
-}
-
-/**
- * This convert a 5 bits value into a base32 character.
- * Only the 5 least significant bits are used.
- */
-static unsigned char encode_char(unsigned char c)
-{
- static unsigned char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
- return base32[c & 0x1F]; // 0001 1111
-}
-
-/**
- * Decode given character into a 5 bits value.
- * Returns -1 iff the argument given was an invalid base32 character
- * or a padding character.
- */
-static int decode_char(unsigned char c)
-{
- int retval = -1;
-
- if (c >= 'A' && c <= 'Z')
- retval = c - 'A';
- if (c >= '2' && c <= '7')
- retval = c - '2' + 26;
-
- assert(retval == -1 || ((retval & 0x1F) == retval));
-
- return retval;
-}
-
-/**
- * Given a block id between 0 and 7 inclusive, this will return the index of
- * the octet in which this block starts. For example, given 3 it will return 1
- * because block 3 starts in octet 1:
- *
- * +--------+--------+
- * | ......<|.3 >....|
- * +--------+--------+
- * octet 1 | octet 2
- */
-static int get_octet(int block)
-{
- assert(block >= 0 && block < 8);
- return (block*5) / 8;
-}
-
-/**
- * Given a block id between 0 and 7 inclusive, this will return how many bits
- * we can drop at the end of the octet in which this block starts.
- * For example, given block 0 it will return 3 because there are 3 bits
- * we don't care about at the end:
- *
- * +--------+-
- * |< 0 >...|
- * +--------+-
- *
- * Given block 1, it will return -2 because there
- * are actually two bits missing to have a complete block:
- *
- * +--------+-
- * |.....< 1|..
- * +--------+-
- **/
-static int get_offset(int block)
-{
- assert(block >= 0 && block < 8);
- return (8 - 5 - (5*block) % 8);
-}
-
-/**
- * Like "b >> offset" but it will do the right thing with negative offset.
- * We need this as bitwise shifting by a negative offset is undefined
- * behavior.
- */
-static unsigned char shift_right(unsigned char byte, int offset)
-{
- if (offset > 0)
- return byte >> offset;
- else
- return byte << -offset;
-}
-
-static unsigned char shift_left(unsigned char byte, int offset)
-{
- return shift_right(byte, - offset);
-}
-
-/**
- * Encode a sequence. A sequence is no longer than 5 octets by definition.
- * Thus passing a length greater than 5 to this function is an error. Encoding
- * sequences shorter than 5 octets is supported and padding will be added to the
- * output as per the specification.
- */
-static void encode_sequence(const unsigned char *plain, int len, unsigned char *coded)
-{
- assert(CHAR_BIT == 8); // not sure this would work otherwise
- assert(len >= 0 && len <= 5);
-
- for (int block = 0; block < 8; block++) {
- int octet = get_octet(block); // figure out which octet this block starts in
- int junk = get_offset(block); // how many bits do we drop from this octet?
-
- if (octet >= len) { // we hit the end of the buffer
- pad(&coded[block], 8 - block);
- return;
- }
-
- unsigned char c = shift_right(plain[octet], junk); // first part
-
- if (junk < 0 // is there a second part?
- && octet < len - 1) // is there still something to read?
- {
- c |= shift_right(plain[octet+1], 8 + junk);
- }
- coded[block] = encode_char(c);
- }
-}
-
-void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded)
-{
- // All the hard work is done in encode_sequence(),
- // here we just need to feed it the data sequence by sequence.
- for (size_t i = 0, j = 0; i < len; i += 5, j += 8) {
- encode_sequence(&plain[i], min(len - i, 5), &coded[j]);
- }
-}
-
-static int decode_sequence(const unsigned char *coded, unsigned char *plain)
-{
- assert(CHAR_BIT == 8);
- assert(coded && plain);
-
- plain[0] = 0;
- for (int block = 0; block < 8; block++) {
- int offset = get_offset(block);
- int octet = get_octet(block);
-
- int c = decode_char(coded[block]);
- if (c < 0) // invalid char, stop here
- return octet;
-
- plain[octet] |= shift_left(c, offset);
- if (offset < 0) { // does this block overflows to next octet?
- assert(octet < 4);
- plain[octet+1] = shift_left(c, 8 + offset);
- }
- }
- return 5;
-}
-
-size_t base32_decode(const unsigned char *coded, unsigned char *plain)
-{
- size_t written = 0;
- for (size_t i = 0, j = 0; ; i += 8, j += 5) {
- int n = decode_sequence(&coded[i], &plain[j]);
- written += n;
- if (n < 5)
- return written;
- }
-}
+++ /dev/null
-/**
- * base32 (de)coder implementation as specified by RFC4648.
- *
- * Copyright (c) 2010 Adrien Kunysz
- *
- * 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.
- **/
-
-#ifndef __BASE32_H_
-#define __BASE32_H_
-
-#include <stddef.h> // size_t
-
-/**
- * Returns the length of the output buffer required to encode len bytes of
- * data into base32. This is a macro to allow users to define buffer size at
- * compilation time.
- */
-#define BASE32_LEN(len) (((len)/5)*8 + ((len) % 5 ? 8 : 0))
-
-/**
- * Returns the length of the output buffer required to decode a base32 string
- * of len characters. Please note that len must be a multiple of 8 as per
- * definition of a base32 string. This is a macro to allow users to define
- * buffer size at compilation time.
- */
-#define UNBASE32_LEN(len) (((len)/8)*5)
-
-/**
- * Encode the data pointed to by plain into base32 and store the
- * result at the address pointed to by coded. The "coded" argument
- * must point to a location that has enough available space
- * to store the whole coded string. The resulting string will only
- * contain characters from the [A-Z2-7=] set. The "len" arguments
- * define how many bytes will be read from the "plain" buffer.
- **/
-void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded);
-
-/**
- * Decode the null terminated string pointed to by coded and write
- * the decoded data into the location pointed to by plain. The
- * "plain" argument must point to a location that has enough available
- * space to store the whole decoded string.
- * Returns the length of the decoded string. This may be less than
- * expected due to padding. If an invalid base32 character is found
- * in the coded string, decoding will stop at that point.
- **/
-size_t base32_decode(const unsigned char *coded, unsigned char *plain);
-
-#endif
+++ /dev/null
-/* SPDX-License-Identifier: MIT */
-
-/*
- * MIT License
- *
- * Copyright © 2021 Wesley Ellis (https://github.com/tahnok)
- * Copyright © 2021-2023 Joey Castillo <joeycastillo@utexas.edu>
- * Copyright © 2022 Jack Bond-Preston <jackbondpreston@outlook.com>
- * Copyright © 2023 Alex Utter <ooterness@gmail.com>
- * Copyright © 2023 Emilien Court <emilien.court@telecomnancy.net>
- * Copyright © 2023 Jeremy O'Brien <neutral@fastmail.com>
- * Copyright © 2024 Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com> (https://www.matheusmoreira.com/)
- * Copyright © 2024 Max Zettlmeißl <max@zettlmeissl.de>
- *
- * 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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "totp_face.h"
-#include "watch.h"
-#include "watch_utility.h"
-#include "TOTP.h"
-#include "base32.h"
-
-#ifndef TOTP_FACE_MAX_KEY_LENGTH
-#define TOTP_FACE_MAX_KEY_LENGTH 128
-#endif
-
-typedef struct {
- unsigned char labels[2];
- hmac_alg algorithm;
- uint32_t period;
- size_t encoded_key_length;
- unsigned char *encoded_key;
-} totp_t;
-
-#define CREDENTIAL(label, key_array, algo, timestep) \
- (const totp_t) { \
- .encoded_key = ((unsigned char *) key_array), \
- .encoded_key_length = sizeof(key_array) - 1, \
- .period = (timestep), \
- .labels = (#label), \
- .algorithm = (algo), \
- }
-
-////////////////////////////////////////////////////////////////////////////////
-// Enter your TOTP key data below
-
-static totp_t credentials[] = {
- CREDENTIAL(2F, "JBSWY3DPEHPK3PXP", SHA1, 30),
- CREDENTIAL(AC, "JBSWY3DPEHPK3PXP", SHA1, 30),
-};
-
-// END OF KEY DATA.
-////////////////////////////////////////////////////////////////////////////////
-
-static inline totp_t *totp_at(size_t i) {
- return &credentials[i];
-}
-
-static inline totp_t *totp_current(totp_state_t *totp_state) {
- return totp_at(totp_state->current_index);
-}
-
-static inline size_t totp_total(void) {
- return sizeof(credentials) / sizeof(*credentials);
-}
-
-static void totp_validate_key_lengths(void) {
- for (size_t n = totp_total(), i = 0; i < n; ++i) {
- totp_t *totp = totp_at(i);
-
- if (UNBASE32_LEN(totp->encoded_key_length) > TOTP_FACE_MAX_KEY_LENGTH) {
- // Key exceeds static limits, turn it off by zeroing the length
- totp->encoded_key_length = 0;
- }
- }
-}
-
-static void totp_generate(totp_state_t *totp_state) {
- totp_t *totp = totp_current(totp_state);
-
- if (totp->encoded_key_length <= 0) {
- // Key exceeded static limits and was turned off
- totp_state->current_decoded_key_length = 0;
- return;
- }
-
- totp_state->current_decoded_key_length = base32_decode(totp->encoded_key, totp_state->current_decoded_key);
-
- if (totp_state->current_decoded_key_length == 0) {
- // Decoding failed for some reason
- // Not a base 32 string?
- return;
- }
-
- TOTP(
- totp_state->current_decoded_key,
- totp_state->current_decoded_key_length,
- totp->period,
- totp->algorithm
- );
-}
-
-static void totp_display_error(totp_state_t *totp_state) {
- char buf[10 + 1];
- totp_t *totp = totp_current(totp_state);
-
- snprintf(buf, sizeof(buf), "%c%c ERROR ", totp->labels[0], totp->labels[1]);
- watch_display_string(buf, 0);
-}
-
-static void totp_display_code(totp_state_t *totp_state) {
- char buf[14];
- div_t result;
- uint8_t valid_for;
- totp_t *totp = totp_current(totp_state);
-
- result = div(totp_state->timestamp, totp->period);
- if (result.quot != totp_state->steps) {
- totp_state->current_code = getCodeFromTimestamp(totp_state->timestamp);
- totp_state->steps = result.quot;
- }
- valid_for = totp->period - result.rem;
- sprintf(buf, "%c%c%2d%06lu", totp->labels[0], totp->labels[1], valid_for, totp_state->current_code);
-
- watch_display_string(buf, 0);
-}
-
-static void totp_display(totp_state_t *totp_state) {
- if (totp_state->current_decoded_key_length > 0) {
- totp_display_code(totp_state);
- } else {
- totp_display_error(totp_state);
- }
-}
-
-static void totp_generate_and_display(totp_state_t *totp_state) {
- totp_generate(totp_state);
- totp_display(totp_state);
-}
-
-static inline uint32_t totp_compute_base_timestamp() {
- return watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_get_current_timezone_offset());
-}
-
-void totp_face_setup(uint8_t watch_face_index, void ** context_ptr) {
- (void) watch_face_index;
-
- totp_validate_key_lengths();
-
- if (*context_ptr == NULL) {
- totp_state_t *totp = malloc(sizeof(totp_state_t));
- totp->current_decoded_key = malloc(TOTP_FACE_MAX_KEY_LENGTH);
- *context_ptr = totp;
- }
-}
-
-void totp_face_activate(void *context) {
-
- totp_state_t *totp = (totp_state_t *) context;
-
- totp->timestamp = totp_compute_base_timestamp();
- totp->steps = 0;
- totp->current_code = 0;
- totp->current_index = 0;
- totp->current_decoded_key_length = 0;
- // totp->current_decoded_key is already initialized in setup
-
- totp_generate_and_display(totp);
-}
-
-bool totp_face_loop(movement_event_t event, void *context) {
-
- totp_state_t *totp_state = (totp_state_t *) context;
-
- switch (event.event_type) {
- case EVENT_TICK:
- totp_state->timestamp++;
- // fall through
- case EVENT_ACTIVATE:
- totp_display(totp_state);
- break;
- case EVENT_TIMEOUT:
- movement_move_to_face(0);
- break;
- case EVENT_ALARM_BUTTON_UP:
- if ((size_t)totp_state->current_index + 1 < totp_total()) {
- totp_state->current_index++;
- } else {
- // wrap around to first key
- totp_state->current_index = 0;
- }
-
- totp_generate_and_display(totp_state);
-
- break;
- case EVENT_LIGHT_BUTTON_UP:
- if (totp_state->current_index == 0) {
- // Wrap around to the last credential.
- totp_state->current_index = totp_total() - 1;
- } else {
- totp_state->current_index--;
- }
-
- totp_generate_and_display(totp_state);
-
- break;
- case EVENT_ALARM_BUTTON_DOWN:
- case EVENT_ALARM_LONG_PRESS:
- case EVENT_LIGHT_BUTTON_DOWN:
- break;
- case EVENT_LIGHT_LONG_PRESS:
- movement_illuminate_led();
- break;
- default:
- movement_default_loop_handler(event);
- break;
- }
-
- return true;
-}
-
-void totp_face_resign(void *context) {
- (void) context;
-}
+++ /dev/null
-/* SPDX-License-Identifier: MIT */
-
-/*
- * MIT License
- *
- * Copyright © 2021 Wesley Ellis (https://github.com/tahnok)
- * Copyright © 2021-2022 Joey Castillo <joeycastillo@utexas.edu>
- * Copyright © 2022 Alexsander Akers <me@a2.io>
- * Copyright © 2022 Jack Bond-Preston <jackbondpreston@outlook.com>
- * Copyright © 2023 Alex Utter <ooterness@gmail.com>
- * Copyright © 2024 Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com> (https://www.matheusmoreira.com/)
- * Copyright © 2024 Max Zettlmeißl <max@zettlmeissl.de>
- *
- * 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.
- */
-
-#ifndef TOTP_FACE_H_
-#define TOTP_FACE_H_
-
-/*
- * TOTP face
- * Time-based one-time password (TOTP) generator
- *
- * Generate one-time passwords often used for two-factor authentication.
- * The secret key must be set by hand, by editing "totp_face.c".
- *
- * Available algorithms:
- * o SHA1 (most TOTP codes use this)
- * o SHA224
- * o SHA256
- * o SHA384
- * o SHA512
- *
- * Instructions:
- * o Find your secret key(s).
- * o Use https://github.com/susam/mintotp to generate test codes for
- * verification
- * o Edit global `credentials` variable in "totp_face.c" to configure your
- * TOTP credentials. The file includes two examples that you can use as a
- * reference. Credentials are added with the `CREDENTIAL` macro in the form
- * `CREDENTIAL(label, key, algorithm, timestep)` where:
- * o `label` is a 2 character label that is displayed in the weekday digits
- * to identify the TOTP credential.
- * o `key` is a string with the base32 encoded secret.
- * o `algorithm` is one of the supported hashing algorithms listed above.
- * o `timestep` is how often the TOTP refreshes in seconds. This is usually
- * 30 seconds.
- *
- * If you have more than one secret key, press ALARM to cycle through them.
- * Press LIGHT to cycle in the other direction or keep it pressed longer to
- * activate the light.
- */
-
-#include "movement.h"
-
-typedef struct {
- uint32_t timestamp;
- uint8_t steps;
- uint32_t current_code;
- uint8_t current_index;
- uint8_t *current_decoded_key;
- size_t current_decoded_key_length;
-} totp_state_t;
-
-void totp_face_setup(uint8_t watch_face_index, void ** context_ptr);
-void totp_face_activate(void *context);
-bool totp_face_loop(movement_event_t event, void *context);
-void totp_face_resign(void *context);
-
-#define totp_face ((const watch_face_t){ \
- totp_face_setup, \
- totp_face_activate, \
- totp_face_loop, \
- totp_face_resign, \
- NULL, \
-})
-
-#endif // TOTP_FACE_H_
--- /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 __attribute__ ((__packed__)) {\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
--- /dev/null
+/**
+ * base32 (de)coder implementation as specified by RFC4648.
+ *
+ * Copyright (c) 2010 Adrien Kunysz
+ *
+ * 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.
+ **/
+
+#include <assert.h> // assert()
+#include <limits.h> // CHAR_BIT
+
+#include "base32.h"
+
+/**
+ * Let this be a sequence of plain data before encoding:
+ *
+ * 01234567 01234567 01234567 01234567 01234567
+ * +--------+--------+--------+--------+--------+
+ * |< 0 >< 1| >< 2 ><|.3 >< 4.|>< 5 ><.|6 >< 7 >|
+ * +--------+--------+--------+--------+--------+
+ *
+ * There are 5 octets of 8 bits each in each sequence.
+ * There are 8 blocks of 5 bits each in each sequence.
+ *
+ * You probably want to refer to that graph when reading the algorithms in this
+ * file. We use "octet" instead of "byte" intentionnaly as we really work with
+ * 8 bits quantities. This implementation will probably not work properly on
+ * systems that don't have exactly 8 bits per (unsigned) char.
+ **/
+
+static size_t min(size_t x, size_t y)
+{
+ return x < y ? x : y;
+}
+
+static const unsigned char PADDING_CHAR = '=';
+
+/**
+ * Pad the given buffer with len padding characters.
+ */
+static void pad(unsigned char *buf, int len)
+{
+ for (int i = 0; i < len; i++)
+ buf[i] = PADDING_CHAR;
+}
+
+/**
+ * This convert a 5 bits value into a base32 character.
+ * Only the 5 least significant bits are used.
+ */
+static unsigned char encode_char(unsigned char c)
+{
+ static unsigned char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+ return base32[c & 0x1F]; // 0001 1111
+}
+
+/**
+ * Decode given character into a 5 bits value.
+ * Returns -1 iff the argument given was an invalid base32 character
+ * or a padding character.
+ */
+static int decode_char(unsigned char c)
+{
+ int retval = -1;
+
+ if (c >= 'A' && c <= 'Z')
+ retval = c - 'A';
+ if (c >= '2' && c <= '7')
+ retval = c - '2' + 26;
+
+ assert(retval == -1 || ((retval & 0x1F) == retval));
+
+ return retval;
+}
+
+/**
+ * Given a block id between 0 and 7 inclusive, this will return the index of
+ * the octet in which this block starts. For example, given 3 it will return 1
+ * because block 3 starts in octet 1:
+ *
+ * +--------+--------+
+ * | ......<|.3 >....|
+ * +--------+--------+
+ * octet 1 | octet 2
+ */
+static int get_octet(int block)
+{
+ assert(block >= 0 && block < 8);
+ return (block*5) / 8;
+}
+
+/**
+ * Given a block id between 0 and 7 inclusive, this will return how many bits
+ * we can drop at the end of the octet in which this block starts.
+ * For example, given block 0 it will return 3 because there are 3 bits
+ * we don't care about at the end:
+ *
+ * +--------+-
+ * |< 0 >...|
+ * +--------+-
+ *
+ * Given block 1, it will return -2 because there
+ * are actually two bits missing to have a complete block:
+ *
+ * +--------+-
+ * |.....< 1|..
+ * +--------+-
+ **/
+static int get_offset(int block)
+{
+ assert(block >= 0 && block < 8);
+ return (8 - 5 - (5*block) % 8);
+}
+
+/**
+ * Like "b >> offset" but it will do the right thing with negative offset.
+ * We need this as bitwise shifting by a negative offset is undefined
+ * behavior.
+ */
+static unsigned char shift_right(unsigned char byte, int offset)
+{
+ if (offset > 0)
+ return byte >> offset;
+ else
+ return byte << -offset;
+}
+
+static unsigned char shift_left(unsigned char byte, int offset)
+{
+ return shift_right(byte, - offset);
+}
+
+/**
+ * Encode a sequence. A sequence is no longer than 5 octets by definition.
+ * Thus passing a length greater than 5 to this function is an error. Encoding
+ * sequences shorter than 5 octets is supported and padding will be added to the
+ * output as per the specification.
+ */
+static void encode_sequence(const unsigned char *plain, int len, unsigned char *coded)
+{
+ assert(CHAR_BIT == 8); // not sure this would work otherwise
+ assert(len >= 0 && len <= 5);
+
+ for (int block = 0; block < 8; block++) {
+ int octet = get_octet(block); // figure out which octet this block starts in
+ int junk = get_offset(block); // how many bits do we drop from this octet?
+
+ if (octet >= len) { // we hit the end of the buffer
+ pad(&coded[block], 8 - block);
+ return;
+ }
+
+ unsigned char c = shift_right(plain[octet], junk); // first part
+
+ if (junk < 0 // is there a second part?
+ && octet < len - 1) // is there still something to read?
+ {
+ c |= shift_right(plain[octet+1], 8 + junk);
+ }
+ coded[block] = encode_char(c);
+ }
+}
+
+void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded)
+{
+ // All the hard work is done in encode_sequence(),
+ // here we just need to feed it the data sequence by sequence.
+ for (size_t i = 0, j = 0; i < len; i += 5, j += 8) {
+ encode_sequence(&plain[i], min(len - i, 5), &coded[j]);
+ }
+}
+
+static int decode_sequence(const unsigned char *coded, unsigned char *plain)
+{
+ assert(CHAR_BIT == 8);
+ assert(coded && plain);
+
+ plain[0] = 0;
+ for (int block = 0; block < 8; block++) {
+ int offset = get_offset(block);
+ int octet = get_octet(block);
+
+ int c = decode_char(coded[block]);
+ if (c < 0) // invalid char, stop here
+ return octet;
+
+ plain[octet] |= shift_left(c, offset);
+ if (offset < 0) { // does this block overflows to next octet?
+ assert(octet < 4);
+ plain[octet+1] = shift_left(c, 8 + offset);
+ }
+ }
+ return 5;
+}
+
+size_t base32_decode(const unsigned char *coded, unsigned char *plain)
+{
+ size_t written = 0;
+ for (size_t i = 0, j = 0; ; i += 8, j += 5) {
+ int n = decode_sequence(&coded[i], &plain[j]);
+ written += n;
+ if (n < 5)
+ return written;
+ }
+}
--- /dev/null
+/**
+ * base32 (de)coder implementation as specified by RFC4648.
+ *
+ * Copyright (c) 2010 Adrien Kunysz
+ *
+ * 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.
+ **/
+
+#ifndef __BASE32_H_
+#define __BASE32_H_
+
+#include <stddef.h> // size_t
+
+/**
+ * Returns the length of the output buffer required to encode len bytes of
+ * data into base32. This is a macro to allow users to define buffer size at
+ * compilation time.
+ */
+#define BASE32_LEN(len) (((len)/5)*8 + ((len) % 5 ? 8 : 0))
+
+/**
+ * Returns the length of the output buffer required to decode a base32 string
+ * of len characters. Please note that len must be a multiple of 8 as per
+ * definition of a base32 string. This is a macro to allow users to define
+ * buffer size at compilation time.
+ */
+#define UNBASE32_LEN(len) (((len)/8)*5)
+
+/**
+ * Encode the data pointed to by plain into base32 and store the
+ * result at the address pointed to by coded. The "coded" argument
+ * must point to a location that has enough available space
+ * to store the whole coded string. The resulting string will only
+ * contain characters from the [A-Z2-7=] set. The "len" arguments
+ * define how many bytes will be read from the "plain" buffer.
+ **/
+void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded);
+
+/**
+ * Decode the null terminated string pointed to by coded and write
+ * the decoded data into the location pointed to by plain. The
+ * "plain" argument must point to a location that has enough available
+ * space to store the whole decoded string.
+ * Returns the length of the decoded string. This may be less than
+ * expected due to padding. If an invalid base32 character is found
+ * in the coded string, decoding will stop at that point.
+ **/
+size_t base32_decode(const unsigned char *coded, unsigned char *plain);
+
+#endif
#include "nanosec_face.h"
#include "mars_time_face.h"
#include "peek_memory_face.h"
+#include "totp_face.h"
// New includes go above this line.
./watch-faces/complication/sunrise_sunset_face.c \
./watch-faces/complication/moon_phase_face.c \
./watch-faces/complication/days_since_face.c \
+ ./watch-faces/complication/totp_face.c \
./watch-faces/demo/all_segments_face.c \
./watch-faces/demo/character_set_face.c \
./watch-faces/demo/light_sensor_face.c \
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * MIT License
+ *
+ * Copyright © 2021 Wesley Ellis (https://github.com/tahnok)
+ * Copyright © 2021-2023 Joey Castillo <joeycastillo@utexas.edu>
+ * Copyright © 2022 Jack Bond-Preston <jackbondpreston@outlook.com>
+ * Copyright © 2023 Alex Utter <ooterness@gmail.com>
+ * Copyright © 2023 Emilien Court <emilien.court@telecomnancy.net>
+ * Copyright © 2023 Jeremy O'Brien <neutral@fastmail.com>
+ * Copyright © 2024 Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com> (https://www.matheusmoreira.com/)
+ * Copyright © 2024 Max Zettlmeißl <max@zettlmeissl.de>
+ * Copyright © 2025 Emilien Court <emilien.court@telecomnancy.net>
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "totp_face.h"
+#include "watch.h"
+#include "watch_utility.h"
+#include "TOTP.h"
+#include "base32.h"
+
+#ifndef TOTP_FACE_MAX_KEY_LENGTH
+#define TOTP_FACE_MAX_KEY_LENGTH 128
+#endif
+
+typedef struct {
+ unsigned char labels[2];
+ hmac_alg algorithm;
+ uint32_t period;
+ size_t encoded_key_length;
+ unsigned char *encoded_key;
+} totp_t;
+
+#define CREDENTIAL(label, key_array, algo, timestep) \
+ (const totp_t) { \
+ .encoded_key = ((unsigned char *) key_array), \
+ .encoded_key_length = sizeof(key_array) - 1, \
+ .period = (timestep), \
+ .labels = (#label), \
+ .algorithm = (algo), \
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// Enter your TOTP key data below
+
+static totp_t credentials[] = {
+ CREDENTIAL(2F, "JBSWY3DPEHPK3PXP", SHA1, 30),
+ CREDENTIAL(AC, "JBSWY3DPEHPK3PXP", SHA1, 30),
+};
+
+// END OF KEY DATA.
+////////////////////////////////////////////////////////////////////////////////
+
+static inline totp_t *totp_at(size_t i) {
+ return &credentials[i];
+}
+
+static inline totp_t *totp_current(totp_state_t *totp_state) {
+ return totp_at(totp_state->current_index);
+}
+
+static inline size_t totp_total(void) {
+ return sizeof(credentials) / sizeof(*credentials);
+}
+
+static void totp_validate_key_lengths(void) {
+ for (size_t n = totp_total(), i = 0; i < n; ++i) {
+ totp_t *totp = totp_at(i);
+
+ if (UNBASE32_LEN(totp->encoded_key_length) > TOTP_FACE_MAX_KEY_LENGTH) {
+ // Key exceeds static limits, turn it off by zeroing the length
+ totp->encoded_key_length = 0;
+ }
+ }
+}
+
+static void totp_generate(totp_state_t *totp_state) {
+ totp_t *totp = totp_current(totp_state);
+
+ if (totp->encoded_key_length <= 0) {
+ // Key exceeded static limits and was turned off
+ totp_state->current_decoded_key_length = 0;
+ return;
+ }
+
+ totp_state->current_decoded_key_length = base32_decode(totp->encoded_key, totp_state->current_decoded_key);
+
+ if (totp_state->current_decoded_key_length == 0) {
+ // Decoding failed for some reason
+ // Not a base 32 string?
+ return;
+ }
+
+ TOTP(
+ totp_state->current_decoded_key,
+ totp_state->current_decoded_key_length,
+ totp->period,
+ totp->algorithm
+ );
+}
+
+static void totp_display_error(totp_state_t *totp_state) {
+ char buf[10 + 1];
+ totp_t *totp = totp_current(totp_state);
+
+ snprintf(buf, sizeof(buf), "%c%c ERROR ", totp->labels[0], totp->labels[1]);
+ watch_display_text(0, buf);
+}
+
+static void totp_display_code(totp_state_t *totp_state) {
+ char buf[14];
+ div_t result;
+ uint8_t valid_for;
+ totp_t *totp = totp_current(totp_state);
+
+ result = div(totp_state->timestamp, totp->period);
+ if (result.quot != totp_state->steps) {
+ totp_state->current_code = getCodeFromTimestamp(totp_state->timestamp);
+ totp_state->steps = result.quot;
+ }
+ valid_for = totp->period - result.rem;
+ sprintf(buf, "%c%c%2d%06lu", totp->labels[0], totp->labels[1], valid_for, totp_state->current_code);
+
+ watch_display_text(0, buf);
+}
+
+static void totp_display(totp_state_t *totp_state) {
+ if (totp_state->current_decoded_key_length > 0) {
+ totp_display_code(totp_state);
+ } else {
+ totp_display_error(totp_state);
+ }
+}
+
+static void totp_generate_and_display(totp_state_t *totp_state) {
+ totp_generate(totp_state);
+ totp_display(totp_state);
+}
+
+static inline uint32_t totp_compute_base_timestamp() {
+ return watch_utility_date_time_to_unix_time(movement_get_utc_date_time(), 0);
+}
+
+void totp_face_setup(uint8_t watch_face_index, void ** context_ptr) {
+ (void) watch_face_index;
+
+ totp_validate_key_lengths();
+
+ if (*context_ptr == NULL) {
+ totp_state_t *totp = malloc(sizeof(totp_state_t));
+ totp->current_decoded_key = malloc(TOTP_FACE_MAX_KEY_LENGTH);
+ *context_ptr = totp;
+ }
+}
+
+void totp_face_activate(void *context) {
+
+ totp_state_t *totp = (totp_state_t *) context;
+
+ totp->timestamp = totp_compute_base_timestamp();
+ totp->steps = 0;
+ totp->current_code = 0;
+ totp->current_index = 0;
+ totp->current_decoded_key_length = 0;
+ // totp->current_decoded_key is already initialized in setup
+
+ totp_generate_and_display(totp);
+}
+
+bool totp_face_loop(movement_event_t event, void *context) {
+
+ totp_state_t *totp_state = (totp_state_t *) context;
+
+ switch (event.event_type) {
+ case EVENT_TICK:
+ totp_state->timestamp++;
+ // fall through
+ case EVENT_ACTIVATE:
+ totp_display(totp_state);
+ break;
+ case EVENT_TIMEOUT:
+ movement_move_to_face(0);
+ break;
+ case EVENT_ALARM_BUTTON_UP:
+ if ((size_t)totp_state->current_index + 1 < totp_total()) {
+ totp_state->current_index++;
+ } else {
+ // wrap around to first key
+ totp_state->current_index = 0;
+ }
+
+ totp_generate_and_display(totp_state);
+
+ break;
+ case EVENT_LIGHT_BUTTON_UP:
+ if (totp_state->current_index == 0) {
+ // Wrap around to the last credential.
+ totp_state->current_index = totp_total() - 1;
+ } else {
+ totp_state->current_index--;
+ }
+
+ totp_generate_and_display(totp_state);
+
+ break;
+ case EVENT_ALARM_BUTTON_DOWN:
+ case EVENT_ALARM_LONG_PRESS:
+ case EVENT_LIGHT_BUTTON_DOWN:
+ break;
+ case EVENT_LIGHT_LONG_PRESS:
+ movement_illuminate_led();
+ break;
+ default:
+ movement_default_loop_handler(event);
+ break;
+ }
+
+ return true;
+}
+
+void totp_face_resign(void *context) {
+ (void) context;
+}
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * MIT License
+ *
+ * Copyright © 2021 Wesley Ellis (https://github.com/tahnok)
+ * Copyright © 2021-2022 Joey Castillo <joeycastillo@utexas.edu>
+ * Copyright © 2022 Alexsander Akers <me@a2.io>
+ * Copyright © 2022 Jack Bond-Preston <jackbondpreston@outlook.com>
+ * Copyright © 2023 Alex Utter <ooterness@gmail.com>
+ * Copyright © 2024 Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com> (https://www.matheusmoreira.com/)
+ * Copyright © 2024 Max Zettlmeißl <max@zettlmeissl.de>
+ *
+ * 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.
+ */
+
+#ifndef TOTP_FACE_H_
+#define TOTP_FACE_H_
+
+/*
+ * TOTP face
+ * Time-based one-time password (TOTP) generator
+ *
+ * Generate one-time passwords often used for two-factor authentication.
+ * The secret key must be set by hand, by editing "totp_face.c".
+ *
+ * Available algorithms:
+ * o SHA1 (most TOTP codes use this)
+ * o SHA224
+ * o SHA256
+ * o SHA384
+ * o SHA512
+ *
+ * Instructions:
+ * o Find your secret key(s).
+ * o Use https://github.com/susam/mintotp to generate test codes for
+ * verification
+ * o Edit global `credentials` variable in "totp_face.c" to configure your
+ * TOTP credentials. The file includes two examples that you can use as a
+ * reference. Credentials are added with the `CREDENTIAL` macro in the form
+ * `CREDENTIAL(label, key, algorithm, timestep)` where:
+ * o `label` is a 2 character label that is displayed in the weekday digits
+ * to identify the TOTP credential.
+ * o `key` is a string with the base32 encoded secret.
+ * o `algorithm` is one of the supported hashing algorithms listed above.
+ * o `timestep` is how often the TOTP refreshes in seconds. This is usually
+ * 30 seconds.
+ *
+ * If you have more than one secret key, press ALARM to cycle through them.
+ * Press LIGHT to cycle in the other direction or keep it pressed longer to
+ * activate the light.
+ */
+
+#include "movement.h"
+
+typedef struct {
+ uint32_t timestamp;
+ uint8_t steps;
+ uint32_t current_code;
+ uint8_t current_index;
+ uint8_t *current_decoded_key;
+ size_t current_decoded_key_length;
+} totp_state_t;
+
+void totp_face_setup(uint8_t watch_face_index, void ** context_ptr);
+void totp_face_activate(void *context);
+bool totp_face_loop(movement_event_t event, void *context);
+void totp_face_resign(void *context);
+
+#define totp_face ((const watch_face_t){ \
+ totp_face_setup, \
+ totp_face_activate, \
+ totp_face_loop, \
+ totp_face_resign, \
+ NULL, \
+})
+
+#endif // TOTP_FACE_H_