#include <string.h>
#include <assert.h>
#if defined(__WIN32)
#include <windows.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include "enc.h"
int encrypt_init (Encryptor *enc, uint8_t *key)
{
memcpy(enc->key, key, ENC_BLOWFISH_KEYLEN);
int res = gcry_cipher_open(&enc->ctx, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
assert(res==0);
res = gcry_cipher_setkey(enc->ctx, key, ENC_BLOWFISH_KEYLEN);
assert(res==0);
return 1;
}
int encrypt_free (Encryptor *enc)
{
gcry_cipher_close(enc->ctx);
memset(enc, 0, sizeof(Encryptor));
}
int encrypt_encrypt (Encryptor *enc, uint8_t *in, int in_len, uint8_t *out, int *out_len)
{
// generate an IV
uint8_t iv[ENC_BLOWFISH_IVLEN];
gcry_randomize(iv, ENC_BLOWFISH_IVLEN, GCRY_STRONG_RANDOM);
// copy IV
memcpy(out, iv, ENC_BLOWFISH_IVLEN);
// calculate cyphertext size
int cyphertext_size = (in_len-(in_len%ENC_BLOWFISH_BLOCKLEN))+ENC_BLOWFISH_BLOCKLEN;
int excess = cyphertext_size - in_len;
// copy data to output and set data marigin
memcpy(out+ENC_BLOWFISH_IVLEN, in, in_len);
out[ENC_BLOWFISH_IVLEN+in_len]=1;
memset(out+ENC_BLOWFISH_IVLEN+in_len+1, 0, excess-1);
// encrypt
if (gcry_cipher_setiv(enc->ctx, iv, ENC_BLOWFISH_IVLEN)) return 0;
if (gcry_cipher_encrypt(enc->ctx, out+ENC_BLOWFISH_IVLEN, cyphertext_size, NULL, 0)) return 0;
// set final size
*out_len = ENC_BLOWFISH_IVLEN+cyphertext_size;
return 1;
}
int encrypt_decrypt (Encryptor *enc, uint8_t *in, int in_len, uint8_t *out, int *out_len)
{
// read IV
if (in_len<ENC_BLOWFISH_IVLEN) return 0;
// check cyphertext size
// must be multiple of block length
// must be at least one block for padding info
int cyphertext_size = in_len-ENC_BLOWFISH_IVLEN;
if (cyphertext_size%ENC_BLOWFISH_BLOCKLEN) return 0;
if (cyphertext_size<ENC_BLOWFISH_BLOCKLEN) return 0;
// copy cyphertext to output
memcpy(out, in+ENC_BLOWFISH_IVLEN, cyphertext_size);
// decrypt cyphertext
if (gcry_cipher_setiv(enc->ctx, in, ENC_BLOWFISH_IVLEN)) return 0;
if (gcry_cipher_decrypt(enc->ctx, out, cyphertext_size, NULL, 0)) return 0;
// read marigin
int i;
for (i=cyphertext_size-1; i>=cyphertext_size-ENC_BLOWFISH_BLOCKLEN; i--)
{
if (out[i]==1)
{
*out_len = i;
return 1;
}
if (out[i]!=0) return 0;
}
return 0;
}