Make encrypt/decrypt code accept integer key lengths instead of using strlen()

Now that encryptions keys and hmac keys may be acquired from /dev/random with
--key-gen (and base64 encoded), they may contain NULL bytes.  This emphasizes
the need to not leverage code that assumes C-style strings when making use of
key information.
This commit is contained in:
Michael Rash 2012-07-10 21:44:06 -04:00
parent 92e403a242
commit 47e39272ed
12 changed files with 152 additions and 103 deletions

View File

@ -37,7 +37,8 @@
/* prototypes /* prototypes
*/ */
static void get_keys(fko_ctx_t ctx, fko_cli_options_t *options, static void get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
char *key, char *hmac_key, const int crypt_op); char *key, int *key_len, char *hmac_key,
int *hmac_key_len, const int crypt_op);
static void display_ctx(fko_ctx_t ctx); static void display_ctx(fko_ctx_t ctx);
static void errmsg(const char *msg, const int err); static void errmsg(const char *msg, const int err);
static void show_last_command(void); static void show_last_command(void);
@ -59,6 +60,7 @@ main(int argc, char **argv)
char access_buf[MAX_LINE_LEN] = {0}; char access_buf[MAX_LINE_LEN] = {0};
char key[MAX_KEY_LEN+1] = {0}; char key[MAX_KEY_LEN+1] = {0};
char hmac_key[MAX_KEY_LEN+1] = {0}; char hmac_key[MAX_KEY_LEN+1] = {0};
int key_len = 0, hmac_key_len = 0;
fko_cli_options_t options; fko_cli_options_t options;
@ -301,11 +303,12 @@ main(int argc, char **argv)
/* Acquire the necessary encryption/hmac keys /* Acquire the necessary encryption/hmac keys
*/ */
get_keys(ctx, &options, key, hmac_key, CRYPT_OP_ENCRYPT); get_keys(ctx, &options, key, &key_len,
hmac_key, &hmac_key_len, CRYPT_OP_ENCRYPT);
/* Finalize the context data (encrypt and encode the SPA data) /* Finalize the context data (encrypt and encode the SPA data)
*/ */
res = fko_spa_data_final(ctx, key, hmac_key); res = fko_spa_data_final(ctx, key, key_len, hmac_key, hmac_key_len);
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
errmsg("fko_spa_data_final", res); errmsg("fko_spa_data_final", res);
@ -366,7 +369,7 @@ main(int argc, char **argv)
* options, then decode it. * options, then decode it.
*/ */
res = fko_new_with_data(&ctx2, spa_data, NULL, res = fko_new_with_data(&ctx2, spa_data, NULL,
ctx->encryption_mode, hmac_key); 0, ctx->encryption_mode, hmac_key, hmac_key_len);
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
errmsg("fko_new_with_data", res); errmsg("fko_new_with_data", res);
@ -395,12 +398,13 @@ main(int argc, char **argv)
} }
} }
get_keys(ctx2, &options, key, hmac_key, CRYPT_OP_DECRYPT); get_keys(ctx2, &options, key, &key_len,
hmac_key, &hmac_key_len, CRYPT_OP_DECRYPT);
/* Verify HMAC first /* Verify HMAC first
*/ */
if(options.use_hmac) if(options.use_hmac)
res = fko_verify_hmac(ctx2, hmac_key); res = fko_verify_hmac(ctx2, hmac_key, hmac_key_len);
/* Decrypt /* Decrypt
*/ */
@ -409,7 +413,7 @@ main(int argc, char **argv)
/* check fko_verify_hmac() return value */ /* check fko_verify_hmac() return value */
} }
else else
res = fko_decrypt_spa_data(ctx2, key); res = fko_decrypt_spa_data(ctx2, key, key_len);
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
@ -751,7 +755,8 @@ set_message_type(fko_ctx_t ctx, fko_cli_options_t *options)
*/ */
static void static void
get_keys(fko_ctx_t ctx, fko_cli_options_t *options, get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
char *key, char *hmac_key, const int crypt_op) char *key, int *key_len, char *hmac_key,
int *hmac_key_len, const int crypt_op)
{ {
int use_hmac = 0, res = 0; int use_hmac = 0, res = 0;
@ -767,10 +772,14 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
return; return;
if (options->have_key) if (options->have_key)
{
strlcpy(key, options->key, MAX_KEY_LEN+1); strlcpy(key, options->key, MAX_KEY_LEN+1);
*key_len = strlen(key);
}
else if (options->have_base64_key) else if (options->have_base64_key)
{ {
fko_base64_decode(options->key_base64, (unsigned char *) options->key); *key_len = fko_base64_decode(options->key_base64,
(unsigned char *) options->key);
memcpy(key, options->key, RIJNDAEL_MAX_KEYSIZE); memcpy(key, options->key, RIJNDAEL_MAX_KEYSIZE);
} }
else else
@ -781,15 +790,22 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
{ {
strlcpy(key, getpasswd_file(options->get_key_file, strlcpy(key, getpasswd_file(options->get_key_file,
options->spa_server_str), MAX_KEY_LEN+1); options->spa_server_str), MAX_KEY_LEN+1);
*key_len = strlen(key);
} }
else if (options->use_gpg) else if (options->use_gpg)
{ {
if(crypt_op == CRYPT_OP_DECRYPT) if(crypt_op == CRYPT_OP_DECRYPT)
{
strlcpy(key, getpasswd("Enter passphrase for secret key: "), strlcpy(key, getpasswd("Enter passphrase for secret key: "),
MAX_KEY_LEN+1); MAX_KEY_LEN+1);
*key_len = strlen(key);
}
else if(options->gpg_signer_key && strlen(options->gpg_signer_key)) else if(options->gpg_signer_key && strlen(options->gpg_signer_key))
{
strlcpy(key, getpasswd("Enter passphrase for signing: "), strlcpy(key, getpasswd("Enter passphrase for signing: "),
MAX_KEY_LEN+1); MAX_KEY_LEN+1);
*key_len = strlen(key);
}
} }
else else
{ {
@ -802,6 +818,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
else else
strlcpy(key, getpasswd("Enter key: "), strlcpy(key, getpasswd("Enter key: "),
MAX_KEY_LEN+1); MAX_KEY_LEN+1);
*key_len = strlen(key);
} }
} }
@ -809,11 +826,13 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
if (options->have_hmac_key) if (options->have_hmac_key)
{ {
strlcpy(hmac_key, options->hmac_key, MAX_KEY_LEN+1); strlcpy(hmac_key, options->hmac_key, MAX_KEY_LEN+1);
*hmac_key_len = strlen(hmac_key);
use_hmac = 1; use_hmac = 1;
} }
else if (options->have_hmac_base64_key) else if (options->have_hmac_base64_key)
{ {
fko_base64_decode(options->hmac_key_base64, (unsigned char *) options->hmac_key); *hmac_key_len = fko_base64_decode(options->hmac_key_base64,
(unsigned char *) options->hmac_key);
memcpy(hmac_key, options->hmac_key, SHA256_BLOCK_LENGTH); memcpy(hmac_key, options->hmac_key, SHA256_BLOCK_LENGTH);
use_hmac = 1; use_hmac = 1;
} }
@ -830,6 +849,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
{ {
#endif #endif
strlcpy(hmac_key, getpasswd("Enter HMAC key: "), MAX_KEY_LEN+1); strlcpy(hmac_key, getpasswd("Enter HMAC key: "), MAX_KEY_LEN+1);
*hmac_key_len = strlen(hmac_key);
use_hmac = 1; use_hmac = 1;
} }

View File

@ -115,27 +115,27 @@ get_random_data(unsigned char *data, const size_t len)
* the Perl Crypt::CBC module's use of Rijndael. * the Perl Crypt::CBC module's use of Rijndael.
*/ */
static void static void
rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, const unsigned char *data) rij_salt_and_iv(RIJNDAEL_context *ctx, const char *key,
const int key_len, const unsigned char *data)
{ {
char pw_buf[16]; char pw_buf[RIJNDAEL_MIN_KEYSIZE];
unsigned char tmp_buf[64]; /* How big does this need to be? */ unsigned char tmp_buf[64]; /* How big does this need to be? */
unsigned char kiv_buf[48]; /* Key and IV buffer */ unsigned char kiv_buf[48]; /* Key and IV buffer */
unsigned char md5_buf[16]; /* Buffer for computed md5 hash */ unsigned char md5_buf[16]; /* Buffer for computed md5 hash */
size_t kiv_len = 0; size_t kiv_len = 0;
size_t plen = strlen(pass);
/* First make pw 16 bytes (pad with "0" (ascii 0x30)) or truncate. /* First make pw 32 bytes (pad with "0" (ascii 0x30)) or truncate.
* Note: pw_buf was initialized with '0' chars (again, not the value * Note: pw_buf was initialized with '0' chars (again, not the value
* 0, but the digit '0' character). * 0, but the digit '0' character).
*/ */
if(plen < 16) if(key_len < RIJNDAEL_MIN_KEYSIZE)
{ {
memcpy(pw_buf, pass, plen); memcpy(pw_buf, key, key_len);
memset(pw_buf+plen, '0', 16 - plen); memset(pw_buf+key_len, '0', RIJNDAEL_MIN_KEYSIZE - key_len);
} }
else else
strncpy(pw_buf, pass, 16); memcpy(pw_buf, key, RIJNDAEL_MIN_KEYSIZE);
/* If we are decrypting, data will contain the salt. Otherwise, /* If we are decrypting, data will contain the salt. Otherwise,
* for encryption, we generate a random salt. * for encryption, we generate a random salt.
@ -157,7 +157,7 @@ rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, const unsigned char *da
* (again it is the perl Crypt::CBC way, with a touch of * (again it is the perl Crypt::CBC way, with a touch of
* fwknop). * fwknop).
*/ */
memcpy(tmp_buf+16, pw_buf, 16); memcpy(tmp_buf+RIJNDAEL_MIN_KEYSIZE, pw_buf, RIJNDAEL_MIN_KEYSIZE);
memcpy(tmp_buf+32, ctx->salt, 8); memcpy(tmp_buf+32, ctx->salt, 8);
while(kiv_len < sizeof(kiv_buf)) while(kiv_len < sizeof(kiv_buf))
@ -181,8 +181,9 @@ rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, const unsigned char *da
/* Initialization entry point. /* Initialization entry point.
*/ */
static void static void
rijndael_init(RIJNDAEL_context *ctx, const char *pass, rijndael_init(RIJNDAEL_context *ctx, const char *key,
const unsigned char *data, int encryption_mode) const int key_len, const unsigned char *data,
int encryption_mode)
{ {
/* The default (set in fko.h) is ECB mode to be compatible with the /* The default (set in fko.h) is ECB mode to be compatible with the
@ -192,11 +193,11 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass,
/* Generate the salt and initialization vector. /* Generate the salt and initialization vector.
*/ */
rij_salt_and_iv(ctx, pass, data); rij_salt_and_iv(ctx, key, key_len, data);
/* Intialize our rinjdael context. /* Intialize our Rijndael context.
*/ */
rijndael_setup(ctx, 32, ctx->key); rijndael_setup(ctx, RIJNDAEL_MAX_KEYSIZE, ctx->key);
} }
/* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC /* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC
@ -204,13 +205,14 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass,
*/ */
size_t size_t
rij_encrypt(unsigned char *in, size_t in_len, rij_encrypt(unsigned char *in, size_t in_len,
const char *pass, unsigned char *out, int encryption_mode) const char *key, const int key_len,
unsigned char *out, int encryption_mode)
{ {
RIJNDAEL_context ctx; RIJNDAEL_context ctx;
int i, pad_val; int i, pad_val;
unsigned char *ondx = out; unsigned char *ondx = out;
rijndael_init(&ctx, pass, NULL, encryption_mode); rijndael_init(&ctx, key, key_len, NULL, encryption_mode);
/* Prepend the salt to the ciphertext... /* Prepend the salt to the ciphertext...
*/ */
@ -237,14 +239,15 @@ rij_encrypt(unsigned char *in, size_t in_len,
*/ */
size_t size_t
rij_decrypt(unsigned char *in, size_t in_len, rij_decrypt(unsigned char *in, size_t in_len,
const char *pass, unsigned char *out, int encryption_mode) const char *key, const int key_len,
unsigned char *out, int encryption_mode)
{ {
RIJNDAEL_context ctx; RIJNDAEL_context ctx;
int i, pad_val, pad_err = 0; int i, pad_val, pad_err = 0;
unsigned char *pad_s; unsigned char *pad_s;
unsigned char *ondx = out; unsigned char *ondx = out;
rijndael_init(&ctx, pass, in, encryption_mode); rijndael_init(&ctx, key, key_len, in, encryption_mode);
/* Remove the first block since it contains the salt (it was consumed /* Remove the first block since it contains the salt (it was consumed
* by the rijndael_init() function above). * by the rijndael_init() function above).

View File

@ -49,9 +49,11 @@
void get_random_data(unsigned char *data, const size_t len); void get_random_data(unsigned char *data, const size_t len);
size_t rij_encrypt(unsigned char *in, size_t len, size_t rij_encrypt(unsigned char *in, size_t len,
const char *key, unsigned char *out, int encryption_mode); const char *key, const int key_len,
unsigned char *out, int encryption_mode);
size_t rij_decrypt(unsigned char *in, size_t len, size_t rij_decrypt(unsigned char *in, size_t len,
const char *key, unsigned char *out, int encryption_mode); const char *key, const int key_len,
unsigned char *out, int encryption_mode);
#endif /* CIPHER_FUNCS_H */ #endif /* CIPHER_FUNCS_H */

View File

@ -222,10 +222,11 @@ enum {
*/ */
DLL_API int fko_new(fko_ctx_t *ctx); DLL_API int fko_new(fko_ctx_t *ctx);
DLL_API int fko_new_with_data(fko_ctx_t *ctx, const char *enc_msg, DLL_API int fko_new_with_data(fko_ctx_t *ctx, const char *enc_msg,
const char *dec_key, int encryption_mode, const char *hmac_key); const char *dec_key, const int dec_key_len, int encryption_mode,
const char *hmac_key, const int hmac_key_len);
DLL_API void fko_destroy(fko_ctx_t ctx); DLL_API void fko_destroy(fko_ctx_t ctx);
DLL_API int fko_spa_data_final(fko_ctx_t ctx, const char *enc_key, DLL_API int fko_spa_data_final(fko_ctx_t ctx, const char *enc_key,
const char *hmac_key); const int enc_key_len, const char *hmac_key, const int hmac_key_len);
/* Set context data functions /* Set context data functions
@ -255,10 +256,14 @@ DLL_API int fko_base64_decode(const char *in, unsigned char *out);
DLL_API int fko_encode_spa_data(fko_ctx_t ctx); DLL_API int fko_encode_spa_data(fko_ctx_t ctx);
DLL_API int fko_decode_spa_data(fko_ctx_t ctx); DLL_API int fko_decode_spa_data(fko_ctx_t ctx);
DLL_API int fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key); DLL_API int fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key,
DLL_API int fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key); const int enc_key_len);
DLL_API int fko_verify_hmac(fko_ctx_t ctx, const char *hmac_key); DLL_API int fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key,
DLL_API int fko_calculate_hmac(fko_ctx_t ctx, const char *hmac_key); const int dec_key_len);
DLL_API int fko_verify_hmac(fko_ctx_t ctx, const char *hmac_key,
const int hmac_key_len);
DLL_API int fko_calculate_hmac(fko_ctx_t ctx, const char *hmac_key,
const int hmac_key_len);
DLL_API int fko_get_hmac_data(fko_ctx_t ctx, char **enc_data); DLL_API int fko_get_hmac_data(fko_ctx_t ctx, char **enc_data);
DLL_API int fko_get_encoded_data(fko_ctx_t ctx, char **enc_data); DLL_API int fko_get_encoded_data(fko_ctx_t ctx, char **enc_data);
@ -295,18 +300,24 @@ DLL_API int fko_get_gpg_home_dir(fko_ctx_t ctx, char **gpg_home_dir);
DLL_API const char* fko_gpg_errstr(fko_ctx_t ctx); DLL_API const char* fko_gpg_errstr(fko_ctx_t ctx);
DLL_API int fko_set_gpg_signature_verify(fko_ctx_t ctx, const unsigned char val); DLL_API int fko_set_gpg_signature_verify(fko_ctx_t ctx,
DLL_API int fko_get_gpg_signature_verify(fko_ctx_t ctx, unsigned char *val); const unsigned char val);
DLL_API int fko_set_gpg_ignore_verify_error(fko_ctx_t ctx, const unsigned char val); DLL_API int fko_get_gpg_signature_verify(fko_ctx_t ctx,
DLL_API int fko_get_gpg_ignore_verify_error(fko_ctx_t ctx, unsigned char *val); unsigned char *val);
DLL_API int fko_set_gpg_ignore_verify_error(fko_ctx_t ctx,
const unsigned char val);
DLL_API int fko_get_gpg_ignore_verify_error(fko_ctx_t ctx,
unsigned char *val);
DLL_API int fko_get_gpg_signature_id(fko_ctx_t ctx, char **sig_id); DLL_API int fko_get_gpg_signature_id(fko_ctx_t ctx, char **sig_id);
DLL_API int fko_get_gpg_signature_fpr(fko_ctx_t ctx, char **sig_fpr); DLL_API int fko_get_gpg_signature_fpr(fko_ctx_t ctx, char **sig_fpr);
DLL_API int fko_get_gpg_signature_summary(fko_ctx_t ctx, int *sigsum); DLL_API int fko_get_gpg_signature_summary(fko_ctx_t ctx, int *sigsum);
DLL_API int fko_get_gpg_signature_status(fko_ctx_t ctx, int *sigstat); DLL_API int fko_get_gpg_signature_status(fko_ctx_t ctx, int *sigstat);
DLL_API int fko_gpg_signature_id_match(fko_ctx_t ctx, const char *id, unsigned char *result); DLL_API int fko_gpg_signature_id_match(fko_ctx_t ctx, const char *id,
DLL_API int fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char *fpr, unsigned char *result); unsigned char *result);
DLL_API int fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char *fpr,
unsigned char *result);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -43,7 +43,7 @@
/* Prep and encrypt using Rijndael /* Prep and encrypt using Rijndael
*/ */
static int static int
_rijndael_encrypt(fko_ctx_t ctx, const char *enc_key) _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key, const int enc_key_len)
{ {
char *plaintext; char *plaintext;
char *b64ciphertext; char *b64ciphertext;
@ -68,8 +68,9 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
cipher_len = rij_encrypt( cipher_len = rij_encrypt(
(unsigned char*)plaintext, strlen(plaintext), (char*)enc_key, ciphertext, (unsigned char*)plaintext, strlen(plaintext),
ctx->encryption_mode (char*)enc_key, enc_key_len,
ciphertext, ctx->encryption_mode
); );
/* Now make a bucket for the base64-encoded version and populate it. /* Now make a bucket for the base64-encoded version and populate it.
@ -98,7 +99,8 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
/* Decode, decrypt, and parse SPA data into the context. /* Decode, decrypt, and parse SPA data into the context.
*/ */
static int static int
_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int encryption_mode) _rijndael_decrypt(fko_ctx_t ctx,
const char *dec_key, const int key_len, int encryption_mode)
{ {
char *tbuf; char *tbuf;
unsigned char *ndx; unsigned char *ndx;
@ -155,7 +157,7 @@ _rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int encryption_mode)
if(ctx->encoded_msg == NULL) if(ctx->encoded_msg == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
pt_len = rij_decrypt(cipher, cipher_len, dec_key, pt_len = rij_decrypt(cipher, cipher_len, dec_key, key_len,
(unsigned char*)ctx->encoded_msg, encryption_mode); (unsigned char*)ctx->encoded_msg, encryption_mode);
/* Done with cipher... /* Done with cipher...
@ -413,7 +415,7 @@ fko_get_spa_encryption_mode(fko_ctx_t ctx, int *enc_mode)
/* Encrypt the encoded SPA data. /* Encrypt the encoded SPA data.
*/ */
int int
fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key) fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key, const int enc_key_len)
{ {
int res = 0; int res = 0;
@ -445,7 +447,7 @@ fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
/* Encrypt according to type and return... /* Encrypt according to type and return...
*/ */
if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL) if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
res = _rijndael_encrypt(ctx, enc_key); res = _rijndael_encrypt(ctx, enc_key, enc_key_len);
else if(ctx->encryption_type == FKO_ENCRYPTION_GPG) else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
#if HAVE_LIBGPGME #if HAVE_LIBGPGME
res = gpg_encrypt(ctx, enc_key); res = gpg_encrypt(ctx, enc_key);
@ -461,7 +463,7 @@ fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
/* Decode, decrypt, and parse SPA data into the context. /* Decode, decrypt, and parse SPA data into the context.
*/ */
int int
fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key) fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key, const int key_len)
{ {
int enc_type, res; int enc_type, res;
@ -484,7 +486,8 @@ fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
else if(enc_type == FKO_ENCRYPTION_RIJNDAEL) else if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
{ {
ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL; ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL;
res = _rijndael_decrypt(ctx, dec_key, ctx->encryption_mode); res = _rijndael_decrypt(ctx,
dec_key, key_len, ctx->encryption_mode);
} }
else else
return(FKO_ERROR_INVALID_DATA); return(FKO_ERROR_INVALID_DATA);

View File

@ -171,7 +171,9 @@ fko_new(fko_ctx_t *r_ctx)
*/ */
int int
fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg, fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg,
const char *dec_key, int encryption_mode, const char *hmac_key) const char *dec_key, const int dec_key_len,
int encryption_mode, const char *hmac_key,
const int hmac_key_len)
{ {
fko_ctx_t ctx; fko_ctx_t ctx;
int res = FKO_SUCCESS; /* Are we optimistic or what? */ int res = FKO_SUCCESS; /* Are we optimistic or what? */
@ -204,7 +206,7 @@ fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg,
*/ */
ctx->initval = FKO_CTX_INITIALIZED; ctx->initval = FKO_CTX_INITIALIZED;
if(hmac_key != NULL) if(hmac_key != NULL)
res = fko_verify_hmac(ctx, hmac_key); res = fko_verify_hmac(ctx, hmac_key, hmac_key_len);
ctx->initval = 0; ctx->initval = 0;
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
@ -221,7 +223,7 @@ fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg,
*/ */
if(dec_key != NULL) if(dec_key != NULL)
{ {
res = fko_decrypt_spa_data(ctx, dec_key); res = fko_decrypt_spa_data(ctx, dec_key, dec_key_len);
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
@ -330,7 +332,7 @@ fko_destroy(fko_ctx_t ctx)
free(ctx); free(ctx);
} }
/* Generate Rijndael and HMAC keys from /dev/random and base-64 /* Generate Rijndael and HMAC keys from /dev/random and base64
* encode them * encode them
*/ */
int int
@ -353,15 +355,13 @@ fko_key_gen(char *key_base64, char *hmac_key_base64)
int int
fko_base64_encode(unsigned char *in, char *out, int in_len) fko_base64_encode(unsigned char *in, char *out, int in_len)
{ {
b64_encode(in, out, in_len); return b64_encode(in, out, in_len);
return(FKO_SUCCESS);
} }
int int
fko_base64_decode(const char *in, unsigned char *out) fko_base64_decode(const char *in, unsigned char *out)
{ {
b64_decode(in, out); return b64_decode(in, out);
return(FKO_SUCCESS);
} }
/* Return the fko version /* Return the fko version
@ -384,7 +384,9 @@ fko_get_version(fko_ctx_t ctx, char **version)
* set. * set.
*/ */
int int
fko_spa_data_final(fko_ctx_t ctx, const char *enc_key, const char *hmac_key) fko_spa_data_final(fko_ctx_t ctx,
const char *enc_key, const int enc_key_len,
const char *hmac_key, const int hmac_key_len)
{ {
char *tbuf; char *tbuf;
int res = 0, data_with_hmac_len = 0; int res = 0, data_with_hmac_len = 0;
@ -394,14 +396,14 @@ fko_spa_data_final(fko_ctx_t ctx, const char *enc_key, const char *hmac_key)
if(!CTX_INITIALIZED(ctx)) if(!CTX_INITIALIZED(ctx))
return(FKO_ERROR_CTX_NOT_INITIALIZED); return(FKO_ERROR_CTX_NOT_INITIALIZED);
res = fko_encrypt_spa_data(ctx, enc_key); res = fko_encrypt_spa_data(ctx, enc_key, enc_key_len);
/* Now calculate hmac if so configured /* Now calculate hmac if so configured
*/ */
if (res == FKO_SUCCESS && if (res == FKO_SUCCESS &&
ctx->hmac_mode != FKO_HMAC_UNKNOWN && hmac_key != NULL) ctx->hmac_mode != FKO_HMAC_UNKNOWN && hmac_key != NULL)
{ {
res = fko_calculate_hmac(ctx, hmac_key); res = fko_calculate_hmac(ctx, hmac_key, hmac_key_len);
if (res == FKO_SUCCESS) if (res == FKO_SUCCESS)
{ {

View File

@ -33,7 +33,8 @@
#include "hmac.h" #include "hmac.h"
#include "base64.h" #include "base64.h"
int fko_verify_hmac(fko_ctx_t ctx, const char *hmac_key) int fko_verify_hmac(fko_ctx_t ctx,
const char *hmac_key, const int hmac_key_len)
{ {
/* Must be initialized /* Must be initialized
*/ */
@ -80,7 +81,8 @@ fko_set_hmac_mode(fko_ctx_t ctx, const short hmac_mode)
return(FKO_SUCCESS); return(FKO_SUCCESS);
} }
int fko_calculate_hmac(fko_ctx_t ctx, const char *hmac_key) int fko_calculate_hmac(fko_ctx_t ctx,
const char *hmac_key, const int hmac_key_len)
{ {
unsigned char hmac[SHA256_DIGEST_STRING_LENGTH] = {0}; unsigned char hmac[SHA256_DIGEST_STRING_LENGTH] = {0};
char *hmac_base64 = NULL; char *hmac_base64 = NULL;
@ -99,7 +101,8 @@ int fko_calculate_hmac(fko_ctx_t ctx, const char *hmac_key)
if (hmac_base64 == NULL) if (hmac_base64 == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
hmac_sha256(ctx->encrypted_msg, strlen(ctx->encrypted_msg), hmac, hmac_key); hmac_sha256(ctx->encrypted_msg,
strlen(ctx->encrypted_msg), hmac, hmac_key);
b64_encode(hmac, hmac_base64, SHA256_DIGEST_LENGTH); b64_encode(hmac, hmac_base64, SHA256_DIGEST_LENGTH);
strip_b64_eq(hmac_base64); strip_b64_eq(hmac_base64);

View File

@ -303,13 +303,13 @@ inv_mix_column(uint32_t *a, uint32_t *b)
} }
void void
rijndael_setup(RIJNDAEL_context *ctx, size_t keysize, const uint8_t *key) rijndael_setup(RIJNDAEL_context *ctx, const size_t keysize, const uint8_t *key)
{ {
int nk, nr, i, lastkey; int nk, nr, i, lastkey;
uint32_t temp, rcon; uint32_t temp, rcon;
/* Truncate keysizes to the valid key sizes provided by Rijndael */ /* Truncate keysizes to the valid key sizes provided by Rijndael */
if (keysize >= 32) { if (keysize >= RIJNDAEL_MAX_KEYSIZE) {
nk = 8; nk = 8;
nr = 14; nr = 14;
} else if (keysize >= 24) { } else if (keysize >= 24) {

View File

@ -63,7 +63,7 @@ typedef struct {
int nrounds; /* number of rounds to use for our key size */ int nrounds; /* number of rounds to use for our key size */
int mode; /* encryption mode */ int mode; /* encryption mode */
/* Added by DSS */ /* Added by DSS */
uint8_t key[32]; uint8_t key[RIJNDAEL_MAX_KEYSIZE];
uint8_t iv[16]; uint8_t iv[16];
uint8_t salt[8]; uint8_t salt[8];
} RIJNDAEL_context; } RIJNDAEL_context;
@ -77,7 +77,8 @@ typedef struct {
* PASS A VALUE LESS THAN 16 TO KEYSIZE! * PASS A VALUE LESS THAN 16 TO KEYSIZE!
*/ */
void void
rijndael_setup(RIJNDAEL_context *ctx, size_t keysize, const uint8_t *key); rijndael_setup(RIJNDAEL_context *ctx,
const size_t keysize, const uint8_t *key);
/* /*
* rijndael_encrypt() * rijndael_encrypt()

View File

@ -49,7 +49,31 @@ add_acc_string(char **var, const char *val)
if((*var = strdup(val)) == NULL) if((*var = strdup(val)) == NULL)
{ {
log_msg(LOG_ERR, log_msg(LOG_ERR,
"Fatal memory allocation error adding access list entry: %s", var "Fatal memory allocation error adding access list entry: %s", *var
);
exit(EXIT_FAILURE);
}
}
/* Decode base64 encoded string into access entry
*/
static void
add_acc_b64_string(char **var, int *len, const char *val)
{
if((*var = strdup(val)) == NULL)
{
log_msg(LOG_ERR,
"Fatal memory allocation error adding access list entry: %s", *var
);
exit(EXIT_FAILURE);
}
memset(*var, 0x0, strlen(val));
*len = fko_base64_decode(val, (unsigned char *) *var);
if (*len < 0)
{
log_msg(LOG_ERR,
"base64 decoding returned error for: %s", *var
); );
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -752,9 +776,8 @@ set_acc_defaults(fko_srv_options_t *opts)
static int static int
acc_data_is_valid(const acc_stanza_t *acc) acc_data_is_valid(const acc_stanza_t *acc)
{ {
if((acc->key == NULL || !strlen(acc->key)) if(acc->key_len < 0 || ((acc->key == NULL && acc->key_base64 == NULL)
&& (acc->key_base64 == NULL || !strlen(acc->key_base64)) && (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw))))
&& (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw)))
{ {
fprintf(stderr, fprintf(stderr,
"[*] No keys found for access stanza source: '%s'\n", acc->source "[*] No keys found for access stanza source: '%s'\n", acc->source
@ -904,6 +927,7 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
} }
add_acc_string(&(curr_acc->key), val); add_acc_string(&(curr_acc->key), val);
curr_acc->key_len = strlen(curr_acc->key);
} }
else if(CONF_VAR_IS(var, "KEY_BASE64")) else if(CONF_VAR_IS(var, "KEY_BASE64"))
{ {
@ -922,6 +946,8 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
} }
add_acc_string(&(curr_acc->key_base64), val); add_acc_string(&(curr_acc->key_base64), val);
add_acc_b64_string(&(curr_acc->key),
&(curr_acc->key_len), curr_acc->key_base64);
} }
else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64")) else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
{ {
@ -940,6 +966,8 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
} }
add_acc_string(&(curr_acc->hmac_key_base64), val); add_acc_string(&(curr_acc->hmac_key_base64), val);
add_acc_b64_string(&(curr_acc->hmac_key),
&curr_acc->hmac_key_len, curr_acc->hmac_key_base64);
} }
else if(CONF_VAR_IS(var, "FW_ACCESS_TIMEOUT")) else if(CONF_VAR_IS(var, "FW_ACCESS_TIMEOUT"))
{ {

View File

@ -267,8 +267,10 @@ typedef struct acc_stanza
char *restrict_ports; char *restrict_ports;
acc_port_list_t *rport_list; acc_port_list_t *rport_list;
char *key; char *key;
int key_len;
char *key_base64; char *key_base64;
char *hmac_key; char *hmac_key;
int hmac_key_len;
char *hmac_key_base64; char *hmac_key_base64;
int fw_access_timeout; int fw_access_timeout;
unsigned char enable_cmd_exec; unsigned char enable_cmd_exec;

View File

@ -241,19 +241,6 @@ incoming_spa(fko_srv_options_t *opts)
if(enc_type == FKO_ENCRYPTION_RIJNDAEL) if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
{ {
if (acc->key_base64 != NULL)
{
if ((acc->key = strdup(acc->key_base64)) == NULL)
{
log_msg(LOG_ERR,
"Fatal memory allocation error copying key_base64 -> key: %s",
acc->key_base64
);
exit(EXIT_FAILURE);
}
memset(acc->key, 0x0, strlen(acc->key_base64));
fko_base64_decode(acc->key_base64, (unsigned char *) acc->key);
}
if (acc->key == NULL) if (acc->key == NULL)
{ {
log_msg(LOG_ERR, log_msg(LOG_ERR,
@ -264,22 +251,9 @@ incoming_spa(fko_srv_options_t *opts)
continue; continue;
} }
if (acc->hmac_key_base64 != NULL)
{
if ((acc->hmac_key = strdup(acc->hmac_key_base64)) == NULL)
{
log_msg(LOG_ERR,
"Fatal memory allocation error copying hmac_key_base64 -> hmac_key: %s",
acc->hmac_key_base64
);
exit(EXIT_FAILURE);
}
memset(acc->hmac_key, 0x0, strlen(acc->hmac_key_base64));
fko_base64_decode(acc->hmac_key_base64, (unsigned char *) acc->hmac_key);
}
res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data,
acc->key, acc->encryption_mode, acc->hmac_key); acc->key, acc->key_len, acc->encryption_mode, acc->hmac_key,
acc->hmac_key_len);
} }
else if(enc_type == FKO_ENCRYPTION_GPG) else if(enc_type == FKO_ENCRYPTION_GPG)
{ {
@ -289,7 +263,7 @@ incoming_spa(fko_srv_options_t *opts)
if(acc->gpg_decrypt_pw != NULL) if(acc->gpg_decrypt_pw != NULL)
{ {
res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL, res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL,
acc->encryption_mode, NULL); 0, acc->encryption_mode, NULL, 0);
if(res != FKO_SUCCESS) if(res != FKO_SUCCESS)
{ {
log_msg(LOG_WARNING, log_msg(LOG_WARNING,
@ -338,7 +312,7 @@ incoming_spa(fko_srv_options_t *opts)
/* Now decrypt the data. /* Now decrypt the data.
*/ */
res = fko_decrypt_spa_data(ctx, acc->gpg_decrypt_pw); res = fko_decrypt_spa_data(ctx, acc->gpg_decrypt_pw, 0);
} }
else else