forked from Mirrorlandia_minetest/irrlicht
Throw out support for Bzip, LZMA and encrypted ZIPs
This commit is contained in:
parent
67f1402410
commit
264f8b72c1
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install g++ gcc libxxf86vm-dev libgl1-mesa-dev libbz2-dev libpng-dev libjpeg-dev zlib1g-dev -qyy
|
sudo apt-get install g++ gcc libxxf86vm-dev libgl1-mesa-dev libpng-dev libjpeg-dev zlib1g-dev -qyy
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
|
@ -771,26 +771,6 @@ ones. */
|
|||||||
#ifdef NO_IRR_COMPILE_WITH_ZLIB_
|
#ifdef NO_IRR_COMPILE_WITH_ZLIB_
|
||||||
#undef _IRR_COMPILE_WITH_ZLIB_
|
#undef _IRR_COMPILE_WITH_ZLIB_
|
||||||
#endif
|
#endif
|
||||||
//! Define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if you want to read AES-encrypted ZIP archives
|
|
||||||
#define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
#ifdef NO_IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
#undef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
#endif
|
|
||||||
//! Define _IRR_COMPILE_WITH_BZIP2_ if you want to support bzip2 compressed zip archives
|
|
||||||
/** bzip2 is superior to the original zip file compression modes, but requires
|
|
||||||
a certain amount of memory for decompression and adds several files to the
|
|
||||||
library. */
|
|
||||||
#define _IRR_COMPILE_WITH_BZIP2_
|
|
||||||
#ifdef NO_IRR_COMPILE_WITH_BZIP2_
|
|
||||||
#undef _IRR_COMPILE_WITH_BZIP2_
|
|
||||||
#endif
|
|
||||||
//! Define _IRR_COMPILE_WITH_LZMA_ if you want to use LZMA compressed zip files.
|
|
||||||
/** LZMA is a very efficient compression code, known from 7zip. Irrlicht
|
|
||||||
currently only supports zip archives, though. */
|
|
||||||
#define _IRR_COMPILE_WITH_LZMA_
|
|
||||||
#ifdef NO_IRR_COMPILE_WITH_LZMA_
|
|
||||||
#undef _IRR_COMPILE_WITH_LZMA_
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives
|
//! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives
|
||||||
|
@ -6,11 +6,6 @@
|
|||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
// This method is used for error output from bzip2.
|
|
||||||
extern "C" void bz_internal_error(int errorCode)
|
|
||||||
{
|
|
||||||
irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_
|
#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_
|
||||||
|
|
||||||
@ -21,16 +16,6 @@ extern "C" void bz_internal_error(int errorCode)
|
|||||||
#include "IrrCompileConfig.h"
|
#include "IrrCompileConfig.h"
|
||||||
#ifdef _IRR_COMPILE_WITH_ZLIB_
|
#ifdef _IRR_COMPILE_WITH_ZLIB_
|
||||||
#include <zlib.h> // use system lib
|
#include <zlib.h> // use system lib
|
||||||
|
|
||||||
#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
#include "aesGladman/fileenc.h"
|
|
||||||
#endif
|
|
||||||
#ifdef _IRR_COMPILE_WITH_BZIP2_
|
|
||||||
#include <bzlib.h>
|
|
||||||
#endif
|
|
||||||
#ifdef _IRR_COMPILE_WITH_LZMA_
|
|
||||||
#include "lzma/LzmaDec.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
@ -315,46 +300,6 @@ bool CZipReader::scanZipHeader(bool ignoreGPBits)
|
|||||||
delete [] tmp;
|
delete [] tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// move forward length of extra field.
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (entry.header.ExtraFieldLength)
|
if (entry.header.ExtraFieldLength)
|
||||||
File->seek(entry.header.ExtraFieldLength, true);
|
File->seek(entry.header.ExtraFieldLength, true);
|
||||||
|
|
||||||
@ -480,24 +425,6 @@ IReadFile* CZipReader::createAndOpenFile(const io::path& filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _IRR_COMPILE_WITH_LZMA_
|
|
||||||
//! Used for LZMA decompression. The lib has no default memory management
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
void *SzAlloc(void *p, size_t size)
|
|
||||||
{
|
|
||||||
(void)p; // disable unused variable warnings
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
void SzFree(void *p, void *address)
|
|
||||||
{
|
|
||||||
(void)p; // disable unused variable warnings
|
|
||||||
free(address);
|
|
||||||
}
|
|
||||||
ISzAlloc lzmaAlloc = { SzAlloc, SzFree };
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! opens a file by index
|
//! opens a file by index
|
||||||
IReadFile* CZipReader::createAndOpenFile(u32 index)
|
IReadFile* CZipReader::createAndOpenFile(u32 index)
|
||||||
{
|
{
|
||||||
@ -526,83 +453,6 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
|
|||||||
IReadFile* decrypted=0;
|
IReadFile* decrypted=0;
|
||||||
u8* decryptedBuf=0;
|
u8* decryptedBuf=0;
|
||||||
u32 decryptedSize=e.header.DataDescriptor.CompressedSize;
|
u32 decryptedSize=e.header.DataDescriptor.CompressedSize;
|
||||||
#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_
|
|
||||||
if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99))
|
|
||||||
{
|
|
||||||
os::Printer::log("Reading encrypted file.");
|
|
||||||
u8 salt[16]={0};
|
|
||||||
const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4;
|
|
||||||
File->seek(e.Offset);
|
|
||||||
File->read(salt, saltSize);
|
|
||||||
char pwVerification[2];
|
|
||||||
char pwVerificationFile[2];
|
|
||||||
File->read(pwVerification, 2);
|
|
||||||
fcrypt_ctx zctx; // the encryption context
|
|
||||||
int rc = fcrypt_init(
|
|
||||||
(e.header.Sig & 0x00ff0000) >>16,
|
|
||||||
(const unsigned char*)Password.c_str(), // the password
|
|
||||||
Password.size(), // 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];
|
|
||||||
u32 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 = FileSystem->createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true);
|
|
||||||
actualCompressionMethod = (e.header.Sig & 0xffff);
|
|
||||||
#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
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
switch(actualCompressionMethod)
|
switch(actualCompressionMethod)
|
||||||
{
|
{
|
||||||
case 0: // no compression
|
case 0: // no compression
|
||||||
@ -688,139 +538,13 @@ IReadFile* CZipReader::createAndOpenFile(u32 index)
|
|||||||
}
|
}
|
||||||
case 12:
|
case 12:
|
||||||
{
|
{
|
||||||
#ifdef _IRR_COMPILE_WITH_BZIP2_
|
|
||||||
|
|
||||||
const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize;
|
|
||||||
c8* pBuf = new c8[ uncompressedSize ];
|
|
||||||
if (!pBuf)
|
|
||||||
{
|
|
||||||
swprintf_irr ( buf, 64, L"Not enough memory for decompressing %s", core::stringw(Files[index].FullName).c_str() );
|
|
||||||
os::Printer::log( buf, ELL_ERROR);
|
|
||||||
if (decrypted)
|
|
||||||
decrypted->drop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *pcData = decryptedBuf;
|
|
||||||
if (!pcData)
|
|
||||||
{
|
|
||||||
pcData = new u8[decryptedSize];
|
|
||||||
if (!pcData)
|
|
||||||
{
|
|
||||||
swprintf_irr ( buf, 64, L"Not enough memory for decompressing %s", core::stringw(Files[index].FullName).c_str() );
|
|
||||||
os::Printer::log( buf, ELL_ERROR);
|
|
||||||
delete [] pBuf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//memset(pcData, 0, decryptedSize);
|
|
||||||
File->seek(e.Offset);
|
|
||||||
File->read(pcData, decryptedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bz_stream bz_ctx;
|
|
||||||
memset(&bz_ctx, 0, sizeof(bz_ctx));
|
|
||||||
/* use BZIP2's default memory allocation
|
|
||||||
bz_ctx->bzalloc = NULL;
|
|
||||||
bz_ctx->bzfree = NULL;
|
|
||||||
bz_ctx->opaque = NULL;
|
|
||||||
*/
|
|
||||||
int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */
|
|
||||||
if(err != BZ_OK)
|
|
||||||
{
|
|
||||||
os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bz_ctx.next_in = (char*)pcData;
|
|
||||||
bz_ctx.avail_in = decryptedSize;
|
|
||||||
/* pass all input to decompressor */
|
|
||||||
bz_ctx.next_out = pBuf;
|
|
||||||
bz_ctx.avail_out = uncompressedSize;
|
|
||||||
err = BZ2_bzDecompress(&bz_ctx);
|
|
||||||
err = BZ2_bzDecompressEnd(&bz_ctx);
|
|
||||||
|
|
||||||
if (decrypted)
|
|
||||||
decrypted->drop();
|
|
||||||
else
|
|
||||||
delete[] pcData;
|
|
||||||
|
|
||||||
if (err != BZ_OK)
|
|
||||||
{
|
|
||||||
swprintf_irr ( buf, 64, L"Error decompressing %s", core::stringw(Files[index].FullName).c_str() );
|
|
||||||
os::Printer::log( buf, ELL_ERROR);
|
|
||||||
delete [] pBuf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FileSystem->createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true);
|
|
||||||
|
|
||||||
#else
|
|
||||||
os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR);
|
os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
case 14:
|
case 14:
|
||||||
{
|
{
|
||||||
#ifdef _IRR_COMPILE_WITH_LZMA_
|
|
||||||
|
|
||||||
u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize;
|
|
||||||
c8* pBuf = new c8[ uncompressedSize ];
|
|
||||||
if (!pBuf)
|
|
||||||
{
|
|
||||||
swprintf_irr ( buf, 64, L"Not enough memory for decompressing %s", core::stringw(Files[index].FullName).c_str() );
|
|
||||||
os::Printer::log( buf, ELL_ERROR);
|
|
||||||
if (decrypted)
|
|
||||||
decrypted->drop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *pcData = decryptedBuf;
|
|
||||||
if (!pcData)
|
|
||||||
{
|
|
||||||
pcData = new u8[decryptedSize];
|
|
||||||
if (!pcData)
|
|
||||||
{
|
|
||||||
swprintf_irr ( buf, 64, L"Not enough memory for decompressing %s", core::stringw(Files[index].FullName).c_str() );
|
|
||||||
os::Printer::log( buf, ELL_ERROR);
|
|
||||||
delete [] pBuf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//memset(pcData, 0, decryptedSize);
|
|
||||||
File->seek(e.Offset);
|
|
||||||
File->read(pcData, decryptedSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
ELzmaStatus status;
|
|
||||||
SizeT tmpDstSize = uncompressedSize;
|
|
||||||
SizeT tmpSrcSize = decryptedSize;
|
|
||||||
|
|
||||||
unsigned int propSize = (pcData[3]<<8)+pcData[2];
|
|
||||||
int err = LzmaDecode((Byte*)pBuf, &tmpDstSize,
|
|
||||||
pcData+4+propSize, &tmpSrcSize,
|
|
||||||
pcData+4, propSize,
|
|
||||||
e.header.GeneralBitFlag&0x1?LZMA_FINISH_END:LZMA_FINISH_ANY, &status,
|
|
||||||
&lzmaAlloc);
|
|
||||||
uncompressedSize = tmpDstSize; // may be different to expected value
|
|
||||||
|
|
||||||
if (decrypted)
|
|
||||||
decrypted->drop();
|
|
||||||
else
|
|
||||||
delete[] pcData;
|
|
||||||
|
|
||||||
if (err != SZ_OK)
|
|
||||||
{
|
|
||||||
os::Printer::log( "Error decompressing", Files[index].FullName, ELL_ERROR);
|
|
||||||
delete [] pBuf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FileSystem->createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true);
|
|
||||||
|
|
||||||
#else
|
|
||||||
os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR);
|
os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
case 99:
|
case 99:
|
||||||
// If we come here with an encrypted file, decryption support is missing
|
// If we come here with an encrypted file, decryption support is missing
|
||||||
|
@ -54,16 +54,15 @@ IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CT
|
|||||||
CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o \
|
CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o \
|
||||||
CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o \
|
CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o \
|
||||||
CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o CTR_transparent_reflection_2_layer.o CTRGouraudNoZ2.o burning_shader_color.o
|
CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o CTR_transparent_reflection_2_layer.o CTRGouraudNoZ2.o burning_shader_color.o
|
||||||
IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CWADReader.o CZipReader.o CPakReader.o CNPKReader.o CTarReader.o CMountPointReader.o irrXML.o CAttributes.o lzma/LzmaDec.o
|
IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CWADReader.o CZipReader.o CPakReader.o CNPKReader.o CTarReader.o CMountPointReader.o irrXML.o CAttributes.o
|
||||||
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o leakHunter.o CProfiler.o utf8.o
|
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o leakHunter.o CProfiler.o utf8.o
|
||||||
IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o CGUIProfiler.o
|
IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o CGUIProfiler.o
|
||||||
LIBAESGM = aesGladman/aescrypt.o aesGladman/aeskey.o aesGladman/aestab.o aesGladman/fileenc.o aesGladman/hmac.o aesGladman/prng.o aesGladman/pwd2key.o aesGladman/sha1.o aesGladman/sha2.o
|
|
||||||
|
|
||||||
# Next variable is for additional scene nodes etc. of customized Irrlicht versions
|
# Next variable is for additional scene nodes etc. of customized Irrlicht versions
|
||||||
EXTRAOBJ =
|
EXTRAOBJ =
|
||||||
LINKOBJ = $(IRRMESHOBJ) $(IRROBJ) $(IRRPARTICLEOBJ) $(IRRANIMOBJ) \
|
LINKOBJ = $(IRRMESHOBJ) $(IRROBJ) $(IRRPARTICLEOBJ) $(IRRANIMOBJ) \
|
||||||
$(IRRVIDEOOBJ) $(IRRSWRENDEROBJ) $(IRRIOOBJ) $(IRROTHEROBJ) \
|
$(IRRVIDEOOBJ) $(IRRSWRENDEROBJ) $(IRRIOOBJ) $(IRROTHEROBJ) \
|
||||||
$(IRRGUIOBJ) $(LIBAESGM) $(EXTRAOBJ)
|
$(IRRGUIOBJ) $(EXTRAOBJ)
|
||||||
|
|
||||||
emscripten: EMSCRIPTEN=1
|
emscripten: EMSCRIPTEN=1
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
#include "irrMath.h"
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
|
|
||||||
typedef irr::u8 aes_08t;
|
|
||||||
typedef irr::u32 aes_32t;
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,307 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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"
|
|
||||||
|
|
||||||
#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 optimization 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;
|
|
||||||
/* Falls through. */
|
|
||||||
case 12:
|
|
||||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
|
||||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
|
||||||
kp += 2 * N_COLS;
|
|
||||||
/* Falls through. */
|
|
||||||
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 optimization 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;
|
|
||||||
/* Falls through. */
|
|
||||||
case 12:
|
|
||||||
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
|
|
||||||
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
|
|
||||||
kp -= 2 * N_COLS;
|
|
||||||
/* Falls through. */
|
|
||||||
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
|
|
||||||
|
|
@ -1,461 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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"
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
ss[4] = word_in(in_key, 4);
|
|
||||||
cx->ks[4] = ff(ss[4]);
|
|
||||||
ss[5] = word_in(in_key, 5);
|
|
||||||
cx->ks[5] = ff(ss[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
|
|
||||||
ss[4] = word_in(in_key, 4);
|
|
||||||
cx->ks[4] = ff(ss[4]);
|
|
||||||
ss[5] = word_in(in_key, 5);
|
|
||||||
cx->ks[5] = ff(ss[5]);
|
|
||||||
ss[6] = word_in(in_key, 6);
|
|
||||||
cx->ks[6] = ff(ss[6]);
|
|
||||||
ss[7] = word_in(in_key, 7);
|
|
||||||
cx->ks[7] = ff(ss[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
|
|
||||||
|
|
@ -1,955 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
My thanks go to Dag Arne Osvik for devising the schemes used here for key
|
|
||||||
length derivation from the form of the key schedule
|
|
||||||
|
|
||||||
This file contains the compilation options for AES (Rijndael) and code
|
|
||||||
that is common across encryption, key scheduling and table generation.
|
|
||||||
|
|
||||||
OPERATION
|
|
||||||
|
|
||||||
These source code files implement the AES algorithm Rijndael designed by
|
|
||||||
Joan Daemen and Vincent Rijmen. This version is designed for the standard
|
|
||||||
block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24
|
|
||||||
and 32 bytes).
|
|
||||||
|
|
||||||
This version is designed for flexibility and speed using operations on
|
|
||||||
32-bit words rather than operations on bytes. It can be compiled with
|
|
||||||
either big or little endian internal byte order but is faster when the
|
|
||||||
native byte order for the processor is used.
|
|
||||||
|
|
||||||
THE CIPHER INTERFACE
|
|
||||||
|
|
||||||
The cipher interface is implemented as an array of bytes in which lower
|
|
||||||
AES bit sequence indexes map to higher numeric significance within bytes.
|
|
||||||
|
|
||||||
aes_08t (an unsigned 8-bit type)
|
|
||||||
aes_32t (an unsigned 32-bit type)
|
|
||||||
struct aes_encrypt_ctx (structure for the cipher encryption context)
|
|
||||||
struct aes_decrypt_ctx (structure for the cipher decryption context)
|
|
||||||
aes_rval the function return type
|
|
||||||
|
|
||||||
C subroutine calls:
|
|
||||||
|
|
||||||
aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_encrypt(const void *in_blk,
|
|
||||||
void *out_blk, const aes_encrypt_ctx cx[1]);
|
|
||||||
|
|
||||||
aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]);
|
|
||||||
aes_rval aes_decrypt(const void *in_blk,
|
|
||||||
void *out_blk, const aes_decrypt_ctx cx[1]);
|
|
||||||
|
|
||||||
IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that
|
|
||||||
you call genTabs() before AES is used so that the tables are initialised.
|
|
||||||
|
|
||||||
C++ aes class subroutines:
|
|
||||||
|
|
||||||
Class AESencrypt for encryption
|
|
||||||
|
|
||||||
Construtors:
|
|
||||||
AESencrypt(void)
|
|
||||||
AESencrypt(const void *in_key) - 128 bit key
|
|
||||||
Members:
|
|
||||||
void key128(const void *in_key)
|
|
||||||
void key192(const void *in_key)
|
|
||||||
void key256(const void *in_key)
|
|
||||||
void encrypt(const void *in_blk, void *out_blk) const
|
|
||||||
|
|
||||||
Class AESdecrypt for encryption
|
|
||||||
Construtors:
|
|
||||||
AESdecrypt(void)
|
|
||||||
AESdecrypt(const void *in_key) - 128 bit key
|
|
||||||
Members:
|
|
||||||
void key128(const void *in_key)
|
|
||||||
void key192(const void *in_key)
|
|
||||||
void key256(const void *in_key)
|
|
||||||
void decrypt(const void *in_blk, void *out_blk) const
|
|
||||||
|
|
||||||
COMPILATION
|
|
||||||
|
|
||||||
The files used to provide AES (Rijndael) are
|
|
||||||
|
|
||||||
a. aes.h for the definitions needed for use in C.
|
|
||||||
b. aescpp.h for the definitions needed for use in C++.
|
|
||||||
c. aesopt.h for setting compilation options (also includes common code).
|
|
||||||
d. aescrypt.c for encryption and decrytpion, or
|
|
||||||
e. aeskey.c for key scheduling.
|
|
||||||
f. aestab.c for table loading or generation.
|
|
||||||
g. aescrypt.asm for encryption and decryption using assembler code.
|
|
||||||
h. aescrypt.mmx.asm for encryption and decryption using MMX assembler.
|
|
||||||
|
|
||||||
To compile AES (Rijndael) for use in C code use aes.h and set the
|
|
||||||
defines here for the facilities you need (key lengths, encryption
|
|
||||||
and/or decryption). Do not define AES_DLL or AES_CPP. Set the options
|
|
||||||
for optimisations and table sizes here.
|
|
||||||
|
|
||||||
To compile AES (Rijndael) for use in in C++ code use aescpp.h but do
|
|
||||||
not define AES_DLL
|
|
||||||
|
|
||||||
To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use
|
|
||||||
aes.h and include the AES_DLL define.
|
|
||||||
|
|
||||||
CONFIGURATION OPTIONS (here and in aes.h)
|
|
||||||
|
|
||||||
a. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL
|
|
||||||
b. You may need to set PLATFORM_BYTE_ORDER to define the byte order.
|
|
||||||
c. If you want the code to run in a specific internal byte order, then
|
|
||||||
ALGORITHM_BYTE_ORDER must be set accordingly.
|
|
||||||
d. set other configuration options decribed below.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _AESOPT_H
|
|
||||||
#define _AESOPT_H
|
|
||||||
|
|
||||||
#include "aes.h"
|
|
||||||
|
|
||||||
/* CONFIGURATION - USE OF DEFINES
|
|
||||||
|
|
||||||
Later in this section there are a number of defines that control the
|
|
||||||
operation of the code. In each section, the purpose of each define is
|
|
||||||
explained so that the relevant form can be included or excluded by
|
|
||||||
setting either 1's or 0's respectively on the branches of the related
|
|
||||||
#if clauses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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) */
|
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* SOME LOCAL DEFINITIONS */
|
|
||||||
|
|
||||||
#define NO_TABLES 0
|
|
||||||
#define ONE_TABLE 1
|
|
||||||
#define FOUR_TABLES 4
|
|
||||||
#define NONE 0
|
|
||||||
#define PARTIAL 1
|
|
||||||
#define FULL 2
|
|
||||||
|
|
||||||
#define aes_sw32 Byteswap::byteswap
|
|
||||||
|
|
||||||
/* 1. FUNCTIONS REQUIRED
|
|
||||||
|
|
||||||
This implementation provides subroutines for encryption, decryption
|
|
||||||
and for setting the three key lengths (separately) for encryption
|
|
||||||
and decryption. When the assembler code is not being used the following
|
|
||||||
definition blocks allow the selection of the routines that are to be
|
|
||||||
included in the compilation.
|
|
||||||
*/
|
|
||||||
#ifdef AES_ENCRYPT
|
|
||||||
#define ENCRYPTION
|
|
||||||
#define ENCRYPTION_KEY_SCHEDULE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AES_DECRYPT
|
|
||||||
#define DECRYPTION
|
|
||||||
#define DECRYPTION_KEY_SCHEDULE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 2. ASSEMBLER SUPPORT
|
|
||||||
|
|
||||||
This define (which can be on the command line) enables the use of the
|
|
||||||
assembler code routines for encryption and decryption with the C code
|
|
||||||
only providing key scheduling
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
#define AES_ASM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 3. BYTE ORDER WITHIN 32 BIT WORDS
|
|
||||||
|
|
||||||
The fundamental data processing units in Rijndael are 8-bit bytes. The
|
|
||||||
input, output and key input are all enumerated arrays of bytes in which
|
|
||||||
bytes are numbered starting at zero and increasing to one less than the
|
|
||||||
number of bytes in the array in question. This enumeration is only used
|
|
||||||
for naming bytes and does not imply any adjacency or order relationship
|
|
||||||
from one byte to another. When these inputs and outputs are considered
|
|
||||||
as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
|
|
||||||
byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
|
|
||||||
In this implementation bits are numbered from 0 to 7 starting at the
|
|
||||||
numerically least significant end of each byte (bit n represents 2^n).
|
|
||||||
|
|
||||||
However, Rijndael can be implemented more efficiently using 32-bit
|
|
||||||
words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
|
|
||||||
into word[n]. While in principle these bytes can be assembled into words
|
|
||||||
in any positions, this implementation only supports the two formats in
|
|
||||||
which bytes in adjacent positions within words also have adjacent byte
|
|
||||||
numbers. This order is called big-endian if the lowest numbered bytes
|
|
||||||
in words have the highest numeric significance and little-endian if the
|
|
||||||
opposite applies.
|
|
||||||
|
|
||||||
This code can work in either order irrespective of the order used by the
|
|
||||||
machine on which it runs. Normally the internal byte order will be set
|
|
||||||
to the order of the processor on which the code is to be run but this
|
|
||||||
define can be used to reverse this in special situations
|
|
||||||
|
|
||||||
NOTE: Assembler code versions rely on PLATFORM_BYTE_ORDER being set
|
|
||||||
*/
|
|
||||||
#if 1 || defined(AES_ASM)
|
|
||||||
#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
|
|
||||||
#elif 0
|
|
||||||
#define ALGORITHM_BYTE_ORDER BRG_LITTLE_ENDIAN
|
|
||||||
#elif 0
|
|
||||||
#define ALGORITHM_BYTE_ORDER BRG_BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#error The algorithm byte order is not defined
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 4. FAST INPUT/OUTPUT OPERATIONS.
|
|
||||||
|
|
||||||
On some machines it is possible to improve speed by transferring the
|
|
||||||
bytes in the input and output arrays to and from the internal 32-bit
|
|
||||||
variables by addressing these arrays as if they are arrays of 32-bit
|
|
||||||
words. On some machines this will always be possible but there may
|
|
||||||
be a large performance penalty if the byte arrays are not aligned on
|
|
||||||
the normal word boundaries. On other machines this technique will
|
|
||||||
lead to memory access errors when such 32-bit word accesses are not
|
|
||||||
properly aligned. The option SAFE_IO avoids such problems but will
|
|
||||||
often be slower on those machines that support misaligned access
|
|
||||||
(especially so if care is taken to align the input and output byte
|
|
||||||
arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
|
|
||||||
assumed that access to byte arrays as if they are arrays of 32-bit
|
|
||||||
words will not cause problems when such accesses are misaligned.
|
|
||||||
*/
|
|
||||||
#if 1 && !defined(_MSC_VER)
|
|
||||||
#define SAFE_IO
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 5. LOOP UNROLLING
|
|
||||||
|
|
||||||
The code for encryption and decrytpion cycles through a number of rounds
|
|
||||||
that can be implemented either in a loop or by expanding the code into a
|
|
||||||
long sequence of instructions, the latter producing a larger program but
|
|
||||||
one that will often be much faster. The latter is called loop unrolling.
|
|
||||||
There are also potential speed advantages in expanding two iterations in
|
|
||||||
a loop with half the number of iterations, which is called partial loop
|
|
||||||
unrolling. The following options allow partial or full loop unrolling
|
|
||||||
to be set independently for encryption and decryption
|
|
||||||
*/
|
|
||||||
#if 1
|
|
||||||
#define ENC_UNROLL FULL
|
|
||||||
#elif 0
|
|
||||||
#define ENC_UNROLL PARTIAL
|
|
||||||
#else
|
|
||||||
#define ENC_UNROLL NONE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
#define DEC_UNROLL FULL
|
|
||||||
#elif 0
|
|
||||||
#define DEC_UNROLL PARTIAL
|
|
||||||
#else
|
|
||||||
#define DEC_UNROLL NONE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 6. FAST FINITE FIELD OPERATIONS
|
|
||||||
|
|
||||||
If this section is included, tables are used to provide faster finite
|
|
||||||
field arithmetic (this has no effect if FIXED_TABLES is defined).
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
#define FF_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 7. INTERNAL STATE VARIABLE FORMAT
|
|
||||||
|
|
||||||
The internal state of Rijndael is stored in a number of local 32-bit
|
|
||||||
word varaibles which can be defined either as an array or as individual
|
|
||||||
names variables. Include this section if you want to store these local
|
|
||||||
varaibles in arrays. Otherwise individual local variables will be used.
|
|
||||||
*/
|
|
||||||
#if 1
|
|
||||||
#define ARRAYS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* In this implementation the columns of the state array are each held in
|
|
||||||
32-bit words. The state array can be held in various ways: in an array
|
|
||||||
of words, in a number of individual word variables or in a number of
|
|
||||||
processor registers. The following define maps a variable name x and
|
|
||||||
a column number c to the way the state array variable is to be held.
|
|
||||||
The first define below maps the state into an array x[c] whereas the
|
|
||||||
second form maps the state into a number of individual variables x0,
|
|
||||||
x1, etc. Another form could map individual state colums to machine
|
|
||||||
register names.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(ARRAYS)
|
|
||||||
#define s(x,c) x[c]
|
|
||||||
#else
|
|
||||||
#define s(x,c) x##c
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 8. FIXED OR DYNAMIC TABLES
|
|
||||||
|
|
||||||
When this section is included the tables used by the code are compiled
|
|
||||||
statically into the binary file. Otherwise the subroutine gen_tabs()
|
|
||||||
must be called to compute them before the code is first used.
|
|
||||||
*/
|
|
||||||
#if 1
|
|
||||||
#define FIXED_TABLES
|
|
||||||
#define DO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 9. TABLE ALIGNMENT
|
|
||||||
|
|
||||||
On some systems speed will be improved by aligning the AES large lookup
|
|
||||||
tables on particular boundaries. This define should be set to a power of
|
|
||||||
two giving the desired alignment. It can be left undefined if alignment
|
|
||||||
is not needed. This option is specific to the Microsft VC++ compiler -
|
|
||||||
it seems to sometimes cause trouble for the VC++ version 6 compiler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0 && defined(_MSC_VER) && (_MSC_VER >= 1300)
|
|
||||||
#define TABLE_ALIGN 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 10. INTERNAL TABLE CONFIGURATION
|
|
||||||
|
|
||||||
This cipher proceeds by repeating in a number of cycles known as 'rounds'
|
|
||||||
which are implemented by a round function which can optionally be speeded
|
|
||||||
up using tables. The basic tables are each 256 32-bit words, with either
|
|
||||||
one or four tables being required for each round function depending on
|
|
||||||
how much speed is required. The encryption and decryption round functions
|
|
||||||
are different and the last encryption and decrytpion round functions are
|
|
||||||
different again making four different round functions in all.
|
|
||||||
|
|
||||||
This means that:
|
|
||||||
1. Normal encryption and decryption rounds can each use either 0, 1
|
|
||||||
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
|
|
||||||
2. The last encryption and decryption rounds can also use either 0, 1
|
|
||||||
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
|
|
||||||
|
|
||||||
Include or exclude the appropriate definitions below to set the number
|
|
||||||
of tables used by this implementation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 1 /* set tables for the normal encryption round */
|
|
||||||
#define ENC_ROUND FOUR_TABLES
|
|
||||||
#elif 0
|
|
||||||
#define ENC_ROUND ONE_TABLE
|
|
||||||
#else
|
|
||||||
#define ENC_ROUND NO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 1 /* set tables for the last encryption round */
|
|
||||||
#define LAST_ENC_ROUND FOUR_TABLES
|
|
||||||
#elif 0
|
|
||||||
#define LAST_ENC_ROUND ONE_TABLE
|
|
||||||
#else
|
|
||||||
#define LAST_ENC_ROUND NO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 1 /* set tables for the normal decryption round */
|
|
||||||
#define DEC_ROUND FOUR_TABLES
|
|
||||||
#elif 0
|
|
||||||
#define DEC_ROUND ONE_TABLE
|
|
||||||
#else
|
|
||||||
#define DEC_ROUND NO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 1 /* set tables for the last decryption round */
|
|
||||||
#define LAST_DEC_ROUND FOUR_TABLES
|
|
||||||
#elif 0
|
|
||||||
#define LAST_DEC_ROUND ONE_TABLE
|
|
||||||
#else
|
|
||||||
#define LAST_DEC_ROUND NO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The decryption key schedule can be speeded up with tables in the same
|
|
||||||
way that the round functions can. Include or exclude the following
|
|
||||||
defines to set this requirement.
|
|
||||||
*/
|
|
||||||
#if 1
|
|
||||||
#define KEY_SCHED FOUR_TABLES
|
|
||||||
#elif 0
|
|
||||||
#define KEY_SCHED ONE_TABLE
|
|
||||||
#else
|
|
||||||
#define KEY_SCHED NO_TABLES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* END OF CONFIGURATION OPTIONS */
|
|
||||||
|
|
||||||
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
|
|
||||||
|
|
||||||
/* Disable or report errors on some combinations of options */
|
|
||||||
|
|
||||||
#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
|
|
||||||
#undef LAST_ENC_ROUND
|
|
||||||
#define LAST_ENC_ROUND NO_TABLES
|
|
||||||
#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
|
|
||||||
#undef LAST_ENC_ROUND
|
|
||||||
#define LAST_ENC_ROUND ONE_TABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
|
|
||||||
#undef ENC_UNROLL
|
|
||||||
#define ENC_UNROLL NONE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
|
|
||||||
#undef LAST_DEC_ROUND
|
|
||||||
#define LAST_DEC_ROUND NO_TABLES
|
|
||||||
#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
|
|
||||||
#undef LAST_DEC_ROUND
|
|
||||||
#define LAST_DEC_ROUND ONE_TABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
|
|
||||||
#undef DEC_UNROLL
|
|
||||||
#define DEC_UNROLL NONE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* upr(x,n): rotates bytes within words by n positions, moving bytes to
|
|
||||||
higher index positions with wrap around into low positions
|
|
||||||
ups(x,n): moves bytes by n positions to higher index positions in
|
|
||||||
words but without wrap around
|
|
||||||
bval(x,n): extracts a byte from a word
|
|
||||||
|
|
||||||
NOTE: The definitions given here are intended only for use with
|
|
||||||
unsigned variables and with shift counts that are compile
|
|
||||||
time constants
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (ALGORITHM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
|
|
||||||
#define upr(x,n) (((aes_32t)(x) << (8 * (n))) | ((aes_32t)(x) >> (32 - 8 * (n))))
|
|
||||||
#define ups(x,n) ((aes_32t) (x) << (8 * (n)))
|
|
||||||
#define bval(x,n) ((aes_08t)((x) >> (8 * (n))))
|
|
||||||
#define bytes2word(b0, b1, b2, b3) \
|
|
||||||
(((aes_32t)(b3) << 24) | ((aes_32t)(b2) << 16) | ((aes_32t)(b1) << 8) | (b0))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (ALGORITHM_BYTE_ORDER == BRG_BIG_ENDIAN)
|
|
||||||
#define upr(x,n) (((aes_32t)(x) >> (8 * (n))) | ((aes_32t)(x) << (32 - 8 * (n))))
|
|
||||||
#define ups(x,n) ((aes_32t) (x) >> (8 * (n))))
|
|
||||||
#define bval(x,n) ((aes_08t)((x) >> (24 - 8 * (n))))
|
|
||||||
#define bytes2word(b0, b1, b2, b3) \
|
|
||||||
(((aes_32t)(b0) << 24) | ((aes_32t)(b1) << 16) | ((aes_32t)(b2) << 8) | (b3))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SAFE_IO)
|
|
||||||
|
|
||||||
#define word_in(x,c) bytes2word(((aes_08t*)(x)+4*c)[0], ((aes_08t*)(x)+4*c)[1], \
|
|
||||||
((aes_08t*)(x)+4*c)[2], ((aes_08t*)(x)+4*c)[3])
|
|
||||||
#define word_out(x,c,v) { ((aes_08t*)(x)+4*c)[0] = bval(v,0); ((aes_08t*)(x)+4*c)[1] = bval(v,1); \
|
|
||||||
((aes_08t*)(x)+4*c)[2] = bval(v,2); ((aes_08t*)(x)+4*c)[3] = bval(v,3); }
|
|
||||||
|
|
||||||
#elif (ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER)
|
|
||||||
|
|
||||||
#define word_in(x,c) (*((aes_32t*)(x)+(c)))
|
|
||||||
#define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = (v))
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define word_in(x,c) aes_sw32(*((aes_32t*)(x)+(c)))
|
|
||||||
#define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = aes_sw32(v))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* the finite field modular polynomial and elements */
|
|
||||||
|
|
||||||
#define WPOLY 0x011b
|
|
||||||
#define BPOLY 0x1b
|
|
||||||
|
|
||||||
/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
|
|
||||||
|
|
||||||
#define m1 0x80808080
|
|
||||||
#define m2 0x7f7f7f7f
|
|
||||||
#define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY))
|
|
||||||
|
|
||||||
/* The following defines provide alternative definitions of gf_mulx that might
|
|
||||||
give improved performance if a fast 32-bit multiply is not available. Note
|
|
||||||
that a temporary variable u needs to be defined where gf_mulx is used.
|
|
||||||
|
|
||||||
#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6))
|
|
||||||
#define m4 (0x01010101 * BPOLY)
|
|
||||||
#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Work out which tables are needed for the different options */
|
|
||||||
|
|
||||||
#ifdef AES_ASM
|
|
||||||
#ifdef ENC_ROUND
|
|
||||||
#undef ENC_ROUND
|
|
||||||
#endif
|
|
||||||
#define ENC_ROUND FOUR_TABLES
|
|
||||||
#ifdef LAST_ENC_ROUND
|
|
||||||
#undef LAST_ENC_ROUND
|
|
||||||
#endif
|
|
||||||
#define LAST_ENC_ROUND FOUR_TABLES
|
|
||||||
#ifdef DEC_ROUND
|
|
||||||
#undef DEC_ROUND
|
|
||||||
#endif
|
|
||||||
#define DEC_ROUND FOUR_TABLES
|
|
||||||
#ifdef LAST_DEC_ROUND
|
|
||||||
#undef LAST_DEC_ROUND
|
|
||||||
#endif
|
|
||||||
#define LAST_DEC_ROUND FOUR_TABLES
|
|
||||||
#ifdef KEY_SCHED
|
|
||||||
#undef KEY_SCHED
|
|
||||||
#define KEY_SCHED FOUR_TABLES
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENCRYPTION) || defined(AES_ASM)
|
|
||||||
#if ENC_ROUND == ONE_TABLE
|
|
||||||
#define FT1_SET
|
|
||||||
#elif ENC_ROUND == FOUR_TABLES
|
|
||||||
#define FT4_SET
|
|
||||||
#else
|
|
||||||
#define SBX_SET
|
|
||||||
#endif
|
|
||||||
#if LAST_ENC_ROUND == ONE_TABLE
|
|
||||||
#define FL1_SET
|
|
||||||
#elif LAST_ENC_ROUND == FOUR_TABLES
|
|
||||||
#define FL4_SET
|
|
||||||
#elif !defined(SBX_SET)
|
|
||||||
#define SBX_SET
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(DECRYPTION) || defined(AES_ASM)
|
|
||||||
#if DEC_ROUND == ONE_TABLE
|
|
||||||
#define IT1_SET
|
|
||||||
#elif DEC_ROUND == FOUR_TABLES
|
|
||||||
#define IT4_SET
|
|
||||||
#else
|
|
||||||
#define ISB_SET
|
|
||||||
#endif
|
|
||||||
#if LAST_DEC_ROUND == ONE_TABLE
|
|
||||||
#define IL1_SET
|
|
||||||
#elif LAST_DEC_ROUND == FOUR_TABLES
|
|
||||||
#define IL4_SET
|
|
||||||
#elif !defined(ISB_SET)
|
|
||||||
#define ISB_SET
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE)
|
|
||||||
#if KEY_SCHED == ONE_TABLE
|
|
||||||
#define LS1_SET
|
|
||||||
#define IM1_SET
|
|
||||||
#elif KEY_SCHED == FOUR_TABLES
|
|
||||||
#define LS4_SET
|
|
||||||
#define IM4_SET
|
|
||||||
#elif !defined(SBX_SET)
|
|
||||||
#define SBX_SET
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* generic definitions of Rijndael macros that use tables */
|
|
||||||
|
|
||||||
#define no_table(x,box,vf,rf,c) bytes2word( \
|
|
||||||
box[bval(vf(x,0,c),rf(0,c))], \
|
|
||||||
box[bval(vf(x,1,c),rf(1,c))], \
|
|
||||||
box[bval(vf(x,2,c),rf(2,c))], \
|
|
||||||
box[bval(vf(x,3,c),rf(3,c))])
|
|
||||||
|
|
||||||
#define one_table(x,op,tab,vf,rf,c) \
|
|
||||||
( tab[bval(vf(x,0,c),rf(0,c))] \
|
|
||||||
^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
|
|
||||||
^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
|
|
||||||
^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
|
|
||||||
|
|
||||||
#define four_tables(x,tab,vf,rf,c) \
|
|
||||||
( tab[0][bval(vf(x,0,c),rf(0,c))] \
|
|
||||||
^ tab[1][bval(vf(x,1,c),rf(1,c))] \
|
|
||||||
^ tab[2][bval(vf(x,2,c),rf(2,c))] \
|
|
||||||
^ tab[3][bval(vf(x,3,c),rf(3,c))])
|
|
||||||
|
|
||||||
#define vf1(x,r,c) (x)
|
|
||||||
#define rf1(r,c) (r)
|
|
||||||
#define rf2(r,c) ((8+r-c)&3)
|
|
||||||
|
|
||||||
/* perform forward and inverse column mix operation on four bytes in long word x in */
|
|
||||||
/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */
|
|
||||||
|
|
||||||
#if defined(FM4_SET) /* not currently used */
|
|
||||||
#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0)
|
|
||||||
#elif defined(FM1_SET) /* not currently used */
|
|
||||||
#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0)
|
|
||||||
#else
|
|
||||||
#define dec_fmvars aes_32t g2
|
|
||||||
#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(IM4_SET)
|
|
||||||
#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0)
|
|
||||||
#elif defined(IM1_SET)
|
|
||||||
#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0)
|
|
||||||
#else
|
|
||||||
#define dec_imvars aes_32t g2, g4, g9
|
|
||||||
#define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \
|
|
||||||
(x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FL4_SET)
|
|
||||||
#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c)
|
|
||||||
#elif defined(LS4_SET)
|
|
||||||
#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c)
|
|
||||||
#elif defined(FL1_SET)
|
|
||||||
#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c)
|
|
||||||
#elif defined(LS1_SET)
|
|
||||||
#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c)
|
|
||||||
#else
|
|
||||||
#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If there are no global variables, the definitions here can be
|
|
||||||
used to put the AES tables in a structure so that a pointer
|
|
||||||
can then be added to the AES context to pass them to the AES
|
|
||||||
routines that need them. If this facility is used, the calling
|
|
||||||
program has to ensure that this pointer is managed appropriately.
|
|
||||||
In particular, the value of the t_dec(in,it) item in the table
|
|
||||||
structure must be set to zero in order to ensure that the tables
|
|
||||||
are initialised. In practice the three code sequences in aeskey.c
|
|
||||||
that control the calls to gen_tabs() and the gen_tabs() routine
|
|
||||||
itself will have to be changed for a specific implementation. If
|
|
||||||
global variables are available it will generally be preferable to
|
|
||||||
use them with the precomputed FIXED_TABLES option that uses static
|
|
||||||
global tables.
|
|
||||||
|
|
||||||
The following defines can be used to control the way the tables
|
|
||||||
are defined, initialised and used in embedded environments that
|
|
||||||
require special features for these purposes
|
|
||||||
|
|
||||||
the 't_dec' construction is used to declare fixed table arrays
|
|
||||||
the 't_set' construction is used to set fixed table values
|
|
||||||
the 't_use' construction is used to access fixed table values
|
|
||||||
|
|
||||||
256 byte tables:
|
|
||||||
|
|
||||||
t_xxx(s,box) => forward S box
|
|
||||||
t_xxx(i,box) => inverse S box
|
|
||||||
|
|
||||||
256 32-bit word OR 4 x 256 32-bit word tables:
|
|
||||||
|
|
||||||
t_xxx(f,n) => forward normal round
|
|
||||||
t_xxx(f,l) => forward last round
|
|
||||||
t_xxx(i,n) => inverse normal round
|
|
||||||
t_xxx(i,l) => inverse last round
|
|
||||||
t_xxx(l,s) => key schedule table
|
|
||||||
t_xxx(i,m) => key schedule table
|
|
||||||
|
|
||||||
Other variables and tables:
|
|
||||||
|
|
||||||
t_xxx(r,c) => the rcon table
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define t_dec(m,n) t_##m##n
|
|
||||||
#define t_set(m,n) t_##m##n
|
|
||||||
#define t_use(m,n) t_##m##n
|
|
||||||
|
|
||||||
#if defined(DO_TABLES) /* declare and instantiate tables */
|
|
||||||
|
|
||||||
/* finite field arithmetic operations for table generation */
|
|
||||||
|
|
||||||
#if defined(FIXED_TABLES) || !defined(FF_TABLES)
|
|
||||||
|
|
||||||
#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
|
|
||||||
#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
|
|
||||||
#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
|
|
||||||
^ (((x>>5) & 4) * WPOLY))
|
|
||||||
#define f3(x) (f2(x) ^ x)
|
|
||||||
#define f9(x) (f8(x) ^ x)
|
|
||||||
#define fb(x) (f8(x) ^ f2(x) ^ x)
|
|
||||||
#define fd(x) (f8(x) ^ f4(x) ^ x)
|
|
||||||
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
|
|
||||||
#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
|
|
||||||
#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
|
|
||||||
#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
|
|
||||||
#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
|
|
||||||
#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
|
|
||||||
#define fi(x) ((x) ? pow[ 255 - log[x]] : 0)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FIXED_TABLES) /* declare and set values for static tables */
|
|
||||||
|
|
||||||
#define sb_data(w) \
|
|
||||||
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
|
|
||||||
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
|
|
||||||
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
|
|
||||||
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
|
|
||||||
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
|
|
||||||
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
|
|
||||||
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
|
|
||||||
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
|
|
||||||
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
|
|
||||||
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
|
|
||||||
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
|
|
||||||
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
|
|
||||||
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
|
|
||||||
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
|
|
||||||
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
|
|
||||||
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
|
|
||||||
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
|
|
||||||
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
|
|
||||||
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
|
|
||||||
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
|
|
||||||
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
|
|
||||||
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
|
|
||||||
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
|
|
||||||
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
|
|
||||||
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
|
|
||||||
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
|
|
||||||
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
|
|
||||||
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
|
|
||||||
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
|
|
||||||
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
|
|
||||||
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
|
|
||||||
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16)
|
|
||||||
|
|
||||||
#define isb_data(w) \
|
|
||||||
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
|
|
||||||
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
|
|
||||||
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
|
|
||||||
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
|
|
||||||
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
|
|
||||||
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
|
|
||||||
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
|
|
||||||
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
|
|
||||||
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
|
|
||||||
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
|
|
||||||
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
|
|
||||||
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
|
|
||||||
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
|
|
||||||
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
|
|
||||||
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
|
|
||||||
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
|
|
||||||
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
|
|
||||||
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
|
|
||||||
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
|
|
||||||
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
|
|
||||||
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
|
|
||||||
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
|
|
||||||
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
|
|
||||||
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
|
|
||||||
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
|
|
||||||
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
|
|
||||||
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
|
|
||||||
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
|
|
||||||
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
|
|
||||||
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
|
|
||||||
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
|
|
||||||
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d),
|
|
||||||
|
|
||||||
#define mm_data(w) \
|
|
||||||
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
|
|
||||||
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
|
|
||||||
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
|
|
||||||
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
|
|
||||||
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
|
|
||||||
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
|
|
||||||
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
|
|
||||||
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
|
|
||||||
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
|
|
||||||
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
|
|
||||||
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
|
|
||||||
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
|
|
||||||
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
|
|
||||||
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
|
|
||||||
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
|
|
||||||
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
|
|
||||||
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
|
|
||||||
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
|
|
||||||
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
|
|
||||||
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
|
|
||||||
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
|
|
||||||
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
|
|
||||||
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
|
|
||||||
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
|
|
||||||
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
|
|
||||||
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
|
|
||||||
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
|
|
||||||
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
|
|
||||||
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
|
|
||||||
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
|
|
||||||
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
|
|
||||||
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff)
|
|
||||||
|
|
||||||
#define h0(x) (x)
|
|
||||||
|
|
||||||
/* These defines are used to ensure tables are generated in the
|
|
||||||
right format depending on the internal byte order required
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define w0(p) bytes2word(p, 0, 0, 0)
|
|
||||||
#define w1(p) bytes2word(0, p, 0, 0)
|
|
||||||
#define w2(p) bytes2word(0, 0, p, 0)
|
|
||||||
#define w3(p) bytes2word(0, 0, 0, p)
|
|
||||||
|
|
||||||
#define u0(p) bytes2word(f2(p), p, p, f3(p))
|
|
||||||
#define u1(p) bytes2word(f3(p), f2(p), p, p)
|
|
||||||
#define u2(p) bytes2word(p, f3(p), f2(p), p)
|
|
||||||
#define u3(p) bytes2word(p, p, f3(p), f2(p))
|
|
||||||
|
|
||||||
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
|
|
||||||
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
|
|
||||||
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
|
|
||||||
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
|
|
||||||
|
|
||||||
const aes_32t t_dec(r,c)[RC_LENGTH] =
|
|
||||||
{
|
|
||||||
w0(0x01), w0(0x02), w0(0x04), w0(0x08), w0(0x10),
|
|
||||||
w0(0x20), w0(0x40), w0(0x80), w0(0x1b), w0(0x36)
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(__BORLANDC__)
|
|
||||||
#define concat(s1, s2) s1##s2
|
|
||||||
#define d_1(t,n,b,v) const t n[256] = { b(concat(v,0)) }
|
|
||||||
#define d_4(t,n,b,v) const t n[4][256] = { { b(concat(v,0)) }, { b(concat(v,1)) }, { b(concat(v,2)) }, { b(concat(v,3)) } }
|
|
||||||
#else
|
|
||||||
#define d_1(t,n,b,v) const t n[256] = { b(v##0) }
|
|
||||||
#define d_4(t,n,b,v) const t n[4][256] = { { b(v##0) }, { b(v##1) }, { b(v##2) }, { b(v##3) } }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* declare and instantiate tables for dynamic value generation in in tab.c */
|
|
||||||
|
|
||||||
aes_32t t_dec(r,c)[RC_LENGTH];
|
|
||||||
|
|
||||||
#define d_1(t,n,b,v) t n[256]
|
|
||||||
#define d_4(t,n,b,v) t n[4][256]
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* declare tables without instantiation */
|
|
||||||
|
|
||||||
#if defined(FIXED_TABLES)
|
|
||||||
|
|
||||||
extern const aes_32t t_dec(r,c)[RC_LENGTH];
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(TABLE_ALIGN)
|
|
||||||
#define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[256]
|
|
||||||
#define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[4][256]
|
|
||||||
#else
|
|
||||||
#define d_1(t,n,b,v) extern const t n[256]
|
|
||||||
#define d_4(t,n,b,v) extern const t n[4][256]
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
extern aes_32t t_dec(r,c)[RC_LENGTH];
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(TABLE_ALIGN)
|
|
||||||
#define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[256]
|
|
||||||
#define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[4][256]
|
|
||||||
#else
|
|
||||||
#define d_1(t,n,b,v) extern t n[256]
|
|
||||||
#define d_4(t,n,b,v) extern t n[4][256]
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SBX_SET
|
|
||||||
d_1(aes_08t, t_dec(s,box), sb_data, h);
|
|
||||||
#endif
|
|
||||||
#ifdef ISB_SET
|
|
||||||
d_1(aes_08t, t_dec(i,box), isb_data, h);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FT1_SET
|
|
||||||
d_1(aes_32t, t_dec(f,n), sb_data, u);
|
|
||||||
#endif
|
|
||||||
#ifdef FT4_SET
|
|
||||||
d_4(aes_32t, t_dec(f,n), sb_data, u);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FL1_SET
|
|
||||||
d_1(aes_32t, t_dec(f,l), sb_data, w);
|
|
||||||
#endif
|
|
||||||
#ifdef FL4_SET
|
|
||||||
d_4(aes_32t, t_dec(f,l), sb_data, w);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IT1_SET
|
|
||||||
d_1(aes_32t, t_dec(i,n), isb_data, v);
|
|
||||||
#endif
|
|
||||||
#ifdef IT4_SET
|
|
||||||
d_4(aes_32t, t_dec(i,n), isb_data, v);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IL1_SET
|
|
||||||
d_1(aes_32t, t_dec(i,l), isb_data, w);
|
|
||||||
#endif
|
|
||||||
#ifdef IL4_SET
|
|
||||||
d_4(aes_32t, t_dec(i,l), isb_data, w);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LS1_SET
|
|
||||||
#ifdef FL1_SET
|
|
||||||
#undef LS1_SET
|
|
||||||
#else
|
|
||||||
d_1(aes_32t, t_dec(l,s), sb_data, w);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LS4_SET
|
|
||||||
#ifdef FL4_SET
|
|
||||||
#undef LS4_SET
|
|
||||||
#else
|
|
||||||
d_4(aes_32t, t_dec(l,s), sb_data, w);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IM1_SET
|
|
||||||
d_1(aes_32t, t_dec(i,m), mm_data, v);
|
|
||||||
#endif
|
|
||||||
#ifdef IM4_SET
|
|
||||||
d_4(aes_32t, t_dec(i,m), mm_data, v);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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"
|
|
||||||
|
|
||||||
/* 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])
|
|
||||||
{
|
|
||||||
hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx);
|
|
||||||
memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */
|
|
||||||
return MAC_LENGTH(cx->mode); /* return MAC length in bytes */
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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 */
|
|
||||||
|
|
||||||
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) */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
Includes a bugfix from Dr Brian Gladman made on 16/04/2012 for compiling on 64-bit
|
|
||||||
|
|
||||||
This is an implementation of HMAC, the FIPS standard keyed hash function
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "hmac.h"
|
|
||||||
|
|
||||||
#define HMAC_IPAD (0x36 * (((unsigned long)-1) / 0xff))
|
|
||||||
#define HMAC_OPAD (0x5c * (((unsigned long)-1) / 0xff))
|
|
||||||
|
|
||||||
/* 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 > HMAC_HASH_INPUT_SIZE) /* if the key has to be hashed */
|
|
||||||
{
|
|
||||||
if(cx->klen <= HMAC_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 > HMAC_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 = HMAC_HASH_OUTPUT_SIZE; /* key and set new length */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pad the key if necessary */
|
|
||||||
memset(cx->key + cx->klen, 0, HMAC_HASH_INPUT_SIZE - cx->klen);
|
|
||||||
|
|
||||||
/* xor ipad into key value */
|
|
||||||
for(i = 0; i < HMAC_HASH_INPUT_SIZE / sizeof(unsigned long); ++i)
|
|
||||||
((unsigned long*)cx->key)[i] ^= HMAC_IPAD;
|
|
||||||
|
|
||||||
/* and start hash operation */
|
|
||||||
sha_begin(cx->ctx);
|
|
||||||
sha_hash(cx->key, HMAC_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[HMAC_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 < HMAC_HASH_INPUT_SIZE / sizeof(unsigned long); ++i)
|
|
||||||
((unsigned long*)cx->key)[i] ^= HMAC_OPAD ^ HMAC_IPAD;
|
|
||||||
|
|
||||||
/* perform the outer hash operation */
|
|
||||||
sha_begin(cx->ctx);
|
|
||||||
sha_hash(cx->key, HMAC_HASH_INPUT_SIZE, cx->ctx);
|
|
||||||
sha_hash(dig, HMAC_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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
Includes a bugfix from Dr Brian Gladman made on 16/04/2012 for compiling on 64-bit
|
|
||||||
|
|
||||||
This is an implementation of HMAC, the FIPS standard keyed hash function
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _HMAC_H
|
|
||||||
#define _HMAC_H
|
|
||||||
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#define USE_SHA1 // Irrlicht only cares about SHA1 for now
|
|
||||||
#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 HMAC_HASH_INPUT_SIZE SHA1_BLOCK_SIZE
|
|
||||||
#define HMAC_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 HMAC_HASH_INPUT_SIZE SHA256_BLOCK_SIZE
|
|
||||||
#define HMAC_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[HMAC_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);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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 <string.h>
|
|
||||||
#include "prng.h"
|
|
||||||
|
|
||||||
/* 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));
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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))
|
|
||||||
|
|
||||||
/* 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]);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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 <string.h>
|
|
||||||
#include "hmac.h"
|
|
||||||
|
|
||||||
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[HMAC_HASH_OUTPUT_SIZE], ux[HMAC_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) / HMAC_HASH_OUTPUT_SIZE;
|
|
||||||
|
|
||||||
for(i = 0; i < n_blk; ++i) /* for each block in key */
|
|
||||||
{
|
|
||||||
/* ux[] holds the running xor value */
|
|
||||||
memset(ux, 0, HMAC_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, HMAC_HASH_OUTPUT_SIZE, c3);
|
|
||||||
|
|
||||||
/* xor into the running xor block */
|
|
||||||
for(k = 0; k < HMAC_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 * HMAC_HASH_OUTPUT_SIZE;
|
|
||||||
while(j < HMAC_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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"
|
|
||||||
#include "../os.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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) */
|
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
|
|
||||||
|
|
||||||
#if (PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN)
|
|
||||||
#define swap_b32(x) (x)
|
|
||||||
#else
|
|
||||||
#define swap_b32(x) irr::os::Byteswap::byteswap(x)
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,629 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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"
|
|
||||||
#include "../os.h"
|
|
||||||
|
|
||||||
/* 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) */
|
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
|
|
||||||
#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) irr::os::Byteswap::byteswap(x)
|
|
||||||
#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;
|
|
||||||
/* Falls through. */
|
|
||||||
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;
|
|
||||||
/* Falls through. */
|
|
||||||
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;
|
|
||||||
/* Falls through. */
|
|
||||||
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
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
|||||||
/*
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
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 "irrMath.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 defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
#if (_MSC_VER < 1300) || (__BORLANDC__ < 0x582)
|
|
||||||
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
|
|
||||||
#else
|
|
||||||
#ifdef _IRR_SOLARIS_PLATFORM_
|
|
||||||
#include <sys/int_types.h>
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
typedef uint64_t sha2_64t;
|
|
||||||
#if __WORDSIZE==64
|
|
||||||
#define s_u64 ul
|
|
||||||
#else
|
|
||||||
#define s_u64 ull
|
|
||||||
#endif
|
|
||||||
#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);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,999 +0,0 @@
|
|||||||
/* LzmaDec.c -- LZMA Decoder
|
|
||||||
2009-09-20 : Igor Pavlov : Public domain */
|
|
||||||
|
|
||||||
#include "LzmaDec.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_INIT_SIZE 5
|
|
||||||
|
|
||||||
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
|
|
||||||
|
|
||||||
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
|
||||||
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
|
||||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
|
|
||||||
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
|
|
||||||
{ UPDATE_0(p); i = (i + i); A0; } else \
|
|
||||||
{ UPDATE_1(p); i = (i + i) + 1; A1; }
|
|
||||||
#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
|
|
||||||
|
|
||||||
#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
|
|
||||||
#define TREE_DECODE(probs, limit, i) \
|
|
||||||
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
|
|
||||||
|
|
||||||
/* #define _LZMA_SIZE_OPT */
|
|
||||||
|
|
||||||
#ifdef _LZMA_SIZE_OPT
|
|
||||||
#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
|
|
||||||
#else
|
|
||||||
#define TREE_6_DECODE(probs, i) \
|
|
||||||
{ i = 1; \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
TREE_GET_BIT(probs, i); \
|
|
||||||
i -= 0x40; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
|
|
||||||
|
|
||||||
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
|
||||||
#define UPDATE_0_CHECK range = bound;
|
|
||||||
#define UPDATE_1_CHECK range -= bound; code -= bound;
|
|
||||||
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
|
|
||||||
{ UPDATE_0_CHECK; i = (i + i); A0; } else \
|
|
||||||
{ UPDATE_1_CHECK; i = (i + i) + 1; A1; }
|
|
||||||
#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
|
|
||||||
#define TREE_DECODE_CHECK(probs, limit, i) \
|
|
||||||
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#define LZMA_BASE_SIZE 1846
|
|
||||||
#define LZMA_LIT_SIZE 768
|
|
||||||
|
|
||||||
#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_DIC_MIN (1 << 12)
|
|
||||||
|
|
||||||
/* First LZMA-symbol is always decoded.
|
|
||||||
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
|
|
||||||
Out:
|
|
||||||
Result:
|
|
||||||
SZ_OK - OK
|
|
||||||
SZ_ERROR_DATA - Error
|
|
||||||
p->remainLen:
|
|
||||||
< kMatchSpecLenStart : normal remain
|
|
||||||
= kMatchSpecLenStart : finished
|
|
||||||
= kMatchSpecLenStart + 1 : Flush marker
|
|
||||||
= kMatchSpecLenStart + 2 : State Init Marker
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
|
||||||
{
|
|
||||||
CLzmaProb *probs = p->probs;
|
|
||||||
|
|
||||||
unsigned state = p->state;
|
|
||||||
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
|
|
||||||
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
|
|
||||||
unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
|
|
||||||
unsigned lc = p->prop.lc;
|
|
||||||
|
|
||||||
Byte *dic = p->dic;
|
|
||||||
SizeT dicBufSize = p->dicBufSize;
|
|
||||||
SizeT dicPos = p->dicPos;
|
|
||||||
|
|
||||||
UInt32 processedPos = p->processedPos;
|
|
||||||
UInt32 checkDicSize = p->checkDicSize;
|
|
||||||
unsigned len = 0;
|
|
||||||
|
|
||||||
const Byte *buf = p->buf;
|
|
||||||
UInt32 range = p->range;
|
|
||||||
UInt32 code = p->code;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CLzmaProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
unsigned ttt;
|
|
||||||
unsigned posState = processedPos & pbMask;
|
|
||||||
|
|
||||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
unsigned symbol;
|
|
||||||
UPDATE_0(prob);
|
|
||||||
prob = probs + Literal;
|
|
||||||
if (checkDicSize != 0 || processedPos != 0)
|
|
||||||
prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
|
|
||||||
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state < kNumLitStates)
|
|
||||||
{
|
|
||||||
state -= (state < 4) ? state : 3;
|
|
||||||
symbol = 1;
|
|
||||||
do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
|
||||||
unsigned offs = 0x100;
|
|
||||||
state -= (state < 10) ? 3 : 6;
|
|
||||||
symbol = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
unsigned bit;
|
|
||||||
CLzmaProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & offs);
|
|
||||||
probLit = prob + offs + bit + symbol;
|
|
||||||
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
dic[dicPos++] = (Byte)symbol;
|
|
||||||
processedPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(prob);
|
|
||||||
prob = probs + IsRep + state;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0(prob);
|
|
||||||
state += kNumStates;
|
|
||||||
prob = probs + LenCoder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(prob);
|
|
||||||
if (checkDicSize == 0 && processedPos == 0)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
prob = probs + IsRepG0 + state;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0(prob);
|
|
||||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0(prob);
|
|
||||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
|
||||||
dicPos++;
|
|
||||||
processedPos++;
|
|
||||||
state = state < kNumLitStates ? 9 : 11;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
UPDATE_1(prob);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
UPDATE_1(prob);
|
|
||||||
prob = probs + IsRepG1 + state;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0(prob);
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(prob);
|
|
||||||
prob = probs + IsRepG2 + state;
|
|
||||||
IF_BIT_0(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0(prob);
|
|
||||||
distance = rep2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(prob);
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
state = state < kNumLitStates ? 8 : 11;
|
|
||||||
prob = probs + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
unsigned limit, offset;
|
|
||||||
CLzmaProb *probLen = prob + LenChoice;
|
|
||||||
IF_BIT_0(probLen)
|
|
||||||
{
|
|
||||||
UPDATE_0(probLen);
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
limit = (1 << kLenNumLowBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(probLen);
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IF_BIT_0(probLen)
|
|
||||||
{
|
|
||||||
UPDATE_0(probLen);
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
limit = (1 << kLenNumMidBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1(probLen);
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
limit = (1 << kLenNumHighBits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TREE_DECODE(probLen, limit, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state >= kNumStates)
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
prob = probs + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
|
|
||||||
TREE_6_DECODE(prob, distance);
|
|
||||||
if (distance >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
unsigned posSlot = (unsigned)distance;
|
|
||||||
int numDirectBits = (int)(((distance >> 1) - 1));
|
|
||||||
distance = (2 | (distance & 1));
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
distance <<= numDirectBits;
|
|
||||||
prob = probs + SpecPos + distance - posSlot - 1;
|
|
||||||
{
|
|
||||||
UInt32 mask = 1;
|
|
||||||
unsigned i = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
GET_BIT2(prob + i, i, ; , distance |= mask);
|
|
||||||
mask <<= 1;
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
NORMALIZE
|
|
||||||
range >>= 1;
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 t;
|
|
||||||
code -= range;
|
|
||||||
t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
|
|
||||||
distance = (distance << 1) + (t + 1);
|
|
||||||
code += range & t;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
distance <<= 1;
|
|
||||||
if (code >= range)
|
|
||||||
{
|
|
||||||
code -= range;
|
|
||||||
distance |= 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = probs + Align;
|
|
||||||
distance <<= kNumAlignBits;
|
|
||||||
{
|
|
||||||
unsigned i = 1;
|
|
||||||
GET_BIT2(prob + i, i, ; , distance |= 1);
|
|
||||||
GET_BIT2(prob + i, i, ; , distance |= 2);
|
|
||||||
GET_BIT2(prob + i, i, ; , distance |= 4);
|
|
||||||
GET_BIT2(prob + i, i, ; , distance |= 8);
|
|
||||||
}
|
|
||||||
if (distance == (UInt32)0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
len += kMatchSpecLenStart;
|
|
||||||
state -= kNumStates;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance + 1;
|
|
||||||
if (checkDicSize == 0)
|
|
||||||
{
|
|
||||||
if (distance >= processedPos)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
}
|
|
||||||
else if (distance >= checkDicSize)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
|
|
||||||
if (limit == dicPos)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
{
|
|
||||||
SizeT rem = limit - dicPos;
|
|
||||||
unsigned curLen = ((rem < len) ? (unsigned)rem : len);
|
|
||||||
SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
|
|
||||||
|
|
||||||
processedPos += curLen;
|
|
||||||
|
|
||||||
len -= curLen;
|
|
||||||
if (pos + curLen <= dicBufSize)
|
|
||||||
{
|
|
||||||
Byte *dest = dic + dicPos;
|
|
||||||
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
|
|
||||||
const Byte *lim = dest + curLen;
|
|
||||||
dicPos += curLen;
|
|
||||||
do
|
|
||||||
*(dest) = (Byte)*(dest + src);
|
|
||||||
while (++dest != lim);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
dic[dicPos++] = dic[pos];
|
|
||||||
if (++pos == dicBufSize)
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
while (--curLen != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (dicPos < limit && buf < bufLimit);
|
|
||||||
NORMALIZE;
|
|
||||||
p->buf = buf;
|
|
||||||
p->range = range;
|
|
||||||
p->code = code;
|
|
||||||
p->remainLen = len;
|
|
||||||
p->dicPos = dicPos;
|
|
||||||
p->processedPos = processedPos;
|
|
||||||
p->reps[0] = rep0;
|
|
||||||
p->reps[1] = rep1;
|
|
||||||
p->reps[2] = rep2;
|
|
||||||
p->reps[3] = rep3;
|
|
||||||
p->state = state;
|
|
||||||
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
|
||||||
{
|
|
||||||
if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
|
|
||||||
{
|
|
||||||
Byte *dic = p->dic;
|
|
||||||
SizeT dicPos = p->dicPos;
|
|
||||||
SizeT dicBufSize = p->dicBufSize;
|
|
||||||
unsigned len = p->remainLen;
|
|
||||||
UInt32 rep0 = p->reps[0];
|
|
||||||
if (limit - dicPos < len)
|
|
||||||
len = (unsigned)(limit - dicPos);
|
|
||||||
|
|
||||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
|
|
||||||
p->checkDicSize = p->prop.dicSize;
|
|
||||||
|
|
||||||
p->processedPos += len;
|
|
||||||
p->remainLen -= len;
|
|
||||||
while (len-- != 0)
|
|
||||||
{
|
|
||||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
|
||||||
dicPos++;
|
|
||||||
}
|
|
||||||
p->dicPos = dicPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SizeT limit2 = limit;
|
|
||||||
if (p->checkDicSize == 0)
|
|
||||||
{
|
|
||||||
UInt32 rem = p->prop.dicSize - p->processedPos;
|
|
||||||
if (limit - p->dicPos > rem)
|
|
||||||
limit2 = p->dicPos + rem;
|
|
||||||
}
|
|
||||||
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
|
|
||||||
if (p->processedPos >= p->prop.dicSize)
|
|
||||||
p->checkDicSize = p->prop.dicSize;
|
|
||||||
LzmaDec_WriteRem(p, limit);
|
|
||||||
}
|
|
||||||
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
|
|
||||||
|
|
||||||
if (p->remainLen > kMatchSpecLenStart)
|
|
||||||
{
|
|
||||||
p->remainLen = kMatchSpecLenStart;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
DUMMY_ERROR, /* unexpected end of input stream */
|
|
||||||
DUMMY_LIT,
|
|
||||||
DUMMY_MATCH,
|
|
||||||
DUMMY_REP
|
|
||||||
} ELzmaDummy;
|
|
||||||
|
|
||||||
static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
|
|
||||||
{
|
|
||||||
UInt32 range = p->range;
|
|
||||||
UInt32 code = p->code;
|
|
||||||
const Byte *bufLimit = buf + inSize;
|
|
||||||
CLzmaProb *probs = p->probs;
|
|
||||||
unsigned state = p->state;
|
|
||||||
ELzmaDummy res;
|
|
||||||
|
|
||||||
{
|
|
||||||
CLzmaProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
unsigned ttt;
|
|
||||||
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
|
|
||||||
|
|
||||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK
|
|
||||||
|
|
||||||
/* if (bufLimit - buf >= 7) return DUMMY_LIT; */
|
|
||||||
|
|
||||||
prob = probs + Literal;
|
|
||||||
if (p->checkDicSize != 0 || p->processedPos != 0)
|
|
||||||
prob += (LZMA_LIT_SIZE *
|
|
||||||
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
|
|
||||||
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
|
|
||||||
|
|
||||||
if (state < kNumLitStates)
|
|
||||||
{
|
|
||||||
unsigned symbol = 1;
|
|
||||||
do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
|
|
||||||
((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
|
|
||||||
unsigned offs = 0x100;
|
|
||||||
unsigned symbol = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
unsigned bit;
|
|
||||||
CLzmaProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & offs);
|
|
||||||
probLit = prob + offs + bit + symbol;
|
|
||||||
GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
res = DUMMY_LIT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned len;
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
|
|
||||||
prob = probs + IsRep + state;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
state = 0;
|
|
||||||
prob = probs + LenCoder;
|
|
||||||
res = DUMMY_MATCH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
res = DUMMY_REP;
|
|
||||||
prob = probs + IsRepG0 + state;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
NORMALIZE_CHECK;
|
|
||||||
return DUMMY_REP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
prob = probs + IsRepG1 + state;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
prob = probs + IsRepG2 + state;
|
|
||||||
IF_BIT_0_CHECK(prob)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state = kNumStates;
|
|
||||||
prob = probs + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
unsigned limit, offset;
|
|
||||||
CLzmaProb *probLen = prob + LenChoice;
|
|
||||||
IF_BIT_0_CHECK(probLen)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
limit = 1 << kLenNumLowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IF_BIT_0_CHECK(probLen)
|
|
||||||
{
|
|
||||||
UPDATE_0_CHECK;
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
limit = 1 << kLenNumMidBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UPDATE_1_CHECK;
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
limit = 1 << kLenNumHighBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TREE_DECODE_CHECK(probLen, limit, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state < 4)
|
|
||||||
{
|
|
||||||
unsigned posSlot;
|
|
||||||
prob = probs + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits);
|
|
||||||
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
|
|
||||||
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
|
|
||||||
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
NORMALIZE_CHECK
|
|
||||||
range >>= 1;
|
|
||||||
code -= range & (((code - range) >> 31) - 1);
|
|
||||||
/* if (code >= range) code -= range; */
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = probs + Align;
|
|
||||||
numDirectBits = kNumAlignBits;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
unsigned i = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
GET_BIT_CHECK(prob + i, i);
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NORMALIZE_CHECK;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
|
|
||||||
{
|
|
||||||
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
|
|
||||||
p->range = 0xFFFFFFFF;
|
|
||||||
p->needFlush = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
|
||||||
{
|
|
||||||
p->needFlush = 1;
|
|
||||||
p->remainLen = 0;
|
|
||||||
p->tempBufSize = 0;
|
|
||||||
|
|
||||||
if (initDic)
|
|
||||||
{
|
|
||||||
p->processedPos = 0;
|
|
||||||
p->checkDicSize = 0;
|
|
||||||
p->needInitState = 1;
|
|
||||||
}
|
|
||||||
if (initState)
|
|
||||||
p->needInitState = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LzmaDec_Init(CLzmaDec *p)
|
|
||||||
{
|
|
||||||
p->dicPos = 0;
|
|
||||||
LzmaDec_InitDicAndState(p, True, True);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LzmaDec_InitStateReal(CLzmaDec *p)
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
|
|
||||||
UInt32 i;
|
|
||||||
CLzmaProb *probs = p->probs;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
probs[i] = kBitModelTotal >> 1;
|
|
||||||
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
|
|
||||||
p->state = 0;
|
|
||||||
p->needInitState = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
|
|
||||||
ELzmaFinishMode finishMode, ELzmaStatus *status)
|
|
||||||
{
|
|
||||||
SizeT inSize = *srcLen;
|
|
||||||
(*srcLen) = 0;
|
|
||||||
LzmaDec_WriteRem(p, dicLimit);
|
|
||||||
|
|
||||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
|
||||||
|
|
||||||
while (p->remainLen != kMatchSpecLenStart)
|
|
||||||
{
|
|
||||||
int checkEndMarkNow;
|
|
||||||
|
|
||||||
if (p->needFlush != 0)
|
|
||||||
{
|
|
||||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
|
||||||
p->tempBuf[p->tempBufSize++] = *src++;
|
|
||||||
if (p->tempBufSize < RC_INIT_SIZE)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (p->tempBuf[0] != 0)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
|
|
||||||
LzmaDec_InitRc(p, p->tempBuf);
|
|
||||||
p->tempBufSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEndMarkNow = 0;
|
|
||||||
if (p->dicPos >= dicLimit)
|
|
||||||
{
|
|
||||||
if (p->remainLen == 0 && p->code == 0)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (finishMode == LZMA_FINISH_ANY)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (p->remainLen != 0)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
}
|
|
||||||
checkEndMarkNow = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->needInitState)
|
|
||||||
LzmaDec_InitStateReal(p);
|
|
||||||
|
|
||||||
if (p->tempBufSize == 0)
|
|
||||||
{
|
|
||||||
SizeT processed;
|
|
||||||
const Byte *bufLimit;
|
|
||||||
if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
|
||||||
{
|
|
||||||
int dummyRes = LzmaDec_TryDummy(p, src, inSize);
|
|
||||||
if (dummyRes == DUMMY_ERROR)
|
|
||||||
{
|
|
||||||
memcpy(p->tempBuf, src, inSize);
|
|
||||||
p->tempBufSize = (unsigned)inSize;
|
|
||||||
(*srcLen) += inSize;
|
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
}
|
|
||||||
bufLimit = src;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
|
|
||||||
p->buf = src;
|
|
||||||
if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
processed = (SizeT)(p->buf - src);
|
|
||||||
(*srcLen) += processed;
|
|
||||||
src += processed;
|
|
||||||
inSize -= processed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned rem = p->tempBufSize, lookAhead = 0;
|
|
||||||
while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
|
|
||||||
p->tempBuf[rem++] = src[lookAhead++];
|
|
||||||
p->tempBufSize = rem;
|
|
||||||
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
|
||||||
{
|
|
||||||
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
|
|
||||||
if (dummyRes == DUMMY_ERROR)
|
|
||||||
{
|
|
||||||
(*srcLen) += lookAhead;
|
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
|
||||||
{
|
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p->buf = p->tempBuf;
|
|
||||||
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
|
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
|
|
||||||
(*srcLen) += lookAhead;
|
|
||||||
src += lookAhead;
|
|
||||||
inSize -= lookAhead;
|
|
||||||
p->tempBufSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p->code == 0)
|
|
||||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
|
||||||
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
|
||||||
{
|
|
||||||
SizeT outSize = *destLen;
|
|
||||||
SizeT inSize = *srcLen;
|
|
||||||
*srcLen = *destLen = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
SizeT inSizeCur = inSize, outSizeCur, dicPos;
|
|
||||||
ELzmaFinishMode curFinishMode;
|
|
||||||
SRes res;
|
|
||||||
if (p->dicPos == p->dicBufSize)
|
|
||||||
p->dicPos = 0;
|
|
||||||
dicPos = p->dicPos;
|
|
||||||
if (outSize > p->dicBufSize - dicPos)
|
|
||||||
{
|
|
||||||
outSizeCur = p->dicBufSize;
|
|
||||||
curFinishMode = LZMA_FINISH_ANY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outSizeCur = dicPos + outSize;
|
|
||||||
curFinishMode = finishMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
|
|
||||||
src += inSizeCur;
|
|
||||||
inSize -= inSizeCur;
|
|
||||||
*srcLen += inSizeCur;
|
|
||||||
outSizeCur = p->dicPos - dicPos;
|
|
||||||
memcpy(dest, p->dic + dicPos, outSizeCur);
|
|
||||||
dest += outSizeCur;
|
|
||||||
outSize -= outSizeCur;
|
|
||||||
*destLen += outSizeCur;
|
|
||||||
if (res != 0)
|
|
||||||
return res;
|
|
||||||
if (outSizeCur == 0 || outSize == 0)
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
alloc->Free(alloc, p->probs);
|
|
||||||
p->probs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
alloc->Free(alloc, p->dic);
|
|
||||||
p->dic = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
LzmaDec_FreeProbs(p, alloc);
|
|
||||||
LzmaDec_FreeDict(p, alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
|
|
||||||
{
|
|
||||||
UInt32 dicSize;
|
|
||||||
Byte d;
|
|
||||||
|
|
||||||
if (size < LZMA_PROPS_SIZE)
|
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
|
||||||
else
|
|
||||||
dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
|
|
||||||
|
|
||||||
if (dicSize < LZMA_DIC_MIN)
|
|
||||||
dicSize = LZMA_DIC_MIN;
|
|
||||||
p->dicSize = dicSize;
|
|
||||||
|
|
||||||
d = data[0];
|
|
||||||
if (d >= (9 * 5 * 5))
|
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
|
||||||
|
|
||||||
p->lc = d % 9;
|
|
||||||
d /= 9;
|
|
||||||
p->pb = d / 5;
|
|
||||||
p->lp = d % 5;
|
|
||||||
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
|
|
||||||
if (p->probs == 0 || numProbs != p->numProbs)
|
|
||||||
{
|
|
||||||
LzmaDec_FreeProbs(p, alloc);
|
|
||||||
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
|
|
||||||
p->numProbs = numProbs;
|
|
||||||
if (p->probs == 0)
|
|
||||||
return SZ_ERROR_MEM;
|
|
||||||
}
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
CLzmaProps propNew;
|
|
||||||
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
|
|
||||||
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
|
|
||||||
p->prop = propNew;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
CLzmaProps propNew;
|
|
||||||
SizeT dicBufSize;
|
|
||||||
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
|
|
||||||
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
|
|
||||||
dicBufSize = propNew.dicSize;
|
|
||||||
if (p->dic == 0 || dicBufSize != p->dicBufSize)
|
|
||||||
{
|
|
||||||
LzmaDec_FreeDict(p, alloc);
|
|
||||||
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
|
|
||||||
if (p->dic == 0)
|
|
||||||
{
|
|
||||||
LzmaDec_FreeProbs(p, alloc);
|
|
||||||
return SZ_ERROR_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p->dicBufSize = dicBufSize;
|
|
||||||
p->prop = propNew;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
|
||||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
|
||||||
ELzmaStatus *status, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
CLzmaDec p;
|
|
||||||
SRes res;
|
|
||||||
SizeT inSize = *srcLen;
|
|
||||||
SizeT outSize = *destLen;
|
|
||||||
*srcLen = *destLen = 0;
|
|
||||||
if (inSize < RC_INIT_SIZE)
|
|
||||||
return SZ_ERROR_INPUT_EOF;
|
|
||||||
|
|
||||||
LzmaDec_Construct(&p);
|
|
||||||
res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
|
|
||||||
if (res != 0)
|
|
||||||
return res;
|
|
||||||
p.dic = dest;
|
|
||||||
p.dicBufSize = outSize;
|
|
||||||
|
|
||||||
LzmaDec_Init(&p);
|
|
||||||
|
|
||||||
*srcLen = inSize;
|
|
||||||
res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
|
||||||
|
|
||||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
|
||||||
res = SZ_ERROR_INPUT_EOF;
|
|
||||||
|
|
||||||
(*destLen) = p.dicPos;
|
|
||||||
LzmaDec_FreeProbs(&p, alloc);
|
|
||||||
return res;
|
|
||||||
}
|
|
@ -1,231 +0,0 @@
|
|||||||
/* LzmaDec.h -- LZMA Decoder
|
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
|
||||||
|
|
||||||
#ifndef __LZMA_DEC_H
|
|
||||||
#define __LZMA_DEC_H
|
|
||||||
|
|
||||||
#include "Types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
|
||||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
|
||||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CLzmaProb UInt32
|
|
||||||
#else
|
|
||||||
#define CLzmaProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Properties ---------- */
|
|
||||||
|
|
||||||
#define LZMA_PROPS_SIZE 5
|
|
||||||
|
|
||||||
typedef struct _CLzmaProps
|
|
||||||
{
|
|
||||||
unsigned lc, lp, pb;
|
|
||||||
UInt32 dicSize;
|
|
||||||
} CLzmaProps;
|
|
||||||
|
|
||||||
/* LzmaProps_Decode - decodes properties
|
|
||||||
Returns:
|
|
||||||
SZ_OK
|
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
|
||||||
*/
|
|
||||||
|
|
||||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Decoder state ---------- */
|
|
||||||
|
|
||||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
|
||||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
|
||||||
|
|
||||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CLzmaProps prop;
|
|
||||||
CLzmaProb *probs;
|
|
||||||
Byte *dic;
|
|
||||||
const Byte *buf;
|
|
||||||
UInt32 range, code;
|
|
||||||
SizeT dicPos;
|
|
||||||
SizeT dicBufSize;
|
|
||||||
UInt32 processedPos;
|
|
||||||
UInt32 checkDicSize;
|
|
||||||
unsigned state;
|
|
||||||
UInt32 reps[4];
|
|
||||||
unsigned remainLen;
|
|
||||||
int needFlush;
|
|
||||||
int needInitState;
|
|
||||||
UInt32 numProbs;
|
|
||||||
unsigned tempBufSize;
|
|
||||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
|
||||||
} CLzmaDec;
|
|
||||||
|
|
||||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
|
||||||
|
|
||||||
void LzmaDec_Init(CLzmaDec *p);
|
|
||||||
|
|
||||||
/* There are two types of LZMA streams:
|
|
||||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
|
||||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
LZMA_FINISH_ANY, /* finish at any point */
|
|
||||||
LZMA_FINISH_END /* block must be finished at the end */
|
|
||||||
} ELzmaFinishMode;
|
|
||||||
|
|
||||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
|
||||||
|
|
||||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
|
||||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
|
||||||
|
|
||||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
|
||||||
and output value of destLen will be less than output buffer size limit.
|
|
||||||
You can check status result also.
|
|
||||||
|
|
||||||
You can use multiple checks to test data integrity after full decompression:
|
|
||||||
1) Check Result and "status" variable.
|
|
||||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
|
||||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
|
||||||
You must use correct finish mode in that case. */
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
|
||||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
|
||||||
} ELzmaStatus;
|
|
||||||
|
|
||||||
/* ELzmaStatus is used only as output value for function call */
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Interfaces ---------- */
|
|
||||||
|
|
||||||
/* There are 3 levels of interfaces:
|
|
||||||
1) Dictionary Interface
|
|
||||||
2) Buffer Interface
|
|
||||||
3) One Call Interface
|
|
||||||
You can select any of these interfaces, but don't mix functions from different
|
|
||||||
groups for same object. */
|
|
||||||
|
|
||||||
|
|
||||||
/* There are two variants to allocate state for Dictionary Interface:
|
|
||||||
1) LzmaDec_Allocate / LzmaDec_Free
|
|
||||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
|
||||||
You can use variant 2, if you set dictionary buffer manually.
|
|
||||||
For Buffer Interface you must always use variant 1.
|
|
||||||
|
|
||||||
LzmaDec_Allocate* can return:
|
|
||||||
SZ_OK
|
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
|
||||||
*/
|
|
||||||
|
|
||||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
|
||||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
|
||||||
|
|
||||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
|
||||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
|
||||||
|
|
||||||
/* ---------- Dictionary Interface ---------- */
|
|
||||||
|
|
||||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
|
||||||
dictionary to some other external buffer.
|
|
||||||
You must work with CLzmaDec variables directly in this interface.
|
|
||||||
|
|
||||||
STEPS:
|
|
||||||
LzmaDec_Constr()
|
|
||||||
LzmaDec_Allocate()
|
|
||||||
for (each new stream)
|
|
||||||
{
|
|
||||||
LzmaDec_Init()
|
|
||||||
while (it needs more decompression)
|
|
||||||
{
|
|
||||||
LzmaDec_DecodeToDic()
|
|
||||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LzmaDec_Free()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* LzmaDec_DecodeToDic
|
|
||||||
|
|
||||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
|
||||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
|
||||||
|
|
||||||
finishMode:
|
|
||||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
|
||||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
|
||||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
SZ_OK
|
|
||||||
status:
|
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
|
||||||
LZMA_STATUS_NOT_FINISHED
|
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
|
||||||
SZ_ERROR_DATA - Data error
|
|
||||||
*/
|
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Buffer Interface ---------- */
|
|
||||||
|
|
||||||
/* It's zlib-like interface.
|
|
||||||
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
|
||||||
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
|
||||||
to work with CLzmaDec variables manually.
|
|
||||||
|
|
||||||
finishMode:
|
|
||||||
It has meaning only if the decoding reaches output limit (*destLen).
|
|
||||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
|
||||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
|
||||||
*/
|
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------- One Call Interface ---------- */
|
|
||||||
|
|
||||||
/* LzmaDecode
|
|
||||||
|
|
||||||
finishMode:
|
|
||||||
It has meaning only if the decoding reaches output limit (*destLen).
|
|
||||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
|
||||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
SZ_OK
|
|
||||||
status:
|
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
|
||||||
LZMA_STATUS_NOT_FINISHED
|
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
|
||||||
SZ_ERROR_DATA - Data error
|
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
|
||||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
|
||||||
*/
|
|
||||||
|
|
||||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
|
||||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
|
||||||
ELzmaStatus *status, ISzAlloc *alloc);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,254 +0,0 @@
|
|||||||
/* Types.h -- Basic types
|
|
||||||
2010-10-09 : Igor Pavlov : Public domain */
|
|
||||||
|
|
||||||
#ifndef __7Z_TYPES_H
|
|
||||||
#define __7Z_TYPES_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EXTERN_C_BEGIN
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define EXTERN_C_BEGIN extern "C" {
|
|
||||||
#define EXTERN_C_END }
|
|
||||||
#else
|
|
||||||
#define EXTERN_C_BEGIN
|
|
||||||
#define EXTERN_C_END
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
|
||||||
|
|
||||||
#define SZ_OK 0
|
|
||||||
|
|
||||||
#define SZ_ERROR_DATA 1
|
|
||||||
#define SZ_ERROR_MEM 2
|
|
||||||
#define SZ_ERROR_CRC 3
|
|
||||||
#define SZ_ERROR_UNSUPPORTED 4
|
|
||||||
#define SZ_ERROR_PARAM 5
|
|
||||||
#define SZ_ERROR_INPUT_EOF 6
|
|
||||||
#define SZ_ERROR_OUTPUT_EOF 7
|
|
||||||
#define SZ_ERROR_READ 8
|
|
||||||
#define SZ_ERROR_WRITE 9
|
|
||||||
#define SZ_ERROR_PROGRESS 10
|
|
||||||
#define SZ_ERROR_FAIL 11
|
|
||||||
#define SZ_ERROR_THREAD 12
|
|
||||||
|
|
||||||
#define SZ_ERROR_ARCHIVE 16
|
|
||||||
#define SZ_ERROR_NO_ARCHIVE 17
|
|
||||||
|
|
||||||
typedef int SRes;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
typedef DWORD WRes;
|
|
||||||
#else
|
|
||||||
typedef int WRes;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RINOK
|
|
||||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
typedef short Int16;
|
|
||||||
typedef unsigned short UInt16;
|
|
||||||
|
|
||||||
#ifdef _LZMA_UINT32_IS_ULONG
|
|
||||||
typedef long Int32;
|
|
||||||
typedef unsigned long UInt32;
|
|
||||||
#else
|
|
||||||
typedef int Int32;
|
|
||||||
typedef unsigned int UInt32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _SZ_NO_INT_64
|
|
||||||
|
|
||||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
|
||||||
NOTES: Some code will work incorrectly in that case! */
|
|
||||||
|
|
||||||
typedef long Int64;
|
|
||||||
typedef unsigned long UInt64;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
typedef __int64 Int64;
|
|
||||||
typedef unsigned __int64 UInt64;
|
|
||||||
#define UINT64_CONST(n) n
|
|
||||||
#else
|
|
||||||
typedef long long int Int64;
|
|
||||||
typedef unsigned long long int UInt64;
|
|
||||||
#define UINT64_CONST(n) n ## ULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
|
||||||
typedef UInt32 SizeT;
|
|
||||||
#else
|
|
||||||
typedef size_t SizeT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int Bool;
|
|
||||||
#define True 1
|
|
||||||
#define False 0
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define MY_STD_CALL __stdcall
|
|
||||||
#else
|
|
||||||
#define MY_STD_CALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1300
|
|
||||||
#define MY_NO_INLINE __declspec(noinline)
|
|
||||||
#else
|
|
||||||
#define MY_NO_INLINE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MY_CDECL __cdecl
|
|
||||||
#define MY_FAST_CALL __fastcall
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define MY_CDECL
|
|
||||||
#define MY_FAST_CALL
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* The following interfaces use first parameter as pointer to structure */
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
|
||||||
} IByteIn;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void (*Write)(void *p, Byte b);
|
|
||||||
} IByteOut;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
|
||||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
|
||||||
(output(*size) < input(*size)) is allowed */
|
|
||||||
} ISeqInStream;
|
|
||||||
|
|
||||||
/* it can return SZ_ERROR_INPUT_EOF */
|
|
||||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
|
||||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
|
||||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
|
||||||
/* Returns: result - the number of actually written bytes.
|
|
||||||
(result < size) means error */
|
|
||||||
} ISeqOutStream;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
SZ_SEEK_SET = 0,
|
|
||||||
SZ_SEEK_CUR = 1,
|
|
||||||
SZ_SEEK_END = 2
|
|
||||||
} ESzSeek;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
|
||||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
|
||||||
} ISeekInStream;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
SRes (*Look)(void *p, const void **buf, size_t *size);
|
|
||||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
|
||||||
(output(*size) > input(*size)) is not allowed
|
|
||||||
(output(*size) < input(*size)) is allowed */
|
|
||||||
SRes (*Skip)(void *p, size_t offset);
|
|
||||||
/* offset must be <= output(*size) of Look */
|
|
||||||
|
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
|
||||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
|
||||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
|
||||||
} ILookInStream;
|
|
||||||
|
|
||||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
|
||||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
|
||||||
|
|
||||||
/* reads via ILookInStream::Read */
|
|
||||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
|
||||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
|
||||||
|
|
||||||
#define LookToRead_BUF_SIZE (1 << 14)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ILookInStream s;
|
|
||||||
ISeekInStream *realStream;
|
|
||||||
size_t pos;
|
|
||||||
size_t size;
|
|
||||||
Byte buf[LookToRead_BUF_SIZE];
|
|
||||||
} CLookToRead;
|
|
||||||
|
|
||||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
|
||||||
void LookToRead_Init(CLookToRead *p);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ISeqInStream s;
|
|
||||||
ILookInStream *realStream;
|
|
||||||
} CSecToLook;
|
|
||||||
|
|
||||||
void SecToLook_CreateVTable(CSecToLook *p);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ISeqInStream s;
|
|
||||||
ILookInStream *realStream;
|
|
||||||
} CSecToRead;
|
|
||||||
|
|
||||||
void SecToRead_CreateVTable(CSecToRead *p);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
|
||||||
/* Returns: result. (result != SZ_OK) means break.
|
|
||||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
|
||||||
} ICompressProgress;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *(*Alloc)(void *p, size_t size);
|
|
||||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
|
||||||
} ISzAlloc;
|
|
||||||
|
|
||||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
|
||||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
#define CHAR_PATH_SEPARATOR '\\'
|
|
||||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
|
||||||
#define STRING_PATH_SEPARATOR "\\"
|
|
||||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define CHAR_PATH_SEPARATOR '/'
|
|
||||||
#define WCHAR_PATH_SEPARATOR L'/'
|
|
||||||
#define STRING_PATH_SEPARATOR "/"
|
|
||||||
#define WSTRING_PATH_SEPARATOR L"/"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EXTERN_C_END
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user