Marty Lamb wrote:
Luc Perthuis wrote:
Hello,
Any advice on this ECB like behaviour of CTR will be highly appreciated.
We are currently integrating openssl in our application.
One of the goals is to use symetric encription on streams of data to
keep them encrypted on a storage device (1).
As far as we are concerned, CTR mode seems to be a good choice for
this goal.
The idea is to use (according to some parameters) either des, 3des,
aes, blowfish or cast5.
Another parameter also permits to chose one hash algorithm.
As openssl does not support CTR mode, it is derived from OFB (as in
EVP_get_cipherbyname(SN_aes_192_ofb128) for instance).
How are you deriving CTR from OFB?
Well, i imagine the issue is somewhere around there.
Unfortunately, i can't figure out where.
When i launch './crypt -phrase AES-192-OFB -in small.txt -out
small.ssl', i get for exemple:
97 occurrences of "43 f9 e5 0e cc b2" and 98 of "37 8d 91 7a b8 c6"
You can try it as same pass phrase should give same output.
'crypt' being compiled from sample code joint here
small.txt being a 150 line text file (see construction at end of mail),
Note that decryption is same process as encryption, 'cause we use CTR
(or OFB), and it works fine.
But those redundancies look like saying "Hey, guy, it's not as secure as
you hope it should be".
You may want to take a look at void AES_ctr128_encrypt() in
crypto/aes/aes_ctr.c (at least, that's where it is in my 0.9.7j-dev
source). I've used it to both encrypt and decrypt successfully. On
our hardware, OpenSSL's CTR performance is *excellent* compared with
other AES modes. Start with num=0 and a bzero'ed ecount_buf and you
should be good to go.
Indeed, in the past it was something like that, apart that we did not
use openssl at all ...
Sorry, i've been quite long extracting this sample from our real code ...
-- source file description --
alternating 10 lines of 5 and 10 lines of A ...
$ grep -c
555555555555555555555555555555555555555555555555555555555555555555555555
small.txt
80
$ grep -c
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
small.txt
70
$ wc 5a.txt
160000 160000 11680000 5a.txt
--
alea+
Luc
/* extracted sample for FED (File Encrypt Decrypt) */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#define FILE_NAME_MAX_SIZE 256
#define BUFF_MAX_SIZE 1024
#define MAXBLOCKSIZE 128
#define SESSION_IV_BLOCK_SIZE 5
#define SESSION_IV_INNER_SIZE 2
#define CONST64(n) n ## ULL
enum FED_State_enum {
FED_State_Not_Set = 0,
FED_State_Init,
FED_State_In_Use,
FED_State_Closed,
};
typedef enum FED_State_enum FED_State_enum;
typedef struct {
unsigned char ctr_iv [MAXBLOCKSIZE]; /* the IV */
unsigned long long block_number; /* current block number (0..2^36) */
} FED_crypto;
struct FED_Context {
FED_State_enum FED_State; /* Current state flag */
unsigned current_session_no;
unsigned session_set;
const char *context_password;
FED_crypto crypto;
EVP_CIPHER_CTX *ossl_cipher_ctx;
};
typedef struct FED_Context FED_Context;
/* OpenSSL Random initialization: some seeding */
static int sec_rand_init (void)
{
char buffer [200];
const char *file = NULL;
const char rng_seed [] =
"=0+The |1*quick/ ^2!brown \"3(fOx #4)jUmps, '5[ovER ~6}tHe _7]lazy? @8{dOg
\\9%`$<->";
#ifdef __WIN32__
RAND_screen ();
#endif
file = RAND_file_name (buffer, sizeof (buffer));
if (file == NULL || !RAND_load_file (file, -1)) {
if (RAND_status () == 0) {
RAND_seed (rng_seed, sizeof (rng_seed) - 1);
if (RAND_status () == 0) {
return -1;
}
return 0;
}
}
return 0;
}
/* Tina Security module initalization:
* - OpenSSL crypto locking initialization
* - OpenSSL initalization
*/
static int sec_ossl_lib_init (void)
{
int rc = 0;
/* OpenSSL classic init */
OpenSSL_add_all_algorithms ();
OpenSSL_add_ssl_algorithms ();
ERR_load_crypto_strings ();
SSL_load_error_strings ();
/* OpenSSL random init */
rc = sec_rand_init ();
return rc;
}
/* Tina Security module cleanup:
* - OpenSSL crypto locking cleanup
* - OpenSSL cleanup
*/
static int sec_ossl_lib_cleanup (void)
{
int rc = 0;
/* OpenSSL classic cleanup */
EVP_cleanup ();
/* ENGINE_cleanup (); */
CRYPTO_cleanup_all_ex_data ();
ERR_remove_state (0);
ERR_free_strings ();
/* OpenSSL random cleanup */
RAND_cleanup ();
return rc;
}
/* EVP_CipherInit (): initialmize an EVP_CIPHER in OFB mode as CTR one could be
* obtained with it */
static int ossl_EVP_CipherInit_ctr (EVP_CIPHER_CTX *ctx, const char *name,
const unsigned char *key, int key_len,
const unsigned char *iv, int iv_len)
{
int rc = 0;
const EVP_CIPHER *evp_ciph = NULL;
int blk_len = 0;
int half_blk_len = 0;
unsigned char ctr_iv [EVP_MAX_IV_LENGTH];
/* algorithm name switch (this should be key length dependant as
* STS as some speicif naming convention) */
if (!name) {
printf ("Invalid input parameter name: %p\n", name);
rc = -1;
goto err;
}
printf ("Initalizing EVP_Cipher in CTR mode for " \
"algorithm: %s, Key length: %d, IV length; %d\n",
name, key_len, iv_len);
evp_ciph = (EVP_CIPHER *) EVP_get_cipherbyname (SN_aes_192_ofb128);
if (!evp_ciph) {
printf ("Unable to retrieve %s " \
"Symmetric algorithm for OpenSSL (%s) " \
"EVP_CIPHERING\n", name, SN_aes_192_ofb128);
rc = -1;
goto err;
}
EVP_CIPHER_CTX_init (ctx);
/* adjust IV for CTR mode:
* NB: - sounds like an error is in STS implementation as
* counter are half IV long
* - iv_len parameter should be the same as EVP_CIPHER_iv_length ()
*/
blk_len = EVP_CIPHER_iv_length (evp_ciph);
/* blk_len = EVP_CIPHER_block_size (evp_ciph); */
half_blk_len = blk_len / 2;
/*ossl_iv_len = EVP_CIPHER_CTX_iv_length (ctx); */
/* zeroes CTR iv half size */
memset (ctr_iv, 0, half_blk_len);
ctr_iv [2] = 0x01;
/* copy the usefull part of the IV */
memcpy ((ctr_iv + half_blk_len - 1),
(iv + half_blk_len - 1), half_blk_len + 1);
rc = EVP_CipherInit (ctx, (const EVP_CIPHER *) evp_ciph, key, iv, 1);
if (rc != 1) {
printf ("Unable to Init Sym Cipher %s: %d\n", name, rc);
goto err;
}
EVP_CIPHER_CTX_set_padding (ctx, 0);
err:
return rc;
}
#define ROUNDUP_BLK(blk_len, len) \
(((len) & (blk_len - 1)) ? ((len) & blk_len) + blk_len : (len))
/* EVP_Cipher (): do it CipherUpdate () and CipherFinal () in OFB mode
* as CTR one could be obtained with it
*
* NB: STS has broken the classic scheme: init, Update, Final */
static int ossl_EVP_Cipher_ctr (EVP_CIPHER_CTX *ctx,
const unsigned char *in, int in_len,
unsigned char *out, int *out_len)
{
int rc = 0;
unsigned char *buff = NULL;
int buff_len = 0;
int nb_blks = 0;
unsigned char ctr_iv [EVP_MAX_IV_LENGTH];
int blk_len = 0;
int half_blk_len = 0;
int iv_len = 0;
int i = 0;
int j = 0;
blk_len = EVP_CIPHER_CTX_key_length (ctx);
half_blk_len = blk_len / 2;
nb_blks = ROUNDUP_BLK (blk_len, in_len) / blk_len - 1;
iv_len = EVP_CIPHER_CTX_iv_length (ctx);
/* zeroes CTR iv */
memset (ctr_iv, 0, iv_len);
buff = out;
/* DONS: Quick fix for EVp_CIPHER_CTX "num" value
* Aim is to validate that */
ctx->num = 0;
/* first IV is OK (set in the upper application level) */
for (i = 0; i <= nb_blks; i++) {
memcpy (ctr_iv, ctx->iv, iv_len);
if (i == nb_blks) {
if (in_len > (i * blk_len)) {
rc = EVP_CipherUpdate (ctx, buff, &buff_len,
(const unsigned char *) (in + i * blk_len),
(in_len - (i * blk_len)));
}
else
break;
}
else {
rc = EVP_CipherUpdate (ctx, buff, &buff_len,
(const unsigned char *) (in + i * blk_len),
blk_len);
}
if (rc <= 0) {
printf ("Unable to Sym CipherUpdate " \
"on block nb %d: %d\n", (i + 1), rc);
return rc;
}
/* adjust buff pointer */
buff += buff_len;
buff_len = 0;
/* no overflow checks */
for (j = 0; j < half_blk_len; j++) {
if (ctr_iv [j] == 0xff) {
ctr_iv [j] = 0x00;
continue;
}
ctr_iv [j] += 1;
break;
}
memcpy (ctx->iv, ctr_iv, iv_len);
}
rc = EVP_CipherFinal (ctx, (unsigned char *) buff, &buff_len);
if (rc <= 0) {
printf ("Unable to Sym CipherFinal: %d\n", rc);
return rc;
}
/* set output length */
*out_len = (buff + buff_len - out);
return rc;
}
/* FED Context setup
*
* Ststus: UPDATED
*/
static int fed_set_ctx (void **context, const char *phrase)
{
int rc = 0;
FED_Context *ctx;
/* OpenSSL specific */
int len = 0;
EVP_CIPHER_CTX *evp_cipher_ctx = NULL;
/* input parameters validity check */
if (context == NULL) {
printf ("Invalid input argument: %s: %p\n",
"context", context);
return -1;
}
ctx = *context;
/* allocate memory for FED context */
if (ctx == NULL) {
len = sizeof (FED_Context);
ctx = malloc (len);
if (ctx == NULL) {
rc = errno;
printf ("Memory allocation failure: " \
"Unable to allocate %d bytes of memory "\
"for FED internal FED_Context: %p\n",
len, ctx);
printf ("errno: %d, %s\n", rc, strerror (rc));
goto mem_error;
}
memset (ctx, 0, len);
}
ctx->session_set = 0;
++(ctx->current_session_no);
ctx->context_password = phrase;
/* alloc memory for internal EVP_CIPHER_CTX struct if not already done */
if (ctx->ossl_cipher_ctx == NULL) {
len = sizeof (EVP_CIPHER_CTX);
evp_cipher_ctx = malloc (len);
if (!evp_cipher_ctx) {
rc = errno;
printf ("Memory allocation failure: " \
"Unable to allocate %d bytes of memory " \
"for FED internal EVP_CIPHER_CTX: %p\n",
len, evp_cipher_ctx);
printf ("errno: %d, %s\n", rc, strerror (rc));
goto mem_error;
}
/* set new context */
ctx->ossl_cipher_ctx = (EVP_CIPHER_CTX *) evp_cipher_ctx;
}
else {
/* cleanup the existing EVP_CIPHER_CTX context */
rc = EVP_CIPHER_CTX_cleanup (ctx->ossl_cipher_ctx);
if (rc != 1) {
printf ("Unable to cleanup the " \
"EVP_CIPHER_CTX context: %d\n", rc);
rc = -1;
goto mem_error;
}
}
/* the following fct call is just a memory zeroing */
EVP_CIPHER_CTX_init (ctx->ossl_cipher_ctx);
/* set output context */
*context = ctx;
return 0;
mem_error:
if (ctx)
free (ctx);
if (evp_cipher_ctx)
free (evp_cipher_ctx);
*context = NULL;
param_error:
return rc;
}
/* FED Context close
*
* Ststus: UPDATED
*/
static int fed_close_ctx (void *context)
{
int rc = 0;
FED_Context *ctx = NULL;
/* parameter check */
if (context == NULL) {
printf ("Invalid Parameter: %p\n", ctx);
return -1;
}
ctx = context;
ctx->FED_State = FED_State_Closed;
return rc;
}
/* FED Context cleanup
*
* Ststus: UPDATED
*/
static int fed_free_ctx (void *ctx)
{
int rc = 0;
FED_Context *context;
/* parameter check */
if (ctx == NULL) {
printf ("Invalid Parameter: %p\n", ctx);
return -1;
}
context = ctx;
/* free the newly OpenSSL EVP_CIPHER_CTX
*/
rc = EVP_CIPHER_CTX_cleanup (context->ossl_cipher_ctx);
if (rc != 1) {
printf ("Unable to cleanup the EVP_CIPHER_CTX " \
"context: %d\n", rc);
}
else rc = 0;
/* free allocated memory */
free (context->ossl_cipher_ctx);
context->ossl_cipher_ctx = NULL;
memset (context, 0, sizeof (*context));
free (context);
return rc;
}
/* Initialisation of context
*/
static int fed_init (FED_Context *ctx)
{
unsigned char encBuf [1024],
sessionkey [MAXBLOCKSIZE],
sessioniv [MAXBLOCKSIZE],
lowgcc [8];
unsigned long encLen, outlen, cert_count;
/* OpenSSL */
EVP_PKEY *pkey = NULL;
RSA *rsa_pubkey = NULL;
/* unsigned char *c_ptr = NULL;
int c_ptr_len = 0; */
int rc = 0;
const char salt [] = "-HlFguARn;a(DN0qreD4TFZg8Il;}Tm&ND_y6gI4WzJ#iylW";
EVP_CIPHER_CTX *evp_ciph_ctx = NULL;
const EVP_CIPHER *evp_ciph = NULL;
const EVP_MD *evp_md = NULL;
unsigned char *ptext = NULL;
int ptext_len = 0;
int tmp_len = 0;
int i = 0;
X509 *x509_crt = NULL;
int x509_sk_size = 0;
unsigned char keyid [EVP_MAX_MD_SIZE];
int len = 0;
/* parameters check */
if (!ctx) {
printf ("Invalid input argument: %s: %p\n",
"context", ctx);
return -1;
}
evp_ciph_ctx = (EVP_CIPHER_CTX *) ctx->ossl_cipher_ctx;
evp_ciph = EVP_get_cipherbyname (SN_aes_192_ofb128);
if (evp_ciph == NULL) {
printf ("Unable to get %s cipher\n", SN_aes_192_ofb128);
rc = -1;
return rc;
}
evp_md = EVP_get_digestbyname(SN_sha384);
if (evp_md == NULL) {
printf ("Unable to get %s digest\n", SN_sha384);
rc = -1;
return rc;
}
/* use a EVP_BytesToKey function for key generation
*/
tmp_len = EVP_BytesToKey(evp_ciph, evp_md, salt,
ctx->context_password, strlen(ctx->context_password),
1023, sessionkey, sessioniv);
if (EVP_CIPHER_key_length(evp_ciph) != tmp_len) {
printf ("Unable to generate session key from passphrase\n");
printf ("%d!=%d\n", tmp_len, EVP_CIPHER_key_length(evp_ciph));
rc = -1;
return rc;
}
/* copy IV and HMAC KEY out */
memcpy (ctx->crypto.ctr_iv, sessioniv, EVP_CIPHER_iv_length(evp_ciph));
/* get space for counters */
tmp_len = SESSION_IV_BLOCK_SIZE + SESSION_IV_INNER_SIZE;
for (i = 0; i < tmp_len; i++) {
ctx->crypto.ctr_iv[i] = 0;
}
printf ("Before real EVP_CipherInit_ctr() function call\n");
printf ("Key size: %d bytes\n", EVP_CIPHER_key_length(evp_ciph));
printf ("IV size: %d bytes\n", EVP_CIPHER_iv_length(evp_ciph));
/* ok get the Symmetric Ciphering context from the STS FED context */
rc = ossl_EVP_CipherInit_ctr (evp_ciph_ctx, SN_aes_192_ofb128,
sessionkey,
EVP_CIPHER_key_length(evp_ciph),
(const unsigned char *) ctx->crypto.ctr_iv,
EVP_CIPHER_iv_length(evp_ciph));
if (rc != 1) {
printf ("Unable to Initialize the EVP_CIPHER_CTX " \
"and the EVP_CIPHER for alg %s: %d\n",
SN_aes_192_ofb128, rc);
rc = -1;
return rc;
}
/* everything seems ok ! */
ctx->FED_State = FED_State_In_Use;
rc = 0;
return rc;
}/* !fed_init */
/* FED DoIt Encrypt/Decrypt
*/
static int fed_cipher_ctx (const void *context,
const unsigned char *in, int in_len,
unsigned char *out, int *out_len)
{
int rc = 0;
FED_Context *ctx;
unsigned char *in_data = NULL;
unsigned char *out_data = NULL;
unsigned char tmpiv [MAXBLOCKSIZE];
unsigned long offset, hmacLen;
/* OpenSSL variables */
EVP_CIPHER_CTX *evp_ciph_ctx = NULL;
int output_len = 0;
unsigned char *c_ptr = NULL;
int i = 0;
/* parameters check */
if (!context) {
printf ("Invalid input argument: %s: %p\n",
"context", context);
return -1;
}
/* re-cast voids to structures, initialize */
ctx = (FED_Context *) context;
evp_ciph_ctx = (EVP_CIPHER_CTX *) ctx->ossl_cipher_ctx;
in_data = (unsigned char *) in;
out_data = (unsigned char *) out;
/* *out_len = 0; */
offset = 0;
/* TOM: do we have a valid context? */
if (ctx->session_set == 0) {
/* FED_Init (context, 0, &rc); */
rc = fed_init (ctx);
if (rc != 0) {
printf ("Unable to initialize " \
"FED Context for Encrytion: %d\n", rc);
return rc;
}
ctx->session_set = 1;
}
/* check if this packet is too large */
if ((unsigned long) in_len > (EVP_CIPHER_CTX_block_size(evp_ciph_ctx) *
(1UL << (8 * SESSION_IV_INNER_SIZE)))) {
printf ("Input buffer is too large: " \
"in_len: %d, packet len: %lu\n", in_len,
(EVP_CIPHER_CTX_block_size(evp_ciph_ctx) *
(1UL << (8 * SESSION_IV_INNER_SIZE))));
return -1;
}
/* enough space? TOM: add in fed header size + meta in the future */
if (*out_len < (long) (in_len)) {
/* overflow */
printf ("Output buffer is too small: *out_len: %d, packet len: %d\n",
*out_len, in_len);
return -1;
}
/* increment counter and form new IV */
++(ctx->crypto.block_number);
/* Sanity check */
if (ctx->crypto.block_number > (CONST64(1) <<
(8 * SESSION_IV_BLOCK_SIZE))) {
printf ("Too many block number for CTR Ciphering\n");
return -1; /* // too many blocks */
}
/* copy the IV */
memcpy (tmpiv, evp_ciph_ctx->iv, EVP_CIPHER_CTX_iv_length(evp_ciph_ctx));
for (i = 0; i < (SESSION_IV_BLOCK_SIZE); i++) {
tmpiv[SESSION_IV_INNER_SIZE + i] =
(ctx->crypto.block_number >> (8 * i)) & 255;
}
/* encrypt and store */
output_len = in_len;
/* set IV */
memcpy (evp_ciph_ctx->iv, tmpiv, EVP_CIPHER_CTX_iv_length(evp_ciph_ctx));
/* DONS: moreover zeroes the Cipher IV matching CTR */
evp_ciph_ctx->iv [0] = 0x00;
evp_ciph_ctx->iv [1] = 0x00;
rc = ossl_EVP_Cipher_ctr (evp_ciph_ctx, in_data, (int) in_len,
(out_data + offset), &output_len);
if (rc != 1) {
printf ("Unable to walk through Cipher Step: " \
"%d\n", rc);
rc = -1;
return rc;
}
/* dump_buffer_hex ("CTR Cipher Output Data", out_data + offset,
output_len); */
offset += in_len;
/* all is well */
*out_len = offset;
rc = 0;
return rc;
}
/* FED encryption scheme using:
* - key derived from passphrase
* - plaintext data contained in ptext_filename
* - ctext_filename as output ciphertext data
*
* NB: - encryption is done with Public Key
* - if ctext_filename is invalid dump data on standard output
*/
static int fed_enc (unsigned char *phrase,
unsigned char *ptext_filename, unsigned char
*ctext_filename)
{
int rc = 0;
FILE *file_pt = NULL;
FILE *file_ct = NULL;
int ptext_buff_len = 0;
unsigned char ptext_buff [BUFF_MAX_SIZE];
int ctext_buff_len = 0;
unsigned char ctext_buff [BUFF_MAX_SIZE];
void *fed_ctx = NULL;
int i = 0;
int blk_len = 0;
int tmp_len = 0;
/* parameters check */
if (!phrase || !ptext_filename || !ctext_filename) {
fprintf (stderr, "ERROR: Invalid input parameter: " \
"ptext_filename: %s, ctext_filename: %s",
(phrase ? (char *) phrase : "NULL"),
(ptext_filename ? (char *) ptext_filename : "NULL"),
(ctext_filename ? (char *) ctext_filename : "NULL"));
goto end;
}
/* do it */
rc = fed_set_ctx ((void **) &fed_ctx, phrase);
if (rc != 0) {
fprintf (stderr, "ERROR: Unable to setup a " \
"FED Context: %d\n", rc);
ERR_print_errors_fp (stderr);
rc = -1;
goto end;
}
memset (ctext_buff, 0, BUFF_MAX_SIZE);
file_pt = fopen (ptext_filename, "rb");
if (!file_pt) {
rc = errno;
fprintf (stderr, "ERROR: Unable to; open the file: %s\n", ptext_filename);
fprintf (stderr, "ERROR: errno: %d, %s\n", rc, strerror (rc));
goto end;
}
file_ct = fopen (ctext_filename, "wb");
if (!file_ct) {
rc = errno;
fprintf (stderr, "ERROR: Unable to; open the file: %s\n", ctext_filename);
fprintf (stderr, "ERROR: errno: %d, %s\n", rc, strerror (rc));
goto end;
}
ctext_buff_len = 0;
tmp_len = 0;
do {
blk_len = tmp_len = fread(ptext_buff, 1, BUFF_MAX_SIZE, file_pt);
if (!blk_len) break;
rc = fed_cipher_ctx (fed_ctx,
ptext_buff, blk_len,
ctext_buff,
(int *) &tmp_len);
if (rc != 0) {
printf ("ERROR: Unable to fed_cipher_ctx data: %d\n", rc);
ERR_print_errors_fp (stderr);
rc = -1;
goto end;
}
if (!fwrite (ctext_buff, 1, tmp_len, file_ct)) break;
} while (BUFF_MAX_SIZE == blk_len);
/* cleanup */
rc = fed_free_ctx ((void *) fed_ctx);
if (rc != 0) {
fprintf (stderr, "ERROR: Unable to cleanup a FED Context: %d\n", rc);
ERR_print_errors_fp (stderr);
rc = -1;
goto end;
}
fprintf (stdout, "INFO: Everything is ok\n");
end:
return rc;
}
/* Usage function:
* - online help
*/
static void usage (char * fct)
{
fprintf (stdout, "Usage: %s args\n\n", fct);
fprintf (stdout, "Do an Encryption operation\n");
fprintf (stdout, "\t-phrase - pass phrase to derive key from\n");
fprintf (stdout, "\t-in - Input file to use\n");
fprintf (stdout, "\t-out - Output file to use\n");
fprintf (stdout, "\n");
}
/* Function to display a buffer */
static void hexdump_buff (char *str, unsigned char *buff, int len)
{
int i = 0;
printf ("Buffer %s (length = %i):\n\t", str, len);
for (i = 0; i < len; i++) {
if (((i % 16) == 0) && (i != 0))
printf ("\n\t");
printf (":%02x ", buff [i]);
}
printf ("\n");
}
/* MAIN programs
*/
int main (int argc, char **argv)
{
int rc = 0;
char *fct = argv [0];
int bad_opt = 0;
unsigned char md_name [] = SN_sha384;
int phrase = 0;
unsigned char phrase_data [FILE_NAME_MAX_SIZE];
unsigned char input_filename [FILE_NAME_MAX_SIZE];
int in = 0;
unsigned char output_filename [FILE_NAME_MAX_SIZE];
int out = 0;
/* Parse command line arguments */
if (argc <= 2) {
usage (fct);
goto end;
}
argc--;
argv++;
while (argc >= 1) {
if (strncmp (*argv, "-phrase", 7) == 0) {
if (--argc < 1)
break;
argv++;
memset (phrase_data, 0, FILE_NAME_MAX_SIZE);
memcpy (phrase_data, *argv, strlen (*argv));
phrase = 1;
}
else if (strncmp (*argv, "-in", 3) == 0) {
if (--argc < 1)
break;
argv++;
memset (input_filename, 0, FILE_NAME_MAX_SIZE);
memcpy (input_filename, *argv, strlen (*argv));
in = 1;
}
else if (strncmp (*argv, "-out", 4) == 0) {
if (--argc < 1)
break;
argv++;
memset (output_filename, 0, FILE_NAME_MAX_SIZE);
memcpy (output_filename, *argv, strlen (*argv));
out = 1;
}
else {
fprintf (stderr, "ERROR: \'%s\' unknown option %s\n\n",
fct, *argv);
bad_opt = 1;
break;
}
argc--;
argv++;
}
if ((bad_opt == 1) || !phrase || !in || !out) {
usage (fct);
goto end;
}
/* initialize OpenSSL based Security module */
rc = sec_ossl_lib_init ();
rc = fed_enc (phrase_data, input_filename, output_filename);
if (rc != 0) {
fprintf (stderr, "ERROR: Unable encrypt file %s", input_filename);
ERR_print_errors_fp (stderr);
}
/* done: */
/* cleanup OpenSSL based Security module */
rc = sec_ossl_lib_cleanup ();
fprintf (stdout, "INFO: sec_ossl_lib cleaned\n");
end:
return rc;
}