Skip to content

Commit

Permalink
Added ndpi_quick_encrypt() ndpi_quick_decrypt() APi calls (#2568)
Browse files Browse the repository at this point in the history
* Added ndpi_quick_encrypt() ndpi_quick_decrypt(0 APi calls based on AES

* Added aes.c
  • Loading branch information
lucaderi authored Sep 24, 2024
1 parent 2bf869c commit 9f3b7cf
Show file tree
Hide file tree
Showing 6 changed files with 833 additions and 0 deletions.
19 changes: 19 additions & 0 deletions example/ndpiReader.c
Original file line number Diff line number Diff line change
Expand Up @@ -6203,6 +6203,24 @@ void ballTreeUnitTest() {

/* *********************************************** */

void cryptDecryptUnitTest() {
u_char enc_dec_key[64] = "9dedb817e5a8805c1de62eb8982665b9a2b4715174c34d23b9a46ffafacfb2a7" /* SHA256("nDPI") */;
const char *test_string = "The quick brown fox jumps over the lazy dog";
char *enc, *dec;

enc = ndpi_quick_encrypt(test_string, strlen(test_string), enc_dec_key);
assert(enc != NULL);
dec = ndpi_quick_decrypt((const char*)enc, strlen(enc), enc_dec_key);
assert(dec != NULL);

assert(strcmp(dec, test_string) == 0);

ndpi_free(enc);
ndpi_free(dec);
}

/* *********************************************** */

void encodeDomainsUnitTest() {
NDPI_PROTOCOL_BITMASK all;
struct ndpi_detection_module_struct *ndpi_str = ndpi_init_detection_module(NULL);
Expand Down Expand Up @@ -6383,6 +6401,7 @@ int main(int argc, char **argv) {
exit(0);
#endif

cryptDecryptUnitTest();
kdUnitTest();
encodeDomainsUnitTest();
loadStressTest();
Expand Down
10 changes: 10 additions & 0 deletions src/include/ndpi_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -2307,6 +2307,16 @@ extern "C" {

/* ******************************* */

char* ndpi_quick_encrypt(const char *cleartext_msg,
u_int16_t cleartext_msg_len,
u_char encrypt_key[64]);

char* ndpi_quick_decrypt(const char *encrypted_msg,
u_int16_t encrypted_msg_len,
u_char decrypt_key[64]);

/* ******************************* */

bool ndpi_serialize_flow_fingerprint(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, ndpi_serializer *serializer);

Expand Down
113 changes: 113 additions & 0 deletions src/lib/ndpi_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -3687,3 +3687,116 @@ bool ndpi_serialize_flow_fingerprint(struct ndpi_detection_module_struct *ndpi_s

return(false);
}

/* ****************************************************** */
/* ****************************************************** */

#include "third_party/include/aes.h"

static void ndpi_key_hex2bin(u_char *out, u_char* key, u_int key_len) {
u_int i, j;

for(i=0, j=0; i<key_len; i += 2, j++) {
char buf[3];

buf[0] = key[i], buf[1] = key[i+1], buf[2] = '\0';
out[j] = strtol(buf, NULL, 16);
}
}

/* ****************************************************** */

/*
IMPORTANT: the returned string (if not NULL) must be freed
*/
char* ndpi_quick_encrypt(const char *cleartext_msg,
u_int16_t cleartext_msg_len,
u_char encrypt_key[64]) {
char *encoded = NULL, *encoded_buf;
struct AES_ctx ctx;
int encoded_len, i, n_padding;
u_char nonce[24] = { 0x0 };
u_char binary_encrypt_key[32];

/* AES, as a block cipher, does not change the size. The input size is always the output size.
* But AES, being a block cipher, requires the input to be multiple of block size (16 bytes). */
encoded_len = cleartext_msg_len + 16 - (cleartext_msg_len % 16);

encoded_buf = (char *)ndpi_calloc(encoded_len, 1);

if (encoded_buf == NULL) {
/* Allocation failure */
return(NULL);
}

ndpi_key_hex2bin(binary_encrypt_key, (u_char*)encrypt_key, 64);

memcpy(encoded_buf, cleartext_msg, cleartext_msg_len);

/* PKCS5 Padding (https://www.cryptosys.net/pki/manpki/pki_paddingschemes.html) */
n_padding = encoded_len - cleartext_msg_len;

for(i = encoded_len - n_padding; i < encoded_len; i++)
encoded_buf[i] = n_padding;

AES_init_ctx_iv(&ctx, binary_encrypt_key, nonce);
AES_CBC_encrypt_buffer(&ctx, (uint8_t*)encoded_buf, encoded_len);

encoded = ndpi_base64_encode((const unsigned char *)encoded_buf, encoded_len);
ndpi_free(encoded_buf);

return(encoded);
}

/* ************************************************************** */

char* ndpi_quick_decrypt(const char *encrypted_msg,
u_int16_t encrypted_msg_len,
u_char decrypt_key[64]) {
u_char nonce[24] = { 0x0 };
u_char binary_decrypt_key[32];
u_char *content;
size_t content_len, allocated_decoded_string = encrypted_msg_len + 8 /* padding */;
char *decoded_string = (char*)ndpi_calloc(sizeof(u_char), allocated_decoded_string);
u_int n_padding;
struct AES_ctx ctx;

if(decoded_string == NULL) {
/* Allocation failure */
return(NULL);
}

ndpi_key_hex2bin(binary_decrypt_key, (u_char*)decrypt_key, 64);

content = ndpi_base64_decode((const u_char*)encrypted_msg, encrypted_msg_len, &content_len);

if((content == NULL) || (content_len == 0)) {
/* Base64 decoding error */
ndpi_free(content);
return(NULL);
}

if(allocated_decoded_string < (content_len+1)) {
/* Buffer size failure */
free(content);
return(NULL);
}

/* AES - https://github.com/kokke/tiny-AES-c */
AES_init_ctx_iv(&ctx, binary_decrypt_key, nonce);
memcpy(decoded_string, content, content_len);
AES_CBC_decrypt_buffer(&ctx, (uint8_t*)decoded_string, content_len);

/* Remove PKCS5 padding */
n_padding = decoded_string[content_len-1];

if(content_len > n_padding) {
content_len = content_len - n_padding;
decoded_string[content_len] = 0;
}

ndpi_free(content);

return(decoded_string);
}

91 changes: 91 additions & 0 deletions src/lib/third_party/include/aes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#ifndef _AES_H_
#define _AES_H_

#include <stdint.h>
#include <stddef.h>

// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.

// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif

#ifndef ECB
#define ECB 1
#endif

#ifndef CTR
#define CTR 1
#endif


//#define AES128 1
//#define AES192 1
#define AES256 1

#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only

#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif

struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};

void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif

#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);

#endif // #if defined(ECB) && (ECB == !)


#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);

#endif // #if defined(CBC) && (CBC == 1)


#if defined(CTR) && (CTR == 1)

// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);

#endif // #if defined(CTR) && (CTR == 1)


#endif // _AES_H_
Loading

0 comments on commit 9f3b7cf

Please sign in to comment.