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-e03cc46cb475master
parent
cbe11eae65
commit
2c72efbab4
|
@ -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.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -97,6 +97,20 @@ namespace io
|
|||
// zipfile comment (variable size)
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SZipFileExtraHeader
|
||||
{
|
||||
s16 ID;
|
||||
s16 Size;
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SZipFileAESExtraData
|
||||
{
|
||||
s16 Version;
|
||||
u8 Vendor[2];
|
||||
u8 EncryptionStrength;
|
||||
s16 CompressionMode;
|
||||
} PACK_STRUCT;
|
||||
|
||||
enum E_GZIP_FLAGS
|
||||
{
|
||||
EGZF_TEXT_DAT = 1,
|
||||
|
|
|
@ -3006,6 +3006,86 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="aesGladman"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\aesGladman\aes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\aescrypt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\aeskey.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\aesopt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\aestab.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\bzlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\fileenc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\fileenc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\hmac.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\hmac.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\prng.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\prng.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\pwd2key.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\pwd2key.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\Readme.txt"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\sha1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\sha1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\sha2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\aesGladman\sha2.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="device"
|
||||
|
@ -3018,6 +3098,14 @@
|
|||
RelativePath=".\CIrrDeviceConsole.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CIrrDeviceFB.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CIrrDeviceFB.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CIrrDeviceLinux.cpp"
|
||||
>
|
||||
|
@ -3050,6 +3138,14 @@
|
|||
RelativePath="CIrrDeviceWin32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CIrrDeviceWinCE.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CIrrDeviceWinCE.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
|
@ -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 ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue