luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

EasyCrypto_simple.c (5568B)


      1 /*
      2  * EasyCrypto.c - Simple wrapper implementation
      3  * Links against crypto_aes.o and crypto_serpent.o
      4  */
      5 
      6 #include "EasyCrypto.h"
      7 #include "crypto_core.h"
      8 #include "CSPRNG.h"
      9 #include <stdio.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 #include <time.h>
     13 
     14 // Global key storage
     15 uint8_t EASYCRYPTO_KEY[32] = {0};
     16 
     17 // Initialized flag
     18 static int g_initialized = 0;
     19 
     20 // Generate random bytes using global CSPRNG
     21 static void generate_random_bytes(uint8_t *buf, size_t len) {
     22     random_bytes(buf, len);
     23 }
     24 
     25 void easycrypto_init(void) {
     26     if (!g_initialized) {
     27         crypto_detect_features();
     28         g_initialized = 1;
     29     }
     30 }
     31 
     32 void easycrypto_set_key(const uint8_t *key) {
     33     memcpy(EASYCRYPTO_KEY, key, 32);
     34 }
     35 
     36 void easycrypto_generate_key(uint8_t *key) {
     37     generate_random_bytes(key, 32);
     38 }
     39 
     40 CryptoResult easycrypto_encrypt(CryptoAlgorithm algo, const uint8_t *plaintext,
     41                                 size_t plaintext_len, const uint8_t *aad, size_t aad_len) {
     42     CryptoResult result = {NULL, 0, 0};
     43 
     44     if (!g_initialized) {
     45         easycrypto_init();
     46     }
     47 
     48     // Check if key is set
     49     int key_is_zero = 1;
     50     for (int i = 0; i < 32; i++) {
     51         if (EASYCRYPTO_KEY[i] != 0) {
     52             key_is_zero = 0;
     53             break;
     54         }
     55     }
     56     if (key_is_zero) {
     57         fprintf(stderr, "Error: Encryption key not set\n");
     58         return result;
     59     }
     60 
     61     // Generate random IV
     62     uint8_t iv[12];
     63     generate_random_bytes(iv, 12);
     64 
     65     // Allocate output: [algo_id(1)][iv(12)][ciphertext][tag(16)]
     66     size_t output_len = 1 + 12 + plaintext_len + 16;
     67     uint8_t *output = malloc(output_len);
     68     if (!output) {
     69         return result;
     70     }
     71 
     72     output[0] = (uint8_t)algo;
     73     memcpy(output + 1, iv, 12);
     74 
     75     uint8_t *ciphertext = output + 13;
     76     uint8_t *tag = output + 13 + plaintext_len;
     77 
     78     int status = -1;
     79 
     80     if (algo == AES_256_GCM) {
     81         if (!crypto_has_aesni || !crypto_has_pclmulqdq) {
     82             fprintf(stderr, "Error: CPU lacks AES-NI/PCLMULQDQ\n");
     83             free(output);
     84             return result;
     85         }
     86 
     87         aes256_gcm_context ctx;
     88         if (aes256_gcm_init(&ctx, EASYCRYPTO_KEY) == 0) {
     89             status = aes256_gcm_encrypt(&ctx, iv, 12, aad, aad_len,
     90                                        plaintext, plaintext_len,
     91                                        ciphertext, tag, 16);
     92         }
     93     } else if (algo == SERPENT_256_GCM) {
     94         if (!crypto_has_pclmulqdq) {
     95             fprintf(stderr, "Error: CPU lacks PCLMULQDQ\n");
     96             free(output);
     97             return result;
     98         }
     99 
    100         serpent_gcm_context ctx;
    101         if (serpent_gcm_init(&ctx, EASYCRYPTO_KEY) == 0) {
    102             status = serpent_gcm_encrypt(&ctx, iv, 12, aad, aad_len,
    103                                         plaintext, plaintext_len,
    104                                         ciphertext, tag, 16);
    105         }
    106     }
    107 
    108     if (status != 0) {
    109         free(output);
    110         return result;
    111     }
    112 
    113     result.data = output;
    114     result.length = output_len;
    115     result.success = 1;
    116 
    117     return result;
    118 }
    119 
    120 CryptoResult easycrypto_decrypt(const uint8_t *encrypted, size_t encrypted_len,
    121                                 const uint8_t *aad, size_t aad_len) {
    122     CryptoResult result = {NULL, 0, 0};
    123 
    124     if (!g_initialized) {
    125         easycrypto_init();
    126     }
    127 
    128     if (encrypted_len < 29) {
    129         fprintf(stderr, "Error: Data too short\n");
    130         return result;
    131     }
    132 
    133     CryptoAlgorithm algo = (CryptoAlgorithm)encrypted[0];
    134     const uint8_t *iv = encrypted + 1;
    135 
    136     size_t ct_len = encrypted_len - 29;
    137     const uint8_t *ciphertext = encrypted + 13;
    138     const uint8_t *tag = encrypted + 13 + ct_len;
    139 
    140     uint8_t *plaintext = malloc(ct_len);
    141     if (!plaintext) {
    142         return result;
    143     }
    144 
    145     int status = -1;
    146 
    147     if (algo == AES_256_GCM) {
    148         if (!crypto_has_aesni || !crypto_has_pclmulqdq) {
    149             fprintf(stderr, "Error: CPU lacks AES-NI/PCLMULQDQ\n");
    150             free(plaintext);
    151             return result;
    152         }
    153 
    154         aes256_gcm_context ctx;
    155         if (aes256_gcm_init(&ctx, EASYCRYPTO_KEY) == 0) {
    156             status = aes256_gcm_decrypt(&ctx, iv, 12, aad, aad_len,
    157                                        ciphertext, ct_len, tag, 16, plaintext);
    158         }
    159     } else if (algo == SERPENT_256_GCM) {
    160         if (!crypto_has_pclmulqdq) {
    161             fprintf(stderr, "Error: CPU lacks PCLMULQDQ\n");
    162             free(plaintext);
    163             return result;
    164         }
    165 
    166         serpent_gcm_context ctx;
    167         if (serpent_gcm_init(&ctx, EASYCRYPTO_KEY) == 0) {
    168             status = serpent_gcm_decrypt(&ctx, iv, 12, aad, aad_len,
    169                                         ciphertext, ct_len, tag, 16, plaintext);
    170         }
    171     }
    172 
    173     if (status != 0) {
    174         fprintf(stderr, "Error: Decryption failed\n");
    175         free(plaintext);
    176         return result;
    177     }
    178 
    179     result.data = plaintext;
    180     result.length = ct_len;
    181     result.success = 1;
    182 
    183     return result;
    184 }
    185 
    186 void easycrypto_free(CryptoResult *result) {
    187     if (result && result->data) {
    188         free(result->data);
    189         result->data = NULL;
    190         result->length = 0;
    191         result->success = 0;
    192     }
    193 }
    194 
    195 void easycrypto_print_hex(const char *label, const uint8_t *data, size_t len) {
    196     printf("%s: ", label);
    197     for (size_t i = 0; i < len; i++) {
    198         printf("%02x", data[i]);
    199     }
    200     printf("\n");
    201 }
    202 
    203 const char* easycrypto_algorithm_name(CryptoAlgorithm algo) {
    204     switch (algo) {
    205         case AES_256_GCM: return "AES-256-GCM";
    206         case SERPENT_256_GCM: return "Serpent-256-GCM";
    207         default: return "Unknown";
    208     }
    209 }