Skip to content
This repository has been archived by the owner on May 27, 2024. It is now read-only.

Commit

Permalink
Support for all openssl FIPS-approved ciphers
Browse files Browse the repository at this point in the history
  • Loading branch information
pushkarnk committed Aug 30, 2023
1 parent 77d4480 commit f6046c3
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 78 deletions.
9 changes: 4 additions & 5 deletions include/cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ typedef struct cipher_context {
int padding;
} cipher_context;

cipher_context* create_cipher_context(const char *name, const char *padding_name);
cipher_context* create_cipher_context(OSSL_LIB_CTX *libctx, const char *name, const char *padding_name);

void cipher_init(cipher_context * ctx, int mode, unsigned char *key, unsigned char *iv);
void cipher_init(cipher_context * ctx, byte in[], int in_len, unsigned char *key, unsigned char *iv, int iv_len, int mode);

void cipher_update(cipher_context *ctx, byte in[], int in_offset, int in_len,
byte out[], int out_offset, int *out_len);
void cipher_update(cipher_context *ctx, byte out[], int *out_len_ptr, byte in[], int in_len);

void cipher_do_final(cipher_context *ctx, byte *out, int *out_len);
void cipher_do_final(cipher_context *ctx, byte *out, int *out_len_ptr);

void cipher_cleanup(cipher_context *ctx);

Expand Down
2 changes: 1 addition & 1 deletion include/jssl.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <openssl/provider.h>
#include <string.h>

OSSL_PROVIDER* load_openssl_fips_provider(const char*);
OSSL_LIB_CTX* load_openssl_fips_provider(const char*);

#define STR_EQUAL(a, b) (0 == strcmp(a, b))

Expand Down
87 changes: 35 additions & 52 deletions src/cipher.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include "cipher.h"
#include <openssl/err.h>
#include <stdio.h>

#define IS_MODE_CCM(ctx) (STR_EQUAL(strrchr(ctx->name, '-'), "-CCM"))
#define IS_OP_DECRYPT(ctx) (ctx->mode == DECRYPT)

#define MAX_CIPHER_TABLE_SIZE 256
#define TAG_LEN 16

typedef struct name_cipher_map {
const char *name;
Expand Down Expand Up @@ -29,79 +34,57 @@ int get_padding_code(const char *name) {
}
}

static int name_table_ready = 0;

static void add_name_table_entry(const char *name, const EVP_CIPHER *cipher) {
cipher_table[table_size].name = name;
cipher_table[table_size++].cipher = cipher;
}

static void populate_name_table() {
// TODO: handle race conditions
if (name_table_ready) return;

add_name_table_entry("AES-128-CFB128", EVP_aes_128_cfb128());
add_name_table_entry("AES-192-CFB128", EVP_aes_192_cfb128());
add_name_table_entry("AES-256-CFB128", EVP_aes_256_cfb128());

name_table_ready = 1;
}

static const EVP_CIPHER* query_name_table(const char *name) {
for (int i = 0; i < table_size; i++) {
if (STR_EQUAL(cipher_table[i].name, name)) {
return cipher_table[i].cipher;
}
}
return NULL;
}

static const EVP_CIPHER* get_cipherbyname(const char *name) {
const EVP_CIPHER *cipher = EVP_get_cipherbyname(name);
if (!IS_NULL(cipher)) return cipher;
return query_name_table(name);
}

// The caller must ensure name is a valid cipher name
// aes-cbc, aes-128-ebc
cipher_context* create_cipher_context(const char *name, const char *padding_name) {
populate_name_table();
cipher_context* create_cipher_context(OSSL_LIB_CTX *libctx, const char *name, const char *padding_name) {
cipher_context *new_context = (cipher_context*)malloc(sizeof(cipher_context));
EVP_CIPHER_CTX *new_ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(new_ctx);
new_context->name = name;
new_context->context = new_ctx;
new_context->cipher = get_cipherbyname(name);
new_context->cipher = EVP_CIPHER_fetch(libctx, name, NULL);
if (IS_NULL(new_context->cipher) || IS_NULL(new_context->context)) {
return NULL;
}
new_context->padding = get_padding_code(padding_name);
return new_context;
}

void cipher_init(cipher_context * ctx, int mode, unsigned char *key, unsigned char *iv) {
// TODO: assert mode lies in {-1, 0, 1 }
EVP_CipherInit_ex(ctx->context, ctx->cipher, NULL, key, iv, mode);
void cipher_init(cipher_context * ctx, byte in_buf[], int in_len, unsigned char *key, unsigned char *iv, int iv_len, int mode) {
EVP_CipherInit_ex(ctx->context, ctx->cipher, NULL, NULL, NULL, mode);
ctx->mode = mode;
if (IS_MODE_CCM(ctx)) {
EVP_CIPHER_CTX_ctrl(ctx->context, EVP_CTRL_CCM_SET_IVLEN, iv_len, 0);
EVP_CIPHER_CTX_ctrl(ctx->context, EVP_CTRL_CCM_SET_TAG, TAG_LEN, mode == ENCRYPT ? 0 : (in_buf + in_len - TAG_LEN));
}
if (!EVP_CipherInit_ex(ctx->context, NULL, NULL, key, iv, mode)) {
ERR_print_errors_fp(stderr);
}
EVP_CIPHER_CTX_set_padding(ctx->context, ctx->padding);
}

void cipher_update(cipher_context *ctx, byte in_buf[], int in_offset, int in_len,
byte out_buf[], int out_offset, int *out_len) {
// TODO: examine return value
EVP_CipherUpdate(ctx->context, out_buf + out_offset, out_len, in_buf + in_offset, in_len);
}
void cipher_update(cipher_context *ctx, byte out_buf[], int *out_len_ptr, byte in_buf[], int in_len) {
if (IS_MODE_CCM(ctx)) {
EVP_CipherUpdate(ctx->context, NULL, out_len_ptr, NULL, IS_OP_DECRYPT(ctx) ? in_len-TAG_LEN : in_len);
}

void cipher_do_final(cipher_context *ctx, byte *out_buf, int *out_len) {
// TODO: examine return value
EVP_CipherFinal_ex(ctx->context, out_buf, out_len);
if (!EVP_CipherUpdate(ctx->context, out_buf, out_len_ptr, in_buf,
(IS_MODE_CCM(ctx) && IS_OP_DECRYPT(ctx)) ? in_len-TAG_LEN : in_len)) {
ERR_print_errors_fp(stderr);
}
}

void cipher_cleanup(cipher_context *ctx) {
EVP_CIPHER_CTX_cleanup(ctx->context);
void cipher_do_final(cipher_context *ctx, byte *out_buf, int *out_len_ptr) {
if (!EVP_CipherFinal_ex(ctx->context, out_buf, out_len_ptr)) {
ERR_print_errors_fp(stderr);
}

if (ctx->mode == ENCRYPT && IS_MODE_CCM(ctx)) {
*out_len_ptr = TAG_LEN;
EVP_CIPHER_CTX_ctrl(ctx->context, EVP_CTRL_CCM_GET_TAG, TAG_LEN, out_buf);
}
}

void cipher_destroy(cipher_context *ctx) {
// TODO: handle errors
EVP_CIPHER_CTX_cleanup(ctx->context);
EVP_CIPHER_CTX_free(ctx->context);
free(ctx);
}
7 changes: 4 additions & 3 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
#include <openssl/err.h>
#include <stdio.h>

OSSL_PROVIDER* load_openssl_fips_provider(const char* conf_file_path) {
if (!OSSL_LIB_CTX_load_config(NULL, conf_file_path)) {
OSSL_LIB_CTX* load_openssl_fips_provider(const char* conf_file_path) {
OSSL_LIB_CTX *fips_libctx = OSSL_LIB_CTX_new();
if (!OSSL_LIB_CTX_load_config(fips_libctx, conf_file_path)) {
ERR_print_errors_fp(stderr);
}

Expand All @@ -14,5 +15,5 @@ OSSL_PROVIDER* load_openssl_fips_provider(const char* conf_file_path) {
ERR_print_errors_fp(stderr);
}

return fips;
return fips_libctx;
}
37 changes: 20 additions & 17 deletions test/cipher_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@ static int array_equals(byte a1[], int l1, byte a2[], int l2) {
return 1;
}

int test_round_trip(const char *cipher_type, const char *padding_name) {
unsigned char *key = "FEDCBA9876543210";
unsigned char *iv = "1234567887654321";
int test_round_trip(OSSL_LIB_CTX *libctx, const char *cipher_type, const char *padding_name) {
unsigned char key[] = {0x5a, 0x33, 0x98, 0x0e, 0x71, 0xe7, 0xd6, 0x7f, 0xd6, 0xcf, 0x17, 0x14, 0x54, 0xdc, 0x96, 0xe5};
unsigned char iv[] = {0x33, 0xae, 0x68, 0xeb, 0xb8, 0x01, 0x0c, 0x6b, 0x3d, 0xa6, 0xb9, 0xcb, 0x29, 0x3a, 0x4d, 0x34};

byte encrypted_output[1024], decrypted_output[1024];
int enc_out_len = 0, dec_out_len = 0, tmplen = 0;

cipher_context *context = create_cipher_context(cipher_type, padding_name);
cipher_context *context = create_cipher_context(libctx, cipher_type, padding_name);
if (IS_NULL(context)) {
printf("Null context: ");
return 0;
}

cipher_init(context, ENCRYPT, key, iv);
cipher_update(context, input, 0, INPUT_SIZE, encrypted_output, 0, &enc_out_len);
cipher_init(context, input, INPUT_SIZE, key, iv, 16, ENCRYPT);
cipher_update(context, encrypted_output, &enc_out_len, input, INPUT_SIZE);
cipher_do_final(context, encrypted_output + enc_out_len, &tmplen);
enc_out_len += tmplen;

tmplen = 0;
cipher_init(context, DECRYPT, key, iv);
cipher_update(context, encrypted_output, 0, enc_out_len, decrypted_output, 0, &dec_out_len);
cipher_init(context, encrypted_output, enc_out_len, key, iv, 16, DECRYPT);
cipher_update(context, decrypted_output, &dec_out_len, encrypted_output, enc_out_len);
cipher_do_final(context, decrypted_output + dec_out_len, &tmplen);
dec_out_len += tmplen;

Expand All @@ -49,9 +50,11 @@ int test_round_trip(const char *cipher_type, const char *padding_name) {
}

int main(int argc, char ** argv) {
OSSL_LIB_CTX *libctx = load_openssl_fips_provider("/usr/local/ssl/openssl.cnf");
char *cipher_type[] = {
"AES-128-ECB",
"AES-256-ECB",
"AES-192-ECB",
"AES-128-CBC",
"AES-256-CBC",
"AES-128-CFB1",
Expand All @@ -60,9 +63,6 @@ int main(int argc, char ** argv) {
"AES-128-CFB8",
"AES-192-CFB8",
"AES-256-CFB8",
"AES-128-CFB128",
"AES-192-CFB128",
"AES-256-CFB128",
"AES-128-CTR",
"AES-192-CTR",
"AES-256-CTR",
Expand All @@ -71,7 +71,8 @@ int main(int argc, char ** argv) {
"AES-192-CCM",
"AES-128-GCM",
"AES-192-GCM",
"AES-256-GCM"
"AES-256-GCM",
"END"
};

char *padding_type[] = {
Expand All @@ -83,17 +84,19 @@ int main(int argc, char ** argv) {
"ISO7816-4"
};

int n_cipher_types = 19;
int n_padding_types = 6;

for (int i = 0; i < n_cipher_types; i++) {
int idx = 0;
const char *cipher_name = cipher_type[idx++];
while (!STR_EQUAL(cipher_name, "END")) {
for(int j = 0; j < n_padding_types; j++) {
if(!test_round_trip(cipher_type[i], padding_type[j])) {
printf("FAILED: test_round_trip(%s, %s)\n", cipher_type[i], padding_type[j]);
if(!test_round_trip(libctx, cipher_name, padding_type[j])) {
printf("FAILED: test_round_trip(%s, %s)\n", cipher_name, padding_type[j]);
} else {
printf("PASSED: test_round_trip(%s, %s)\n", cipher_type[i], padding_type[j]);
printf("PASSED: test_round_trip(%s, %s)\n", cipher_name, padding_type[j]);
}
}
cipher_name = cipher_type[idx++];
}

return 0;
Expand Down

0 comments on commit f6046c3

Please sign in to comment.