#include #include #include #include #include #include #include #include #include #include // crypto.h used for the version #include #include #define READ_BUFFER 1024 struct ceb_header { uint32_t version; uint16_t app_len; char* app; uint16_t jid_len; char* jid; uint64_t timestamp; uint8_t iv[12]; uint8_t salt[16]; }; int main(int argc, char* argv[]) { if (argc < 2){ printf("Need 1 argument."); exit(1); } // get filename char* fn = argv[1]; // output file char* output = "out.sqlgz"; if (argc > 2) output = argv[2]; struct ceb_header header; // Open file FILE* ceb = fopen(fn, "r"); if (ceb == NULL) { perror("Couldn't open input file"); exit(errno); } // Read header fread(&header.version, sizeof(uint32_t), 1, ceb); header.version = ntohl(header.version); // Read app fread(&header.app_len, sizeof(uint16_t), 1, ceb); header.app_len = ntohs(header.app_len); header.app = malloc(header.app_len+1); fread(header.app, sizeof(char), header.app_len, ceb); header.app[header.app_len] = 0; // Read JID fread(&header.jid_len, sizeof(uint16_t), 1, ceb); header.jid_len = ntohs(header.jid_len); header.jid = malloc(header.jid_len+1); fread(header.jid, sizeof(char), header.jid_len, ceb); header.jid[header.jid_len] = 0; // Read the reset of the struct fread(&header.timestamp, sizeof(uint64_t)+12+16, 1, ceb); printf("Version %d\n%s, %s\nCreated at %llu\n", header.version, header.app, header.jid, header.timestamp); // Get password char* pw = getpass("Password: "); // Derive key uint8_t key[128]; PKCS5_PBKDF2_HMAC_SHA1(pw, strlen(pw), header.salt, 16, 1024, 128, key); // Read the whole file now uint8_t* encrypted = malloc(READ_BUFFER); if (encrypted == NULL) { printf("Error allocating..\n"); return 1; } size_t bs = READ_BUFFER; size_t pos = 0; size_t nread = 0; do { // Perform read nread = fread(encrypted+pos, sizeof(uint8_t), READ_BUFFER, ceb); // Move position over by nread pos += nread; // If the position has reached the buffer size if (pos >= bs) { // Reallocate encrypted = realloc(encrypted, pos+READ_BUFFER); // Increase tracked buffer size bs += READ_BUFFER; if (encrypted == NULL) { printf("Error allocating..\n"); exit(1); } } } while(nread != 0); printf("Total read %ld bytes\n", pos); // Reallocate encrypted = realloc(encrypted, pos); // Try perform decryption uint8_t* plaintext = malloc(pos); EVP_CIPHER_CTX *ctx; // Create cipher context if(!(ctx = EVP_CIPHER_CTX_new())) { printf("Error creating decryption context\n"); ERR_print_errors_fp(stderr); exit(1); } // Load key and iv if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, key, header.iv)){ printf("Could not DecryptInit!\n"); ERR_print_errors_fp(stderr); exit(1); } // No padding EVP_CIPHER_CTX_set_padding(ctx, 0); // decryption int dec_length = 0; int plaintext_len = 0; if (1 != EVP_DecryptUpdate(ctx, plaintext, &dec_length, encrypted, pos)){ printf("Could not DecryptUpdate!\n"); ERR_print_errors_fp(stderr); exit(1); } plaintext_len += dec_length; // finalize decryption //if (1 != EVP_DecryptFinal_ex(ctx, plaintext+plaintext_len, &dec_length)) { // printf("Could not DecryptFinal!\n"); // ERR_print_errors_fp(stderr); // exit(1); //} // Cleanup EVP_CIPHER_CTX_free(ctx); printf("Decrypted %d bytes\n", plaintext_len); fclose(ceb); // Write output file FILE* outputf = fopen(output, "w"); if (outputf == NULL) { perror("Couldn't open output file"); exit(errno); } fwrite(plaintext, sizeof(uint8_t), plaintext_len, outputf); fclose(outputf); return 0; }