Skip to content

Commit

Permalink
Merge pull request #129 from ozbenh/ossl-helpers
Browse files Browse the repository at this point in the history
Create helpers for openssl AES use
  • Loading branch information
nhorman committed May 21, 2021
2 parents 39660fe + 0f0580f commit fc27e61
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 330 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ man_MANS = rngd.8 rngtest.1
noinst_LIBRARIES = librngd.a

rngd_SOURCES = rngd.h rngd.c rngd_entsource.h rngd_entsource.c \
rngd_linux.h rngd_linux.c util.c
rngd_linux.h rngd_linux.c util.c ossl_helpers.c

if NISTBEACON
rngd_SOURCES += rngd_nistbeacon.c
Expand Down
122 changes: 122 additions & 0 deletions ossl_helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* ossl_helpers.c -- Helper wrappers around openssl functions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*/

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "ossl_helpers.h"

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>

struct ossl_aes_ctx
{
EVP_CIPHER_CTX *c;
const unsigned char *key;
const unsigned char *iv;
};

void ossl_aes_random_key(unsigned char *key, const unsigned char *pepper)
{
static unsigned char default_key[AES_BLOCK] = {
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
}; /* AES data reduction key */
unsigned char stack_junk[AES_BLOCK];
int fd, i;

/* Try getting some randomness from the kernel */
fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
int r = read(fd, key, sizeof key);
close(fd);
}

/* Mix in our default key */
for (i = 0; i < AES_BLOCK && pepper; i++)
key[i] ^= default_key[i];

/* Mix in stack junk */
for (i = 0; i < AES_BLOCK && pepper; i++)
key[i] ^= stack_junk[i];

/* Spice it up if we can */
for (i = 0; i < AES_BLOCK && pepper; i++)
key[i] ^= pepper[i];
}


struct ossl_aes_ctx *ossl_aes_init(const unsigned char *key,
const unsigned char *iv)
{
struct ossl_aes_ctx *ctx;

ctx = malloc(sizeof(*ctx));
if (!ctx)
return NULL;

ctx->c = EVP_CIPHER_CTX_new();
if (!ctx->c) {
free(ctx);
return NULL;
}
ctx->key = key;
ctx->iv = iv;
return ctx;
}

void ossl_aes_exit(struct ossl_aes_ctx *ctx)
{
EVP_CIPHER_CTX_free(ctx->c);
free(ctx);
}

int ossl_aes_encrypt(struct ossl_aes_ctx *ctx,
unsigned char *plaintext, int plaintext_len,
unsigned char *ciphertext)
{
int len, ciphertext_len;

if(1 != EVP_EncryptInit_ex(ctx->c, EVP_aes_128_cbc(), NULL, ctx->key, ctx->iv))
return 0;

/*
* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx->c, ciphertext, &len, plaintext, plaintext_len))
return 0;

ciphertext_len = len;

/*
* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx->c, ciphertext + len, &len))
return 0;
ciphertext_len += len;

return ciphertext_len;
}

58 changes: 58 additions & 0 deletions ossl_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* ossl_helpers.h -- Helper wrappers around openssl functions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*/

#ifndef OSSL_HELPERS__H
#define OSSL_HELPERS__H

#define AES_BLOCK 16

struct ossl_aes_ctx;

extern int ossl_aes_encrypt(struct ossl_aes_ctx *ctx,
unsigned char *plaintext, int plaintext_len,
unsigned char *ciphertext);

extern struct ossl_aes_ctx *ossl_aes_init(const unsigned char *key,
const unsigned char *iv);
extern void ossl_aes_exit(struct ossl_aes_ctx *ctx);
extern void ossl_aes_random_key(unsigned char *key, const unsigned char *pepper);

static inline int ossl_aes_mangle(struct ossl_aes_ctx *ctx, unsigned char *data,
size_t size)
{
int ciphertext_len;

/*
* Buffer for ciphertext. Ensure the buffer is long enough for the
* ciphertext which may be longer than the plaintext, depending on the
* algorithm and mode.
*
* For AES, one extra AES block should be sufficient.
*/
unsigned char ciphertext[size + AES_BLOCK];

/* Encrypt the plaintext */
ciphertext_len = ossl_aes_encrypt(ctx, data, size, ciphertext);
if (!ciphertext_len)
return -1;

memcpy(data, ciphertext, size);
return ciphertext_len;
}

#endif /* OSSL_HELPERS__H */
90 changes: 12 additions & 78 deletions rngd_darn.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,12 @@
#include <string.h>
#include <limits.h>
#include <sys/auxv.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>


#include "rngd.h"
#include "fips.h"
#include "exits.h"
#include "rngd_entsource.h"
#include "ossl_helpers.h"

#define min(x,y) ({ \
typeof(x) _x = (x); \
Expand All @@ -49,18 +46,13 @@ static uint64_t get_darn();
static int refill_rand(struct rng *ent_src, bool allow_reinit);
static size_t copy_avail_rand_to_buf(unsigned char *buf, size_t size, size_t copied);

#define AES_BLOCK 16
#define CHUNK_SIZE AES_BLOCK * 8
#define RDRAND_ROUNDS 512 /* 512:1 data reduction */

static unsigned char key[AES_BLOCK] = {
0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
}; /* AES data reduction key */

#define THRESH_BITS 14

static EVP_CIPHER_CTX *ctx = NULL;
/* ossl AES context */
static struct ossl_aes_ctx *ossl_ctx;
static unsigned char key[AES_BLOCK];
static unsigned char iv_buf[AES_BLOCK];

static unsigned char darn_rand_buf[CHUNK_SIZE];
Expand All @@ -72,15 +64,10 @@ static size_t rand_bytes_served = 0;

static int init_openssl(struct rng *ent_src)
{
unsigned char xkey[AES_BLOCK];
int i;
uint64_t darn_val;
int i;

/*
* Use stack junk to create a key, shuffle it a bit
*/
for (i=0; i< sizeof(key); i++)
key[i] ^= xkey[i];
ossl_aes_random_key(key, NULL);

darn_val = get_darn();
if (darn_val == ULONG_MAX)
Expand All @@ -92,13 +79,11 @@ static int init_openssl(struct rng *ent_src)
return 1;
memcpy(&iv_buf[8], &darn_val, sizeof(uint64_t));

if (ctx != NULL) {
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
}
if(!(ctx = EVP_CIPHER_CTX_new()))
return 1;

if (ossl_ctx != NULL)
ossl_aes_exit(ossl_ctx);
ossl_ctx = ossl_aes_init(key, iv_buf);
if (!ossl_ctx)
return 1;
rand_bytes_served = 0;
if (refill_rand(ent_src, false))
return 1;
Expand All @@ -109,56 +94,6 @@ static int init_openssl(struct rng *ent_src)
return 0;
}

static int osslencrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext)
{
int len;

int ciphertext_len;

if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
return 0;
/*
* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
return 0;

ciphertext_len = len;

/*
* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
return 0;
ciphertext_len += len;

return ciphertext_len;
}

static inline int openssl_mangle(unsigned char *tmp, size_t size, struct rng *ent_src)
{
int ciphertext_len;

/*
* Buffer for ciphertext. Ensure the buffer is long enough for the
* ciphertext which may be longer than the plaintext, depending on the
* algorithm and mode.
*/
unsigned char ciphertext[CHUNK_SIZE * RDRAND_ROUNDS];

/* Encrypt the plaintext */
ciphertext_len = osslencrypt (tmp, size, key, iv_buf,
ciphertext);
if (!ciphertext_len)
return -1;

memcpy(tmp, ciphertext, size);
return 0;
}

static int refill_rand(struct rng *ent_src, bool allow_reinit)
{
int i;
Expand All @@ -172,9 +107,8 @@ static int refill_rand(struct rng *ent_src, bool allow_reinit)
return 1;
}

if (openssl_mangle(darn_rand_buf, CHUNK_SIZE, ent_src)) {
if (ossl_aes_mangle(ossl_ctx, darn_rand_buf, CHUNK_SIZE) < 0)
return 1;
}
} else {
uint64_t *ptr = (uint64_t *)darn_rand_buf;
for (i = 0; i < CHUNK_SIZE/sizeof(uint64_t); i++) {
Expand Down
Loading

0 comments on commit fc27e61

Please sign in to comment.