'movement' -> 'legacy' to signal things we still need to bring in
This commit is contained in:
21
legacy/lib/TOTP/LICENSE
Normal file
21
legacy/lib/TOTP/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
68
legacy/lib/TOTP/README.md
Normal file
68
legacy/lib/TOTP/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
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
|
||||
69
legacy/lib/TOTP/TOTP.c
Normal file
69
legacy/lib/TOTP/TOTP.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
21
legacy/lib/TOTP/TOTP.h
Normal file
21
legacy/lib/TOTP/TOTP.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#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_
|
||||
27
legacy/lib/TOTP/example.c
Normal file
27
legacy/lib/TOTP/example.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#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);
|
||||
}
|
||||
398
legacy/lib/TOTP/sha1.c
Normal file
398
legacy/lib/TOTP/sha1.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
98
legacy/lib/TOTP/sha1.h
Normal file
98
legacy/lib/TOTP/sha1.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* \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 */
|
||||
372
legacy/lib/TOTP/sha256.c
Normal file
372
legacy/lib/TOTP/sha256.c
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
112
legacy/lib/TOTP/sha256.h
Normal file
112
legacy/lib/TOTP/sha256.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* \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 */
|
||||
422
legacy/lib/TOTP/sha512.c
Normal file
422
legacy/lib/TOTP/sha512.c
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
119
legacy/lib/TOTP/sha512.h
Normal file
119
legacy/lib/TOTP/sha512.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* \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 */
|
||||
9
legacy/lib/astrolib/LICENSE.txt
Executable file
9
legacy/lib/astrolib/LICENSE.txt
Executable file
@@ -0,0 +1,9 @@
|
||||
Public domain
|
||||
|
||||
THIS 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.
|
||||
9
legacy/lib/astrolib/README.md
Normal file
9
legacy/lib/astrolib/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Astrolib
|
||||
|
||||
This is a relatively straightforward C port of Greg Miller's [JavaScript astro library](https://github.com/gmiller123456/astrogreg), done by Joey Castillo, for the Sensor Watch Astronomy watch face.
|
||||
|
||||
He released his work into the public domain and so I release this into the public domain as well.
|
||||
|
||||
I have tested the output of this library against [NASA's Horizons system](https://ssd.jpl.nasa.gov/horizons/app.html#/) and found the results to match (within reason, as we're using a truncated version of VSOP87). Moon calculations still seem a bit iffy, but it doesn't surprise me seeing as there are three calculations involved and the error could stack up.
|
||||
|
||||
THIS 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.
|
||||
555
legacy/lib/astrolib/astrolib.c
Normal file
555
legacy/lib/astrolib/astrolib.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* Partial C port of Greg Miller's public domain astro library (gmiller@gregmiller.net) 2019
|
||||
* https://github.com/gmiller123456/astrogreg
|
||||
*
|
||||
* Ported by Joey Castillo for Sensor Watch
|
||||
* https://github.com/joeycastillo/Sensor-Watch/
|
||||
*
|
||||
* Public Domain
|
||||
*
|
||||
* THIS 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 <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "astrolib.h"
|
||||
#include "vsop87a_milli.h"
|
||||
|
||||
double astro_convert_utc_to_tt(double jd) ;
|
||||
double astro_get_GMST(double ut1);
|
||||
astro_cartesian_coordinates_t astro_subtract_cartesian(astro_cartesian_coordinates_t a, astro_cartesian_coordinates_t b);
|
||||
astro_cartesian_coordinates_t astro_rotate_from_vsop_to_J2000(astro_cartesian_coordinates_t c);
|
||||
astro_matrix_t astro_get_x_rotation_matrix(double r);
|
||||
astro_matrix_t astro_get_y_rotation_matrix(double r);
|
||||
astro_matrix_t astro_get_z_rotation_matrix(double r);
|
||||
astro_matrix_t astro_transpose_matrix(astro_matrix_t m);
|
||||
astro_matrix_t astro_dot_product(astro_matrix_t a, astro_matrix_t b);
|
||||
astro_matrix_t astro_get_precession_matrix(double jd);
|
||||
astro_cartesian_coordinates_t astro_matrix_multiply(astro_cartesian_coordinates_t v, astro_matrix_t m);
|
||||
astro_cartesian_coordinates_t astro_convert_geodedic_latlon_to_ITRF_XYZ(double lat, double lon, double height);
|
||||
astro_cartesian_coordinates_t astro_convert_ITRF_to_GCRS(astro_cartesian_coordinates_t r, double ut1);
|
||||
astro_cartesian_coordinates_t astro_convert_coordinates_from_meters_to_AU(astro_cartesian_coordinates_t c);
|
||||
astro_cartesian_coordinates_t astro_get_observer_geocentric_coords(double jd, double lat, double lon);
|
||||
astro_cartesian_coordinates_t astro_get_body_coordinates(astro_body_t bodyNum, double et);
|
||||
astro_cartesian_coordinates_t astro_get_body_coordinates_light_time_adjusted(astro_body_t body, astro_cartesian_coordinates_t origin, double t);
|
||||
astro_equatorial_coordinates_t astro_convert_cartesian_to_polar(astro_cartesian_coordinates_t xyz);
|
||||
|
||||
//Special "Math.floor()" function used by convertDateToJulianDate()
|
||||
static double _astro_special_floor(double d) {
|
||||
if(d > 0) {
|
||||
return floor(d);
|
||||
}
|
||||
return floor(d) - 1;
|
||||
}
|
||||
|
||||
double astro_convert_date_to_julian_date(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
if (month < 3){
|
||||
year = year - 1;
|
||||
month = month + 12;
|
||||
}
|
||||
|
||||
double b = 0;
|
||||
if (!(year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day < 5))))) {
|
||||
double a = _astro_special_floor(year / 100.0);
|
||||
b = 2 - a + _astro_special_floor(a / 4.0);
|
||||
}
|
||||
|
||||
double jd = _astro_special_floor(365.25 * (year + 4716)) + _astro_special_floor(30.6001 * (month + 1)) + day + b - 1524.5;
|
||||
jd += hour / 24.0;
|
||||
jd += minute / 24.0 / 60.0;
|
||||
jd += second / 24.0 / 60.0 / 60.0;
|
||||
|
||||
return jd;
|
||||
}
|
||||
|
||||
//Return all values in radians.
|
||||
//The positions are adjusted for the parallax of the Earth, and the offset of the observer from the Earth's center
|
||||
//All input and output angles are in radians!
|
||||
astro_equatorial_coordinates_t astro_get_ra_dec(double jd, astro_body_t body, double lat, double lon, bool calculate_precession) {
|
||||
double jdTT = astro_convert_utc_to_tt(jd);
|
||||
double t = astro_convert_jd_to_julian_millenia_since_j2000(jdTT);
|
||||
|
||||
// Get current position of Earth and the target body
|
||||
astro_cartesian_coordinates_t earth_coords = astro_get_body_coordinates(ASTRO_BODY_EARTH, t);
|
||||
astro_cartesian_coordinates_t body_coords = astro_get_body_coordinates_light_time_adjusted(body, earth_coords, t);
|
||||
|
||||
// Convert to Geocentric coordinate
|
||||
body_coords = astro_subtract_cartesian(body_coords, earth_coords);
|
||||
|
||||
//Rotate ecliptic coordinates to J2000 coordinates
|
||||
body_coords = astro_rotate_from_vsop_to_J2000(body_coords);
|
||||
|
||||
astro_matrix_t precession;
|
||||
// TODO: rotate body for precession, nutation and bias
|
||||
if(calculate_precession) {
|
||||
precession = astro_get_precession_matrix(jdTT);
|
||||
body_coords = astro_matrix_multiply(body_coords, precession);
|
||||
}
|
||||
|
||||
//Convert to topocentric
|
||||
astro_cartesian_coordinates_t observerXYZ = astro_get_observer_geocentric_coords(jdTT, lat, lon);
|
||||
|
||||
if(calculate_precession) {
|
||||
//TODO: rotate observerXYZ for precession, nutation and bias
|
||||
astro_matrix_t precessionInv = astro_transpose_matrix(precession);
|
||||
observerXYZ = astro_matrix_multiply(observerXYZ, precessionInv);
|
||||
}
|
||||
|
||||
body_coords = astro_subtract_cartesian(body_coords, observerXYZ);
|
||||
|
||||
//Convert to topocentric RA DEC by converting from cartesian coordinates to polar coordinates
|
||||
astro_equatorial_coordinates_t retval = astro_convert_cartesian_to_polar(body_coords);
|
||||
|
||||
retval.declination = M_PI/2.0 - retval.declination; //Dec. Offset to make 0 the equator, and the poles +/-90 deg
|
||||
if(retval.right_ascension < 0) retval.right_ascension += 2*M_PI; //Ensure RA is positive
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//Converts a Julian Date in UTC to Terrestrial Time (TT)
|
||||
double astro_convert_utc_to_tt(double jd) {
|
||||
//Leap seconds are hard coded, should be updated from the IERS website for other times
|
||||
|
||||
//TAI = UTC + leap seconds (e.g. 32)
|
||||
//TT=TAI + 32.184
|
||||
|
||||
//return jd + (32.0 + 32.184) / 24.0 / 60.0 / 60.0;
|
||||
return jd + (37.0 + 32.184) / 24.0 / 60.0 / 60.0;
|
||||
|
||||
/*
|
||||
https://data.iana.org/time-zones/tzdb-2018a/leap-seconds.list
|
||||
2272060800 10 # 1 Jan 1972
|
||||
2287785600 11 # 1 Jul 1972
|
||||
2303683200 12 # 1 Jan 1973
|
||||
2335219200 13 # 1 Jan 1974
|
||||
2366755200 14 # 1 Jan 1975
|
||||
2398291200 15 # 1 Jan 1976
|
||||
2429913600 16 # 1 Jan 1977
|
||||
2461449600 17 # 1 Jan 1978
|
||||
2492985600 18 # 1 Jan 1979
|
||||
2524521600 19 # 1 Jan 1980
|
||||
2571782400 20 # 1 Jul 1981
|
||||
2603318400 21 # 1 Jul 1982
|
||||
2634854400 22 # 1 Jul 1983
|
||||
2698012800 23 # 1 Jul 1985
|
||||
2776982400 24 # 1 Jan 1988
|
||||
2840140800 25 # 1 Jan 1990
|
||||
2871676800 26 # 1 Jan 1991
|
||||
2918937600 27 # 1 Jul 1992
|
||||
2950473600 28 # 1 Jul 1993
|
||||
2982009600 29 # 1 Jul 1994
|
||||
3029443200 30 # 1 Jan 1996
|
||||
3076704000 31 # 1 Jul 1997
|
||||
3124137600 32 # 1 Jan 1999
|
||||
3345062400 33 # 1 Jan 2006
|
||||
3439756800 34 # 1 Jan 2009
|
||||
3550089600 35 # 1 Jul 2012
|
||||
3644697600 36 # 1 Jul 2015
|
||||
3692217600 37 # 1 Jan 2017
|
||||
*/
|
||||
}
|
||||
|
||||
double astro_convert_jd_to_julian_millenia_since_j2000(double jd) {
|
||||
return (jd - 2451545.0) / 365250.0;
|
||||
}
|
||||
|
||||
astro_cartesian_coordinates_t astro_subtract_cartesian(astro_cartesian_coordinates_t a, astro_cartesian_coordinates_t b) {
|
||||
astro_cartesian_coordinates_t retval;
|
||||
|
||||
retval.x = a.x - b.x;
|
||||
retval.y = a.y - b.y;
|
||||
retval.z = a.z - b.z;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Performs the rotation from ecliptic coordinates to J2000 coordinates for the given vector x
|
||||
astro_cartesian_coordinates_t astro_rotate_from_vsop_to_J2000(astro_cartesian_coordinates_t c) {
|
||||
/* From VSOP87.doc
|
||||
X +1.000000000000 +0.000000440360 -0.000000190919 X
|
||||
Y = -0.000000479966 +0.917482137087 -0.397776982902 Y
|
||||
Z FK5 0.000000000000 +0.397776982902 +0.917482137087 Z VSOP87A
|
||||
*/
|
||||
astro_cartesian_coordinates_t t;
|
||||
t.x = c.x + c.y * 0.000000440360 + c.z * -0.000000190919;
|
||||
t.y = c.x * -0.000000479966 + c.y * 0.917482137087 + c.z * -0.397776982902;
|
||||
t.z = c.y * 0.397776982902 + c.z * 0.917482137087;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
double astro_get_GMST(double ut1) {
|
||||
double D = ut1 - 2451545.0;
|
||||
double T = D/36525.0;
|
||||
double gmst = fmod((280.46061837 + 360.98564736629*D + 0.000387933*T*T - T*T*T/38710000.0), 360.0);
|
||||
|
||||
if(gmst<0) {
|
||||
gmst+=360;
|
||||
}
|
||||
|
||||
return gmst/15;
|
||||
}
|
||||
|
||||
static astro_matrix_t _astro_get_empty_matrix() {
|
||||
astro_matrix_t t;
|
||||
for(uint8_t i = 0; i < 3 ; i++) {
|
||||
for(uint8_t j = 0 ; j < 3 ; j++) {
|
||||
t.elements[i][j] = 0;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
//Gets a rotation matrix about the x axis. Angle R is in radians
|
||||
astro_matrix_t astro_get_x_rotation_matrix(double r) {
|
||||
astro_matrix_t t = _astro_get_empty_matrix();
|
||||
|
||||
t.elements[0][0]=1;
|
||||
t.elements[0][1]=0;
|
||||
t.elements[0][2]=0;
|
||||
t.elements[1][0]=0;
|
||||
t.elements[1][1]=cos(r);
|
||||
t.elements[1][2]=sin(r);
|
||||
t.elements[2][0]=0;
|
||||
t.elements[2][1]=-sin(r);
|
||||
t.elements[2][2]=cos(r);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//Gets a rotation matrix about the y axis. Angle R is in radians
|
||||
astro_matrix_t astro_get_y_rotation_matrix(double r) {
|
||||
astro_matrix_t t = _astro_get_empty_matrix();
|
||||
|
||||
t.elements[0][0]=cos(r);
|
||||
t.elements[0][1]=0;
|
||||
t.elements[0][2]=-sin(r);
|
||||
t.elements[1][0]=0;
|
||||
t.elements[1][1]=1;
|
||||
t.elements[1][2]=0;
|
||||
t.elements[2][0]=sin(r);
|
||||
t.elements[2][1]=0;
|
||||
t.elements[2][2]=cos(r);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//Gets a rotation matrix about the z axis. Angle R is in radians
|
||||
astro_matrix_t astro_get_z_rotation_matrix(double r) {
|
||||
astro_matrix_t t = _astro_get_empty_matrix();
|
||||
|
||||
t.elements[0][0]=cos(r);
|
||||
t.elements[0][1]=sin(r);
|
||||
t.elements[0][2]=0;
|
||||
t.elements[1][0]=-sin(r);
|
||||
t.elements[1][1]=cos(r);
|
||||
t.elements[1][2]=0;
|
||||
t.elements[2][0]=0;
|
||||
t.elements[2][1]=0;
|
||||
t.elements[2][2]=1;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void astro_print_matrix(char * title, astro_matrix_t matrix);
|
||||
void astro_print_matrix(char * title, astro_matrix_t matrix) {
|
||||
printf("%s\n", title);
|
||||
for(uint8_t i = 0; i < 3 ; i++) {
|
||||
printf("\t");
|
||||
for(uint8_t j = 0 ; j < 3 ; j++) {
|
||||
printf("%12f", matrix.elements[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
astro_matrix_t astro_dot_product(astro_matrix_t a, astro_matrix_t b) {
|
||||
astro_matrix_t retval;
|
||||
|
||||
for(uint8_t i = 0; i < 3 ; i++) {
|
||||
for(uint8_t j = 0 ; j < 3 ; j++) {
|
||||
double temp = 0;
|
||||
for(uint8_t k = 0; k < 3 ; k++) {
|
||||
temp += a.elements[i][k] * b.elements[k][j];
|
||||
}
|
||||
retval.elements[i][j]=temp;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
astro_matrix_t astro_transpose_matrix(astro_matrix_t m) {
|
||||
astro_matrix_t retval;
|
||||
for(uint8_t i = 0; i < 3 ; i++) {
|
||||
for(uint8_t j = 0 ; j < 3 ; j++) {
|
||||
retval.elements[i][j] = m.elements[j][i];
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
astro_matrix_t astro_get_precession_matrix(double jd) {
|
||||
//2006 IAU Precession. Implemented from IERS Technical Note No 36 ch5.
|
||||
//https://www.iers.org/SharedDocs/Publikationen/EN/IERS/Publications/tn/TechnNote36/tn36_043.pdf?__blob=publicationFile&v=1
|
||||
|
||||
double t = (jd - 2451545.0) / 36525.0; //5.2
|
||||
const double Arcsec2Radians = M_PI/180.0/60.0/60.0; //Converts arc seconds used in equations below to radians
|
||||
|
||||
double e0 = 84381.406 * Arcsec2Radians; //5.6.4
|
||||
double omegaA = e0 + ((-0.025754 + (0.0512623 + (-0.00772503 + (-0.000000467 + 0.0000003337*t) * t) * t) * t) * t) * Arcsec2Radians; //5.39
|
||||
double psiA = ((5038.481507 + (-1.0790069 + (-0.00114045 + (0.000132851 - 0.0000000951*t) * t) * t) * t) * t) * Arcsec2Radians; //5.39
|
||||
double chiA = ((10.556403 + (-2.3814292 + (-0.00121197 + (0.000170663 - 0.0000000560*t) * t) * t) * t) * t) * Arcsec2Radians; //5.40
|
||||
//Rotation matrix from 5.4.5
|
||||
//(R1(−e0) · R3(psiA) · R1(omegaA) · R3(−chiA))
|
||||
//Above eq rotates from "of date" to J2000, so we reverse the signs to go from J2000 to "of date"
|
||||
astro_matrix_t m1 = astro_get_x_rotation_matrix(e0);
|
||||
astro_matrix_t m2 = astro_get_z_rotation_matrix(-psiA);
|
||||
astro_matrix_t m3 = astro_get_x_rotation_matrix(-omegaA);
|
||||
astro_matrix_t m4 = astro_get_z_rotation_matrix(chiA);
|
||||
|
||||
astro_matrix_t m5 = astro_dot_product(m4, m3);
|
||||
astro_matrix_t m6 = astro_dot_product(m5, m2);
|
||||
astro_matrix_t precessionMatrix = astro_dot_product(m6, m1);
|
||||
|
||||
return precessionMatrix;
|
||||
}
|
||||
|
||||
astro_cartesian_coordinates_t astro_matrix_multiply(astro_cartesian_coordinates_t v, astro_matrix_t m) {
|
||||
astro_cartesian_coordinates_t t;
|
||||
|
||||
t.x = v.x*m.elements[0][0] + v.y*m.elements[0][1] + v.z*m.elements[0][2];
|
||||
t.y = v.x*m.elements[1][0] + v.y*m.elements[1][1] + v.z*m.elements[1][2];
|
||||
t.z = v.x*m.elements[2][0] + v.y*m.elements[2][1] + v.z*m.elements[2][2];
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//Converts cartesian XYZ coordinates to polar (e.g. J2000 xyz to Right Accention and Declication)
|
||||
astro_equatorial_coordinates_t astro_convert_cartesian_to_polar(astro_cartesian_coordinates_t xyz) {
|
||||
astro_equatorial_coordinates_t t;
|
||||
|
||||
t.distance = sqrt(xyz.x * xyz.x + xyz.y * xyz.y + xyz.z * xyz.z);
|
||||
t.declination = acos(xyz.z / t.distance);
|
||||
t.right_ascension = atan2(xyz.y, xyz.x);
|
||||
|
||||
if(t.declination < 0) t.declination += 2 * M_PI;
|
||||
|
||||
if(t.right_ascension < 0) t.right_ascension += 2 * M_PI;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//Convert Geodedic Lat Lon to geocentric XYZ position vector
|
||||
//All angles are input as radians
|
||||
astro_cartesian_coordinates_t astro_convert_geodedic_latlon_to_ITRF_XYZ(double lat, double lon, double height) {
|
||||
//Algorithm from Explanatory Supplement to the Astronomical Almanac 3rd ed. P294
|
||||
const double a = 6378136.6;
|
||||
const double f = 1 / 298.25642;
|
||||
|
||||
const double C = sqrt(((cos(lat)*cos(lat)) + (1.0-f)*(1.0-f) * (sin(lat)*sin(lat))));
|
||||
|
||||
const double S = (1-f)*(1-f)*C;
|
||||
|
||||
double h = height;
|
||||
|
||||
astro_cartesian_coordinates_t r;
|
||||
r.x = (a*C+h) * cos(lat) * cos(lon);
|
||||
r.y = (a*C+h) * cos(lat) * sin(lon);
|
||||
r.z = (a*S+h) * sin(lat);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//Convert position vector to celestial "of date" system.
|
||||
//g(t)=R3(-GAST) r
|
||||
//(Remember to use UT1 for GAST, not ET)
|
||||
//All angles are input and output as radians
|
||||
astro_cartesian_coordinates_t astro_convert_ITRF_to_GCRS(astro_cartesian_coordinates_t r, double ut1) {
|
||||
//This is a simple rotation matrix implemenation about the Z axis, rotation angle is -GMST
|
||||
|
||||
double GMST = astro_get_GMST(ut1);
|
||||
GMST =- GMST * 15.0 * M_PI / 180.0;
|
||||
|
||||
astro_matrix_t m = astro_get_z_rotation_matrix(GMST);
|
||||
astro_cartesian_coordinates_t t = astro_matrix_multiply(r, m);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
astro_cartesian_coordinates_t astro_convert_coordinates_from_meters_to_AU(astro_cartesian_coordinates_t c) {
|
||||
astro_cartesian_coordinates_t t;
|
||||
|
||||
t.x = c.x / 1.49597870691E+11;
|
||||
t.y = c.y / 1.49597870691E+11;
|
||||
t.z = c.z / 1.49597870691E+11;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
astro_cartesian_coordinates_t astro_get_observer_geocentric_coords(double jd, double lat, double lon) {
|
||||
astro_cartesian_coordinates_t r = astro_convert_geodedic_latlon_to_ITRF_XYZ(lat, lon,0);
|
||||
r = astro_convert_ITRF_to_GCRS(r, jd);
|
||||
r = astro_convert_coordinates_from_meters_to_AU(r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//Returns a body's cartesian coordinates centered on the Sun.
|
||||
//Requires vsop87a_milli_js, if you wish to use a different version of VSOP87, replace the class name vsop87a_milli below
|
||||
astro_cartesian_coordinates_t astro_get_body_coordinates(astro_body_t body, double et) {
|
||||
astro_cartesian_coordinates_t retval = {0};
|
||||
double coords[3];
|
||||
switch(body) {
|
||||
case ASTRO_BODY_SUN:
|
||||
return retval; //Sun is at the center for vsop87a
|
||||
case ASTRO_BODY_MERCURY:
|
||||
vsop87a_milli_getMercury(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_VENUS:
|
||||
vsop87a_milli_getVenus(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_EARTH:
|
||||
vsop87a_milli_getEarth(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_MARS:
|
||||
vsop87a_milli_getMars(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_JUPITER:
|
||||
vsop87a_milli_getJupiter(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_SATURN:
|
||||
vsop87a_milli_getSaturn(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_URANUS:
|
||||
vsop87a_milli_getUranus(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_NEPTUNE:
|
||||
vsop87a_milli_getNeptune(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_EMB:
|
||||
vsop87a_milli_getEmb(et, coords);
|
||||
break;
|
||||
case ASTRO_BODY_MOON:
|
||||
{
|
||||
double earth_coords[3];
|
||||
double emb_coords[3];
|
||||
vsop87a_milli_getEarth(et, earth_coords);
|
||||
vsop87a_milli_getEmb(et, emb_coords);
|
||||
vsop87a_milli_getMoon(earth_coords, emb_coords, coords);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval.x = coords[0];
|
||||
retval.y = coords[1];
|
||||
retval.z = coords[2];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
astro_cartesian_coordinates_t astro_get_body_coordinates_light_time_adjusted(astro_body_t body, astro_cartesian_coordinates_t origin, double t) {
|
||||
//Get current position of body
|
||||
astro_cartesian_coordinates_t body_coords = astro_get_body_coordinates(body, t);
|
||||
|
||||
double newT = t;
|
||||
|
||||
for(uint8_t i = 0 ; i < 2 ; i++) {
|
||||
//Calculate light time to body
|
||||
body_coords = astro_subtract_cartesian(body_coords, origin);
|
||||
double distance = sqrt(body_coords.x*body_coords.x + body_coords.y*body_coords.y + body_coords.z*body_coords.z);
|
||||
distance *= 1.496e+11; //Convert from AU to meters
|
||||
double lightTime = distance / 299792458.0;
|
||||
|
||||
//Convert light time to Julian Millenia, and subtract it from the original value of t
|
||||
newT -= lightTime / 24.0 / 60.0 / 60.0 / 365250.0;
|
||||
//Recalculate body position adjusted for light time
|
||||
body_coords = astro_get_body_coordinates(body, newT);
|
||||
}
|
||||
|
||||
return body_coords;
|
||||
}
|
||||
|
||||
astro_horizontal_coordinates_t astro_ra_dec_to_alt_az(double jd, double lat, double lon, double ra, double dec) {
|
||||
double GMST = astro_get_GMST(jd) * M_PI/180.0 * 15.0;
|
||||
double h = GMST + lon - ra;
|
||||
|
||||
double sina = sin(dec)*sin(lat) + cos(dec)*cos(h)*cos(lat);
|
||||
double a = asin(sina);
|
||||
|
||||
double cosAz = (sin(dec)*cos(lat) - cos(dec)*cos(h)*sin(lat)) / cos(a);
|
||||
double Az = acos(cosAz);
|
||||
|
||||
if(sin(h) > 0) Az = 2.0*M_PI - Az;
|
||||
|
||||
astro_horizontal_coordinates_t retval;
|
||||
retval.altitude = a;
|
||||
retval.azimuth = Az;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
double astro_degrees_to_radians(double degrees) {
|
||||
return degrees * M_PI / 180;
|
||||
}
|
||||
|
||||
double astro_radians_to_degrees(double radians) {
|
||||
return radians * 180.0 / M_PI;
|
||||
}
|
||||
|
||||
astro_angle_dms_t astro_radians_to_dms(double radians) {
|
||||
astro_angle_dms_t retval;
|
||||
int8_t sign = (radians < 0) ? -1 : 1;
|
||||
double degrees = fabs(astro_radians_to_degrees(radians));
|
||||
|
||||
retval.degrees = (uint16_t)degrees;
|
||||
double temp = 60.0 * (degrees - retval.degrees);
|
||||
retval.minutes = (uint8_t)temp;
|
||||
retval.seconds = (uint8_t)round(60.0 * (temp - retval.minutes));
|
||||
|
||||
if (retval.seconds > 59) {
|
||||
retval.seconds = 0.0;
|
||||
retval.minutes++;
|
||||
}
|
||||
|
||||
if (retval.minutes > 59) {
|
||||
retval.minutes = 0;
|
||||
retval.degrees++;
|
||||
}
|
||||
|
||||
degrees *= sign;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
astro_angle_hms_t astro_radians_to_hms(double radians) {
|
||||
astro_angle_hms_t retval;
|
||||
double degrees = astro_radians_to_degrees(radians);
|
||||
double temp = degrees / 15.0;
|
||||
|
||||
retval.hours = (uint8_t)temp;
|
||||
temp = 60.0 * (temp - retval.hours);
|
||||
retval.minutes = (uint8_t)temp;
|
||||
retval.seconds = (uint8_t)round(60.0 * (temp - retval.minutes));
|
||||
|
||||
if (retval.seconds > 59) {
|
||||
retval.seconds = 0;
|
||||
retval.minutes++;
|
||||
}
|
||||
|
||||
if (retval.minutes > 59) {
|
||||
retval.minutes = 0;
|
||||
retval.hours++;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
87
legacy/lib/astrolib/astrolib.h
Normal file
87
legacy/lib/astrolib/astrolib.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Partial C port of Greg Miller's public domain astro library (gmiller@gregmiller.net) 2019
|
||||
* https://github.com/gmiller123456/astrogreg
|
||||
*
|
||||
* Ported by Joey Castillo for Sensor Watch
|
||||
* https://github.com/joeycastillo/Sensor-Watch/
|
||||
*
|
||||
* Public Domain
|
||||
*
|
||||
* THIS 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 ASTROLIB_H_
|
||||
#define ASTROLIB_H_
|
||||
|
||||
typedef enum {
|
||||
ASTRO_BODY_SUN = 0,
|
||||
ASTRO_BODY_MERCURY,
|
||||
ASTRO_BODY_VENUS,
|
||||
ASTRO_BODY_EARTH,
|
||||
ASTRO_BODY_MARS,
|
||||
ASTRO_BODY_JUPITER,
|
||||
ASTRO_BODY_SATURN,
|
||||
ASTRO_BODY_URANUS,
|
||||
ASTRO_BODY_NEPTUNE,
|
||||
ASTRO_BODY_EMB,
|
||||
ASTRO_BODY_MOON
|
||||
} astro_body_t;
|
||||
|
||||
typedef struct {
|
||||
double elements[3][3];
|
||||
} astro_matrix_t;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} astro_cartesian_coordinates_t;
|
||||
|
||||
typedef struct {
|
||||
double right_ascension;
|
||||
double declination;
|
||||
double distance;
|
||||
} astro_equatorial_coordinates_t;
|
||||
|
||||
typedef struct {
|
||||
double altitude;
|
||||
double azimuth;
|
||||
} astro_horizontal_coordinates_t;
|
||||
|
||||
typedef struct {
|
||||
int16_t degrees;
|
||||
uint8_t minutes;
|
||||
uint8_t seconds; // you may want this to be a float, watch just can't display any more digits
|
||||
} astro_angle_dms_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t hours;
|
||||
uint8_t minutes;
|
||||
uint8_t seconds; // you may want this to be a float, watch just can't display any more digits
|
||||
} astro_angle_hms_t;
|
||||
|
||||
// Convert a date to a julian date. Must be in UTC+0 time zone!
|
||||
double astro_convert_date_to_julian_date(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second);
|
||||
|
||||
// Converts a Julan Date to Julian Millenia since J2000, which is what VSOP87 expects as input.
|
||||
double astro_convert_jd_to_julian_millenia_since_j2000(double jd);
|
||||
|
||||
// Get right ascension / declination for a given body in the list above.
|
||||
astro_equatorial_coordinates_t astro_get_ra_dec(double jd, astro_body_t bodyNum, double lat, double lon, bool calculate_precession);
|
||||
|
||||
// Convert right ascension / declination to altitude/azimuth for a given location.
|
||||
astro_horizontal_coordinates_t astro_ra_dec_to_alt_az(double jd, double lat, double lon, double ra, double dec);
|
||||
|
||||
// these are self-explanatory
|
||||
double astro_degrees_to_radians(double degrees);
|
||||
double astro_radians_to_degrees(double radians);
|
||||
astro_angle_dms_t astro_radians_to_dms(double radians);
|
||||
astro_angle_hms_t astro_radians_to_hms(double radians);
|
||||
|
||||
#endif // ASTROLIB_H_
|
||||
221
legacy/lib/base32/base32.c
Normal file
221
legacy/lib/base32/base32.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
66
legacy/lib/base32/base32.h
Normal file
66
legacy/lib/base32/base32.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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
|
||||
113
legacy/lib/morsecalc/calc.c
Normal file
113
legacy/lib/morsecalc/calc.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include "calc.h"
|
||||
#include "calc_fns.h"
|
||||
|
||||
#define CALC_NAN (0.0/0.0)
|
||||
|
||||
/* calc_init
|
||||
* Initialize calculator
|
||||
*/
|
||||
int calc_init(calc_state_t *cs) {
|
||||
memset(cs->stack, CALC_NAN, N_STACK*sizeof(cs->stack[0]));
|
||||
cs->s = 0;
|
||||
cs->mem = 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calc_input_function
|
||||
* Try to execute the token as a calculator function
|
||||
*/
|
||||
int calc_input_function(calc_state_t *cs, char *token) {
|
||||
for(uint8_t idx=0; idx<sizeof(calc_dict)/sizeof(calc_dict[0]); idx++) {
|
||||
for(uint8_t idxn=0; idxn<calc_dict[idx].n_names; idxn++) {
|
||||
if(0 == strcmp(calc_dict[idx].names[idxn], token)) { // Found a match
|
||||
return (*calc_dict[idx].fn)(cs); // Run calculator function
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1; // Unrecognized function name
|
||||
}
|
||||
|
||||
/* calc_input_float
|
||||
* Read the token as a float.
|
||||
* For convenience, numerals can be written in binary:
|
||||
* 0 1 2 3 4 5 6 7 8 9
|
||||
* . - -. -- -.. -.- --. --- -... -..-
|
||||
* e t n m d k g o b x
|
||||
*
|
||||
* Exponent signs must be entered as "p".
|
||||
* Decimal place "." can be entered as "h" (code ....)
|
||||
* Sign "-" can be entered as "Ch digraph" (code ----)
|
||||
*
|
||||
* e.g. "4.2e-3" can be entered directly or as "4h2pC3"
|
||||
* similarly, "0.0042" can be "eheedn"
|
||||
*/
|
||||
#define REPCHAR(X,Y) for(idx=0; idx<strlen(token); idx++) \
|
||||
if(X==token[idx]) token[idx] = Y
|
||||
int calc_input_float(calc_state_t *cs, char *token) {
|
||||
uint8_t idx;
|
||||
REPCHAR('e', '0');
|
||||
REPCHAR('t', '1');
|
||||
REPCHAR('n', '2');
|
||||
REPCHAR('m', '3');
|
||||
REPCHAR('d', '4');
|
||||
REPCHAR('k', '5');
|
||||
REPCHAR('g', '6');
|
||||
REPCHAR('o', '7');
|
||||
REPCHAR('b', '8');
|
||||
REPCHAR('x', '9');
|
||||
REPCHAR('h', '.');
|
||||
REPCHAR('C', '-');
|
||||
REPCHAR('p', 'E');
|
||||
|
||||
char *endptr;
|
||||
double d = calc_strtof(token, &endptr);
|
||||
if(!endptr || (uint8_t)(endptr-token)<strlen(token)) return -1; // Bad format
|
||||
if(cs->s >= N_STACK) return -2; // Stack full
|
||||
cs->stack[cs->s++] = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calc_input
|
||||
* Manipulate the stack using the entered token.
|
||||
* If the token isn't a calculator function, try to convert it to a number and
|
||||
* add it to the stack.
|
||||
*
|
||||
* Return values:
|
||||
* 0 if function completed successfully.
|
||||
* -1 if token isn't a calculator function and couldn't convert to float.
|
||||
* -2 if stack is too full or too empty
|
||||
* -3 for something else
|
||||
*/
|
||||
int calc_input(calc_state_t *cs, char *token) {
|
||||
int retval = calc_input_function(cs, token);
|
||||
if(-1 == retval) retval = calc_input_float(cs, token);
|
||||
return retval;
|
||||
}
|
||||
44
legacy/lib/morsecalc/calc.h
Normal file
44
legacy/lib/morsecalc/calc.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 CALC_H_INCLUDED
|
||||
#define CALC_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define N_STACK 10
|
||||
|
||||
typedef struct {
|
||||
double stack[N_STACK];
|
||||
double mem;
|
||||
uint8_t s; // # of items in stack
|
||||
} calc_state_t;
|
||||
|
||||
int calc_init(calc_state_t *cs);
|
||||
int calc_input(calc_state_t *cs, char *token);
|
||||
int calc_input_function(calc_state_t *cs, char *token);
|
||||
int calc_input_float(calc_state_t *cs, char *token);
|
||||
double calc_strtof(const char *str, char **endptr);
|
||||
|
||||
#endif
|
||||
240
legacy/lib/morsecalc/calc_fns.c
Normal file
240
legacy/lib/morsecalc/calc_fns.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "calc_fns.h"
|
||||
|
||||
#define STACK_CHECK_0_IN_1_OUT if(cs->s >= N_STACK) return -2
|
||||
#define STACK_CHECK_1_IN_0_OUT if(cs->s < 1) return -2
|
||||
#define STACK_CHECK_1_IN_1_OUT if(cs->s < 1) return -2
|
||||
#define STACK_CHECK_2_IN_1_OUT if(cs->s < 2) return -2
|
||||
#define STACK_CHECK_2_IN_2_OUT if(cs->s < 2) return -2
|
||||
|
||||
static const double to_rad = M_PI/180;
|
||||
static const double to_deg = 180/M_PI;
|
||||
|
||||
// Stack and memory control
|
||||
int calc_delete(calc_state_t *cs) {
|
||||
if(cs->s < 1) return -2; // Check stack
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_clear_stack(calc_state_t *cs) {
|
||||
memset(cs->stack, (0.0/0.0), N_STACK*sizeof(cs->stack[0]));
|
||||
cs->s = 0;
|
||||
return 0;
|
||||
}
|
||||
int calc_flip(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_2_OUT;
|
||||
double buff = cs->stack[cs->s-2];
|
||||
cs->stack[cs->s-2] = cs->stack[cs->s-1];
|
||||
cs->stack[cs->s-1] = buff;
|
||||
return 0;
|
||||
}
|
||||
int calc_mem_clear(calc_state_t *cs) {
|
||||
cs->mem = 0.0;
|
||||
return 0;
|
||||
}
|
||||
int calc_mem_recall(calc_state_t *cs) {
|
||||
STACK_CHECK_0_IN_1_OUT;
|
||||
cs->stack[cs->s++] = cs->mem;
|
||||
return 0;
|
||||
}
|
||||
int calc_mem_add(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_0_OUT;
|
||||
cs->mem += cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_mem_subtract(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_0_OUT;
|
||||
cs->mem -= cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Basic operations
|
||||
int calc_add(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] += cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_subtract(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] -= cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_negate(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = -cs->stack[cs->s-1];
|
||||
return 0;
|
||||
}
|
||||
int calc_multiply(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] *= cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_divide(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] /= cs->stack[cs->s-1];
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int calc_invert(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = 1.0/cs->stack[cs->s-1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Constants
|
||||
int calc_e(calc_state_t *cs) {
|
||||
STACK_CHECK_0_IN_1_OUT;
|
||||
cs->stack[cs->s++] = M_E;
|
||||
return 0;
|
||||
}
|
||||
int calc_pi(calc_state_t *cs) {
|
||||
STACK_CHECK_0_IN_1_OUT;
|
||||
cs->stack[cs->s++] = M_PI;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Exponential/logarithmic
|
||||
int calc_exp(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = exp(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_pow(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] = pow(cs->stack[cs->s-2], cs->stack[cs->s-1]);
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_ln(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = log(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_log(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = log10(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_sqrt(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = sqrt(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Trigonometric
|
||||
int calc_sin(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = sin(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_cos(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = cos(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_tan(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = tan(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_asin(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = asin(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_acos(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = acos(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_atan(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = atan(cs->stack[cs->s-1]);
|
||||
return 0;
|
||||
}
|
||||
int calc_atan2(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] = atan2(cs->stack[cs->s-2], cs->stack[cs->s-1]);
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int calc_sind(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = sin(cs->stack[cs->s-1]*to_rad);
|
||||
return 0;
|
||||
}
|
||||
int calc_cosd(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = cos(cs->stack[cs->s-1]*to_rad);
|
||||
return 0;
|
||||
}
|
||||
int calc_tand(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = tan(cs->stack[cs->s-1]*to_rad);
|
||||
return 0;
|
||||
}
|
||||
int calc_asind(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = asin(cs->stack[cs->s-1])*to_deg;
|
||||
return 0;
|
||||
}
|
||||
int calc_acosd(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = acos(cs->stack[cs->s-1])*to_deg;
|
||||
return 0;
|
||||
}
|
||||
int calc_atand(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = atan(cs->stack[cs->s-1])*to_deg;
|
||||
return 0;
|
||||
}
|
||||
int calc_atan2d(calc_state_t *cs) {
|
||||
STACK_CHECK_2_IN_1_OUT;
|
||||
cs->stack[cs->s-2] = atan2(cs->stack[cs->s-2], cs->stack[cs->s-1])*to_deg;
|
||||
cs->s--;
|
||||
return 0;
|
||||
}
|
||||
int calc_torad(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = cs->stack[cs->s-1]*to_rad;
|
||||
return 0;
|
||||
}
|
||||
int calc_todeg(calc_state_t *cs) {
|
||||
STACK_CHECK_1_IN_1_OUT;
|
||||
cs->stack[cs->s-1] = cs->stack[cs->s-1]*to_deg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
128
legacy/lib/morsecalc/calc_fns.h
Normal file
128
legacy/lib/morsecalc/calc_fns.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 "calc.h"
|
||||
|
||||
// Stack and register control
|
||||
int calc_delete(calc_state_t *cs);
|
||||
int calc_clear_stack(calc_state_t *cs);
|
||||
int calc_flip(calc_state_t *cs);
|
||||
int calc_mem_clear(calc_state_t *cs);
|
||||
int calc_mem_recall(calc_state_t *cs);
|
||||
int calc_mem_add(calc_state_t *cs);
|
||||
int calc_mem_subtract(calc_state_t *cs);
|
||||
|
||||
// Basic operations
|
||||
int calc_add(calc_state_t *cs);
|
||||
int calc_subtract(calc_state_t *cs);
|
||||
int calc_negate(calc_state_t *cs);
|
||||
int calc_multiply(calc_state_t *cs);
|
||||
int calc_divide(calc_state_t *cs);
|
||||
int calc_invert(calc_state_t *cs);
|
||||
|
||||
// Constants
|
||||
int calc_e(calc_state_t *cs);
|
||||
int calc_pi(calc_state_t *cs);
|
||||
|
||||
// Exponential/logarithmic
|
||||
int calc_exp(calc_state_t *cs);
|
||||
int calc_pow(calc_state_t *cs);
|
||||
int calc_ln(calc_state_t *cs);
|
||||
int calc_log(calc_state_t *cs);
|
||||
int calc_sqrt(calc_state_t *cs);
|
||||
|
||||
// Trigonometric
|
||||
int calc_sin(calc_state_t *cs);
|
||||
int calc_cos(calc_state_t *cs);
|
||||
int calc_tan(calc_state_t *cs);
|
||||
int calc_asin(calc_state_t *cs);
|
||||
int calc_acos(calc_state_t *cs);
|
||||
int calc_atan(calc_state_t *cs);
|
||||
int calc_atan2(calc_state_t *cs);
|
||||
int calc_sind(calc_state_t *cs);
|
||||
int calc_cosd(calc_state_t *cs);
|
||||
int calc_tand(calc_state_t *cs);
|
||||
int calc_asind(calc_state_t *cs);
|
||||
int calc_acosd(calc_state_t *cs);
|
||||
int calc_atand(calc_state_t *cs);
|
||||
int calc_atan2d(calc_state_t *cs);
|
||||
int calc_torad(calc_state_t *cs);
|
||||
int calc_todeg(calc_state_t *cs);
|
||||
|
||||
// Dictionary definition
|
||||
typedef int (*calc_fn_t)(calc_state_t *cs);
|
||||
typedef struct {
|
||||
uint8_t n_names; // Number of aliases
|
||||
const char ** names; // Token to use to run this function
|
||||
calc_fn_t fn; // Pointer to function
|
||||
} calc_dict_entry_t;
|
||||
|
||||
static const calc_dict_entry_t calc_dict[] = {
|
||||
// Stack and register control
|
||||
{1, (const char*[]){"x"}, &calc_delete},
|
||||
{1, (const char*[]){"xx"}, &calc_clear_stack},
|
||||
{1, (const char*[]){"xxx"}, &calc_init},
|
||||
{1, (const char*[]){"f"}, &calc_flip},
|
||||
{1, (const char*[]){"mc"}, &calc_mem_clear},
|
||||
{1, (const char*[]){"mr"}, &calc_mem_recall},
|
||||
{1, (const char*[]){"ma"}, &calc_mem_add},
|
||||
{1, (const char*[]){"ms"}, &calc_mem_subtract},
|
||||
|
||||
// Basic operations
|
||||
{1, (const char*[]){"a"}, &calc_add},
|
||||
{1, (const char*[]){"s"}, &calc_subtract},
|
||||
{1, (const char*[]){"n"}, &calc_negate},
|
||||
{1, (const char*[]){"m"}, &calc_multiply},
|
||||
{1, (const char*[]){"d"}, &calc_divide},
|
||||
{1, (const char*[]){"i"}, &calc_invert},
|
||||
|
||||
// Constants
|
||||
{1, (const char*[]){"e"}, &calc_e},
|
||||
{1, (const char*[]){"pi"}, &calc_pi},
|
||||
|
||||
// Exponential/logarithmic
|
||||
{1, (const char*[]){"exp"}, &calc_exp},
|
||||
{1, (const char*[]){"pow"}, &calc_pow},
|
||||
{1, (const char*[]){"ln"}, &calc_ln},
|
||||
{1, (const char*[]){"log"}, &calc_log},
|
||||
{1, (const char*[]){"sqrt"}, &calc_sqrt},
|
||||
|
||||
// Trigonometric
|
||||
{2, (const char*[]){"sin", "sn"}, &calc_sin},
|
||||
{1, (const char*[]){"cos"}, &calc_cos},
|
||||
{1, (const char*[]){"tan"}, &calc_tan},
|
||||
{1, (const char*[]){"asin"}, &calc_asin},
|
||||
{1, (const char*[]){"acos"}, &calc_acos},
|
||||
{1, (const char*[]){"atan"}, &calc_atan},
|
||||
{1, (const char*[]){"atan2"}, &calc_atan2},
|
||||
{1, (const char*[]){"sind"}, &calc_sind},
|
||||
{1, (const char*[]){"cosd"}, &calc_cosd},
|
||||
{1, (const char*[]){"tand"}, &calc_tand},
|
||||
{1, (const char*[]){"asind"}, &calc_asind},
|
||||
{1, (const char*[]){"acosd"}, &calc_acosd},
|
||||
{1, (const char*[]){"atand"}, &calc_atand},
|
||||
{1, (const char*[]){"atan2d"}, &calc_atan2d},
|
||||
{1, (const char*[]){"tor"}, &calc_torad},
|
||||
{1, (const char*[]){"tod"}, &calc_todeg},
|
||||
};
|
||||
144
legacy/lib/morsecalc/calc_strtof.c
Normal file
144
legacy/lib/morsecalc/calc_strtof.c
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// strtod.c
|
||||
//
|
||||
// Convert string to double
|
||||
//
|
||||
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the project nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "calc.h"
|
||||
|
||||
double calc_strtof(const char *str, char **endptr) {
|
||||
double number;
|
||||
int exponent;
|
||||
int negative;
|
||||
char *p = (char *) str;
|
||||
double p10;
|
||||
int n;
|
||||
int num_digits;
|
||||
int num_decimals;
|
||||
|
||||
// Skip leading whitespace
|
||||
while (isspace((int) *p)) p++;
|
||||
|
||||
// Handle optional sign
|
||||
negative = 0;
|
||||
switch (*p) {
|
||||
case '-': negative = 1; // Fall through to increment position
|
||||
__attribute__ ((fallthrough));
|
||||
case '+': p++;
|
||||
}
|
||||
|
||||
number = 0.;
|
||||
exponent = 0;
|
||||
num_digits = 0;
|
||||
num_decimals = 0;
|
||||
|
||||
// Process string of digits
|
||||
while (isdigit((int) *p)) {
|
||||
number = number * 10. + (*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
}
|
||||
|
||||
// Process decimal part
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
|
||||
while (isdigit((int) *p)) {
|
||||
number = number * 10. + (*p - '0');
|
||||
p++;
|
||||
num_digits++;
|
||||
num_decimals++;
|
||||
}
|
||||
|
||||
exponent -= num_decimals;
|
||||
}
|
||||
|
||||
if (num_digits == 0) {
|
||||
if (endptr) *endptr = p;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Correct for sign
|
||||
if (negative) number = -number;
|
||||
|
||||
// Process an exponent string
|
||||
if (*p == 'e' || *p == 'E') {
|
||||
// Handle optional sign
|
||||
negative = 0;
|
||||
switch (*++p) {
|
||||
case '-': negative = 1; // Fall through to increment pos
|
||||
__attribute__ ((fallthrough));
|
||||
case '+': p++;
|
||||
}
|
||||
|
||||
// Process string of digits
|
||||
n = 0;
|
||||
while (isdigit((int) *p)) {
|
||||
n = n * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
exponent -= n;
|
||||
} else {
|
||||
exponent += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) {
|
||||
return HUGE_VAL;
|
||||
}
|
||||
|
||||
// Scale the result
|
||||
p10 = 10.;
|
||||
n = exponent;
|
||||
if (n < 0) n = -n;
|
||||
while (n) {
|
||||
if (n & 1) {
|
||||
if (exponent < 0) {
|
||||
number /= p10;
|
||||
} else {
|
||||
number *= p10;
|
||||
}
|
||||
}
|
||||
n >>= 1;
|
||||
p10 *= p10;
|
||||
}
|
||||
|
||||
if (endptr) *endptr = p;
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
147
legacy/lib/morsecalc/morsecalc_display.c
Normal file
147
legacy/lib/morsecalc/morsecalc_display.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "watch_private_display.h"
|
||||
#include "morsecalc_display.h"
|
||||
|
||||
// Display float on screen
|
||||
void morsecalc_display_float(double d) {
|
||||
// Special cases
|
||||
if(d == 0) {
|
||||
watch_display_string(" 0", 4);
|
||||
return;
|
||||
}
|
||||
else if(isnan(d)) {
|
||||
watch_display_string(" nan", 4);
|
||||
return;
|
||||
}
|
||||
else if(d == (1.0)/(0.0)) {
|
||||
watch_display_string(" inf", 4);
|
||||
return;
|
||||
}
|
||||
else if(d == (-1.0)/(0.0)) {
|
||||
watch_display_character('X', 1);
|
||||
watch_display_string(" inf", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// Record number properties
|
||||
// Sign
|
||||
int is_negative = d<0;
|
||||
if(is_negative) d = -d;
|
||||
|
||||
// Order of magnitude
|
||||
int om = (int) floor(log(d)/log(10));
|
||||
int om_is_negative = (om<0);
|
||||
|
||||
// Get the first 4 significant figures
|
||||
int digits;
|
||||
digits = round(d*pow(10.0, 3-om));
|
||||
if(digits>9999) {
|
||||
digits = 1000;
|
||||
om++;
|
||||
}
|
||||
|
||||
// Print signs
|
||||
if(is_negative) {
|
||||
// Xi; see https://joeycastillo.github.io/Sensor-Watch-Documentation/segmap
|
||||
watch_set_pixel(0,11);
|
||||
watch_set_pixel(2,12);
|
||||
watch_set_pixel(2,11);
|
||||
}
|
||||
else watch_display_character(' ', 1);
|
||||
if(om_is_negative) watch_set_pixel(1,9);
|
||||
else watch_display_character(' ', 2);
|
||||
|
||||
// Print first 4 significant figures
|
||||
watch_display_character('0'+(digits/1000)%10, 4);
|
||||
watch_display_character('0'+(digits/100 )%10, 5);
|
||||
watch_display_character('0'+(digits/10 )%10, 6);
|
||||
watch_display_character('0'+(digits/1 )%10, 7);
|
||||
|
||||
// Prinat exponent
|
||||
if(om_is_negative) om = -om; // Make exponent positive for display
|
||||
if(om<=99) {
|
||||
watch_display_character('0'+(om/10 )%10, 8);
|
||||
watch_display_character('0'+(om/1 )%10, 9);
|
||||
} else { // Over/underflow
|
||||
if(om_is_negative) watch_display_string(" uf", 4);
|
||||
else watch_display_string(" of", 4);
|
||||
if(om<9999) { // Use main display to show order of magnitude
|
||||
// (Should always succeed; max double is <2e308)
|
||||
watch_display_character('0'+(om/1000)%10, 4);
|
||||
watch_display_character('0'+(om/100 )%10, 5);
|
||||
watch_display_character('0'+(om/10 )%10, 6);
|
||||
watch_display_character('0'+(om/1 )%10, 7);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Print current input token
|
||||
void morsecalc_display_token(morsecalc_state_t *mcs) {
|
||||
watch_display_string(" ", 0); // Clear display
|
||||
|
||||
// Print morse code buffer
|
||||
char c = MORSECODE_TREE[mcs->mc]; // Decode the morse code buffer's current contents
|
||||
if('\0' == c) c = ' '; // Needed for watch_display_character
|
||||
watch_display_character(c, 0); // Display current morse code char in mode position
|
||||
|
||||
unsigned int v = mcs->mc+1;
|
||||
char bidx = 0; while (v >>= 1) bidx++;
|
||||
watch_display_character('0'+bidx, 3); // Display buffer position in top right
|
||||
|
||||
// Print last 6 chars of current input line
|
||||
uint8_t nlen = strlen(mcs->token); // number of characters in token
|
||||
uint8_t nprint = min(nlen,6); // number of characters to print
|
||||
watch_display_string(mcs->token+nlen-nprint, 10-nprint); // print right-aligned
|
||||
return;
|
||||
}
|
||||
|
||||
// Print stack or memory register contents.
|
||||
void morsecalc_display_stack(morsecalc_state_t * mcs) {
|
||||
watch_display_string(" ", 0); // Clear display
|
||||
|
||||
char c = MORSECODE_TREE[mcs->mc];
|
||||
if('m' == c) { // Display memory
|
||||
morsecalc_display_float(mcs->cs->mem);
|
||||
watch_display_character(c, 0);
|
||||
}
|
||||
else {
|
||||
// If the morse code buffer has a numeral in it, print that stack item
|
||||
// Otherwise print top of stack
|
||||
uint8_t idx = 0;
|
||||
if(c >= '0' && c <= '9') idx = c - '0';
|
||||
if(idx >= mcs->cs->s) watch_display_string(" empty", 4); // Stack empty
|
||||
else morsecalc_display_float(mcs->cs->stack[mcs->cs->s-1-idx]); // Print stack item
|
||||
|
||||
watch_display_character('0'+idx, 0); // Print which stack item this is top center
|
||||
}
|
||||
watch_display_character('0'+(mcs->cs->s), 3); // Print the # of stack items top right
|
||||
return;
|
||||
}
|
||||
|
||||
35
legacy/lib/morsecalc/morsecalc_display.h
Normal file
35
legacy/lib/morsecalc/morsecalc_display.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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 "morsecalc_face.h"
|
||||
|
||||
// Display float on screen
|
||||
void morsecalc_display_float(double d);
|
||||
|
||||
// Print current input token
|
||||
void morsecalc_display_token(morsecalc_state_t *mcs);
|
||||
|
||||
// Print stack or memory register contents.
|
||||
void morsecalc_display_stack(morsecalc_state_t *mcs);
|
||||
|
||||
66
legacy/lib/morsecalc/test_morsecalc.c
Normal file
66
legacy/lib/morsecalc/test_morsecalc.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Christian Chapman
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Computer console interface to calc and morsecode for testing without involving watch stuff.
|
||||
// cc calc_strtof.c calc.c calc_fns.c test_morsecalc.c -lm
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "calc.h"
|
||||
#include "calc_fns.h"
|
||||
|
||||
int main(void) {
|
||||
calc_state_t cs;
|
||||
calc_init(&cs);
|
||||
|
||||
char * word = malloc(0);
|
||||
unsigned int nword = 0;
|
||||
char c;
|
||||
int retval = 0;
|
||||
for(unsigned int ii = 0; ii < 100; ii++) {
|
||||
c = getchar();
|
||||
word = realloc(word, (++nword)*sizeof(char));
|
||||
word[nword-1] = c;
|
||||
if((nword > 0) && isspace(c)) { // Word is finished
|
||||
word[nword-1] = '\0';
|
||||
retval = calc_input(&cs, word); // Submit word
|
||||
word = realloc(word, 0); nword = 0; // Clear word
|
||||
|
||||
switch(retval) {
|
||||
case 0: printf("Success.\n"); break;
|
||||
case -1: printf("Bad command.\n"); break;
|
||||
case -2: printf("Stack over/underflow.\n"); break;
|
||||
case -3: printf("Error.\n"); break;
|
||||
}
|
||||
if(cs.s > 0) printf("[%i]: %.4f\n", cs.s, cs.stack[cs.s-1]);
|
||||
else printf("[%i]\n", cs.s);
|
||||
}
|
||||
}
|
||||
|
||||
free(word);
|
||||
return 0;
|
||||
}
|
||||
3704
legacy/lib/smallchesslib/smallchesslib.h
Normal file
3704
legacy/lib/smallchesslib/smallchesslib.h
Normal file
File diff suppressed because it is too large
Load Diff
5
legacy/lib/vsop87/LICENSE.txt
Executable file
5
legacy/lib/vsop87/LICENSE.txt
Executable file
@@ -0,0 +1,5 @@
|
||||
Author: Greg A Miller (gmiller@gregmiller.net)
|
||||
I release all of my work in this project to the public domain.
|
||||
|
||||
Note, though, not everything here can be considered my work. The VSOP87 theory is the work of
|
||||
Bureau des Longitudes.
|
||||
143
legacy/lib/vsop87/README.md
Executable file
143
legacy/lib/vsop87/README.md
Executable file
@@ -0,0 +1,143 @@
|
||||
# Example
|
||||
|
||||
An example in JavaScript showing computations is available at http://www.celestialprogramming.com/vsop87-multilang/
|
||||
|
||||
### Current Stauts
|
||||
Versions for many different languages and environments have been created. These have passed all test cases provided by the
|
||||
VSOP87 authors, a validation program is also included for each language. They are ready for use. See the "Languages" directory for the status
|
||||
of each language.
|
||||
|
||||
Still to come: more languages, documentation, and examples.
|
||||
|
||||
# About this Project
|
||||
The purpose of this project is to create versions of VSOP87 in many different languages. The plan is to generate a initial version in C# truncated to different
|
||||
precisions, then convert the resulting files into other languages. This project was inspired by the [Neoprogrammics Source Code Generator Tool](http://www.neoprogrammics.com/vsop87/source_code_generator_tool/).
|
||||
The goal of this project is to provide easier to use (readymade source files), include all data (e.g. the Moon and velocities), are truncated to different accuracy levels,
|
||||
, for more languages, and have a more permissive license (public domain). It will provide tests against the original VSOP87 test data for each programming language to validate correctness, as well as examples to show common useage.
|
||||
|
||||
# Language Status
|
||||
|
||||
Below is a list of the planned languages and their current status.
|
||||
|
||||
|
||||
Language |Inline|JSON|CSV|CSV Low Mem|Validation Tests|Alt Az Reduction Example
|
||||
-------------|------|----|---|-----------|----------------|--------------
|
||||
Java |Yes | |Yes| |Pass |
|
||||
C |Yes | | |Yes |Pass |
|
||||
C# |Yes | |Yes| |Pass |
|
||||
Python |Yes |Yes |Yes| |Pass |
|
||||
C++ |Yes | | | |Pass |
|
||||
VB.Net |Yes | | | |Pass |
|
||||
JavaScript |Yes |Yes | | |Pass |Yes
|
||||
PHP |Yes | | | |Pass |
|
||||
Ruby |Yes | | | |Pass |
|
||||
Swift |Yes | | | |Pass |
|
||||
Matlab/Octave|Yes | | | |Pass |
|
||||
Groovy | | |Yes| |Pass |
|
||||
Go |Yes | | | |Pass |
|
||||
Pascal |Yes | | | |0.000009au |
|
||||
Perl |Yes | | |Yes |Pass |
|
||||
R |Fail! | | | |Fail! |
|
||||
Cobol | | | | | |
|
||||
Fortran | | | | | |
|
||||
Rust |Yes | | | |Pass |
|
||||
Arduino |Yes | | | |0.000009au |
|
||||
|
||||
# What is VSOP87? Why use it?
|
||||
VSOP87 is one of many solutions available for predicting the positions of the planets (plus the Sun and the Moon) in our solar system. The actual name is
|
||||
Variations S<>culaires des Orbites Plan<61>taires, and it was published in 1987 by the Bureau des Longitudes. Even though there have been many other methods
|
||||
developed before and after VSOP87, it remains one of the most popular methods among amatuers. It provides better accuracy than most amatuers require (.1 arcseconds)
|
||||
over a period of a few thousand years before and after the year 2000.
|
||||
|
||||
# Implementation Types
|
||||
There are a few different types of implementations: Inline, JSON, CSV, and CSV Low Memory. The inline versions are generally the easiest to use as they will have no
|
||||
external requirements, they are also the easiest to generate, so they're available for more languages. The JSON versions require a JSON file (located in the
|
||||
languages/JSON folder) which is loaded into memory. The advantages of the JSON versions are you can compute the velocities with the same data the positions
|
||||
are generated from, and you can load and dispose of the memory used by the data when you need it. The CSV implementations are similar to the JSON implementations,
|
||||
but, obviously, read from a CSV file (located in the languages/CSV folder). And the Low Memory CSV implementations read the same CSV files, but the
|
||||
data is not retained in memory. The JSON versions are located in the Languages/JSON directory, as well as the required JSON files, and the CSV implementations
|
||||
are in the languages/CSV folder.
|
||||
|
||||
# Which Version Should I Use?
|
||||
For the overwhelming majority of users, the VSOP87A_full version will be all that you need. This is the full version, but should still be fast enough and small enough
|
||||
for most use cases. Using the full version eliminates any questions of whether it will be accurate enough. If, after trying the full version, the computation isn't
|
||||
fast enough, from there you should experiment with truncated versions. The VSOP87A versions are the only versions which include both the Earth and Moon. VSOP87A doesn't include the moon directly, but does include the Earth and the Earth-Moon Barrycenter, and all provided code for the VSOP87A versions include a function to compute the Moon's position from the Earth and EMB. Using the versions that provide the velocities is necessary if you want to account for relativistic effects do to the motion of the observer.
|
||||
|
||||
There are several versions of the main theory. The first is just called VSOP87, the remainder of them are appended with the letters A, B, C, D, E. Each version
|
||||
provides the data in a slightly different form.
|
||||
|
||||
Version|Mercury|Venus|Earth|EMB|Mars|Jupiter|Saturn|Uranus|Neptune|Sun|Coordinates
|
||||
-------|-------|-----|-----|---|----|-------|------|------|-------|---|-----------
|
||||
VSOP87|Yes|Yes|No|Yes|Yes|Yes|Yes|Yes|Yes|No|Keperian Orbital Elements
|
||||
VSOP87A|Yes|Yes|Yes|Yes|Yes|Yes|Yes|Yes|Yes|No|Heliocentric J2000 Ecliptic Rectangular XYZ
|
||||
VSOP87B|Yes|Yes|Yes|No|Yes|Yes|Yes|Yes|Yes|No|Heliocentric J2000 Ecliptic Spherical LBR
|
||||
VSOP87C|Yes|Yes|Yes|No|Yes|Yes|Yes|Yes|Yes|No|Heliocentric Ecliptic of date Rectangular XYZ
|
||||
VSOP87D|Yes|Yes|Yes|No|Yes|Yes|Yes|Yes|Yes|No|Heliocentric Ecliptic of date Spherical LBR
|
||||
VSOP87E|Yes|Yes|Yes|No|Yes|Yes|Yes|Yes|Yes|Yes|Barycentric J2000 Ecliptic Rectangular XYZ
|
||||
|
||||
# Truncated versions
|
||||
Since the full VSOP87 provides more accuracy than most amateurs require, the algorithm can be shortened by eliminating terms. This speeds up the computations, and
|
||||
reduces the overall size of the code at the cost of accuracy. For each programming language, this project supplies VSOP87 truncated at ten different levels. The
|
||||
effects of accuracy are detailed in the graphs below. Each level of truncation eliminates any terms with a coefficient 1/10 the previous truncation level.
|
||||
|
||||
Trunaction Level|Total Terms|Skipped Terms|Percent Skipped
|
||||
----------------|-----------|-------------|---------------
|
||||
full |269949|0 |0 %
|
||||
xx large |269949|20998 |7.7 %
|
||||
x large |269949|67848 |25.1 %
|
||||
large |269949|145031|53.7 %
|
||||
small |269949|218559|80.9 %
|
||||
x small |269949|250204|92.6 %
|
||||
milli |269949|262369|97.1 %
|
||||
micro |269949|266975|98.8 %
|
||||
nano |269949|268686|99.5 %
|
||||
pico |269949|269464|99.8 %
|
||||
|
||||
# Accuracy
|
||||
|
||||
Accuracy graphs are below. They show the error in degrees of each body as viewed from Earth. Each graph shows the error for one body for all truncated versions of
|
||||
VSOP87. The error is vs. the full version of VSOP87, so the inherent error in VSOP87 also has to be added. Some bodies appear twice, to zoom in on the lower portion
|
||||
of the graph, as the error of the pico version makes it difficult to see errors amongst the larger versions. The Python script and data to reproduce the graphs is
|
||||
in the Accuracy folder, by regenerating them you can use the Matplotlib interface to explore the graphs further.
|
||||
|
||||
Since the error is computed from the geocenter, the Earth does not appear in the graphs below, nor does the Sun. Graphs are also not present for the Moon, but graphs
|
||||
are available for the Earth-Moon Barrycenter (EMB), the error for the Moon will be a linear function of the EMB error.
|
||||
|
||||
The full VSOP87 accuracy is .1 arcseconds for Saturn, and better for all others. For more details on accuracy of the full theory consult
|
||||
[Planetary theories in rectangular and spherical variables - VSOP 87 solutions](http://articles.adsabs.harvard.edu/full/1988A%26A...202..309B).
|
||||
|
||||
### Mercury
|
||||

|
||||
|
||||
### Venus
|
||||

|
||||
|
||||
### Earth-Moon Barrycenter
|
||||

|
||||
|
||||
### Earth-Moon Barrycenter (zoomed)
|
||||

|
||||
|
||||
### Mars
|
||||

|
||||
|
||||
### Jupiter
|
||||

|
||||
|
||||
### Saturn
|
||||

|
||||
|
||||
### Saturn (zoomed)
|
||||

|
||||
|
||||
### Uranus
|
||||

|
||||
|
||||
### Uranus (zoomed)
|
||||

|
||||
|
||||
### Neptune
|
||||

|
||||
|
||||
### Neptune (zoomed)
|
||||

|
||||
1019
legacy/lib/vsop87/vsop87a_micro.c
Executable file
1019
legacy/lib/vsop87/vsop87a_micro.c
Executable file
File diff suppressed because it is too large
Load Diff
17
legacy/lib/vsop87/vsop87a_micro.h
Executable file
17
legacy/lib/vsop87/vsop87a_micro.h
Executable file
@@ -0,0 +1,17 @@
|
||||
//VSOP87-Multilang http://www.astrogreg.com/vsop87-multilang/index.html
|
||||
//Greg Miller (gmiller@gregmiller.net) 2019. Released as Public Domain
|
||||
|
||||
#ifndef VSOP87A_MICRO
|
||||
#define VSOP87A_MICRO
|
||||
|
||||
void vsop87a_micro_getEarth(double t,double temp[]);
|
||||
void vsop87a_micro_getEmb(double t,double temp[]);
|
||||
void vsop87a_micro_getJupiter(double t,double temp[]);
|
||||
void vsop87a_micro_getMars(double t,double temp[]);
|
||||
void vsop87a_micro_getMercury(double t,double temp[]);
|
||||
void vsop87a_micro_getNeptune(double t,double temp[]);
|
||||
void vsop87a_micro_getSaturn(double t,double temp[]);
|
||||
void vsop87a_micro_getUranus(double t,double temp[]);
|
||||
void vsop87a_micro_getVenus(double t,double temp[]);
|
||||
void vsop87a_micro_getMoon(double earth[], double emb[],double temp[]);
|
||||
#endif
|
||||
2048
legacy/lib/vsop87/vsop87a_milli.c
Executable file
2048
legacy/lib/vsop87/vsop87a_milli.c
Executable file
File diff suppressed because it is too large
Load Diff
17
legacy/lib/vsop87/vsop87a_milli.h
Executable file
17
legacy/lib/vsop87/vsop87a_milli.h
Executable file
@@ -0,0 +1,17 @@
|
||||
//VSOP87-Multilang http://www.astrogreg.com/vsop87-multilang/index.html
|
||||
//Greg Miller (gmiller@gregmiller.net) 2019. Released as Public Domain
|
||||
|
||||
#ifndef VSOP87A_MILLI
|
||||
#define VSOP87A_MILLI
|
||||
|
||||
void vsop87a_milli_getEarth(double t,double temp[]);
|
||||
void vsop87a_milli_getEmb(double t,double temp[]);
|
||||
void vsop87a_milli_getJupiter(double t,double temp[]);
|
||||
void vsop87a_milli_getMars(double t,double temp[]);
|
||||
void vsop87a_milli_getMercury(double t,double temp[]);
|
||||
void vsop87a_milli_getNeptune(double t,double temp[]);
|
||||
void vsop87a_milli_getSaturn(double t,double temp[]);
|
||||
void vsop87a_milli_getUranus(double t,double temp[]);
|
||||
void vsop87a_milli_getVenus(double t,double temp[]);
|
||||
void vsop87a_milli_getMoon(double earth[], double emb[],double temp[]);
|
||||
#endif
|
||||
Reference in New Issue
Block a user