readceb/readceb.c

176 lines
3.7 KiB
C

#include <errno.h>
#include<stdlib.h>
#include<stdio.h>
#include<libgen.h>
#include <sys/syslimits.h>
#include<string.h>
#include<pwd.h>
#include<unistd.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
// crypto.h used for the version
#include <openssl/crypto.h>
#include <openssl/err.h>
#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;
}