mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-15 01:08:35 -07:00
Format
This commit is contained in:
385
applications/external/esubghz_chat/crypto/aes.c
vendored
385
applications/external/esubghz_chat/crypto/aes.c
vendored
@@ -37,7 +37,7 @@ static int aes_tables_inited = 0; // run-once flag for performing key
|
|||||||
* the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
|
* the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
|
||||||
* decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
|
* decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
|
||||||
*/
|
*/
|
||||||
// We always need our forward tables
|
// We always need our forward tables
|
||||||
static uchar FSb[256]; // Forward substitution box (FSb)
|
static uchar FSb[256]; // Forward substitution box (FSb)
|
||||||
static uint32_t FT0[256]; // Forward key schedule assembly tables
|
static uint32_t FT0[256]; // Forward key schedule assembly tables
|
||||||
static uint32_t FT1[256];
|
static uint32_t FT1[256];
|
||||||
@@ -58,78 +58,73 @@ static uint32_t RCON[10]; // AES round constants
|
|||||||
* Platform Endianness Neutralizing Load and Store Macro definitions
|
* Platform Endianness Neutralizing Load and Store Macro definitions
|
||||||
* AES wants platform-neutral Little Endian (LE) byte ordering
|
* AES wants platform-neutral Little Endian (LE) byte ordering
|
||||||
*/
|
*/
|
||||||
#define GET_UINT32_LE(n,b,i) { \
|
#define GET_UINT32_LE(n, b, i) \
|
||||||
(n) = ( (uint32_t) (b)[(i) ] ) \
|
{ \
|
||||||
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
|
(n) = ((uint32_t)(b)[(i)]) | ((uint32_t)(b)[(i) + 1] << 8) | \
|
||||||
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
|
((uint32_t)(b)[(i) + 2] << 16) | ((uint32_t)(b)[(i) + 3] << 24); \
|
||||||
| ( (uint32_t) (b)[(i) + 3] << 24 ); }
|
}
|
||||||
|
|
||||||
#define PUT_UINT32_LE(n,b,i) { \
|
#define PUT_UINT32_LE(n, b, i) \
|
||||||
(b)[(i) ] = (uchar) ( (n) ); \
|
{ \
|
||||||
(b)[(i) + 1] = (uchar) ( (n) >> 8 ); \
|
(b)[(i)] = (uchar)((n)); \
|
||||||
(b)[(i) + 2] = (uchar) ( (n) >> 16 ); \
|
(b)[(i) + 1] = (uchar)((n) >> 8); \
|
||||||
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
|
(b)[(i) + 2] = (uchar)((n) >> 16); \
|
||||||
|
(b)[(i) + 3] = (uchar)((n) >> 24); \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES forward and reverse encryption round processing macros
|
* AES forward and reverse encryption round processing macros
|
||||||
*/
|
*/
|
||||||
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
|
#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||||
{ \
|
{ \
|
||||||
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
|
X0 = *RK++ ^ FT0[(Y0)&0xFF] ^ FT1[(Y1 >> 8) & 0xFF] ^ FT2[(Y2 >> 16) & 0xFF] ^ \
|
||||||
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
|
FT3[(Y3 >> 24) & 0xFF]; \
|
||||||
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
|
|
||||||
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
|
X1 = *RK++ ^ FT0[(Y1)&0xFF] ^ FT1[(Y2 >> 8) & 0xFF] ^ FT2[(Y3 >> 16) & 0xFF] ^ \
|
||||||
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
|
FT3[(Y0 >> 24) & 0xFF]; \
|
||||||
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
|
|
||||||
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
|
X2 = *RK++ ^ FT0[(Y2)&0xFF] ^ FT1[(Y3 >> 8) & 0xFF] ^ FT2[(Y0 >> 16) & 0xFF] ^ \
|
||||||
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
|
FT3[(Y1 >> 24) & 0xFF]; \
|
||||||
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
|
|
||||||
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
|
X3 = *RK++ ^ FT0[(Y3)&0xFF] ^ FT1[(Y0 >> 8) & 0xFF] ^ FT2[(Y1 >> 16) & 0xFF] ^ \
|
||||||
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
|
FT3[(Y2 >> 24) & 0xFF]; \
|
||||||
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
|
}
|
||||||
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
|
#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
|
||||||
{ \
|
{ \
|
||||||
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
|
X0 = *RK++ ^ RT0[(Y0)&0xFF] ^ RT1[(Y3 >> 8) & 0xFF] ^ RT2[(Y2 >> 16) & 0xFF] ^ \
|
||||||
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
|
RT3[(Y1 >> 24) & 0xFF]; \
|
||||||
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
|
|
||||||
RT3[ ( Y1 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
|
X1 = *RK++ ^ RT0[(Y1)&0xFF] ^ RT1[(Y0 >> 8) & 0xFF] ^ RT2[(Y3 >> 16) & 0xFF] ^ \
|
||||||
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
|
RT3[(Y2 >> 24) & 0xFF]; \
|
||||||
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
|
|
||||||
RT3[ ( Y2 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
|
X2 = *RK++ ^ RT0[(Y2)&0xFF] ^ RT1[(Y1 >> 8) & 0xFF] ^ RT2[(Y0 >> 16) & 0xFF] ^ \
|
||||||
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
|
RT3[(Y3 >> 24) & 0xFF]; \
|
||||||
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
|
|
||||||
RT3[ ( Y3 >> 24 ) & 0xFF ]; \
|
|
||||||
\
|
\
|
||||||
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
|
X3 = *RK++ ^ RT0[(Y3)&0xFF] ^ RT1[(Y2 >> 8) & 0xFF] ^ RT2[(Y1 >> 16) & 0xFF] ^ \
|
||||||
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
|
RT3[(Y0 >> 24) & 0xFF]; \
|
||||||
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
|
}
|
||||||
RT3[ ( Y0 >> 24 ) & 0xFF ]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These macros improve the readability of the key
|
* These macros improve the readability of the key
|
||||||
* generation initialization code by collapsing
|
* generation initialization code by collapsing
|
||||||
* repetitive common operations into logical pieces.
|
* repetitive common operations into logical pieces.
|
||||||
*/
|
*/
|
||||||
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
|
#define ROTL8(x) ((x << 8) & 0xFFFFFFFF) | (x >> 24)
|
||||||
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
|
#define XTIME(x) ((x << 1) ^ ((x & 0x80) ? 0x1B : 0x00))
|
||||||
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
|
#define MUL(x, y) ((x && y) ? pow[(log[x] + log[y]) % 255] : 0)
|
||||||
#define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
|
#define MIX(x, y) \
|
||||||
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \
|
{ \
|
||||||
*RK++ = *SK++; *RK++ = *SK++; }
|
y = ((y << 1) | (y >> 7)) & 0xFF; \
|
||||||
|
x ^= y; \
|
||||||
|
}
|
||||||
|
#define CPY128 \
|
||||||
|
{ \
|
||||||
|
*RK++ = *SK++; \
|
||||||
|
*RK++ = *SK++; \
|
||||||
|
*RK++ = *SK++; \
|
||||||
|
*RK++ = *SK++; \
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -141,24 +136,23 @@ static uint32_t RCON[10]; // AES round constants
|
|||||||
* at system initialization to setup the tables for all subsequent use.
|
* at system initialization to setup the tables for all subsequent use.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void aes_init_keygen_tables( void )
|
void aes_init_keygen_tables(void) {
|
||||||
{
|
|
||||||
int i, x, y, z; // general purpose iteration and computation locals
|
int i, x, y, z; // general purpose iteration and computation locals
|
||||||
int pow[256];
|
int pow[256];
|
||||||
int log[256];
|
int log[256];
|
||||||
|
|
||||||
if (aes_tables_inited) return;
|
if(aes_tables_inited) return;
|
||||||
|
|
||||||
// fill the 'pow' and 'log' tables over GF(2^8)
|
// fill the 'pow' and 'log' tables over GF(2^8)
|
||||||
for( i = 0, x = 1; i < 256; i++ ) {
|
for(i = 0, x = 1; i < 256; i++) {
|
||||||
pow[i] = x;
|
pow[i] = x;
|
||||||
log[x] = i;
|
log[x] = i;
|
||||||
x = ( x ^ XTIME( x ) ) & 0xFF;
|
x = (x ^ XTIME(x)) & 0xFF;
|
||||||
}
|
}
|
||||||
// compute the round constants
|
// compute the round constants
|
||||||
for( i = 0, x = 1; i < 10; i++ ) {
|
for(i = 0, x = 1; i < 10; i++) {
|
||||||
RCON[i] = (uint32_t) x;
|
RCON[i] = (uint32_t)x;
|
||||||
x = XTIME( x ) & 0xFF;
|
x = XTIME(x) & 0xFF;
|
||||||
}
|
}
|
||||||
// fill the forward and reverse substitution boxes
|
// fill the forward and reverse substitution boxes
|
||||||
FSb[0x00] = 0x63;
|
FSb[0x00] = 0x63;
|
||||||
@@ -166,42 +160,38 @@ void aes_init_keygen_tables( void )
|
|||||||
RSb[0x63] = 0x00;
|
RSb[0x63] = 0x00;
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
|
|
||||||
for( i = 1; i < 256; i++ ) {
|
for(i = 1; i < 256; i++) {
|
||||||
x = y = pow[255 - log[i]];
|
x = y = pow[255 - log[i]];
|
||||||
MIX(x,y);
|
MIX(x, y);
|
||||||
MIX(x,y);
|
MIX(x, y);
|
||||||
MIX(x,y);
|
MIX(x, y);
|
||||||
MIX(x,y);
|
MIX(x, y);
|
||||||
FSb[i] = (uchar) ( x ^= 0x63 );
|
FSb[i] = (uchar)(x ^= 0x63);
|
||||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||||
RSb[x] = (uchar) i;
|
RSb[x] = (uchar)i;
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
|
|
||||||
}
|
}
|
||||||
// generate the forward and reverse key expansion tables
|
// generate the forward and reverse key expansion tables
|
||||||
for( i = 0; i < 256; i++ ) {
|
for(i = 0; i < 256; i++) {
|
||||||
x = FSb[i];
|
x = FSb[i];
|
||||||
y = XTIME( x ) & 0xFF;
|
y = XTIME(x) & 0xFF;
|
||||||
z = ( y ^ x ) & 0xFF;
|
z = (y ^ x) & 0xFF;
|
||||||
|
|
||||||
FT0[i] = ( (uint32_t) y ) ^ ( (uint32_t) x << 8 ) ^
|
FT0[i] = ((uint32_t)y) ^ ((uint32_t)x << 8) ^ ((uint32_t)x << 16) ^ ((uint32_t)z << 24);
|
||||||
( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 );
|
|
||||||
|
|
||||||
FT1[i] = ROTL8( FT0[i] );
|
FT1[i] = ROTL8(FT0[i]);
|
||||||
FT2[i] = ROTL8( FT1[i] );
|
FT2[i] = ROTL8(FT1[i]);
|
||||||
FT3[i] = ROTL8( FT2[i] );
|
FT3[i] = ROTL8(FT2[i]);
|
||||||
|
|
||||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||||
x = RSb[i];
|
x = RSb[i];
|
||||||
|
|
||||||
RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
|
RT0[i] = ((uint32_t)MUL(0x0E, x)) ^ ((uint32_t)MUL(0x09, x) << 8) ^
|
||||||
( (uint32_t) MUL( 0x09, x ) << 8 ) ^
|
((uint32_t)MUL(0x0D, x) << 16) ^ ((uint32_t)MUL(0x0B, x) << 24);
|
||||||
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
|
|
||||||
( (uint32_t) MUL( 0x0B, x ) << 24 );
|
|
||||||
|
|
||||||
RT1[i] = ROTL8( RT0[i] );
|
RT1[i] = ROTL8(RT0[i]);
|
||||||
RT2[i] = ROTL8( RT1[i] );
|
RT2[i] = ROTL8(RT1[i]);
|
||||||
RT3[i] = ROTL8( RT2[i] );
|
RT3[i] = ROTL8(RT2[i]);
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
}
|
}
|
||||||
aes_tables_inited = 1; // flag that the tables have been generated
|
aes_tables_inited = 1; // flag that the tables have been generated
|
||||||
@@ -217,26 +207,21 @@ void aes_init_keygen_tables( void )
|
|||||||
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
|
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_set_encryption_key( aes_context *ctx,
|
int aes_set_encryption_key(aes_context* ctx, const uchar* key, uint keysize) {
|
||||||
const uchar *key,
|
|
||||||
uint keysize )
|
|
||||||
{
|
|
||||||
uint i; // general purpose iteration local
|
uint i; // general purpose iteration local
|
||||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
uint32_t* RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||||
|
|
||||||
for( i = 0; i < (keysize >> 2); i++ ) {
|
for(i = 0; i < (keysize >> 2); i++) {
|
||||||
GET_UINT32_LE( RK[i], key, i << 2 );
|
GET_UINT32_LE(RK[i], key, i << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( ctx->rounds )
|
switch(ctx->rounds) {
|
||||||
{
|
|
||||||
case 10:
|
case 10:
|
||||||
for( i = 0; i < 10; i++, RK += 4 ) {
|
for(i = 0; i < 10; i++, RK += 4) {
|
||||||
RK[4] = RK[0] ^ RCON[i] ^
|
RK[4] = RK[0] ^ RCON[i] ^ ((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^
|
||||||
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
|
((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^
|
||||||
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
|
((uint32_t)FSb[(RK[3]) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
RK[5] = RK[1] ^ RK[4];
|
RK[5] = RK[1] ^ RK[4];
|
||||||
RK[6] = RK[2] ^ RK[5];
|
RK[6] = RK[2] ^ RK[5];
|
||||||
@@ -245,12 +230,11 @@ int aes_set_encryption_key( aes_context *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
for( i = 0; i < 8; i++, RK += 6 ) {
|
for(i = 0; i < 8; i++, RK += 6) {
|
||||||
RK[6] = RK[0] ^ RCON[i] ^
|
RK[6] = RK[0] ^ RCON[i] ^ ((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^
|
||||||
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
|
((uint32_t)FSb[(RK[5] >> 24) & 0xFF] << 16) ^
|
||||||
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
|
((uint32_t)FSb[(RK[5]) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
RK[7] = RK[1] ^ RK[6];
|
RK[7] = RK[1] ^ RK[6];
|
||||||
RK[8] = RK[2] ^ RK[7];
|
RK[8] = RK[2] ^ RK[7];
|
||||||
@@ -261,22 +245,20 @@ int aes_set_encryption_key( aes_context *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 14:
|
case 14:
|
||||||
for( i = 0; i < 7; i++, RK += 8 ) {
|
for(i = 0; i < 7; i++, RK += 8) {
|
||||||
RK[8] = RK[0] ^ RCON[i] ^
|
RK[8] = RK[0] ^ RCON[i] ^ ((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^
|
||||||
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
|
((uint32_t)FSb[(RK[7] >> 24) & 0xFF] << 16) ^
|
||||||
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
|
((uint32_t)FSb[(RK[7]) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
RK[9] = RK[1] ^ RK[8];
|
RK[9] = RK[1] ^ RK[8];
|
||||||
RK[10] = RK[2] ^ RK[9];
|
RK[10] = RK[2] ^ RK[9];
|
||||||
RK[11] = RK[3] ^ RK[10];
|
RK[11] = RK[3] ^ RK[10];
|
||||||
|
|
||||||
RK[12] = RK[4] ^
|
RK[12] = RK[4] ^ ((uint32_t)FSb[(RK[11]) & 0xFF]) ^
|
||||||
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
|
((uint32_t)FSb[(RK[11] >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
|
((uint32_t)FSb[(RK[11] >> 16) & 0xFF] << 16) ^
|
||||||
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
|
((uint32_t)FSb[(RK[11] >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
RK[13] = RK[5] ^ RK[12];
|
RK[13] = RK[5] ^ RK[12];
|
||||||
RK[14] = RK[6] ^ RK[13];
|
RK[14] = RK[6] ^ RK[13];
|
||||||
@@ -287,7 +269,7 @@ int aes_set_encryption_key( aes_context *ctx,
|
|||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||||
@@ -302,37 +284,31 @@ int aes_set_encryption_key( aes_context *ctx,
|
|||||||
* length in bits. Valid lengths are: 128, 192, or 256 bits.
|
* length in bits. Valid lengths are: 128, 192, or 256 bits.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_set_decryption_key( aes_context *ctx,
|
int aes_set_decryption_key(aes_context* ctx, const uchar* key, uint keysize) {
|
||||||
const uchar *key,
|
|
||||||
uint keysize )
|
|
||||||
{
|
|
||||||
int i, j;
|
int i, j;
|
||||||
aes_context cty; // a calling aes context for set_encryption_key
|
aes_context cty; // a calling aes context for set_encryption_key
|
||||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
uint32_t* RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||||
uint32_t *SK;
|
uint32_t* SK;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cty.rounds = ctx->rounds; // initialize our local aes context
|
cty.rounds = ctx->rounds; // initialize our local aes context
|
||||||
cty.rk = cty.buf; // round count and key buf pointer
|
cty.rk = cty.buf; // round count and key buf pointer
|
||||||
|
|
||||||
if (( ret = aes_set_encryption_key( &cty, key, keysize )) != 0 )
|
if((ret = aes_set_encryption_key(&cty, key, keysize)) != 0) return (ret);
|
||||||
return( ret );
|
|
||||||
|
|
||||||
SK = cty.rk + cty.rounds * 4;
|
SK = cty.rk + cty.rounds * 4;
|
||||||
|
|
||||||
CPY128 // copy a 128-bit block from *SK to *RK
|
CPY128 // copy a 128-bit block from *SK to *RK
|
||||||
|
|
||||||
for( i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8 ) {
|
for(i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8) {
|
||||||
for( j = 0; j < 4; j++, SK++ ) {
|
for(j = 0; j < 4; j++, SK++) {
|
||||||
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
|
*RK++ = RT0[FSb[(*SK) & 0xFF]] ^ RT1[FSb[(*SK >> 8) & 0xFF]] ^
|
||||||
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
|
RT2[FSb[(*SK >> 16) & 0xFF]] ^ RT3[FSb[(*SK >> 24) & 0xFF]];
|
||||||
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
|
|
||||||
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CPY128 // copy a 128-bit block from *SK to *RK
|
CPY128 // copy a 128-bit block from *SK to *RK
|
||||||
memset( &cty, 0, sizeof( aes_context ) ); // clear local aes context
|
memset(&cty, 0, sizeof(aes_context)); // clear local aes context
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
@@ -344,34 +320,42 @@ int aes_set_decryption_key( aes_context *ctx,
|
|||||||
* Invoked to establish the key schedule for subsequent encryption/decryption
|
* Invoked to establish the key schedule for subsequent encryption/decryption
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_setkey( aes_context *ctx, // AES context provided by our caller
|
int aes_setkey(
|
||||||
|
aes_context* ctx, // AES context provided by our caller
|
||||||
int mode, // ENCRYPT or DECRYPT flag
|
int mode, // ENCRYPT or DECRYPT flag
|
||||||
const uchar *key, // pointer to the key
|
const uchar* key, // pointer to the key
|
||||||
uint keysize ) // key length in bytes
|
uint keysize) // key length in bytes
|
||||||
{
|
{
|
||||||
// since table initialization is not thread safe, we could either add
|
// since table initialization is not thread safe, we could either add
|
||||||
// system-specific mutexes and init the AES key generation tables on
|
// system-specific mutexes and init the AES key generation tables on
|
||||||
// demand, or ask the developer to simply call "gcm_initialize" once during
|
// demand, or ask the developer to simply call "gcm_initialize" once during
|
||||||
// application startup before threading begins. That's what we choose.
|
// application startup before threading begins. That's what we choose.
|
||||||
if( !aes_tables_inited ) return ( -1 ); // fail the call when not inited.
|
if(!aes_tables_inited) return (-1); // fail the call when not inited.
|
||||||
|
|
||||||
ctx->mode = mode; // capture the key type we're creating
|
ctx->mode = mode; // capture the key type we're creating
|
||||||
ctx->rk = ctx->buf; // initialize our round key pointer
|
ctx->rk = ctx->buf; // initialize our round key pointer
|
||||||
|
|
||||||
switch( keysize ) // set the rounds count based upon the keysize
|
switch(keysize) // set the rounds count based upon the keysize
|
||||||
{
|
{
|
||||||
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
|
case 16:
|
||||||
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
|
ctx->rounds = 10;
|
||||||
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
|
break; // 16-byte, 128-bit key
|
||||||
default: return(-1);
|
case 24:
|
||||||
|
ctx->rounds = 12;
|
||||||
|
break; // 24-byte, 192-bit key
|
||||||
|
case 32:
|
||||||
|
ctx->rounds = 14;
|
||||||
|
break; // 32-byte, 256-bit key
|
||||||
|
default:
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if AES_DECRYPTION
|
#if AES_DECRYPTION
|
||||||
if( mode == DECRYPT ) // expand our key for encryption or decryption
|
if(mode == DECRYPT) // expand our key for encryption or decryption
|
||||||
return( aes_set_decryption_key( ctx, key, keysize ) );
|
return (aes_set_decryption_key(ctx, key, keysize));
|
||||||
else /* ENCRYPT */
|
else /* ENCRYPT */
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
return( aes_set_encryption_key( ctx, key, keysize ) );
|
return (aes_set_encryption_key(ctx, key, keysize));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -383,101 +367,74 @@ int aes_setkey( aes_context *ctx, // AES context provided by our caller
|
|||||||
* and all keying information appropriate for the task.
|
* and all keying information appropriate for the task.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_cipher( aes_context *ctx,
|
int aes_cipher(aes_context* ctx, const uchar input[16], uchar output[16]) {
|
||||||
const uchar input[16],
|
|
||||||
uchar output[16] )
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
||||||
|
|
||||||
RK = ctx->rk;
|
RK = ctx->rk;
|
||||||
|
|
||||||
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; // load our 128-bit
|
GET_UINT32_LE(X0, input, 0);
|
||||||
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; // input buffer in a storage
|
X0 ^= *RK++; // load our 128-bit
|
||||||
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; // memory endian-neutral way
|
GET_UINT32_LE(X1, input, 4);
|
||||||
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
|
X1 ^= *RK++; // input buffer in a storage
|
||||||
|
GET_UINT32_LE(X2, input, 8);
|
||||||
|
X2 ^= *RK++; // memory endian-neutral way
|
||||||
|
GET_UINT32_LE(X3, input, 12);
|
||||||
|
X3 ^= *RK++;
|
||||||
|
|
||||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||||
|
|
||||||
if( ctx->mode == DECRYPT )
|
if(ctx->mode == DECRYPT) {
|
||||||
{
|
for(i = (ctx->rounds >> 1) - 1; i > 0; i--) {
|
||||||
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
|
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||||
{
|
AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
|
||||||
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
|
||||||
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||||
|
|
||||||
X0 = *RK++ ^ \
|
X0 = *RK++ ^ ((uint32_t)RSb[(Y0)&0xFF]) ^ ((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
|
((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^ ((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X1 = *RK++ ^ \
|
X1 = *RK++ ^ ((uint32_t)RSb[(Y1)&0xFF]) ^ ((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
|
((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^ ((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X2 = *RK++ ^ \
|
X2 = *RK++ ^ ((uint32_t)RSb[(Y2)&0xFF]) ^ ((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
|
((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^ ((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X3 = *RK++ ^ \
|
X3 = *RK++ ^ ((uint32_t)RSb[(Y3)&0xFF]) ^ ((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
|
((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^ ((uint32_t)RSb[(Y0 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
|
} else /* ENCRYPT */
|
||||||
( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
}
|
|
||||||
else /* ENCRYPT */
|
|
||||||
{
|
{
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
|
|
||||||
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
|
for(i = (ctx->rounds >> 1) - 1; i > 0; i--) {
|
||||||
{
|
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||||
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
|
||||||
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
|
||||||
|
|
||||||
X0 = *RK++ ^ \
|
X0 = *RK++ ^ ((uint32_t)FSb[(Y0)&0xFF]) ^ ((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^ ((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X1 = *RK++ ^ \
|
X1 = *RK++ ^ ((uint32_t)FSb[(Y1)&0xFF]) ^ ((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^ ((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X2 = *RK++ ^ \
|
X2 = *RK++ ^ ((uint32_t)FSb[(Y2)&0xFF]) ^ ((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^ ((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
X3 = *RK++ ^ \
|
X3 = *RK++ ^ ((uint32_t)FSb[(Y3)&0xFF]) ^ ((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^
|
||||||
( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
|
((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^ ((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24);
|
||||||
( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
|
|
||||||
( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
|
|
||||||
|
|
||||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||||
}
|
}
|
||||||
#endif /* AES_DECRYPTION */
|
#endif /* AES_DECRYPTION */
|
||||||
|
|
||||||
PUT_UINT32_LE( X0, output, 0 );
|
PUT_UINT32_LE(X0, output, 0);
|
||||||
PUT_UINT32_LE( X1, output, 4 );
|
PUT_UINT32_LE(X1, output, 4);
|
||||||
PUT_UINT32_LE( X2, output, 8 );
|
PUT_UINT32_LE(X2, output, 8);
|
||||||
PUT_UINT32_LE( X3, output, 12 );
|
PUT_UINT32_LE(X3, output, 12);
|
||||||
|
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
/* end of aes.c */
|
/* end of aes.c */
|
||||||
|
|||||||
25
applications/external/esubghz_chat/crypto/aes.h
vendored
25
applications/external/esubghz_chat/crypto/aes.h
vendored
@@ -33,21 +33,19 @@
|
|||||||
#define DECRYPT 0 // or decrypting
|
#define DECRYPT 0 // or decrypting
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <basetsd.h>
|
#include <basetsd.h>
|
||||||
typedef UINT32 uint32_t;
|
typedef UINT32 uint32_t;
|
||||||
#else
|
#else
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned char uchar; // add some convienent shorter types
|
typedef unsigned char uchar; // add some convienent shorter types
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void aes_init_keygen_tables( void );
|
void aes_init_keygen_tables(void);
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* AES_CONTEXT : cipher context / holds inter-call data
|
* AES_CONTEXT : cipher context / holds inter-call data
|
||||||
@@ -55,27 +53,28 @@ void aes_init_keygen_tables( void );
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int mode; // 1 for Encryption, 0 for Decryption
|
int mode; // 1 for Encryption, 0 for Decryption
|
||||||
int rounds; // keysize-based rounds count
|
int rounds; // keysize-based rounds count
|
||||||
uint32_t *rk; // pointer to current round key
|
uint32_t* rk; // pointer to current round key
|
||||||
uint32_t buf[68]; // key expansion buffer
|
uint32_t buf[68]; // key expansion buffer
|
||||||
} aes_context;
|
} aes_context;
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* AES_SETKEY : called to expand the key for encryption or decryption
|
* AES_SETKEY : called to expand the key for encryption or decryption
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_setkey( aes_context *ctx, // pointer to context
|
int aes_setkey(
|
||||||
|
aes_context* ctx, // pointer to context
|
||||||
int mode, // 1 or 0 for Encrypt/Decrypt
|
int mode, // 1 or 0 for Encrypt/Decrypt
|
||||||
const uchar *key, // AES input key
|
const uchar* key, // AES input key
|
||||||
uint keysize ); // size in bytes (must be 16, 24, 32 for
|
uint keysize); // size in bytes (must be 16, 24, 32 for
|
||||||
// 128, 192 or 256-bit keys respectively)
|
// 128, 192 or 256-bit keys respectively)
|
||||||
// returns 0 for success
|
// returns 0 for success
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
|
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int aes_cipher( aes_context *ctx, // pointer to context
|
int aes_cipher(
|
||||||
|
aes_context* ctx, // pointer to context
|
||||||
const uchar input[16], // 128-bit block to en/decipher
|
const uchar input[16], // 128-bit block to en/decipher
|
||||||
uchar output[16] ); // 128-bit output result block
|
uchar output[16]); // 128-bit output result block
|
||||||
// returns 0 for success
|
// returns 0 for success
|
||||||
|
|
||||||
#endif /* AES_HEADER */
|
#endif /* AES_HEADER */
|
||||||
|
|||||||
307
applications/external/esubghz_chat/crypto/gcm.c
vendored
307
applications/external/esubghz_chat/crypto/gcm.c
vendored
@@ -76,25 +76,40 @@
|
|||||||
* significantly slower 128x128 bit multiple within GF(2^128).
|
* significantly slower 128x128 bit multiple within GF(2^128).
|
||||||
*/
|
*/
|
||||||
static const uint64_t last4[16] = {
|
static const uint64_t last4[16] = {
|
||||||
0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
|
0x0000,
|
||||||
0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 };
|
0x1c20,
|
||||||
|
0x3840,
|
||||||
|
0x2460,
|
||||||
|
0x7080,
|
||||||
|
0x6ca0,
|
||||||
|
0x48c0,
|
||||||
|
0x54e0,
|
||||||
|
0xe100,
|
||||||
|
0xfd20,
|
||||||
|
0xd940,
|
||||||
|
0xc560,
|
||||||
|
0x9180,
|
||||||
|
0x8da0,
|
||||||
|
0xa9c0,
|
||||||
|
0xb5e0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform Endianness Neutralizing Load and Store Macro definitions
|
* Platform Endianness Neutralizing Load and Store Macro definitions
|
||||||
* GCM wants platform-neutral Big Endian (BE) byte ordering
|
* GCM wants platform-neutral Big Endian (BE) byte ordering
|
||||||
*/
|
*/
|
||||||
#define GET_UINT32_BE(n,b,i) { \
|
#define GET_UINT32_BE(n, b, i) \
|
||||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
{ \
|
||||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
(n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | \
|
||||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \
|
||||||
| ( (uint32_t) (b)[(i) + 3] ); }
|
}
|
||||||
|
|
||||||
#define PUT_UINT32_BE(n,b,i) { \
|
|
||||||
(b)[(i) ] = (uchar) ( (n) >> 24 ); \
|
|
||||||
(b)[(i) + 1] = (uchar) ( (n) >> 16 ); \
|
|
||||||
(b)[(i) + 2] = (uchar) ( (n) >> 8 ); \
|
|
||||||
(b)[(i) + 3] = (uchar) ( (n) ); }
|
|
||||||
|
|
||||||
|
#define PUT_UINT32_BE(n, b, i) \
|
||||||
|
{ \
|
||||||
|
(b)[(i)] = (uchar)((n) >> 24); \
|
||||||
|
(b)[(i) + 1] = (uchar)((n) >> 16); \
|
||||||
|
(b)[(i) + 2] = (uchar)((n) >> 8); \
|
||||||
|
(b)[(i) + 3] = (uchar)((n)); \
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -108,13 +123,11 @@ static const uint64_t last4[16] = {
|
|||||||
* environment is running.
|
* environment is running.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_initialize( void )
|
int gcm_initialize(void) {
|
||||||
{
|
|
||||||
aes_init_keygen_tables();
|
aes_init_keygen_tables();
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM_MULT
|
* GCM_MULT
|
||||||
@@ -124,45 +137,45 @@ int gcm_initialize( void )
|
|||||||
* 'x' and 'output' are seen as elements of GCM's GF(2^128) Galois field.
|
* 'x' and 'output' are seen as elements of GCM's GF(2^128) Galois field.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static void gcm_mult( gcm_context *ctx, // pointer to established context
|
static void gcm_mult(
|
||||||
|
gcm_context* ctx, // pointer to established context
|
||||||
const uchar x[16], // pointer to 128-bit input vector
|
const uchar x[16], // pointer to 128-bit input vector
|
||||||
uchar output[16] ) // pointer to 128-bit output vector
|
uchar output[16]) // pointer to 128-bit output vector
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uchar lo, hi, rem;
|
uchar lo, hi, rem;
|
||||||
uint64_t zh, zl;
|
uint64_t zh, zl;
|
||||||
|
|
||||||
lo = (uchar)( x[15] & 0x0f );
|
lo = (uchar)(x[15] & 0x0f);
|
||||||
hi = (uchar)( x[15] >> 4 );
|
hi = (uchar)(x[15] >> 4);
|
||||||
zh = ctx->HH[lo];
|
zh = ctx->HH[lo];
|
||||||
zl = ctx->HL[lo];
|
zl = ctx->HL[lo];
|
||||||
|
|
||||||
for( i = 15; i >= 0; i-- ) {
|
for(i = 15; i >= 0; i--) {
|
||||||
lo = (uchar) ( x[i] & 0x0f );
|
lo = (uchar)(x[i] & 0x0f);
|
||||||
hi = (uchar) ( x[i] >> 4 );
|
hi = (uchar)(x[i] >> 4);
|
||||||
|
|
||||||
if( i != 15 ) {
|
if(i != 15) {
|
||||||
rem = (uchar) ( zl & 0x0f );
|
rem = (uchar)(zl & 0x0f);
|
||||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
zl = (zh << 60) | (zl >> 4);
|
||||||
zh = ( zh >> 4 );
|
zh = (zh >> 4);
|
||||||
zh ^= (uint64_t) last4[rem] << 48;
|
zh ^= (uint64_t)last4[rem] << 48;
|
||||||
zh ^= ctx->HH[lo];
|
zh ^= ctx->HH[lo];
|
||||||
zl ^= ctx->HL[lo];
|
zl ^= ctx->HL[lo];
|
||||||
}
|
}
|
||||||
rem = (uchar) ( zl & 0x0f );
|
rem = (uchar)(zl & 0x0f);
|
||||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
zl = (zh << 60) | (zl >> 4);
|
||||||
zh = ( zh >> 4 );
|
zh = (zh >> 4);
|
||||||
zh ^= (uint64_t) last4[rem] << 48;
|
zh ^= (uint64_t)last4[rem] << 48;
|
||||||
zh ^= ctx->HH[hi];
|
zh ^= ctx->HH[hi];
|
||||||
zl ^= ctx->HL[hi];
|
zl ^= ctx->HL[hi];
|
||||||
}
|
}
|
||||||
PUT_UINT32_BE( zh >> 32, output, 0 );
|
PUT_UINT32_BE(zh >> 32, output, 0);
|
||||||
PUT_UINT32_BE( zh, output, 4 );
|
PUT_UINT32_BE(zh, output, 4);
|
||||||
PUT_UINT32_BE( zl >> 32, output, 8 );
|
PUT_UINT32_BE(zl >> 32, output, 8);
|
||||||
PUT_UINT32_BE( zl, output, 12 );
|
PUT_UINT32_BE(zl, output, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM_SETKEY
|
* GCM_SETKEY
|
||||||
@@ -171,59 +184,57 @@ static void gcm_mult( gcm_context *ctx, // pointer to established context
|
|||||||
* and populates the gcm context's pre-calculated HTables.
|
* and populates the gcm context's pre-calculated HTables.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_setkey( gcm_context *ctx, // pointer to caller-provided gcm context
|
int gcm_setkey(
|
||||||
const uchar *key, // pointer to the AES encryption key
|
gcm_context* ctx, // pointer to caller-provided gcm context
|
||||||
|
const uchar* key, // pointer to the AES encryption key
|
||||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||||
// 128, 192 or 256-bit keys respectively)
|
// 128, 192 or 256-bit keys respectively)
|
||||||
{
|
{
|
||||||
int ret, i, j;
|
int ret, i, j;
|
||||||
uint64_t hi, lo;
|
uint64_t hi, lo;
|
||||||
uint64_t vl, vh;
|
uint64_t vl, vh;
|
||||||
unsigned char h[16];
|
unsigned char h[16];
|
||||||
|
|
||||||
memset( ctx, 0, sizeof(gcm_context) ); // zero caller-provided GCM context
|
memset(ctx, 0, sizeof(gcm_context)); // zero caller-provided GCM context
|
||||||
memset( h, 0, 16 ); // initialize the block to encrypt
|
memset(h, 0, 16); // initialize the block to encrypt
|
||||||
|
|
||||||
// encrypt the null 128-bit block to generate a key-based value
|
// encrypt the null 128-bit block to generate a key-based value
|
||||||
// which is then used to initialize our GHASH lookup tables
|
// which is then used to initialize our GHASH lookup tables
|
||||||
if(( ret = aes_setkey( &ctx->aes_ctx, ENCRYPT, key, keysize )) != 0 )
|
if((ret = aes_setkey(&ctx->aes_ctx, ENCRYPT, key, keysize)) != 0) return (ret);
|
||||||
return( ret );
|
if((ret = aes_cipher(&ctx->aes_ctx, h, h)) != 0) return (ret);
|
||||||
if(( ret = aes_cipher( &ctx->aes_ctx, h, h )) != 0 )
|
|
||||||
return( ret );
|
|
||||||
|
|
||||||
GET_UINT32_BE( hi, h, 0 ); // pack h as two 64-bit ints, big-endian
|
GET_UINT32_BE(hi, h, 0); // pack h as two 64-bit ints, big-endian
|
||||||
GET_UINT32_BE( lo, h, 4 );
|
GET_UINT32_BE(lo, h, 4);
|
||||||
vh = (uint64_t) hi << 32 | lo;
|
vh = (uint64_t)hi << 32 | lo;
|
||||||
|
|
||||||
GET_UINT32_BE( hi, h, 8 );
|
GET_UINT32_BE(hi, h, 8);
|
||||||
GET_UINT32_BE( lo, h, 12 );
|
GET_UINT32_BE(lo, h, 12);
|
||||||
vl = (uint64_t) hi << 32 | lo;
|
vl = (uint64_t)hi << 32 | lo;
|
||||||
|
|
||||||
ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
|
ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
|
||||||
ctx->HH[8] = vh;
|
ctx->HH[8] = vh;
|
||||||
ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
|
ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
|
||||||
ctx->HL[0] = 0;
|
ctx->HL[0] = 0;
|
||||||
|
|
||||||
for( i = 4; i > 0; i >>= 1 ) {
|
for(i = 4; i > 0; i >>= 1) {
|
||||||
uint32_t T = (uint32_t) ( vl & 1 ) * 0xe1000000U;
|
uint32_t T = (uint32_t)(vl & 1) * 0xe1000000U;
|
||||||
vl = ( vh << 63 ) | ( vl >> 1 );
|
vl = (vh << 63) | (vl >> 1);
|
||||||
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
|
vh = (vh >> 1) ^ ((uint64_t)T << 32);
|
||||||
ctx->HL[i] = vl;
|
ctx->HL[i] = vl;
|
||||||
ctx->HH[i] = vh;
|
ctx->HH[i] = vh;
|
||||||
}
|
}
|
||||||
for (i = 2; i < 16; i <<= 1 ) {
|
for(i = 2; i < 16; i <<= 1) {
|
||||||
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
|
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
|
||||||
vh = *HiH;
|
vh = *HiH;
|
||||||
vl = *HiL;
|
vl = *HiL;
|
||||||
for( j = 1; j < i; j++ ) {
|
for(j = 1; j < i; j++) {
|
||||||
HiH[j] = vh ^ ctx->HH[j];
|
HiH[j] = vh ^ ctx->HH[j];
|
||||||
HiL[j] = vl ^ ctx->HL[j];
|
HiL[j] = vl ^ ctx->HL[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
|
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
|
||||||
@@ -245,62 +256,61 @@ int gcm_setkey( gcm_context *ctx, // pointer to caller-provided gcm context
|
|||||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_start(
|
||||||
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
int mode, // GCM_ENCRYPT or GCM_DECRYPT
|
int mode, // GCM_ENCRYPT or GCM_DECRYPT
|
||||||
const uchar *iv, // pointer to initialization vector
|
const uchar* iv, // pointer to initialization vector
|
||||||
size_t iv_len, // IV length in bytes (should == 12)
|
size_t iv_len, // IV length in bytes (should == 12)
|
||||||
const uchar *add, // ptr to additional AEAD data (NULL if none)
|
const uchar* add, // ptr to additional AEAD data (NULL if none)
|
||||||
size_t add_len ) // length of additional AEAD data (bytes)
|
size_t add_len) // length of additional AEAD data (bytes)
|
||||||
{
|
{
|
||||||
int ret; // our error return if the AES encrypt fails
|
int ret; // our error return if the AES encrypt fails
|
||||||
uchar work_buf[16]; // XOR source built from provided IV if len != 16
|
uchar work_buf[16]; // XOR source built from provided IV if len != 16
|
||||||
const uchar *p; // general purpose array pointer
|
const uchar* p; // general purpose array pointer
|
||||||
size_t use_len; // byte count to process, up to 16 bytes
|
size_t use_len; // byte count to process, up to 16 bytes
|
||||||
size_t i; // local loop iterator
|
size_t i; // local loop iterator
|
||||||
|
|
||||||
// since the context might be reused under the same key
|
// since the context might be reused under the same key
|
||||||
// we zero the working buffers for this next new process
|
// we zero the working buffers for this next new process
|
||||||
memset( ctx->y, 0x00, sizeof(ctx->y ) );
|
memset(ctx->y, 0x00, sizeof(ctx->y));
|
||||||
memset( ctx->buf, 0x00, sizeof(ctx->buf) );
|
memset(ctx->buf, 0x00, sizeof(ctx->buf));
|
||||||
ctx->len = 0;
|
ctx->len = 0;
|
||||||
ctx->add_len = 0;
|
ctx->add_len = 0;
|
||||||
|
|
||||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||||
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||||
|
|
||||||
if( iv_len == 12 ) { // GCM natively uses a 12-byte, 96-bit IV
|
if(iv_len == 12) { // GCM natively uses a 12-byte, 96-bit IV
|
||||||
memcpy( ctx->y, iv, iv_len ); // copy the IV to the top of the 'y' buff
|
memcpy(ctx->y, iv, iv_len); // copy the IV to the top of the 'y' buff
|
||||||
ctx->y[15] = 1; // start "counting" from 1 (not 0)
|
ctx->y[15] = 1; // start "counting" from 1 (not 0)
|
||||||
}
|
} else // if we don't have a 12-byte IV, we GHASH whatever we've been given
|
||||||
else // if we don't have a 12-byte IV, we GHASH whatever we've been given
|
|
||||||
{
|
{
|
||||||
memset( work_buf, 0x00, 16 ); // clear the working buffer
|
memset(work_buf, 0x00, 16); // clear the working buffer
|
||||||
PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); // place the IV into buffer
|
PUT_UINT32_BE(iv_len * 8, work_buf, 12); // place the IV into buffer
|
||||||
|
|
||||||
p = iv;
|
p = iv;
|
||||||
while( iv_len > 0 ) {
|
while(iv_len > 0) {
|
||||||
use_len = ( iv_len < 16 ) ? iv_len : 16;
|
use_len = (iv_len < 16) ? iv_len : 16;
|
||||||
for( i = 0; i < use_len; i++ ) ctx->y[i] ^= p[i];
|
for(i = 0; i < use_len; i++) ctx->y[i] ^= p[i];
|
||||||
gcm_mult( ctx, ctx->y, ctx->y );
|
gcm_mult(ctx, ctx->y, ctx->y);
|
||||||
iv_len -= use_len;
|
iv_len -= use_len;
|
||||||
p += use_len;
|
p += use_len;
|
||||||
}
|
}
|
||||||
for( i = 0; i < 16; i++ ) ctx->y[i] ^= work_buf[i];
|
for(i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i];
|
||||||
gcm_mult( ctx, ctx->y, ctx->y );
|
gcm_mult(ctx, ctx->y, ctx->y);
|
||||||
}
|
}
|
||||||
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ctx->base_ectr ) ) != 0 )
|
if((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0) return (ret);
|
||||||
return( ret );
|
|
||||||
|
|
||||||
ctx->add_len = add_len;
|
ctx->add_len = add_len;
|
||||||
p = add;
|
p = add;
|
||||||
while( add_len > 0 ) {
|
while(add_len > 0) {
|
||||||
use_len = ( add_len < 16 ) ? add_len : 16;
|
use_len = (add_len < 16) ? add_len : 16;
|
||||||
for( i = 0; i < use_len; i++ ) ctx->buf[i] ^= p[i];
|
for(i = 0; i < use_len; i++) ctx->buf[i] ^= p[i];
|
||||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
gcm_mult(ctx, ctx->buf, ctx->buf);
|
||||||
add_len -= use_len;
|
add_len -= use_len;
|
||||||
p += use_len;
|
p += use_len;
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -314,10 +324,11 @@ int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
* have a partial block length of < 128 bits.)
|
* have a partial block length of < 128 bits.)
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_update(
|
||||||
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
size_t length, // length, in bytes, of data to process
|
size_t length, // length, in bytes, of data to process
|
||||||
const uchar *input, // pointer to source data
|
const uchar* input, // pointer to source data
|
||||||
uchar *output ) // pointer to destination data
|
uchar* output) // pointer to destination data
|
||||||
{
|
{
|
||||||
int ret; // our error return if the AES encrypt fails
|
int ret; // our error return if the AES encrypt fails
|
||||||
uchar ectr[16]; // counter-mode cipher output for XORing
|
uchar ectr[16]; // counter-mode cipher output for XORing
|
||||||
@@ -326,33 +337,30 @@ int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
|
|
||||||
ctx->len += length; // bump the GCM context's running length count
|
ctx->len += length; // bump the GCM context's running length count
|
||||||
|
|
||||||
while( length > 0 ) {
|
while(length > 0) {
|
||||||
// clamp the length to process at 16 bytes
|
// clamp the length to process at 16 bytes
|
||||||
use_len = ( length < 16 ) ? length : 16;
|
use_len = (length < 16) ? length : 16;
|
||||||
|
|
||||||
// increment the context's 128-bit IV||Counter 'y' vector
|
// increment the context's 128-bit IV||Counter 'y' vector
|
||||||
for( i = 16; i > 12; i-- ) if( ++ctx->y[i - 1] != 0 ) break;
|
for(i = 16; i > 12; i--)
|
||||||
|
if(++ctx->y[i - 1] != 0) break;
|
||||||
|
|
||||||
// encrypt the context's 'y' vector under the established key
|
// encrypt the context's 'y' vector under the established key
|
||||||
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ectr ) ) != 0 )
|
if((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ectr)) != 0) return (ret);
|
||||||
return( ret );
|
|
||||||
|
|
||||||
// encrypt or decrypt the input to the output
|
// encrypt or decrypt the input to the output
|
||||||
if( ctx->mode == ENCRYPT )
|
if(ctx->mode == ENCRYPT) {
|
||||||
{
|
for(i = 0; i < use_len; i++) {
|
||||||
for( i = 0; i < use_len; i++ ) {
|
|
||||||
// XOR the cipher's ouptut vector (ectr) with our input
|
// XOR the cipher's ouptut vector (ectr) with our input
|
||||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
output[i] = (uchar)(ectr[i] ^ input[i]);
|
||||||
// now we mix in our data into the authentication hash.
|
// now we mix in our data into the authentication hash.
|
||||||
// if we're ENcrypting we XOR in the post-XOR (output)
|
// if we're ENcrypting we XOR in the post-XOR (output)
|
||||||
// results, but if we're DEcrypting we XOR in the input
|
// results, but if we're DEcrypting we XOR in the input
|
||||||
// data
|
// data
|
||||||
ctx->buf[i] ^= output[i];
|
ctx->buf[i] ^= output[i];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
for(i = 0; i < use_len; i++) {
|
||||||
{
|
|
||||||
for( i = 0; i < use_len; i++ ) {
|
|
||||||
// but if we're DEcrypting we XOR in the input data first,
|
// but if we're DEcrypting we XOR in the input data first,
|
||||||
// i.e. before saving to ouput data, otherwise if the input
|
// i.e. before saving to ouput data, otherwise if the input
|
||||||
// and output buffer are the same (inplace decryption) we
|
// and output buffer are the same (inplace decryption) we
|
||||||
@@ -361,16 +369,16 @@ int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
ctx->buf[i] ^= input[i];
|
ctx->buf[i] ^= input[i];
|
||||||
|
|
||||||
// XOR the cipher's ouptut vector (ectr) with our input
|
// XOR the cipher's ouptut vector (ectr) with our input
|
||||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
output[i] = (uchar)(ectr[i] ^ input[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gcm_mult( ctx, ctx->buf, ctx->buf ); // perform a GHASH operation
|
gcm_mult(ctx, ctx->buf, ctx->buf); // perform a GHASH operation
|
||||||
|
|
||||||
length -= use_len; // drop the remaining byte count to process
|
length -= use_len; // drop the remaining byte count to process
|
||||||
input += use_len; // bump our input pointer forward
|
input += use_len; // bump our input pointer forward
|
||||||
output += use_len; // bump our output pointer forward
|
output += use_len; // bump our output pointer forward
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -381,33 +389,33 @@ int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_finish(
|
||||||
uchar *tag, // pointer to buffer which receives the tag
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
size_t tag_len ) // length, in bytes, of the tag-receiving buf
|
uchar* tag, // pointer to buffer which receives the tag
|
||||||
|
size_t tag_len) // length, in bytes, of the tag-receiving buf
|
||||||
{
|
{
|
||||||
uchar work_buf[16];
|
uchar work_buf[16];
|
||||||
uint64_t orig_len = ctx->len * 8;
|
uint64_t orig_len = ctx->len * 8;
|
||||||
uint64_t orig_add_len = ctx->add_len * 8;
|
uint64_t orig_add_len = ctx->add_len * 8;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if( tag_len != 0 ) memcpy( tag, ctx->base_ectr, tag_len );
|
if(tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
|
||||||
|
|
||||||
if( orig_len || orig_add_len ) {
|
if(orig_len || orig_add_len) {
|
||||||
memset( work_buf, 0x00, 16 );
|
memset(work_buf, 0x00, 16);
|
||||||
|
|
||||||
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
|
PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
|
||||||
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
|
PUT_UINT32_BE((orig_add_len), work_buf, 4);
|
||||||
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
|
PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
|
||||||
PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
|
PUT_UINT32_BE((orig_len), work_buf, 12);
|
||||||
|
|
||||||
for( i = 0; i < 16; i++ ) ctx->buf[i] ^= work_buf[i];
|
for(i = 0; i < 16; i++) ctx->buf[i] ^= work_buf[i];
|
||||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
gcm_mult(ctx, ctx->buf, ctx->buf);
|
||||||
for( i = 0; i < tag_len; i++ ) tag[i] ^= ctx->buf[i];
|
for(i = 0; i < tag_len; i++) tag[i] ^= ctx->buf[i];
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM_CRYPT_AND_TAG
|
* GCM_CRYPT_AND_TAG
|
||||||
@@ -426,29 +434,28 @@ int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_crypt_and_tag(
|
int gcm_crypt_and_tag(
|
||||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context* ctx, // gcm context with key already setup
|
||||||
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
|
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
|
||||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar* iv, // pointer to the 12-byte initialization vector
|
||||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar* add, // pointer to the non-ciphered additional data
|
||||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||||
const uchar *input, // pointer to the cipher data source
|
const uchar* input, // pointer to the cipher data source
|
||||||
uchar *output, // pointer to the cipher data destination
|
uchar* output, // pointer to the cipher data destination
|
||||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||||
uchar *tag, // pointer to the tag to be generated
|
uchar* tag, // pointer to the tag to be generated
|
||||||
size_t tag_len ) // byte length of the tag to be generated
|
size_t tag_len) // byte length of the tag to be generated
|
||||||
{ /*
|
{ /*
|
||||||
assuming that the caller has already invoked gcm_setkey to
|
assuming that the caller has already invoked gcm_setkey to
|
||||||
prepare the gcm context with the keying material, we simply
|
prepare the gcm context with the keying material, we simply
|
||||||
invoke each of the three GCM sub-functions in turn...
|
invoke each of the three GCM sub-functions in turn...
|
||||||
*/
|
*/
|
||||||
gcm_start ( ctx, mode, iv, iv_len, add, add_len );
|
gcm_start(ctx, mode, iv, iv_len, add, add_len);
|
||||||
gcm_update ( ctx, length, input, output );
|
gcm_update(ctx, length, input, output);
|
||||||
gcm_finish ( ctx, tag, tag_len );
|
gcm_finish(ctx, tag, tag_len);
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM_AUTH_DECRYPT
|
* GCM_AUTH_DECRYPT
|
||||||
@@ -462,16 +469,16 @@ int gcm_crypt_and_tag(
|
|||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_auth_decrypt(
|
int gcm_auth_decrypt(
|
||||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context* ctx, // gcm context with key already setup
|
||||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar* iv, // pointer to the 12-byte initialization vector
|
||||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar* add, // pointer to the non-ciphered additional data
|
||||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||||
const uchar *input, // pointer to the cipher data source
|
const uchar* input, // pointer to the cipher data source
|
||||||
uchar *output, // pointer to the cipher data destination
|
uchar* output, // pointer to the cipher data destination
|
||||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||||
const uchar *tag, // pointer to the tag to be authenticated
|
const uchar* tag, // pointer to the tag to be authenticated
|
||||||
size_t tag_len ) // byte length of the tag <= 16
|
size_t tag_len) // byte length of the tag <= 16
|
||||||
{
|
{
|
||||||
uchar check_tag[16]; // the tag generated and returned by decryption
|
uchar check_tag[16]; // the tag generated and returned by decryption
|
||||||
int diff; // an ORed flag to detect authentication errors
|
int diff; // an ORed flag to detect authentication errors
|
||||||
@@ -481,18 +488,17 @@ int gcm_auth_decrypt(
|
|||||||
(which is an identical XORing to reverse the previous one)
|
(which is an identical XORing to reverse the previous one)
|
||||||
and also to re-generate the matching authentication tag
|
and also to re-generate the matching authentication tag
|
||||||
*/
|
*/
|
||||||
gcm_crypt_and_tag( ctx, DECRYPT, iv, iv_len, add, add_len,
|
gcm_crypt_and_tag(
|
||||||
input, output, length, check_tag, tag_len );
|
ctx, DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len);
|
||||||
|
|
||||||
// now we verify the authentication tag in 'constant time'
|
// now we verify the authentication tag in 'constant time'
|
||||||
for( diff = 0, i = 0; i < tag_len; i++ )
|
for(diff = 0, i = 0; i < tag_len; i++) diff |= tag[i] ^ check_tag[i];
|
||||||
diff |= tag[i] ^ check_tag[i];
|
|
||||||
|
|
||||||
if( diff != 0 ) { // see whether any bits differed?
|
if(diff != 0) { // see whether any bits differed?
|
||||||
memset( output, 0, length ); // if so... wipe the output data
|
memset(output, 0, length); // if so... wipe the output data
|
||||||
return( GCM_AUTH_FAILURE ); // return GCM_AUTH_FAILURE
|
return (GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
|
||||||
}
|
}
|
||||||
return( 0 );
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -504,8 +510,7 @@ int gcm_auth_decrypt(
|
|||||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void gcm_zero_ctx( gcm_context *ctx )
|
void gcm_zero_ctx(gcm_context* ctx) {
|
||||||
{
|
|
||||||
// zero the context originally provided to us
|
// zero the context originally provided to us
|
||||||
memset( ctx, 0, sizeof( gcm_context ) );
|
memset(ctx, 0, sizeof(gcm_context));
|
||||||
}
|
}
|
||||||
|
|||||||
80
applications/external/esubghz_chat/crypto/gcm.h
vendored
80
applications/external/esubghz_chat/crypto/gcm.h
vendored
@@ -29,15 +29,14 @@
|
|||||||
#include "aes.h" // gcm_context includes aes_context
|
#include "aes.h" // gcm_context includes aes_context
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <basetsd.h>
|
#include <basetsd.h>
|
||||||
typedef unsigned int size_t;// use the right type for length declarations
|
typedef unsigned int size_t; // use the right type for length declarations
|
||||||
typedef UINT32 uint32_t;
|
typedef UINT32 uint32_t;
|
||||||
typedef UINT64 uint64_t;
|
typedef UINT64 uint64_t;
|
||||||
#else
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
|
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -53,23 +52,21 @@ typedef struct {
|
|||||||
aes_context aes_ctx; // cipher context used
|
aes_context aes_ctx; // cipher context used
|
||||||
} gcm_context;
|
} gcm_context;
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* GCM_CONTEXT : MUST be called once before ANY use of this library
|
* GCM_CONTEXT : MUST be called once before ANY use of this library
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_initialize( void );
|
int gcm_initialize(void);
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* GCM_SETKEY : sets the GCM (and AES) keying material for use
|
* GCM_SETKEY : sets the GCM (and AES) keying material for use
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_setkey( gcm_context *ctx, // caller-provided context ptr
|
int gcm_setkey(
|
||||||
const uchar *key, // pointer to cipher key
|
gcm_context* ctx, // caller-provided context ptr
|
||||||
|
const uchar* key, // pointer to cipher key
|
||||||
const uint keysize // size in bytes (must be 16, 24, 32 for
|
const uint keysize // size in bytes (must be 16, 24, 32 for
|
||||||
// 128, 192 or 256-bit keys respectively)
|
// 128, 192 or 256-bit keys respectively)
|
||||||
); // returns 0 for success
|
); // returns 0 for success
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* GCM_CRYPT_AND_TAG
|
* GCM_CRYPT_AND_TAG
|
||||||
@@ -88,18 +85,17 @@ int gcm_setkey( gcm_context *ctx, // caller-provided context ptr
|
|||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_crypt_and_tag(
|
int gcm_crypt_and_tag(
|
||||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context* ctx, // gcm context with key already setup
|
||||||
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
|
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
|
||||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar* iv, // pointer to the 12-byte initialization vector
|
||||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar* add, // pointer to the non-ciphered additional data
|
||||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||||
const uchar *input, // pointer to the cipher data source
|
const uchar* input, // pointer to the cipher data source
|
||||||
uchar *output, // pointer to the cipher data destination
|
uchar* output, // pointer to the cipher data destination
|
||||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||||
uchar *tag, // pointer to the tag to be generated
|
uchar* tag, // pointer to the tag to be generated
|
||||||
size_t tag_len ); // byte length of the tag to be generated
|
size_t tag_len); // byte length of the tag to be generated
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -114,17 +110,16 @@ int gcm_crypt_and_tag(
|
|||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_auth_decrypt(
|
int gcm_auth_decrypt(
|
||||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context* ctx, // gcm context with key already setup
|
||||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar* iv, // pointer to the 12-byte initialization vector
|
||||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar* add, // pointer to the non-ciphered additional data
|
||||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||||
const uchar *input, // pointer to the cipher data source
|
const uchar* input, // pointer to the cipher data source
|
||||||
uchar *output, // pointer to the cipher data destination
|
uchar* output, // pointer to the cipher data destination
|
||||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||||
const uchar *tag, // pointer to the tag to be authenticated
|
const uchar* tag, // pointer to the tag to be authenticated
|
||||||
size_t tag_len ); // byte length of the tag <= 16
|
size_t tag_len); // byte length of the tag <= 16
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -134,13 +129,13 @@ int gcm_auth_decrypt(
|
|||||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_start(
|
||||||
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
int mode, // ENCRYPT (1) or DECRYPT (0)
|
int mode, // ENCRYPT (1) or DECRYPT (0)
|
||||||
const uchar *iv, // pointer to initialization vector
|
const uchar* iv, // pointer to initialization vector
|
||||||
size_t iv_len, // IV length in bytes (should == 12)
|
size_t iv_len, // IV length in bytes (should == 12)
|
||||||
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
const uchar* add, // pointer to additional AEAD data (NULL if none)
|
||||||
size_t add_len ); // length of additional AEAD data (bytes)
|
size_t add_len); // length of additional AEAD data (bytes)
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -153,11 +148,11 @@ int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
* have a partial block length of < 128 bits.)
|
* have a partial block length of < 128 bits.)
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_update(
|
||||||
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
size_t length, // length, in bytes, of data to process
|
size_t length, // length, in bytes, of data to process
|
||||||
const uchar *input, // pointer to source data
|
const uchar* input, // pointer to source data
|
||||||
uchar *output ); // pointer to destination data
|
uchar* output); // pointer to destination data
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -167,10 +162,10 @@ int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_finish(
|
||||||
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
gcm_context* ctx, // pointer to user-provided GCM context
|
||||||
size_t tag_len ); // length, in bytes, of the tag-receiving buf
|
uchar* tag, // ptr to tag buffer - NULL if tag_len = 0
|
||||||
|
size_t tag_len); // length, in bytes, of the tag-receiving buf
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -181,7 +176,6 @@ int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
|||||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void gcm_zero_ctx( gcm_context *ctx );
|
void gcm_zero_ctx(gcm_context* ctx);
|
||||||
|
|
||||||
|
|
||||||
#endif /* GCM_HEADER */
|
#endif /* GCM_HEADER */
|
||||||
|
|||||||
118
applications/external/esubghz_chat/crypto_wrapper.c
vendored
118
applications/external/esubghz_chat/crypto_wrapper.c
vendored
@@ -26,27 +26,24 @@ struct ESubGhzChatCryptoMsg {
|
|||||||
uint8_t iv[IV_BYTES];
|
uint8_t iv[IV_BYTES];
|
||||||
uint8_t tag[TAG_BYTES];
|
uint8_t tag[TAG_BYTES];
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __attribute__ ((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
void crypto_init(void)
|
void crypto_init(void) {
|
||||||
{
|
|
||||||
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
||||||
/* init the GCM and AES tables */
|
/* init the GCM and AES tables */
|
||||||
gcm_initialize();
|
gcm_initialize();
|
||||||
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_explicit_bzero(void *s, size_t len)
|
void crypto_explicit_bzero(void* s, size_t len) {
|
||||||
{
|
|
||||||
memset(s, 0, len);
|
memset(s, 0, len);
|
||||||
asm volatile("" ::: "memory");
|
asm volatile("" ::: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
ESubGhzChatCryptoCtx *crypto_ctx_alloc(void)
|
ESubGhzChatCryptoCtx* crypto_ctx_alloc(void) {
|
||||||
{
|
ESubGhzChatCryptoCtx* ret = malloc(sizeof(ESubGhzChatCryptoCtx));
|
||||||
ESubGhzChatCryptoCtx *ret = malloc(sizeof(ESubGhzChatCryptoCtx));
|
|
||||||
|
|
||||||
if (ret != NULL) {
|
if(ret != NULL) {
|
||||||
memset(ret, 0, sizeof(ESubGhzChatCryptoCtx));
|
memset(ret, 0, sizeof(ESubGhzChatCryptoCtx));
|
||||||
ESubGhzChatReplayDict_init(ret->replay_dict);
|
ESubGhzChatReplayDict_init(ret->replay_dict);
|
||||||
ret->run_id = 0;
|
ret->run_id = 0;
|
||||||
@@ -56,15 +53,13 @@ ESubGhzChatCryptoCtx *crypto_ctx_alloc(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_ctx_free(ESubGhzChatCryptoCtx *ctx)
|
void crypto_ctx_free(ESubGhzChatCryptoCtx* ctx) {
|
||||||
{
|
|
||||||
crypto_ctx_clear(ctx);
|
crypto_ctx_clear(ctx);
|
||||||
ESubGhzChatReplayDict_clear(ctx->replay_dict);
|
ESubGhzChatReplayDict_clear(ctx->replay_dict);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx)
|
void crypto_ctx_clear(ESubGhzChatCryptoCtx* ctx) {
|
||||||
{
|
|
||||||
crypto_explicit_bzero(ctx->key, sizeof(ctx->key));
|
crypto_explicit_bzero(ctx->key, sizeof(ctx->key));
|
||||||
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
#ifndef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
||||||
crypto_explicit_bzero(&(ctx->gcm_ctx), sizeof(ctx->gcm_ctx));
|
crypto_explicit_bzero(&(ctx->gcm_ctx), sizeof(ctx->gcm_ctx));
|
||||||
@@ -74,9 +69,8 @@ void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx)
|
|||||||
ctx->counter = 1;
|
ctx->counter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t crypto_calc_run_id(FuriString *flipper_name, uint32_t tick)
|
static uint64_t crypto_calc_run_id(FuriString* flipper_name, uint32_t tick) {
|
||||||
{
|
const char* fn = furi_string_get_cstr(flipper_name);
|
||||||
const char *fn = furi_string_get_cstr(flipper_name);
|
|
||||||
size_t fn_len = strlen(fn);
|
size_t fn_len = strlen(fn);
|
||||||
|
|
||||||
uint8_t h_in[fn_len + sizeof(uint32_t)];
|
uint8_t h_in[fn_len + sizeof(uint32_t)];
|
||||||
@@ -92,9 +86,11 @@ static uint64_t crypto_calc_run_id(FuriString *flipper_name, uint32_t tick)
|
|||||||
return run_id;
|
return run_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key,
|
bool crypto_ctx_set_key(
|
||||||
FuriString *flipper_name, uint32_t tick)
|
ESubGhzChatCryptoCtx* ctx,
|
||||||
{
|
const uint8_t* key,
|
||||||
|
FuriString* flipper_name,
|
||||||
|
uint32_t tick) {
|
||||||
ctx->run_id = crypto_calc_run_id(flipper_name, tick);
|
ctx->run_id = crypto_calc_run_id(flipper_name, tick);
|
||||||
ctx->counter = 1;
|
ctx->counter = 1;
|
||||||
|
|
||||||
@@ -106,59 +102,62 @@ bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key,
|
|||||||
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_ctx_get_key(ESubGhzChatCryptoCtx *ctx, uint8_t *key)
|
void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key) {
|
||||||
{
|
|
||||||
memcpy(key, ctx->key, KEY_BITS / 8);
|
memcpy(key, ctx->key, KEY_BITS / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out) {
|
||||||
uint8_t *out)
|
if(in_len < MSG_OVERHEAD + 1) {
|
||||||
{
|
|
||||||
if (in_len < MSG_OVERHEAD + 1) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ESubGhzChatCryptoMsg *msg = (struct ESubGhzChatCryptoMsg *) in;
|
struct ESubGhzChatCryptoMsg* msg = (struct ESubGhzChatCryptoMsg*)in;
|
||||||
|
|
||||||
// check if message is stale, if yes, discard
|
// check if message is stale, if yes, discard
|
||||||
uint32_t *counter = ESubGhzChatReplayDict_get(ctx->replay_dict,
|
uint32_t* counter = ESubGhzChatReplayDict_get(ctx->replay_dict, msg->run_id);
|
||||||
msg->run_id);
|
if(counter != NULL) {
|
||||||
if (counter != NULL) {
|
if(*counter >= __ntohl(msg->counter)) {
|
||||||
if (*counter >= __ntohl(msg->counter)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt and auth message
|
// decrypt and auth message
|
||||||
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
||||||
bool ret = (furi_hal_crypto_gcm_decrypt_and_verify(ctx->key,
|
bool ret =
|
||||||
|
(furi_hal_crypto_gcm_decrypt_and_verify(
|
||||||
|
ctx->key,
|
||||||
msg->iv,
|
msg->iv,
|
||||||
(uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
(uint8_t*)msg,
|
||||||
msg->data, out,
|
RUN_ID_BYTES + COUNTER_BYTES,
|
||||||
|
msg->data,
|
||||||
|
out,
|
||||||
in_len - MSG_OVERHEAD,
|
in_len - MSG_OVERHEAD,
|
||||||
msg->tag) == FuriHalCryptoGCMStateOk);
|
msg->tag) == FuriHalCryptoGCMStateOk);
|
||||||
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
bool ret = (gcm_auth_decrypt(&(ctx->gcm_ctx),
|
bool ret =
|
||||||
msg->iv, IV_BYTES,
|
(gcm_auth_decrypt(
|
||||||
(uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
&(ctx->gcm_ctx),
|
||||||
msg->data, out,
|
msg->iv,
|
||||||
|
IV_BYTES,
|
||||||
|
(uint8_t*)msg,
|
||||||
|
RUN_ID_BYTES + COUNTER_BYTES,
|
||||||
|
msg->data,
|
||||||
|
out,
|
||||||
in_len - MSG_OVERHEAD,
|
in_len - MSG_OVERHEAD,
|
||||||
msg->tag, TAG_BYTES) == 0);
|
msg->tag,
|
||||||
|
TAG_BYTES) == 0);
|
||||||
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
|
|
||||||
// if auth was successful update replay dict
|
// if auth was successful update replay dict
|
||||||
if (ret) {
|
if(ret) {
|
||||||
ESubGhzChatReplayDict_set_at(ctx->replay_dict, msg->run_id,
|
ESubGhzChatReplayDict_set_at(ctx->replay_dict, msg->run_id, __ntohl(msg->counter));
|
||||||
__ntohl(msg->counter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out) {
|
||||||
uint8_t *out)
|
struct ESubGhzChatCryptoMsg* msg = (struct ESubGhzChatCryptoMsg*)out;
|
||||||
{
|
|
||||||
struct ESubGhzChatCryptoMsg *msg = (struct ESubGhzChatCryptoMsg *) out;
|
|
||||||
|
|
||||||
// fill message header
|
// fill message header
|
||||||
msg->run_id = ctx->run_id;
|
msg->run_id = ctx->run_id;
|
||||||
@@ -167,23 +166,34 @@ bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
|||||||
|
|
||||||
// encrypt message and store tag in header
|
// encrypt message and store tag in header
|
||||||
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
#ifdef FURI_HAL_CRYPTO_ADVANCED_AVAIL
|
||||||
bool ret = (furi_hal_crypto_gcm_encrypt_and_tag(ctx->key,
|
bool ret =
|
||||||
|
(furi_hal_crypto_gcm_encrypt_and_tag(
|
||||||
|
ctx->key,
|
||||||
msg->iv,
|
msg->iv,
|
||||||
(uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
(uint8_t*)msg,
|
||||||
in, msg->data,
|
RUN_ID_BYTES + COUNTER_BYTES,
|
||||||
|
in,
|
||||||
|
msg->data,
|
||||||
in_len,
|
in_len,
|
||||||
msg->tag) == FuriHalCryptoGCMStateOk);
|
msg->tag) == FuriHalCryptoGCMStateOk);
|
||||||
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#else /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
bool ret = (gcm_crypt_and_tag(&(ctx->gcm_ctx), ENCRYPT,
|
bool ret =
|
||||||
msg->iv, IV_BYTES,
|
(gcm_crypt_and_tag(
|
||||||
(uint8_t *) msg, RUN_ID_BYTES + COUNTER_BYTES,
|
&(ctx->gcm_ctx),
|
||||||
in, msg->data,
|
ENCRYPT,
|
||||||
|
msg->iv,
|
||||||
|
IV_BYTES,
|
||||||
|
(uint8_t*)msg,
|
||||||
|
RUN_ID_BYTES + COUNTER_BYTES,
|
||||||
|
in,
|
||||||
|
msg->data,
|
||||||
in_len,
|
in_len,
|
||||||
msg->tag, TAG_BYTES) == 0);
|
msg->tag,
|
||||||
|
TAG_BYTES) == 0);
|
||||||
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
|
||||||
|
|
||||||
// increase internal counter
|
// increase internal counter
|
||||||
if (ret) {
|
if(ret) {
|
||||||
ctx->counter++;
|
ctx->counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,21 +17,22 @@ typedef struct ESugGhzChatCryptoCtx ESubGhzChatCryptoCtx;
|
|||||||
void crypto_init(void);
|
void crypto_init(void);
|
||||||
|
|
||||||
/* Function to clear sensitive memory. */
|
/* Function to clear sensitive memory. */
|
||||||
void crypto_explicit_bzero(void *s, size_t len);
|
void crypto_explicit_bzero(void* s, size_t len);
|
||||||
|
|
||||||
ESubGhzChatCryptoCtx *crypto_ctx_alloc(void);
|
ESubGhzChatCryptoCtx* crypto_ctx_alloc(void);
|
||||||
void crypto_ctx_free(ESubGhzChatCryptoCtx *ctx);
|
void crypto_ctx_free(ESubGhzChatCryptoCtx* ctx);
|
||||||
|
|
||||||
void crypto_ctx_clear(ESubGhzChatCryptoCtx *ctx);
|
void crypto_ctx_clear(ESubGhzChatCryptoCtx* ctx);
|
||||||
|
|
||||||
bool crypto_ctx_set_key(ESubGhzChatCryptoCtx *ctx, const uint8_t *key,
|
bool crypto_ctx_set_key(
|
||||||
FuriString *flipper_name, uint32_t tick);
|
ESubGhzChatCryptoCtx* ctx,
|
||||||
void crypto_ctx_get_key(ESubGhzChatCryptoCtx *ctx, uint8_t *key);
|
const uint8_t* key,
|
||||||
|
FuriString* flipper_name,
|
||||||
|
uint32_t tick);
|
||||||
|
void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key);
|
||||||
|
|
||||||
bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);
|
||||||
uint8_t *out);
|
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);
|
||||||
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx *ctx, uint8_t *in, size_t in_len,
|
|
||||||
uint8_t *out);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
319
applications/external/esubghz_chat/esubghz_chat.c
vendored
319
applications/external/esubghz_chat/esubghz_chat.c
vendored
@@ -15,8 +15,7 @@
|
|||||||
|
|
||||||
/* Callback for RX events from the Sub-GHz worker. Records the current ticks as
|
/* Callback for RX events from the Sub-GHz worker. Records the current ticks as
|
||||||
* the time of the last reception. */
|
* the time of the last reception. */
|
||||||
static void have_read_cb(void* context)
|
static void have_read_cb(void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
@@ -25,20 +24,17 @@ static void have_read_cb(void* context)
|
|||||||
|
|
||||||
/* Sets the header for the chat input field depending on whether or not a
|
/* Sets the header for the chat input field depending on whether or not a
|
||||||
* message preview exists. */
|
* message preview exists. */
|
||||||
void set_chat_input_header(ESubGhzChatState *state)
|
void set_chat_input_header(ESubGhzChatState* state) {
|
||||||
{
|
if(strlen(state->msg_preview) == 0) {
|
||||||
if (strlen(state->msg_preview) == 0) {
|
|
||||||
text_input_set_header_text(state->text_input, "Message");
|
text_input_set_header_text(state->text_input, "Message");
|
||||||
} else {
|
} else {
|
||||||
text_input_set_header_text(state->text_input,
|
text_input_set_header_text(state->text_input, state->msg_preview);
|
||||||
state->msg_preview);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Appends the latest message to the chat box and prepares the message preview.
|
/* Appends the latest message to the chat box and prepares the message preview.
|
||||||
*/
|
*/
|
||||||
void append_msg(ESubGhzChatState *state, const char *msg)
|
void append_msg(ESubGhzChatState* state, const char* msg) {
|
||||||
{
|
|
||||||
/* append message to text box */
|
/* append message to text box */
|
||||||
furi_string_cat_printf(state->chat_box_store, "\n%s", msg);
|
furi_string_cat_printf(state->chat_box_store, "\n%s", msg);
|
||||||
|
|
||||||
@@ -48,19 +44,16 @@ void append_msg(ESubGhzChatState *state, const char *msg)
|
|||||||
set_chat_input_header(state);
|
set_chat_input_header(state);
|
||||||
|
|
||||||
/* reset text box contents and focus */
|
/* reset text box contents and focus */
|
||||||
text_box_set_text(state->chat_box,
|
text_box_set_text(state->chat_box, furi_string_get_cstr(state->chat_box_store));
|
||||||
furi_string_get_cstr(state->chat_box_store));
|
|
||||||
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decrypts a message for post_rx(). */
|
/* Decrypts a message for post_rx(). */
|
||||||
static bool post_rx_decrypt(ESubGhzChatState *state, size_t rx_size)
|
static bool post_rx_decrypt(ESubGhzChatState* state, size_t rx_size) {
|
||||||
{
|
bool ret = crypto_ctx_decrypt(
|
||||||
bool ret = crypto_ctx_decrypt(state->crypto_ctx,
|
state->crypto_ctx, state->rx_buffer, rx_size, (uint8_t*)state->rx_str_buffer);
|
||||||
state->rx_buffer, rx_size,
|
|
||||||
(uint8_t*) state->rx_str_buffer);
|
|
||||||
|
|
||||||
if (ret) {
|
if(ret) {
|
||||||
state->rx_str_buffer[rx_size - (MSG_OVERHEAD)] = 0;
|
state->rx_str_buffer[rx_size - (MSG_OVERHEAD)] = 0;
|
||||||
} else {
|
} else {
|
||||||
state->rx_str_buffer[0] = 0;
|
state->rx_str_buffer[0] = 0;
|
||||||
@@ -70,29 +63,28 @@ static bool post_rx_decrypt(ESubGhzChatState *state, size_t rx_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Post RX handler, decrypts received messages and calls append_msg(). */
|
/* Post RX handler, decrypts received messages and calls append_msg(). */
|
||||||
static void post_rx(ESubGhzChatState *state, size_t rx_size)
|
static void post_rx(ESubGhzChatState* state, size_t rx_size) {
|
||||||
{
|
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
if (rx_size == 0) {
|
if(rx_size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_check(rx_size <= RX_TX_BUFFER_SIZE);
|
furi_check(rx_size <= RX_TX_BUFFER_SIZE);
|
||||||
|
|
||||||
/* decrypt if necessary */
|
/* decrypt if necessary */
|
||||||
if (!state->encrypted) {
|
if(!state->encrypted) {
|
||||||
memcpy(state->rx_str_buffer, state->rx_buffer, rx_size);
|
memcpy(state->rx_str_buffer, state->rx_buffer, rx_size);
|
||||||
state->rx_str_buffer[rx_size] = 0;
|
state->rx_str_buffer[rx_size] = 0;
|
||||||
|
|
||||||
/* remove trailing newline if it is there, for compat with CLI
|
/* remove trailing newline if it is there, for compat with CLI
|
||||||
* Sub-GHz chat */
|
* Sub-GHz chat */
|
||||||
if (state->rx_str_buffer[rx_size - 1] == '\n') {
|
if(state->rx_str_buffer[rx_size - 1] == '\n') {
|
||||||
state->rx_str_buffer[rx_size - 1] = 0;
|
state->rx_str_buffer[rx_size - 1] = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* if decryption fails output an error message */
|
/* if decryption fails output an error message */
|
||||||
if (!post_rx_decrypt(state, rx_size)) {
|
if(!post_rx_decrypt(state, rx_size)) {
|
||||||
strcpy(state->rx_str_buffer, "ERR: Decryption failed!");
|
strcpy(state->rx_str_buffer, "ERR: Decryption failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,26 +98,23 @@ static void post_rx(ESubGhzChatState *state, size_t rx_size)
|
|||||||
|
|
||||||
/* Reads the message from msg_input, encrypts it if necessary and then
|
/* Reads the message from msg_input, encrypts it if necessary and then
|
||||||
* transmits it. */
|
* transmits it. */
|
||||||
void tx_msg_input(ESubGhzChatState *state)
|
void tx_msg_input(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
/* encrypt message if necessary */
|
/* encrypt message if necessary */
|
||||||
size_t msg_len = strlen(furi_string_get_cstr(state->msg_input));
|
size_t msg_len = strlen(furi_string_get_cstr(state->msg_input));
|
||||||
size_t tx_size = msg_len;
|
size_t tx_size = msg_len;
|
||||||
if (state->encrypted) {
|
if(state->encrypted) {
|
||||||
tx_size += MSG_OVERHEAD;
|
tx_size += MSG_OVERHEAD;
|
||||||
furi_check(tx_size <= sizeof(state->tx_buffer));
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
||||||
|
|
||||||
crypto_ctx_encrypt(state->crypto_ctx,
|
crypto_ctx_encrypt(
|
||||||
(uint8_t *)
|
state->crypto_ctx,
|
||||||
furi_string_get_cstr(state->msg_input),
|
(uint8_t*)furi_string_get_cstr(state->msg_input),
|
||||||
msg_len,
|
msg_len,
|
||||||
state->tx_buffer);
|
state->tx_buffer);
|
||||||
} else {
|
} else {
|
||||||
tx_size += 2;
|
tx_size += 2;
|
||||||
furi_check(tx_size <= sizeof(state->tx_buffer));
|
furi_check(tx_size <= sizeof(state->tx_buffer));
|
||||||
memcpy(state->tx_buffer,
|
memcpy(state->tx_buffer, furi_string_get_cstr(state->msg_input), msg_len);
|
||||||
furi_string_get_cstr(state->msg_input),
|
|
||||||
msg_len);
|
|
||||||
|
|
||||||
/* append \r\n for compat with Sub-GHz CLI chat */
|
/* append \r\n for compat with Sub-GHz CLI chat */
|
||||||
state->tx_buffer[msg_len] = '\r';
|
state->tx_buffer[msg_len] = '\r';
|
||||||
@@ -133,20 +122,17 @@ void tx_msg_input(ESubGhzChatState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* transmit */
|
/* transmit */
|
||||||
subghz_tx_rx_worker_write(state->subghz_worker, state->tx_buffer,
|
subghz_tx_rx_worker_write(state->subghz_worker, state->tx_buffer, tx_size);
|
||||||
tx_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Displays whether or not encryption has been enabled in the text box. Also
|
/* Displays whether or not encryption has been enabled in the text box. Also
|
||||||
* clears the text input buffer to remove the password and starts the Sub-GHz
|
* clears the text input buffer to remove the password and starts the Sub-GHz
|
||||||
* worker. After starting the worker a join message is transmitted. */
|
* worker. After starting the worker a join message is transmitted. */
|
||||||
void enter_chat(ESubGhzChatState *state)
|
void enter_chat(ESubGhzChatState* state) {
|
||||||
{
|
furi_string_cat_printf(
|
||||||
furi_string_cat_printf(state->chat_box_store, "\nEncrypted: %s",
|
state->chat_box_store, "\nEncrypted: %s", (state->encrypted ? "yes" : "no"));
|
||||||
(state->encrypted ? "yes" : "no"));
|
|
||||||
|
|
||||||
subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device,
|
subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device, state->frequency);
|
||||||
state->frequency);
|
|
||||||
|
|
||||||
/* concatenate the name prefix and join message */
|
/* concatenate the name prefix and join message */
|
||||||
furi_string_set(state->msg_input, state->name_prefix);
|
furi_string_set(state->msg_input, state->name_prefix);
|
||||||
@@ -160,8 +146,7 @@ void enter_chat(ESubGhzChatState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sends a leave message */
|
/* Sends a leave message */
|
||||||
void exit_chat(ESubGhzChatState *state)
|
void exit_chat(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
/* concatenate the name prefix and leave message */
|
/* concatenate the name prefix and leave message */
|
||||||
furi_string_set(state->msg_input, state->name_prefix);
|
furi_string_set(state->msg_input, state->name_prefix);
|
||||||
furi_string_cat_str(state->msg_input, " left chat.");
|
furi_string_cat_str(state->msg_input, " left chat.");
|
||||||
@@ -177,19 +162,17 @@ void exit_chat(ESubGhzChatState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Whether or not to display the locked message. */
|
/* Whether or not to display the locked message. */
|
||||||
static bool kbd_lock_msg_display(ESubGhzChatState *state)
|
static bool kbd_lock_msg_display(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
return (state->kbd_lock_msg_ticks != 0);
|
return (state->kbd_lock_msg_ticks != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Whether or not to hide the locked message again. */
|
/* Whether or not to hide the locked message again. */
|
||||||
static bool kbd_lock_msg_reset_timeout(ESubGhzChatState *state)
|
static bool kbd_lock_msg_reset_timeout(ESubGhzChatState* state) {
|
||||||
{
|
if(state->kbd_lock_msg_ticks == 0) {
|
||||||
if (state->kbd_lock_msg_ticks == 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (furi_get_tick() - state->kbd_lock_msg_ticks > KBD_UNLOCK_TIMEOUT) {
|
if(furi_get_tick() - state->kbd_lock_msg_ticks > KBD_UNLOCK_TIMEOUT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,34 +181,29 @@ static bool kbd_lock_msg_reset_timeout(ESubGhzChatState *state)
|
|||||||
|
|
||||||
/* Resets the timeout for the locked message and turns off the backlight if
|
/* Resets the timeout for the locked message and turns off the backlight if
|
||||||
* specified. */
|
* specified. */
|
||||||
static void kbd_lock_msg_reset(ESubGhzChatState *state, bool backlight_off)
|
static void kbd_lock_msg_reset(ESubGhzChatState* state, bool backlight_off) {
|
||||||
{
|
|
||||||
state->kbd_lock_msg_ticks = 0;
|
state->kbd_lock_msg_ticks = 0;
|
||||||
state->kbd_lock_count = 0;
|
state->kbd_lock_count = 0;
|
||||||
|
|
||||||
if (backlight_off) {
|
if(backlight_off) {
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_display_backlight_off);
|
||||||
&sequence_display_backlight_off);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locks the keyboard. */
|
/* Locks the keyboard. */
|
||||||
static void kbd_lock(ESubGhzChatState *state)
|
static void kbd_lock(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
state->kbd_locked = true;
|
state->kbd_locked = true;
|
||||||
kbd_lock_msg_reset(state, true);
|
kbd_lock_msg_reset(state, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlocks the keyboard. */
|
/* Unlocks the keyboard. */
|
||||||
static void kbd_unlock(ESubGhzChatState *state)
|
static void kbd_unlock(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
state->kbd_locked = false;
|
state->kbd_locked = false;
|
||||||
kbd_lock_msg_reset(state, false);
|
kbd_lock_msg_reset(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Custom event callback for view dispatcher. Just calls scene manager. */
|
/* Custom event callback for view dispatcher. Just calls scene manager. */
|
||||||
static bool esubghz_chat_custom_event_callback(void* context, uint32_t event)
|
static bool esubghz_chat_custom_event_callback(void* context, uint32_t event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_custom_event_callback");
|
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_custom_event_callback");
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
@@ -233,8 +211,7 @@ static bool esubghz_chat_custom_event_callback(void* context, uint32_t event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Navigation event callback for view dispatcher. Just calls scene manager. */
|
/* Navigation event callback for view dispatcher. Just calls scene manager. */
|
||||||
static bool esubghz_chat_navigation_event_callback(void* context)
|
static bool esubghz_chat_navigation_event_callback(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_navigation_event_callback");
|
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_navigation_event_callback");
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
@@ -244,15 +221,14 @@ static bool esubghz_chat_navigation_event_callback(void* context)
|
|||||||
/* Tick event callback for view dispatcher. Called every TICK_INTERVAL. Resets
|
/* Tick event callback for view dispatcher. Called every TICK_INTERVAL. Resets
|
||||||
* the locked message if necessary. Retrieves a received message from the
|
* the locked message if necessary. Retrieves a received message from the
|
||||||
* Sub-GHz worker and calls post_rx(). Then calls the scene manager. */
|
* Sub-GHz worker and calls post_rx(). Then calls the scene manager. */
|
||||||
static void esubghz_chat_tick_event_callback(void* context)
|
static void esubghz_chat_tick_event_callback(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_tick_event_callback");
|
FURI_LOG_T(APPLICATION_NAME, "esubghz_chat_tick_event_callback");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
/* reset locked message if necessary */
|
/* reset locked message if necessary */
|
||||||
if (kbd_lock_msg_reset_timeout(state)) {
|
if(kbd_lock_msg_reset_timeout(state)) {
|
||||||
kbd_lock_msg_reset(state, true);
|
kbd_lock_msg_reset(state, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,17 +236,14 @@ static void esubghz_chat_tick_event_callback(void* context)
|
|||||||
* MESSAGE_COMPLETION_TIMEOUT has expired, retrieve a message and call
|
* MESSAGE_COMPLETION_TIMEOUT has expired, retrieve a message and call
|
||||||
* post_rx() */
|
* post_rx() */
|
||||||
size_t avail = 0;
|
size_t avail = 0;
|
||||||
while ((avail = subghz_tx_rx_worker_available(state->subghz_worker)) >
|
while((avail = subghz_tx_rx_worker_available(state->subghz_worker)) > 0) {
|
||||||
0) {
|
volatile uint32_t since_last_rx = furi_get_tick() - state->last_time_rx_data;
|
||||||
volatile uint32_t since_last_rx = furi_get_tick() -
|
if(avail < RX_TX_BUFFER_SIZE && since_last_rx < MESSAGE_COMPLETION_TIMEOUT) {
|
||||||
state->last_time_rx_data;
|
|
||||||
if (avail < RX_TX_BUFFER_SIZE && since_last_rx <
|
|
||||||
MESSAGE_COMPLETION_TIMEOUT) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t rx_size = subghz_tx_rx_worker_read(state->subghz_worker,
|
size_t rx_size =
|
||||||
state->rx_buffer, RX_TX_BUFFER_SIZE);
|
subghz_tx_rx_worker_read(state->subghz_worker, state->rx_buffer, RX_TX_BUFFER_SIZE);
|
||||||
post_rx(state, rx_size);
|
post_rx(state, rx_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,8 +253,7 @@ static void esubghz_chat_tick_event_callback(void* context)
|
|||||||
|
|
||||||
/* Hooks into the view port's draw callback to overlay the keyboard locked
|
/* Hooks into the view port's draw callback to overlay the keyboard locked
|
||||||
* message. */
|
* message. */
|
||||||
static void esubghz_hooked_draw_callback(Canvas* canvas, void* context)
|
static void esubghz_hooked_draw_callback(Canvas* canvas, void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "esubghz_hooked_draw_callback");
|
FURI_LOG_T(APPLICATION_NAME, "esubghz_hooked_draw_callback");
|
||||||
|
|
||||||
furi_assert(canvas);
|
furi_assert(canvas);
|
||||||
@@ -293,13 +265,13 @@ static void esubghz_hooked_draw_callback(Canvas* canvas, void* context)
|
|||||||
state->orig_draw_cb(canvas, state->view_dispatcher);
|
state->orig_draw_cb(canvas, state->view_dispatcher);
|
||||||
|
|
||||||
/* display if the keyboard is locked */
|
/* display if the keyboard is locked */
|
||||||
if (state->kbd_locked) {
|
if(state->kbd_locked) {
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
elements_multiline_text_framed(canvas, 42, 30, "Locked");
|
elements_multiline_text_framed(canvas, 42, 30, "Locked");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* display the unlock message if necessary */
|
/* display the unlock message if necessary */
|
||||||
if (kbd_lock_msg_display(state)) {
|
if(kbd_lock_msg_display(state)) {
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
elements_bold_rounded_frame(canvas, 14, 8, 99, 48);
|
elements_bold_rounded_frame(canvas, 14, 8, 99, 48);
|
||||||
elements_multiline_text(canvas, 65, 26, "To unlock\npress:");
|
elements_multiline_text(canvas, 65, 26, "To unlock\npress:");
|
||||||
@@ -312,8 +284,7 @@ static void esubghz_hooked_draw_callback(Canvas* canvas, void* context)
|
|||||||
|
|
||||||
/* Hooks into the view port's input callback to handle the user locking the
|
/* Hooks into the view port's input callback to handle the user locking the
|
||||||
* keyboard. */
|
* keyboard. */
|
||||||
static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
static void esubghz_hooked_input_callback(InputEvent* event, void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "esubghz_hooked_input_callback");
|
FURI_LOG_T(APPLICATION_NAME, "esubghz_hooked_input_callback");
|
||||||
|
|
||||||
furi_assert(event);
|
furi_assert(event);
|
||||||
@@ -322,21 +293,20 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
/* if the keyboard is locked no key presses are forwarded */
|
/* if the keyboard is locked no key presses are forwarded */
|
||||||
if (state->kbd_locked) {
|
if(state->kbd_locked) {
|
||||||
/* key has been pressed, display the unlock message and
|
/* key has been pressed, display the unlock message and
|
||||||
* initiate the timer */
|
* initiate the timer */
|
||||||
if (state->kbd_lock_count == 0) {
|
if(state->kbd_lock_count == 0) {
|
||||||
state->kbd_lock_msg_ticks = furi_get_tick();
|
state->kbd_lock_msg_ticks = furi_get_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* back button has been pressed, increase the lock counter */
|
/* back button has been pressed, increase the lock counter */
|
||||||
if (event->key == InputKeyBack && event->type ==
|
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||||
InputTypeShort) {
|
|
||||||
state->kbd_lock_count++;
|
state->kbd_lock_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unlock the keyboard */
|
/* unlock the keyboard */
|
||||||
if (state->kbd_lock_count >= KBD_UNLOCK_CNT) {
|
if(state->kbd_lock_count >= KBD_UNLOCK_CNT) {
|
||||||
kbd_unlock(state);
|
kbd_unlock(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,14 +314,13 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->key == InputKeyOk) {
|
if(event->key == InputKeyOk) {
|
||||||
/* if we are in the chat view and no input is ongoing, allow
|
/* if we are in the chat view and no input is ongoing, allow
|
||||||
* locking */
|
* locking */
|
||||||
if (state->view_dispatcher->current_view ==
|
if(state->view_dispatcher->current_view == text_box_get_view(state->chat_box) &&
|
||||||
text_box_get_view(state->chat_box) &&
|
|
||||||
!(state->kbd_ok_input_ongoing)) {
|
!(state->kbd_ok_input_ongoing)) {
|
||||||
/* lock keyboard upon long press of Ok button */
|
/* lock keyboard upon long press of Ok button */
|
||||||
if (event->type == InputTypeLong) {
|
if(event->type == InputTypeLong) {
|
||||||
kbd_lock(state);
|
kbd_lock(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,23 +330,22 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle ongoing inputs when changing to chat view */
|
/* handle ongoing inputs when changing to chat view */
|
||||||
if (event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
state->kbd_ok_input_ongoing = true;
|
state->kbd_ok_input_ongoing = true;
|
||||||
} else if (event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
state->kbd_ok_input_ongoing = false;
|
state->kbd_ok_input_ongoing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->key == InputKeyLeft) {
|
if(event->key == InputKeyLeft) {
|
||||||
/* if we are in the chat view and no input is ongoing, allow
|
/* if we are in the chat view and no input is ongoing, allow
|
||||||
* switching to msg input */
|
* switching to msg input */
|
||||||
if (state->view_dispatcher->current_view ==
|
if(state->view_dispatcher->current_view == text_box_get_view(state->chat_box) &&
|
||||||
text_box_get_view(state->chat_box) &&
|
|
||||||
!(state->kbd_left_input_ongoing)) {
|
!(state->kbd_left_input_ongoing)) {
|
||||||
/* go to msg input upon short press of Left button */
|
/* go to msg input upon short press of Left button */
|
||||||
if (event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_GotoMsgInput);
|
state->view_dispatcher, ESubGhzChatEvent_GotoMsgInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do not handle any Left key events to prevent
|
/* do not handle any Left key events to prevent
|
||||||
@@ -386,24 +354,23 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle ongoing inputs when changing to chat view */
|
/* handle ongoing inputs when changing to chat view */
|
||||||
if (event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
state->kbd_left_input_ongoing = true;
|
state->kbd_left_input_ongoing = true;
|
||||||
} else if (event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
state->kbd_left_input_ongoing = false;
|
state->kbd_left_input_ongoing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->key == InputKeyRight) {
|
if(event->key == InputKeyRight) {
|
||||||
/* if we are in the chat view and no input is ongoing, allow
|
/* if we are in the chat view and no input is ongoing, allow
|
||||||
* switching to key display */
|
* switching to key display */
|
||||||
if (state->view_dispatcher->current_view ==
|
if(state->view_dispatcher->current_view == text_box_get_view(state->chat_box) &&
|
||||||
text_box_get_view(state->chat_box) &&
|
|
||||||
!(state->kbd_right_input_ongoing)) {
|
!(state->kbd_right_input_ongoing)) {
|
||||||
/* go to key display upon short press of Right button
|
/* go to key display upon short press of Right button
|
||||||
*/
|
*/
|
||||||
if (event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_GotoKeyDisplay);
|
state->view_dispatcher, ESubGhzChatEvent_GotoKeyDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do not handle any Right key events to prevent
|
/* do not handle any Right key events to prevent
|
||||||
@@ -412,9 +379,9 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle ongoing inputs when changing to chat view */
|
/* handle ongoing inputs when changing to chat view */
|
||||||
if (event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
state->kbd_right_input_ongoing = true;
|
state->kbd_right_input_ongoing = true;
|
||||||
} else if (event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
state->kbd_right_input_ongoing = false;
|
state->kbd_right_input_ongoing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,17 +390,16 @@ static void esubghz_hooked_input_callback(InputEvent* event, void* context)
|
|||||||
state->orig_input_cb(event, state->view_dispatcher);
|
state->orig_input_cb(event, state->view_dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool helper_strings_alloc(ESubGhzChatState *state)
|
static bool helper_strings_alloc(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
state->name_prefix = furi_string_alloc();
|
state->name_prefix = furi_string_alloc();
|
||||||
if (state->name_prefix == NULL) {
|
if(state->name_prefix == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->msg_input = furi_string_alloc();
|
state->msg_input = furi_string_alloc();
|
||||||
if (state->msg_input == NULL) {
|
if(state->msg_input == NULL) {
|
||||||
furi_string_free(state->name_prefix);
|
furi_string_free(state->name_prefix);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -441,48 +407,43 @@ static bool helper_strings_alloc(ESubGhzChatState *state)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void helper_strings_free(ESubGhzChatState *state)
|
static void helper_strings_free(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
furi_string_free(state->name_prefix);
|
furi_string_free(state->name_prefix);
|
||||||
furi_string_free(state->msg_input);
|
furi_string_free(state->msg_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool chat_box_alloc(ESubGhzChatState *state)
|
static bool chat_box_alloc(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
state->chat_box = text_box_alloc();
|
state->chat_box = text_box_alloc();
|
||||||
if (state->chat_box == NULL) {
|
if(state->chat_box == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->chat_box_store = furi_string_alloc();
|
state->chat_box_store = furi_string_alloc();
|
||||||
if (state->chat_box_store == NULL) {
|
if(state->chat_box_store == NULL) {
|
||||||
text_box_free(state->chat_box);
|
text_box_free(state->chat_box);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_reserve(state->chat_box_store, CHAT_BOX_STORE_SIZE);
|
furi_string_reserve(state->chat_box_store, CHAT_BOX_STORE_SIZE);
|
||||||
furi_string_set_char(state->chat_box_store, 0, 0);
|
furi_string_set_char(state->chat_box_store, 0, 0);
|
||||||
text_box_set_text(state->chat_box,
|
text_box_set_text(state->chat_box, furi_string_get_cstr(state->chat_box_store));
|
||||||
furi_string_get_cstr(state->chat_box_store));
|
|
||||||
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_box_free(ESubGhzChatState *state)
|
static void chat_box_free(ESubGhzChatState* state) {
|
||||||
{
|
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
text_box_free(state->chat_box);
|
text_box_free(state->chat_box);
|
||||||
furi_string_free(state->chat_box_store);
|
furi_string_free(state->chat_box_store);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t esubghz_chat(void)
|
int32_t esubghz_chat(void) {
|
||||||
{
|
|
||||||
/* init the crypto system */
|
/* init the crypto system */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
|
|
||||||
@@ -492,80 +453,78 @@ int32_t esubghz_chat(void)
|
|||||||
|
|
||||||
/* allocate necessary structs and buffers */
|
/* allocate necessary structs and buffers */
|
||||||
|
|
||||||
ESubGhzChatState *state = malloc(sizeof(ESubGhzChatState));
|
ESubGhzChatState* state = malloc(sizeof(ESubGhzChatState));
|
||||||
if (state == NULL) {
|
if(state == NULL) {
|
||||||
goto err_alloc;
|
goto err_alloc;
|
||||||
}
|
}
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
state->scene_manager = scene_manager_alloc(
|
state->scene_manager = scene_manager_alloc(&esubghz_chat_scene_event_handlers, state);
|
||||||
&esubghz_chat_scene_event_handlers, state);
|
if(state->scene_manager == NULL) {
|
||||||
if (state->scene_manager == NULL) {
|
|
||||||
goto err_alloc_sm;
|
goto err_alloc_sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->view_dispatcher = view_dispatcher_alloc();
|
state->view_dispatcher = view_dispatcher_alloc();
|
||||||
if (state->view_dispatcher == NULL) {
|
if(state->view_dispatcher == NULL) {
|
||||||
goto err_alloc_vd;
|
goto err_alloc_vd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!helper_strings_alloc(state)) {
|
if(!helper_strings_alloc(state)) {
|
||||||
goto err_alloc_hs;
|
goto err_alloc_hs;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->menu = menu_alloc();
|
state->menu = menu_alloc();
|
||||||
if (state->menu == NULL) {
|
if(state->menu == NULL) {
|
||||||
goto err_alloc_menu;
|
goto err_alloc_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->text_input = text_input_alloc();
|
state->text_input = text_input_alloc();
|
||||||
if (state->text_input == NULL) {
|
if(state->text_input == NULL) {
|
||||||
goto err_alloc_ti;
|
goto err_alloc_ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->hex_key_input = byte_input_alloc();
|
state->hex_key_input = byte_input_alloc();
|
||||||
if (state->hex_key_input == NULL) {
|
if(state->hex_key_input == NULL) {
|
||||||
goto err_alloc_hki;
|
goto err_alloc_hki;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chat_box_alloc(state)) {
|
if(!chat_box_alloc(state)) {
|
||||||
goto err_alloc_cb;
|
goto err_alloc_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->key_display = dialog_ex_alloc();
|
state->key_display = dialog_ex_alloc();
|
||||||
if (state->key_display == NULL) {
|
if(state->key_display == NULL) {
|
||||||
goto err_alloc_kd;
|
goto err_alloc_kd;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->nfc_popup = popup_alloc();
|
state->nfc_popup = popup_alloc();
|
||||||
if (state->nfc_popup == NULL) {
|
if(state->nfc_popup == NULL) {
|
||||||
goto err_alloc_np;
|
goto err_alloc_np;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->subghz_worker = subghz_tx_rx_worker_alloc();
|
state->subghz_worker = subghz_tx_rx_worker_alloc();
|
||||||
if (state->subghz_worker == NULL) {
|
if(state->subghz_worker == NULL) {
|
||||||
goto err_alloc_worker;
|
goto err_alloc_worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->nfc_worker = nfc_worker_alloc();
|
state->nfc_worker = nfc_worker_alloc();
|
||||||
if (state->nfc_worker == NULL) {
|
if(state->nfc_worker == NULL) {
|
||||||
goto err_alloc_nworker;
|
goto err_alloc_nworker;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->nfc_dev_data = malloc(sizeof(NfcDeviceData));
|
state->nfc_dev_data = malloc(sizeof(NfcDeviceData));
|
||||||
if (state->nfc_dev_data == NULL) {
|
if(state->nfc_dev_data == NULL) {
|
||||||
goto err_alloc_ndevdata;
|
goto err_alloc_ndevdata;
|
||||||
}
|
}
|
||||||
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
||||||
|
|
||||||
state->crypto_ctx = crypto_ctx_alloc();
|
state->crypto_ctx = crypto_ctx_alloc();
|
||||||
if (state->crypto_ctx == NULL) {
|
if(state->crypto_ctx == NULL) {
|
||||||
goto err_alloc_crypto;
|
goto err_alloc_crypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the have_read callback of the Sub-GHz worker */
|
/* set the have_read callback of the Sub-GHz worker */
|
||||||
subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker,
|
subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker, have_read_cb, state);
|
||||||
have_read_cb, state);
|
|
||||||
|
|
||||||
/* enter suppress charge mode */
|
/* enter suppress charge mode */
|
||||||
furi_hal_power_suppress_charge_enter();
|
furi_hal_power_suppress_charge_enter();
|
||||||
@@ -575,8 +534,7 @@ int32_t esubghz_chat(void)
|
|||||||
state->subghz_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
state->subghz_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
||||||
|
|
||||||
/* set chat name prefix */
|
/* set chat name prefix */
|
||||||
furi_string_printf(state->name_prefix, "%s",
|
furi_string_printf(state->name_prefix, "%s", furi_hal_version_get_name_ptr());
|
||||||
furi_hal_version_get_name_ptr());
|
|
||||||
|
|
||||||
/* get notification record, we use this to make the flipper vibrate */
|
/* get notification record, we use this to make the flipper vibrate */
|
||||||
/* no error handling here, don't know how */
|
/* no error handling here, don't know how */
|
||||||
@@ -585,45 +543,44 @@ int32_t esubghz_chat(void)
|
|||||||
/* hook into the view port's draw and input callbacks */
|
/* hook into the view port's draw and input callbacks */
|
||||||
state->orig_draw_cb = state->view_dispatcher->view_port->draw_callback;
|
state->orig_draw_cb = state->view_dispatcher->view_port->draw_callback;
|
||||||
state->orig_input_cb = state->view_dispatcher->view_port->input_callback;
|
state->orig_input_cb = state->view_dispatcher->view_port->input_callback;
|
||||||
view_port_draw_callback_set(state->view_dispatcher->view_port,
|
view_port_draw_callback_set(
|
||||||
esubghz_hooked_draw_callback, state);
|
state->view_dispatcher->view_port, esubghz_hooked_draw_callback, state);
|
||||||
view_port_input_callback_set(state->view_dispatcher->view_port,
|
view_port_input_callback_set(
|
||||||
esubghz_hooked_input_callback, state);
|
state->view_dispatcher->view_port, esubghz_hooked_input_callback, state);
|
||||||
|
|
||||||
view_dispatcher_enable_queue(state->view_dispatcher);
|
view_dispatcher_enable_queue(state->view_dispatcher);
|
||||||
|
|
||||||
/* set callbacks for view dispatcher */
|
/* set callbacks for view dispatcher */
|
||||||
view_dispatcher_set_event_callback_context(state->view_dispatcher, state);
|
view_dispatcher_set_event_callback_context(state->view_dispatcher, state);
|
||||||
view_dispatcher_set_custom_event_callback(
|
view_dispatcher_set_custom_event_callback(
|
||||||
state->view_dispatcher,
|
state->view_dispatcher, esubghz_chat_custom_event_callback);
|
||||||
esubghz_chat_custom_event_callback);
|
|
||||||
view_dispatcher_set_navigation_event_callback(
|
view_dispatcher_set_navigation_event_callback(
|
||||||
state->view_dispatcher,
|
state->view_dispatcher, esubghz_chat_navigation_event_callback);
|
||||||
esubghz_chat_navigation_event_callback);
|
|
||||||
view_dispatcher_set_tick_event_callback(
|
view_dispatcher_set_tick_event_callback(
|
||||||
state->view_dispatcher,
|
state->view_dispatcher, esubghz_chat_tick_event_callback, TICK_INTERVAL);
|
||||||
esubghz_chat_tick_event_callback,
|
|
||||||
TICK_INTERVAL);
|
|
||||||
|
|
||||||
/* add our two views to the view dispatcher */
|
/* add our two views to the view dispatcher */
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_Menu,
|
view_dispatcher_add_view(
|
||||||
menu_get_view(state->menu));
|
state->view_dispatcher, ESubGhzChatView_Menu, menu_get_view(state->menu));
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_Input,
|
view_dispatcher_add_view(
|
||||||
text_input_get_view(state->text_input));
|
state->view_dispatcher, ESubGhzChatView_Input, text_input_get_view(state->text_input));
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_HexKeyInput,
|
view_dispatcher_add_view(
|
||||||
|
state->view_dispatcher,
|
||||||
|
ESubGhzChatView_HexKeyInput,
|
||||||
byte_input_get_view(state->hex_key_input));
|
byte_input_get_view(state->hex_key_input));
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_ChatBox,
|
view_dispatcher_add_view(
|
||||||
text_box_get_view(state->chat_box));
|
state->view_dispatcher, ESubGhzChatView_ChatBox, text_box_get_view(state->chat_box));
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay,
|
view_dispatcher_add_view(
|
||||||
|
state->view_dispatcher,
|
||||||
|
ESubGhzChatView_KeyDisplay,
|
||||||
dialog_ex_get_view(state->key_display));
|
dialog_ex_get_view(state->key_display));
|
||||||
view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_NfcPopup,
|
view_dispatcher_add_view(
|
||||||
popup_get_view(state->nfc_popup));
|
state->view_dispatcher, ESubGhzChatView_NfcPopup, popup_get_view(state->nfc_popup));
|
||||||
|
|
||||||
/* get the GUI record and attach the view dispatcher to the GUI */
|
/* get the GUI record and attach the view dispatcher to the GUI */
|
||||||
/* no error handling here, don't know how */
|
/* no error handling here, don't know how */
|
||||||
Gui *gui = furi_record_open(RECORD_GUI);
|
Gui* gui = furi_record_open(RECORD_GUI);
|
||||||
view_dispatcher_attach_to_gui(state->view_dispatcher, gui,
|
view_dispatcher_attach_to_gui(state->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||||
ViewDispatcherTypeFullscreen);
|
|
||||||
|
|
||||||
/* switch to the frequency input scene */
|
/* switch to the frequency input scene */
|
||||||
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
|
||||||
@@ -633,7 +590,7 @@ int32_t esubghz_chat(void)
|
|||||||
view_dispatcher_run(state->view_dispatcher);
|
view_dispatcher_run(state->view_dispatcher);
|
||||||
|
|
||||||
/* if it is running, stop the Sub-GHz worker */
|
/* if it is running, stop the Sub-GHz worker */
|
||||||
if (subghz_tx_rx_worker_is_running(state->subghz_worker)) {
|
if(subghz_tx_rx_worker_is_running(state->subghz_worker)) {
|
||||||
exit_chat(state);
|
exit_chat(state);
|
||||||
subghz_tx_rx_worker_stop(state->subghz_worker);
|
subghz_tx_rx_worker_stop(state->subghz_worker);
|
||||||
}
|
}
|
||||||
@@ -647,32 +604,24 @@ int32_t esubghz_chat(void)
|
|||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
/* remove our two views from the view dispatcher */
|
/* remove our two views from the view dispatcher */
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_Menu);
|
||||||
ESubGhzChatView_Menu);
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_HexKeyInput);
|
||||||
ESubGhzChatView_Input);
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
|
||||||
ESubGhzChatView_HexKeyInput);
|
view_dispatcher_remove_view(state->view_dispatcher, ESubGhzChatView_NfcPopup);
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
|
||||||
ESubGhzChatView_ChatBox);
|
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
|
||||||
ESubGhzChatView_KeyDisplay);
|
|
||||||
view_dispatcher_remove_view(state->view_dispatcher,
|
|
||||||
ESubGhzChatView_NfcPopup);
|
|
||||||
|
|
||||||
/* close notification record */
|
/* close notification record */
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
/* clear the key and potential password */
|
/* clear the key and potential password */
|
||||||
crypto_explicit_bzero(state->text_input_store,
|
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
|
||||||
sizeof(state->text_input_store));
|
crypto_explicit_bzero(state->hex_key_input_store, sizeof(state->hex_key_input_store));
|
||||||
crypto_explicit_bzero(state->hex_key_input_store,
|
|
||||||
sizeof(state->hex_key_input_store));
|
|
||||||
crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
|
crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
|
||||||
crypto_ctx_clear(state->crypto_ctx);
|
crypto_ctx_clear(state->crypto_ctx);
|
||||||
|
|
||||||
/* clear nfc data */
|
/* clear nfc data */
|
||||||
if (state->nfc_dev_data->parsed_data != NULL) {
|
if(state->nfc_dev_data->parsed_data != NULL) {
|
||||||
furi_string_free(state->nfc_dev_data->parsed_data);
|
furi_string_free(state->nfc_dev_data->parsed_data);
|
||||||
}
|
}
|
||||||
crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData));
|
crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData));
|
||||||
@@ -727,7 +676,7 @@ err_alloc_sm:
|
|||||||
free(state);
|
free(state);
|
||||||
|
|
||||||
err_alloc:
|
err_alloc:
|
||||||
if (err != 0) {
|
if(err != 0) {
|
||||||
FURI_LOG_E(APPLICATION_NAME, "Failed to launch (alloc error)!");
|
FURI_LOG_E(APPLICATION_NAME, "Failed to launch (alloc error)!");
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_I(APPLICATION_NAME, "Clean exit.");
|
FURI_LOG_I(APPLICATION_NAME, "Clean exit.");
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
#include "../esubghz_chat_i.h"
|
#include "../esubghz_chat_i.h"
|
||||||
|
|
||||||
/* Prepares the text box scene. */
|
/* Prepares the text box scene. */
|
||||||
void scene_on_enter_chat_box(void* context)
|
void scene_on_enter_chat_box(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_box");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_box");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
text_box_reset(state->chat_box);
|
text_box_reset(state->chat_box);
|
||||||
text_box_set_text(state->chat_box,
|
text_box_set_text(state->chat_box, furi_string_get_cstr(state->chat_box_store));
|
||||||
furi_string_get_cstr(state->chat_box_store));
|
|
||||||
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the text box scene. */
|
/* Handles scene manager events for the text box scene. */
|
||||||
bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
|
bool scene_on_event_chat_box(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -31,15 +28,13 @@ bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to message input scene */
|
/* switch to message input scene */
|
||||||
case ESubGhzChatEvent_GotoMsgInput:
|
case ESubGhzChatEvent_GotoMsgInput:
|
||||||
if (!scene_manager_previous_scene(
|
if(!scene_manager_previous_scene(state->scene_manager)) {
|
||||||
state->scene_manager)) {
|
|
||||||
view_dispatcher_stop(state->view_dispatcher);
|
view_dispatcher_stop(state->view_dispatcher);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case ESubGhzChatEvent_GotoKeyDisplay:
|
case ESubGhzChatEvent_GotoKeyDisplay:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyDisplay);
|
||||||
ESubGhzChatScene_KeyDisplay);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -54,8 +49,7 @@ bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the text box scene. */
|
/* Cleans up the text box scene. */
|
||||||
void scene_on_exit_chat_box(void* context)
|
void scene_on_exit_chat_box(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_box");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_box");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -6,18 +6,15 @@
|
|||||||
* then copied into the TX buffer. The contents of the TX buffer are then
|
* then copied into the TX buffer. The contents of the TX buffer are then
|
||||||
* transmitted. The sent message is appended to the text box and a MsgEntered
|
* transmitted. The sent message is appended to the text box and a MsgEntered
|
||||||
* event is sent to the scene manager to switch to the text box view. */
|
* event is sent to the scene manager to switch to the text box view. */
|
||||||
static bool chat_input_validator(const char *text, FuriString *error,
|
static bool chat_input_validator(const char* text, FuriString* error, void* context) {
|
||||||
void *context)
|
|
||||||
{
|
|
||||||
UNUSED(error);
|
UNUSED(error);
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
/* no message, just switch to the text box view */
|
/* no message, just switch to the text box view */
|
||||||
if (strlen(text) == 0) {
|
if(strlen(text) == 0) {
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_MsgEntered);
|
||||||
ESubGhzChatEvent_MsgEntered);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,15 +33,13 @@ static bool chat_input_validator(const char *text, FuriString *error,
|
|||||||
furi_string_set_char(state->msg_input, 0, 0);
|
furi_string_set_char(state->msg_input, 0, 0);
|
||||||
|
|
||||||
/* switch to text box view */
|
/* switch to text box view */
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_MsgEntered);
|
||||||
ESubGhzChatEvent_MsgEntered);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the message input scene. */
|
/* Prepares the message input scene. */
|
||||||
void scene_on_enter_chat_input(void* context)
|
void scene_on_enter_chat_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -61,18 +56,14 @@ void scene_on_enter_chat_input(void* context)
|
|||||||
state->text_input_store,
|
state->text_input_store,
|
||||||
sizeof(state->text_input_store),
|
sizeof(state->text_input_store),
|
||||||
true);
|
true);
|
||||||
text_input_set_validator(
|
text_input_set_validator(state->text_input, chat_input_validator, state);
|
||||||
state->text_input,
|
|
||||||
chat_input_validator,
|
|
||||||
state);
|
|
||||||
set_chat_input_header(state);
|
set_chat_input_header(state);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the message input scene. */
|
/* Handles scene manager events for the message input scene. */
|
||||||
bool scene_on_event_chat_input(void* context, SceneManagerEvent event)
|
bool scene_on_event_chat_input(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -85,8 +76,7 @@ bool scene_on_event_chat_input(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to text box scene */
|
/* switch to text box scene */
|
||||||
case ESubGhzChatEvent_MsgEntered:
|
case ESubGhzChatEvent_MsgEntered:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatBox);
|
||||||
ESubGhzChatScene_ChatBox);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -107,8 +97,7 @@ bool scene_on_event_chat_input(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the password input scene. */
|
/* Cleans up the password input scene. */
|
||||||
void scene_on_exit_chat_input(void* context)
|
void scene_on_exit_chat_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -2,22 +2,17 @@
|
|||||||
|
|
||||||
/* Sends FreqEntered event to scene manager and displays the frequency in the
|
/* Sends FreqEntered event to scene manager and displays the frequency in the
|
||||||
* text box. */
|
* text box. */
|
||||||
static void freq_input_cb(void *context)
|
static void freq_input_cb(void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu",
|
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency);
|
||||||
state->frequency);
|
|
||||||
|
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_FreqEntered);
|
||||||
ESubGhzChatEvent_FreqEntered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validates the entered frequency. */
|
/* Validates the entered frequency. */
|
||||||
static bool freq_input_validator(const char *text, FuriString *error,
|
static bool freq_input_validator(const char* text, FuriString* error, void* context) {
|
||||||
void *context)
|
|
||||||
{
|
|
||||||
furi_assert(text);
|
furi_assert(text);
|
||||||
furi_assert(error);
|
furi_assert(error);
|
||||||
|
|
||||||
@@ -25,25 +20,22 @@ static bool freq_input_validator(const char *text, FuriString *error,
|
|||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
int ret = sscanf(text, "%lu", &(state->frequency));
|
int ret = sscanf(text, "%lu", &(state->frequency));
|
||||||
if (ret != 1) {
|
if(ret != 1) {
|
||||||
furi_string_printf(error, "Please enter\nfrequency\nin Hz!");
|
furi_string_printf(error, "Please enter\nfrequency\nin Hz!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subghz_devices_is_frequency_valid(state->subghz_device,
|
if(!subghz_devices_is_frequency_valid(state->subghz_device, state->frequency)) {
|
||||||
state->frequency)) {
|
furi_string_printf(error, "Frequency\n%lu\n is invalid!", state->frequency);
|
||||||
furi_string_printf(error, "Frequency\n%lu\n is invalid!",
|
|
||||||
state->frequency);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FW_ORIGIN_Official
|
#ifdef FW_ORIGIN_Official
|
||||||
if (!furi_hal_region_is_frequency_allowed(state->frequency)) {
|
if(!furi_hal_region_is_frequency_allowed(state->frequency)) {
|
||||||
#else /* FW_ORIGIN_Official */
|
#else /* FW_ORIGIN_Official */
|
||||||
if (!furi_hal_subghz_is_tx_allowed(state->frequency)) {
|
if(!furi_hal_subghz_is_tx_allowed(state->frequency)) {
|
||||||
#endif /* FW_ORIGIN_Official */
|
#endif /* FW_ORIGIN_Official */
|
||||||
furi_string_printf(error, "TX forbidden\non frequency\n%lu!",
|
furi_string_printf(error, "TX forbidden\non frequency\n%lu!", state->frequency);
|
||||||
state->frequency);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,15 +43,13 @@ static bool freq_input_validator(const char *text, FuriString *error,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the frequency input scene. */
|
/* Prepares the frequency input scene. */
|
||||||
void scene_on_enter_freq_input(void* context)
|
void scene_on_enter_freq_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_freq_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_freq_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu",
|
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", (uint32_t)DEFAULT_FREQ);
|
||||||
(uint32_t) DEFAULT_FREQ);
|
|
||||||
text_input_reset(state->text_input);
|
text_input_reset(state->text_input);
|
||||||
text_input_set_result_callback(
|
text_input_set_result_callback(
|
||||||
state->text_input,
|
state->text_input,
|
||||||
@@ -68,20 +58,14 @@ void scene_on_enter_freq_input(void* context)
|
|||||||
state->text_input_store,
|
state->text_input_store,
|
||||||
sizeof(state->text_input_store),
|
sizeof(state->text_input_store),
|
||||||
true);
|
true);
|
||||||
text_input_set_validator(
|
text_input_set_validator(state->text_input, freq_input_validator, state);
|
||||||
state->text_input,
|
text_input_set_header_text(state->text_input, "Frequency");
|
||||||
freq_input_validator,
|
|
||||||
state);
|
|
||||||
text_input_set_header_text(
|
|
||||||
state->text_input,
|
|
||||||
"Frequency");
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the frequency input scene. */
|
/* Handles scene manager events for the frequency input scene. */
|
||||||
bool scene_on_event_freq_input(void* context, SceneManagerEvent event)
|
bool scene_on_event_freq_input(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_freq_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_freq_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -94,8 +78,7 @@ bool scene_on_event_freq_input(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to password input scene */
|
/* switch to password input scene */
|
||||||
case ESubGhzChatEvent_FreqEntered:
|
case ESubGhzChatEvent_FreqEntered:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu);
|
||||||
ESubGhzChatScene_KeyMenu);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -116,8 +99,7 @@ bool scene_on_event_freq_input(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the frequency input scene. */
|
/* Cleans up the frequency input scene. */
|
||||||
void scene_on_exit_freq_input(void* context)
|
void scene_on_exit_freq_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_freq_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_freq_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -2,21 +2,18 @@
|
|||||||
|
|
||||||
/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered
|
/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered
|
||||||
* event to the scene manager. */
|
* event to the scene manager. */
|
||||||
static void hex_key_input_cb(void* context)
|
static void hex_key_input_cb(void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
/* initiate the crypto context */
|
/* initiate the crypto context */
|
||||||
bool ret = crypto_ctx_set_key(state->crypto_ctx,
|
bool ret = crypto_ctx_set_key(
|
||||||
state->hex_key_input_store, state->name_prefix,
|
state->crypto_ctx, state->hex_key_input_store, state->name_prefix, furi_get_tick());
|
||||||
furi_get_tick());
|
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
crypto_explicit_bzero(state->hex_key_input_store,
|
crypto_explicit_bzero(state->hex_key_input_store, sizeof(state->hex_key_input_store));
|
||||||
sizeof(state->hex_key_input_store));
|
|
||||||
|
|
||||||
if (!ret) {
|
if(!ret) {
|
||||||
crypto_ctx_clear(state->crypto_ctx);
|
crypto_ctx_clear(state->crypto_ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -25,32 +22,29 @@ static void hex_key_input_cb(void* context)
|
|||||||
|
|
||||||
enter_chat(state);
|
enter_chat(state);
|
||||||
|
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_HexKeyEntered);
|
||||||
ESubGhzChatEvent_HexKeyEntered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the hex key input scene. */
|
/* Prepares the hex key input scene. */
|
||||||
void scene_on_enter_hex_key_input(void* context)
|
void scene_on_enter_hex_key_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_hex_key_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_hex_key_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
byte_input_set_result_callback(state->hex_key_input,
|
byte_input_set_result_callback(
|
||||||
|
state->hex_key_input,
|
||||||
hex_key_input_cb,
|
hex_key_input_cb,
|
||||||
NULL,
|
NULL,
|
||||||
state,
|
state,
|
||||||
state->hex_key_input_store,
|
state->hex_key_input_store,
|
||||||
sizeof(state->hex_key_input_store));
|
sizeof(state->hex_key_input_store));
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_HexKeyInput);
|
||||||
ESubGhzChatView_HexKeyInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the hex key input scene. */
|
/* Handles scene manager events for the hex key input scene. */
|
||||||
bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event)
|
bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_hex_key_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_hex_key_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -63,8 +57,7 @@ bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to message input scene */
|
/* switch to message input scene */
|
||||||
case ESubGhzChatEvent_HexKeyEntered:
|
case ESubGhzChatEvent_HexKeyEntered:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
|
||||||
ESubGhzChatScene_ChatInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -79,13 +72,11 @@ bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the hex key input scene. */
|
/* Cleans up the hex key input scene. */
|
||||||
void scene_on_exit_hex_key_input(void* context)
|
void scene_on_exit_hex_key_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_hex_key_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_hex_key_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
crypto_explicit_bzero(state->hex_key_input_store,
|
crypto_explicit_bzero(state->hex_key_input_store, sizeof(state->hex_key_input_store));
|
||||||
sizeof(state->hex_key_input_store));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
#include "../esubghz_chat_i.h"
|
#include "../esubghz_chat_i.h"
|
||||||
|
|
||||||
void key_display_result_cb(DialogExResult result, void* context)
|
void key_display_result_cb(DialogExResult result, void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
switch(result) {
|
switch(result) {
|
||||||
case DialogExResultLeft:
|
case DialogExResultLeft:
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyDisplayBack);
|
||||||
ESubGhzChatEvent_KeyDisplayBack);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DialogExResultCenter:
|
case DialogExResultCenter:
|
||||||
if (state->encrypted) {
|
if(state->encrypted) {
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyDisplayShare);
|
state->view_dispatcher, ESubGhzChatEvent_KeyDisplayShare);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -24,17 +22,18 @@ void key_display_result_cb(DialogExResult result, void* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the key display scene. */
|
/* Prepares the key display scene. */
|
||||||
void scene_on_enter_key_display(void* context)
|
void scene_on_enter_key_display(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_display");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_display");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
if (state->encrypted) {
|
if(state->encrypted) {
|
||||||
uint8_t key[KEY_BITS / 8];
|
uint8_t key[KEY_BITS / 8];
|
||||||
crypto_ctx_get_key(state->crypto_ctx, key);
|
crypto_ctx_get_key(state->crypto_ctx, key);
|
||||||
snprintf(state->key_hex_str, KEY_HEX_STR_SIZE,
|
snprintf(
|
||||||
|
state->key_hex_str,
|
||||||
|
KEY_HEX_STR_SIZE,
|
||||||
"%02hX%02hX%02hX%02hX"
|
"%02hX%02hX%02hX%02hX"
|
||||||
"%02hX%02hX%02hX%02hX\n"
|
"%02hX%02hX%02hX%02hX\n"
|
||||||
"%02hX%02hX%02hX%02hX"
|
"%02hX%02hX%02hX%02hX"
|
||||||
@@ -43,14 +42,38 @@ void scene_on_enter_key_display(void* context)
|
|||||||
"%02hX%02hX%02hX%02hX\n"
|
"%02hX%02hX%02hX%02hX\n"
|
||||||
"%02hX%02hX%02hX%02hX"
|
"%02hX%02hX%02hX%02hX"
|
||||||
"%02hX%02hX%02hX%02hX",
|
"%02hX%02hX%02hX%02hX",
|
||||||
key[0], key[1], key[2], key[3],
|
key[0],
|
||||||
key[4], key[5], key[6], key[7],
|
key[1],
|
||||||
key[8], key[9], key[10], key[11],
|
key[2],
|
||||||
key[12], key[13], key[14], key[15],
|
key[3],
|
||||||
key[16], key[17], key[18], key[19],
|
key[4],
|
||||||
key[20], key[21], key[22], key[23],
|
key[5],
|
||||||
key[24], key[25], key[26], key[27],
|
key[6],
|
||||||
key[28], key[29], key[30], key[31]);
|
key[7],
|
||||||
|
key[8],
|
||||||
|
key[9],
|
||||||
|
key[10],
|
||||||
|
key[11],
|
||||||
|
key[12],
|
||||||
|
key[13],
|
||||||
|
key[14],
|
||||||
|
key[15],
|
||||||
|
key[16],
|
||||||
|
key[17],
|
||||||
|
key[18],
|
||||||
|
key[19],
|
||||||
|
key[20],
|
||||||
|
key[21],
|
||||||
|
key[22],
|
||||||
|
key[23],
|
||||||
|
key[24],
|
||||||
|
key[25],
|
||||||
|
key[26],
|
||||||
|
key[27],
|
||||||
|
key[28],
|
||||||
|
key[29],
|
||||||
|
key[30],
|
||||||
|
key[31]);
|
||||||
crypto_explicit_bzero(key, sizeof(key));
|
crypto_explicit_bzero(key, sizeof(key));
|
||||||
} else {
|
} else {
|
||||||
strcpy(state->key_hex_str, "No Key");
|
strcpy(state->key_hex_str, "No Key");
|
||||||
@@ -58,27 +81,24 @@ void scene_on_enter_key_display(void* context)
|
|||||||
|
|
||||||
dialog_ex_reset(state->key_display);
|
dialog_ex_reset(state->key_display);
|
||||||
|
|
||||||
dialog_ex_set_text(state->key_display, state->key_hex_str, 64, 2,
|
dialog_ex_set_text(state->key_display, state->key_hex_str, 64, 2, AlignCenter, AlignTop);
|
||||||
AlignCenter, AlignTop);
|
|
||||||
|
|
||||||
dialog_ex_set_icon(state->key_display, 0, 0, NULL);
|
dialog_ex_set_icon(state->key_display, 0, 0, NULL);
|
||||||
|
|
||||||
dialog_ex_set_left_button_text(state->key_display, "Back");
|
dialog_ex_set_left_button_text(state->key_display, "Back");
|
||||||
|
|
||||||
if (state->encrypted) {
|
if(state->encrypted) {
|
||||||
dialog_ex_set_center_button_text(state->key_display, "Share");
|
dialog_ex_set_center_button_text(state->key_display, "Share");
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog_ex_set_result_callback(state->key_display,
|
dialog_ex_set_result_callback(state->key_display, key_display_result_cb);
|
||||||
key_display_result_cb);
|
|
||||||
dialog_ex_set_context(state->key_display, state);
|
dialog_ex_set_context(state->key_display, state);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the key display scene. */
|
/* Handles scene manager events for the key display scene. */
|
||||||
bool scene_on_event_key_display(void* context, SceneManagerEvent event)
|
bool scene_on_event_key_display(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_display");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_display");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -91,8 +111,7 @@ bool scene_on_event_key_display(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to message input scene */
|
/* switch to message input scene */
|
||||||
case ESubGhzChatEvent_KeyDisplayBack:
|
case ESubGhzChatEvent_KeyDisplayBack:
|
||||||
if (!scene_manager_previous_scene(
|
if(!scene_manager_previous_scene(state->scene_manager)) {
|
||||||
state->scene_manager)) {
|
|
||||||
view_dispatcher_stop(state->view_dispatcher);
|
view_dispatcher_stop(state->view_dispatcher);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@@ -100,8 +119,7 @@ bool scene_on_event_key_display(void* context, SceneManagerEvent event)
|
|||||||
|
|
||||||
/* open key sharing popup */
|
/* open key sharing popup */
|
||||||
case ESubGhzChatEvent_KeyDisplayShare:
|
case ESubGhzChatEvent_KeyDisplayShare:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeySharePopup);
|
||||||
ESubGhzChatScene_KeySharePopup);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -116,8 +134,7 @@ bool scene_on_event_key_display(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the key display scene. */
|
/* Cleans up the key display scene. */
|
||||||
void scene_on_exit_key_display(void* context)
|
void scene_on_exit_key_display(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_display");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_display");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ typedef enum {
|
|||||||
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
||||||
} ESubGhzChatKeyMenuItems;
|
} ESubGhzChatKeyMenuItems;
|
||||||
|
|
||||||
static void key_menu_cb(void* context, uint32_t index)
|
static void key_menu_cb(void* context, uint32_t index) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
@@ -20,18 +19,17 @@ static void key_menu_cb(void* context, uint32_t index)
|
|||||||
state->encrypted = false;
|
state->encrypted = false;
|
||||||
enter_chat(state);
|
enter_chat(state);
|
||||||
|
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyMenuNoEncryption);
|
state->view_dispatcher, ESubGhzChatEvent_KeyMenuNoEncryption);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESubGhzChatKeyMenuItems_Password:
|
case ESubGhzChatKeyMenuItems_Password:
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyMenuPassword);
|
state->view_dispatcher, ESubGhzChatEvent_KeyMenuPassword);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESubGhzChatKeyMenuItems_HexKey:
|
case ESubGhzChatKeyMenuItems_HexKey:
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuHexKey);
|
||||||
ESubGhzChatEvent_KeyMenuHexKey);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESubGhzChatKeyMenuItems_GenKey:
|
case ESubGhzChatKeyMenuItems_GenKey:
|
||||||
@@ -39,13 +37,12 @@ static void key_menu_cb(void* context, uint32_t index)
|
|||||||
furi_hal_random_fill_buf(key, KEY_BITS / 8);
|
furi_hal_random_fill_buf(key, KEY_BITS / 8);
|
||||||
|
|
||||||
/* initiate the crypto context */
|
/* initiate the crypto context */
|
||||||
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
|
bool ret = crypto_ctx_set_key(state->crypto_ctx, key, state->name_prefix, furi_get_tick());
|
||||||
state->name_prefix, furi_get_tick());
|
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
crypto_explicit_bzero(key, sizeof(key));
|
crypto_explicit_bzero(key, sizeof(key));
|
||||||
|
|
||||||
if (!ret) {
|
if(!ret) {
|
||||||
crypto_ctx_clear(state->crypto_ctx);
|
crypto_ctx_clear(state->crypto_ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -54,13 +51,12 @@ static void key_menu_cb(void* context, uint32_t index)
|
|||||||
state->encrypted = true;
|
state->encrypted = true;
|
||||||
enter_chat(state);
|
enter_chat(state);
|
||||||
|
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuGenKey);
|
||||||
ESubGhzChatEvent_KeyMenuGenKey);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
|
case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
|
state->view_dispatcher, ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -69,8 +65,7 @@ static void key_menu_cb(void* context, uint32_t index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the key menu scene. */
|
/* Prepares the key menu scene. */
|
||||||
void scene_on_enter_key_menu(void* context)
|
void scene_on_enter_key_menu(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_menu");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_menu");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -84,47 +79,26 @@ void scene_on_enter_key_menu(void* context)
|
|||||||
NULL,
|
NULL,
|
||||||
ESubGhzChatKeyMenuItems_NoEncryption,
|
ESubGhzChatKeyMenuItems_NoEncryption,
|
||||||
key_menu_cb,
|
key_menu_cb,
|
||||||
state
|
state);
|
||||||
);
|
|
||||||
menu_add_item(
|
menu_add_item(
|
||||||
state->menu,
|
state->menu, "Password", NULL, ESubGhzChatKeyMenuItems_Password, key_menu_cb, state);
|
||||||
"Password",
|
|
||||||
NULL,
|
|
||||||
ESubGhzChatKeyMenuItems_Password,
|
|
||||||
key_menu_cb,
|
|
||||||
state
|
|
||||||
);
|
|
||||||
menu_add_item(
|
menu_add_item(
|
||||||
state->menu,
|
state->menu, "Hex Key", NULL, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state);
|
||||||
"Hex Key",
|
|
||||||
NULL,
|
|
||||||
ESubGhzChatKeyMenuItems_HexKey,
|
|
||||||
key_menu_cb,
|
|
||||||
state
|
|
||||||
);
|
|
||||||
menu_add_item(
|
menu_add_item(
|
||||||
state->menu,
|
state->menu, "Generate Key", NULL, ESubGhzChatKeyMenuItems_GenKey, key_menu_cb, state);
|
||||||
"Generate Key",
|
|
||||||
NULL,
|
|
||||||
ESubGhzChatKeyMenuItems_GenKey,
|
|
||||||
key_menu_cb,
|
|
||||||
state
|
|
||||||
);
|
|
||||||
menu_add_item(
|
menu_add_item(
|
||||||
state->menu,
|
state->menu,
|
||||||
"Read Key from NFC",
|
"Read Key from NFC",
|
||||||
NULL,
|
NULL,
|
||||||
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
|
||||||
key_menu_cb,
|
key_menu_cb,
|
||||||
state
|
state);
|
||||||
);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the key menu scene. */
|
/* Handles scene manager events for the key menu scene. */
|
||||||
bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
|
bool scene_on_event_key_menu(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_menu");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_menu");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -138,29 +112,25 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
|
|||||||
/* switch to message input scene */
|
/* switch to message input scene */
|
||||||
case ESubGhzChatEvent_KeyMenuNoEncryption:
|
case ESubGhzChatEvent_KeyMenuNoEncryption:
|
||||||
case ESubGhzChatEvent_KeyMenuGenKey:
|
case ESubGhzChatEvent_KeyMenuGenKey:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
|
||||||
ESubGhzChatScene_ChatInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* switch to password input scene */
|
/* switch to password input scene */
|
||||||
case ESubGhzChatEvent_KeyMenuPassword:
|
case ESubGhzChatEvent_KeyMenuPassword:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_PassInput);
|
||||||
ESubGhzChatScene_PassInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* switch to hex key input scene */
|
/* switch to hex key input scene */
|
||||||
case ESubGhzChatEvent_KeyMenuHexKey:
|
case ESubGhzChatEvent_KeyMenuHexKey:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_HexKeyInput);
|
||||||
ESubGhzChatScene_HexKeyInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* switch to hex key read scene */
|
/* switch to hex key read scene */
|
||||||
case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
|
case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
||||||
ESubGhzChatScene_KeyReadPopup);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -182,8 +152,7 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the key menu scene. */
|
/* Cleans up the key menu scene. */
|
||||||
void scene_on_exit_key_menu(void* context)
|
void scene_on_exit_key_menu(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_menu");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_menu");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -191,4 +160,3 @@ void scene_on_exit_key_menu(void* context)
|
|||||||
|
|
||||||
menu_reset(state->menu);
|
menu_reset(state->menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ typedef enum {
|
|||||||
KeyReadPopupState_Success,
|
KeyReadPopupState_Success,
|
||||||
} KeyReadPopupState;
|
} KeyReadPopupState;
|
||||||
|
|
||||||
static bool read_worker_cb(NfcWorkerEvent event, void* context)
|
static bool read_worker_cb(NfcWorkerEvent event, void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
@@ -18,43 +17,40 @@ static bool read_worker_cb(NfcWorkerEvent event, void* context)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void key_read_popup_timeout_cb(void* context)
|
static void key_read_popup_timeout_cb(void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
uint32_t cur_state = scene_manager_get_scene_state(
|
uint32_t cur_state =
|
||||||
state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
||||||
|
|
||||||
/* done displaying our failure */
|
/* done displaying our failure */
|
||||||
if (cur_state == KeyReadPopupState_Fail) {
|
if(cur_state == KeyReadPopupState_Fail) {
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyReadPopupFailed);
|
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed);
|
||||||
/* done displaying our success, enter chat */
|
/* done displaying our success, enter chat */
|
||||||
} else if (cur_state == KeyReadPopupState_Success) {
|
} else if(cur_state == KeyReadPopupState_Success) {
|
||||||
enter_chat(state);
|
enter_chat(state);
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(
|
||||||
ESubGhzChatEvent_KeyReadPopupSucceeded);
|
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
|
static bool key_read_popup_handle_key_read(ESubGhzChatState* state) {
|
||||||
{
|
NfcDeviceData* dev_data = state->nfc_dev_data;
|
||||||
NfcDeviceData *dev_data = state->nfc_dev_data;
|
|
||||||
|
|
||||||
if (dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
|
if(dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initiate the crypto context */
|
/* initiate the crypto context */
|
||||||
bool ret = crypto_ctx_set_key(state->crypto_ctx,
|
bool ret = crypto_ctx_set_key(
|
||||||
dev_data->mf_ul_data.data, state->name_prefix,
|
state->crypto_ctx, dev_data->mf_ul_data.data, state->name_prefix, furi_get_tick());
|
||||||
furi_get_tick());
|
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
|
crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
|
||||||
|
|
||||||
if (!ret) {
|
if(!ret) {
|
||||||
crypto_ctx_clear(state->crypto_ctx);
|
crypto_ctx_clear(state->crypto_ctx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -65,78 +61,69 @@ static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void key_read_popup_set_state(ESubGhzChatState *state, KeyReadPopupState
|
static void key_read_popup_set_state(ESubGhzChatState* state, KeyReadPopupState new_state) {
|
||||||
new_state)
|
uint32_t cur_state =
|
||||||
{
|
scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
||||||
uint32_t cur_state = scene_manager_get_scene_state(
|
if(cur_state == new_state) {
|
||||||
state->scene_manager, ESubGhzChatScene_KeyReadPopup);
|
|
||||||
if (cur_state == new_state) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_state == KeyReadPopupState_Detecting) {
|
if(new_state == KeyReadPopupState_Detecting) {
|
||||||
popup_reset(state->nfc_popup);
|
popup_reset(state->nfc_popup);
|
||||||
popup_disable_timeout(state->nfc_popup);
|
popup_disable_timeout(state->nfc_popup);
|
||||||
popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97,
|
popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97, 24, AlignCenter, AlignTop);
|
||||||
24, AlignCenter, AlignTop);
|
|
||||||
popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
|
popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_blink_start_cyan);
|
||||||
&sequence_blink_start_cyan);
|
} else if(new_state == KeyReadPopupState_Reading) {
|
||||||
} else if (new_state == KeyReadPopupState_Reading) {
|
|
||||||
popup_reset(state->nfc_popup);
|
popup_reset(state->nfc_popup);
|
||||||
popup_disable_timeout(state->nfc_popup);
|
popup_disable_timeout(state->nfc_popup);
|
||||||
popup_set_header(state->nfc_popup, "Reading key\nDon't "
|
popup_set_header(
|
||||||
"move...", 85, 24, AlignCenter, AlignTop);
|
state->nfc_popup,
|
||||||
|
"Reading key\nDon't "
|
||||||
|
"move...",
|
||||||
|
85,
|
||||||
|
24,
|
||||||
|
AlignCenter,
|
||||||
|
AlignTop);
|
||||||
popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
|
popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_blink_start_yellow);
|
||||||
&sequence_blink_start_yellow);
|
} else if(new_state == KeyReadPopupState_Fail) {
|
||||||
} else if (new_state == KeyReadPopupState_Fail) {
|
|
||||||
nfc_worker_stop(state->nfc_worker);
|
nfc_worker_stop(state->nfc_worker);
|
||||||
|
|
||||||
popup_reset(state->nfc_popup);
|
popup_reset(state->nfc_popup);
|
||||||
popup_set_header(state->nfc_popup, "Failure!", 64, 2,
|
popup_set_header(state->nfc_popup, "Failure!", 64, 2, AlignCenter, AlignTop);
|
||||||
AlignCenter, AlignTop);
|
popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78, 16, AlignLeft, AlignTop);
|
||||||
popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78,
|
|
||||||
16, AlignLeft, AlignTop);
|
|
||||||
popup_set_icon(state->nfc_popup, 21, 13, &I_Cry_dolph_55x52);
|
popup_set_icon(state->nfc_popup, 21, 13, &I_Cry_dolph_55x52);
|
||||||
|
|
||||||
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
||||||
popup_set_context(state->nfc_popup, state);
|
popup_set_context(state->nfc_popup, state);
|
||||||
popup_set_callback(state->nfc_popup,
|
popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb);
|
||||||
key_read_popup_timeout_cb);
|
|
||||||
popup_enable_timeout(state->nfc_popup);
|
popup_enable_timeout(state->nfc_popup);
|
||||||
|
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_blink_stop);
|
||||||
&sequence_blink_stop);
|
} else if(new_state == KeyReadPopupState_Success) {
|
||||||
} else if (new_state == KeyReadPopupState_Success) {
|
|
||||||
nfc_worker_stop(state->nfc_worker);
|
nfc_worker_stop(state->nfc_worker);
|
||||||
|
|
||||||
popup_reset(state->nfc_popup);
|
popup_reset(state->nfc_popup);
|
||||||
popup_set_header(state->nfc_popup, "Key\nread!", 13, 22,
|
popup_set_header(state->nfc_popup, "Key\nread!", 13, 22, AlignLeft, AlignBottom);
|
||||||
AlignLeft, AlignBottom);
|
|
||||||
popup_set_icon(state->nfc_popup, 32, 5, &I_DolphinNice_96x59);
|
popup_set_icon(state->nfc_popup, 32, 5, &I_DolphinNice_96x59);
|
||||||
|
|
||||||
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
|
||||||
popup_set_context(state->nfc_popup, state);
|
popup_set_context(state->nfc_popup, state);
|
||||||
popup_set_callback(state->nfc_popup,
|
popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb);
|
||||||
key_read_popup_timeout_cb);
|
|
||||||
popup_enable_timeout(state->nfc_popup);
|
popup_enable_timeout(state->nfc_popup);
|
||||||
|
|
||||||
notification_message(state->notification, &sequence_success);
|
notification_message(state->notification, &sequence_success);
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_blink_stop);
|
||||||
&sequence_blink_stop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_manager_set_scene_state(state->scene_manager,
|
scene_manager_set_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup, new_state);
|
||||||
ESubGhzChatScene_KeyReadPopup, new_state);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup);
|
||||||
ESubGhzChatView_NfcPopup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the key share read scene. */
|
/* Prepares the key share read scene. */
|
||||||
void scene_on_enter_key_read_popup(void* context)
|
void scene_on_enter_key_read_popup(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -145,18 +132,17 @@ void scene_on_enter_key_read_popup(void* context)
|
|||||||
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
|
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
|
||||||
|
|
||||||
state->nfc_dev_data->parsed_data = furi_string_alloc();
|
state->nfc_dev_data->parsed_data = furi_string_alloc();
|
||||||
if (state->nfc_dev_data->parsed_data == NULL) {
|
if(state->nfc_dev_data->parsed_data == NULL) {
|
||||||
/* can't do anything here, crash */
|
/* can't do anything here, crash */
|
||||||
furi_check(0);
|
furi_check(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_worker_start(state->nfc_worker, NfcWorkerStateRead,
|
nfc_worker_start(
|
||||||
state->nfc_dev_data, read_worker_cb, state);
|
state->nfc_worker, NfcWorkerStateRead, state->nfc_dev_data, read_worker_cb, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the key read popup scene. */
|
/* Handles scene manager events for the key read popup scene. */
|
||||||
bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
|
bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -169,34 +155,29 @@ bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* card detected */
|
/* card detected */
|
||||||
case NfcWorkerEventCardDetected:
|
case NfcWorkerEventCardDetected:
|
||||||
key_read_popup_set_state(state,
|
key_read_popup_set_state(state, KeyReadPopupState_Reading);
|
||||||
KeyReadPopupState_Reading);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* no card detected */
|
/* no card detected */
|
||||||
case NfcWorkerEventNoCardDetected:
|
case NfcWorkerEventNoCardDetected:
|
||||||
key_read_popup_set_state(state,
|
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
|
||||||
KeyReadPopupState_Detecting);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* key probably read */
|
/* key probably read */
|
||||||
case NfcWorkerEventReadMfUltralight:
|
case NfcWorkerEventReadMfUltralight:
|
||||||
if (key_read_popup_handle_key_read(state)) {
|
if(key_read_popup_handle_key_read(state)) {
|
||||||
key_read_popup_set_state(state,
|
key_read_popup_set_state(state, KeyReadPopupState_Success);
|
||||||
KeyReadPopupState_Success);
|
|
||||||
} else {
|
} else {
|
||||||
key_read_popup_set_state(state,
|
key_read_popup_set_state(state, KeyReadPopupState_Fail);
|
||||||
KeyReadPopupState_Fail);
|
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* close the popup and go back */
|
/* close the popup and go back */
|
||||||
case ESubGhzChatEvent_KeyReadPopupFailed:
|
case ESubGhzChatEvent_KeyReadPopupFailed:
|
||||||
if (!scene_manager_previous_scene(
|
if(!scene_manager_previous_scene(state->scene_manager)) {
|
||||||
state->scene_manager)) {
|
|
||||||
view_dispatcher_stop(state->view_dispatcher);
|
view_dispatcher_stop(state->view_dispatcher);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@@ -204,15 +185,13 @@ bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
|
|||||||
|
|
||||||
/* success, go to chat input */
|
/* success, go to chat input */
|
||||||
case ESubGhzChatEvent_KeyReadPopupSucceeded:
|
case ESubGhzChatEvent_KeyReadPopupSucceeded:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
|
||||||
ESubGhzChatScene_ChatInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* something else happend, treat as failure */
|
/* something else happend, treat as failure */
|
||||||
default:
|
default:
|
||||||
key_read_popup_set_state(state,
|
key_read_popup_set_state(state, KeyReadPopupState_Fail);
|
||||||
KeyReadPopupState_Fail);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -228,23 +207,22 @@ bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the key read popup scene. */
|
/* Cleans up the key read popup scene. */
|
||||||
void scene_on_exit_key_read_popup(void* context)
|
void scene_on_exit_key_read_popup(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
popup_reset(state->nfc_popup);
|
popup_reset(state->nfc_popup);
|
||||||
scene_manager_set_scene_state(state->scene_manager,
|
scene_manager_set_scene_state(
|
||||||
ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
|
state->scene_manager, ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
|
||||||
|
|
||||||
notification_message(state->notification, &sequence_blink_stop);
|
notification_message(state->notification, &sequence_blink_stop);
|
||||||
|
|
||||||
nfc_worker_stop(state->nfc_worker);
|
nfc_worker_stop(state->nfc_worker);
|
||||||
|
|
||||||
crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
|
crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
|
||||||
if (state->nfc_dev_data->parsed_data != NULL) {
|
if(state->nfc_dev_data->parsed_data != NULL) {
|
||||||
furi_string_free(state->nfc_dev_data->parsed_data);
|
furi_string_free(state->nfc_dev_data->parsed_data);
|
||||||
}
|
}
|
||||||
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#include "../esubghz_chat_i.h"
|
#include "../esubghz_chat_i.h"
|
||||||
|
|
||||||
static void prepare_nfc_dev_data(ESubGhzChatState *state)
|
static void prepare_nfc_dev_data(ESubGhzChatState* state) {
|
||||||
{
|
NfcDeviceData* dev_data = state->nfc_dev_data;
|
||||||
NfcDeviceData *dev_data = state->nfc_dev_data;
|
|
||||||
|
|
||||||
dev_data->protocol = NfcDeviceProtocolMifareUl;
|
dev_data->protocol = NfcDeviceProtocolMifareUl;
|
||||||
furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7);
|
furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7);
|
||||||
@@ -27,8 +26,7 @@ static void prepare_nfc_dev_data(ESubGhzChatState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the key share popup scene. */
|
/* Prepares the key share popup scene. */
|
||||||
void scene_on_enter_key_share_popup(void* context)
|
void scene_on_enter_key_share_popup(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -38,26 +36,21 @@ void scene_on_enter_key_share_popup(void* context)
|
|||||||
|
|
||||||
popup_disable_timeout(state->nfc_popup);
|
popup_disable_timeout(state->nfc_popup);
|
||||||
|
|
||||||
popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft,
|
popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft, AlignTop);
|
||||||
AlignTop);
|
|
||||||
popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_47x61);
|
popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_47x61);
|
||||||
popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28,
|
popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28, AlignCenter, AlignTop);
|
||||||
AlignCenter, AlignTop);
|
|
||||||
|
|
||||||
prepare_nfc_dev_data(state);
|
prepare_nfc_dev_data(state);
|
||||||
nfc_worker_start(state->nfc_worker, NfcWorkerStateMfUltralightEmulate,
|
nfc_worker_start(
|
||||||
state->nfc_dev_data, NULL, NULL);
|
state->nfc_worker, NfcWorkerStateMfUltralightEmulate, state->nfc_dev_data, NULL, NULL);
|
||||||
|
|
||||||
notification_message(state->notification,
|
notification_message(state->notification, &sequence_blink_start_magenta);
|
||||||
&sequence_blink_start_magenta);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher,
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup);
|
||||||
ESubGhzChatView_NfcPopup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the key share popup scene. */
|
/* Handles scene manager events for the key share popup scene. */
|
||||||
bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event)
|
bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -70,8 +63,7 @@ bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the key share popup scene. */
|
/* Cleans up the key share popup scene. */
|
||||||
void scene_on_exit_key_share_popup(void* context)
|
void scene_on_exit_key_share_popup(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -1,33 +1,28 @@
|
|||||||
#include "../esubghz_chat_i.h"
|
#include "../esubghz_chat_i.h"
|
||||||
|
|
||||||
/* Sends PassEntered event to scene manager and enters the chat. */
|
/* Sends PassEntered event to scene manager and enters the chat. */
|
||||||
static void pass_input_cb(void *context)
|
static void pass_input_cb(void* context) {
|
||||||
{
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
crypto_explicit_bzero(state->text_input_store,
|
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
|
||||||
sizeof(state->text_input_store));
|
|
||||||
|
|
||||||
enter_chat(state);
|
enter_chat(state);
|
||||||
|
|
||||||
view_dispatcher_send_custom_event(state->view_dispatcher,
|
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_PassEntered);
|
||||||
ESubGhzChatEvent_PassEntered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a password was entered this derives a key from the password using a
|
/* If a password was entered this derives a key from the password using a
|
||||||
* single pass of SHA256 and initiates the AES-GCM context for encryption. If
|
* single pass of SHA256 and initiates the AES-GCM context for encryption. If
|
||||||
* the initiation fails, the password is rejected. */
|
* the initiation fails, the password is rejected. */
|
||||||
static bool pass_input_validator(const char *text, FuriString *error,
|
static bool pass_input_validator(const char* text, FuriString* error, void* context) {
|
||||||
void *context)
|
|
||||||
{
|
|
||||||
furi_assert(text);
|
furi_assert(text);
|
||||||
furi_assert(error);
|
furi_assert(error);
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
if (strlen(text) == 0) {
|
if(strlen(text) == 0) {
|
||||||
furi_string_printf(error, "Enter a\npassword!");
|
furi_string_printf(error, "Enter a\npassword!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -35,16 +30,15 @@ static bool pass_input_validator(const char *text, FuriString *error,
|
|||||||
unsigned char key[KEY_BITS / 8];
|
unsigned char key[KEY_BITS / 8];
|
||||||
|
|
||||||
/* derive a key from the password */
|
/* derive a key from the password */
|
||||||
sha256((unsigned char *) text, strlen(text), key);
|
sha256((unsigned char*)text, strlen(text), key);
|
||||||
|
|
||||||
/* initiate the crypto context */
|
/* initiate the crypto context */
|
||||||
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
|
bool ret = crypto_ctx_set_key(state->crypto_ctx, key, state->name_prefix, furi_get_tick());
|
||||||
state->name_prefix, furi_get_tick());
|
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
crypto_explicit_bzero(key, sizeof(key));
|
crypto_explicit_bzero(key, sizeof(key));
|
||||||
|
|
||||||
if (!ret) {
|
if(!ret) {
|
||||||
crypto_ctx_clear(state->crypto_ctx);
|
crypto_ctx_clear(state->crypto_ctx);
|
||||||
furi_string_printf(error, "Failed to\nset key!");
|
furi_string_printf(error, "Failed to\nset key!");
|
||||||
return false;
|
return false;
|
||||||
@@ -56,8 +50,7 @@ static bool pass_input_validator(const char *text, FuriString *error,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepares the password input scene. */
|
/* Prepares the password input scene. */
|
||||||
void scene_on_enter_pass_input(void* context)
|
void scene_on_enter_pass_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_pass_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_pass_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -72,20 +65,14 @@ void scene_on_enter_pass_input(void* context)
|
|||||||
state->text_input_store,
|
state->text_input_store,
|
||||||
sizeof(state->text_input_store),
|
sizeof(state->text_input_store),
|
||||||
true);
|
true);
|
||||||
text_input_set_validator(
|
text_input_set_validator(state->text_input, pass_input_validator, state);
|
||||||
state->text_input,
|
text_input_set_header_text(state->text_input, "Password");
|
||||||
pass_input_validator,
|
|
||||||
state);
|
|
||||||
text_input_set_header_text(
|
|
||||||
state->text_input,
|
|
||||||
"Password");
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles scene manager events for the password input scene. */
|
/* Handles scene manager events for the password input scene. */
|
||||||
bool scene_on_event_pass_input(void* context, SceneManagerEvent event)
|
bool scene_on_event_pass_input(void* context, SceneManagerEvent event) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_pass_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_pass_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -98,8 +85,7 @@ bool scene_on_event_pass_input(void* context, SceneManagerEvent event)
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
/* switch to message input scene */
|
/* switch to message input scene */
|
||||||
case ESubGhzChatEvent_PassEntered:
|
case ESubGhzChatEvent_PassEntered:
|
||||||
scene_manager_next_scene(state->scene_manager,
|
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
|
||||||
ESubGhzChatScene_ChatInput);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -114,14 +100,12 @@ bool scene_on_event_pass_input(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up the password input scene. */
|
/* Cleans up the password input scene. */
|
||||||
void scene_on_exit_pass_input(void* context)
|
void scene_on_exit_pass_input(void* context) {
|
||||||
{
|
|
||||||
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_pass_input");
|
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_pass_input");
|
||||||
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
ESubGhzChatState* state = context;
|
ESubGhzChatState* state = context;
|
||||||
|
|
||||||
text_input_reset(state->text_input);
|
text_input_reset(state->text_input);
|
||||||
crypto_explicit_bzero(state->text_input_store,
|
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
|
||||||
sizeof(state->text_input_store));
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
applications/external/wire_tester/wire_tester.c
vendored
19
applications/external/wire_tester/wire_tester.c
vendored
@@ -9,22 +9,19 @@
|
|||||||
|
|
||||||
#include "wire_tester_icons.h"
|
#include "wire_tester_icons.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TAG "wire_tester"
|
//#define TAG "wire_tester"
|
||||||
|
|
||||||
|
|
||||||
static const uint32_t EVENT_PERIOD_MS = 10; // check for input changes often
|
static const uint32_t EVENT_PERIOD_MS = 10; // check for input changes often
|
||||||
static const float BEEP_FREQ = 2400.0f; // louder than other frequencies
|
static const float BEEP_FREQ = 2400.0f; // louder than other frequencies
|
||||||
static const float BEEP_VOL = 0.8f;
|
static const float BEEP_VOL = 0.8f;
|
||||||
static const GpioPin* const INPUT_PIN = &gpio_ext_pb2; // pin 6
|
static const GpioPin* const INPUT_PIN = &gpio_ext_pb2; // pin 6
|
||||||
|
|
||||||
|
|
||||||
static void start_feedback(NotificationApp* notifications) {
|
static void start_feedback(NotificationApp* notifications) {
|
||||||
// set LED to green
|
// set LED to green
|
||||||
notification_message_block(notifications, &sequence_set_only_green_255);
|
notification_message_block(notifications, &sequence_set_only_green_255);
|
||||||
|
|
||||||
// start beep
|
// start beep
|
||||||
if (furi_hal_speaker_acquire(1000)) {
|
if(furi_hal_speaker_acquire(1000)) {
|
||||||
furi_hal_speaker_start(BEEP_FREQ, BEEP_VOL);
|
furi_hal_speaker_start(BEEP_FREQ, BEEP_VOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +31,7 @@ static void stop_feedback(NotificationApp* notifications) {
|
|||||||
notification_message_block(notifications, &sequence_reset_rgb);
|
notification_message_block(notifications, &sequence_reset_rgb);
|
||||||
|
|
||||||
// stop beep
|
// stop beep
|
||||||
if (furi_hal_speaker_is_mine()) {
|
if(furi_hal_speaker_is_mine()) {
|
||||||
furi_hal_speaker_stop();
|
furi_hal_speaker_stop();
|
||||||
furi_hal_speaker_release();
|
furi_hal_speaker_release();
|
||||||
}
|
}
|
||||||
@@ -75,21 +72,21 @@ int32_t app_main(void* p) {
|
|||||||
|
|
||||||
bool alarming = false;
|
bool alarming = false;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while (running) {
|
while(running) {
|
||||||
// start and stop feedback on the transition
|
// start and stop feedback on the transition
|
||||||
bool continuous = !furi_hal_gpio_read(INPUT_PIN);
|
bool continuous = !furi_hal_gpio_read(INPUT_PIN);
|
||||||
if (continuous && !alarming) {
|
if(continuous && !alarming) {
|
||||||
start_feedback(notifications);
|
start_feedback(notifications);
|
||||||
} else if (!continuous && alarming) {
|
} else if(!continuous && alarming) {
|
||||||
stop_feedback(notifications);
|
stop_feedback(notifications);
|
||||||
}
|
}
|
||||||
alarming = continuous;
|
alarming = continuous;
|
||||||
|
|
||||||
// exit on back key
|
// exit on back key
|
||||||
InputEvent event;
|
InputEvent event;
|
||||||
if (furi_message_queue_get(event_queue, &event, EVENT_PERIOD_MS) == FuriStatusOk) {
|
if(furi_message_queue_get(event_queue, &event, EVENT_PERIOD_MS) == FuriStatusOk) {
|
||||||
if ((event.type == InputTypePress || event.type == InputTypeRepeat)
|
if((event.type == InputTypePress || event.type == InputTypeRepeat) &&
|
||||||
&& event.key == InputKeyBack) {
|
event.key == InputKeyBack) {
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user