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 }