bring totp_face into Second Movement

This commit is contained in:
EmilienCourt
2025-06-29 19:25:42 +02:00
parent e3101749c9
commit 67a1bfd661
18 changed files with 16 additions and 3 deletions

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,68 +0,0 @@
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

View File

@ -1,69 +0,0 @@
#include "TOTP.h"
#include "sha1.h"
#include "sha256.h"
#include "sha512.h"
#include <stdio.h>
uint8_t* _hmacKey;
uint8_t _keyLength;
uint8_t _timeZoneOffset;
uint32_t _timeStep;
hmac_alg _algorithm;
// Init the library with the private key, its length, the timeStep duration and the algorithm that should be used
void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep, hmac_alg algorithm) {
_hmacKey = hmacKey;
_keyLength = keyLength;
_timeStep = timeStep;
_algorithm = algorithm;
}
void setTimezone(uint8_t timezone){
_timeZoneOffset = timezone;
}
static uint32_t TimeStruct2Timestamp(struct tm time){
//time.tm_mon -= 1;
//time.tm_year -= 1900;
return mktime(&(time)) - (_timeZoneOffset * 3600) - 2208988800;
}
// Generate a code, using the timestamp provided
uint32_t getCodeFromTimestamp(uint32_t timeStamp) {
uint32_t steps = timeStamp / _timeStep;
return getCodeFromSteps(steps);
}
// Generate a code, using the timestamp provided
uint32_t getCodeFromTimeStruct(struct tm time) {
return getCodeFromTimestamp(TimeStruct2Timestamp(time));
}
// Generate a code, using the number of steps provided
uint32_t getCodeFromSteps(uint32_t steps) {
// STEP 0, map the number of steps in a 8-bytes array (counter value)
uint8_t _byteArray[8];
_byteArray[0] = 0x00;
_byteArray[1] = 0x00;
_byteArray[2] = 0x00;
_byteArray[3] = 0x00;
_byteArray[4] = (uint8_t)((steps >> 24) & 0xFF);
_byteArray[5] = (uint8_t)((steps >> 16) & 0xFF);
_byteArray[6] = (uint8_t)((steps >> 8) & 0XFF);
_byteArray[7] = (uint8_t)((steps & 0XFF));
switch(_algorithm){
case SHA1:
return(TOTP_HMAC_SHA1(_hmacKey, _keyLength, _byteArray, 8));
case SHA224:
return(TOTP_HMAC_SHA256(_hmacKey, _keyLength, _byteArray, 8, 1));
case SHA256:
return(TOTP_HMAC_SHA256(_hmacKey, _keyLength, _byteArray, 8, 0));
case SHA384:
return(TOTP_HMAC_SHA512(_hmacKey, _keyLength, _byteArray, 8, 1));
case SHA512:
return(TOTP_HMAC_SHA512(_hmacKey, _keyLength, _byteArray, 8, 0));
default:
return(0);
}
}

View File

@ -1,21 +0,0 @@
#ifndef TOTP_H_
#define TOTP_H_
#include <inttypes.h>
#include "time.h"
typedef enum __attribute__ ((__packed__)) {
SHA1,
SHA224,
SHA256,
SHA384,
SHA512
} hmac_alg;
void TOTP(uint8_t* hmacKey, uint8_t keyLength, uint32_t timeStep, hmac_alg algorithm);
void setTimezone(uint8_t timezone);
uint32_t getCodeFromTimestamp(uint32_t timeStamp);
uint32_t getCodeFromTimeStruct(struct tm time);
uint32_t getCodeFromSteps(uint32_t steps);
#endif // TOTP_H_

View File

@ -1,27 +0,0 @@
#include "TOTP.h"
#include <stdio.h>
/**
* example.c
*/
void main(void)
{
uint8_t hmacKey[] = {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72}; // Secret key
TOTP(hmacKey, 10, 7200, SHA1); // Secret key, Key length, Timestep (7200s - 2hours)
setTimezone(9); // Set timezone
uint32_t newCode = getCodeFromTimestamp(1557414000); // Timestamp Now
///////////////// For struct tm //////////////////
// 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);
///////////////////////////////////////////////////
printf("Code : %06u\n",newCode);
}

View File

@ -1,398 +0,0 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "sha1.h"
#include <string.h>
#include <stdio.h>
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
}
/*
* SHA-1 context setup
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[SHA1_BLOCK_LENGTH] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[SHA1_BLOCK_LENGTH] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[SHA1_DIGEST_LENGTH] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha1_update( ctx, sha1_padding, padn );
mbedtls_sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
/*
* output = SHA-1( input buffer )
*/
void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[SHA1_DIGEST_LENGTH] )
{
mbedtls_sha1_context ctx;
mbedtls_sha1_init( &ctx );
mbedtls_sha1_starts( &ctx );
mbedtls_sha1_update( &ctx, input, ilen );
mbedtls_sha1_finish( &ctx, output );
mbedtls_sha1_free( &ctx );
}
/*
* Compute HMAC_SHA1 using key, key length, text to hash, size of the text, and output buffer
*/
void HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t out[SHA1_DIGEST_LENGTH]){
uint8_t i;
uint8_t k_ipad[SHA1_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */
uint8_t k_opad[SHA1_BLOCK_LENGTH]; /* outer padding - key XORd with opad */
uint8_t buffer[SHA1_BLOCK_LENGTH + SHA1_DIGEST_LENGTH];
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
if (key_length <= SHA1_BLOCK_LENGTH) {
memcpy(k_ipad, key, key_length);
memcpy(k_opad, key, key_length);
}
else {
mbedtls_sha1(key, key_length, k_ipad);
memcpy(k_opad, k_ipad, SHA1_BLOCK_LENGTH);
}
/* XOR key with ipad and opad values */
for (i = 0; i < SHA1_BLOCK_LENGTH; i++) {
k_ipad[i] ^= HMAC_IPAD;
k_opad[i] ^= HMAC_OPAD;
}
// perform inner SHA1
memcpy(buffer, k_ipad, SHA1_BLOCK_LENGTH);
memcpy(buffer + SHA1_BLOCK_LENGTH, in, n);
mbedtls_sha1(buffer, SHA1_BLOCK_LENGTH + n, out);
memset(buffer, 0, SHA1_BLOCK_LENGTH + n);
// perform outer SHA1
memcpy(buffer, k_opad, SHA1_BLOCK_LENGTH);
memcpy(buffer + SHA1_BLOCK_LENGTH, out, SHA1_DIGEST_LENGTH);
mbedtls_sha1(buffer, SHA1_BLOCK_LENGTH + SHA1_DIGEST_LENGTH, out);
}
/*
* Compute TOTP_HMAC_SHA1 using key, key length, text to hash, size of the text
*/
uint32_t TOTP_HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n){
// STEP 1, get the HMAC-SHA1 hash from counter and key
uint8_t hash[SHA1_DIGEST_LENGTH];
HMAC_SHA1(key, key_length, in, n, hash);
// STEP 2, apply dynamic truncation to obtain a 4-bytes string
uint32_t truncated_hash = 0;
uint8_t _offset = hash[SHA1_DIGEST_LENGTH - 1] & 0xF;
uint8_t j;
for (j = 0; j < 4; ++j) {
truncated_hash <<= 8;
truncated_hash |= hash[_offset + j];
}
// STEP 3, compute the OTP value
truncated_hash &= 0x7FFFFFFF; //Disabled
truncated_hash %= 1000000;
return truncated_hash;
}

View File

@ -1,98 +0,0 @@
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA1_H
#define MBEDTLS_SHA1_H
#define SHA1_DIGEST_LENGTH 20
#define SHA1_BLOCK_LENGTH 64
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
#include <stddef.h>
#include <stdint.h>
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[SHA1_BLOCK_LENGTH]; /*!< data block being processed */
}
mbedtls_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[SHA1_DIGEST_LENGTH] );
/* Internal use */
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[SHA1_BLOCK_LENGTH] );
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[SHA1_DIGEST_LENGTH] );
void HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t out[SHA1_DIGEST_LENGTH]);
uint32_t TOTP_HMAC_SHA1(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n);
#endif /* mbedtls_sha1.h */

View File

@ -1,372 +0,0 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "sha256.h"
#include <string.h>
#include <stdio.h>
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
static const uint32_t K[] =
{
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_LENGTH] )
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
for( i = 0; i < 16; i++ )
GET_UINT32_BE( W[i], data, 4 * i );
for( i = 0; i < 16; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
}
for( i = 16; i < 64; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
}
for( i = 0; i < 8; i++ )
ctx->state[i] += A[i];
}
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha256_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha256_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha256_padding[SHA256_BLOCK_LENGTH] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char* output )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_update( ctx, sha256_padding, padn );
mbedtls_sha256_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
/*
* output = SHA-256( input buffer )
*/
void mbedtls_sha256( const unsigned char *input, size_t ilen,
unsigned char* output, int is224 )
{
mbedtls_sha256_context ctx;
mbedtls_sha256_init( &ctx );
mbedtls_sha256_starts( &ctx, is224 );
mbedtls_sha256_update( &ctx, input, ilen );
mbedtls_sha256_finish( &ctx, output );
mbedtls_sha256_free( &ctx );
}
/*
* Compute HMAC_SHA224/256 using key, key length, text to hash, size of the text, output buffer and a switch for SHA224
*/
void HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is224){
int digest_length = SHA256_DIGEST_LENGTH;
if (is224 == 1) {
digest_length = SHA224_DIGEST_LENGTH;
}
uint8_t i;
uint8_t k_ipad[SHA256_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */
uint8_t k_opad[SHA256_BLOCK_LENGTH]; /* outer padding - key XORd with opad */
uint8_t buffer[SHA256_BLOCK_LENGTH + digest_length];
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
if (key_length <= SHA256_BLOCK_LENGTH) {
memcpy(k_ipad, key, key_length);
memcpy(k_opad, key, key_length);
}
else {
mbedtls_sha256(key, key_length, k_ipad, is224);
memcpy(k_opad, k_ipad, SHA256_BLOCK_LENGTH);
}
/* XOR key with ipad and opad values */
for (i = 0; i < SHA256_BLOCK_LENGTH; i++) {
k_ipad[i] ^= HMAC_IPAD;
k_opad[i] ^= HMAC_OPAD;
}
// perform inner SHA256
memcpy(buffer, k_ipad, SHA256_BLOCK_LENGTH);
memcpy(buffer + SHA256_BLOCK_LENGTH, in, n);
mbedtls_sha256(buffer, SHA256_BLOCK_LENGTH + n, out, is224);
memset(buffer, 0, SHA256_BLOCK_LENGTH + n);
// perform outer SHA256
memcpy(buffer, k_opad, SHA256_BLOCK_LENGTH);
memcpy(buffer + SHA256_BLOCK_LENGTH, out, digest_length);
mbedtls_sha256(buffer, SHA256_BLOCK_LENGTH + digest_length, out, is224);
}
/*
* Compute TOTP_HMAC_SHA224/256 using key, key length, text to hash, size of the text and a switch for SHA224
*/
uint32_t TOTP_HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is224){
int digest_length = SHA256_DIGEST_LENGTH;
if (is224 == 1) {
digest_length = SHA224_DIGEST_LENGTH;
}
// STEP 1, get the HMAC-SHA256 hash from counter and key
uint8_t hash[digest_length];
HMAC_SHA256(key, key_length, in, n, hash, is224);
// STEP 2, apply dynamic truncation to obtain a 4-bytes string
uint32_t truncated_hash = 0;
uint8_t _offset = hash[digest_length - 1] & 0xF;
uint8_t j;
for (j = 0; j < 4; ++j) {
truncated_hash <<= 8;
truncated_hash |= hash[_offset + j];
}
// STEP 3, compute the OTP value
truncated_hash &= 0x7FFFFFFF; //Disabled
truncated_hash %= 1000000;
return truncated_hash;
}

View File

@ -1,112 +0,0 @@
/**
* \file sha256.h
*
* \brief SHA-224 and SHA-256 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA256_H
#define MBEDTLS_SHA256_H
#define SHA224_DIGEST_LENGTH 28
#define SHA256_DIGEST_LENGTH 32
#define SHA256_BLOCK_LENGTH 64
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
#include <stddef.h>
#include <stdint.h>
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[SHA256_BLOCK_LENGTH]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
}
mbedtls_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char* output );
/* Internal use */
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_LENGTH] );
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-224/256 checksum result
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256( const unsigned char *input, size_t ilen,
unsigned char* output, int is224 );
void HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is224);
uint32_t TOTP_HMAC_SHA256(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is224);
#endif /* mbedtls_sha256.h */

View File

@ -1,422 +0,0 @@
/*
* FIPS-180-2 compliant SHA-384/512 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "sha512.h"
#include <string.h>
#include <stdio.h>
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
}
#endif /* GET_UINT64_BE */
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif /* PUT_UINT64_BE */
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src )
{
*dst = *src;
}
/*
* SHA-512 context setup
*/
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
ctx->is384 = is384;
}
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_LENGTH] )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-512 process buffer
*/
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
unsigned int left;
if( ilen == 0 )
return;
left = (unsigned int) (ctx->total[0] & 0x7F);
fill = 128 - left;
ctx->total[0] += (uint64_t) ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha512_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
mbedtls_sha512_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha512_padding[SHA512_BLOCK_LENGTH] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char* output )
{
size_t last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
mbedtls_sha512_update( ctx, sha512_padding, padn );
mbedtls_sha512_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( ctx->is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
/*
* output = SHA-512( input buffer )
*/
void mbedtls_sha512( const unsigned char *input, size_t ilen,
unsigned char* output, int is384 )
{
mbedtls_sha512_context ctx;
mbedtls_sha512_init( &ctx );
mbedtls_sha512_starts( &ctx, is384 );
mbedtls_sha512_update( &ctx, input, ilen );
mbedtls_sha512_finish( &ctx, output );
mbedtls_sha512_free( &ctx );
}
/*
* Compute HMAC_SHA384/512 using key, key length, text to hash, size of the text, output buffer and a switch for SHA384
*/
void HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is384){
int digest_length = SHA512_DIGEST_LENGTH;
if (is384 == 1) {
digest_length = SHA384_DIGEST_LENGTH;
}
uint8_t i;
uint8_t k_ipad[SHA512_BLOCK_LENGTH]; /* inner padding - key XORd with ipad */
uint8_t k_opad[SHA512_BLOCK_LENGTH]; /* outer padding - key XORd with opad */
uint8_t buffer[SHA512_BLOCK_LENGTH + digest_length];
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
if (key_length <= SHA512_BLOCK_LENGTH) {
memcpy(k_ipad, key, key_length);
memcpy(k_opad, key, key_length);
}
else {
mbedtls_sha512(key, key_length, k_ipad, is384);
memcpy(k_opad, k_ipad, SHA512_BLOCK_LENGTH);
}
/* XOR key with ipad and opad values */
for (i = 0; i < SHA512_BLOCK_LENGTH; i++) {
k_ipad[i] ^= HMAC_IPAD;
k_opad[i] ^= HMAC_OPAD;
}
// perform inner SHA512
memcpy(buffer, k_ipad, SHA512_BLOCK_LENGTH);
memcpy(buffer + SHA512_BLOCK_LENGTH, in, n);
mbedtls_sha512(buffer, SHA512_BLOCK_LENGTH + n, out, is384);
memset(buffer, 0, SHA512_BLOCK_LENGTH + n);
// perform outer SHA512
memcpy(buffer, k_opad, SHA512_BLOCK_LENGTH);
memcpy(buffer + SHA512_BLOCK_LENGTH, out, digest_length);
mbedtls_sha512(buffer, SHA512_BLOCK_LENGTH + digest_length, out, is384);
}
/*
* Compute TOTP_HMAC_SHA384/512 using key, key length, text to hash, size of the text and a switch for SHA384
*/
uint32_t TOTP_HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is384){
int digest_length = SHA512_DIGEST_LENGTH;
if (is384 == 1) {
digest_length = SHA384_DIGEST_LENGTH;
}
// STEP 1, get the HMAC-SHA512 hash from counter and key
uint8_t hash[digest_length];
HMAC_SHA512(key, key_length, in, n, hash, is384);
// STEP 2, apply dynamic truncation to obtain a 4-bytes string
uint32_t truncated_hash = 0;
uint8_t _offset = hash[digest_length - 1] & 0xF;
uint8_t j;
for (j = 0; j < 4; ++j) {
truncated_hash <<= 8;
truncated_hash |= hash[_offset + j];
}
// STEP 3, compute the OTP value
truncated_hash &= 0x7FFFFFFF; //Disabled
truncated_hash %= 1000000;
return truncated_hash;
}

View File

@ -1,119 +0,0 @@
/**
* \file sha512.h
*
* \brief SHA-384 and SHA-512 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA512_H
#define MBEDTLS_SHA512_H
#define SHA384_DIGEST_LENGTH 48
#define SHA512_DIGEST_LENGTH 64
#define SHA512_BLOCK_LENGTH 128
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
#include <stddef.h>
#include <stdint.h>
/**
* \brief SHA-512 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[SHA512_BLOCK_LENGTH]; /*!< data block being processed */
int is384; /*!< 0 => SHA-512, else SHA-384 */
}
mbedtls_sha512_context;
/**
* \brief Initialize SHA-512 context
*
* \param ctx SHA-512 context to be initialized
*/
void mbedtls_sha512_init( mbedtls_sha512_context *ctx );
/**
* \brief Clear SHA-512 context
*
* \param ctx SHA-512 context to be cleared
*/
void mbedtls_sha512_free( mbedtls_sha512_context *ctx );
/**
* \brief Clone (the state of) a SHA-512 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src );
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
*/
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char* output );
/**
* \brief Output = SHA-512( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-384/512 checksum result
* \param is384 0 = use SHA512, 1 = use SHA384
*/
void mbedtls_sha512( const unsigned char *input, size_t ilen,
unsigned char* output, int is384 );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_sha512_self_test( int verbose );
/* Internal use */
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_LENGTH] );
void HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, uint8_t* out, int is384);
uint32_t TOTP_HMAC_SHA512(const uint8_t* key, size_t key_length, const uint8_t *in, size_t n, int is384);
#endif /* mbedtls_sha512.h */

View File

@ -1,221 +0,0 @@
/**
* 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;
}
}

View File

@ -1,66 +0,0 @@
/**
* 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

View File

@ -1,243 +0,0 @@
/* 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;
}

View File

@ -1,94 +0,0 @@
/* 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_