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
master
hybrid 2009-12-01 01:45:55 +00:00
parent cbe11eae65
commit 2c72efbab4
25 changed files with 5546 additions and 24 deletions

34
doc/aesGladman.txt Normal file
View File

@ -0,0 +1,34 @@
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.
---------------------------------------------------------------------------
*/

View File

@ -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,39 +485,128 @@ 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
{
return createLimitReadFile(Files[index].FullName, File, e.Offset, e.header.DataDescriptor.CompressedSize);
if (decrypted)
return decrypted;
else
return createLimitReadFile(Files[index].FullName, File, e.Offset, e.header.DataDescriptor.CompressedSize);
}
case 8:
{
#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)
{
swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() );
os::Printer::log( buf, ELL_ERROR);
delete [] (c8*)pBuf;
return 0;
}
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 );
//memset(pcData, 0, compressedSize );
File->seek(e.Offset);
File->read(pcData, compressedSize );
}
// Setup the inflate stream.
z_stream stream;
@ -506,7 +631,10 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
inflateEnd(&stream);
}
delete[] pcData;
if (decrypted)
decrypted->drop();
else
delete[] pcData;
if (err != Z_OK)
{

View File

@ -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,

View File

@ -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
@ -3107,14 +3203,6 @@
RelativePath="CMountPointReader.h"
>
</File>
<File
RelativePath="CPakReader.cpp"
>
</File>
<File
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CNPKReader.cpp"
>
@ -3123,6 +3211,14 @@
RelativePath="CNPKReader.h"
>
</File>
<File
RelativePath="CPakReader.cpp"
>
</File>
<File
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CReadFile.cpp"
>

View 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

View File

@ -0,0 +1,25 @@
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

View File

@ -0,0 +1,155 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,311 @@
/*
---------------------------------------------------------------------------
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 code for implementing encryption and decryption
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
can optionally be replaced by code written in assembler using NASM. For
further details see the file aesopt.h
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
#define so(y,x,c) word_out(y, c, s(x,c))
#if defined(ARRAYS)
#define locals(y,x) x[4],y[4]
#else
#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
#endif
#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
s(y,2) = s(x,2); s(y,3) = s(x,3);
#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
#if defined(ENCRYPTION) && !defined(AES_ASM)
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined(_MSC_VER)
#pragma optimize( "s", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define fwd_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
#if defined(FT4_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
#elif defined(FT1_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
#else
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
#endif
#if defined(FL4_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
#elif defined(FL1_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
#else
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
#endif
aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1])
{ aes_32t locals(b0, b1);
const aes_32t *kp = cx->ks;
#ifdef dec_fmvars
dec_fmvars; /* declare variables for fwd_mcol() if needed */
#endif
aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14);
#ifdef AES_ERR_CHK
if( (nr != 10 || !(kp[0] | kp[3] | kp[4]))
&& (nr != 12 || !(kp[0] | kp[5] | kp[6]))
&& (nr != 14 || !(kp[0] | kp[7] | kp[8])) )
return aes_error;
#endif
state_in(b0, in_blk, kp);
#if (ENC_UNROLL == FULL)
switch(nr)
{
case 14:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 12:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 10:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
}
#else
#if (ENC_UNROLL == PARTIAL)
{ aes_32t rnd;
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
kp += N_COLS;
round(fwd_rnd, b0, b1, kp);
}
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
#else
{ aes_32t rnd;
for(rnd = 0; rnd < nr - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp += N_COLS;
round(fwd_lrnd, b0, b1, kp);
}
#endif
state_out(out_blk, b0);
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(DECRYPTION) && !defined(AES_ASM)
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined(_MSC_VER)
#pragma optimize( "t", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define inv_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
#if defined(IT4_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
#elif defined(IT1_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
#else
#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
#endif
#if defined(IL4_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
#elif defined(IL1_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
#else
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
#endif
aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1])
{ aes_32t locals(b0, b1);
#ifdef dec_imvars
dec_imvars; /* declare variables for inv_mcol() if needed */
#endif
aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14);
const aes_32t *kp = cx->ks + nr * N_COLS;
#ifdef AES_ERR_CHK
if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4]))
&& (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6]))
&& (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) )
return aes_error;
#endif
state_in(b0, in_blk, kp);
#if (DEC_UNROLL == FULL)
switch(nr)
{
case 14:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
kp -= 2 * N_COLS;
case 12:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
kp -= 2 * N_COLS;
case 10:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
round(inv_rnd, b1, b0, kp - 3 * N_COLS);
round(inv_rnd, b0, b1, kp - 4 * N_COLS);
round(inv_rnd, b1, b0, kp - 5 * N_COLS);
round(inv_rnd, b0, b1, kp - 6 * N_COLS);
round(inv_rnd, b1, b0, kp - 7 * N_COLS);
round(inv_rnd, b0, b1, kp - 8 * N_COLS);
round(inv_rnd, b1, b0, kp - 9 * N_COLS);
round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
}
#else
#if (DEC_UNROLL == PARTIAL)
{ aes_32t rnd;
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
{
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
kp -= N_COLS;
round(inv_rnd, b0, b1, kp);
}
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
#else
{ aes_32t rnd;
for(rnd = 0; rnd < nr - 1; ++rnd)
{
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp -= N_COLS;
round(inv_lrnd, b0, b1, kp);
}
#endif
state_out(out_blk, b0);
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,463 @@
/*
---------------------------------------------------------------------------
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 code for implementing the key schedule for AES
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
for further details including optimisation.
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* Initialise the key schedule from the user supplied key. The key
length can be specified in bytes, with legal values of 16, 24
and 32, or in bits, with legal values of 128, 192 and 256. These
values correspond with Nk values of 4, 6 and 8 respectively.
The following macros implement a single cycle in the key
schedule generation process. The number of cycles needed
for each cx->n_col and nk value is:
nk = 4 5 6 7 8
------------------------------
cx->n_col = 4 10 9 8 7 7
cx->n_col = 5 14 11 10 9 9
cx->n_col = 6 19 15 12 11 11
cx->n_col = 7 21 19 16 13 14
cx->n_col = 8 29 23 19 17 14
*/
#define ke4(k,i) \
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
}
#define kel4(k,i) \
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
}
#define ke6(k,i) \
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
}
#define kel6(k,i) \
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
}
#define ke8(k,i) \
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
}
#define kel8(k,i) \
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
}
#if defined(ENCRYPTION_KEY_SCHEDULE)
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[4];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < ((11 * N_COLS - 1) / 4); ++i)
ke4(cx->ks, i);
}
#else
ke4(cx->ks, 0); ke4(cx->ks, 1);
ke4(cx->ks, 2); ke4(cx->ks, 3);
ke4(cx->ks, 4); ke4(cx->ks, 5);
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8); kel4(cx->ks, 9);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45] = 0;
cx->ks[52] = 10;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[6];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
ke6(cx->ks, i);
}
#else
ke6(cx->ks, 0); ke6(cx->ks, 1);
ke6(cx->ks, 2); ke6(cx->ks, 3);
ke6(cx->ks, 4); ke6(cx->ks, 5);
ke6(cx->ks, 6); kel6(cx->ks, 7);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45];
cx->ks[52] = 12;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[8];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
cx->ks[6] = ss[6] = word_in(in_key, 6);
cx->ks[7] = ss[7] = word_in(in_key, 7);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
ke8(cx->ks, i);
}
#else
ke8(cx->ks, 0); ke8(cx->ks, 1);
ke8(cx->ks, 2); ke8(cx->ks, 3);
ke8(cx->ks, 4); ke8(cx->ks, 5);
kel8(cx->ks, 6);
#endif
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_VAR)
aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1])
{
switch(key_len)
{
#ifdef AES_ERR_CHK
case 16: case 128: return aes_encrypt_key128(in_key, cx);
case 24: case 192: return aes_encrypt_key192(in_key, cx);
case 32: case 256: return aes_encrypt_key256(in_key, cx);
default: return aes_error;
#else
case 16: case 128: aes_encrypt_key128(in_key, cx); return;
case 24: case 192: aes_encrypt_key192(in_key, cx); return;
case 32: case 256: aes_encrypt_key256(in_key, cx); return;
#endif
}
}
#endif
#endif
#if defined(DECRYPTION_KEY_SCHEDULE)
#if DEC_ROUND == NO_TABLES
#define ff(x) (x)
#else
#define ff(x) inv_mcol(x)
#ifdef dec_imvars
#define d_vars dec_imvars
#endif
#endif
#if 1
#define kdf4(k,i) \
{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
}
#define kdl4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
}
#else
#define kdf4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
}
#define kdl4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
}
#endif
#define kdf6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
}
#define kd6(k,i) \
{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
}
#define kdl6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
}
#define kdf8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
}
#define kd8(k,i) \
{ aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
g = ls_box(ss[3],0); \
ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
}
#define kdl8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
}
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[5];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (11 * N_COLS - 1) / 4; ++i)
ke4(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 10 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
kdf4(cx->ks, 0); kd4(cx->ks, 1);
kd4(cx->ks, 2); kd4(cx->ks, 3);
kd4(cx->ks, 4); kd4(cx->ks, 5);
kd4(cx->ks, 6); kd4(cx->ks, 7);
kd4(cx->ks, 8); kdl4(cx->ks, 9);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45] = 0;
cx->ks[52] = 10;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[7];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
{ aes_32t i;
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
ke6(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 12 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
kdf6(cx->ks, 0); kd6(cx->ks, 1);
kd6(cx->ks, 2); kd6(cx->ks, 3);
kd6(cx->ks, 4); kd6(cx->ks, 5);
kd6(cx->ks, 6); kdl6(cx->ks, 7);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45];
cx->ks[52] = 12;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[8];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
cx->ks[6] = ss[6] = word_in(in_key, 6);
cx->ks[7] = ss[7] = word_in(in_key, 7);
{ aes_32t i;
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
ke8(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 14 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
cx->ks[6] = ff(ss[6] = word_in(in_key, 6));
cx->ks[7] = ff(ss[7] = word_in(in_key, 7));
kdf8(cx->ks, 0); kd8(cx->ks, 1);
kd8(cx->ks, 2); kd8(cx->ks, 3);
kd8(cx->ks, 4); kd8(cx->ks, 5);
kdl8(cx->ks, 6);
#endif
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_VAR)
aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
{
switch(key_len)
{
#ifdef AES_ERR_CHK
case 16: case 128: return aes_decrypt_key128(in_key, cx);
case 24: case 192: return aes_decrypt_key192(in_key, cx);
case 32: case 256: return aes_decrypt_key256(in_key, cx);
default: return aes_error;
#else
case 16: case 128: aes_decrypt_key128(in_key, cx); return;
case 24: case 192: aes_decrypt_key192(in_key, cx); return;
case 32: case 256: aes_decrypt_key256(in_key, cx); return;
#endif
}
}
#endif
#endif
#if defined(__cplusplus)
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,232 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,321 @@
/*-------------------------------------------------------------*/
/*--- 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 ---*/
/*-------------------------------------------------------------*/

View File

@ -0,0 +1,145 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,122 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,145 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,102 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,431 @@
/*
---------------------------------------------------------------------------
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: 18th November 2008
A simple file encryption application based on
a. RFC2898 for key derivation (using HMAC-SHA1)
b. AES in CTR mode for encryption
c. HMAC-SHA1 for authentication
d. A Random Data Pool based on Peter Gutmann's ideas
e. compression using BZIP2
The command line is:
encfile password infile
If the last file name extension is ".enc", the file is assumed to be an
encrypted file and an attempt is made to decrypt it with the given password,
writing the output to a file with the same name except for the ".enc" on the
end. Otherwise the file is encrypted with the given password and the output
is written to a file with the same name except that ".enc" is added on the
end.
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <windows.h>
#include "bzlib.h"
#include "fileenc.h"
#include "prng.h"
/* local error values */
#define ERROR_USAGE 1
#define ERROR_PASSWORD_LENGTH 2
#define ERROR_OUT_OF_MEMORY 3
#define ERROR_INPUT_FILE 4
#define ERROR_OUTPUT_FILE 5
#define ERROR_BAD_PASSWORD 6
#define ERROR_BAD_AUTHENTICATION 7
/* these values are for reporting BZIP2 errors (7 - bzip2_error_value) */
#define ERROR_BZ_SEQUENCE 8
#define ERROR_BZ_PARAM 9
#define ERROR_BZ_MEM 10
#define ERROR_BZ_DATA 11
#define ERROR_BZ_DATA_MAGIC 12
#define ERROR_BZ_IO 13
#define ERROR_BZ_UNEXPECTED_EOF 14
#define ERROR_BZ_OUTBUFF_FULL 15
#define ERROR_BZ_CONFIG_ERROR 16
/* the size of the local buffers for file handling */
#define FILE_BUF_SIZE 1024
/* error messages for user output */
char *err_string[] =
{
"\nusage: encfile password infile outfile\n",
"\npassword is too short\n",
"\nmemory allocation has failed\n",
"\ncannot open the input file (%s)\n",
"\ncannot open the output file (%s)\n",
"\nbad password\n",
"\ndamaged file or incorrect password\n",
"\nBZIP2 sequence error\n",
"\nBZIP2 parameter error\n",
"\nBZIP2 memory error\n",
"\nBZIP2 data error\n",
"\nBZIP2 magic data error\n",
"\nBZIP2 input/output error\n",
"\nBZIP2 unexpected end of file error\n",
"\nBZIP2 full output buffer error\n",
"\nBZIP2 configuration error\n"
};
/* simple entropy collection function that uses the fast timer */
/* since we are not using the random pool for generating secret */
/* keys we don't need to be too worried about the entropy quality */
/* Modified in 2008 to add revised entropy generation courtesy of */
/* WinZip Inc. This code now performs the following sequence of */
/* entropy generation operations on sequential calls: */
/* */
/* - the current 8-byte Windows performance counter value */
/* - an 8-byte representation of the current date/time */
/* - an 8-byte value built from the current process ID */
/* and thread ID */
/* - all subsequent calls return the then-current 8-byte */
/* performance counter value */
int entropy_fun(unsigned char buf[], unsigned int len)
{ unsigned __int64 pentium_tsc[1];
unsigned int i;
static unsigned int num = 0;
switch(num)
{
/* use a value that is unlikely to repeat across system reboots */
case 1:
++num;
GetSystemTimeAsFileTime((FILETIME *)pentium_tsc);
break;
/* use a value that distinguishes between different instances of this */
/* code that might be running on different processors at the same time */
case 2:
++num;
{ unsigned __int32 processtest = GetCurrentProcessId();
unsigned __int32 threadtest = GetCurrentThreadId();
pentium_tsc[0] = processtest;
pentium_tsc[0] = (pentium_tsc[0] << 32) + threadtest;
}
break;
/* use a rapidly-changing value -- check QueryPerformanceFrequency() */
/* to ensure that QueryPerformanceCounter() will work */
case 0:
++num;
default:
QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc);
break;
}
for(i = 0; i < 8 && i < len; ++i)
buf[i] = ((unsigned char*)pentium_tsc)[i];
return i;
}
/* this is the main file encryption/decryption routine code */
int main(int argc, char *argv[])
{ FILE *inf, *outf;
unsigned char buf[FILE_BUF_SIZE], buf2[FILE_BUF_SIZE];
unsigned char tmp_buf1[16], tmp_buf2[16], salt[16], *fname = 0, *cp;
fcrypt_ctx zcx[1];
bz_stream bz_ctx[1]; /* the bzip2 compression context */
int len, flen, err = 0;
unsigned char mode;
if(argc != 3) /* the command line is bad */
{
err = ERROR_USAGE; goto error_0;
}
len = (int)strlen(argv[1]);
if(len < 8) /* password is too short */
{
err = ERROR_PASSWORD_LENGTH; goto error_0;
}
/* set the key length based on password length assuming that there */
/* are about 4 bits of entropy per password character (optimistic!) */
/* (the key length and other mode dependent parameter values are */
/* set using macros defined in fileenc.h) */
mode = (len < 32 ? 1 : len < 48 ? 2 : 3);
/* save input file name to a temporary memory area with extra space */
/* for the extension ".enc" to be added */
fname = (unsigned char*)malloc(strlen(argv[2]) + 5);
if(fname == NULL)
{
err = ERROR_OUT_OF_MEMORY; goto error_0;
}
/* open the input file for binary input */
strcpy(fname, argv[2]);
if((inf = fopen(fname, "rb")) == NULL)
{
err = ERROR_INPUT_FILE; goto error_1;
}
/* if the file name extension is ".enc" assume this is an encrypted */
/* file */
if((cp = strrchr(fname, '.')) && strcmp(cp, ".enc") == 0)
{
*cp = 0;
mode |= 4; /* hence signal decryption */
}
else /* otherwise add ".enc" to file name to */
strcat(fname, ".enc"); /* mark the file as an encrypted one */
/* open the output file for binary output */
if((outf = fopen(fname, "wb")) == NULL)
{
err = ERROR_OUTPUT_FILE; goto error_2;
}
/* use BZIP2's default memory allocation */
bz_ctx->bzalloc = NULL;
bz_ctx->bzfree = NULL;
bz_ctx->opaque = NULL;
if(!(mode & 4)) /* perfrom an encryption operation */
{
prng_ctx rng[1]; /* the context for the random number pool */
prng_init(entropy_fun, rng); /* initialise RNG, */
prng_rand(salt, SALT_LENGTH(mode), rng); /* the salt and */
err = BZ2_bzCompressInit(bz_ctx, 5, 0, 0); /* compression */
if(err != BZ_OK)
{
err = 7 - err; goto error_2;
}
/* write the salt value to the output file */
fwrite(salt, sizeof(unsigned char), SALT_LENGTH(mode), outf);
/* initialise encryption and authentication */
#ifdef PASSWORD_VERIFIER
fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, tmp_buf1, zcx);
/* write the password verifier (if used) */
fwrite(tmp_buf1, sizeof(unsigned char), PWD_VER_LENGTH, outf);
#else
fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, zcx);
#endif
/* compress, encrypt and authenticate file */
while(len = (int)fread(buf, sizeof(unsigned char), FILE_BUF_SIZE, inf))
{
bz_ctx->next_in = buf; /* compress from buf to buf2 */
bz_ctx->avail_in = len;
while(bz_ctx->avail_in > 0)
{ /* pass all input to compressor */
bz_ctx->next_out = buf2;
bz_ctx->avail_out = FILE_BUF_SIZE;
err = BZ2_bzCompress(bz_ctx, BZ_RUN);
if(err != BZ_RUN_OK) /* check for errors */
{
err = 7 - err; goto error_2;
}
/* if there is output, encrypt, authenticate and */
/* write it to the output file */
if(len = bz_ctx->next_out - buf2)
{
fcrypt_encrypt(buf2, len, zcx);
len = fwrite(buf2, sizeof(unsigned char), len, outf);
}
}
}
/* finish the compression operation */
bz_ctx->next_in = NULL;
bz_ctx->avail_in = 0;
do
{ /* load output buffer from compressor */
bz_ctx->next_out = buf2;
bz_ctx->avail_out = FILE_BUF_SIZE;
err = BZ2_bzCompress(bz_ctx, BZ_FINISH);
if(err != BZ_FINISH_OK && err != BZ_STREAM_END)
{
err = 7 - err; goto error_2;
}
/* encrypt, authenticate amd write any */
/* output to output file */
if(len = bz_ctx->next_out - buf2)
{
fcrypt_encrypt(buf2, len, zcx);
len = fwrite(buf2, sizeof(unsigned char), len, outf);
}
}
while /* until the compressor end signal */
(err != BZ_STREAM_END);
if(BZ2_bzCompressEnd(bz_ctx) != BZ_OK)
{
err = 7 - err; goto error_2;
}
else
err = 0;
/* write the MAC */
fcrypt_end(tmp_buf1, zcx);
fwrite(tmp_buf1, sizeof(unsigned char), MAC_LENGTH(mode), outf);
/* and close random pool */
prng_end(rng);
}
else /* perfrom a decryption operation */
{
/* we need to know the file length to avoid reading the MAC */
fseek(inf, 0, SEEK_END);
flen = ftell(inf);
fseek(inf, 0, SEEK_SET);
mode &= 3;
/* initialise decryption, authentication and decompression */
err = BZ2_bzDecompressInit(bz_ctx, 0, 0); /* decompression */
if(err != BZ_OK)
{
err = 7 - err; goto error_2;
}
/* recover the password salt */
fread(salt, sizeof(unsigned char), SALT_LENGTH(mode), inf); flen -= SALT_LENGTH(mode);
#ifdef PASSWORD_VERIFIER
fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, tmp_buf2, zcx);
/* recover the password verifier (if used) */
fread(tmp_buf1, sizeof(unsigned char), PWD_VER_LENGTH, inf); flen -= PWD_VER_LENGTH;
/* check password verifier */
if(memcmp(tmp_buf1, tmp_buf2, PWD_VER_LENGTH))
{
err = ERROR_BAD_PASSWORD; fclose(outf); goto error_2;
}
#else
fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, zcx);
#endif
flen -= MAC_LENGTH(mode); /* avoid reading the MAC */
len = (flen < FILE_BUF_SIZE ? flen : FILE_BUF_SIZE);
/* decrypt the file */
while(len = (int)fread(buf, sizeof(unsigned char), len, inf))
{
/* decrypt a block */
flen -= len;
fcrypt_decrypt(buf, len, zcx);
bz_ctx->next_in = buf;
bz_ctx->avail_in = len;
while(bz_ctx->avail_in > 0)
{ /* pass all input to compressor */
bz_ctx->next_out = buf2;
bz_ctx->avail_out = FILE_BUF_SIZE;
err = BZ2_bzDecompress(bz_ctx);
if(err != BZ_OK && err != BZ_STREAM_END)
{
err = 7 - err; goto error_2;
}
/* write any output from decompressor */
if(len = bz_ctx->next_out - buf2)
fwrite(buf2, sizeof(unsigned char), len, outf);
}
len = (flen < FILE_BUF_SIZE ? flen : FILE_BUF_SIZE);
}
/* complete the decompression operation and write any */
/* output that results */
bz_ctx->next_in = NULL;
bz_ctx->avail_in = 0;
while(err != BZ_STREAM_END)
{
bz_ctx->next_out = buf2;
bz_ctx->avail_out = FILE_BUF_SIZE;
err = BZ2_bzDecompress(bz_ctx);
if(err != BZ_OK && err != BZ_STREAM_END)
{
err = 7 - err; goto error_2;
}
if(len = bz_ctx->next_out - buf2)
fwrite(buf2, sizeof(unsigned char), len, outf);
}
if(BZ2_bzDecompressEnd(bz_ctx) != BZ_OK)
{
err = 7 - err; goto error_2;
}
else
err = 0;
/* calculate the MAC value */
fcrypt_end(tmp_buf2, zcx);
/* now read the stored MAC value */
fread(tmp_buf1, sizeof(unsigned char), MAC_LENGTH(mode), inf);
/* compare the stored and calculated MAC values */
if(memcmp(tmp_buf1, tmp_buf2, MAC_LENGTH(mode)))
{ /* authentication failed */
err = ERROR_BAD_AUTHENTICATION;
fclose(outf);
/* delete the (bad) output file */
remove(fname);
goto error_2;
}
}
fclose(outf);
error_2:
fclose(inf);
error_1:
error_0:
if(err)
printf(err_string[err - 1], fname);
if(fname != 0)
free(fname);
return -err;
}

View File

@ -0,0 +1,155 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,82 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,194 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,58 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,323 @@
/*
---------------------------------------------------------------------------
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 a byte oriented version of SHA1 that operates on arrays of bytes
stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
*/
#include <string.h> /* for memcpy() etc. */
#include <stdlib.h> /* for _lrotl with VC++ */
#include "sha1.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/*
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the order in which bytes are packed into such words.
The following block of code is an attempt to capture the most obvious
ways in which various environemnts specify their endian definitions.
It may well fail, in which case the definitions will need to be set by
editing at the points marked **** EDIT HERE IF NECESSARY **** below.
*/
/* PLATFORM SPECIFIC INCLUDES */
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 )
# include <machine/endian.h>
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# include <endian.h>
# include <byteswap.h>
#elif defined( linux )
# include <endian.h>
#endif
/* BYTE ORDER IN 32-BIT WORDS
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the byte order of the target machine. The following
block of code is an attempt to capture the most obvious ways in which
various environemnts define byte order. It may well fail, in which case
the definitions will need to be set by editing at the points marked
**** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for
some of these defines (from cryptlib).
*/
#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS )
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#endif
#if defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __TANDEM ) || defined( THINK_C ) || defined( __VMCMS__ )
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#endif
/* if the platform is still not known, try to find its byte order */
/* from commonly used definitions in the headers included earlier */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
# if defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
# if defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)
# if defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __LITTLE_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#else
#error Please edit sha1.c (line 141 or 144) to set the platform byte order
#endif
#endif
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
#if (PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN)
#define swap_b32(x) (x)
#elif defined(bswap_32)
#define swap_b32(x) bswap_32(x)
#else
#define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00))
#endif
#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
#if 1
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* Discovered Rich Schroeppel and Colin Plumb */
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
#endif
/* A normal version as set out in the FIPS */
#define rnd(f,k) \
t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
e = d; d = c; c = rotl32(b, 30); b = t
void sha1_compile(sha1_ctx ctx[1])
{ sha1_32t w[80], i, a, b, c, d, e, t;
/* note that words are compiled from the buffer into 32-bit */
/* words in big-endian order so an order reversal is needed */
/* here on little endian machines */
for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
w[i] = swap_b32(ctx->wbuf[i]);
for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
a = ctx->hash[0];
b = ctx->hash[1];
c = ctx->hash[2];
d = ctx->hash[3];
e = ctx->hash[4];
for(i = 0; i < 20; ++i)
{
rnd(ch, 0x5a827999);
}
for(i = 20; i < 40; ++i)
{
rnd(parity, 0x6ed9eba1);
}
for(i = 40; i < 60; ++i)
{
rnd(maj, 0x8f1bbcdc);
}
for(i = 60; i < 80; ++i)
{
rnd(parity, 0xca62c1d6);
}
ctx->hash[0] += a;
ctx->hash[1] += b;
ctx->hash[2] += c;
ctx->hash[3] += d;
ctx->hash[4] += e;
}
void sha1_begin(sha1_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
ctx->hash[0] = 0x67452301;
ctx->hash[1] = 0xefcdab89;
ctx->hash[2] = 0x98badcfe;
ctx->hash[3] = 0x10325476;
ctx->hash[4] = 0xc3d2e1f0;
}
/* SHA1 hash data in an array of bytes into hash buffer and */
/* call the hash_compile function as required. */
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK),
space = SHA1_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks if possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
sha1_compile(ctx);
}
/*lint -e{803} conceivable data overrun */
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA1 final padding and digest calculation */
#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
static sha1_32t mask[4] =
{ 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
static sha1_32t bits[4] =
{ 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
#else
static sha1_32t mask[4] =
{ 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
static sha1_32t bits[4] =
{ 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
#endif
void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK);
/* mask out the rest of any partial 32-bit word and then set */
/* the next byte to 0x80. On big-endian machines any bytes in */
/* the buffer will be at the top end of 32 bit words, on little */
/* endian machines they will be at the bottom. Hence the AND */
/* and OR masks above are reversed for little endian systems */
/* Note that we can always add the first padding byte at this */
/* point because the buffer always has at least one empty slot */
ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & mask[i & 3]) | bits[i & 3];
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space pad and empty the buffer */
if(i > SHA1_BLOCK_SIZE - 9)
{
if(i < 60) ctx->wbuf[15] = 0;
sha1_compile(ctx);
i = 0;
}
else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while(i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* assemble the eight byte counter in in big-endian format */
ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29));
ctx->wbuf[15] = swap_b32(ctx->count[0] << 3);
sha1_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
}
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha1_ctx cx[1];
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
}
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,76 @@
/*
---------------------------------------------------------------------------
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

View File

@ -0,0 +1,713 @@
/*
---------------------------------------------------------------------------
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 a byte oriented version of SHA2 that operates on arrays of bytes
stored in memory. This code implements sha256, sha384 and sha512 but the
latter two functions rely on efficient 64-bit integer operations that
may not be very efficient on 32-bit machines
The sha256 functions use a type 'sha256_ctx' to hold details of the
current hash state and uses the following three calls:
void sha256_begin(sha256_ctx ctx[1])
void sha256_hash(const unsigned char data[],
unsigned long len, sha256_ctx ctx[1])
void sha256_end(unsigned char hval[], sha256_ctx ctx[1])
The first subroutine initialises a hash computation by setting up the
context in the sha256_ctx context. The second subroutine hashes 8-bit
bytes from array data[] into the hash state withinh sha256_ctx context,
the number of bytes to be hashed being given by the the unsigned long
integer len. The third subroutine completes the hash calculation and
places the resulting digest value in the array of 8-bit bytes hval[].
The sha384 and sha512 functions are similar and use the interfaces:
void sha384_begin(sha384_ctx ctx[1]);
void sha384_hash(const unsigned char data[],
unsigned long len, sha384_ctx ctx[1]);
void sha384_end(unsigned char hval[], sha384_ctx ctx[1]);
void sha512_begin(sha512_ctx ctx[1]);
void sha512_hash(const unsigned char data[],
unsigned long len, sha512_ctx ctx[1]);
void sha512_end(unsigned char hval[], sha512_ctx ctx[1]);
In addition there is a function sha2 that can be used to call all these
functions using a call with a hash length parameter as follows:
int sha2_begin(unsigned long len, sha2_ctx ctx[1]);
void sha2_hash(const unsigned char data[],
unsigned long len, sha2_ctx ctx[1]);
void sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
My thanks to Erik Andersen <andersen@codepoet.org> for testing this code
on big-endian systems and for his assistance with corrections
*/
/* define the hash functions that you need */
#define SHA_2 /* for dynamic hash length */
#define SHA_256
#define SHA_384
#define SHA_512
#include <string.h> /* for memcpy() etc. */
#include <stdlib.h> /* for _lrotr with VC++ */
#include "sha2.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* PLATFORM SPECIFIC INCLUDES */
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 )
# include <machine/endian.h>
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# include <endian.h>
# include <byteswap.h>
#elif defined( linux )
# include <endian.h>
#endif
/* BYTE ORDER IN 32-BIT WORDS
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the byte order of the target machine. The following
block of code is an attempt to capture the most obvious ways in which
various environemnts define byte order. It may well fail, in which case
the definitions will need to be set by editing at the points marked
**** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for
some of these defines (from cryptlib).
*/
#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS )
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#endif
#if defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __TANDEM ) || defined( THINK_C ) || defined( __VMCMS__ )
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#endif
/* if the platform is still not known, try to find its byte order */
/* from commonly used definitions in the headers included earlier */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
# if defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
# if defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)
# if defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif !defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __LITTLE_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)
# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
# endif
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#else
#error Please edit sha2.c (line 180 or 183) to set the platform byte order
#endif
#endif
#ifdef _MSC_VER
#pragma intrinsic(memcpy)
#endif
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
#if !defined(bswap_32)
#define bswap_32(x) (rotr32((x), 24) & 0x00ff00ff | rotr32((x), 8) & 0xff00ff00)
#endif
#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
#define SWAP_BYTES
#else
#undef SWAP_BYTES
#endif
#if defined(SHA_2) || defined(SHA_256)
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
#if defined(SWAP_BYTES)
#define bsw_32(p,n) { int _i = (n); while(_i--) p[_i] = bswap_32(p[_i]); }
#else
#define bsw_32(p,n)
#endif
/* SHA256 mixing function definitions */
#if 0
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
#endif
#define s256_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
#define s256_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
#define g256_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
#define g256_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
/* rotated SHA256 round definition. Rather than swapping variables as in */
/* FIPS-180, different variables are 'rotated' on each round, returning */
/* to their starting positions every eight rounds */
#define h2(i) p[i & 15] += \
g256_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g256_0(p[(i + 1) & 15])
#define h2_cycle(i,j) \
v[(7 - i) & 7] += (j ? h2(i) : p[i & 15]) + k256[i + j] \
+ s256_1(v[(4 - i) & 7]) + ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \
v[(3 - i) & 7] += v[(7 - i) & 7]; \
v[(7 - i) & 7] += s256_0(v[(0 - i) & 7]) + maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7])
/* SHA256 mixing data */
const sha2_32t k256[64] =
{ n_u32(428a2f98), n_u32(71374491), n_u32(b5c0fbcf), n_u32(e9b5dba5),
n_u32(3956c25b), n_u32(59f111f1), n_u32(923f82a4), n_u32(ab1c5ed5),
n_u32(d807aa98), n_u32(12835b01), n_u32(243185be), n_u32(550c7dc3),
n_u32(72be5d74), n_u32(80deb1fe), n_u32(9bdc06a7), n_u32(c19bf174),
n_u32(e49b69c1), n_u32(efbe4786), n_u32(0fc19dc6), n_u32(240ca1cc),
n_u32(2de92c6f), n_u32(4a7484aa), n_u32(5cb0a9dc), n_u32(76f988da),
n_u32(983e5152), n_u32(a831c66d), n_u32(b00327c8), n_u32(bf597fc7),
n_u32(c6e00bf3), n_u32(d5a79147), n_u32(06ca6351), n_u32(14292967),
n_u32(27b70a85), n_u32(2e1b2138), n_u32(4d2c6dfc), n_u32(53380d13),
n_u32(650a7354), n_u32(766a0abb), n_u32(81c2c92e), n_u32(92722c85),
n_u32(a2bfe8a1), n_u32(a81a664b), n_u32(c24b8b70), n_u32(c76c51a3),
n_u32(d192e819), n_u32(d6990624), n_u32(f40e3585), n_u32(106aa070),
n_u32(19a4c116), n_u32(1e376c08), n_u32(2748774c), n_u32(34b0bcb5),
n_u32(391c0cb3), n_u32(4ed8aa4a), n_u32(5b9cca4f), n_u32(682e6ff3),
n_u32(748f82ee), n_u32(78a5636f), n_u32(84c87814), n_u32(8cc70208),
n_u32(90befffa), n_u32(a4506ceb), n_u32(bef9a3f7), n_u32(c67178f2),
};
/* SHA256 initialisation data */
const sha2_32t i256[8] =
{
n_u32(6a09e667), n_u32(bb67ae85), n_u32(3c6ef372), n_u32(a54ff53a),
n_u32(510e527f), n_u32(9b05688c), n_u32(1f83d9ab), n_u32(5be0cd19)
};
sha2_void sha256_begin(sha256_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i256, 8 * sizeof(sha2_32t));
}
/* Compile 64 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream placed in this */
/* buffer will now go to the high end of words on BOTH big */
/* and little endian systems */
sha2_void sha256_compile(sha256_ctx ctx[1])
{ sha2_32t v[8], j, *p = ctx->wbuf;
memcpy(v, ctx->hash, 8 * sizeof(sha2_32t));
for(j = 0; j < 64; j += 16)
{
h2_cycle( 0, j); h2_cycle( 1, j); h2_cycle( 2, j); h2_cycle( 3, j);
h2_cycle( 4, j); h2_cycle( 5, j); h2_cycle( 6, j); h2_cycle( 7, j);
h2_cycle( 8, j); h2_cycle( 9, j); h2_cycle(10, j); h2_cycle(11, j);
h2_cycle(12, j); h2_cycle(13, j); h2_cycle(14, j); h2_cycle(15, j);
}
ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; ctx->hash[6] += v[6]; ctx->hash[7] += v[7];
}
/* SHA256 hash data in an array of bytes into hash buffer */
/* and call the hash_compile function as required. */
sha2_void sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1])
{ sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA256_MASK),
space = SHA256_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks while possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0;
bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2)
sha256_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA256 Final padding and digest calculation */
static sha2_32t m1[4] =
{
n_u32(00000000), n_u32(ff000000), n_u32(ffff0000), n_u32(ffffff00)
};
static sha2_32t b1[4] =
{
n_u32(80000000), n_u32(00800000), n_u32(00008000), n_u32(00000080)
};
sha2_void sha256_end(unsigned char hval[], sha256_ctx ctx[1])
{ sha2_32t i = (sha2_32t)(ctx->count[0] & SHA256_MASK);
bsw_32(ctx->wbuf, (i + 3) >> 2)
/* bytes in the buffer are now in an order in which references */
/* to 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. */
ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & m1[i & 3]) | b1[i & 3];
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space pad and empty the buffer */
if(i > SHA256_BLOCK_SIZE - 9)
{
if(i < 60) ctx->wbuf[15] = 0;
sha256_compile(ctx);
i = 0;
}
else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while(i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* the following 32-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 32-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
ctx->wbuf[15] = ctx->count[0] << 3;
sha256_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* mislaigned for 32-bit words */
for(i = 0; i < SHA256_DIGEST_SIZE; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
}
sha2_void sha256(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha256_ctx cx[1];
sha256_begin(cx); sha256_hash(data, len, cx); sha256_end(hval, cx);
}
#endif
#if defined(SHA_2) || defined(SHA_384) || defined(SHA_512)
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n)))
#if !defined(bswap_64)
#define bswap_64(x) (((sha2_64t)(bswap_32((sha2_32t)(x)))) << 32 | bswap_32((sha2_32t)((x) >> 32)))
#endif
#if defined(SWAP_BYTES)
#define bsw_64(p,n) { int _i = (n); while(_i--) p[_i] = bswap_64(p[_i]); }
#else
#define bsw_64(p,n)
#endif
/* SHA512 mixing function definitions */
#define s512_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
#define s512_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
#define g512_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
#define g512_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
/* rotated SHA512 round definition. Rather than swapping variables as in */
/* FIPS-180, different variables are 'rotated' on each round, returning */
/* to their starting positions every eight rounds */
#define h5(i) ctx->wbuf[i & 15] += \
g512_1(ctx->wbuf[(i + 14) & 15]) + ctx->wbuf[(i + 9) & 15] + g512_0(ctx->wbuf[(i + 1) & 15])
#define h5_cycle(i,j) \
v[(7 - i) & 7] += (j ? h5(i) : ctx->wbuf[i & 15]) + k512[i + j] \
+ s512_1(v[(4 - i) & 7]) + ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \
v[(3 - i) & 7] += v[(7 - i) & 7]; \
v[(7 - i) & 7] += s512_0(v[(0 - i) & 7]) + maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7])
/* SHA384/SHA512 mixing data */
const sha2_64t k512[80] =
{
n_u64(428a2f98d728ae22), n_u64(7137449123ef65cd),
n_u64(b5c0fbcfec4d3b2f), n_u64(e9b5dba58189dbbc),
n_u64(3956c25bf348b538), n_u64(59f111f1b605d019),
n_u64(923f82a4af194f9b), n_u64(ab1c5ed5da6d8118),
n_u64(d807aa98a3030242), n_u64(12835b0145706fbe),
n_u64(243185be4ee4b28c), n_u64(550c7dc3d5ffb4e2),
n_u64(72be5d74f27b896f), n_u64(80deb1fe3b1696b1),
n_u64(9bdc06a725c71235), n_u64(c19bf174cf692694),
n_u64(e49b69c19ef14ad2), n_u64(efbe4786384f25e3),
n_u64(0fc19dc68b8cd5b5), n_u64(240ca1cc77ac9c65),
n_u64(2de92c6f592b0275), n_u64(4a7484aa6ea6e483),
n_u64(5cb0a9dcbd41fbd4), n_u64(76f988da831153b5),
n_u64(983e5152ee66dfab), n_u64(a831c66d2db43210),
n_u64(b00327c898fb213f), n_u64(bf597fc7beef0ee4),
n_u64(c6e00bf33da88fc2), n_u64(d5a79147930aa725),
n_u64(06ca6351e003826f), n_u64(142929670a0e6e70),
n_u64(27b70a8546d22ffc), n_u64(2e1b21385c26c926),
n_u64(4d2c6dfc5ac42aed), n_u64(53380d139d95b3df),
n_u64(650a73548baf63de), n_u64(766a0abb3c77b2a8),
n_u64(81c2c92e47edaee6), n_u64(92722c851482353b),
n_u64(a2bfe8a14cf10364), n_u64(a81a664bbc423001),
n_u64(c24b8b70d0f89791), n_u64(c76c51a30654be30),
n_u64(d192e819d6ef5218), n_u64(d69906245565a910),
n_u64(f40e35855771202a), n_u64(106aa07032bbd1b8),
n_u64(19a4c116b8d2d0c8), n_u64(1e376c085141ab53),
n_u64(2748774cdf8eeb99), n_u64(34b0bcb5e19b48a8),
n_u64(391c0cb3c5c95a63), n_u64(4ed8aa4ae3418acb),
n_u64(5b9cca4f7763e373), n_u64(682e6ff3d6b2b8a3),
n_u64(748f82ee5defb2fc), n_u64(78a5636f43172f60),
n_u64(84c87814a1f0ab72), n_u64(8cc702081a6439ec),
n_u64(90befffa23631e28), n_u64(a4506cebde82bde9),
n_u64(bef9a3f7b2c67915), n_u64(c67178f2e372532b),
n_u64(ca273eceea26619c), n_u64(d186b8c721c0c207),
n_u64(eada7dd6cde0eb1e), n_u64(f57d4f7fee6ed178),
n_u64(06f067aa72176fba), n_u64(0a637dc5a2c898a6),
n_u64(113f9804bef90dae), n_u64(1b710b35131c471b),
n_u64(28db77f523047d84), n_u64(32caab7b40c72493),
n_u64(3c9ebe0a15c9bebc), n_u64(431d67c49c100d4c),
n_u64(4cc5d4becb3e42b6), n_u64(597f299cfc657e2a),
n_u64(5fcb6fab3ad6faec), n_u64(6c44198c4a475817)
};
/* Compile 64 bytes of hash data into SHA384/SHA512 digest value */
sha2_void sha512_compile(sha512_ctx ctx[1])
{ sha2_64t v[8];
sha2_32t j;
memcpy(v, ctx->hash, 8 * sizeof(sha2_64t));
for(j = 0; j < 80; j += 16)
{
h5_cycle( 0, j); h5_cycle( 1, j); h5_cycle( 2, j); h5_cycle( 3, j);
h5_cycle( 4, j); h5_cycle( 5, j); h5_cycle( 6, j); h5_cycle( 7, j);
h5_cycle( 8, j); h5_cycle( 9, j); h5_cycle(10, j); h5_cycle(11, j);
h5_cycle(12, j); h5_cycle(13, j); h5_cycle(14, j); h5_cycle(15, j);
}
ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; ctx->hash[6] += v[6]; ctx->hash[7] += v[7];
}
/* Compile 128 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream placed in this */
/* buffer will now go to the high end of words on BOTH big */
/* and little endian systems */
sha2_void sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1])
{ sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA512_MASK),
space = SHA512_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks while possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0;
bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3);
sha512_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA384/512 Final padding and digest calculation */
static sha2_64t m2[8] =
{
n_u64(0000000000000000), n_u64(ff00000000000000),
n_u64(ffff000000000000), n_u64(ffffff0000000000),
n_u64(ffffffff00000000), n_u64(ffffffffff000000),
n_u64(ffffffffffff0000), n_u64(ffffffffffffff00)
};
static sha2_64t b2[8] =
{
n_u64(8000000000000000), n_u64(0080000000000000),
n_u64(0000800000000000), n_u64(0000008000000000),
n_u64(0000000080000000), n_u64(0000000000800000),
n_u64(0000000000008000), n_u64(0000000000000080)
};
static void sha_end(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen)
{ sha2_32t i = (sha2_32t)(ctx->count[0] & SHA512_MASK);
bsw_64(ctx->wbuf, (i + 7) >> 3);
/* bytes in the buffer are now in an order in which references */
/* to 64-bit words will put bytes with lower addresses into the */
/* top of 64 bit words on BOTH big and little endian machines */
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. */
ctx->wbuf[i >> 3] = (ctx->wbuf[i >> 3] & m2[i & 7]) | b2[i & 7];
/* we need 17 or more empty byte positions, one for the padding */
/* byte (above) and sixteen for the length count. If there is */
/* not enough space pad and empty the buffer */
if(i > SHA512_BLOCK_SIZE - 17)
{
if(i < 120) ctx->wbuf[15] = 0;
sha512_compile(ctx);
i = 0;
}
else
i = (i >> 3) + 1;
while(i < 14)
ctx->wbuf[i++] = 0;
/* the following 64-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 64-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61);
ctx->wbuf[15] = ctx->count[0] << 3;
sha512_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for(i = 0; i < hlen; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7)));
}
#endif
#if defined(SHA_2) || defined(SHA_384)
/* SHA384 initialisation data */
const sha2_64t i384[80] =
{
n_u64(cbbb9d5dc1059ed8), n_u64(629a292a367cd507),
n_u64(9159015a3070dd17), n_u64(152fecd8f70e5939),
n_u64(67332667ffc00b31), n_u64(8eb44a8768581511),
n_u64(db0c2e0d64f98fa7), n_u64(47b5481dbefa4fa4)
};
sha2_void sha384_begin(sha384_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i384, 8 * sizeof(sha2_64t));
}
sha2_void sha384_end(unsigned char hval[], sha384_ctx ctx[1])
{
sha_end(hval, ctx, SHA384_DIGEST_SIZE);
}
sha2_void sha384(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha384_ctx cx[1];
sha384_begin(cx); sha384_hash(data, len, cx); sha384_end(hval, cx);
}
#endif
#if defined(SHA_2) || defined(SHA_512)
/* SHA512 initialisation data */
const sha2_64t i512[80] =
{
n_u64(6a09e667f3bcc908), n_u64(bb67ae8584caa73b),
n_u64(3c6ef372fe94f82b), n_u64(a54ff53a5f1d36f1),
n_u64(510e527fade682d1), n_u64(9b05688c2b3e6c1f),
n_u64(1f83d9abfb41bd6b), n_u64(5be0cd19137e2179)
};
sha2_void sha512_begin(sha512_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i512, 8 * sizeof(sha2_64t));
}
sha2_void sha512_end(unsigned char hval[], sha512_ctx ctx[1])
{
sha_end(hval, ctx, SHA512_DIGEST_SIZE);
}
sha2_void sha512(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha512_ctx cx[1];
sha512_begin(cx); sha512_hash(data, len, cx); sha512_end(hval, cx);
}
#endif
#if defined(SHA_2)
#define CTX_256(x) ((x)->uu->ctx256)
#define CTX_384(x) ((x)->uu->ctx512)
#define CTX_512(x) ((x)->uu->ctx512)
/* SHA2 initialisation */
sha2_int sha2_begin(unsigned long len, sha2_ctx ctx[1])
{ unsigned long l = len;
switch(len)
{
case 256: l = len >> 3;
case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;
memcpy(CTX_256(ctx)->hash, i256, 32); break;
case 384: l = len >> 3;
case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0;
memcpy(CTX_384(ctx)->hash, i384, 64); break;
case 512: l = len >> 3;
case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0;
memcpy(CTX_512(ctx)->hash, i512, 64); break;
default: return SHA2_BAD;
}
ctx->sha2_len = l; return SHA2_GOOD;
}
sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1])
{
switch(ctx->sha2_len)
{
case 32: sha256_hash(data, len, CTX_256(ctx)); return;
case 48: sha384_hash(data, len, CTX_384(ctx)); return;
case 64: sha512_hash(data, len, CTX_512(ctx)); return;
}
}
sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1])
{
switch(ctx->sha2_len)
{
case 32: sha256_end(hval, CTX_256(ctx)); return;
case 48: sha_end(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return;
case 64: sha_end(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return;
}
}
sha2_int sha2(unsigned char hval[], unsigned long size,
const unsigned char data[], unsigned long len)
{ sha2_ctx cx[1];
if(sha2_begin(size, cx) == SHA2_GOOD)
{
sha2_hash(data, len, cx); sha2_end(hval, cx); return SHA2_GOOD;
}
else
return SHA2_BAD;
}
#endif
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,154 @@
/*
---------------------------------------------------------------------------
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