Commit 2c72efba authored by hybrid's avatar hybrid

Create an initial stub for support of AES-encrypted zip files. This code is...

Create an initial stub for support of AES-encrypted zip files. This code is not yet functional. There is no way to specify the password, and it's unconditionally compiled in. But the basic algorithm is there, though untested so far.
We use the aes library by Dr Gladman, which is also used in WinZip. It can be used for other encryption support as well, and also provides a PRNG, SHA, and other things.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2955 dfc29bdd-3216-0410-991c-e03cc46cb475
parent cbe11eae
The Irrlicht Engine may be compiled to provide support for AES encrypted files. The implementation used by Irrlicht is provided by Dr Brian Gladman. The license for these files (including AES, a PRNG, SHA, and other algorithms) is as follows
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
*/
......@@ -19,7 +19,7 @@
#include "zlib/zlib.h"
#endif // _IRR_USE_NON_SYSTEM_ZLIB_
#endif // _IRR_COMPILE_WITH_ZLIB_
#include "aesGladman/fileenc.h"
namespace irr
{
namespace io
......@@ -388,7 +388,43 @@ bool CZipReader::scanZipHeader()
// move forward length of extra field.
if (entry.header.ExtraFieldLength)
// AES encryption
if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99))
{
s16 restSize = entry.header.ExtraFieldLength;
SZipFileExtraHeader extraHeader;
while (restSize)
{
File->read(&extraHeader, sizeof(extraHeader));
#ifdef __BIG_ENDIAN__
extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID);
extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size);
#endif
restSize -= sizeof(extraHeader);
if (extraHeader.ID=(s16)0x9901)
{
SZipFileAESExtraData data;
File->read(&data, sizeof(data));
#ifdef __BIG_ENDIAN__
data.Version = os::Byteswap::byteswap(data.Version);
data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode);
#endif
restSize -= sizeof(data);
if (data.Vendor[0]=='A' && data.Vendor[1]=='E')
{
// encode values into Sig
// AE-Version | Strength | ActualMode
entry.header.Sig =
((data.Version & 0xff) << 24) |
(data.EncryptionStrength << 16) |
(data.CompressionMode);
File->seek(restSize, true);
break;
}
}
}
}
else if (entry.header.ExtraFieldLength)
File->seek(entry.header.ExtraFieldLength, true);
// if bit 3 was set, read DataDescriptor, following after the compressed data
......@@ -449,10 +485,91 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
const SZipFileEntry &e = FileInfo[Files[index].ID];
wchar_t buf[64];
switch(e.header.CompressionMethod)
s16 actualCompressionMethod=e.header.CompressionMethod;
IReadFile* decrypted=0;
u8* decryptedBuf=0;
u16 decryptedSize=e.header.DataDescriptor.CompressedSize;
if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99))
{
u8 salt[16]={0};
const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*64;
File->seek(e.Offset);
File->read(salt, saltSize);
c8 pwVerification[2];
c8 pwVerificationFile[2];
File->read(pwVerification, 2);
fcrypt_ctx zctx; // the encryption context
const char* Password="0123456789";
int rc = fcrypt_init(
(e.header.Sig & 0x00ff0000) >>16,
(const unsigned char*)Password, // the password
strlen(Password), // number of bytes in password
salt, // the salt
(unsigned char*)pwVerificationFile, // on return contains password verifier
&zctx); // encryption context
if (strncmp(pwVerificationFile, pwVerification, 2))
{
os::Printer::log("Wrong password");
return 0;
}
decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12;
decryptedBuf= new u8[decryptedSize];
u16 c = 0;
while ((c+32768)<=decryptedSize)
{
File->read(decryptedBuf+c, 32768);
fcrypt_decrypt(
decryptedBuf+c, // pointer to the data to decrypt
32768, // how many bytes to decrypt
&zctx); // decryption context
c+=32768;
}
File->read(decryptedBuf+c, decryptedSize-c);
fcrypt_decrypt(
decryptedBuf+c, // pointer to the data to decrypt
decryptedSize-c, // how many bytes to decrypt
&zctx); // decryption context
char fileMAC[10];
char resMAC[10];
rc = fcrypt_end(
(unsigned char*)resMAC, // on return contains the authentication code
&zctx); // encryption context
if (rc != 10)
{
os::Printer::log("Error on encryption closing");
delete [] decryptedBuf;
return 0;
}
File->read(fileMAC, 10);
if (strncmp(fileMAC, resMAC, 10))
{
os::Printer::log("Error on encryption check");
delete [] decryptedBuf;
return 0;
}
decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true);
#if 0
if ((e.header.Sig & 0xff000000)==0x01000000)
{
}
else if ((e.header.Sig & 0xff000000)==0x02000000)
{
}
else
{
os::Printer::log("Unknown encryption method");
return 0;
}
#endif
}
switch(actualCompressionMethod)
{
case 0: // no compression
{
if (decrypted)
return decrypted;
else
return createLimitReadFile(Files[index].FullName, File, e.Offset, e.header.DataDescriptor.CompressedSize);
}
case 8:
......@@ -460,28 +577,36 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
#ifdef _IRR_COMPILE_WITH_ZLIB_
const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize;
const u32 compressedSize = e.header.DataDescriptor.CompressedSize;
const u32 compressedSize = decryptedSize;
void* pBuf = new c8[ uncompressedSize ];
if (!pBuf)
{
swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() );
os::Printer::log( buf, ELL_ERROR);
if (decrypted)
decrypted->drop();
return 0;
}
c8 *pcData = new c8[ compressedSize ];
u8 *pcData = decryptedBuf;
if (!pcData)
{
new c8[ compressedSize ];
if (!pcData)
{
swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() );
os::Printer::log( buf, ELL_ERROR);
delete [] (c8*)pBuf;
if (decrypted)
decrypted->drop();
return 0;
}
//memset(pcData, 0, compressedSize );
File->seek(e.Offset);
File->read(pcData, compressedSize );
}
// Setup the inflate stream.
z_stream stream;
......@@ -506,6 +631,9 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
inflateEnd(&stream);
}
if (decrypted)
decrypted->drop();
else
delete[] pcData;
if (err != Z_OK)
......
......@@ -97,6 +97,20 @@ namespace io
// zipfile comment (variable size)
} PACK_STRUCT;
struct SZipFileExtraHeader
{
s16 ID;
s16 Size;
} PACK_STRUCT;
struct SZipFileAESExtraData
{
s16 Version;
u8 Vendor[2];
u8 EncryptionStrength;
s16 CompressionMode;
} PACK_STRUCT;
enum E_GZIP_FLAGS
{
EGZF_TEXT_DAT = 1,
......
......@@ -3006,6 +3006,86 @@
>
</File>
</Filter>
<Filter
Name="aesGladman"
>
<File
RelativePath=".\aesGladman\aes.h"
>
</File>
<File
RelativePath=".\aesGladman\aescrypt.c"
>
</File>
<File
RelativePath=".\aesGladman\aeskey.c"
>
</File>
<File
RelativePath=".\aesGladman\aesopt.h"
>
</File>
<File
RelativePath=".\aesGladman\aestab.c"
>
</File>
<File
RelativePath=".\aesGladman\bzlib.h"
>
</File>
<File
RelativePath=".\aesGladman\fileenc.c"
>
</File>
<File
RelativePath=".\aesGladman\fileenc.h"
>
</File>
<File
RelativePath=".\aesGladman\hmac.c"
>
</File>
<File
RelativePath=".\aesGladman\hmac.h"
>
</File>
<File
RelativePath=".\aesGladman\prng.c"
>
</File>
<File
RelativePath=".\aesGladman\prng.h"
>
</File>
<File
RelativePath=".\aesGladman\pwd2key.c"
>
</File>
<File
RelativePath=".\aesGladman\pwd2key.h"
>
</File>
<File
RelativePath=".\aesGladman\Readme.txt"
>
</File>
<File
RelativePath=".\aesGladman\sha1.c"
>
</File>
<File
RelativePath=".\aesGladman\sha1.h"
>
</File>
<File
RelativePath=".\aesGladman\sha2.c"
>
</File>
<File
RelativePath=".\aesGladman\sha2.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="device"
......@@ -3018,6 +3098,14 @@
RelativePath=".\CIrrDeviceConsole.h"
>
</File>
<File
RelativePath=".\CIrrDeviceFB.cpp"
>
</File>
<File
RelativePath=".\CIrrDeviceFB.h"
>
</File>
<File
RelativePath="CIrrDeviceLinux.cpp"
>
......@@ -3050,6 +3138,14 @@
RelativePath="CIrrDeviceWin32.h"
>
</File>
<File
RelativePath=".\CIrrDeviceWinCE.cpp"
>
</File>
<File
RelativePath=".\CIrrDeviceWinCE.h"
>
</File>
</Filter>
</Filter>
<Filter
......@@ -3108,19 +3204,19 @@
>
</File>
<File
RelativePath="CPakReader.cpp"
RelativePath="CNPKReader.cpp"
>
</File>
<File
RelativePath="CPakReader.h"
RelativePath="CNPKReader.h"
>
</File>
<File
RelativePath="CNPKReader.cpp"
RelativePath="CPakReader.cpp"
>
</File>
<File
RelativePath="CNPKReader.h"
RelativePath="CPakReader.h"
>
</File>
<File
......
......@@ -42,11 +42,13 @@ IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEdi
ZLIBOBJ = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o
JPEGLIBOBJ = jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcphuff.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdphuff.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jidctred.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o
LIBPNGOBJ = libpng/png.o libpng/pngerror.o libpng/pngget.o libpng/pngmem.o libpng/pngpread.o libpng/pngread.o libpng/pngrio.o libpng/pngrtran.o libpng/pngrutil.o libpng/pngset.o libpng/pngtrans.o libpng/pngwio.o libpng/pngwrite.o libpng/pngwtran.o libpng/pngwutil.o
LIBAESGM = aesGladman/aescrypt.c aesGladman/aeskey.c aesGladman/aestab.c aesGladman/fileenc.c aesGladman/hmac.c aesGladman/prng.c aesGladman/pwd2key.c aesGladman/sha1.c aesGladman/sha2.c
# Next variable is for additional scene nodes etc. of customized Irrlicht versions
EXTRAOBJ =
LINKOBJ = $(IRRMESHOBJ) $(IRROBJ) $(IRRPARTICLEOBJ) $(IRRANIMOBJ) \
$(IRRVIDEOOBJ) $(IRRSWRENDEROBJ) $(IRRIOOBJ) $(IRROTHEROBJ) \
$(IRRGUIOBJ) $(ZLIBOBJ) $(JPEGLIBOBJ) $(LIBPNGOBJ) $(EXTRAOBJ)
$(IRRGUIOBJ) $(ZLIBOBJ) $(JPEGLIBOBJ) $(LIBPNGOBJ) $(LIBAESGM) \
$(EXTRAOBJ)
###############
#Compiler flags
......
A File Encryption Utility - VC++ 7.1 project Instructions
1. Unzip the enclosed files into a suitable VC++ project directory.
2. Obtain the bzip2 source code from http://sources.redhat.com/bzip2/
and unzip the files into the bzip2 sub-directory.
3. Compile the bzip2 project to give a static library
4. Compile the encfile project.
5. The executable encfile.exe is now ready for use:
enfile password filename
If the filename does not have the extension 'enc', it is assumed to
be a normal file that will then be encrypted to a file with the same
name but with an added extension 'enc'.
If the filename has the extension 'enc' its is assumed to be an
encrypted file that will be decrypted to a file with the same name
but without the 'enc' extension.
The default HASH function is SHA1, which is set up by defining USE_SHA1 in
compiling the project. If USE_SHA256 is defined instead then SHA256 is used.
Brian Gladman
/*
---------------------------------------------------------------------------
Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This file contains the definitions required to use AES in C. See aesopt.h
for optimisation details.
*/
#ifndef _AES_H
#define _AES_H
/* This include is used to find 8 & 32 bit unsigned integer types */
#include "limits.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define AES_128 /* define if AES with 128 bit keys is needed */
#define AES_192 /* define if AES with 192 bit keys is needed */
#define AES_256 /* define if AES with 256 bit keys is needed */
#define AES_VAR /* define if a variable key size is needed */
/* The following must also be set in assembler files if being used */
#define AES_ENCRYPT /* if support for encryption is needed */
//#define AES_DECRYPT /* if support for decryption is needed */
#define AES_ERR_CHK /* for parameter checks & error return codes */
#if UCHAR_MAX == 0xff /* an unsigned 8 bit type */
typedef unsigned char aes_08t;
#else
#error Please define aes_08t as an 8-bit unsigned integer type in aes.h
#endif
#if UINT_MAX == 0xffffffff /* an unsigned 32 bit type */
typedef unsigned int aes_32t;
#elif ULONG_MAX == 0xffffffff
typedef unsigned long aes_32t;
#else
#error Please define aes_32t as a 32-bit unsigned integer type in aes.h
#endif
#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */
#define N_COLS 4 /* the number of columns in the state */
/* a maximum of 60 32-bit words are needed for the key schedule */
#define KS_LENGTH 64
#ifdef AES_ERR_CHK
#define aes_ret int
#define aes_good 0
#define aes_error -1
#else
#define aes_ret void
#endif
#ifndef AES_DLL /* implement normal/DLL functions */
#define aes_rval aes_ret
#else
#define aes_rval aes_ret __declspec(dllexport) _stdcall
#endif
/* This routine must be called before first use if non-static */
/* tables are being used */
void gen_tabs(void);
/* The key length (klen) is input in bytes when it is in the range */
/* 16 <= klen <= 32 or in bits when in the range 128 <= klen <= 256 */
#ifdef AES_ENCRYPT
typedef struct
{ aes_32t ks[KS_LENGTH];
} aes_encrypt_ctx;
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]);
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]);
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]);
#endif
#if defined(AES_VAR)
aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1]);
#endif
aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1]);
#endif
#ifdef AES_DECRYPT
typedef struct
{ aes_32t ks[KS_LENGTH];
} aes_decrypt_ctx;
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]);
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]);
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]);
#endif
#if defined(AES_VAR)
aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]);
#endif
aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]);
#endif
#if defined(__cplusplus)
}
#endif
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
---------------------------------------------------------------------------
Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#if defined(__cplusplus)
extern "C"
{
#endif
#define DO_TABLES
#include "aesopt.h"
#if defined(FIXED_TABLES)
/* implemented in case of wrong call for fixed tables */
void gen_tabs(void)
{
}
#else /* dynamic table generation */
#if !defined(FF_TABLES)
/* Generate the tables for the dynamic table option
It will generally be sensible to use tables to compute finite
field multiplies and inverses but where memory is scarse this
code might sometimes be better. But it only has effect during
initialisation so its pretty unimportant in overall terms.
*/
/* return 2 ^ (n - 1) where n is the bit number of the highest bit
set in x with x in the range 1 < x < 0x00000200. This form is
used so that locals within fi can be bytes rather than words
*/
static aes_08t hibit(const aes_32t x)
{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static aes_08t fi(const aes_08t x)
{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if(x < 2) return x;
for(;;)
{
if(!n1) return v1;
while(n2 >= n1)
{
n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
}
if(!n2) return v2;
while(n1 >= n2)
{
n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
}
}
}
#endif
/* The forward and inverse affine transformations used in the S-box */
#define fwd_affine(x) \
(w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8)))
#define inv_affine(x) \
(w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8)))
static int init = 0;
void gen_tabs(void)
{ aes_32t i, w;
#if defined(FF_TABLES)
aes_08t pow[512], log[256];
if(init) return;
/* log and power tables for GF(2^8) finite field with
WPOLY as modular polynomial - the simplest primitive
root is 0x03, used here to generate the tables
*/
i = 0; w = 1;
do
{
pow[i] = (aes_08t)w;
pow[i + 255] = (aes_08t)w;
log[w] = (aes_08t)i++;
w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
}
while (w != 1);
#else
if(init) return;
#endif
for(i = 0, w = 1; i < RC_LENGTH; ++i)
{
t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
w = f2(w);
}
for(i = 0; i < 256; ++i)
{ aes_08t b;
b = fwd_affine(fi((aes_08t)i));
w = bytes2word(f2(b), b, b, f3(b));
#ifdef SBX_SET
t_set(s,box)[i] = b;
#endif
#ifdef FT1_SET /* tables for a normal encryption round */
t_set(f,n)[i] = w;
#endif
#ifdef FT4_SET
t_set(f,n)[0][i] = w;
t_set(f,n)[1][i] = upr(w,1);
t_set(f,n)[2][i] = upr(w,2);
t_set(f,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#ifdef FL1_SET /* tables for last encryption round (may also */
t_set(f,l)[i] = w; /* be used in the key schedule) */
#endif
#ifdef FL4_SET
t_set(f,l)[0][i] = w;
t_set(f,l)[1][i] = upr(w,1);
t_set(f,l)[2][i] = upr(w,2);
t_set(f,l)[3][i] = upr(w,3);
#endif
#ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */
t_set(l,s)[i] = w; /* not of the required form */
#endif
#ifdef LS4_SET
t_set(l,s)[0][i] = w;
t_set(l,s)[1][i] = upr(w,1);
t_set(l,s)[2][i] = upr(w,2);
t_set(l,s)[3][i] = upr(w,3);
#endif
b = fi(inv_affine((aes_08t)i));
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
#ifdef IM1_SET /* tables for the inverse mix column operation */
t_set(i,m)[b] = w;
#endif
#ifdef IM4_SET
t_set(i,m)[0][b] = w;
t_set(i,m)[1][b] = upr(w,1);
t_set(i,m)[2][b] = upr(w,2);
t_set(i,m)[3][b] = upr(w,3);
#endif
#ifdef ISB_SET
t_set(i,box)[i] = b;
#endif
#ifdef IT1_SET /* tables for a normal decryption round */
t_set(i,n)[i] = w;
#endif
#ifdef IT4_SET
t_set(i,n)[0][i] = w;
t_set(i,n)[1][i] = upr(w,1);
t_set(i,n)[2][i] = upr(w,2);
t_set(i,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#ifdef IL1_SET /* tables for last decryption round */
t_set(i,l)[i] = w;
#endif
#ifdef IL4_SET
t_set(i,l)[0][i] = w;
t_set(i,l)[1][i] = upr(w,1);
t_set(i,l)[2][i] = upr(w,2);
t_set(i,l)[3][i] = upr(w,3);
#endif
}
init = 1;
}
#endif
#if defined(__cplusplus)
}
#endif
/*-------------------------------------------------------------*/
/*--- Public header file for the library. ---*/
/*--- bzlib.h ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#ifndef _BZLIB_H
#define _BZLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define BZ_RUN 0
#define BZ_FLUSH 1
#define BZ_FINISH 2
#define BZ_OK 0
#define BZ_RUN_OK 1
#define BZ_FLUSH_OK 2
#define BZ_FINISH_OK 3
#define BZ_STREAM_END 4
#define BZ_SEQUENCE_ERROR (-1)
#define BZ_PARAM_ERROR (-2)
#define BZ_MEM_ERROR (-3)
#define BZ_DATA_ERROR (-4)
#define BZ_DATA_ERROR_MAGIC (-5)
#define BZ_IO_ERROR (-6)
#define BZ_UNEXPECTED_EOF (-7)
#define BZ_OUTBUFF_FULL (-8)
#define BZ_CONFIG_ERROR (-9)
typedef
struct {
char *next_in;
unsigned int avail_in;
unsigned int total_in_lo32;
unsigned int total_in_hi32;
char *next_out;
unsigned int avail_out;
unsigned int total_out_lo32;
unsigned int total_out_hi32;
void *state;
void *(*bzalloc)(void *,int,int);
void (*bzfree)(void *,void *);
void *opaque;
}
bz_stream;
#ifndef BZ_IMPORT
#define BZ_EXPORT
#endif
/* Need a definitition for FILE */
#include <stdio.h>
#ifdef _WIN32
# include <windows.h>
# ifdef small
/* windows.h define small to char */
# undef small
# endif
# ifdef BZ_EXPORT
# define BZ_API(func) WINAPI func
# define BZ_EXTERN extern
# else
/* import windows dll dynamically */
# define BZ_API(func) (WINAPI * func)
# define BZ_EXTERN
# endif
#else
# define BZ_API(func) func
# define BZ_EXTERN extern
#endif
/*-- Core (low-level) library functions --*/
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
bz_stream* strm,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
bz_stream* strm,
int action
);
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
bz_stream* strm
);
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
bz_stream *strm,
int verbosity,
int small
);
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
bz_stream* strm
);
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
bz_stream *strm
);
/*-- High(er) level library functions --*/
#ifndef BZ_NO_STDIO
#define BZ_MAX_UNUSED 5000
typedef void BZFILE;
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
int* bzerror,
FILE* f,
int verbosity,
int small,
void* unused,
int nUnused
);
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
int* bzerror,
BZFILE* b
);
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
int* bzerror,
BZFILE* b,
void** unused,
int* nUnused
);
BZ_EXTERN int BZ_API(BZ2_bzRead) (
int* bzerror,
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
int* bzerror,
FILE* f,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
int* bzerror,
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in,
unsigned int* nbytes_out
);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in_lo32,
unsigned int* nbytes_in_hi32,
unsigned int* nbytes_out_lo32,
unsigned int* nbytes_out_hi32
);
#endif
/*-- Utility functions --*/
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int small,
int verbosity
);
/*--
Code contributed by Yoshioka Tsuneo
(QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
to support better zlib compatibility.
This code is not _officially_ part of libbzip2 (yet);
I haven't tested it, documented it, or considered the
threading-safeness of it.
If this code breaks, please contact both Yoshioka and me.
--*/
BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
void
);
#ifndef BZ_NO_STDIO
BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
const char *path,
const char *mode
);
BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
int fd,
const char *mode
);
BZ_EXTERN int BZ_API(BZ2_bzread) (
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN int BZ_API(BZ2_bzflush) (
BZFILE* b
);
BZ_EXTERN void BZ_API(BZ2_bzclose) (
BZFILE* b
);
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
BZFILE *b,
int *errnum
);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*-------------------------------------------------------------*/
/*--- end bzlib.h ---*/
/*-------------------------------------------------------------*/
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
-------------------------------------------------------------------------
Issue Date: 26/08/2003
This file implements password based file encryption and authentication
using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password
based key derivation.
*/
#include <memory.h>
#include "fileenc.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* subroutine for data encryption/decryption */
/* this could be speeded up a lot by aligning */
/* buffers and using 32 bit operations */
static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1])
{ unsigned long i = 0, pos = cx->encr_pos;
while(i < d_len)
{
if(pos == BLOCK_SIZE)
{ unsigned int j = 0;
/* increment encryption nonce */
while(j < 8 && !++cx->nonce[j])
++j;
/* encrypt the nonce to form next xor buffer */
aes_encrypt(cx->nonce, cx->encr_bfr, cx->encr_ctx);
pos = 0;
}
data[i++] ^= cx->encr_bfr[pos++];
}
cx->encr_pos = pos;
}
int fcrypt_init(
int mode, /* the mode to be used (input) */
const unsigned char pwd[], /* the user specified password (input) */
unsigned int pwd_len, /* the length of the password (input) */
const unsigned char salt[], /* the salt (input) */
#ifdef PASSWORD_VERIFIER
unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */
#endif
fcrypt_ctx cx[1]) /* the file encryption context (output) */
{ unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH];
if(pwd_len > MAX_PWD_LENGTH)
return PASSWORD_TOO_LONG;
if(mode < 1 || mode > 3)
return BAD_MODE;
cx->mode = mode;
cx->pwd_len = pwd_len;
/* initialise the encryption nonce and buffer pos */
cx->encr_pos = BLOCK_SIZE;
/* if we need a random component in the encryption */
/* nonce, this is where it would have to be set */
memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char));
/* initialise for authentication */
hmac_sha_begin(cx->auth_ctx);
/* derive the encryption and authetication keys and the password verifier */
derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS,
kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH);
/* set the encryption key */
aes_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx);
/* set the authentication key */
hmac_sha_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx);
#ifdef PASSWORD_VERIFIER
memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH);
#endif
/* clear the buffer holding the derived key values */
memset(kbuf, 0, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH);
return GOOD_RETURN;
}
/* perform 'in place' encryption and authentication */
void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1])
{
encr_data(data, data_len, cx);
hmac_sha_data(data, data_len, cx->auth_ctx);
}
/* perform 'in place' authentication and decryption */
void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1])
{
hmac_sha_data(data, data_len, cx->auth_ctx);
encr_data(data, data_len, cx);
}
/* close encryption/decryption and return the MAC value */
int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1])
{ unsigned int res = cx->mode;
hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx);
memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */
return MAC_LENGTH(res); /* return MAC length in bytes */
}
#if defined(__cplusplus)
}
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 24/01/2003
This file contains the header file for fileenc.c, which implements password
based file encryption and authentication using AES in CTR mode, HMAC-SHA1
authentication and RFC2898 password based key derivation.
*/
#ifndef _FENC_H
#define _FENC_H
#include "aes.h"
#include "hmac.h"
#include "pwd2key.h"
#define BLOCK_SIZE AES_BLOCK_SIZE
#define PASSWORD_VERIFIER
#define MAX_KEY_LENGTH 32
#define MAX_PWD_LENGTH 128
#define MAX_SALT_LENGTH 16
#define KEYING_ITERATIONS 1000
#ifdef PASSWORD_VERIFIER
#define PWD_VER_LENGTH 2
#else
#define PWD_VER_LENGTH 0
#endif
#define GOOD_RETURN 0
#define PASSWORD_TOO_LONG -100
#define BAD_MODE -101
/*
Field lengths (in bytes) versus File Encryption Mode (0 < mode < 4)
Mode Key Salt MAC Overhead
1 16 8 10 18
2 24 12 10 22
3 32 16 10 26
The following macros assume that the mode value is correct.
*/
#define KEY_LENGTH(mode) (8 * (mode & 3) + 8)
#define SALT_LENGTH(mode) (4 * (mode & 3) + 4)
#define MAC_LENGTH(mode) (10)
/* the context for file encryption */
#if defined(__cplusplus)
extern "C"
{
#endif
typedef struct
{ unsigned char nonce[BLOCK_SIZE]; /* the CTR nonce */
unsigned char encr_bfr[BLOCK_SIZE]; /* encrypt buffer */
aes_encrypt_ctx encr_ctx[1]; /* encryption context */
hmac_ctx auth_ctx[1]; /* authentication context */
unsigned int encr_pos; /* block position (enc) */
unsigned int pwd_len; /* password length */
unsigned int mode; /* File encryption mode */
} fcrypt_ctx;
/* initialise file encryption or decryption */
int fcrypt_init(
int mode, /* the mode to be used (input) */
const unsigned char pwd[], /* the user specified password (input) */
unsigned int pwd_len, /* the length of the password (input) */
const unsigned char salt[], /* the salt (input) */
#ifdef PASSWORD_VERIFIER
unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */
#endif
fcrypt_ctx cx[1]); /* the file encryption context (output) */
/* perform 'in place' encryption or decryption and authentication */
void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]);
void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]);
/* close encryption/decryption and return the MAC value */
/* the return value is the length of the MAC */
int fcrypt_end(unsigned char mac[], /* the MAC value (output) */
fcrypt_ctx cx[1]); /* the context (input) */
#if defined(__cplusplus)
}
#endif
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This is an implementation of HMAC, the FIPS standard keyed hash function
*/
#include "hmac.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* initialise the HMAC context to zero */
void hmac_sha_begin(hmac_ctx cx[1])
{
memset(cx, 0, sizeof(hmac_ctx));
}
/* input the HMAC key (can be called multiple times) */
int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1])
{
if(cx->klen == HMAC_IN_DATA) /* error if further key input */
return HMAC_BAD_MODE; /* is attempted in data mode */
if(cx->klen + key_len > HASH_INPUT_SIZE) /* if the key has to be hashed */
{
if(cx->klen <= HASH_INPUT_SIZE) /* if the hash has not yet been */
{ /* started, initialise it and */
sha_begin(cx->ctx); /* hash stored key characters */
sha_hash(cx->key, cx->klen, cx->ctx);
}
sha_hash(key, key_len, cx->ctx); /* hash long key data into hash */
}
else /* otherwise store key data */
memcpy(cx->key + cx->klen, key, key_len);
cx->klen += key_len; /* update the key length count */
return HMAC_OK;
}
/* input the HMAC data (can be called multiple times) - */
/* note that this call terminates the key input phase */
void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1])
{ unsigned int i;
if(cx->klen != HMAC_IN_DATA) /* if not yet in data phase */
{
if(cx->klen > HASH_INPUT_SIZE) /* if key is being hashed */
{ /* complete the hash and */
sha_end(cx->key, cx->ctx); /* store the result as the */
cx->klen = HASH_OUTPUT_SIZE; /* key and set new length */
}
/* pad the key if necessary */
memset(cx->key + cx->klen, 0, HASH_INPUT_SIZE - cx->klen);
/* xor ipad into key value */
for(i = 0; i < (HASH_INPUT_SIZE >> 2); ++i)
((unsigned long*)cx->key)[i] ^= 0x36363636;
/* and start hash operation */
sha_begin(cx->ctx);
sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx);
/* mark as now in data mode */
cx->klen = HMAC_IN_DATA;
}
/* hash the data (if any) */
if(data_len)
sha_hash(data, data_len, cx->ctx);
}
/* compute and output the MAC value */
void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1])
{ unsigned char dig[HASH_OUTPUT_SIZE];
unsigned int i;
/* if no data has been entered perform a null data phase */
if(cx->klen != HMAC_IN_DATA)
hmac_sha_data((const unsigned char*)0, 0, cx);
sha_end(dig, cx->ctx); /* complete the inner hash */
/* set outer key value using opad and removing ipad */
for(i = 0; i < (HASH_INPUT_SIZE >> 2); ++i)
((unsigned long*)cx->key)[i] ^= 0x36363636 ^ 0x5c5c5c5c;
/* perform the outer hash operation */
sha_begin(cx->ctx);
sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx);
sha_hash(dig, HASH_OUTPUT_SIZE, cx->ctx);
sha_end(dig, cx->ctx);
/* output the hash value */
for(i = 0; i < mac_len; ++i)
mac[i] = dig[i];
}
/* 'do it all in one go' subroutine */
void hmac_sha(const unsigned char key[], unsigned long key_len,
const unsigned char data[], unsigned long data_len,
unsigned char mac[], unsigned long mac_len)
{ hmac_ctx cx[1];
hmac_sha_begin(cx);
hmac_sha_key(key, key_len, cx);
hmac_sha_data(data, data_len, cx);
hmac_sha_end(mac, mac_len, cx);
}
#if defined(__cplusplus)
}
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This is an implementation of HMAC, the FIPS standard keyed hash function
*/
#ifndef _HMAC_H
#define _HMAC_H
#include <memory.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#define USE_SHA1
#if !defined(USE_SHA1) && !defined(USE_SHA256)
#error define USE_SHA1 or USE_SHA256 to set the HMAC hash algorithm
#endif
#ifdef USE_SHA1
#include "sha1.h"
#define HASH_INPUT_SIZE SHA1_BLOCK_SIZE
#define HASH_OUTPUT_SIZE SHA1_DIGEST_SIZE
#define sha_ctx sha1_ctx
#define sha_begin sha1_begin
#define sha_hash sha1_hash
#define sha_end sha1_end
#endif
#ifdef USE_SHA256
#include "sha2.h"
#define HASH_INPUT_SIZE SHA256_BLOCK_SIZE
#define HASH_OUTPUT_SIZE SHA256_DIGEST_SIZE
#define sha_ctx sha256_ctx
#define sha_begin sha256_begin
#define sha_hash sha256_hash
#define sha_end sha256_end
#endif
#define HMAC_OK 0
#define HMAC_BAD_MODE -1
#define HMAC_IN_DATA 0xffffffff
typedef struct
{ unsigned char key[HASH_INPUT_SIZE];
sha_ctx ctx[1];
unsigned long klen;
} hmac_ctx;
void hmac_sha_begin(hmac_ctx cx[1]);
int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]);
void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]);
void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]);
void hmac_sha(const unsigned char key[], unsigned long key_len,
const unsigned char data[], unsigned long data_len,
unsigned char mac[], unsigned long mac_len);
#if defined(__cplusplus)
}
#endif
#endif
This diff is collapsed.
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 24/01/2003
This file implements a random data pool based on the use of an external
entropy function. It is based on the ideas advocated by Peter Gutmann in
his work on pseudo random sequence generators. It is not a 'paranoid'
random sequence generator and no attempt is made to protect the pool
from prying eyes either by memory locking or by techniques to obscure
its location in memory.
*/
#include <memory.h>
#include "prng.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* mix a random data pool using the SHA1 compression function (as */
/* suggested by Peter Gutmann in his paper on random pools) */
static void prng_mix(unsigned char buf[])
{ unsigned int i, len;
sha1_ctx ctx[1];
/*lint -e{663} unusual array to pointer conversion */
for(i = 0; i < PRNG_POOL_SIZE; i += SHA1_DIGEST_SIZE)
{
/* copy digest size pool block into SHA1 hash block */
memcpy(ctx->hash, buf + (i ? i : PRNG_POOL_SIZE)
- SHA1_DIGEST_SIZE, SHA1_DIGEST_SIZE);
/* copy data from pool into the SHA1 data buffer */
len = PRNG_POOL_SIZE - i;
memcpy(ctx->wbuf, buf + i, (len > SHA1_BLOCK_SIZE ? SHA1_BLOCK_SIZE : len));
if(len < SHA1_BLOCK_SIZE)
memcpy(((char*)ctx->wbuf) + len, buf, SHA1_BLOCK_SIZE - len);
/* compress using the SHA1 compression function */
sha1_compile(ctx);
/* put digest size block back into the random pool */
memcpy(buf + i, ctx->hash, SHA1_DIGEST_SIZE);
}
}
/* refresh the output buffer and update the random pool by adding */
/* entropy and remixing */
static void update_pool(prng_ctx ctx[1])
{ unsigned int i = 0;
/* transfer random pool data to the output buffer */
memcpy(ctx->obuf, ctx->rbuf, PRNG_POOL_SIZE);
/* enter entropy data into the pool */
while(i < PRNG_POOL_SIZE)
i += ctx->entropy(ctx->rbuf + i, PRNG_POOL_SIZE - i);
/* invert and xor the original pool data into the pool */
for(i = 0; i < PRNG_POOL_SIZE; ++i)
ctx->rbuf[i] ^= ~ctx->obuf[i];
/* mix the pool and the output buffer */
prng_mix(ctx->rbuf);
prng_mix(ctx->obuf);
}
void prng_init(prng_entropy_fn fun, prng_ctx ctx[1])
{ int i;
/* clear the buffers and the counter in the context */
memset(ctx, 0, sizeof(prng_ctx));
/* set the pointer to the entropy collection function */
ctx->entropy = fun;
/* initialise the random data pool */
update_pool(ctx);
/* mix the pool a minimum number of times */
for(i = 0; i < PRNG_MIN_MIX; ++i)
prng_mix(ctx->rbuf);
/* update the pool to prime the pool output buffer */
update_pool(ctx);
}
/* provide random bytes from the random data pool */
void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1])
{ unsigned char *rp = data;
unsigned int len, pos = ctx->pos;
while(data_len)
{
/* transfer 'data_len' bytes (or the number of bytes remaining */
/* the pool output buffer if less) into the output */
len = (data_len < PRNG_POOL_SIZE - pos ? data_len : PRNG_POOL_SIZE - pos);
memcpy(rp, ctx->obuf + pos, len);
rp += len; /* update ouput buffer position pointer */
pos += len; /* update pool output buffer pointer */
data_len -= len; /* update the remaining data count */
/* refresh the random pool if necessary */
if(pos == PRNG_POOL_SIZE)
{
update_pool(ctx); pos = 0;
}
}
ctx->pos = pos;
}
void prng_end(prng_ctx ctx[1])
{
/* ensure the data in the context is destroyed */
memset(ctx, 0, sizeof(prng_ctx));
}
#if defined(__cplusplus)
}
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 24/01/2003
This is the header file for an implementation of a random data pool based on
the use of an external entropy function (inspired by Peter Gutmann's work).
*/
#ifndef _PRNG_H
#define _PRNG_H
#include "sha1.h"
#define PRNG_POOL_LEN 256 /* minimum random pool size */
#define PRNG_MIN_MIX 20 /* min initial pool mixing iterations */
/* ensure that pool length is a multiple of the SHA1 digest size */
#define PRNG_POOL_SIZE (SHA1_DIGEST_SIZE * (1 + (PRNG_POOL_LEN - 1) / SHA1_DIGEST_SIZE))
#if defined(__cplusplus)
extern "C"
{
#endif
/* A function for providing entropy is a parameter in the prng_init() */
/* call. This function has the following form and returns a maximum */
/* of 'len' bytes of pseudo random data in the buffer 'buf'. It can */
/* return less than 'len' bytes but will be repeatedly called for more */
/* data in this case. */
typedef int (*prng_entropy_fn)(unsigned char buf[], unsigned int len);
typedef struct
{ unsigned char rbuf[PRNG_POOL_SIZE]; /* the random pool */
unsigned char obuf[PRNG_POOL_SIZE]; /* pool output buffer */
unsigned int pos; /* output buffer position */
prng_entropy_fn entropy; /* entropy function pointer */
} prng_ctx;
/* initialise the random stream generator */
void prng_init(prng_entropy_fn fun, prng_ctx ctx[1]);
/* obtain random bytes from the generator */
void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]);
/* close the random stream generator */
void prng_end(prng_ctx ctx[1]);
#if defined(__cplusplus)
}
#endif
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This is an implementation of RFC2898, which specifies key derivation from
a password and a salt value.
*/
#include <memory.h>
#include "hmac.h"
#if defined(__cplusplus)
extern "C"
{
#endif
void derive_key(const unsigned char pwd[], /* the PASSWORD */
unsigned int pwd_len, /* and its length */
const unsigned char salt[], /* the SALT and its */
unsigned int salt_len, /* length */
unsigned int iter, /* the number of iterations */
unsigned char key[], /* space for the output key */
unsigned int key_len)/* and its required length */
{
unsigned int i, j, k, n_blk;
unsigned char uu[HASH_OUTPUT_SIZE], ux[HASH_OUTPUT_SIZE];
hmac_ctx c1[1], c2[1], c3[1];
/* set HMAC context (c1) for password */
hmac_sha_begin(c1);
hmac_sha_key(pwd, pwd_len, c1);
/* set HMAC context (c2) for password and salt */
memcpy(c2, c1, sizeof(hmac_ctx));
hmac_sha_data(salt, salt_len, c2);
/* find the number of SHA blocks in the key */
n_blk = 1 + (key_len - 1) / HASH_OUTPUT_SIZE;
for(i = 0; i < n_blk; ++i) /* for each block in key */
{
/* ux[] holds the running xor value */
memset(ux, 0, HASH_OUTPUT_SIZE);
/* set HMAC context (c3) for password and salt */
memcpy(c3, c2, sizeof(hmac_ctx));
/* enter additional data for 1st block into uu */
uu[0] = (unsigned char)((i + 1) >> 24);
uu[1] = (unsigned char)((i + 1) >> 16);
uu[2] = (unsigned char)((i + 1) >> 8);
uu[3] = (unsigned char)(i + 1);
/* this is the key mixing iteration */
for(j = 0, k = 4; j < iter; ++j)
{
/* add previous round data to HMAC */
hmac_sha_data(uu, k, c3);
/* obtain HMAC for uu[] */
hmac_sha_end(uu, HASH_OUTPUT_SIZE, c3);
/* xor into the running xor block */
for(k = 0; k < HASH_OUTPUT_SIZE; ++k)
ux[k] ^= uu[k];
/* set HMAC context (c3) for password */
memcpy(c3, c1, sizeof(hmac_ctx));
}
/* compile key blocks into the key output */
j = 0; k = i * HASH_OUTPUT_SIZE;
while(j < HASH_OUTPUT_SIZE && k < key_len)
key[k++] = ux[j++];
}
}
#ifdef TEST
#include <stdio.h>
struct
{ unsigned int pwd_len;
unsigned int salt_len;
unsigned int it_count;
unsigned char *pwd;
unsigned char salt[32];
unsigned char key[32];
} tests[] =
{
{ 8, 4, 5, (unsigned char*)"password",
{
0x12, 0x34, 0x56, 0x78
},
{
0x5c, 0x75, 0xce, 0xf0, 0x1a, 0x96, 0x0d, 0xf7,
0x4c, 0xb6, 0xb4, 0x9b, 0x9e, 0x38, 0xe6, 0xb5
}
},
{ 8, 8, 5, (unsigned char*)"password",
{
0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12
},
{
0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6,
0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49
}
},
{ 8, 21, 1, (unsigned char*)"password",
{
"ATHENA.MIT.EDUraeburn"
},
{
0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01,
0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15
}
},
{ 8, 21, 2, (unsigned char*)"password",
{
"ATHENA.MIT.EDUraeburn"
},
{
0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e,
0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d
}
},
{ 8, 21, 1200, (unsigned char*)"password",
{
"ATHENA.MIT.EDUraeburn"
},
{
0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e,
0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b
}
}
};
int main()
{ unsigned int i, j, key_len = 256;
unsigned char key[256];
printf("\nTest of RFC2898 Password Based Key Derivation");
for(i = 0; i < 5; ++i)
{
derive_key(tests[i].pwd, tests[i].pwd_len, tests[i].salt,
tests[i].salt_len, tests[i].it_count, key, key_len);
printf("\ntest %i: ", i + 1);
printf("key %s", memcmp(tests[i].key, key, 16) ? "is bad" : "is good");
for(j = 0; j < key_len && j < 64; j += 4)
{
if(j % 16 == 0)
printf("\n");
printf("0x%02x%02x%02x%02x ", key[j], key[j + 1], key[j + 2], key[j + 3]);
}
printf(j < key_len ? " ... \n" : "\n");
}
printf("\n");
return 0;
}
#if defined(__cplusplus)
}
#endif
#endif
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This is an implementation of RFC2898, which specifies key derivation from
a password and a salt value.
*/
#ifndef PWD2KEY_H
#define PWD2KEY_H
#if defined(__cplusplus)
extern "C"
{
#endif
void derive_key(
const unsigned char pwd[], /* the PASSWORD, and */
unsigned int pwd_len, /* its length */
const unsigned char salt[], /* the SALT and its */
unsigned int salt_len, /* length */
unsigned int iter, /* the number of iterations */
unsigned char key[], /* space for the output key */
unsigned int key_len); /* and its required length */
#if defined(__cplusplus)
}
#endif
#endif
This diff is collapsed.
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#ifndef _SHA1_H
#define _SHA1_H
#include <limits.h>
#define SHA1_BLOCK_SIZE 64
#define SHA1_DIGEST_SIZE 20
#if defined(__cplusplus)
extern "C"
{
#endif
/* define an unsigned 32-bit type */
#if UINT_MAX == 0xffffffff
typedef unsigned int sha1_32t;
#elif ULONG_MAX == 0xffffffff
typedef unsigned long sha1_32t;
#else
#error Please define sha1_32t as an unsigned 32 bit type in sha2.h
#endif
/* type to hold the SHA256 context */
typedef struct
{ sha1_32t count[2];
sha1_32t hash[5];
sha1_32t wbuf[16];
} sha1_ctx;
void sha1_compile(sha1_ctx ctx[1]);
void sha1_begin(sha1_ctx ctx[1]);
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif
#endif
This diff is collapsed.
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#ifndef _SHA2_H
#define _SHA2_H
#include <limits.h>
/* Defines for suffixes to 32 and 64 bit unsigned numeric values */
#define sfx_lo(x,y) x##y
#define sfx_hi(x,y) sfx_lo(x,y)
#define n_u32(p) sfx_hi(0x##p,s_u32)
#define n_u64(p) sfx_hi(0x##p,s_u64)
/* define an unsigned 32-bit type */
#if UINT_MAX == 0xffffffff
typedef unsigned int sha2_32t;
#define s_u32 u
#elif ULONG_MAX == 0xffffffff
typedef unsigned long sha2_32t;
#define s_u32 ul
#else
#error Please define sha2_32t as an unsigned 32 bit type in sha2.h
#endif
/* define an unsigned 64-bit type */
#if _MSC_VER < 1300
typedef unsigned __int64 sha2_64t;
#define s_u64 ui64
#elif ULONG_MAX == 0xffffffffffffffff
typedef unsigned long sha2_64t;
#define s_u64 ul
#elif ULONG_MAX == 0xffffffff
typedef unsigned long long sha2_64t; /* a somewhat dangerous guess */
#define s_u64 ull
#else
#error Please define sha2_64t as an unsigned 64 bit type in sha2.h
#endif
#if defined(__cplusplus)
extern "C"
{
#endif
#define SHA256_DIGEST_SIZE 32
#define SHA384_DIGEST_SIZE 48
#define SHA512_DIGEST_SIZE 64
#define SHA256_BLOCK_SIZE 64
#define SHA384_BLOCK_SIZE 128
#define SHA512_BLOCK_SIZE 128
#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
#define SHA2_GOOD 0
#define SHA2_BAD 1
/* type to hold the SHA256 context */
typedef struct
{ sha2_32t count[2];
sha2_32t hash[8];
sha2_32t wbuf[16];
} sha256_ctx;
/* type to hold the SHA384/512 context */
typedef struct
{ sha2_64t count[2];
sha2_64t hash[8];
sha2_64t wbuf[16];
} sha512_ctx;
typedef sha512_ctx sha384_ctx;
/* type to hold a SHA2 context (256/384/512) */
typedef struct
{ union
{ sha256_ctx ctx256[1];
sha512_ctx ctx512[1];
} uu[1];
sha2_32t sha2_len;
} sha2_ctx;
#ifndef SHA2_DLL /* implement normal or DLL functions */
#define sha2_void void
#define sha2_int int
#else
#define sha2_void void __declspec(dllexport) _stdcall
#define sha2_int int __declspec(dllexport) _stdcall
#endif
sha2_void sha256_compile(sha256_ctx ctx[1]);
sha2_void sha512_compile(sha512_ctx ctx[1]);
sha2_void sha256_begin(sha256_ctx ctx[1]);
sha2_void sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]);
sha2_void sha256_end(unsigned char hval[], sha256_ctx ctx[1]);
sha2_void sha256(unsigned char hval[], const unsigned char data[], unsigned long len);
sha2_void sha384_begin(sha384_ctx ctx[1]);
#define sha384_hash sha512_hash
sha2_void sha384_end(unsigned char hval[], sha384_ctx ctx[1]);
sha2_void sha384(unsigned char hval[], const unsigned char data[], unsigned long len);
sha2_void sha512_begin(sha512_ctx ctx[1]);
sha2_void sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]);
sha2_void sha512_end(unsigned char hval[], sha512_ctx ctx[1]);
sha2_void sha512(unsigned char hval[], const unsigned char data[], unsigned long len);
sha2_int sha2_begin(unsigned long size, sha2_ctx ctx[1]);
sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]);
sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
sha2_int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment