Skip to content

Commit

Permalink
Add a tool to decrypt AES-128-GCM
Browse files Browse the repository at this point in the history
  • Loading branch information
syncsynchalt committed Oct 30, 2018
1 parent 2e1eb2b commit 3283421
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,3 +4,4 @@
/boringssl/include
/server/server
/client/client
/tools/aes_128_gcm_decrypt
4 changes: 2 additions & 2 deletions client/Makefile
@@ -1,8 +1,8 @@
CFLAGS += -I../boringssl/include
CFLAGS += -I../boringssl/include -Wall
LDFLAGS += -L../boringssl -lssl -lcrypto

client: main.c ../boringssl/libssl.a ../boringssl/libcrypto.a
$(CC) $(CFLAGS) -o client main.c -Wall $(LDFLAGS)

clean:
rm -f server
rm -f client
2 changes: 1 addition & 1 deletion server/Makefile
@@ -1,4 +1,4 @@
CFLAGS += -I../boringssl/include
CFLAGS += -I../boringssl/include -Wall
LDFLAGS += -L../boringssl -lssl -lcrypto

client: main.c ../boringssl/libssl.a ../boringssl/libcrypto.a
Expand Down
7 changes: 7 additions & 0 deletions tools/Makefile
@@ -0,0 +1,7 @@
CFLAGS += -I../boringssl/include -Wall
LDFLAGS += -L../boringssl -lssl -lcrypto

all: aes_128_gcm_decrypt

aes_128_gcm_decrypt: aes_128_gcm_decrypt.c ../boringssl/libssl.a ../boringssl/libcrypto.a
$(CC) $(CFLAGS) -o $@ aes_128_gcm_decrypt.c $(LDFLAGS)
115 changes: 115 additions & 0 deletions tools/aes_128_gcm_decrypt.c
@@ -0,0 +1,115 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <stdint.h>

typedef unsigned char uchar;

static void die(const char *msg);
static void read_hex(const char *hex, uchar *out, size_t outmax, size_t *outlen);
static void build_iv(uchar *iv, uint64_t seq);

const int gcm_ivlen = 12;
const int gcm_taglen = 16;
const int aes_keylen = 16; // aes-128

int main(int argc, char **argv)
{
if (argc != 6) {
fprintf(stderr, "Usage: %s hexiv seq hexkey hexaad hextag\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "Reads ciphertext on stdin and prints plaintext on stdout\n");
exit(1);
}

uchar iv[1024], key[1024], aad[1024], tag[1024];
size_t ivlen, keylen, aadlen, taglen;
read_hex(argv[1], iv, sizeof(iv), &ivlen);
read_hex(argv[3], key, sizeof(key), &keylen);
read_hex(argv[4], aad, sizeof(aad), &aadlen);
read_hex(argv[5], tag, sizeof(tag), &taglen);
uint64_t seq = atoi(argv[2]);

if (keylen != aes_keylen)
die("Incorrect key length, expected 16 bytes");
if (ivlen != gcm_ivlen)
die("Incorrect IV length, expected 12 bytes");
if (taglen != gcm_taglen)
die("Incorrect IV length, expected 16 bytes");
build_iv(iv, seq);

EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx)
die("cipher ctx create failed");

if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL))
die("init algorithm failed");

if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, NULL))
die("set ivlen failed");

if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
die("set key/iv failed");

int len = 0;
if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen))
die("set aad failed");

uchar bufin[1024], bufout[1024];
char *out = NULL;
int outlen = 0;
while (!feof(stdin)) {
size_t num = fread(bufin, 1, sizeof(bufin), stdin);
if (!EVP_DecryptUpdate(ctx, bufout, &len, bufin, num))
die("decrypt failed");
out = realloc(out, outlen + len);
memcpy(out + outlen, bufout, len);
outlen += len;
}

if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, taglen, tag))
die("set expected tag failed");

// positive is success
int final = EVP_DecryptFinal_ex(ctx, bufout, &len);
out = realloc(out, outlen + len);
memcpy(out + outlen, bufout, len);
outlen += len;

EVP_CIPHER_CTX_free(ctx);

if (final > 0) {
fwrite(out, 1, outlen, stdout);
free(out);
} else {
free(out);
die("decrypt failed; tag value didn't match");
}
}

static void die(const char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}

static void read_hex(const char *hex, uchar *out, size_t outmax, size_t *outlen)
{
*outlen = 0;
if (strlen(hex) > 2*outmax)
die("read_hex overflow");
for (size_t i = 0; hex[i] && hex[i+1]; i += 2) {
unsigned int value = 0;
if (!sscanf(hex + i, "%02x", &value))
die("sscanf failure");
out[(*outlen)++] = value;
}
}

static void build_iv(uchar *iv, uint64_t seq)
{
for (size_t i = 0; i < 8; i++) {
iv[gcm_ivlen-1-i] ^= ((seq>>(i*8))&0xFF);
}
}

0 comments on commit 3283421

Please sign in to comment.