Building.Open.Source.Network.Security.Tools.Components.And.Techniques [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Building.Open.Source.Network.Security.Tools.Components.And.Techniques [Electronic resources] - نسخه متنی

Mike D. Schiffman

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Sample Code–Roil

The following two source files comprise the Roil codebase. To preserve readability, we richly comment the code but do not include any book-text inside the code. You can download the full source files from this book's companion Web site at http://www.wiley.com/compbooks/schiffman.


roil.h



/*
* $Id: roil.h,v 1.1 2002/04/11 04:42:06 route Exp $
*
* Building Open Source Network Security Tools
* roil.h - openssl example code
*
* Copyright (c) 2002 Mike D. Schiffman <mike@infonexus.com>
* All rights reserved.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "/usr/local/ssl/include/openssl/evp.h"
#define KEY_LENGTH 0x100 /* max passphrase size */
#define IV_LENGTH 0x008 /* IV length */
#define RETRY_THRESHOLD 0x003 /* password retries */
#define BUF_SIZE 0x100 /* 256 byte buffer */
# define ERRBUF_SIZE 0x100 /* 256 byte buffer */
/* magic file header number */
u_char magic[]= {0x0f, 0x01, 0x02, 0x0d, 0xff, 0xee, 0xfl, 0x43};
struct roil_pack
{
int fd_in;
int fd_out;
char fn_in[100];
char fn_out[100];
char passphrase[KEY_LENGTH];
u_char flags;
#define MD 0x01 /* Hash */
#define MD_FROMFILE 0x02 /*Hash from a file */
#define ENCRYPT 0x04 /* Encrypt */
#define DECRYPT 0x08 /* Decrypt */
char md[10];
char ea[10];
char errbuf[ERRBUF_SIZE];
};
struct roil_pack *roil_init(char *, u_char, char *, char *, char *);
int open_outputfile(struct roil_pack *);
void roil_destroy(struct roil_pack *);
void roil(struct roil_pack *);
u_char *roil_digest(struct roil_pack *, int *);
int roil_cipher(struct roil_pack *);
int get_passphrase(char *);
int make_key(struct roil_pack *, u_char *);
void get_iv(u_char *);
void usage(char *);
/* EOF */


roil.c



/*
* $Id: roil.c,v 1.1 2002/04/11 04:42:06 route Exp $
*
* Building Open Source Network Security Tools
* roil.c - openssl example code
*
* Copyright (c) 2002 Mike D. Schiffman <mike@infonexus.com>
* All rights reserved.
*
#include "./roil.h"
int
main(int argc, char **argv)
{
int c;
u_char flags;
char *md;
char *ea;
FILE *filename;
char errbuf[256];
struct roil_pack *rp;
printf("Roil 1.0 [little encryption tool]\n");
flags = 0;
md = NULL;
ea = NULL;
filename = NULL;
while ((c = getopt(argc, argv, "de:hm:")) != EOF)
{
switch (c)
{
case 'd':
flags |= DECRYPT;
break;
case 'e':
ea = optarg;
flags |= ENCRYPT;
break;
case 'h':
usage(argv[0]};
exit(EXIT_SUCCESS);
break;
case 'm':
md = optarg;
flags |= MD;
break;
default:
usage(argv[0]);
exit(EXIT_FAILURE);
}
}
if (flags == 0 || (flags & ENCRYPT && flags & DECRYPT))
{
usage(argvf0]);
exit(EXIT_FAILURE);
}
if (argc - optind !=1)
{
usage(argv[0]);
exit(EXIT_FAILURE);
}
rp= roil_init(argv[optind], flags, md, ea, errbuf);
if (rp==NULL)
{
fprintf(stderr, "roil_init(): %s n" errbuf);
exit(EXIT_FAILURE)
}
roil(rp);
roil_destroy(rp);
return (EXIT_SUCCESS);
}
struct roil_pack *
roil_init(char *filename, u_char flags, char *md, char *ea, char *errbuf)
{
struct roil_pack *rp;
/* grab memory for our monolithic structure */
rp= malloc(sizeof (struct roil_pack));
if (rp==NULL)
{
sprintf(errbuf, strerror(errno));
return (NULL);
}
/* open the input file */
rp->fd_in= open(filename, 0_RDWR);
if (rp->fd_in==-1)
{
sprintf(errbuf, "can't open input file \"%s" %s",
filename, strerror(errno));
roil_destroy(rp);
return (NULL);
}
/* save the filename */
strncpy(rp-> fn_in, filename, sizeof (rp->fn_in) - 1);
rp->flags = flags;
/* copy over the message digest name */
if (md)
{
strncpy (rp->md, md, 10);
}
/* copy over the message digest name */
if (ea)
{
strncpy(rp->ea, ea, 10);
}
return (rp);
}
void
roil_destroy (struct roil_pack *rp
{
if (rp)
{
if (rp->fd_in)
{
close (rp->fd_in);
}
if (rp->fd_out)
{
close (rp->fd_out); }
}
free(rp);
EVP_cleanup();
}
}
int
open_outputfile(struct roil_pack *rp)
{
int n;
n= strlen(rp->fn_in);
strcpy(rp->fn_out, rp->fn_in);
if (rp->flags & ENCRYPT)
{
if (!(n + 4 100))
{
/* filename too long */
sprintf(rp->errbuf, "open_outputfile(): filename too long n");
return (-1);
}
strcpy(rp->fn_out + n, ".roil");
}
else
{
if (n < 4)
{
/* filename too short */
sprintf(rp->errbuf,
"open_outputfile(): filename too short n");
return (-1);
}
if (strncmp(&rp->fn_out[n - 5], ".roil", 5)==0)
{
/* cut ".roil" from filename */
rp->fn_out[n - 5]= 0;
}
else
{
/* unknown suffix / filename */
sprintf(rp->errbuf, "open_outputfile(): unknown suffix \n");
return (-1);
}
}
/* open the file */
rp->fd_out= open(rp->fn_out, 0_CREAT | 0_WRONLY);
if (rp->fd_out==-1)
{
sprintf(rp->errbuf, "open_outputfile(): %s n", strerror(errno));
return (-1);
}
/* set a umask of 600 */
if (fchmod(rp->fd_out, 0600)==-1)
{
sprintf(rp->errbuf, "open_outputflie(): %s\n", strerror(errno));
return (-1);
}
return (1);
}
void
roil(struct roil_pack *rp)
{
int n, len;
u_char *p;
if (rp->flags & MD)
{
/*
* We're going to be digesting a file here. The other case
* when we would be digesting a user's passphrase to create a
* sufficiently long key for encryption or decryption comes
* into play from within roil_cipher() and never here.
*/
rp->flags |=MD_FROMFILE;
/*
* Digest the file contained in rp. Upon success, the function
* will return a pointer to a static buffer containing the hash
* and the length will be written to len. Upon failure p will
* point to a NULL buffer and rp- errbuf will contain the
* reason.
*/
p = roil_digest(rp, &len);
if (p==NULL)
{
fprintf(stderr, "roil_digest(): %s", rp->errbuf);
return;
}
printf("%s message digest of %s: ", rp->md, rp->fn_in);
for (n = 0; n < len; n++)
{
printf ("%02x", p[n]);
}
printf("\n");
}
else if ((rp- flags & ENCRYPT) || (rp- flags & DECRYPT))
{
/*
* Encrypt or decrypt the file contained in rp. Upon success,
* the function will return 1; upon failure the function will
* return -1 and rp-> errbuf will contain the reason.
*/
if (roil_cipher(rp)==-1)
{
fprintf(stderr, "roil_cipher(): %s", rp->errbuf);
return;
}
}
}
u_char *
roil_digest(struct roil_pack *rp, int *digest_len)
{
int n;
const EVP_MD *md;
u_char buf[BUF_SIZE];
EVP_MD_CTX md_context;
static u_char digest[EVP_MAX_MD_SIZE];
/* add all available digest algorithms to the hash table */
OpenSSL_add_all_digests();
/* load and verify the digest specified at the command line */
md = EVP_get_digestbyname(rp->md);
if (md==NULL)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "unknown digest %s n",rp->md);
goto bad;
}
/*
* Initialize the md context. Really all this does is zero out the
* structure.
*/
EVP_MD_CTX_init(&md_context);
/* initialize the md algorithm */
if (EVP_DigestInit(&md_context, md)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "EVP_DigestInit() failed \n");
goto bad;
}
memset (digest, 0, sizeof (digest));
if (rp->flags & MD_FROMFILE)
{
/*
* Digest the file. Read in a block of data into buf and
* process it with the md algorithm.
*/
while ((n= read(rp->fd_in, buf, sizeof (buf))) 0)
{
if (EVP_DigestUpdate(&md_context, buf, n)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE,
"EVP_DigestUpdate() failed \n");
goto bad;
}
}
/* retrieve the digest value and length from the md context */
if (EVP_DigestFinal(&md_context, digest, digest_len)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE,
"EVP_DigestFinal() failed \n");
goto bad;
}
}
else
{
/*
* Digest a user's passphrase. Since we know this no more
* than KEY_LENGTH bytes, we can do it all in one chunk.
*/
if (EVP_DigestUpdate(&md_context, rp- passphrase,
strlen(rp->passphrase))==0)
{
snprintf(rp- errbuf, ERRBUF_SIZE,
"EVP_DigestUpdate() failed \n");
goto bad;
}
if (EVP_DigestFinal(&md_context, digest, digest_len)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE,
"EVP_DigestFinal() failed \n");
goto bad;
}
}
return (digest);
bad:
* digest_len= 0;
return (NULL);
}
int
roil_cipher(struct roil_pack *rp)
{
int n, m, mode;
EVP_CIPHER_CTX ea_context;
const EVP_CIPHER *ea;
u_long bytecnt;
u_char buf[BUF_SIZE], ebuf[BUF_SIZE], key[KEY_LENGTH],
iv[IV_LENGTH];
/* set the mode for the cipher functions */
mode= (rp->flags & ENCRYPT) ? 1 : 0;
/* add all available encryption algorithms to the hash table */
OpenSSL_add_all_ciphers();
if (rp->flags & ENCRYPT)
{
/*
* If we're encrypting, we have to first load and verify the
* cipher specified at the command line.
*/
ea = EVP_get_cipherbyname(rp->ea);
if (ea == NULL)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "unknown cipher %s n",
rp->ea);
return (-1);
}
}
else /* decrypting */
{
/*
* If we're decrypting, we have to check to see if this file
* was previously encrypted by roil. To do that, we read the
* first 8 bytes and see if they correspond to the "magic
* number" that is written to every roiled file prior to
* encryption.
*/
n= read(rp->fd_in, buf, 8);
if (n != 8)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "read error %s\n",
strerror(errno));
return (-1);
}
if (bcmp(buf, magic, 8))
{
snprintf(rp->errbuf, ERRBUF_SIZE, "%s is not a roiled file n",
rp->fn_in);
return (-1);
}
/*
* Next, we have to determine which symmetric cipher was used
* to encrypt the file. That is written in the next 16 bytes
* of the file.
*/
n = read(rp->fd_in, buf, 16);
if (n !=16)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "read error %s n",
strerror(errno));
return (-1);
}
/*
* Look up the cipher by canonical name and if it's "good" fill
* in an EVP_CIPHER structure.
*/
ea= EVP_get_cipherbyname(buf);
if (ea==NULL)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "unknown cipher %s n",
buf) ;
return (-1);
}
/*
* The next 8 bytes contain the initialization vector, which
* may or may not be used by the algorithm. We store it either
* way.
*/
n = read(rp->fd_in, iv, 8);
if (n !=8)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "read error %s n",
strerror(errno));
return (-1);
}
}
/*
* Get a passpnrase from the user to use as a key for the symmetric
* encryption.
*/
if (get_passphrase(rp->passphrase)==-1)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "can't read passphrase %s n",
strerror(errno));
return (-1);
}
/*
* Take the passphrase and hash it using SHA1 to create our
* symmetric key.
*/
if (make_key(rp, key)==-1)
{
/* error set in roil_digest() */
return (-1);
}
/* we appear good to go; we open our output file */
if (open_outputfile(rp)==-1)
{
/* error set in open_outputfile() */
return (-1);
}
if (rp->flags & ENCRYPT)
{
/*
* Write out our 8 byte magic number to the file. This will
* let the decryption code know if this file was encrypted by
* us or not.
*/
n = write(rp->fd_out, magic, 8);
if (n != 8)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "write error %s\n",
strerror (errno) );
return (-1);
}
/*
* Write the encryption algorithm to the file, which will be
* NULL padded to 16 bytes. This will allow the decryption
* code to figure it out without needing the user to specify.
*/
memset(buf, 0, sizeof (buf));
memcpy(buf, rp->ea, strlen(rp->ea)) ;
n= write(rp->fd_out, buf, 16);
if (n !=16)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "write error %s n",
strerror(errno));
return (-1);
}
/*
* Some encryption algorithms use an initialization vector to
* seed the first round of encryption with (it acts as a dummy
* block). We might need it so we'll get one and write it to
* the file next.
*/
get_iv(iv);
n= write(rp->fd_out, iv, 8);
if (n != 8)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "write error %s n",
strerror(errno));
return (-1);
}
}
/*
* Initialize the cipher context. Really all this does is zero
* out the structure.
*/
EVP_CIPHER_CTX_init(&ea_context);
/* initialize the encryption/decryption operation */
if (EVP_CipherInit_ex(&ea_context, ea, NULL, key, iv, mode)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "EVP_CipherInit_ex() failed\n");
return (-1);
}
/*
* Encrypt/decrypt the file. Read a block of data, encrypt it and
* write it out to the file.
*/
if (rp->flags & ENCRYPT)
{
fprintf(stderr, "\nencrypting file \"%s\"\n",
rp->fn_in);
}
else
{
fprintf(stderr, "\ndecrypting %s encrypted file\"%s "\n", buf,
rp->fn_in);
}
bytecnt= 0;
while ((n= read(rp->fd_in, buf, sizeof (buf))) > 0)
{
bytecnt +=n;
/*
* Encrypt or decrypt n bytes from buf and write the output to
* ebuf.
*/
if (EVP_CipherUpdate(&ea_context, ebuf, &m, buf, n)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE,
"EVP_CipherUpdate() failed \n");
return (-1);
}
n = write(rp->fd_out, ebuf, m);
if (n !=m)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "write error %s n",
strerror(errno));
return (-1);
}
fprintf(stderr, "byte: Ox%081x\r", bytecnt);
}
/*
* Finalize the encryption or decryption by taking care of padding
* the last block if necessary.
*/
if (EVP_CipherFinal_ex(&ea_context, ebuf, &m)==0)
{
snprintf(rp->errbuf, ERRBUF_SIZE,
"EVP_CipherFinal_ex() failed \n");
return (-1);
}
n= write(rp- fd_out, ebuf, m);
if (n !=m)
{
snprintf(rp->errbuf, ERRBUF_SIZE, "write error %s n",
strerror(errno));
return (-1);
}
printf("\ndone, output file is \"%s \"\n", rp->fn_out);
return (1);
}
int
get_passphrase(char *passphrase)
{
int n, retry;
char passphrase_match[KEY_LENGTH];
struct termios term;
/* we want to turn off terminal echoing so no one can see! */
n= tcgetattr(STDIN_FILENO, &term);
if (n==-1)
{
fprintf(stderr, "warning: password will be echoed\n");
/* nonfatal */
}
else
{
/* disable terminal echo */
term.c_lflag &=-ECHO;
}
/* set our changed state "NOW"*/
n= tcsetattr(STDIN_FILENO, TCSANOW, &term);
if (n==-1)
{
fprintf(stderr, "warning: password will be echoed \n");
/* nonfatal */
}
retry= RETRY_THRESHOLD;
memset(passphrase, 0, KEY_LENGTH);
again:
printf("Passphrase: ");
if (fgets(passphrase, KEY_LENGTH, stdin)==NULL)
{
return (-1);
}
passphrase[strlen(passphrase) - 1]= 0;
printf("\nAgain:");
if (fgets(passphrase_match, KEY_LENGTH, stdin)==NULL)
{
return (-1);
}
passphrase_match[strlen(passphrase_match) - 1]= 0;
/*
* Check to make sure they match. It's safe to use strcmp here
* since we're confident both strings will be KEY_LENGTH or fewer
* bytes.
*/
if (strcmp(passphrase, passphrase_match))
{
if (retry<= 0)
{
/* we've run through this RETRY_THRESHOLD times, we're done */
fprintf(stderr, "\nyou're hopeless; get typing lessons \n");
errno= EPERH; /* this is as good as any I suppose */
return (-1);
}
fprintf(stderr, "\nno doofus, they don't match, try again\n");
retry--;
goto again;
}
memset(passphrase_match, 0, KEY_LENGTH);
return (1);
}
int
make_key(struct roil_pack *rp, u_char *key)
{
int len;
u_char *p;
strncpy(rp->md, "sha1", 4);
p= roil_digest(rp, &len);
if (p==NULL)
{
/* error set in roil_digest() */
return (-1);
}
memcpy(key, p, len);
return (1);
}
void
get_iv(u_char *iv)
{
int n;
/* XXX - should use the rand() interface from OpenSSL */
srandom((unsigned)time(NULL));
/* get 8 bytes of pseudo random value, from 0 - 255 */
for (n= 0; n < IV_LENGTH; n++)
{
iv[n]= random() % 0xff;
}
}
void
usage(char *name)
{
printf("usage %s [options] file n"
"-e cipher_type\t\tencrypt\n"
"-d\t\t tdecrypt\n"
"-h\t\t\tthis blurb you see right here n"
"-m message_digest\tmessage digest\n", name);
}
/* EOF */

/ 135