commit
8b6d9dba76
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,6 +22,8 @@ doc/crypt.pdf
|
||||
doc/refman.pdf
|
||||
|
||||
# *nix/windows test executables
|
||||
aesgcm
|
||||
aesgcm.exe
|
||||
constants
|
||||
constants.exe
|
||||
ltcrypt
|
||||
|
146
demos/aesgcm.c
Normal file
146
demos/aesgcm.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file aesgcm.c
|
||||
AES128-GCM demo - file en-&decryption, Steffen Jaeckel
|
||||
Uses the format: |ciphertext|tag-16-bytes|
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <tomcrypt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gcm-file/gcm_filehandle.c"
|
||||
#include "gcm-file/gcm_file.c"
|
||||
|
||||
|
||||
static off_t fsize(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(filename, &st) == 0) return st.st_size;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mv(const char *old_name, const char *new_name)
|
||||
{
|
||||
int fd;
|
||||
if (rename(old_name, new_name) == -1) return -1;
|
||||
fd = open(new_name, 0);
|
||||
if (fd == -1) return -1;
|
||||
if (fsync(fd) != 0) goto OUT;
|
||||
syncfs(fd);
|
||||
OUT:
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* https://stackoverflow.com/a/23898449 */
|
||||
static void scan_hex(const char* str, uint8_t* bytes, size_t blen)
|
||||
{
|
||||
uint8_t pos;
|
||||
uint8_t idx0;
|
||||
uint8_t idx1;
|
||||
|
||||
const uint8_t hashmap[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
|
||||
0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
|
||||
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */
|
||||
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */
|
||||
};
|
||||
|
||||
for (pos = 0; ((pos < (blen*2)) && (pos < strlen(str))); pos += 2)
|
||||
{
|
||||
idx0 = (uint8_t)(str[pos+0] & 0x1F) ^ 0x10;
|
||||
idx1 = (uint8_t)(str[pos+1] & 0x1F) ^ 0x10;
|
||||
bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1];
|
||||
}
|
||||
}
|
||||
|
||||
static void die(int ret)
|
||||
{
|
||||
fprintf(stderr, "Usage: aesgcm <-e|-d> <infile> <outfile> <96 char hex-string 'IV | key'>\n");
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = 0, err, arg, direction, res, tmp;
|
||||
size_t keylen;
|
||||
uint8_t keybuf[48] = {0};
|
||||
char *out = NULL;
|
||||
const char *mode, *in_file, *out_file, *key_string;
|
||||
|
||||
if (argc < 5) die(__LINE__);
|
||||
|
||||
arg = 1;
|
||||
mode = argv[arg++];
|
||||
in_file = argv[arg++];
|
||||
out_file = argv[arg++];
|
||||
key_string = argv[arg++];
|
||||
|
||||
if(strcmp(mode, "-d") == 0) direction = GCM_DECRYPT;
|
||||
else if(strcmp(mode, "-e") == 0) direction = GCM_ENCRYPT;
|
||||
else die(__LINE__);
|
||||
|
||||
if (fsize(in_file) <= 0) die(__LINE__);
|
||||
|
||||
keylen = strlen(key_string);
|
||||
if (keylen != 96) die(__LINE__);
|
||||
|
||||
scan_hex(key_string, keybuf, sizeof(keybuf));
|
||||
|
||||
register_all_ciphers();
|
||||
|
||||
if(asprintf(&out, "%s-XXXXXX", out_file) < 0) die(__LINE__);
|
||||
if((tmp = mkstemp(out)) == -1) {
|
||||
ret = __LINE__;
|
||||
goto cleanup;
|
||||
}
|
||||
close(tmp);
|
||||
if((err = gcm_file(find_cipher("aes"), &keybuf[16], 32, keybuf, 16, NULL, 0, in_file, out, 16, direction, &res)) != CRYPT_OK) {
|
||||
fprintf(stderr, "boooh %s\n", error_to_string(err));
|
||||
ret = __LINE__;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(res != 1) {
|
||||
ret = __LINE__;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mv(out, out_file) != 0) ret = __LINE__;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if(ret != 0) unlink(out);
|
||||
free(out);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
91
demos/gcm-file/gcm_file.c
Normal file
91
demos/gcm-file/gcm_file.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file gcm_file.c
|
||||
GCM process a file, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_GCM_MODE
|
||||
#ifndef LTC_NO_FILE
|
||||
|
||||
/**
|
||||
Process a file.
|
||||
|
||||
c.f. gcm_filehandle() for basic documentation.
|
||||
|
||||
It is possible, that in error-cases the 'out' file
|
||||
will be created and after the error occurred it will
|
||||
be removed again.
|
||||
|
||||
@param cipher Index of cipher to use
|
||||
@param key The secret key
|
||||
@param keylen The length of the secret key
|
||||
@param IV The initial vector
|
||||
@param IVlen The length of the initial vector
|
||||
@param adata The additional authentication data (header)
|
||||
@param adatalen The length of the adata
|
||||
@param in The input file
|
||||
@param out The output file
|
||||
@param taglen The MAC tag length
|
||||
@param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int gcm_file( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
const char *in,
|
||||
const char *out,
|
||||
unsigned long taglen,
|
||||
int direction,
|
||||
int *res)
|
||||
{
|
||||
int err;
|
||||
FILE *f_in = NULL, *f_out = NULL;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(res != NULL);
|
||||
|
||||
f_in = fopen(in, "rb");
|
||||
if (f_in == NULL) {
|
||||
err = CRYPT_FILE_NOTFOUND;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
f_out = fopen(out, "w+b");
|
||||
if (f_out == NULL) {
|
||||
err = CRYPT_FILE_NOTFOUND;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
err = gcm_filehandle(cipher, key, keylen, IV, IVlen, adata, adatalen, f_in, f_out, taglen, direction, res);
|
||||
|
||||
LBL_ERR:
|
||||
if (f_out != NULL && fclose(f_out) != 0) {
|
||||
err = CRYPT_ERROR;
|
||||
}
|
||||
if (*res != 1) {
|
||||
remove(out);
|
||||
}
|
||||
if (f_in != NULL && fclose(f_in) != 0) {
|
||||
err = CRYPT_ERROR;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
201
demos/gcm-file/gcm_filehandle.c
Normal file
201
demos/gcm-file/gcm_filehandle.c
Normal file
@ -0,0 +1,201 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file gcm_filehandle.c
|
||||
GCM process a filehandle, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_GCM_MODE
|
||||
#ifndef LTC_NO_FILE
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ftruncate _chsize
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
Process a filehandle.
|
||||
|
||||
This uses the widely established scheme where the tag is appended
|
||||
to the ciphertext.
|
||||
|
||||
encrypted_file = aesgcm(plain_file) | aesgcm_tag(plain_file)
|
||||
|
||||
Depending on 'direction' this function does:
|
||||
|
||||
Encrypt file 'in' to 'out' and append the tag of length 'taglen'
|
||||
to 'out'.
|
||||
|
||||
or
|
||||
|
||||
Decrypt file 'in' to 'out' and check the tag of length 'taglen'
|
||||
and strip the tag from 'in'.
|
||||
|
||||
In error-cases 'out' will be zeroed out first and then truncated to
|
||||
a length of 0.
|
||||
|
||||
@param cipher Index of cipher to use
|
||||
@param key The secret key
|
||||
@param keylen The length of the secret key
|
||||
@param IV The initial vector
|
||||
@param IVlen The length of the initial vector
|
||||
@param adata The additional authentication data (header)
|
||||
@param adatalen The length of the adata
|
||||
@param in The input file
|
||||
@param out The output file
|
||||
@param taglen The MAC tag length
|
||||
@param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int gcm_filehandle( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
FILE *in,
|
||||
FILE *out,
|
||||
unsigned long taglen,
|
||||
int direction,
|
||||
int *res)
|
||||
{
|
||||
void *orig;
|
||||
gcm_state *gcm;
|
||||
int err;
|
||||
unsigned char *buf, tag[16];
|
||||
size_t x, tot_data;
|
||||
unsigned long tag_len;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(res != NULL);
|
||||
|
||||
*res = 0;
|
||||
|
||||
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef LTC_GCM_TABLES_SSE2
|
||||
orig = gcm = XMALLOC(sizeof(*gcm));
|
||||
#else
|
||||
orig = gcm = XMALLOC(sizeof(*gcm) + 16);
|
||||
#endif
|
||||
if (gcm == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) {
|
||||
XFREE(gcm);
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
/* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations
|
||||
* note that we only modify gcm and keep orig intact. This code is not portable
|
||||
* but again it's only for SSE2 anyways, so who cares?
|
||||
*/
|
||||
#ifdef LTC_GCM_TABLES_SSE2
|
||||
if ((unsigned long)gcm & 15) {
|
||||
gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15)));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
tot_data = ftell(in);
|
||||
if (direction == GCM_DECRYPT) {
|
||||
tot_data -= taglen;
|
||||
}
|
||||
rewind(in);
|
||||
do {
|
||||
x = MIN(tot_data, LTC_FILE_READ_BUFSIZE);
|
||||
x = fread(buf, 1, x, in);
|
||||
tot_data -= x;
|
||||
if ((err = gcm_process(gcm, buf, (unsigned long)x, buf, direction)) != CRYPT_OK) {
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
if(fwrite(buf, 1, x, out) != x) {
|
||||
err = CRYPT_ERROR;
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
} while (x == LTC_FILE_READ_BUFSIZE);
|
||||
|
||||
tag_len = taglen;
|
||||
if ((err = gcm_done(gcm, tag, &tag_len)) != CRYPT_OK) {
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
if (tag_len != taglen) {
|
||||
err = CRYPT_ERROR;
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
|
||||
if (direction == GCM_DECRYPT) {
|
||||
x = fread(buf, 1, taglen, in);
|
||||
if (x != taglen) {
|
||||
err = CRYPT_ERROR;
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
|
||||
if (XMEM_NEQ(buf, tag, taglen) == 0) {
|
||||
*res = 1;
|
||||
}
|
||||
} else {
|
||||
if(fwrite(tag, 1, taglen, out) != taglen) {
|
||||
err = CRYPT_ERROR;
|
||||
goto LBL_CLEANBUF;
|
||||
}
|
||||
*res = 1;
|
||||
}
|
||||
|
||||
LBL_CLEANBUF:
|
||||
zeromem(buf, LTC_FILE_READ_BUFSIZE);
|
||||
zeromem(tag, sizeof(tag));
|
||||
LBL_ERR:
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
#ifndef LTC_GCM_TABLES_SSE2
|
||||
zeromem(orig, sizeof(*gcm));
|
||||
#else
|
||||
zeromem(orig, sizeof(*gcm) + 16);
|
||||
#endif
|
||||
#endif
|
||||
if(*res == 0) {
|
||||
x = ftell(out);
|
||||
rewind(out);
|
||||
while((size_t)ftell(out) < x) {
|
||||
fwrite(buf, 1, LTC_FILE_READ_BUFSIZE, out);
|
||||
}
|
||||
if(ftruncate(fileno(out), 0)) {
|
||||
/* well, what shall we do here... */
|
||||
}
|
||||
}
|
||||
fflush(out);
|
||||
|
||||
XFREE(buf);
|
||||
XFREE(orig);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
@ -147,9 +147,10 @@ USEABLE_DEMOS = ltcrypt sizes constants
|
||||
TEST_DEMOS = small tv_gen
|
||||
|
||||
# Demos that are in one config broken
|
||||
# openssl-enc - can't be build with LTC_EASY
|
||||
# aesgcm - can't be built with LTC_EASY
|
||||
# openssl-enc - can't be built with LTC_EASY
|
||||
# timing - not really broken, but older gcc builds spit warnings
|
||||
BROKEN_DEMOS = openssl-enc timing
|
||||
BROKEN_DEMOS = aesgcm openssl-enc timing
|
||||
|
||||
# Combine demos in groups
|
||||
UNBROKEN_DEMOS = $(TEST_DEMOS) $(USEABLE_DEMOS) $(USEFUL_DEMOS)
|
||||
|
Loading…
Reference in New Issue
Block a user