Add project files.

This commit is contained in:
Gabriel Tofvesson 2017-09-29 00:47:33 +02:00
parent e4d28d4811
commit ece5ad6ee1
160 changed files with 33846 additions and 0 deletions

271
.gitignore vendored Normal file
View File

@ -0,0 +1,271 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/

31
CPPTools.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPTools", "CPPTools\CPPTools.vcxproj", "{77C5A027-83A9-4197-88E1-E79D935CB274}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{77C5A027-83A9-4197-88E1-E79D935CB274}.Debug|x64.ActiveCfg = Debug|x64
{77C5A027-83A9-4197-88E1-E79D935CB274}.Debug|x64.Build.0 = Debug|x64
{77C5A027-83A9-4197-88E1-E79D935CB274}.Debug|x86.ActiveCfg = Debug|Win32
{77C5A027-83A9-4197-88E1-E79D935CB274}.Debug|x86.Build.0 = Debug|Win32
{77C5A027-83A9-4197-88E1-E79D935CB274}.Release|x64.ActiveCfg = Release|x64
{77C5A027-83A9-4197-88E1-E79D935CB274}.Release|x64.Build.0 = Release|x64
{77C5A027-83A9-4197-88E1-E79D935CB274}.Release|x86.ActiveCfg = Release|Win32
{77C5A027-83A9-4197-88E1-E79D935CB274}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FD42DEB2-CFAD-43B5-8D13-D1E58247985A}
EndGlobalSection
EndGlobal

7
CPPTools/ArchAbstract.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
// Add architecture abstraction things here. I.e. things that make the difference between architectures less visible
#ifndef ulong_64b
#define ulong_64b unsigned long long
#endif

155
CPPTools/CPPTools.vcxproj Normal file
View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{24D9CC51-39A4-4AD3-81FC-8CAE3D590AC1}</ProjectGuid>
<RootNamespace>SlimSupport</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)\libs\SlimSupport\</OutDir>
<TargetExt>64.lib</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)\libs\SlimSupport</OutDir>
<TargetExt>.lib</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)libs\win_crypto++\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cryptlib64.lib;winsqlite3.lib;shlwapi.lib;Crypt32.lib;Ws2_32.lib;Mswsock.lib;AdvApi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
<AdditionalLibraryDirectories>$(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cryptlib64.lib;winsqlite3.lib;shlwapi.lib;Crypt32.lib;Ws2_32.lib;Mswsock.lib;AdvApi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)libs\win_crypto++\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Lib>
<AdditionalDependencies>cryptlib64.lib;winsqlite3.lib;shlwapi.lib;Crypt32.lib;Ws2_32.lib;Mswsock.lib;AdvApi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
<Lib>
<AdditionalLibraryDirectories>$(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)libs\win_crypto++\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<AdditionalLibraryDirectories>$(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cryptlib.lib;winsqlite3.lib;shlwapi.lib;Crypt32.lib;Ws2_32.lib;Mswsock.lib;AdvApi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ArchAbstract.h" />
<ClInclude Include="Crypto.h" />
<ClInclude Include="Tools.h" />
<ClInclude Include="Support.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Crypto.cpp" />
<ClCompile Include="Support.cpp" />
<ClCompile Include="Test.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Support.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ArchAbstract.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Tools.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Crypto.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Support.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

233
CPPTools/Crypto.cpp Normal file
View File

@ -0,0 +1,233 @@
#include "Crypto.h"
#include <randpool.h>
#include <modes.h>
#include <iostream>
namespace Crypto {
namespace AES {
// -------- AES START --------
// Parameters:
// message: Message to encrypt
// size: Length of message (probably strlen(message))
// resultingSize: Secondary return value representing string length of returned char*
// aes_key: Key to use for encryption
// aes_it: Initialization vector to use for encryption
char* aes_encrypt(void* msg, ulong_64b size, ulong_64b* resultingSize, AES_KEY aes_key, AES_IV aes_iv) {
char* message = (char*)msg;
byte key[_AES_BYTE_SIZE], iv[_AES_BYTE_SIZE];
memset(key, aes_key, _AES_BYTE_SIZE);
memset(iv, aes_iv, _AES_BYTE_SIZE);
std::string ciphertext;
CryptoPP::AES::Encryption aesEncryption(key, _AES_BYTE_SIZE);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
if (size > (size_t)size) throw _exception();
CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext));
stfEncryptor.Put((const unsigned char*)message, size + 1);
stfEncryptor.MessageEnd();
ulong_64b t = ciphertext.size();
(*resultingSize) = t;
char* cipher = (char*)malloc(t);
memcpy(cipher, ciphertext.c_str(), t);
return cipher;
}
char* aes_decrypt(void* msg, ulong_64b size, ulong_64b* resultSize, AES_KEY aes_key, AES_IV aes_iv) {
char* message = (char*)msg;
byte key[_AES_BYTE_SIZE], iv[_AES_BYTE_SIZE];
memset(key, aes_key, _AES_BYTE_SIZE);
memset(iv, aes_iv, _AES_BYTE_SIZE);
std::string decryptedtext;
CryptoPP::AES::Decryption aesDecryption(key, _AES_BYTE_SIZE);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext));
stfDecryptor.Put((const unsigned char*)message, size);
stfDecryptor.MessageEnd();
*resultSize = decryptedtext.size();
char* c = (char*)malloc(*resultSize);
//memset(c, 0, decryptedtext.size());
memcpy(c, decryptedtext.c_str(), decryptedtext.size());
decryptedtext.~basic_string();
return c;
}
// Just use this :P
Payload aes_auto_encrypt(void* msg, ulong_64b size) {
char* message = (char*)msg;
Payload p;
srand(time(NULL));
p.key = (char*)malloc(sizeof(AES_KEY));
AES_KEY k = (AES_KEY)rand();
p.keySize = sizeof(AES_KEY);
memcpy(p.key, &k, sizeof(AES_KEY));
p.iv = (AES_IV)rand();
ulong_64b s;
p.ldPayload = aes_encrypt(message, size, &s, *(AES_KEY*)p.key, p.iv);
p.size = s;
return p;
}
// This too :P
char* aes_auto_decrypt(Payload p, ulong_64b* resultingSize) {
return aes_decrypt(p.ldPayload, p.size, resultingSize, *(AES_KEY*)p.key, p.iv);
}
char* Payload::serialize(ulong_64b* size) {
char* ser = (char*)new char[*size=((sizeof(ulong_64b) * 2) + sizeof(AES_IV) + this->size + this->keySize)];
ulong_64b offset = 0;
memcpy(ser + offset, &this->size, sizeof(ulong_64b));
offset += sizeof(ulong_64b);
memcpy(ser + offset, &this->keySize, sizeof(ulong_64b));
offset += sizeof(ulong_64b);
memcpy(ser + offset, &this->iv, sizeof(AES_IV));
offset += sizeof(AES_IV);
memcpy(ser + offset, this->ldPayload, this->size);
offset += this->size;
memcpy(ser + offset, this->key, this->keySize);
return ser;
}
Payload deserializePayload(void* frm, ulong_64b* readBytes) {
char* from = (char*)frm;
Payload data;
ulong_64b offset = 0;
// Read target sizes
memcpy(&data.size, from + offset, sizeof(ulong_64b));
offset += sizeof(ulong_64b);
memcpy(&data.keySize, from + offset, sizeof(ulong_64b));
offset += sizeof(ulong_64b);
memcpy(&data.iv, from + offset, sizeof(AES_IV));
offset += sizeof(AES_IV);
// Allocate target sizes
data.ldPayload = (char*)malloc(data.size);
data.key = (char*)malloc(data.keySize);
// Read data
memcpy(data.ldPayload, from + offset, data.size);
offset += data.size;
memcpy(data.key, from + offset, data.keySize);
offset += data.keySize;
*readBytes = offset;
return data;
}
// -------- AES END --------
}
namespace RSA {
// -------- RSA START --------
KeyData rsa_gen_keys() {
KeyData k;
CryptoPP::InvertibleRSAFunction params;
CryptoPP::RandomPool rng;
time_t t = time(NULL);
rng.IncorporateEntropy((const byte*)&t, sizeof(t) * 8);
params.GenerateRandomWithKeySize(rng, 3072);
k.privKey = CryptoPP::RSA::PrivateKey(params);
k.publKey = CryptoPP::RSA::PublicKey(params);
return k;
}
char* serializeKey(CryptoPP::RSA::PublicKey& func, ulong_64b* rSize) {
CryptoPP::ByteQueue queue;
func.Save(queue);
//func.DEREncodePublicKey(queue);
byte* shortened = (byte*)malloc(*rSize=queue.TotalBytesRetrievable());
memset(shortened, 0, *rSize);
std::vector<byte> spk;
spk.resize(queue.TotalBytesRetrievable());
CryptoPP::ArraySink snk(&spk[0], spk.size());
queue.CopyTo(snk);
for (ulong_64b t = 0; t < spk.size(); ++t) shortened[t] = spk.at(t);
return (char*)shortened;
}
char* rsa_encrypt(void* msg, ulong_64b size, CryptoPP::RSA::PublicKey& pubKey, ulong_64b* resultingSize) {
char* message = (char*)msg;
CryptoPP::RandomPool rng;
time_t t = time(NULL);
rng.IncorporateEntropy((const byte*)&t, sizeof(t) * 8);
CryptoPP::RSAES_OAEP_SHA_Encryptor e(pubKey);
std::string cipher;
CryptoPP::StringSource s((const byte*)message, size, true, new CryptoPP::PK_EncryptorFilter(rng, e, new CryptoPP::StringSink(cipher)));
*resultingSize = cipher.size();
char* c = (char*)malloc(cipher.size());
memset(c, 0, cipher.size());
memcpy(c, cipher.c_str(), cipher.size());
return c;
}
char* rsa_decrypt(void* msg, ulong_64b size, CryptoPP::RSA::PrivateKey& privKey, ulong_64b* resultingSize) {
char* message = (char*)msg;
CryptoPP::RandomPool rng;
time_t t = time(NULL);
rng.IncorporateEntropy((const byte*)&t, sizeof(t) * 8);
CryptoPP::RSAES_OAEP_SHA_Decryptor e(privKey);
std::string clear;
CryptoPP::StringSource s((const byte*)message, size, true, new CryptoPP::PK_DecryptorFilter(rng, e, new CryptoPP::StringSink(clear)));
*resultingSize = clear.size();
char* c = (char*)malloc(clear.size());
memset(c, 0, clear.size());
memcpy(c, clear.c_str(), clear.size());
return c;
}
// -------- RSA END --------
}
char* full_auto_encrypt(void* msg, ulong_64b mSize, CryptoPP::RSA::PublicKey& pk, ulong_64b* rSize) {
AES::Payload p = AES::aes_auto_encrypt(msg, mSize);
p.key = RSA::rsa_encrypt(p.key, p.keySize, pk, &p.keySize);
return p.serialize(rSize);
}
char* full_auto_decrypt(void* msg, CryptoPP::RSA::PrivateKey& pk, ulong_64b* rSize) {
ulong_64b size;
AES::Payload p = AES::deserializePayload(msg, &size);
p.key = RSA::rsa_decrypt(p.key, p.keySize, pk, &p.keySize);
return AES::aes_auto_decrypt(p, rSize);
}
}

69
CPPTools/Crypto.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#ifndef LOGINDATA_H
#define LOGINDATA_H
#include "ArchAbstract.h"
#include <aes.h>
#include <rsa.h>
typedef unsigned short AES_IV_16;
typedef unsigned short AES_KEY_16;
typedef unsigned int AES_IV_32;
typedef unsigned int AES_KEY_32;
#ifdef _AES_16_BIT
// 128 bit AES encryption
#define _AES_BYTE_SIZE 16
typedef AES_IV_16 AES_IV;
typedef AES_KEY_16 AES_KEY;
#else
// 256 bit AES encryption
#define _AES_BYTE_SIZE 32
typedef AES_IV_32 AES_IV;
typedef AES_KEY_32 AES_KEY;
#endif
namespace Crypto {
namespace AES {
struct Payload {
ulong_64b size; // Payload metadata
ulong_64b keySize; // Key metadata
AES_IV iv; // Initialization vector
char* ldPayload; // Encrypted Data
char* key; // Encrypted AES key
char* serialize(ulong_64b*);// Serialize data to be sent over the wire :P
};
Payload deserializePayload(void*, ulong_64b*);
char* aes_encrypt(void* message, ulong_64b size, ulong_64b* resultingSize, AES_KEY key, AES_IV iv);
char* aes_decrypt(void* message, ulong_64b size, ulong_64b* resultSize, AES_KEY key, AES_IV iv);
char* aes_auto_decrypt(Payload p, ulong_64b* resultingSize);
Payload aes_auto_encrypt(void* message, ulong_64b size);
}
namespace RSA {
struct KeyData {
CryptoPP::RSA::PrivateKey privKey;
CryptoPP::RSA::PublicKey publKey;
};
char* serializeKey(CryptoPP::RSA::PublicKey&, ulong_64b* rSize);
KeyData rsa_gen_keys();
char* rsa_encrypt(void* message, ulong_64b size, CryptoPP::RSA::PublicKey& pubKey, ulong_64b* resultingSize);
char* rsa_decrypt(void* message, ulong_64b size, CryptoPP::RSA::PrivateKey& privKey, ulong_64b* resultingSize);
}
char* full_auto_encrypt(void* message, ulong_64b mSize, CryptoPP::RSA::PublicKey&, ulong_64b* rSize);
char* full_auto_decrypt(void* cryptMessage, CryptoPP::RSA::PrivateKey&, ulong_64b* rSize);
}
#endif

493
CPPTools/Support.cpp Normal file
View File

@ -0,0 +1,493 @@
#include <iostream>
#include <memory>
#include "Support.h"
namespace Tools {
char* strappend(char* to, char* from) {
ulong_64b l, l1;
to = (char*)realloc(to, (l = strlen(to)) + (l1 = strlen(from))+1);
memcpy(to + l, from, l1);
to[l + l1] = 0;
return to;
}
char* strappend(char* to, const char* from) {
ulong_64b l, l1;
to = (char*)realloc(to, (l = strlen(to)) + (l1 = strlen(from))+1);
memcpy(to + l, from, l1);
to[l + l1] = 0;
return to;
}
char* strappend(const char* from, char* to) {
ulong_64b l, l1;
to = (char*)realloc(to, (l = strlen(to)) + (l1 = strlen(from))+1);
memcpy(to + l1, to, l);
memcpy(to, from, l1);
to[l + l1] = 0;
return to;
}
char* __cdecl strappend(const char* from, const char* from1) {
ulong_64b l, l1;
char* to = (char*)malloc((l = strlen(from)) + (l1 = strlen(from1))+1);
memcpy(to, from, l);
memcpy(to + l, from1, l1);
to[l + l1] = 0;
return to;
}
void destructivePrint(char* message, ulong_64b size) {
for (ulong_64b t = 0; t < size; ++t) std::cout << message[t];
free(message);
}
void destructivePrint(char* message) {
std::cout << message;
free(message);
}
void destructivePrintln(char* message, ulong_64b size) {
destructivePrint(message, size);
std::cout << std::endl;
}
void destructivePrintln(char* message) {
destructivePrint(message);
std::cout << std::endl;
}
ulong_64b indexOf(char* in, char find) {
ulong_64b t = strlen(in);
for (ulong_64b t1 = 0; t1 < t; ++t1) if (in[t1] == find) return t1;
return -1;
}
ulong_64b lastIndexOf(char* in, char find) {
ulong_64b t = strlen(in);
for (ulong_64b t1 = 0; t1 < t; ++t1) if (in[t - t1 - 1] == find) return t - t1;
return -1;
}
char* copydata(const char* from, ulong_64b readBytes) {
char* c = (char*)malloc(readBytes);
memcpy(c, from, readBytes);
return c;
}
char* toHexString(const void* data, ulong_64b size) {
char* c = (char*)data;
ulong_64b lastNonZero = 0;
for (ulong_64b t = 0; t < size; ++t) if (c[t] != 0) lastNonZero = t;
if (lastNonZero == 0) return (char*)memset(malloc(1), '0', 1);
char* c1 = (char*)malloc(lastNonZero * 2);
for (ulong_64b t = 0; t < lastNonZero; ++t) {
c1[2 * t] = (c[t]) & 15;
if (c1[(2 * t)] < 9) c1[(2 * t)] += 48;
else c1[(2 * t)] += 55;
c1[(2 * t) + 1] = (c[t] >> 4) & 15;
if (c1[(2 * t) + 1] < 9) c1[(2 * t) + 1] += 48;
else c1[(2 * t) + 1] += 55;
}
return c1;
}
char* toHexString(ulong_64b value) { return toHexString(&value, sizeof(value)); }
bool isDigit(char c) { return (c > 47) && (c < 58); }
bool isIP(char* c) {
size_t t = strlen(c);
size_t count = 0;
for (size_t t1 = 0; t1 < t; ++t1) {
if (c[t1] == '.') {
if ((t1 + 1) == t) return false;
++count;
}
else if (!isDigit(c[t1])) return false;
if (count > 3) return false;
}
return count == 3;
}
bool isNumber(char* c) {
for (size_t t = strlen(c); t > 0; --t) if (!isDigit(c[t - 1])) return false;
return true;
}
}
namespace IO {
bool cryptoLevelsAreCompatible(CryptoLevel l1, CryptoLevel l2) {
return !(((l1 == CryptoLevel::None) && (l2 == CryptoLevel::Force)) || ((l2 == CryptoLevel::None) && (l1 == CryptoLevel::Force)));
}
char* __cdecl readSparse(std::vector<char>* sparse, ulong_64b rSize, bool pop = true) {
if (sparse->size() < rSize) throw new _exception(); // This should never happen if function is used correctly
char* c = new char[rSize];
for (ulong_64b b = 0; b < rSize; ++b) c[b] = sparse->at(b);
if(pop) sparse->erase(sparse->begin(), sparse->begin() + rSize);
return c;
}
bool hasFullMessage(std::vector<char> *sparse) {
if (sparse->size() < sizeof(ulong_64b)) return false;
ulong_64b size = 0;
char* c = readSparse(sparse, sizeof(ulong_64b), false);
memcpy(&size, c, sizeof(ulong_64b));
delete[] c;
return sparse->size() >= (size + sizeof(ulong_64b));
}
void NetClient::sharedSetup() {
if (preferEncrypted != CryptoLevel::None) keys = Crypto::RSA::rsa_gen_keys();
packets = new std::vector<Packet>();
sparse = new std::vector<char>();
outPacketBuf = new std::vector<Packet>();
_open = true;
canWrite = true;
evt = nullptr;
char cryptoPref = static_cast<char>(preferEncrypted);
if(send(_socket, &cryptoPref, 1, 0)==SOCKET_ERROR) throw new _exception(); // Cannot establish connection :(
//_write(&cryptoPref, 1);
if (!noThread) listener = std::thread([this]() { while(_open) { update(); Sleep(25); } }); // Setup separate thread for reading new data
}
NetClient::NetClient(char* ipAddr, char* port, CryptoLevel preferEncrypted) :
commTime(time(nullptr)), preferEncrypted(preferEncrypted), startNegotiate(false)
{
_socket = INVALID_SOCKET;
this->noThread = false;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) throw new _exception();
struct addrinfo *result = NULL, *ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo(ipAddr, port, &hints, &result);
if (iResult) throw new _exception();
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (_socket == INVALID_SOCKET) {
throw new _exception();
}
// Connect to server.
iResult = connect(_socket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(_socket);
_socket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (_socket == INVALID_SOCKET) throw new _exception();
sharedSetup();
}
NetClient::NetClient(SOCKET wrap, bool noThread, Crypto::RSA::KeyData& keys, CryptoLevel preferEncrypted, bool startNegotiate) :
commTime(time(nullptr)), preferEncrypted(preferEncrypted), startNegotiate(startNegotiate)
{
_socket = wrap;
this->noThread = noThread;
sharedSetup();
}
NetClient::~NetClient() {
packets->clear();
delete packets;
sparse->clear();
delete sparse;
if (isOpen()) close();
}
bool NetClient::close() {
bool result = !_open;
_open = false;
result &= (SOCKET_ERROR==shutdown(_socket, SD_BOTH));
closesocket(_socket);
return result;
}
void NetClient::closeWrite() {
shutdown(_socket, SD_SEND);
canWrite = false;
}
bool NetClient::_write(char* message, ulong_64b size) {
int i;
char* c = new char[sizeof(ulong_64b)];
memcpy(c, &size, sizeof(ulong_64b));
for (ulong_64b wIdx = 0; wIdx < sizeof(ulong_64b); ++wIdx) {
if ((i = send(_socket, c + wIdx, 1, 0)) == SOCKET_ERROR) return false;
else if (i == 0) --wIdx;
}
for (ulong_64b wIdx = 0; wIdx < size; ++wIdx) {
if ((i = send(_socket, message + wIdx, 1, 0)) == SOCKET_ERROR) return false;
else if (i == 0) --wIdx;
}
return true;
}
bool NetClient::write(void* message, ulong_64b size) {
if (firstMessage) {
Packet p;
p.message = (char*)message;
p.size = size;
outPacketBuf->push_back(p);
return true;
}
if (!canWrite) return false;
char* msg = encrypted?Crypto::full_auto_encrypt(message, size, pK, &size):(char*)message;
_write(msg, size);
if (encrypted) delete[] msg;
return true;
}
bool NetClient::write(char* message) { return write(message, strlen(message)); }
bool NetClient::writeBufferedPackets() {
for (size_t t = 0; t < outPacketBuf->size(); ++t) if (!write(outPacketBuf->at(t).message, outPacketBuf->at(t).size)) { delete outPacketBuf; return false; };
delete outPacketBuf;
return true;
}
Packet NetClient::read() {
if (packets->size() != 0) {
Packet p = packets->at(0);
packets->erase(packets->begin(), packets->begin()+1); // Delete first buffered packet
return p;
}
throw new _exception(); // No packets available!
}
void NetClient::setEventHandler(std::function<void(NetClient*, Packet)> _ev) {
evt = _ev;
// Process unhandled packets
if (evt != nullptr)
for (size_t t = packets->size(); t > 0; --t) {
Packet p = packets->at(t - 1);
packets->pop_back();
evt(this, p);
}
}
bool NetClient::isEncrypted() { return encrypted; }
void NetClient::update() {
int iResult = 0;
unsigned long rCount;
int rdErr = ioctlsocket(_socket, FIONREAD, &rCount);
if (rdErr == SOCKET_ERROR) throw new _exception(); // Error using socket :(
if (rCount > 0) {
iResult = recv(_socket, rBuf, BUFSIZE, 0);
if (iResult > 0)
for (int i = 0; i < iResult; ++i)
if (sparse->size() < BUF_2_MAX)
sparse->push_back(rBuf[i]); // Drop anything over the absolute max
}
while (!firstMessage && hasFullMessage(sparse)) {
Packet p;
char* size = readSparse(sparse, sizeof(ulong_64b));
memcpy(&p.size, size, sizeof(ulong_64b));
delete[] size;
p.message = readSparse(sparse, p.size);
if (encrypted) p.message = Crypto::full_auto_decrypt(p.message, keys.privKey, &p.size);
if(evt==nullptr) packets->push_back(p);
else evt(this, p); // Notify event handler of a new packet
}
if (iResult > 0) {
if (firstMessage) {
if (!fm_neg_hasLevel && sparse->size() >= 1) {
fm_neg_hasLevel = true;
char* readCrypt = readSparse(sparse, 1);
CryptoLevel lvl = static_cast<CryptoLevel>(*readCrypt);
free(readCrypt);
if (cryptoLevelsAreCompatible(lvl, preferEncrypted)) {
// Determine whether or not to use encryption
encrypted = (preferEncrypted == CryptoLevel::Force) || (lvl == CryptoLevel::Force) || ((preferEncrypted == CryptoLevel::Prefer) && (lvl == CryptoLevel::Prefer));
if (!encrypted) {
firstMessage = false; // We're done here. No need to try to get a public key for an unencrypted channel
writeBufferedPackets();
}
else {
ulong_64b size;
char* c = Crypto::RSA::serializeKey(keys.publKey, &size);
_write(c, size); // This shouldn't be encrypted
delete[] c;
}
}
else throw new _exception(); // Incompatible cryptographic requirements!
}
if (fm_neg_hasLevel && !fm_neg_hasSize && encrypted && sparse->size() >= sizeof(ulong_64b)) {
fm_neg_hasSize = true;
char* readSize = readSparse(sparse, sizeof(ulong_64b));
fm_neg_size = 0;
memcpy(&fm_neg_size, readSize, sizeof(ulong_64b));
free(readSize);
}
if (fm_neg_hasSize && sparse->size() >= fm_neg_size) {
char* msg = readSparse(sparse, fm_neg_size);
CryptoPP::StringSource src((const byte*)msg, fm_neg_size, true);
pK.Load(src);
firstMessage = false;
writeBufferedPackets();
}
}
}else if (iResult < 0 && _open) {
_open = false;
close();
}
}
bool NetClient::isOpen() { return _open; }
void NetClient::setOnDestroy(std::function<void()> call) { onDestroy = call; }
ulong_64b NetClient::available() { return packets->size(); }
bool NetServer::close() {
if (!_open) return false;
_open = false;
for (ulong_64b t = clients->size(); t > 0; --t) {
NetClient* s = clients->at(t-1);
s->close();
clients->pop_back();
delete s;
}
return true;
}
NetServer::NetServer(char* port, std::function<bool(NetClient*)> f=nullptr, CryptoLevel pref=CryptoLevel::None) : pref(pref) {
if (pref != CryptoLevel::None) keys = Crypto::RSA::rsa_gen_keys();
_open = true;
timeoutHandler = NULL;
onDestroy = NULL;
handlers = new std::vector <std::function<bool(NetClient*)>>();
if (f != NULL) handlers->push_back(f);
clients = new std::vector<NetClient*>();
clientListener = std::thread([this, port]() {
SOCKET _server;
WSADATA wsaData;
int iResult;
struct addrinfo *result = NULL;
struct addrinfo hints;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) throw new _exception();
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, port, &hints, &result);
if (iResult) {
throw new _exception();
}
// Create a SOCKET for connecting to server
_server = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (_server == INVALID_SOCKET) {
freeaddrinfo(result);
throw new _exception();
}
// Setup the TCP listening socket
iResult = bind(_server, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
freeaddrinfo(result);
closesocket(_server);
throw new _exception(); // Can't be fucked to deal with errors
}
if (listen(_server, 20) == SOCKET_ERROR) { // 20 is the backlog amount, i.e. amount of connections Windows will accept if program is busy and can't accept atm.
closesocket(_server);
throw new _exception();
}
timeval t;
t.tv_sec = 0;
t.tv_usec = 5000;
do {
fd_set connecting;
connecting.fd_count = 1;
connecting.fd_array[0] = _server;
int i = select(NULL, &connecting, NULL, NULL, &t); // Check for new clients
if (i == SOCKET_ERROR) {
throw new _exception();
}
if (connecting.fd_count > 0) { // This checks if any new clients are tryig to connect. If not, don't block to await one; just continue to update clients
SOCKET client = accept(_server, NULL, NULL);
if (client == INVALID_SOCKET) {
closesocket(_server);
if (_open) throw new _exception();
else break;
}
NetClient* cli = new NetClient(client, true, keys, this->pref, false);
clients->push_back(cli);
for (ulong_64b t = 0; t < handlers->size(); ++t)
if (handlers->at(t)(cli))
break;
}
updateClients();
} while (_open);
closesocket(_server);
close();
});
}
NetServer::~NetServer() {
if (_open) close();
handlers->clear();
delete handlers;
clients->clear();
delete clients;
onDestroy();
}
void NetServer::addHandler(std::function<bool(NetClient*)> evtH) {
handlers->push_back(evtH);
}
void NetServer::clearHandlers() {
handlers->clear();
}
void NetServer::updateClients() {
for (ulong_64b t = clients->size(); t > 0; --t) {
NetClient* c = clients->at(t-1);
if (!c->isOpen() || (timeoutHandler != NULL && !timeoutHandler(c))) {
clients->erase(clients->begin() + t - 1, clients->begin() + t);
c->close();
}
else c->update();
}
}
CryptoLevel NetServer::getCryptoPreference() { return pref; }
bool NetServer::isOpen() { return _open; }
void NetServer::setOnDestroy(std::function<void()> call) { onDestroy = call; }
}

134
CPPTools/Support.h Normal file
View File

@ -0,0 +1,134 @@
#pragma once
#ifndef _SUPPORT_H
#define _SUPPORT_H
#ifdef _SUPPORT_SMALL_BUF
#define BUFSIZE 512
#define BUF_2_MAX 2048
#else
#define BUFSIZE 16384
#define BUF_2_MAX 16384
#endif
#define WIN32_LEAN_AND_MEAN
#include "ArchAbstract.h"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <thread>
#include <functional>
#include <time.h>
#include "Crypto.h"
namespace Tools {
char* strappend(char*, char*);
char* strappend(char*, const char*);
char* strappend(const char*, char*);
char* strappend(const char*, const char*);
void destructivePrint(char* message, ulong_64b size);
void destructivePrint(char* message);
void destructivePrintln(char* message, ulong_64b size);
void destructivePrintln(char* message);
ulong_64b indexOf(char*, char);
ulong_64b lastIndexOf(char*, char);
char* copydata(const char*, ulong_64b);
char* toHexString(const void* data, ulong_64b size);
char* toHexString(ulong_64b value);
bool isDigit(char c);
bool isNumber(char* c);
bool isIP(char* c);
}
namespace IO {
enum CryptoLevel { None, Prefer, Force };
struct Packet {
ulong_64b size;
char* message;
};
class NetServer;
class NetClient {
friend class NetServer; // Allow NetServer to access all members of NetClient
private:
volatile bool _open; // Whether or not connection is open
bool canWrite; // Whether or not writing to peer is possible
bool noThread; // Whether or not reading incoming data should be / is being done in a separate thread
char rBuf[BUFSIZE]; // Recieve buffer
CryptoLevel preferEncrypted = CryptoLevel::None;// Whether or not the socket should attempt to request an encrypted channel
bool encrypted = false; // Whether or not negotiation determined the use of an encrypted channel
bool firstMessage = true; // Whether or not negotiation has yet ocurred
ulong_64b fm_neg_size;
bool fm_neg_hasLevel = false;
bool fm_neg_hasSize = false;
bool startNegotiate = false;
std::vector<char>* sparse;
std::vector<Packet>* outPacketBuf;
Crypto::RSA::KeyData keys; // Client's keysets (if using encryption)
CryptoPP::RSAFunction pK; // Remote host's public key (if using encryption)
NetClient(SOCKET, bool, CryptoLevel, bool);// Special setup constructor
NetClient(SOCKET, bool, Crypto::RSA::KeyData&, CryptoLevel = CryptoLevel::None, bool = false);// Create wrapper for existing socket
void sharedSetup(); // Setup function for all constructor
bool _write(char*, ulong_64b); // Internal write function. Doesn't do any of the fancy auto encryption: just raw write...
bool writeBufferedPackets(); // Flushes and deletes buffer
void update(); // Read incoming data and store in buffers
protected:
std::thread listener; // Incoming data listener (optional)
SOCKET _socket; // Underlying socket used for communication
std::vector<Packet>* packets; // Basically a set containing a backlog of unprocessed data. Will oly be used if event handler doesn't exist
std::function<void(NetClient*, Packet)> evt; // New data event handler
std::function<void()> onDestroy; // Event handler called when NetClient object is destroyed
public:
time_t commTime; // Latest time a transaction occurred
std::vector<char*> associatedData;
NetClient(char* ipAddr, char* port, CryptoLevel = CryptoLevel::None);// Standard constructor for creating connection
~NetClient();
bool close();
void closeWrite();
bool isEncrypted();
size_t getBOPCount(); // Should return the amount of buffered packets to be sent to server
bool write(void* message, ulong_64b size);
bool write(char* message);
Packet read();
void setEventHandler(std::function<void(NetClient*, Packet)>); // Register a callback that is guaranteed to be called when the socket has at least one unprocessed packet
void setOnDestroy(std::function<void()>);
bool isOpen();
ulong_64b available();
};
class NetServer {
friend class NetClient;
private:
CryptoLevel pref;
Crypto::RSA::KeyData keys; // Server's keysets (if using encryption)
std::function<void()> onDestroy;
volatile bool _open;
void updateClients();
protected:
std::thread clientListener;
std::vector<std::function<bool(NetClient*)>>* handlers;
std::vector<NetClient*>* clients;
public:
std::function<bool(NetClient*)> timeoutHandler;
NetServer(char* port, std::function<bool(NetClient*)>, CryptoLevel);
~NetServer();
bool isOpen();
CryptoLevel getCryptoPreference();
void addHandler(std::function<bool(NetClient*)>);
void clearHandlers();
void setOnDestroy(std::function<void()>);
bool close();
};
}
#endif

17
CPPTools/Test.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "Support.h"
#include <iostream>
int main() {
std::vector<char>* sparse = new std::vector<char>();
sparse->push_back(1);
sparse->push_back(2);
sparse->push_back(3);
std::cout << sparse->size() << std::endl;
sparse->erase(sparse->begin(), sparse->begin()+sparse->size());
std::cout << sparse->size() << std::endl;
std::cin.ignore();
}

5
CPPTools/Tools.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "Crypto.h"
#include "Support.h"
#include "ArchAbstract.h"

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# CPPTools
Useful tools for use in C++ projects

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,68 @@
// 3way.h - written and placed in the public domain by Wei Dai
//! \file 3way.h
//! \brief Classes for the 3-Way block cipher
#ifndef CRYPTOPP_THREEWAY_H
#define CRYPTOPP_THREEWAY_H
#include "config.h"
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class ThreeWay_Info
//! \brief ThreeWay block cipher information
struct ThreeWay_Info : public FixedBlockSize<12>, public FixedKeyLength<12>, public VariableRounds<11>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "3-Way";}
};
//! \class ThreeWay
//! \brief ThreeWay block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#3-Way">3-Way</a>
class ThreeWay : public ThreeWay_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief Class specific implementation and overrides used to operate the cipher.
//! \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<ThreeWay_Info>
{
public:
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
protected:
unsigned int m_rounds;
FixedSizeSecBlock<word32, 3> m_k;
};
//! \class Enc
//! \brief Class specific methods used to operate the cipher in the forward direction.
//! \details Implementations and overrides in \p Enc apply to \p ENCRYPTION.
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \class Dec
//! \brief Class specific methods used to operate the cipher in the reverse direction.
//! \details Implementations and overrides in \p Dec apply to \p DECRYPTION.
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
typedef ThreeWay::Encryption ThreeWayEncryption;
typedef ThreeWay::Decryption ThreeWayDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,34 @@
// adler32.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile adler32.h
//! \brief Class file for ADLER-32 checksum calculations
#ifndef CRYPTOPP_ADLER32_H
#define CRYPTOPP_ADLER32_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
//! ADLER-32 checksum calculations
class Adler32 : public HashTransformation
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
Adler32() {Reset();}
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "Adler32";}
std::string AlgorithmName() const {return StaticAlgorithmName();}
private:
void Reset() {m_s1 = 1; m_s2 = 0;}
word16 m_s1, m_s2;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,23 @@
// aes.h - written and placed in the public domain by Wei Dai
//! \file
//! \brief Class file for the AES cipher (Rijndael)
#ifndef CRYPTOPP_AES_H
#define CRYPTOPP_AES_H
#include "rijndael.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class AES
//! \brief AES block cipher (Rijndael)
//! \sa <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
DOCUMENTED_TYPEDEF(Rijndael, AES);
typedef RijndaelEncryption AESEncryption;
typedef RijndaelDecryption AESDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,453 @@
// algebra.h - written and placed in the public domain by Wei Dai
//! \file algebra.h
//! \brief Classes for performing mathematics over different fields
#ifndef CRYPTOPP_ALGEBRA_H
#define CRYPTOPP_ALGEBRA_H
#include "config.h"
#include "misc.h"
#include "integer.h"
NAMESPACE_BEGIN(CryptoPP)
class Integer;
//! \brief Abstract group
//! \tparam T element class or type
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
{
public:
typedef T Element;
virtual ~AbstractGroup() {}
//! \brief Compare two elements for equality
//! \param a first element
//! \param b second element
//! \returns true if the elements are equal, false otherwise
//! \details Equal() tests the elements for equality using <tt>a==b</tt>
virtual bool Equal(const Element &a, const Element &b) const =0;
//! \brief Provides the Identity element
//! \returns the Identity element
virtual const Element& Identity() const =0;
//! \brief Adds elements in the group
//! \param a first element
//! \param b second element
//! \returns the sum of <tt>a</tt> and <tt>b</tt>
virtual const Element& Add(const Element &a, const Element &b) const =0;
//! \brief Inverts the element in the group
//! \param a first element
//! \returns the inverse of the element
virtual const Element& Inverse(const Element &a) const =0;
//! \brief Determine if inversion is fast
//! \returns true if inversion is fast, false otherwise
virtual bool InversionIsFast() const {return false;}
//! \brief Doubles an element in the group
//! \param a the element
//! \returns the element doubled
virtual const Element& Double(const Element &a) const;
//! \brief Subtracts elements in the group
//! \param a first element
//! \param b second element
//! \returns the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
virtual const Element& Subtract(const Element &a, const Element &b) const;
//! \brief TODO
//! \param a first element
//! \param b second element
//! \returns TODO
virtual Element& Accumulate(Element &a, const Element &b) const;
//! \brief Reduces an element in the congruence class
//! \param a element to reduce
//! \param b the congruence class
//! \returns the reduced element
virtual Element& Reduce(Element &a, const Element &b) const;
//! \brief Performs a scalar multiplication
//! \param a multiplicand
//! \param e multiplier
//! \returns the product
virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
//! \brief TODO
//! \param x first multiplicand
//! \param e1 the first multiplier
//! \param y second multiplicand
//! \param e2 the second multiplier
//! \returns TODO
virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
//! \brief Multiplies a base to multiple exponents in a group
//! \param results an array of Elements
//! \param base the base to raise to the exponents
//! \param exponents an array of exponents
//! \param exponentsCount the number of exponents in the array
//! \details SimultaneousMultiply() multiplies the base to each exponent in the exponents array and stores the
//! result at the respective position in the results array.
//! \details SimultaneousMultiply() must be implemented in a derived class.
//! \pre <tt>COUNTOF(results) == exponentsCount</tt>
//! \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
};
//! \brief Abstract ring
//! \tparam T element class or type
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
{
public:
typedef T Element;
//! \brief Construct an AbstractRing
AbstractRing() {m_mg.m_pRing = this;}
//! \brief Copy construct an AbstractRing
//! \param source other AbstractRing
AbstractRing(const AbstractRing &source)
{CRYPTOPP_UNUSED(source); m_mg.m_pRing = this;}
//! \brief Assign an AbstractRing
//! \param source other AbstractRing
AbstractRing& operator=(const AbstractRing &source)
{CRYPTOPP_UNUSED(source); return *this;}
//! \brief Determines whether an element is a unit in the group
//! \param a the element
//! \returns true if the element is a unit after reduction, false otherwise.
virtual bool IsUnit(const Element &a) const =0;
//! \brief Retrieves the multiplicative identity
//! \returns the multiplicative identity
virtual const Element& MultiplicativeIdentity() const =0;
//! \brief Multiplies elements in the group
//! \param a the multiplicand
//! \param b the multiplier
//! \returns the product of a and b
virtual const Element& Multiply(const Element &a, const Element &b) const =0;
//! \brief Calculate the multiplicative inverse of an element in the group
//! \param a the element
virtual const Element& MultiplicativeInverse(const Element &a) const =0;
//! \brief Square an element in the group
//! \param a the element
//! \returns the element squared
virtual const Element& Square(const Element &a) const;
//! \brief Divides elements in the group
//! \param a the dividend
//! \param b the divisor
//! \returns the quotient
virtual const Element& Divide(const Element &a, const Element &b) const;
//! \brief Raises a base to an exponent in the group
//! \param a the base
//! \param e the exponent
//! \returns the exponentiation
virtual Element Exponentiate(const Element &a, const Integer &e) const;
//! \brief TODO
//! \param x first element
//! \param e1 first exponent
//! \param y second element
//! \param e2 second exponent
//! \returns TODO
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
//! \brief Exponentiates a base to multiple exponents in the Ring
//! \param results an array of Elements
//! \param base the base to raise to the exponents
//! \param exponents an array of exponents
//! \param exponentsCount the number of exponents in the array
//! \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the
//! result at the respective position in the results array.
//! \details SimultaneousExponentiate() must be implemented in a derived class.
//! \pre <tt>COUNTOF(results) == exponentsCount</tt>
//! \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
//! \brief Retrieves the multiplicative group
//! \returns the multiplicative group
virtual const AbstractGroup<T>& MultiplicativeGroup() const
{return m_mg;}
private:
class MultiplicativeGroupT : public AbstractGroup<T>
{
public:
const AbstractRing<T>& GetRing() const
{return *m_pRing;}
bool Equal(const Element &a, const Element &b) const
{return GetRing().Equal(a, b);}
const Element& Identity() const
{return GetRing().MultiplicativeIdentity();}
const Element& Add(const Element &a, const Element &b) const
{return GetRing().Multiply(a, b);}
Element& Accumulate(Element &a, const Element &b) const
{return a = GetRing().Multiply(a, b);}
const Element& Inverse(const Element &a) const
{return GetRing().MultiplicativeInverse(a);}
const Element& Subtract(const Element &a, const Element &b) const
{return GetRing().Divide(a, b);}
Element& Reduce(Element &a, const Element &b) const
{return a = GetRing().Divide(a, b);}
const Element& Double(const Element &a) const
{return GetRing().Square(a);}
Element ScalarMultiply(const Element &a, const Integer &e) const
{return GetRing().Exponentiate(a, e);}
Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
{return GetRing().CascadeExponentiate(x, e1, y, e2);}
void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
{GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
const AbstractRing<T> *m_pRing;
};
MultiplicativeGroupT m_mg;
};
// ********************************************************
//! \brief Base and exponent
//! \tparam T base class or type
//! \tparam T exponent class or type
template <class T, class E = Integer>
struct BaseAndExponent
{
public:
BaseAndExponent() {}
BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
T base;
E exponent;
};
// VC60 workaround: incomplete member template support
template <class Element, class Iterator>
Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
template <class Element, class Iterator>
Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
// ********************************************************
//! \brief Abstract Euclidean domain
//! \tparam T element class or type
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
{
public:
typedef T Element;
//! \brief Performs the division algorithm on two elements in the ring
//! \param r the remainder
//! \param q the quotient
//! \param a the dividend
//! \param d the divisor
virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
//! \brief Performs a modular reduction in the ring
//! \param a the element
//! \param b the modulus
//! \returns the result of <tt>a%b</tt>.
virtual const Element& Mod(const Element &a, const Element &b) const =0;
//! \brief Calculates the greatest common denominator in the ring
//! \param a the first element
//! \param b the second element
//! \returns the the greatest common denominator of a and b.
virtual const Element& Gcd(const Element &a, const Element &b) const;
protected:
mutable Element result;
};
// ********************************************************
//! \brief Euclidean domain
//! \tparam T element class or type
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
{
public:
typedef T Element;
EuclideanDomainOf() {}
bool Equal(const Element &a, const Element &b) const
{return a==b;}
const Element& Identity() const
{return Element::Zero();}
const Element& Add(const Element &a, const Element &b) const
{return result = a+b;}
Element& Accumulate(Element &a, const Element &b) const
{return a+=b;}
const Element& Inverse(const Element &a) const
{return result = -a;}
const Element& Subtract(const Element &a, const Element &b) const
{return result = a-b;}
Element& Reduce(Element &a, const Element &b) const
{return a-=b;}
const Element& Double(const Element &a) const
{return result = a.Doubled();}
const Element& MultiplicativeIdentity() const
{return Element::One();}
const Element& Multiply(const Element &a, const Element &b) const
{return result = a*b;}
const Element& Square(const Element &a) const
{return result = a.Squared();}
bool IsUnit(const Element &a) const
{return a.IsUnit();}
const Element& MultiplicativeInverse(const Element &a) const
{return result = a.MultiplicativeInverse();}
const Element& Divide(const Element &a, const Element &b) const
{return result = a/b;}
const Element& Mod(const Element &a, const Element &b) const
{return result = a%b;}
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
{Element::Divide(r, q, a, d);}
bool operator==(const EuclideanDomainOf<T> &rhs) const
{CRYPTOPP_UNUSED(rhs); return true;}
private:
mutable Element result;
};
//! \brief Quotient ring
//! \tparam T element class or type
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
template <class T> class QuotientRing : public AbstractRing<typename T::Element>
{
public:
typedef T EuclideanDomain;
typedef typename T::Element Element;
QuotientRing(const EuclideanDomain &domain, const Element &modulus)
: m_domain(domain), m_modulus(modulus) {}
const EuclideanDomain & GetDomain() const
{return m_domain;}
const Element& GetModulus() const
{return m_modulus;}
bool Equal(const Element &a, const Element &b) const
{return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
const Element& Identity() const
{return m_domain.Identity();}
const Element& Add(const Element &a, const Element &b) const
{return m_domain.Add(a, b);}
Element& Accumulate(Element &a, const Element &b) const
{return m_domain.Accumulate(a, b);}
const Element& Inverse(const Element &a) const
{return m_domain.Inverse(a);}
const Element& Subtract(const Element &a, const Element &b) const
{return m_domain.Subtract(a, b);}
Element& Reduce(Element &a, const Element &b) const
{return m_domain.Reduce(a, b);}
const Element& Double(const Element &a) const
{return m_domain.Double(a);}
bool IsUnit(const Element &a) const
{return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
const Element& MultiplicativeIdentity() const
{return m_domain.MultiplicativeIdentity();}
const Element& Multiply(const Element &a, const Element &b) const
{return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
const Element& Square(const Element &a) const
{return m_domain.Mod(m_domain.Square(a), m_modulus);}
const Element& MultiplicativeInverse(const Element &a) const;
bool operator==(const QuotientRing<T> &rhs) const
{return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
protected:
EuclideanDomain m_domain;
Element m_modulus;
};
NAMESPACE_END
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
#include "algebra.cpp"
#endif
#endif

View File

@ -0,0 +1,580 @@
// algparam.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile algparam.h
//! \brief Classes for working with NameValuePairs
#ifndef CRYPTOPP_ALGPARAM_H
#define CRYPTOPP_ALGPARAM_H
#include "config.h"
#include "cryptlib.h"
// TODO: fix 6011 when the API/ABI can change
#if (CRYPTOPP_MSC_VERSION >= 1400)
# pragma warning(push)
# pragma warning(disable: 6011 28193)
#endif
#include "smartptr.h"
#include "secblock.h"
#include "integer.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class ConstByteArrayParameter
//! \brief Used to pass byte array input as part of a NameValuePairs object
class ConstByteArrayParameter
{
public:
//! \brief Construct a ConstByteArrayParameter
//! \param data a C-String
//! \param deepCopy flag indicating whether the data should be copied
//! \details The deepCopy option is used when the NameValuePairs object can't
//! keep a copy of the data available
ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
: m_deepCopy(false), m_data(NULL), m_size(0)
{
Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
}
//! \brief Construct a ConstByteArrayParameter
//! \param data a memory buffer
//! \param size the length of the memory buffer
//! \param deepCopy flag indicating whether the data should be copied
//! \details The deepCopy option is used when the NameValuePairs object can't
//! keep a copy of the data available
ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
: m_deepCopy(false), m_data(NULL), m_size(0)
{
Assign(data, size, deepCopy);
}
//! \brief Construct a ConstByteArrayParameter
//! \tparam T a std::basic_string<char> class
//! \param string a std::basic_string<char> class
//! \param deepCopy flag indicating whether the data should be copied
//! \details The deepCopy option is used when the NameValuePairs object can't
//! keep a copy of the data available
template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
: m_deepCopy(false), m_data(NULL), m_size(0)
{
CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
Assign((const byte *)string.data(), string.size(), deepCopy);
}
//! \brief Assign contents from a memory buffer
//! \param data a memory buffer
//! \param size the length of the memory buffer
//! \param deepCopy flag indicating whether the data should be copied
//! \details The deepCopy option is used when the NameValuePairs object can't
//! keep a copy of the data available
void Assign(const byte *data, size_t size, bool deepCopy)
{
// This fires, which means: no data with a size, or data with no size.
// CRYPTOPP_ASSERT((data && size) || !(data || size));
if (deepCopy)
m_block.Assign(data, size);
else
{
m_data = data;
m_size = size;
}
m_deepCopy = deepCopy;
}
//! \brief Pointer to the first byte in the memory block
const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
//! \brief Pointer beyond the last byte in the memory block
const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
//! \brief Length of the memory block
size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
private:
bool m_deepCopy;
const byte *m_data;
size_t m_size;
SecByteBlock m_block;
};
//! \class ByteArrayParameter
//! \brief Used to pass byte array input as part of a NameValuePairs object
class ByteArrayParameter
{
public:
//! \brief Construct a ByteArrayParameter
//! \param data a memory buffer
//! \param size the length of the memory buffer
ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
: m_data(data), m_size(size) {}
//! \brief Construct a ByteArrayParameter
//! \param block a SecByteBlock
ByteArrayParameter(SecByteBlock &block)
: m_data(block.begin()), m_size(block.size()) {}
//! \brief Pointer to the first byte in the memory block
byte *begin() const {return m_data;}
//! \brief Pointer beyond the last byte in the memory block
byte *end() const {return m_data + m_size;}
//! \brief Length of the memory block
size_t size() const {return m_size;}
private:
byte *m_data;
size_t m_size;
};
//! \class CombinedNameValuePairs
//! \brief Combines two sets of NameValuePairs
//! \details CombinedNameValuePairs allows you to provide two sets of of NameValuePairs.
//! If a name is not found in the first set, then the second set is searched for the
//! name and value pair. The second set of NameValuePairs often provides default values.
class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
{
public:
//! \brief Construct a CombinedNameValuePairs
//! \param pairs1 reference to the first set of NameValuePairs
//! \param pairs2 reference to the second set of NameValuePairs
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
: m_pairs1(pairs1), m_pairs2(pairs2) {}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
private:
const NameValuePairs &m_pairs1, &m_pairs2;
};
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
template <class T, class BASE>
class GetValueHelperClass
{
public:
GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
: m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
{
if (strcmp(m_name, "ValueNames") == 0)
{
m_found = m_getValueNames = true;
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
if (searchFirst)
searchFirst->GetVoidValue(m_name, valueType, pValue);
if (typeid(T) != typeid(BASE))
pObject->BASE::GetVoidValue(m_name, valueType, pValue);
((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
}
if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
*reinterpret_cast<const T **>(pValue) = pObject;
m_found = true;
return;
}
if (!m_found && searchFirst)
m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
if (!m_found && typeid(T) != typeid(BASE))
m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
}
operator bool() const {return m_found;}
template <class R>
GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
{
if (m_getValueNames)
(*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
if (!m_found && strcmp(name, m_name) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
*reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
m_found = true;
}
return *this;
}
GetValueHelperClass<T,BASE> &Assignable()
{
#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
if (m_getValueNames)
((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
*reinterpret_cast<T *>(m_pValue) = *m_pObject;
m_found = true;
}
#endif
return *this;
}
private:
const T *m_pObject;
const char *m_name;
const std::type_info *m_valueType;
void *m_pValue;
bool m_found, m_getValueNames;
};
template <class BASE, class T>
GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
}
template <class T>
GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
{
return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
}
// ********************************************************
// VC60 workaround
#if defined(_MSC_VER) && (_MSC_VER < 1300)
template <class R>
R Hack_DefaultValueFromConstReferenceType(const R &)
{
return R();
}
template <class R>
bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
{
return source.GetValue(name, const_cast<R &>(value));
}
template <class T, class BASE>
class AssignFromHelperClass
{
public:
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
: m_pObject(pObject), m_source(source), m_done(false)
{
if (source.GetThisObject(*pObject))
m_done = true;
else if (typeid(BASE) != typeid(T))
pObject->BASE::AssignFrom(source);
}
template <class R>
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
{
if (!m_done)
{
R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name, value))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
(m_pObject->*pm)(value);
}
return *this;
}
template <class R, class S>
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
{
if (!m_done)
{
R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
(m_pObject->*pm)(value1, value2);
}
return *this;
}
private:
T *m_pObject;
const NameValuePairs &m_source;
bool m_done;
};
#else
template <class T, class BASE>
class AssignFromHelperClass
{
public:
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
: m_pObject(pObject), m_source(source), m_done(false)
{
if (source.GetThisObject(*pObject))
m_done = true;
else if (typeid(BASE) != typeid(T))
pObject->BASE::AssignFrom(source);
}
template <class R>
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&))
{
if (!m_done)
{
R value;
if (!m_source.GetValue(name, value))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
(m_pObject->*pm)(value);
}
return *this;
}
template <class R, class S>
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&))
{
if (!m_done)
{
R value1;
if (!m_source.GetValue(name1, value1))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
S value2;
if (!m_source.GetValue(name2, value2))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
(m_pObject->*pm)(value1, value2);
}
return *this;
}
private:
T *m_pObject;
const NameValuePairs &m_source;
bool m_done;
};
#endif
template <class BASE, class T>
AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
return AssignFromHelperClass<T, BASE>(pObject, source);
}
template <class T>
AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
{
return AssignFromHelperClass<T, T>(pObject, source);
}
#endif // CRYPTOPP_DOXYGEN_PROCESSING
// ********************************************************
// to allow the linker to discard Integer code if not needed.
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
//! \class AlgorithmParametersBase
//! \brief Base class for AlgorithmParameters
class CRYPTOPP_DLL AlgorithmParametersBase
{
public:
//! \class ParameterNotUsed
//! \brief Exception thrown when an AlgorithmParameter is unused
class ParameterNotUsed : public Exception
{
public:
ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
};
// this is actually a move, not a copy
AlgorithmParametersBase(const AlgorithmParametersBase &x)
: m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
{
m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
x.m_used = true;
}
//! \brief Construct a AlgorithmParametersBase
//! \param name the parameter name
//! \param throwIfNotUsed flags indicating whether an exception should be thrown
//! \details If throwIfNotUsed is true, then a ParameterNotUsed exception
//! will be thrown in the destructor if the parameter is not not retrieved.
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
: m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
{
#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
if (!std::uncaught_exception())
#else
try
#endif
{
if (m_throwIfNotUsed && !m_used)
throw ParameterNotUsed(m_name);
}
#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
catch(const Exception&)
{
}
#endif
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
protected:
friend class AlgorithmParameters;
void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
virtual void MoveInto(void *p) const =0; // not really const
const char *m_name;
bool m_throwIfNotUsed;
mutable bool m_used;
member_ptr<AlgorithmParametersBase> m_next;
};
//! \class AlgorithmParametersTemplate
//! \brief Template base class for AlgorithmParameters
//! \tparam T the class or type
template <class T>
class AlgorithmParametersTemplate : public AlgorithmParametersBase
{
public:
//! \brief Construct an AlgorithmParametersTemplate
//! \param name the name of the value
//! \param value a reference to the value
//! \param throwIfNotUsed flags indicating whether an exception should be thrown
//! \details If throwIfNotUsed is true, then a ParameterNotUsed exception
//! will be thrown in the destructor if the parameter is not not retrieved.
AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
: AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
{
}
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
{
// special case for retrieving an Integer parameter when an int was passed in
if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
{
NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
*reinterpret_cast<T *>(pValue) = m_value;
}
}
#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
# pragma push_macro("new")
# undef new
#endif
void MoveInto(void *buffer) const
{
AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
CRYPTOPP_UNUSED(p); // silence warning
}
#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
# pragma pop_macro("new")
#endif
protected:
T m_value;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
//! \class AlgorithmParameters
//! \brief An object that implements NameValuePairs
//! \tparam T the class or type
//! \param name the name of the object or value to retrieve
//! \param value reference to a variable that receives the value
//! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
//! \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
//! such as MSVC 7.0 and earlier.
//! \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
//! repeatedly using operator() on the object returned by MakeParameters, for example:
//! <pre>
//! AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
//! </pre>
class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
{
public:
AlgorithmParameters();
#ifdef __BORLANDC__
template <class T>
AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
: m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
, m_defaultThrowIfNotUsed(throwIfNotUsed)
{
}
#endif
AlgorithmParameters(const AlgorithmParameters &x);
AlgorithmParameters & operator=(const AlgorithmParameters &x);
//! \tparam T the class or type
//! \param name the name of the object or value to retrieve
//! \param value reference to a variable that receives the value
//! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
{
member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
p->m_next.reset(m_next.release());
m_next.reset(p.release());
m_defaultThrowIfNotUsed = throwIfNotUsed;
return *this;
}
//! \brief Appends a NameValuePair to a collection of NameValuePairs
//! \tparam T the class or type
//! \param name the name of the object or value to retrieve
//! \param value reference to a variable that receives the value
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value)
{
return operator()(name, value, m_defaultThrowIfNotUsed);
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
protected:
member_ptr<AlgorithmParametersBase> m_next;
bool m_defaultThrowIfNotUsed;
};
//! \brief Create an object that implements NameValuePairs
//! \tparam T the class or type
//! \param name the name of the object or value to retrieve
//! \param value reference to a variable that receives the value
//! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
//! \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
//! such as MSVC 7.0 and earlier.
//! \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
//! repeatedly using \p operator() on the object returned by \p MakeParameters, for example:
//! <pre>
//! AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
//! </pre>
#ifdef __BORLANDC__
typedef AlgorithmParameters MakeParameters;
#else
template <class T>
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
{
return AlgorithmParameters()(name, value, throwIfNotUsed);
}
#endif
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
// TODO: fix 6011 when the API/ABI can change
#if (CRYPTOPP_MSC_VERSION >= 1400)
# pragma warning(pop)
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,83 @@
// arc4.h - written and placed in the public domain by Wei Dai
//! \file arc4.h
//! \brief Classes for ARC4 cipher
#ifndef CRYPTOPP_ARC4_H
#define CRYPTOPP_ARC4_H
#include "cryptlib.h"
#include "strciphr.h"
#include "secblock.h"
#include "smartptr.h"
NAMESPACE_BEGIN(CryptoPP)
namespace Weak1 {
//! \class ARC4_Base
//! \brief Class specific methods used to operate the cipher.
//! \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions
class CRYPTOPP_NO_VTABLE ARC4_Base : public VariableKeyLength<16, 1, 256>, public RandomNumberGenerator, public SymmetricCipher, public SymmetricCipherDocumentation
{
public:
~ARC4_Base();
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "ARC4";}
void GenerateBlock(byte *output, size_t size);
void DiscardBytes(size_t n);
void ProcessData(byte *outString, const byte *inString, size_t length);
bool IsRandomAccess() const {return false;}
bool IsSelfInverting() const {return true;}
bool IsForwardTransformation() const {return true;}
typedef SymmetricCipherFinal<ARC4_Base> Encryption;
typedef SymmetricCipherFinal<ARC4_Base> Decryption;
protected:
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
virtual unsigned int GetDefaultDiscardBytes() const {return 0;}
FixedSizeSecBlock<byte, 256> m_state;
byte m_x, m_y;
};
//! <a href="http://www.weidai.com/scan-mirror/cs.html#RC4">Alleged RC4</a>
DOCUMENTED_TYPEDEF(SymmetricCipherFinal<ARC4_Base>, ARC4)
//! \class MARC4_Base
//! \brief Class specific methods used to operate the cipher.
//! \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions
//! \details MARC4 discards the first 256 bytes of keystream, which may be weaker than the rest
class CRYPTOPP_NO_VTABLE MARC4_Base : public ARC4_Base
{
public:
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "MARC4";}
typedef SymmetricCipherFinal<MARC4_Base> Encryption;
typedef SymmetricCipherFinal<MARC4_Base> Decryption;
protected:
unsigned int GetDefaultDiscardBytes() const {return 256;}
};
DOCUMENTED_TYPEDEF(SymmetricCipherFinal<MARC4_Base>, MARC4)
}
#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
#else
using namespace Weak1; // import Weak1 into CryptoPP with warning
#ifdef __GNUC__
#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
#else
#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
#endif
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,94 @@
// argnames.h - written and placed in the public domain by Wei Dai
//! \file argnames.h
//! \brief Standard names for retrieving values by name when working with \p NameValuePairs
#ifndef CRYPTOPP_ARGNAMES_H
#define CRYPTOPP_ARGNAMES_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
DOCUMENTED_NAMESPACE_BEGIN(Name)
#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector *
CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char *
CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) //!< const wchar_t *
CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream *
CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char *
CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) //!< const wchar_t *
CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream *
CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool
CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int
CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool
CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte
CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int
CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte *
CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte *
CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(Blinding) //!< bool, timing attack mitigations, ON by default
CRYPTOPP_DEFINE_NAME_STRING(DerivedKey) //!< ByteArrayParameter, key derivation, derived key
CRYPTOPP_DEFINE_NAME_STRING(DerivedKeyLength) //!< int, key derivation, derived key length in bytes
CRYPTOPP_DEFINE_NAME_STRING(Personalization) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(PersonalizationSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(Salt) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Tweak) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(SaltSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(TreeMode) //< byte
DOCUMENTED_NAMESPACE_END
NAMESPACE_END
#endif

View File

@ -0,0 +1,546 @@
// asn.h - written and placed in the public domain by Wei Dai
//! \file asn.h
//! \brief Classes and functions for working with ANS.1 objects
#ifndef CRYPTOPP_ASN_H
#define CRYPTOPP_ASN_H
#include "cryptlib.h"
#include "filters.h"
#include "smartptr.h"
#include "stdcpp.h"
#include "queue.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief ASN.1 types
//! \note These tags and flags are not complete
enum ASNTag
{
BOOLEAN = 0x01,
INTEGER = 0x02,
BIT_STRING = 0x03,
OCTET_STRING = 0x04,
TAG_NULL = 0x05,
OBJECT_IDENTIFIER = 0x06,
OBJECT_DESCRIPTOR = 0x07,
EXTERNAL = 0x08,
REAL = 0x09,
ENUMERATED = 0x0a,
UTF8_STRING = 0x0c,
SEQUENCE = 0x10,
SET = 0x11,
NUMERIC_STRING = 0x12,
PRINTABLE_STRING = 0x13,
T61_STRING = 0x14,
VIDEOTEXT_STRING = 0x15,
IA5_STRING = 0x16,
UTC_TIME = 0x17,
GENERALIZED_TIME = 0x18,
GRAPHIC_STRING = 0x19,
VISIBLE_STRING = 0x1a,
GENERAL_STRING = 0x1b
};
//! \brief ASN.1 flags
//! \note These tags and flags are not complete
enum ASNIdFlag
{
UNIVERSAL = 0x00,
// DATA = 0x01,
// HEADER = 0x02,
CONSTRUCTED = 0x20,
APPLICATION = 0x40,
CONTEXT_SPECIFIC = 0x80,
PRIVATE = 0xc0
};
//! \brief Raises a BERDecodeErr
inline void BERDecodeError() {throw BERDecodeErr();}
//! \brief Exception thrown when an unknown object identifier is encountered
class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
{
public:
//! \brief Construct an UnknownOID
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
//! \brief Construct an UnknownOID
//! \param err error message to use for the execption
UnknownOID(const char *err) : BERDecodeErr(err) {}
};
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
//! \brief DER encode a length
//! \param bt BufferedTransformation object for writing
//! \param length the size to encode
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &bt, lword length);
//! \brief BER decode a length
//! \param bt BufferedTransformation object for reading
//! \param length the decoded size
//! \returns true if the value was decoded
//! \throws BERDecodeError if the value fails to decode or is too large for size_t
//! \details BERLengthDecode() returns false if the encoding is indefinite length.
CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &bt, size_t &length);
//! \brief DER encode NULL
//! \param bt BufferedTransformation object for writing
CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &bt);
//! \brief BER decode NULL
//! \param bt BufferedTransformation object for reading
CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &bt);
//! \brief DER encode octet string
//! \param bt BufferedTransformation object for writing
//! \param str the string to encode
//! \param strLen the length of the string
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen);
//! \brief DER encode octet string
//! \param bt BufferedTransformation object for reading
//! \param str the string to encode
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str);
//! \brief BER decode octet string
//! \param bt BufferedTransformation object for reading
//! \param str the decoded string
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str);
//! \brief BER decode octet string
//! \param bt BufferedTransformation object for reading
//! \param str the decoded string
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str);
//! \brief DER encode text string
//! \param bt BufferedTransformation object for writing
//! \param str the string to encode
//! \param asnTag the ASN.1 type
//! \returns the number of octets used for the encoding
//! \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag);
//! \brief BER decode text string
//! \param bt BufferedTransformation object for reading
//! \param str the string to encode
//! \param asnTag the ASN.1 type
//! \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag);
//! \brief DER encode bit string
//! \param bt BufferedTransformation object for writing
//! \param str the string to encode
//! \param strLen the length of the string
//! \param unusedBits the number of unused bits
//! \returns the number of octets used for the encoding
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits=0);
//! \brief DER decode bit string
//! \param bt BufferedTransformation object for reading
//! \param str the decoded string
//! \param unusedBits the number of unused bits
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits);
//! \brief BER decode and DER re-encode
//! \param bt BufferedTransformation object for writing
//! \param dest BufferedTransformation object
CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &bt, BufferedTransformation &dest);
//! \brief Object Identifier
class CRYPTOPP_DLL OID
{
public:
//! \brief Construct an OID
OID() {}
//! \brief Construct an OID
//! \param v value to initialize the OID
OID(word32 v) : m_values(1, v) {}
//! \brief Construct an OID
//! \param bt BufferedTransformation object
OID(BufferedTransformation &bt) {BERDecode(bt);}
//! \brief Append a value to an OID
//! \param rhs the value to append
inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
//! \brief DER encode this OID
//! \param bt BufferedTransformation object
void DEREncode(BufferedTransformation &bt) const;
//! \brief BER decode an OID
//! \param bt BufferedTransformation object
void BERDecode(BufferedTransformation &bt);
//! \brief BER decode an OID
//! \param bt BufferedTransformation object
//! \throws BERDecodeErr() if decoded value doesn't match an expected OID
//! \details BERDecodeAndCheck() can be used to parse an OID and verify it matches an expected.
//! <pre>
//! BERSequenceDecoder key(bt);
//! ...
//! BERSequenceDecoder algorithm(key);
//! GetAlgorithmID().BERDecodeAndCheck(algorithm);
//! </pre>
void BERDecodeAndCheck(BufferedTransformation &bt) const;
std::vector<word32> m_values;
private:
static void EncodeValue(BufferedTransformation &bt, word32 v);
static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
};
//! \brief ASN.1 encoded object filter
class EncodedObjectFilter : public Filter
{
public:
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
//! \brief Construct an EncodedObjectFilter
//! \param attachment a BufferedTrasformation to attach to this object
//! \param nObjects
//! \param flags bitwise OR of EncodedObjectFilter::Flag
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
//! \brief Input a byte buffer for processing
//! \param inString the byte buffer to process
//! \param length the size of the string, in bytes
void Put(const byte *inString, size_t length);
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
private:
BufferedTransformation & CurrentTarget();
word32 m_flags;
unsigned int m_nObjects, m_nCurrentObject, m_level;
std::vector<unsigned int> m_positions;
ByteQueue m_queue;
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
byte m_id;
lword m_lengthRemaining;
};
//! \brief BER General Decoder
class CRYPTOPP_DLL BERGeneralDecoder : public Store
{
public:
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
~BERGeneralDecoder();
bool IsDefiniteLength() const {return m_definiteLength;}
lword RemainingLength() const {CRYPTOPP_ASSERT(m_definiteLength); return m_length;}
bool EndReached() const;
byte PeekByte() const;
void CheckByte(byte b);
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
// call this to denote end of sequence
void MessageEnd();
protected:
BufferedTransformation &m_inQueue;
bool m_finished, m_definiteLength;
lword m_length;
private:
void Init(byte asnTag);
void StoreInitialize(const NameValuePairs &parameters)
{CRYPTOPP_UNUSED(parameters); CRYPTOPP_ASSERT(false);}
lword ReduceLength(lword delta);
};
// GCC (and likely other compilers) identify the explicit DERGeneralEncoder as a copy constructor;
// and not a constructor. We had to remove the default asnTag value to point the compiler in the
// proper direction. We did not break the library or versioning based on the output of
// `nm --demangle libcryptopp.a | grep DERGeneralEncoder::DERGeneralEncoder | grep -v " U "`.
//! \brief DER General Encoder
class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
{
public:
#if defined(CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562)
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
#else
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag /*= SEQUENCE | CONSTRUCTED*/);
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag /*= SEQUENCE | CONSTRUCTED*/);
#endif
~DERGeneralEncoder();
// call this to denote end of sequence
void MessageEnd();
private:
BufferedTransformation &m_outQueue;
bool m_finished;
byte m_asnTag;
};
//! \brief BER Sequence Decoder
class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
{
public:
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
};
//! \brief DER Sequence Encoder
class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
{
public:
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
};
//! \brief BER Set Decoder
class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
{
public:
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
};
//! \brief DER Set Encoder
class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
{
public:
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
};
//! \brief Optional data encoder and decoder
//! \tparam T class or type
template <class T>
class ASNOptional : public member_ptr<T>
{
public:
//! \brief BER decode optional data
//! \param seqDecoder sequence with the optional ASN.1 data
//! \param tag ASN.1 tag to match as optional data
//! \param mask the mask to apply when matching the tag
//! \sa ASNTag and ASNIdFlag
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
{
byte b;
if (seqDecoder.Peek(b) && (b & mask) == tag)
reset(new T(seqDecoder));
}
//! \brief DER encode optional data
//! \param out BufferedTransformation object
void DEREncode(BufferedTransformation &out)
{
if (this->get() != NULL)
this->get()->DEREncode(out);
}
};
//! \brief Encode and decode ASN.1 objects with additional information
//! \tparam BASE base class or type
//! \details Encodes and decodes public keys, private keys and group
//! parameters with OID identifying the algorithm or scheme.
template <class BASE>
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
{
public:
//! \brief DER encode ASN.1 object
//! \param bt BufferedTransformation object
//! \details Save() will write the OID associated with algorithm or scheme.
//! In the case of public and private keys, this function writes the
//! subjectPubicKeyInfo and privateKeyInfo parts.
void Save(BufferedTransformation &bt) const
{BEREncode(bt);}
//! \brief BER decode ASN.1 object
//! \param bt BufferedTransformation object
void Load(BufferedTransformation &bt)
{BERDecode(bt);}
};
//! \brief Encodes and decodes subjectPublicKeyInfo
class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
{
public:
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
//! \brief Retrieves the OID of the algorithm
//! \returns OID of the algorithm
virtual OID GetAlgorithmID() const =0;
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{BERDecodeNull(bt); return false;}
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
//! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
//! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
};
//! \brief Encodes and decodesprivateKeyInfo
class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
{
public:
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
//! \brief Retrieves the OID of the algorithm
//! \returns OID of the algorithm
virtual OID GetAlgorithmID() const =0;
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{BERDecodeNull(bt); return false;}
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
//! decode privateKey part of privateKeyInfo, without the OCTET STRING header
virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
//! encode privateKey part of privateKeyInfo, without the OCTET STRING header
virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
//! decode optional attributes including context-specific tag
/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
//! encode optional attributes including context-specific tag
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
protected:
ByteQueue m_optionalAttributes;
};
// ********************************************************
//! \brief DER Encode unsigned value
//! \tparam T class or type
//! \param out BufferedTransformation object
//! \param w unsigned value to encode
//! \param asnTag the ASN.1 type
//! \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
template <class T>
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
{
byte buf[sizeof(w)+1];
unsigned int bc;
if (asnTag == BOOLEAN)
{
buf[sizeof(w)] = w ? 0xff : 0;
bc = 1;
}
else
{
buf[0] = 0;
for (unsigned int i=0; i<sizeof(w); i++)
buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
bc = sizeof(w);
while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
--bc;
if (buf[sizeof(w)+1-bc] & 0x80)
++bc;
}
out.Put(asnTag);
size_t lengthBytes = DERLengthEncode(out, bc);
out.Put(buf+sizeof(w)+1-bc, bc);
return 1+lengthBytes+bc;
}
//! \brief BER Decode unsigned value
//! \tparam T class or type
//! \param in BufferedTransformation object
//! \param w unsigned value to encode
//! \param asnTag the ASN.1 type
//! \param minValue the minimum expected value
//! \param maxValue the maximum expected value
//! \throws BERDecodeErr() if the value cannot be parsed or the decoded value is not within range.
//! \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
template <class T>
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
T minValue = 0, T maxValue = ((std::numeric_limits<T>::max)()))
{
byte b;
if (!in.Get(b) || b != asnTag)
BERDecodeError();
size_t bc;
bool definite = BERLengthDecode(in, bc);
if (!definite)
BERDecodeError();
SecByteBlock buf(bc);
if (bc != in.Get(buf, bc))
BERDecodeError();
const byte *ptr = buf;
while (bc > sizeof(w) && *ptr == 0)
{
bc--;
ptr++;
}
if (bc > sizeof(w))
BERDecodeError();
w = 0;
for (unsigned int i=0; i<bc; i++)
w = (w << 8) | ptr[i];
if (w < minValue || w > maxValue)
BERDecodeError();
}
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
//! \brief Compare two OIDs for equality
//! \param lhs the first OID
//! \param rhs the second OID
//! \returns true if the OIDs are equal, false otherwise
inline bool operator==(const OID &lhs, const OID &rhs);
//! \brief Compare two OIDs for inequality
//! \param lhs the first OID
//! \param rhs the second OID
//! \returns true if the OIDs are not equal, false otherwise
inline bool operator!=(const OID &lhs, const OID &rhs);
//! \brief Compare two OIDs for ordering
//! \param lhs the first OID
//! \param rhs the second OID
//! \returns true if the first OID is less than the second OID, false otherwise
//! \details operator<() calls std::lexicographical_compare() on each element in the array of values.
inline bool operator<(const OID &lhs, const OID &rhs);
//! \brief Append a value to an OID
//! \param lhs the OID
//! \param rhs the value to append
inline OID operator+(const OID &lhs, unsigned long rhs);
#else
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return lhs.m_values == rhs.m_values;}
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return lhs.m_values != rhs.m_values;}
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
{return ::CryptoPP::OID(lhs)+=rhs;}
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,66 @@
// authenc.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile authenc.h
//! \brief Base classes for working with authenticated encryption modes of encryption
//! \since Crypto++ 5.6.0
#ifndef CRYPTOPP_AUTHENC_H
#define CRYPTOPP_AUTHENC_H
#include "cryptlib.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class AuthenticatedSymmetricCipherBase
//! \brief Base implementation for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication
//! \since Crypto++ 5.6.0
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
{
public:
AuthenticatedSymmetricCipherBase() : m_state(State_Start), m_bufferedDataLength(0),
m_totalHeaderLength(0), m_totalMessageLength(0), m_totalFooterLength(0) {}
bool IsRandomAccess() const {return false;}
bool IsSelfInverting() const {return true;}
//! \brief Sets the key for this object without performing parameter validation
//! \param key a byte buffer used to key the cipher
//! \param length the length of the byte buffer
//! \param params additional parameters passed as NameValuePairs
//! \details key must be at least DEFAULT_KEYLENGTH in length.
void UncheckedSetKey(const byte * key, unsigned int length,const CryptoPP::NameValuePairs &params)
{CRYPTOPP_UNUSED(key), CRYPTOPP_UNUSED(length), CRYPTOPP_UNUSED(params); CRYPTOPP_ASSERT(false);}
void SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
void Resynchronize(const byte *iv, int length=-1);
void Update(const byte *input, size_t length);
void ProcessData(byte *outString, const byte *inString, size_t length);
void TruncatedFinal(byte *mac, size_t macSize);
protected:
void AuthenticateData(const byte *data, size_t len);
const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
virtual SymmetricCipher & AccessSymmetricCipher() =0;
virtual bool AuthenticationIsOnPlaintext() const =0;
virtual unsigned int AuthenticationBlockSize() const =0;
virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params) =0;
virtual void Resync(const byte *iv, size_t len) =0;
virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
virtual void AuthenticateLastHeaderBlock() =0;
virtual void AuthenticateLastConfidentialBlock() {}
virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
State m_state;
unsigned int m_bufferedDataLength;
lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
AlignedSecByteBlock m_buffer;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,96 @@
// base32.h - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai
//! \file
//! \brief Classes for Base32Encoder and Base32Decoder
#ifndef CRYPTOPP_BASE32_H
#define CRYPTOPP_BASE32_H
#include "cryptlib.h"
#include "basecode.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Base32Encoder
//! \brief Base32 encodes data
//! \details Converts data to base32. The default code is based on <A HREF="http://www.ietf.org/proceedings/51/I-D/draft-ietf-idn-dude-02.txt">Differential Unicode Domain Encoding (DUDE) (draft-ietf-idn-dude-02.txt)</A>.
class Base32Encoder : public SimpleProxyFilter
{
public:
//! \brief Construct a Base32Encoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \param uppercase a flag indicating uppercase output
//! \param groupSize the size of the grouping
//! \param separator the separator to use between groups
//! \param terminator the terminator appeand after processing
//! \details Base32Encoder() constructs a default encoder. The constructor lacks fields for padding and
//! line breaks. You must use IsolatedInitialize() to change the default padding character or suppress it.
//! \sa IsolatedInitialize() for an example of modifying a Base32Encoder after construction.
Base32Encoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int groupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), groupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator)));
}
//! \brief Initialize or reinitialize this object, without signal propagation
//! \param parameters a set of NameValuePairs used to initialize this object
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached
//! transformations. If initialization should be propagated, then use the Initialize() function.
//! \details The following code modifies the padding and line break parameters for an encoder:
//! <pre>
//! Base32Encoder encoder;
//! AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
//! encoder.IsolatedInitialize(params);</pre>
//! \details You can change the encoding to <A HREF="http://tools.ietf.org/html/rfc4648#page-10">RFC 4648, Base
//! 32 Encoding with Extended Hex Alphabet</A> by performing the following:
//! <pre>
//! Base32Encoder encoder;
//! const byte ALPHABET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
//! AlgorithmParameters params = MakeParameters(Name::EncodingLookupArray(),(const byte *)ALPHABET);
//! encoder.IsolatedInitialize(params);</pre>
//! \details If you change the encoding alphabet, then you will need to change the decoding alphabet \a and
//! the decoder's lookup table.
//! \sa Base32Decoder::IsolatedInitialize() for an example of changing a Base32Decoder's lookup table.
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! \class Base32Decoder
//! \brief Base32 decodes data
//! \details Decode base32 data. The default code is based on <A HREF="http://www.ietf.org/proceedings/51/I-D/draft-ietf-idn-dude-02.txt">Differential Unicode Domain Encoding (DUDE) (draft-ietf-idn-dude-02.txt)</A>.
class Base32Decoder : public BaseN_Decoder
{
public:
//! \brief Construct a Base32Decoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \sa IsolatedInitialize() for an example of modifying a Base32Decoder after construction.
Base32Decoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {}
//! \brief Initialize or reinitialize this object, without signal propagation
//! \param parameters a set of NameValuePairs used to initialize this object
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached
//! transformations. If initialization should be propagated, then use the Initialize() function.
//! \details You can change the encoding to <A HREF="http://tools.ietf.org/html/rfc4648#page-10">RFC 4648, Base
//! 32 Encoding with Extended Hex Alphabet</A> by performing the following:
//! <pre>
//! int lookup[256];
//! const byte ALPHABET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
//! Base32Decoder::InitializeDecodingLookupArray(lookup, ALPHABET, 32, true /*insensitive*/);
//!
//! Base32Decoder decoder;
//! AlgorithmParameters params = MakeParameters(Name::DecodingLookupArray(),(const int *)lookup);
//! decoder.IsolatedInitialize(params);</pre>
//! \sa Base32Encoder::IsolatedInitialize() for an example of changing a Base32Encoder's alphabet.
void IsolatedInitialize(const NameValuePairs &parameters);
private:
//! \brief Provides the default decoding lookup table
//! \return default decoding lookup table
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,162 @@
// base64.h - written and placed in the public domain by Wei Dai
//! \file base64.h
//! \brief Classes for the Base64Encoder, Base64Decoder, Base64URLEncoder and Base64URLDecoder
#ifndef CRYPTOPP_BASE64_H
#define CRYPTOPP_BASE64_H
#include "cryptlib.h"
#include "basecode.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Base64Encoder
//! \brief Base64 encodes data
//! \details Base64 encodes data per <A HREF="http://tools.ietf.org/html/rfc4648#section-4">RFC 4648, Base 64 Encoding</A>.
class Base64Encoder : public SimpleProxyFilter
{
public:
//! \brief Construct a Base64Encoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \param insertLineBreaks a BufferedTrasformation to attach to this object
//! \param maxLineLength the lenght of a line if line breaks are used
//! \details Base64Encoder constructs a default encoder. The constructor lacks a parameter for padding, and you must
//! use IsolatedInitialize() to modify the Base64Encoder after construction.
//! \sa IsolatedInitialize() for an example of modifying an encoder after construction.
Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72)
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength));
}
//! \brief Initialize or reinitialize this object, without signal propagation
//! \param parameters a set of NameValuePairs used to initialize this object
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached
//! transformations. If initialization should be propagated, then use the Initialize() function.
//! \details The following code modifies the padding and line break parameters for an encoder:
//! <pre>
//! Base64Encoder encoder;
//! AlgorithmParameters params = MakeParameters(Pad(), false)(InsertLineBreaks(), false);
//! encoder.IsolatedInitialize(params);</pre>
//! \details You can change the encoding to RFC 4648 web safe alphabet by performing the following:
//! <pre>
//! Base64Encoder encoder;
//! const byte ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
//! AlgorithmParameters params = MakeParameters(Name::EncodingLookupArray(),(const byte *)ALPHABET);
//! encoder.IsolatedInitialize(params);</pre>
//! \details If you change the encoding alphabet, then you will need to change the decoding alphabet \a and
//! the decoder's lookup table.
//! \sa Base64URLEncoder for an encoder that provides the web safe alphabet, and Base64Decoder::IsolatedInitialize()
//! for an example of modifying a decoder's lookup table after construction.
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! \class Base64Decoder
//! \brief Base64 decodes data
//! \details Base64 encodes data per <A HREF="http://tools.ietf.org/html/rfc4648#section-4">RFC 4648, Base 64 Encoding</A>.
class Base64Decoder : public BaseN_Decoder
{
public:
//! \brief Construct a Base64Decoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \sa IsolatedInitialize() for an example of modifying an encoder after construction.
Base64Decoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
//! \brief Initialize or reinitialize this object, without signal propagation
//! \param parameters a set of NameValuePairs used to initialize this object
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached
//! transformations. If initialization should be propagated, then use the Initialize() function.
//! \details The default decoding alpahbet is RFC 4868. You can change the to RFC 4868 web safe alphabet
//! by performing the following:
//! <pre>
//! int lookup[256];
//! const byte ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
//! Base64Decoder::InitializeDecodingLookupArray(lookup, ALPHABET, 64, false);
//!
//! Base64Decoder decoder;
//! AlgorithmParameters params = MakeParameters(Name::DecodingLookupArray(),(const int *)lookup);
//! decoder.IsolatedInitialize(params);</pre>
//! \sa Base64URLDecoder for a decoder that provides the web safe alphabet, and Base64Encoder::IsolatedInitialize()
//! for an example of modifying an encoder's alphabet after construction.
void IsolatedInitialize(const NameValuePairs &parameters);
private:
//! \brief Provides the default decoding lookup table
//! \return default decoding lookup table
static const int * CRYPTOPP_API GetDecodingLookupArray();
};
//! \class Base64URLEncoder
//! \brief Base64 encodes data using a web safe alphabet
//! \details Base64 encodes data per <A HREF="http://tools.ietf.org/html/rfc4648#section-5">RFC 4648, Base 64 Encoding
//! with URL and Filename Safe Alphabet</A>.
class Base64URLEncoder : public SimpleProxyFilter
{
public:
//! \brief Construct a Base64URLEncoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \param insertLineBreaks a BufferedTrasformation to attach to this object
//! \param maxLineLength the lenght of a line if line breaks are used
//! \details Base64URLEncoder() constructs a default encoder using a web safe alphabet. The constructor ignores
//! insertLineBreaks and maxLineLength because the web and URL safe specifications don't use them. They are
//! present in the constructor for API compatibility with Base64Encoder so it is a drop-in replacement. The
//! constructor also disables padding on the encoder for the same reason.
//! \details If you need line breaks or padding, then you must use IsolatedInitialize() to set them
//! after constructing a Base64URLEncoder.
//! \sa Base64Encoder for an encoder that provides a classic alphabet, and Base64URLEncoder::IsolatedInitialize
//! for an example of modifying an encoder after construction.
Base64URLEncoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = false, int maxLineLength = -1)
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
CRYPTOPP_UNUSED(insertLineBreaks), CRYPTOPP_UNUSED(maxLineLength);
IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), false)(Name::MaxLineLength(), -1)(Name::Pad(),false));
}
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on attached
//! transformations. If initialization should be propagated, then use the Initialize() function.
//! \details The following code modifies the padding and line break parameters for an encoder:
//! <pre>
//! Base64URLEncoder encoder;
//! AlgorithmParameters params = MakeParameters(Name::Pad(), true)(Name::InsertLineBreaks(), true);
//! encoder.IsolatedInitialize(params);</pre>
//! \sa Base64Encoder for an encoder that provides a classic alphabet.
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! \class Base64URLDecoder
//! \brief Base64 decodes data using a web safe alphabet
//! \details Base64 encodes data per <A HREF="http://tools.ietf.org/html/rfc4648#section-5">RFC 4648, Base 64 Encoding
//! with URL and Filename Safe Alphabet</A>.
class Base64URLDecoder : public BaseN_Decoder
{
public:
//! \brief Construct a Base64URLDecoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \details Base64URLDecoder() constructs a default decoder using a web safe alphabet.
//! \sa Base64Decoder for a decoder that provides a classic alphabet.
Base64URLDecoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
//! \brief Initialize or reinitialize this object, without signal propagation
//! \param parameters a set of NameValuePairs used to initialize this object
//! \details IsolatedInitialize() is used to initialize or reinitialize an object using a variable
//! number of arbitrarily typed arguments. IsolatedInitialize() does not call Initialize() on
//! attached transformations. If initialization should be propagated, then use the Initialize() function.
//! \sa Base64Decoder for a decoder that provides a classic alphabet, and Base64URLEncoder::IsolatedInitialize
//! for an example of modifying an encoder after construction.
void IsolatedInitialize(const NameValuePairs &parameters);
private:
//! \brief Provides the default decoding lookup table
//! \return default decoding lookup table
static const int * CRYPTOPP_API GetDecodingLookupArray();
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,142 @@
// basecode.h - written and placed in the public domain by Wei Dai
//! \file
//! \brief Base classes for working with encoders and decoders.
#ifndef CRYPTOPP_BASECODE_H
#define CRYPTOPP_BASECODE_H
#include "cryptlib.h"
#include "filters.h"
#include "algparam.h"
#include "argnames.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class BaseN_Encoder
//! \brief Encoder for bases that are a power of 2
class CRYPTOPP_DLL BaseN_Encoder : public Unflushable<Filter>
{
public:
//! \brief Construct a BaseN_Encoder
//! \param attachment a BufferedTransformation to attach to this object
BaseN_Encoder(BufferedTransformation *attachment=NULL)
: m_alphabet(NULL), m_padding(0), m_bitsPerChar(0)
, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
{Detach(attachment);}
//! \brief Construct a BaseN_Encoder
//! \param alphabet table of ASCII characters to use as the alphabet
//! \param log2base the log<sub>2</sub>base
//! \param attachment a BufferedTransformation to attach to this object
//! \param padding the character to use as padding
//! \pre log2base must be between 1 and 7 inclusive
//! \throws InvalidArgument if log2base is not between 1 and 7
BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
: m_alphabet(NULL), m_padding(0), m_bitsPerChar(0)
, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
(Name::Log2Base(), log2base)
(Name::Pad(), padding != -1)
(Name::PaddingByte(), byte(padding)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
private:
const byte *m_alphabet;
int m_padding, m_bitsPerChar, m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};
//! \class BaseN_Decoder
//! \brief Decoder for bases that are a power of 2
class CRYPTOPP_DLL BaseN_Decoder : public Unflushable<Filter>
{
public:
//! \brief Construct a BaseN_Decoder
//! \param attachment a BufferedTransformation to attach to this object
//! \details padding is set to -1, which means use default padding. If not
//! required, then the value must be set via IsolatedInitialize().
BaseN_Decoder(BufferedTransformation *attachment=NULL)
: m_lookup(0), m_padding(0), m_bitsPerChar(0)
, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
{Detach(attachment);}
//! \brief Construct a BaseN_Decoder
//! \param lookup table of values
//! \param log2base the log<sub>2</sub>base
//! \param attachment a BufferedTransformation to attach to this object
//! \details log2base is the exponent (like 5 in 2<sup>5</sup>), and not
//! the number of elements (like 32).
//! \details padding is set to -1, which means use default padding. If not
//! required, then the value must be set via IsolatedInitialize().
BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
: m_lookup(0), m_padding(0), m_bitsPerChar(0)
, m_outputBlockSize(0), m_bytePos(0), m_bitPos(0)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
//! \brief Intializes BaseN lookup array
//! \param lookup table of values
//! \param alphabet table of ASCII characters
//! \param base the base for the encoder
//! \param caseInsensitive flag indicating whether the alpabet is case sensitivie
//! \pre COUNTOF(lookup) == 256
//! \pre COUNTOF(alphabet) == base
//! \details Internally, the function sets the first 256 elements in the lookup table to
//! their value from the alphabet array or -1. base is the number of element (like 32),
//! and not an exponent (like 5 in 2<sup>5</sup>)
static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive);
private:
const int *m_lookup;
int m_padding, m_bitsPerChar, m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};
//! \class Grouper
//! \brief Filter that breaks input stream into groups of fixed size
class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
{
public:
//! \brief Construct a Grouper
//! \param attachment a BufferedTransformation to attach to this object
Grouper(BufferedTransformation *attachment=NULL)
: m_groupSize(0), m_counter(0) {Detach(attachment);}
//! \brief Construct a Grouper
//! \param groupSize the size of the grouping
//! \param separator the separator to use between groups
//! \param terminator the terminator appeand after processing
//! \param attachment a BufferedTransformation to attach to this object
Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
: m_groupSize(0), m_counter(0)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
(Name::Separator(), ConstByteArrayParameter(separator))
(Name::Terminator(), ConstByteArrayParameter(terminator)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
private:
SecByteBlock m_separator, m_terminator;
size_t m_groupSize, m_counter;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,13 @@
// bench.h - written and placed in the public domain by Wei Dai
#ifndef CRYPTOPP_BENCH_H
#define CRYPTOPP_BENCH_H
#include "cryptlib.h"
extern const double CLOCK_TICKS_PER_SECOND;
void BenchmarkAll(double t, double hertz);
void BenchmarkAll2(double t, double hertz);
#endif

View File

@ -0,0 +1,314 @@
// blake2.h - written and placed in the public domain by Jeffrey Walton and Zooko
// Wilcox-O'Hearn. Copyright assigned to the Crypto++ project.
// Based on Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's reference BLAKE2
// implementation at http://github.com/BLAKE2/BLAKE2.
//! \file blake2.h
//! \brief Classes for BLAKE2b and BLAKE2s message digests and keyed message digests
//! \details This implmentation follows Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
//! <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
//! Static algorithm name return either "BLAKE2b" or "BLAKE2s". An object algorithm name follows
//! the naming described in <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The
//! BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)</A>.
//! \details The library provides specialized SSE2, SSE4 and NEON version of the BLAKE2 compression
//! function. For best results under ARM NEON, specify both an architecture and cpu. For example:
//! <pre>CXXFLAGS="-DNDEBUG -march=armv8-a+crc -mcpu=cortex-a53 ..."</pre>
//! \since Crypto++ 5.6.4
#ifndef CRYPTOPP_BLAKE2_H
#define CRYPTOPP_BLAKE2_H
#include "cryptlib.h"
#include "secblock.h"
#include "seckey.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class BLAKE2_Info
//! \brief BLAKE2 hash information
//! \tparam T_64bit flag indicating 64-bit
//! \since Crypto++ 5.6.4
template <bool T_64bit>
struct BLAKE2_Info : public VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
{
typedef VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(BLOCKSIZE = (T_64bit ? 128 : 64))
CRYPTOPP_CONSTANT(DIGESTSIZE = (T_64bit ? 64 : 32))
CRYPTOPP_CONSTANT(SALTSIZE = (T_64bit ? 16 : 8))
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = (T_64bit ? 16 : 8))
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return (T_64bit ? "BLAKE2b" : "BLAKE2s");}
};
//! \class BLAKE2_ParameterBlock
//! \brief BLAKE2 parameter block
//! \tparam T_64bit flag indicating 64-bit
//! \details BLAKE2b uses BLAKE2_ParameterBlock<true>, while BLAKE2s
//! uses BLAKE2_ParameterBlock<false>.
//! \since Crypto++ 5.6.4
template <bool T_64bit>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock
{
};
//! \brief BLAKE2b parameter block specialization
template<>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<true>
{
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<true>::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<true>::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<true>::PERSONALIZATIONSIZE)
BLAKE2_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[8];
byte nodeDepth, innerLength, rfu[14];
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
};
//! \brief BLAKE2s parameter block specialization
template<>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<false>
{
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<false>::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<false>::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<false>::PERSONALIZATIONSIZE)
BLAKE2_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[6];
byte nodeDepth, innerLength;
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
};
//! \class BLAKE2_State
//! \brief BLAKE2 state information
//! \tparam W word type
//! \tparam T_64bit flag indicating 64-bit
//! \details BLAKE2b uses BLAKE2_State<word64, true>, while BLAKE2s
//! uses BLAKE2_State<word32, false>.
//! \since Crypto++ 5.6.4
template <class W, bool T_64bit>
struct CRYPTOPP_NO_VTABLE BLAKE2_State
{
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
BLAKE2_State()
{
// Set all members except scratch buffer[]
h[0]=h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7] = 0;
t[0]=t[1]=f[0]=f[1] = 0;
length = 0;
}
// SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side
W h[8], t[2], f[2];
byte buffer[BLOCKSIZE];
size_t length;
};
//! \class BLAKE2_Base
//! \brief BLAKE2 hash implementation
//! \tparam W word type
//! \tparam T_64bit flag indicating 64-bit
//! \details BLAKE2b uses BLAKE2_Base<word64, true>, while BLAKE2s
//! uses BLAKE2_Base<word32, false>.
//! \since Crypto++ 5.6.4
template <class W, bool T_64bit>
class BLAKE2_Base : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2_Info<T_64bit> >
{
public:
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2_Info<T_64bit>::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2_Info<T_64bit>::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2_Info<T_64bit>::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<T_64bit>::DIGESTSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<T_64bit>::SALTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<T_64bit>::PERSONALIZATIONSIZE)
typedef BLAKE2_State<W, T_64bit> State;
typedef BLAKE2_ParameterBlock<T_64bit> ParameterBlock;
typedef SecBlock<State, AllocatorWithCleanup<State, true> > AlignedState;
typedef SecBlock<ParameterBlock, AllocatorWithCleanup<ParameterBlock, true> > AlignedParameterBlock;
virtual ~BLAKE2_Base() {}
//! \brief Retrieve the static algorithm name
//! \returns the algorithm name (BLAKE2s or BLAKE2b)
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return BLAKE2_Info<T_64bit>::StaticAlgorithmName();}
//! \brief Retrieve the object's name
//! \returns the object's algorithm name following RFC 7693
//! \details Object algorithm name follows the naming described in
//! <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
//! Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
std::string AlgorithmName() const {return std::string(StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);}
unsigned int DigestSize() const {return m_digestSize;}
unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf<W>());}
void Update(const byte *input, size_t length);
void Restart();
//! \brief Restart a hash with parameter block and counter
//! \param block paramter block
//! \param counter counter array
//! \details Parameter block is persisted across calls to Restart().
void Restart(const BLAKE2_ParameterBlock<T_64bit>& block, const W counter[2]);
//! \brief Set tree mode
//! \param mode the new tree mode
//! \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
//! If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
//! <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
//! Tree mode is persisted across calls to Restart().
void SetTreeMode(bool mode) {m_treeMode=mode;}
//! \brief Get tree mode
//! \returns the current tree mode
//! \details Tree mode is persisted across calls to Restart().
bool GetTreeMode() const {return m_treeMode;}
void TruncatedFinal(byte *hash, size_t size);
protected:
BLAKE2_Base();
BLAKE2_Base(bool treeMode, unsigned int digestSize);
BLAKE2_Base(const byte *key, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength,
bool treeMode, unsigned int digestSize);
// Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
void Compress(const byte *input);
inline void IncrementCounter(size_t count=BLOCKSIZE);
void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
private:
AlignedState m_state;
AlignedParameterBlock m_block;
AlignedSecByteBlock m_key;
word32 m_digestSize;
bool m_treeMode;
};
//! \brief The BLAKE2b cryptographic hash function
//! \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
//! then use the BLAKE2b constructor that accepts no parameters or digest size. If you
//! want a keyed hash, then use the constuctor that accpts the key as a parameter.
//! Once a key and digest size are selected, its effectively immutable. The Restart()
//! method that accepts a ParameterBlock does not allow you to change it.
//! \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
//! <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
//! \since Crypto++ 5.6.4
class BLAKE2b : public BLAKE2_Base<word64, true>
{
public:
typedef BLAKE2_Base<word64, true> ThisBase; // Early Visual Studio workaround
typedef BLAKE2_ParameterBlock<true> ParameterBlock;
CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 64);
//! \brief Construct a BLAKE2b hash
//! \param digestSize the digest size, in bytes
//! \param treeMode flag indicating tree mode
BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
//! \brief Construct a BLAKE2b hash
//! \param key a byte array used to key the cipher
//! \param keyLength the size of the byte array
//! \param salt a byte array used as salt
//! \param saltLength the size of the byte array
//! \param personalization a byte array used as prsonalization string
//! \param personalizationLength the size of the byte array
//! \param treeMode flag indicating tree mode
//! \param digestSize the digest size, in bytes
BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULL, size_t saltLength = 0,
const byte* personalization = NULL, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
};
//! \brief The BLAKE2s cryptographic hash function
//! \details BLAKE2s can function as both a hash and keyed hash. If you want only the hash,
//! then use the BLAKE2s constructor that accepts no parameters or digest size. If you
//! want a keyed hash, then use the constuctor that accpts the key as a parameter.
//! Once a key and digest size are selected, its effectively immutable. The Restart()
//! method that accepts a ParameterBlock does not allow you to change it.
//! \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
//! <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
//! \since Crypto++ 5.6.4
class BLAKE2s : public BLAKE2_Base<word32, false>
{
public:
typedef BLAKE2_Base<word32, false> ThisBase; // Early Visual Studio workaround
typedef BLAKE2_ParameterBlock<false> ParameterBlock;
CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 32);
//! \brief Construct a BLAKE2s hash
//! \param digestSize the digest size, in bytes
//! \param treeMode flag indicating tree mode
BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
//! \brief Construct a BLAKE2s hash
//! \param key a byte array used to key the cipher
//! \param keyLength the size of the byte array
//! \param salt a byte array used as salt
//! \param saltLength the size of the byte array
//! \param personalization a byte array used as prsonalization string
//! \param personalizationLength the size of the byte array
//! \param treeMode flag indicating tree mode
//! \param digestSize the digest size, in bytes
BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULL, size_t saltLength = 0,
const byte* personalization = NULL, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,56 @@
// blowfish.h - written and placed in the public domain by Wei Dai
//! \file blowfish.h
//! \brief Classes for the Blowfish block cipher
#ifndef CRYPTOPP_BLOWFISH_H
#define CRYPTOPP_BLOWFISH_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Blowfish_Info
//! \brief Blowfish block cipher information
struct Blowfish_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 4, 56>, public FixedRounds<16>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "Blowfish";}
};
// <a href="http://www.weidai.com/scan-mirror/cs.html#Blowfish">Blowfish</a>
//! \class Blowfish_Info
//! \brief Blowfish block cipher
class Blowfish : public Blowfish_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief Class specific implementation and overrides used to operate the cipher.
//! \details Implementations and overrides in \p Base apply to both \p ENCRYPTION and \p DECRYPTION directions
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Blowfish_Info>
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
void UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &params);
private:
void crypt_block(const word32 in[2], word32 out[2]) const;
static const word32 p_init[ROUNDS+2];
static const word32 s_init[4*256];
FixedSizeSecBlock<word32, ROUNDS+2> pbox;
FixedSizeSecBlock<word32, 4*256> sbox;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
typedef Blowfish::Encryption BlowfishEncryption;
typedef Blowfish::Decryption BlowfishDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,63 @@
// blumshub.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile blumshub.h
//! \brief Classes for Blum Blum Shub generator
#ifndef CRYPTOPP_BLUMSHUB_H
#define CRYPTOPP_BLUMSHUB_H
#include "cryptlib.h"
#include "modarith.h"
#include "integer.h"
NAMESPACE_BEGIN(CryptoPP)
//! BlumBlumShub without factorization of the modulus
class PublicBlumBlumShub : public RandomNumberGenerator,
public StreamTransformation
{
public:
PublicBlumBlumShub(const Integer &n, const Integer &seed);
unsigned int GenerateBit();
byte GenerateByte();
void GenerateBlock(byte *output, size_t size);
void ProcessData(byte *outString, const byte *inString, size_t length);
bool IsSelfInverting() const {return true;}
bool IsForwardTransformation() const {return true;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~PublicBlumBlumShub() {}
#endif
protected:
ModularArithmetic modn;
Integer current;
word maxBits, bitsLeft;
};
//! BlumBlumShub with factorization of the modulus
class BlumBlumShub : public PublicBlumBlumShub
{
public:
// Make sure p and q are both primes congruent to 3 mod 4 and at least 512 bits long,
// seed is the secret key and should be about as big as p*q
BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed);
bool IsRandomAccess() const {return true;}
void Seek(lword index);
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~BlumBlumShub() {}
#endif
protected:
const Integer p, q;
const Integer x0;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,51 @@
// camellia.h - written and placed in the public domain by Wei Dai
//! \file camellia.h
//! \brief Classes for the Cameliia block cipher
#ifndef CRYPTOPP_CAMELLIA_H
#define CRYPTOPP_CAMELLIA_H
#include "config.h"
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Camellia_Info
//! \brief Camellia block cipher information
struct Camellia_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "Camellia";}
};
//! \class Camellia
//! \brief Camellia block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#Camellia">Camellia</a>
class Camellia : public Camellia_Info, public BlockCipherDocumentation
{
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Camellia_Info>
{
public:
void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
protected:
CRYPTOPP_ALIGN_DATA(4) static const byte s1[256];
static const word32 SP[4][256];
unsigned int m_rounds;
SecBlock<word32> m_key;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
typedef Camellia::Encryption CamelliaEncryption;
typedef Camellia::Decryption CamelliaDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,109 @@
// cast.h - written and placed in the public domain by Wei Dai
//! \file cast.h
//! \brief Classes for the CAST-128 and CAST-256 block ciphers
#ifndef CRYPTOPP_CAST_H
#define CRYPTOPP_CAST_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class CAST
//! \brief CAST block cipher base
class CAST
{
protected:
static const word32 S[8][256];
};
//! \class CAST128_Info
//! \brief CAST128 block cipher information
struct CAST128_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 5, 16>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "CAST-128";}
};
//! \class CAST128
//! \brief CAST128 block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#CAST-128">CAST-128</a>
class CAST128 : public CAST128_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief CAST128 block cipher default operation
class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl<CAST128_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
protected:
bool reduced;
FixedSizeSecBlock<word32, 32> K;
};
//! \class Enc
//! \brief CAST128 block cipher encryption operation
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \class Dec
//! \brief CAST128 block cipher decryption operation
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
//! \class CAST256_Info
//! \brief CAST256 block cipher information
struct CAST256_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 4>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "CAST-256";}
};
//! \class CAST256
//! \brief CAST256 block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#CAST-256">CAST-256</a>
class CAST256 : public CAST256_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief CAST256 block cipher default operation
class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl<CAST256_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
protected:
static const word32 t_m[8][24];
static const unsigned int t_r[8][24];
static void Omega(int i, word32 kappa[8]);
FixedSizeSecBlock<word32, 8*12> K;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
typedef CAST128::Encryption CAST128Encryption;
typedef CAST128::Decryption CAST128Decryption;
typedef CAST256::Encryption CAST256Encryption;
typedef CAST256::Decryption CAST256Decryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,56 @@
// cbcmac.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile cbcmac.h
//! \brief Classes for CBC MAC
#ifndef CRYPTOPP_CBCMAC_H
#define CRYPTOPP_CBCMAC_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode
{
public:
CBC_MAC_Base() : m_counter(0) {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int DigestSize() const {return const_cast<CBC_MAC_Base*>(this)->AccessCipher().BlockSize();}
protected:
virtual BlockCipher & AccessCipher() =0;
private:
void ProcessBuf();
SecByteBlock m_reg;
unsigned int m_counter;
};
//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
*/
template <class T>
class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
{
public:
CBC_MAC() {}
CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";}
private:
BlockCipher & AccessCipher() {return m_cipher;}
typename T::Encryption m_cipher;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,122 @@
// ccm.h - written and placed in the public domain by Wei Dai
//! \file ccm.h
//! \brief CCM block cipher mode of operation
//! \since Crypto++ 5.6.0
#ifndef CRYPTOPP_CCM_H
#define CRYPTOPP_CCM_H
#include "authenc.h"
#include "modes.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class CCM_Base
//! \brief CCM block cipher base implementation
//! \details Base implementation of the AuthenticatedSymmetricCipher interface
//! \since Crypto++ 5.6.0
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
{
public:
CCM_Base()
: m_digestSize(0), m_L(0), m_messageLength(0), m_aadLength(0) {}
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
size_t MinKeyLength() const
{return GetBlockCipher().MinKeyLength();}
size_t MaxKeyLength() const
{return GetBlockCipher().MaxKeyLength();}
size_t DefaultKeyLength() const
{return GetBlockCipher().DefaultKeyLength();}
size_t GetValidKeyLength(size_t n) const
{return GetBlockCipher().GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const
{return GetBlockCipher().IsValidKeyLength(n);}
unsigned int OptimalDataAlignment() const
{return GetBlockCipher().OptimalDataAlignment();}
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return 8;}
unsigned int MinIVLength() const
{return 7;}
unsigned int MaxIVLength() const
{return 13;}
unsigned int DigestSize() const
{return m_digestSize;}
lword MaxHeaderLength() const
{return W64LIT(0)-1;}
lword MaxMessageLength() const
{return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
bool NeedsPrespecifiedDataLengths() const
{return true;}
void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const
{return true;}
unsigned int AuthenticationBlockSize() const
{return GetBlockCipher().BlockSize();}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastConfidentialBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
virtual BlockCipher & AccessBlockCipher() =0;
virtual int DefaultDigestSize() const =0;
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
enum {REQUIRED_BLOCKSIZE = 16};
int m_digestSize, m_L;
word64 m_messageLength, m_aadLength;
CTR_Mode_ExternalCipher::Encryption m_ctr;
};
//! \class CCM_Final
//! \brief CCM block cipher final implementation
//! \tparam T_BlockCipher block cipher
//! \tparam T_DefaultDigestSize default digest size, in bytes
//! \tparam T_IsEncryption direction in which to operate the cipher
//! \since Crypto++ 5.6.0
template <class T_BlockCipher, int T_DefaultDigestSize, bool T_IsEncryption>
class CCM_Final : public CCM_Base
{
public:
static std::string StaticAlgorithmName()
{return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
bool IsForwardTransformation() const
{return T_IsEncryption;}
private:
BlockCipher & AccessBlockCipher() {return m_cipher;}
int DefaultDigestSize() const {return T_DefaultDigestSize;}
typename T_BlockCipher::Encryption m_cipher;
};
//! \class CCM
//! \brief CCM block cipher mode of operation
//! \tparam T_BlockCipher block cipher
//! \tparam T_DefaultDigestSize default digest size, in bytes
//! \details \p CCM provides the \p Encryption and \p Decryption typedef. See GCM_Base
//! and GCM_Final for the AuthenticatedSymmetricCipher implementation.
//! \sa <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a> at the Crypto Lounge
//! \since Crypto++ 5.6.0
template <class T_BlockCipher, int T_DefaultDigestSize = 16>
struct CCM : public AuthenticatedSymmetricCipherDocumentation
{
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, true> Encryption;
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, false> Decryption;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,91 @@
// chacha.h - written and placed in the public domain by Jeffrey Walton.
// Copyright assigned to the Crypto++ project.
// Based on Wei Dai's Salsa20 and Bernstein's reference ChaCha
// family implementation at http://cr.yp.to/chacha.html.
//! \file chacha.h
//! \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers
//! \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha,
//! a variant of Salsa20</a> (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's
//! implementation for cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
//! <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
//! \since Crypto++ 5.6.4
#ifndef CRYPTOPP_CHACHA_H
#define CRYPTOPP_CHACHA_H
#include "strciphr.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class ChaCha_Info
//! \brief ChaCha stream cipher information
//! \since Crypto++ 5.6.4
template <unsigned int R>
struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>, public FixedRounds<R>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {
return (R==8?"ChaCha8":(R==12?"ChaCha12":(R==20?"ChaCha20":"ChaCha")));
}
};
//! \class ChaCha_Policy
//! \brief ChaCha stream cipher implementation
//! \since Crypto++ 5.6.4
template <unsigned int R>
class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{
protected:
CRYPTOPP_CONSTANT(ROUNDS=FixedRounds<R>::ROUNDS)
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
bool CipherIsRandomAccess() const {return false;} // TODO
void SeekToIteration(lword iterationCount);
unsigned int GetAlignment() const;
unsigned int GetOptimalBlockSize() const;
FixedSizeAlignedSecBlock<word32, 16> m_state;
};
//! \class ChaCha8
//! \brief ChaCha8 stream cipher
//! \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
//! \since Crypto++ 5.6.4
struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation
{
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption;
typedef Encryption Decryption;
};
//! \class ChaCha12
//! \brief ChaCha12 stream cipher
//! \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working group's implementation for
//! cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
//! <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
//! \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
//! \since Crypto++ 5.6.4
struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation
{
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption;
typedef Encryption Decryption;
};
//! \class ChaCha20
//! \brief ChaCha20 stream cipher
//! \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
//! \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working group's implementation for
//! cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
//! <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
//! \since Crypto++ 5.6.4
struct ChaCha20 : public ChaCha_Info<20>, public SymmetricCipherDocumentation
{
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption;
typedef Encryption Decryption;
};
NAMESPACE_END
#endif // CRYPTOPP_CHACHA_H

View File

@ -0,0 +1,134 @@
// channels.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile channels.h
//! \brief Classes for multiple named channels
#ifndef CRYPTOPP_CHANNELS_H
#define CRYPTOPP_CHANNELS_H
#include "cryptlib.h"
#include "simple.h"
#include "smartptr.h"
#include "stdcpp.h"
NAMESPACE_BEGIN(CryptoPP)
#if 0
//! Route input on default channel to different and/or multiple channels based on message sequence number
class MessageSwitch : public Sink
{
public:
void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
void Put(byte inByte);
void Put(const byte *inString, unsigned int length);
void Flush(bool completeFlush, int propagation=-1);
void MessageEnd(int propagation=-1);
void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
void MessageSeriesEnd(int propagation=-1);
private:
typedef std::pair<BufferedTransformation *, std::string> Route;
struct RangeRoute
{
RangeRoute(unsigned int begin, unsigned int end, const Route &route)
: begin(begin), end(end), route(route) {}
bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
unsigned int begin, end;
Route route;
};
typedef std::list<RangeRoute> RouteList;
typedef std::list<Route> DefaultRouteList;
RouteList m_routes;
DefaultRouteList m_defaultRoutes;
unsigned int m_nCurrentMessage;
};
#endif
class ChannelSwitchTypedefs
{
public:
typedef std::pair<BufferedTransformation *, std::string> Route;
typedef std::multimap<std::string, Route> RouteMap;
typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
typedef std::list<DefaultRoute> DefaultRouteList;
// SunCC workaround: can't use const_iterator here
typedef RouteMap::iterator MapIterator;
typedef DefaultRouteList::iterator ListIterator;
};
class ChannelSwitch;
class ChannelRouteIterator : public ChannelSwitchTypedefs
{
public:
ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs), m_useDefault(false) {}
void Reset(const std::string &channel);
bool End() const;
void Next();
BufferedTransformation & Destination();
const std::string & Channel();
ChannelSwitch& m_cs;
std::string m_channel;
bool m_useDefault;
MapIterator m_itMapCurrent, m_itMapEnd;
ListIterator m_itListCurrent, m_itListEnd;
protected:
// Hide this to see if we break something...
ChannelRouteIterator();
};
//! Route input to different and/or multiple channels based on channel ID
class CRYPTOPP_DLL ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs
{
public:
ChannelSwitch() : m_it(*this), m_blocked(false) {}
ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false)
{
AddDefaultRoute(destination);
}
ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false)
{
AddDefaultRoute(destination, outChannel);
}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
void AddDefaultRoute(BufferedTransformation &destination);
void RemoveDefaultRoute(BufferedTransformation &destination);
void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
private:
RouteMap m_routeMap;
DefaultRouteList m_defaultRoutes;
ChannelRouteIterator m_it;
bool m_blocked;
friend class ChannelRouteIterator;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,67 @@
// cmac.h - written and placed in the public domain by Wei Dai
//! \file cmac.h
//! \brief Classes for CMAC message authentication code
//! \since Crypto++ 5.6.0
#ifndef CRYPTOPP_CMAC_H
#define CRYPTOPP_CMAC_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class CMAC_Base
//! \brief CMAC base implementation
//! \since Crypto++ 5.6.0
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
{
public:
CMAC_Base() : m_counter(0) {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int DigestSize() const {return GetCipher().BlockSize();}
unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
protected:
friend class EAX_Base;
const BlockCipher & GetCipher() const {return const_cast<CMAC_Base*>(this)->AccessCipher();}
virtual BlockCipher & AccessCipher() =0;
void ProcessBuf();
SecByteBlock m_reg;
unsigned int m_counter;
};
//! \brief CMAC message authentication code
//! \tparam T block cipher
//! \details Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32.
//! \sa <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
//! \since Crypto++ 5.6.0
template <class T>
class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
{
public:
//! \brief Construct a CMAC
CMAC() {}
//! \brief Construct a CMAC
//! \param key the MAC key
//! \param length the key size, in bytes
CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
private:
BlockCipher & AccessCipher() {return m_cipher;}
typename T::Encryption m_cipher;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,945 @@
// config.h - written and placed in the public domain by Wei Dai
//! \file config.h
//! \brief Library configuration file
#ifndef CRYPTOPP_CONFIG_H
#define CRYPTOPP_CONFIG_H
// ***************** Important Settings ********************
// define this if running on a big-endian CPU
#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || (defined(__m68k__) || defined(__MC68K__)) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
# define IS_BIG_ENDIAN
#endif
// define this if running on a little-endian CPU
// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
#ifndef IS_BIG_ENDIAN
# define IS_LITTLE_ENDIAN
#endif
// Sanity checks. Some processors have more than big-, little- and bi-endian modes. PDP mode, where order results in "4312", should
// raise red flags immediately. Additionally, mis-classified machines, like (previosuly) S/390, should raise red flags immediately.
#if defined(IS_BIG_ENDIAN) && defined(__GNUC__) && defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__)
# error "IS_BIG_ENDIAN is set, but __BYTE_ORDER__ does not equal __ORDER_BIG_ENDIAN__"
#endif
#if defined(IS_LITTLE_ENDIAN) && defined(__GNUC__) && defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
# error "IS_LITTLE_ENDIAN is set, but __BYTE_ORDER__ does not equal __ORDER_LITTLE_ENDIAN__"
#endif
// Define this if you want to disable all OS-dependent features,
// such as sockets and OS-provided random number generators
// #define NO_OS_DEPENDENCE
// Define this to use features provided by Microsoft's CryptoAPI.
// Currently the only feature used is Windows random number generation.
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
// #define USE_MS_CRYPTOAPI
// Define this to use features provided by Microsoft's CryptoNG API.
// CryptoNG API is available in Vista and above and its cross platform,
// including desktop apps and store apps. Currently the only feature
// used is Windows random number generation.
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
// #define USE_MS_CNGAPI
// If the user did not make a choice, then select CryptoNG if either
// Visual Studio 2015 is available, or Windows 10 or above is available.
#if !defined(USE_MS_CRYPTOAPI) && !defined(USE_MS_CNGAPI)
# if (_MSC_VER >= 1900) || ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/))
# define USE_MS_CNGAPI
# else
# define USE_MS_CRYPTOAPI
# endif
#endif
// Define this to ensure C/C++ standard compliance and respect for GCC aliasing rules and other alignment fodder. If you
// experience a break with GCC at -O3, you should try this first. Guard it in case its set on the command line (and it differs).
#ifndef CRYPTOPP_NO_UNALIGNED_DATA_ACCESS
# define CRYPTOPP_NO_UNALIGNED_DATA_ACCESS
#endif
// ***************** Less Important Settings ***************
// Library version
#define CRYPTOPP_VERSION 565
// Define this if you want to set a prefix for TestData/ and TestVectors/
// Be mindful of the trailing slash since its simple concatenation.
// g++ ... -DCRYPTOPP_DATA_DIR='"/tmp/cryptopp_test/share/"'
#ifndef CRYPTOPP_DATA_DIR
# define CRYPTOPP_DATA_DIR ""
#endif
// define this to retain (as much as possible) old deprecated function and class names
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
// Define this to retain (as much as possible) ABI and binary compatibility with Crypto++ 5.6.2.
// Also see https://cryptopp.com/wiki/Config.h#Avoid_MAINTAIN_BACKWARDS_COMPATIBILITY
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
// Define this if you want or need the library's memcpy_s and memmove_s.
// See http://github.com/weidai11/cryptopp/issues/28.
// #if !defined(CRYPTOPP_WANT_SECURE_LIB)
// # define CRYPTOPP_WANT_SECURE_LIB
// #endif
// File system code to write to GZIP archive.
#if !defined(GZIP_OS_CODE)
# define GZIP_OS_CODE 0
#endif
// Try this if your CPU has 256K internal cache or a slow multiply instruction
// and you want a (possibly) faster IDEA implementation using log tables
// #define IDEA_LARGECACHE
// Define this if, for the linear congruential RNG, you want to use
// the original constants as specified in S.K. Park and K.W. Miller's
// CACM paper.
// #define LCRNG_ORIGINAL_NUMBERS
// Define this if you want Integer's operator<< to honor std::showbase (and
// std::noshowbase). If defined, Integer will use a suffix of 'b', 'o', 'h'
// or '.' (the last for decimal) when std::showbase is in effect. If
// std::noshowbase is set, then the suffix is not added to the Integer. If
// not defined, existing behavior is preserved and Integer will use a suffix
// of 'b', 'o', 'h' or '.' (the last for decimal).
// #define CRYPTOPP_USE_STD_SHOWBASE
// choose which style of sockets to wrap (mostly useful for MinGW which has both)
#if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS)
# define PREFER_BERKELEY_STYLE_SOCKETS
#endif
// #if !defined(NO_WINDOWS_STYLE_SOCKETS) && !defined(PREFER_WINDOWS_STYLE_SOCKETS)
// # define PREFER_WINDOWS_STYLE_SOCKETS
// #endif
// set the name of Rijndael cipher, was "Rijndael" before version 5.3
#define CRYPTOPP_RIJNDAEL_NAME "AES"
// CRYPTOPP_DEBUG enables the library's CRYPTOPP_ASSERT. CRYPTOPP_ASSERT
// raises a SIGTRAP (Unix) or calls DebugBreak() (Windows). CRYPTOPP_ASSERT
// is only in effect when CRYPTOPP_DEBUG, DEBUG or _DEBUG is defined. Unlike
// Posix assert, CRYPTOPP_ASSERT is not affected by NDEBUG (or failure to
// define it).
// Also see http://github.com/weidai11/cryptopp/issues/277, CVE-2016-7420
#if (defined(DEBUG) || defined(_DEBUG)) && !defined(CRYPTOPP_DEBUG)
# define CRYPTOPP_DEBUG 1
#endif
// ***************** Initialization and Constructor priorities ********************
// MacPorts/GCC and Solaris/GCC does not provide constructor(priority). Apple/GCC and Fink/GCC do provide it.
// See http://cryptopp.com/wiki/Static_Initialization_Order_Fiasco
// CRYPTOPP_INIT_PRIORITY attempts to manage initialization of C++ static objects.
// Under GCC, the library uses init_priority attribute in the range
// [CRYPTOPP_INIT_PRIORITY, CRYPTOPP_INIT_PRIORITY+100]. Under Windows,
// CRYPTOPP_INIT_PRIORITY enlists "#pragma init_seg(lib)".
#ifndef CRYPTOPP_INIT_PRIORITY
# define CRYPTOPP_INIT_PRIORITY 250
#endif
// CRYPTOPP_USER_PRIORITY is for other libraries and user code that is using Crypto++
// and managing C++ static object creation. It is guaranteed not to conflict with
// values used by (or would be used by) the Crypto++ library.
#if defined(CRYPTOPP_INIT_PRIORITY) && (CRYPTOPP_INIT_PRIORITY > 0)
# define CRYPTOPP_USER_PRIORITY (CRYPTOPP_INIT_PRIORITY + 101)
#else
# define CRYPTOPP_USER_PRIORITY 350
#endif
// __attribute__(init_priority(250)) is supported
#if (__GNUC__ && (CRYPTOPP_INIT_PRIORITY > 0) && ((CRYPTOPP_GCC_VERSION >= 40300) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 300)) && !(MACPORTS_GCC_COMPILER > 0) && !defined(__sun__))
# define HAVE_GCC_CONSTRUCTOR1 1
#endif
// __attribute__(init_priority()) is supported
#if (__GNUC__ && (CRYPTOPP_INIT_PRIORITY > 0) && !HAVE_GCC_CONSTRUCTOR1 && !(MACPORTS_GCC_COMPILER > 0) && !defined(__sun__))
# define HAVE_GCC_CONSTRUCTOR0 1
#endif
#if (_MSC_VER && (CRYPTOPP_INIT_PRIORITY > 0))
# define HAVE_MSC_INIT_PRIORITY 1
#endif
// ***************** Important Settings Again ********************
// But the defaults should be ok.
// namespace support is now required
#ifdef NO_NAMESPACE
# error namespace support is now required
#endif
// Define this to workaround a Microsoft CryptoAPI bug where
// each call to CryptAcquireContext causes a 100 KB memory leak.
// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
#define WORKAROUND_MS_BUG_Q258000
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
// Document the namespce exists. Put it here before CryptoPP is undefined below.
//! \namespace CryptoPP
//! \brief Crypto++ library namespace
//! \details Nearly all classes are located in the CryptoPP namespace. Within
//! the namespace, there are two additional namespaces.
//! <ul>
//! <li>Name - namespace for names used with \p NameValuePairs and documented in argnames.h
//! <li>Weak - namespace for weak and wounded algorithms, like ARC4, MD5 and Pananma
//! </ul>
namespace CryptoPP { }
// Bring in the symbols fund in the weak namespace; and fold Weak1 into Weak
# define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
# define Weak1 Weak
// Avoid putting "CryptoPP::" in front of everything in Doxygen output
# define CryptoPP
# define NAMESPACE_BEGIN(x)
# define NAMESPACE_END
// Get Doxygen to generate better documentation for these typedefs
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
// Make "protected" "private" so the functions and members are not documented
# define protected private
#else
# define NAMESPACE_BEGIN(x) namespace x {
# define NAMESPACE_END }
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
#define ANONYMOUS_NAMESPACE_END }
#define USING_NAMESPACE(x) using namespace x;
#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
#define DOCUMENTED_NAMESPACE_END }
// What is the type of the third parameter to bind?
// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
// Unfortunately there is no way to tell whether or not socklen_t is defined.
// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
#ifndef TYPE_OF_SOCKLEN_T
# if defined(_WIN32) || defined(__CYGWIN__)
# define TYPE_OF_SOCKLEN_T int
# else
# define TYPE_OF_SOCKLEN_T ::socklen_t
# endif
#endif
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
# define __USE_W32_SOCKETS
#endif
typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs
NAMESPACE_BEGIN(CryptoPP)
typedef unsigned short word16;
typedef unsigned int word32;
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 word64;
#define W64LIT(x) x##ui64
#elif (_LP64 || __LP64__)
typedef unsigned long word64;
#define W64LIT(x) x##UL
#else
typedef unsigned long long word64;
#define W64LIT(x) x##ULL
#endif
// define large word type, used for file offsets and such
typedef word64 lword;
const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
// Clang pretends to be VC++, too.
// See http://github.com/weidai11/cryptopp/issues/147
#if defined(_MSC_VER) && defined(__clang__)
# error: "Unsupported configuration"
#endif
#ifdef __GNUC__
#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
// Apple and LLVM's Clang. Apple Clang version 7.0 roughly equals LLVM Clang version 3.7
#if defined(__clang__ ) && !defined(__apple_build_version__)
#define CRYPTOPP_LLVM_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#define CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER 1
#elif defined(__clang__ ) && defined(__apple_build_version__)
#define CRYPTOPP_APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#define CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER 1
#endif
#ifdef _MSC_VER
#define CRYPTOPP_MSC_VERSION (_MSC_VER)
#endif
// Need GCC 4.6/Clang 1.7/Apple Clang 2.0 or above due to "GCC diagnostic {push|pop}"
#if (CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_LLVM_CLANG_VERSION >= 10700) || (CRYPTOPP_APPLE_CLANG_VERSION >= 20000)
#define CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE 1
#endif
// Clang due to "Inline assembly operands don't work with .intel_syntax", http://llvm.org/bugs/show_bug.cgi?id=24232
// TODO: supply the upper version when LLVM fixes it. We set it to 20.0 for compilation purposes.
#if (defined(CRYPTOPP_LLVM_CLANG_VERSION) && CRYPTOPP_LLVM_CLANG_VERSION <= 200000) || (defined(CRYPTOPP_APPLE_CLANG_VERSION) && CRYPTOPP_APPLE_CLANG_VERSION <= 200000) || defined(CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER)
#define CRYPTOPP_DISABLE_INTEL_ASM 1
#endif
// define hword, word, and dword. these are used for multiprecision integer arithmetic
// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
typedef word32 hword;
typedef word64 word;
#else
#define CRYPTOPP_NATIVE_DWORD_AVAILABLE 1
#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
typedef word32 hword;
typedef word64 word;
typedef __uint128_t dword;
typedef __uint128_t word128;
#define CRYPTOPP_WORD128_AVAILABLE 1
#else
// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
typedef word16 hword;
typedef word32 word;
typedef word64 dword;
#endif
#else
// being here means the native register size is probably 32 bits or less
#define CRYPTOPP_BOOL_SLOW_WORD64 1
typedef word16 hword;
typedef word32 word;
typedef word64 dword;
#endif
#endif
#ifndef CRYPTOPP_BOOL_SLOW_WORD64
#define CRYPTOPP_BOOL_SLOW_WORD64 0
#endif
const unsigned int WORD_SIZE = sizeof(word);
const unsigned int WORD_BITS = WORD_SIZE * 8;
NAMESPACE_END
#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
// Also see http://stackoverflow.com/questions/794632/programmatically-get-the-cache-line-size.
#if defined(_M_X64) || defined(__x86_64__) || (__arm64__) || (__aarch64__)
#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
#else
// L1 cache line size is 32 on Pentium III and earlier
#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
#endif
#endif
#if defined(_MSC_VER)
#if _MSC_VER == 1200
#include <malloc.h>
#endif
#if _MSC_VER > 1200 || defined(_mm_free)
#define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later
#else
#define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack
#endif
#endif
#ifndef CRYPTOPP_ALIGN_DATA
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
#elif defined(__GNUC__)
#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
#else
#define CRYPTOPP_ALIGN_DATA(x)
#endif
#endif
#ifndef CRYPTOPP_SECTION_ALIGN16
#if defined(__GNUC__) && !defined(__APPLE__)
// the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
#define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
#else
#define CRYPTOPP_SECTION_ALIGN16
#endif
#endif
// The section attribute attempts to initialize CPU flags to avoid Valgrind findings above -O1
#if ((__MACH__ >= 1) && ((CRYPTOPP_LLVM_CLANG_VERSION >= 30600) || (CRYPTOPP_APPLE_CLANG_VERSION >= 70100) || (CRYPTOPP_GCC_VERSION >= 40300)))
#define CRYPTOPP_SECTION_INIT __attribute__((section ("__DATA,__data")))
#elif ((__ELF__ >= 1) && (CRYPTOPP_GCC_VERSION >= 40300))
#define CRYPTOPP_SECTION_INIT __attribute__((section ("nocommon")))
#else
#define CRYPTOPP_SECTION_INIT
#endif
#if defined(_MSC_VER) || defined(__fastcall)
#define CRYPTOPP_FASTCALL __fastcall
#else
#define CRYPTOPP_FASTCALL
#endif
// VC60 workaround: it doesn't allow typename in some places
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#define CPP_TYPENAME
#else
#define CPP_TYPENAME typename
#endif
// VC60 workaround: can't cast unsigned __int64 to float or double
#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_VC6_INT64 (__int64)
#else
#define CRYPTOPP_VC6_INT64
#endif
#ifdef _MSC_VER
#define CRYPTOPP_NO_VTABLE __declspec(novtable)
#else
#define CRYPTOPP_NO_VTABLE
#endif
#ifdef _MSC_VER
// 4127: conditional expression is constant
// 4231: nonstandard extension used : 'extern' before template explicit instantiation
// 4250: dominance
// 4251: member needs to have dll-interface
// 4275: base needs to have dll-interface
// 4505: unreferenced local function
// 4512: assignment operator not generated
// 4660: explicitly instantiating a class that's already implicitly instantiated
// 4661: no suitable definition provided for explicit template instantiation request
// 4786: identifer was truncated in debug information
// 4355: 'this' : used in base member initializer list
// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
# pragma warning(disable: 4127 4231 4250 4251 4275 4505 4512 4660 4661 4786 4355 4910)
// Security related, possible defects
// http://blogs.msdn.com/b/vcblog/archive/2010/12/14/off-by-default-compiler-warnings-in-visual-c.aspx
# pragma warning(once: 4191 4242 4263 4264 4266 4302 4826 4905 4906 4928)
#endif
#ifdef __BORLANDC__
// 8037: non-const function called for const object. needed to work around BCB2006 bug
# pragma warn -8037
#endif
// [GCC Bug 53431] "C++ preprocessor ignores #pragma GCC diagnostic". Clang honors it.
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic ignored "-Wunknown-pragmas"
# pragma GCC diagnostic ignored "-Wunused-function"
#endif
// You may need to force include a C++ header on Android when using STLPort to ensure
// _STLPORT_VERSION is defined: CXXFLAGS="-DNDEBUG -g2 -O2 -std=c++11 -include iosfwd"
// TODO: Figure out C++17 and lack of std::uncaught_exception
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || (defined(_STLPORT_VERSION) && ((_STLPORT_VERSION < 0x450) || defined(_STLP_NO_UNCAUGHT_EXCEPT_SUPPORT)))
#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
#endif
#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
#endif
#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings
#define CRYPTOPP_DISABLE_ASM
#define CRYPTOPP_DISABLE_SSE2
#endif
// Apple's Clang prior to 5.0 cannot handle SSE2 (and Apple does not use LLVM Clang numbering...)
#if defined(CRYPTOPP_APPLE_CLANG_VERSION) && (CRYPTOPP_APPLE_CLANG_VERSION < 50000)
# define CRYPTOPP_DISABLE_ASM
#endif
// Sun Studio 12 provides GCC inline assembly, http://blogs.oracle.com/x86be/entry/gcc_style_asm_inlining_support
// We can enable SSE2 for Sun Studio in the makefile with -D__SSE2__, but users may not compile with it.
#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(__SSE2__) && defined(__x86_64__) && (__SUNPRO_CC >= 0x5100)
# define __SSE2__ 1
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
#define CRYPTOPP_X86_ASM_AVAILABLE
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__))
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
#endif
#if !defined(CRYPTOPP_DISABLE_SSE3) && (_MSC_VER >= 1500 || (defined(__SSE3__) && defined(__SSSE3__)))
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
#endif
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
#define CRYPTOPP_X64_MASM_AVAILABLE
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
#define CRYPTOPP_X64_ASM_AVAILABLE
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__)) && !defined(_M_ARM)
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
#endif
// Intrinsics availible in GCC 4.3 (http://gcc.gnu.org/gcc-4.3/changes.html) and
// MSVC 2008 (http://msdn.microsoft.com/en-us/library/bb892950%28v=vs.90%29.aspx)
// SunCC could generate SSE4 at 12.1, but the intrinsics are missing until 12.4.
#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_SSE4) && !defined(_M_ARM) && ((_MSC_VER >= 1500) || (defined(__SSE4_1__) && defined(__SSE4_2__)))
#define CRYPTOPP_BOOL_SSE4_INTRINSICS_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSE4_INTRINSICS_AVAILABLE 0
#endif
// Don't disgorge AES-NI from CLMUL. There will be two to four subtle breaks
#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_AESNI) && !defined(_M_ARM) && (_MSC_FULL_VER >= 150030729 || __INTEL_COMPILER >= 1110 || (defined(__AES__) && defined(__PCLMUL__)))
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 0
#endif
// AVX2 in MSC 18.00
#if !defined(CRYPTOPP_DISABLE_ASM) && !defined(CRYPTOPP_DISABLE_AVX) && !defined(_M_ARM) && ((_MSC_VER >= 1600) || (defined(__RDRND__) || defined(__RDSEED__) || defined(__AVX__)))
#define CRYPTOPP_BOOL_AVX_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_AVX_AVAILABLE 0
#endif
// Requires ARMv7 and ACLE 1.0. Testing shows ARMv7 is really ARMv7a under most toolchains.
#if !defined(CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__ARM_NEON__) || defined(__ARM_NEON) || defined(_M_ARM)
# define CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE 1
# endif
#endif
// Requires ARMv8 and ACLE 2.0. For GCC, requires 4.8 and above.
// Microsoft plans to support ARM-64, but its not clear how to detect it.
// TODO: Add MSC_VER and ARM-64 platform define when available
#if !defined(CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__ARM_FEATURE_CRC32) || defined(_M_ARM64)
# define CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE 1
# endif
#endif
// Requires ARMv8 and ACLE 2.0. For GCC, requires 4.8 and above.
// Microsoft plans to support ARM-64, but its not clear how to detect it.
// TODO: Add MSC_VER and ARM-64 platform define when available
#if !defined(CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__ARM_FEATURE_CRYPTO) || defined(_M_ARM64)
# define CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE 1
# endif
#endif
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
#define CRYPTOPP_BOOL_ALIGN16 1
#else
#define CRYPTOPP_BOOL_ALIGN16 0
#endif
// how to allocate 16-byte aligned memory (for SSE2)
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_MM_MALLOC_AVAILABLE
#elif defined(__APPLE__)
#define CRYPTOPP_APPLE_MALLOC_AVAILABLE
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
#define CRYPTOPP_MEMALIGN_AVAILABLE
#else
#define CRYPTOPP_NO_ALIGNED_ALLOC
#endif
// Apple always provides 16-byte aligned, and tells us to use calloc
// http://developer.apple.com/library/mac/documentation/Performance/Conceptual/ManagingMemory/Articles/MemoryAlloc.html
// how to disable inlining
#if defined(_MSC_VER) && _MSC_VER >= 1300
# define CRYPTOPP_NOINLINE_DOTDOTDOT
# define CRYPTOPP_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
# define CRYPTOPP_NOINLINE_DOTDOTDOT
# define CRYPTOPP_NOINLINE __attribute__((noinline))
#else
# define CRYPTOPP_NOINLINE_DOTDOTDOT ...
# define CRYPTOPP_NOINLINE
#endif
// How to declare class constants
// Use enum for OS X 10.5 ld, http://github.com/weidai11/cryptopp/issues/255
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER) || defined(__BORLANDC__)
# define CRYPTOPP_CONSTANT(x) enum {x};
#else
# define CRYPTOPP_CONSTANT(x) static const int x;
#endif
// Linux provides X32, which is 32-bit integers, longs and pointers on x86_64 using the full x86_64 register set.
// Detect via __ILP32__ (http://wiki.debian.org/X32Port). However, __ILP32__ shows up in more places than
// the System V ABI specs calls out, like on just about any 32-bit system with Clang.
#if ((__ILP32__ >= 1) || (_ILP32 >= 1)) && defined(__x86_64__)
#define CRYPTOPP_BOOL_X32 1
#else
#define CRYPTOPP_BOOL_X32 0
#endif
// see http://predef.sourceforge.net/prearch.html
#if (defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)) && !CRYPTOPP_BOOL_X32
#define CRYPTOPP_BOOL_X86 1
#else
#define CRYPTOPP_BOOL_X86 0
#endif
#if (defined(_M_X64) || defined(__x86_64__)) && !CRYPTOPP_BOOL_X32
#define CRYPTOPP_BOOL_X64 1
#else
#define CRYPTOPP_BOOL_X64 0
#endif
// Undo the ASM and Intrinsic related defines due to X32.
#if CRYPTOPP_BOOL_X32
# undef CRYPTOPP_BOOL_X64
# undef CRYPTOPP_X64_ASM_AVAILABLE
# undef CRYPTOPP_X64_MASM_AVAILABLE
#endif
#if defined(__arm__) || defined(__aarch32__) || defined(_M_ARM)
#define CRYPTOPP_BOOL_ARM32 1
#else
#define CRYPTOPP_BOOL_ARM32 0
#endif
// Microsoft plans to support ARM-64, but its not clear how to detect it.
// TODO: Add MSC_VER and ARM-64 platform define when available
#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
#define CRYPTOPP_BOOL_ARM64 1
#else
#define CRYPTOPP_BOOL_ARM64 0
#endif
#if !defined(CRYPTOPP_NO_UNALIGNED_DATA_ACCESS) && !defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS)
#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || defined(__powerpc__) || (__ARM_FEATURE_UNALIGNED >= 1))
#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
#endif
#endif
// ***************** determine availability of OS features ********************
#ifndef NO_OS_DEPENDENCE
#if defined(_WIN32) || defined(__CYGWIN__)
#define CRYPTOPP_WIN32_AVAILABLE
#endif
#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
#define CRYPTOPP_UNIX_AVAILABLE
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define CRYPTOPP_BSD_AVAILABLE
#endif
#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
# define HIGHRES_TIMER_AVAILABLE
#endif
#ifdef CRYPTOPP_WIN32_AVAILABLE
# if !defined(WINAPI_FAMILY)
# define THREAD_TIMER_AVAILABLE
# elif defined(WINAPI_FAMILY)
# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
# define THREAD_TIMER_AVAILABLE
# endif
# endif
#endif
#ifdef CRYPTOPP_UNIX_AVAILABLE
# define HAS_BERKELEY_STYLE_SOCKETS
# define SOCKETS_AVAILABLE
#endif
// Sockets are only available under Windows Runtime desktop partition apps (despite the MSDN literature)
#ifdef CRYPTOPP_WIN32_AVAILABLE
# define HAS_WINDOWS_STYLE_SOCKETS
# if !defined(WINAPI_FAMILY)
# define SOCKETS_AVAILABLE
# elif defined(WINAPI_FAMILY)
# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
# define SOCKETS_AVAILABLE
# endif
# endif
#endif
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
# define USE_WINDOWS_STYLE_SOCKETS
#else
# define USE_BERKELEY_STYLE_SOCKETS
#endif
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(SOCKETS_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
# define WINDOWS_PIPES_AVAILABLE
#endif
#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
# define NONBLOCKING_RNG_AVAILABLE
# define BLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
# define HAS_PTHREADS
# define THREADS_AVAILABLE
#endif
#if defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) || defined(__CYGWIN__)
# define UNIX_SIGNALS_AVAILABLE 1
#endif
#ifdef CRYPTOPP_WIN32_AVAILABLE
# if !defined(WINAPI_FAMILY)
# define HAS_WINTHREADS
# define THREADS_AVAILABLE
# define NONBLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
# elif defined(WINAPI_FAMILY)
# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
# define HAS_WINTHREADS
# define THREADS_AVAILABLE
# define NONBLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
# elif !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
# if ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/))
# define NONBLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
# endif
# endif
# endif
#endif
#endif // NO_OS_DEPENDENCE
// ***************** DLL related ********************
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
#ifdef CRYPTOPP_EXPORTS
#define CRYPTOPP_IS_DLL
#define CRYPTOPP_DLL __declspec(dllexport)
#elif defined(CRYPTOPP_IMPORTS)
#define CRYPTOPP_IS_DLL
#define CRYPTOPP_DLL __declspec(dllimport)
#else
#define CRYPTOPP_DLL
#endif
#define CRYPTOPP_API __cdecl
#else // not CRYPTOPP_WIN32_AVAILABLE
#define CRYPTOPP_DLL
#define CRYPTOPP_API
#endif // CRYPTOPP_WIN32_AVAILABLE
#if defined(__MWERKS__)
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
#else
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
#endif
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
#else
#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
#endif
#if defined(__MWERKS__)
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
#else
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
#endif
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
#else
#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
#endif
// ************** Unused variable ***************
// Portable way to suppress warnings.
// Moved from misc.h due to circular depenedencies.
#define CRYPTOPP_UNUSED(x) ((void)(x))
// ************** Deprecated ***************
#if (CRYPTOPP_GCC_VERSION >= 40500) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20800)
# define CRYPTOPP_DEPRECATED(msg) __attribute__((deprecated (msg)));
#elif (CRYPTOPP_GCC_VERSION)
# define CRYPTOPP_DEPRECATED(msg) __attribute__((deprecated));
#else
# define CRYPTOPP_DEPRECATED(msg)
#endif
// ***************** C++11 related ********************
// Visual Studio began at VS2010, http://msdn.microsoft.com/en-us/library/hh567368%28v=vs.110%29.aspx.
// Intel and C++11 language features, http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
// GCC and C++11 language features, http://gcc.gnu.org/projects/cxx0x.html
// Clang and C++11 language features, http://clang.llvm.org/cxx_status.html
#if ((_MSC_VER >= 1600) || (__cplusplus >= 201103L)) && !defined(_STLPORT_VERSION)
# define CRYPTOPP_CXX11 1
#endif
// Hack ahead. Apple's standard library does not have C++'s unique_ptr in C++11. We can't
// test for unique_ptr directly because some of the non-Apple Clangs on OS X fail the same
// way. However, modern standard libraries have <forward_list>, so we test for it instead.
// Thanks to Jonathan Wakely for devising the clever test for modern/ancient versions.
// TODO: test under Xcode 3, where g++ is really g++.
#if defined(__APPLE__) && defined(__clang__)
# if !(defined(__has_include) && __has_include(<forward_list>))
# undef CRYPTOPP_CXX11
# endif
#endif
// C++11 or C++14 is available
#if defined(CRYPTOPP_CXX11)
// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; Intel 13.0; SunCC 12.5.
#if (CRYPTOPP_MSC_VERSION >= 1700)
# define CRYPTOPP_CXX11_ATOMICS 1
#elif (__INTEL_COMPILER >= 1300)
# define CRYPTOPP_CXX11_ATOMICS 1
#elif defined(__clang__)
# if __has_feature(cxx_atomic)
# define CRYPTOPP_CXX11_ATOMICS 1
# endif
#elif (CRYPTOPP_GCC_VERSION >= 40400)
# define CRYPTOPP_CXX11_ATOMICS 1
#elif (__SUNPRO_CC >= 0x5140)
# define CRYPTOPP_CXX11_ATOMICS 1
#endif // atomics
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; Intel 12.0; SunCC 12.4.
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
#if (CRYPTOPP_MSC_VERSION >= 1700)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (__INTEL_COMPILER >= 1200)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_GCC_VERSION >= 40400)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#endif // synchronization
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; Intel 15.0; SunCC 12.4.
#if (CRYPTOPP_MSC_VERSION >= 1900)
# define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1
#elif (__INTEL_COMPILER >= 1500)
# define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1
#elif defined(__clang__)
# if __has_feature(cxx_alignas)
# define CRYPTOPP_CXX11_ALIGNAS 1
# endif
# if __has_feature(cxx_alignof)
# define CRYPTOPP_CXX11_ALIGNOF 1
# endif
#elif (CRYPTOPP_GCC_VERSION >= 40800)
# define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1
#elif (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1
#endif // alignof/alignas
// noexcept: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 14.0; SunCC 12.4.
#if (CRYPTOPP_MSC_VERSION >= 1900)
# define CRYPTOPP_CXX11_NOEXCEPT 1
#elif (__INTEL_COMPILER >= 1400)
# define CRYPTOPP_CXX11_NOEXCEPT 1
#elif defined(__clang__)
# if __has_feature(cxx_noexcept)
# define CRYPTOPP_CXX11_NOEXCEPT 1
# endif
#elif (CRYPTOPP_GCC_VERSION >= 40600)
# define CRYPTOPP_CXX11_NOEXCEPT 1
#elif (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_NOEXCEPT 1
#endif // noexcept compilers
// variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 12.4.
#if (CRYPTOPP_MSC_VERSION >= 1800)
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
#elif (__INTEL_COMPILER >= 1210)
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
#elif defined(__clang__)
# if __has_feature(cxx_variadic_templates)
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
# endif
#elif (CRYPTOPP_GCC_VERSION >= 40300)
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
#elif (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
#endif // variadic templates
// constexpr: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 16.0; SunCC 12.4.
// Intel has mis-supported the feature since at least ICPC 13.00
#if (CRYPTOPP_MSC_VERSION >= 1900)
# define CRYPTOPP_CXX11_CONSTEXPR 1
#elif (__INTEL_COMPILER >= 1600)
# define CRYPTOPP_CXX11_CONSTEXPR 1
#elif defined(__clang__)
# if __has_feature(cxx_constexpr)
# define CRYPTOPP_CXX11_CONSTEXPR 1
# endif
#elif (CRYPTOPP_GCC_VERSION >= 40600)
# define CRYPTOPP_CXX11_CONSTEXPR 1
#elif (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_CONSTEXPR 1
#endif // constexpr compilers
// TODO: Emplacement, R-values and Move semantics
// Needed because we are catching warnings with GCC and MSC
#endif // CRYPTOPP_CXX11
#if defined(CRYPTOPP_CXX11_NOEXCEPT)
# define CRYPTOPP_THROW noexcept(false)
# define CRYPTOPP_NO_THROW noexcept(true)
#else
# define CRYPTOPP_THROW
# define CRYPTOPP_NO_THROW
#endif // CRYPTOPP_CXX11_NOEXCEPT
#if defined(CRYPTOPP_CXX11_CONSTEXPR)
# define CRYPTOPP_CONSTEXPR constexpr
#else
# define CRYPTOPP_CONSTEXPR
#endif // CRYPTOPP_CXX11_CONSTEXPR
// Hack... CRYPTOPP_ALIGN_DATA is defined earlier, before C++11 alignas availability is determined
#if defined(CRYPTOPP_CXX11_ALIGNAS)
# undef CRYPTOPP_ALIGN_DATA
# define CRYPTOPP_ALIGN_DATA(x) alignas(x)
#endif // CRYPTOPP_CXX11_ALIGNAS
// Hack... CRYPTOPP_CONSTANT is defined earlier, before C++11 constexpr availability is determined
#if defined(CRYPTOPP_CXX11_CONSTEXPR)
# undef CRYPTOPP_CONSTANT
# define CRYPTOPP_CONSTANT(x) constexpr static int x;
#endif
// OK to comment the following out, but please report it so we can fix it.
// C++17 value taken from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf.
#if (defined(__cplusplus) && (__cplusplus >= 199711L) && (__cplusplus < 201402L)) && !defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
# error "std::uncaught_exception is not available. This is likely a configuration error."
#endif
#endif

View File

@ -0,0 +1,597 @@
// cpu.h - written and placed in the public domain by Wei Dai
//! \file cpu.h
//! \brief Functions for CPU features and intrinsics
//! \details The functions are used in X86/X32/X64 and NEON code paths
#ifndef CRYPTOPP_CPU_H
#define CRYPTOPP_CPU_H
#include "config.h"
// ARM32/ARM64 Headers
#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
# if defined(__GNUC__)
# include <stdint.h>
# endif
# if CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE || defined(__ARM_NEON)
# include <arm_neon.h>
# endif
# if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE) || defined(__ARM_ACLE)
# include <arm_acle.h>
# endif
#endif // ARM32 and ARM64 Headers
// X86/X64/X32 Headers
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
// GCC X86 super-include
#if (CRYPTOPP_GCC_VERSION >= 40800)
# include <x86intrin.h>
#endif
#if (CRYPTOPP_MSC_VERSION >= 1400)
# include <intrin.h>
#endif
// Baseline include
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
# include <emmintrin.h> // __m64, __m128i, _mm_set_epi64x
#endif
#if CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE
# include <tmmintrin.h> // _mm_shuffle_pi8, _mm_shuffle_epi8
#endif // tmmintrin.h
#if CRYPTOPP_BOOL_SSE4_INTRINSICS_AVAILABLE
# include <smmintrin.h> // _mm_blend_epi16
# include <nmmintrin.h> // _mm_crc32_u{8|16|32}
#endif // smmintrin.h
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
# include <wmmintrin.h> // aesenc, aesdec, etc
#endif // wmmintrin.h
#if CRYPTOPP_BOOL_AVX_INTRINSICS_AVAILABLE
# include <immintrin.h> // RDRAND, RDSEED and AVX
#endif
#if CRYPTOPP_BOOL_AVX2_INTRINSICS_AVAILABLE
# include <zmmintrin.h> // AVX 512-bit extensions
#endif
#endif // X86/X64/X32 Headers
// Applies to both X86/X32/X64 and ARM32/ARM64. And we've got MIPS devices on the way.
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
#else
# define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
#endif
// Applies to both X86/X32/X64 and ARM32/ARM64
#if defined(CRYPTOPP_LLVM_CLANG_VERSION) || defined(CRYPTOPP_APPLE_CLANG_VERSION) || defined(CRYPTOPP_CLANG_INTEGRATED_ASSEMBLER)
#define NEW_LINE "\n"
#define INTEL_PREFIX ".intel_syntax;"
#define INTEL_NOPREFIX ".intel_syntax;"
#define ATT_PREFIX ".att_syntax;"
#define ATT_NOPREFIX ".att_syntax;"
#elif defined(__GNUC__)
#define NEW_LINE
#define INTEL_PREFIX ".intel_syntax prefix;"
#define INTEL_NOPREFIX ".intel_syntax noprefix;"
#define ATT_PREFIX ".att_syntax prefix;"
#define ATT_NOPREFIX ".att_syntax noprefix;"
#else
#define NEW_LINE
#define INTEL_PREFIX
#define INTEL_NOPREFIX
#define ATT_PREFIX
#define ATT_NOPREFIX
#endif
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define CRYPTOPP_X86_ASM_AVAILABLE
#define CRYPTOPP_BOOL_X64 1
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
#define NAMESPACE_END
#else
NAMESPACE_BEGIN(CryptoPP)
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 || CRYPTOPP_DOXYGEN_PROCESSING
#define CRYPTOPP_CPUID_AVAILABLE
// Hide from Doxygen
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
// These should not be used directly
extern CRYPTOPP_DLL bool g_x86DetectionDone;
extern CRYPTOPP_DLL bool g_hasMMX;
extern CRYPTOPP_DLL bool g_hasISSE;
extern CRYPTOPP_DLL bool g_hasSSE2;
extern CRYPTOPP_DLL bool g_hasSSSE3;
extern CRYPTOPP_DLL bool g_hasSSE4;
extern CRYPTOPP_DLL bool g_hasAESNI;
extern CRYPTOPP_DLL bool g_hasCLMUL;
extern CRYPTOPP_DLL bool g_isP4;
extern CRYPTOPP_DLL bool g_hasRDRAND;
extern CRYPTOPP_DLL bool g_hasRDSEED;
extern CRYPTOPP_DLL bool g_hasPadlockRNG;
extern CRYPTOPP_DLL bool g_hasPadlockACE;
extern CRYPTOPP_DLL bool g_hasPadlockACE2;
extern CRYPTOPP_DLL bool g_hasPadlockPHE;
extern CRYPTOPP_DLL bool g_hasPadlockPMM;
extern CRYPTOPP_DLL word32 g_cacheLineSize;
CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 output[4]);
#endif // CRYPTOPP_DOXYGEN_PROCESSING
//! \brief Determines MMX availability
//! \returns true if MMX is determined to be available, false otherwise
//! \details MMX, SSE and SSE2 are core processor features for x86_64, and
//! the function always returns true for the platform.
inline bool HasMMX()
{
#if CRYPTOPP_BOOL_X64
return true;
#else
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasMMX;
#endif
}
//! \brief Determines SSE availability
//! \returns true if SSE is determined to be available, false otherwise
//! \details MMX, SSE and SSE2 are core processor features for x86_64, and
//! the function always returns true for the platform.
inline bool HasISSE()
{
#if CRYPTOPP_BOOL_X64
return true;
#else
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasISSE;
#endif
}
//! \brief Determines SSE2 availability
//! \returns true if SSE2 is determined to be available, false otherwise
//! \details MMX, SSE and SSE2 are core processor features for x86_64, and
//! the function always returns true for the platform.
inline bool HasSSE2()
{
#if CRYPTOPP_BOOL_X64
return true;
#else
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasSSE2;
#endif
}
//! \brief Determines SSSE3 availability
//! \returns true if SSSE3 is determined to be available, false otherwise
//! \details HasSSSE3() is a runtime check performed using CPUID
//! \note Some Clang compilers incorrectly omit SSSE3 even though its native to the processor.
inline bool HasSSSE3()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasSSSE3;
}
//! \brief Determines SSE4 availability
//! \returns true if SSE4.1 and SSE4.2 are determined to be available, false otherwise
//! \details HasSSE4() is a runtime check performed using CPUID which requires both SSE4.1 and SSE4.2
inline bool HasSSE4()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasSSE4;
}
//! \brief Determines AES-NI availability
//! \returns true if AES-NI is determined to be available, false otherwise
//! \details HasAESNI() is a runtime check performed using CPUID
inline bool HasAESNI()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasAESNI;
}
//! \brief Determines Carryless Multiply availability
//! \returns true if pclmulqdq is determined to be available, false otherwise
//! \details HasCLMUL() is a runtime check performed using CPUID
inline bool HasCLMUL()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasCLMUL;
}
//! \brief Determines if the CPU is an Intel P4
//! \returns true if the CPU is a P4, false otherwise
//! \details IsP4() is a runtime check performed using CPUID
inline bool IsP4()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_isP4;
}
//! \brief Determines RDRAND availability
//! \returns true if RDRAND is determined to be available, false otherwise
//! \details HasRDRAND() is a runtime check performed using CPUID
inline bool HasRDRAND()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasRDRAND;
}
//! \brief Determines RDSEED availability
//! \returns true if RDSEED is determined to be available, false otherwise
//! \details HasRDSEED() is a runtime check performed using CPUID
inline bool HasRDSEED()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasRDSEED;
}
//! \brief Determines Padlock RNG availability
//! \returns true if VIA Padlock RNG is determined to be available, false otherwise
//! \details HasPadlockRNG() is a runtime check performed using CPUID
inline bool HasPadlockRNG()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockRNG;
}
//! \brief Determines Padlock ACE availability
//! \returns true if VIA Padlock ACE is determined to be available, false otherwise
//! \details HasPadlockACE() is a runtime check performed using CPUID
inline bool HasPadlockACE()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockACE;
}
//! \brief Determines Padlock ACE2 availability
//! \returns true if VIA Padlock ACE2 is determined to be available, false otherwise
//! \details HasPadlockACE2() is a runtime check performed using CPUID
inline bool HasPadlockACE2()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockACE2;
}
//! \brief Determines Padlock PHE availability
//! \returns true if VIA Padlock PHE is determined to be available, false otherwise
//! \details HasPadlockPHE() is a runtime check performed using CPUID
inline bool HasPadlockPHE()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockPHE;
}
//! \brief Determines Padlock PMM availability
//! \returns true if VIA Padlock PMM is determined to be available, false otherwise
//! \details HasPadlockPMM() is a runtime check performed using CPUID
inline bool HasPadlockPMM()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockPMM;
}
//! \brief Provides the cache line size
//! \returns lower bound on the size of a cache line in bytes, if available
//! \details GetCacheLineSize() returns the lower bound on the size of a cache line, if it
//! is available. If the value is not available at runtime, then 32 is returned for a 32-bit
//! processor and 64 is returned for a 64-bit processor.
//! \details x86/x32/x64 uses CPUID to determine the value and its usually accurate. The ARM
//! processor equivalent is a privileged instruction, so a compile time value is returned.
inline int GetCacheLineSize()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_cacheLineSize;
}
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
extern bool g_ArmDetectionDone;
extern bool g_hasNEON, g_hasPMULL, g_hasCRC32, g_hasAES, g_hasSHA1, g_hasSHA2;
void CRYPTOPP_API DetectArmFeatures();
//! \brief Determine if an ARM processor has Advanced SIMD available
//! \returns true if the hardware is capable of Advanced SIMD at runtime, false otherwise.
//! \details Advanced SIMD instructions are available under Aarch64 (ARM-64) and Aarch32 (ARM-32).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-mfpu=neon</tt> (32-bit) or <tt>-march=armv8-a</tt>
//! (64-bit). Also see ARM's <tt>__ARM_NEON</tt> preprocessor macro.
inline bool HasNEON()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasNEON;
}
//! \brief Determine if an ARM processor provides Polynomial Multiplication (long)
//! \returns true if the hardware is capable of polynomial multiplications at runtime, false otherwise.
//! \details The multiplication instructions are available under Aarch64 (ARM-64) and Aarch32 (ARM-32).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
//! <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
inline bool HasPMULL()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasPMULL;
}
//! \brief Determine if an ARM processor has CRC32 available
//! \returns true if the hardware is capable of CRC32 at runtime, false otherwise.
//! \details CRC32 instructions provide access to the processor's CRC32 and CRC32-C intructions.
//! They are provided by ARM C Language Extensions 2.0 (ACLE 2.0) and available under Aarch64
//! (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an AArch32 execution environment).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-march=armv8-a+crc</tt>; while Apple requires
//! <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRC32</tt> preprocessor macro.
inline bool HasCRC32()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasCRC32;
}
//! \brief Determine if an ARM processor has AES available
//! \returns true if the hardware is capable of AES at runtime, false otherwise.
//! \details AES is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
//! AArch32 execution environment).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
//! <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
inline bool HasAES()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasAES;
}
//! \brief Determine if an ARM processor has SHA1 available
//! \returns true if the hardware is capable of SHA1 at runtime, false otherwise.
//! \details SHA1 is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
//! AArch32 execution environment).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
//! <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
inline bool HasSHA1()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSHA1;
}
//! \brief Determine if an ARM processor has SHA2 available
//! \returns true if the hardware is capable of SHA2 at runtime, false otherwise.
//! \details SHA2 is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
//! AArch32 execution environment).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
//! <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
inline bool HasSHA2()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSHA2;
}
//! \brief Provides the cache line size at runtime
//! \returns true if the hardware is capable of CRC32 at runtime, false otherwise.
//! \details GetCacheLineSize() provides is an estimate using CRYPTOPP_L1_CACHE_LINE_SIZE.
//! The runtime instructions to query the processor are privileged.
inline int GetCacheLineSize()
{
return CRYPTOPP_L1_CACHE_LINE_SIZE;
}
#else
inline int GetCacheLineSize()
{
return CRYPTOPP_L1_CACHE_LINE_SIZE;
}
#endif // X86/X32/X64 and ARM
#endif
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define AS1(x) x*newline*
#define AS2(x, y) x, y*newline*
#define AS3(x, y, z) x, y, z*newline*
#define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
#define ASL(x) label##x:*newline*
#define ASJ(x, y, z) x label##y*newline*
#define ASC(x, y) x label##y*newline*
#define AS_HEX(y) 0##y##h
#elif defined(_MSC_VER) || defined(__BORLANDC__)
#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
#define AS1(x) __asm {x}
#define AS2(x, y) __asm {x, y}
#define AS3(x, y, z) __asm {x, y, z}
#define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)}
#define ASL(x) __asm {label##x:}
#define ASJ(x, y, z) __asm {x label##y}
#define ASC(x, y) __asm {x label##y}
#define CRYPTOPP_NAKED __declspec(naked)
#define AS_HEX(y) 0x##y
#else
#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
// define these in two steps to allow arguments to be expanded
#define GNU_AS1(x) #x ";" NEW_LINE
#define GNU_AS2(x, y) #x ", " #y ";" NEW_LINE
#define GNU_AS3(x, y, z) #x ", " #y ", " #z ";" NEW_LINE
#define GNU_ASL(x) "\n" #x ":" NEW_LINE
#define GNU_ASJ(x, y, z) #x " " #y #z ";" NEW_LINE
#define AS1(x) GNU_AS1(x)
#define AS2(x, y) GNU_AS2(x, y)
#define AS3(x, y, z) GNU_AS3(x, y, z)
#define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
#define ASL(x) GNU_ASL(x)
#define ASJ(x, y, z) GNU_ASJ(x, y, z)
#define ASC(x, y) #x " " #y ";"
#define CRYPTOPP_NAKED
#define AS_HEX(y) 0x##y
#endif
#define IF0(y)
#define IF1(y) y
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define ASM_MOD(x, y) ((x) MOD (y))
#define XMMWORD_PTR XMMWORD PTR
#else
// GNU assembler doesn't seem to have mod operator
#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
#define XMMWORD_PTR
#endif
#if CRYPTOPP_BOOL_X86
#define AS_REG_1 ecx
#define AS_REG_2 edx
#define AS_REG_3 esi
#define AS_REG_4 edi
#define AS_REG_5 eax
#define AS_REG_6 ebx
#define AS_REG_7 ebp
#define AS_REG_1d ecx
#define AS_REG_2d edx
#define AS_REG_3d esi
#define AS_REG_4d edi
#define AS_REG_5d eax
#define AS_REG_6d ebx
#define AS_REG_7d ebp
#define WORD_SZ 4
#define WORD_REG(x) e##x
#define WORD_PTR DWORD PTR
#define AS_PUSH_IF86(x) AS1(push e##x)
#define AS_POP_IF86(x) AS1(pop e##x)
#define AS_JCXZ jecxz
#elif CRYPTOPP_BOOL_X32
#define AS_REG_1 ecx
#define AS_REG_2 edx
#define AS_REG_3 r8d
#define AS_REG_4 r9d
#define AS_REG_5 eax
#define AS_REG_6 r10d
#define AS_REG_7 r11d
#define AS_REG_1d ecx
#define AS_REG_2d edx
#define AS_REG_3d r8d
#define AS_REG_4d r9d
#define AS_REG_5d eax
#define AS_REG_6d r10d
#define AS_REG_7d r11d
#define WORD_SZ 4
#define WORD_REG(x) e##x
#define WORD_PTR DWORD PTR
#define AS_PUSH_IF86(x) AS1(push r##x)
#define AS_POP_IF86(x) AS1(pop r##x)
#define AS_JCXZ jecxz
#elif CRYPTOPP_BOOL_X64
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define AS_REG_1 rcx
#define AS_REG_2 rdx
#define AS_REG_3 r8
#define AS_REG_4 r9
#define AS_REG_5 rax
#define AS_REG_6 r10
#define AS_REG_7 r11
#define AS_REG_1d ecx
#define AS_REG_2d edx
#define AS_REG_3d r8d
#define AS_REG_4d r9d
#define AS_REG_5d eax
#define AS_REG_6d r10d
#define AS_REG_7d r11d
#else
#define AS_REG_1 rdi
#define AS_REG_2 rsi
#define AS_REG_3 rdx
#define AS_REG_4 rcx
#define AS_REG_5 r8
#define AS_REG_6 r9
#define AS_REG_7 r10
#define AS_REG_1d edi
#define AS_REG_2d esi
#define AS_REG_3d edx
#define AS_REG_4d ecx
#define AS_REG_5d r8d
#define AS_REG_6d r9d
#define AS_REG_7d r10d
#endif
#define WORD_SZ 8
#define WORD_REG(x) r##x
#define WORD_PTR QWORD PTR
#define AS_PUSH_IF86(x)
#define AS_POP_IF86(x)
#define AS_JCXZ jrcxz
#endif
// helper macro for stream cipher output
#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
AS2( test inputPtr, inputPtr)\
ASC( jz, labelPrefix##3)\
AS2( test inputPtr, 15)\
ASC( jnz, labelPrefix##7)\
AS2( pxor xmm##x0, [inputPtr+p0*16])\
AS2( pxor xmm##x1, [inputPtr+p1*16])\
AS2( pxor xmm##x2, [inputPtr+p2*16])\
AS2( pxor xmm##x3, [inputPtr+p3*16])\
AS2( add inputPtr, increment*16)\
ASC( jmp, labelPrefix##3)\
ASL(labelPrefix##7)\
AS2( movdqu xmm##t, [inputPtr+p0*16])\
AS2( pxor xmm##x0, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p1*16])\
AS2( pxor xmm##x1, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p2*16])\
AS2( pxor xmm##x2, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p3*16])\
AS2( pxor xmm##x3, xmm##t)\
AS2( add inputPtr, increment*16)\
ASL(labelPrefix##3)\
AS2( test outputPtr, 15)\
ASC( jnz, labelPrefix##8)\
AS2( movdqa [outputPtr+p0*16], xmm##x0)\
AS2( movdqa [outputPtr+p1*16], xmm##x1)\
AS2( movdqa [outputPtr+p2*16], xmm##x2)\
AS2( movdqa [outputPtr+p3*16], xmm##x3)\
ASC( jmp, labelPrefix##9)\
ASL(labelPrefix##8)\
AS2( movdqu [outputPtr+p0*16], xmm##x0)\
AS2( movdqu [outputPtr+p1*16], xmm##x1)\
AS2( movdqu [outputPtr+p2*16], xmm##x2)\
AS2( movdqu [outputPtr+p3*16], xmm##x3)\
ASL(labelPrefix##9)\
AS2( add outputPtr, increment*16)
#endif // X86/X32/X64
NAMESPACE_END
#endif // CRYPTOPP_CPU_H

View File

@ -0,0 +1,75 @@
// crc.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile crc.h
//! \brief Classes for CRC-32 and CRC-32C checksum algorithm
#ifndef CRYPTOPP_CRC32_H
#define CRYPTOPP_CRC32_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
const word32 CRC32_NEGL = 0xffffffffL;
#ifdef IS_LITTLE_ENDIAN
#define CRC32_INDEX(c) (c & 0xff)
#define CRC32_SHIFTED(c) (c >> 8)
#else
#define CRC32_INDEX(c) (c >> 24)
#define CRC32_SHIFTED(c) (c << 8)
#endif
//! \brief CRC-32 Checksum Calculation
//! \details Uses CRC polynomial 0xEDB88320
class CRC32 : public HashTransformation
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
CRC32();
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "CRC32";}
std::string AlgorithmName() const {return StaticAlgorithmName();}
void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
protected:
void Reset() {m_crc = CRC32_NEGL;}
private:
static const word32 m_tab[256];
word32 m_crc;
};
//! \brief CRC-32C Checksum Calculation
//! \details Uses CRC polynomial 0x82F63B78
//! \since Crypto++ 5.6.4
class CRC32C : public HashTransformation
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
CRC32C();
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "CRC32C";}
std::string AlgorithmName() const {return StaticAlgorithmName();}
void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
protected:
void Reset() {m_crc = CRC32_NEGL;}
private:
static const word32 m_tab[256];
word32 m_crc;
};
NAMESPACE_END
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
// default.h - written and placed in the public domain by Wei Dai
//! \file default.h
//! \brief Classes for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC
#ifndef CRYPTOPP_DEFAULT_H
#define CRYPTOPP_DEFAULT_H
#include "sha.h"
#include "hmac.h"
#include "des.h"
#include "modes.h"
#include "filters.h"
#include "smartptr.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief Default block cipher for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC
typedef DES_EDE2 DefaultBlockCipher;
//! \brief Default hash for use with DefaultEncryptorWithMAC and DefaultDecryptorWithMAC
typedef SHA DefaultHashModule;
//! \brief Default HMAC for use withDefaultEncryptorWithMAC and DefaultDecryptorWithMAC
typedef HMAC<DefaultHashModule> DefaultMAC;
//! \class DefaultEncryptor
//! \brief Password-Based Encryptor using TripleDES
//! \details The class uses 2-key TripleDES (DES_EDE2) for encryption, which only
//! provides about 80-bits of security.
class DefaultEncryptor : public ProxyFilter
{
public:
//! \brief Construct a DefaultEncryptor
//! \param passphrase a C-String password
//! \param attachment a BufferedTransformation to attach to this object
DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment = NULL);
//! \brief Construct a DefaultEncryptor
//! \param passphrase a byte string password
//! \param passphraseLength the length of the byte string password
//! \param attachment a BufferedTransformation to attach to this object
DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
protected:
void FirstPut(const byte *);
void LastPut(const byte *inString, size_t length);
private:
SecByteBlock m_passphrase;
CBC_Mode<DefaultBlockCipher>::Encryption m_cipher;
} CRYPTOPP_DEPRECATED ("DefaultEncryptor will be changing in the near future because the algorithms are no longer secure");
//! \class DefaultDecryptor
//! \brief Password-Based Decryptor using TripleDES
//! \details The class uses 2-key TripleDES (DES_EDE2) for encryption, which only
//! provides about 80-bits of security.
class DefaultDecryptor : public ProxyFilter
{
public:
//! \brief Constructs a DefaultDecryptor
//! \param passphrase a C-String password
//! \param attachment a BufferedTransformation to attach to this object
//! \param throwException a flag specifiying whether an Exception should be thrown on error
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
//! \brief Constructs a DefaultDecryptor
//! \param passphrase a byte string password
//! \param passphraseLength the length of the byte string password
//! \param attachment a BufferedTransformation to attach to this object
//! \param throwException a flag specifiying whether an Exception should be thrown on error
DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
class Err : public Exception
{
public:
Err(const std::string &s)
: Exception(DATA_INTEGRITY_CHECK_FAILED, s) {}
};
class KeyBadErr : public Err {public: KeyBadErr() : Err("DefaultDecryptor: cannot decrypt message with this passphrase") {}};
enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
State CurrentState() const {return m_state;}
protected:
void FirstPut(const byte *inString);
void LastPut(const byte *inString, size_t length);
State m_state;
private:
void CheckKey(const byte *salt, const byte *keyCheck);
SecByteBlock m_passphrase;
CBC_Mode<DefaultBlockCipher>::Decryption m_cipher;
member_ptr<FilterWithBufferedInput> m_decryptor;
bool m_throwException;
} CRYPTOPP_DEPRECATED ("DefaultDecryptor will be changing in the near future because the algorithms are no longer secure");
//! \class DefaultEncryptorWithMAC
//! \brief Password-Based encryptor using TripleDES and HMAC/SHA-1
//! \details DefaultEncryptorWithMAC uses a non-standard mashup function called Mash() to derive key
//! bits from the password. The class also uses 2-key TripleDES (DES_EDE2) for encryption, which only
//! provides about 80-bits of security.
//! \details The purpose of the function Mash() is to take an arbitrary length input string and
//! *deterministically* produce an arbitrary length output string such that (1) it looks random,
//! (2) no information about the input is deducible from it, and (3) it contains as much entropy
//! as it can hold, or the amount of entropy in the input string, whichever is smaller.
class DefaultEncryptorWithMAC : public ProxyFilter
{
public:
//! \brief Constructs a DefaultEncryptorWithMAC
//! \param passphrase a C-String password
//! \param attachment a BufferedTransformation to attach to this object
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL);
//! \brief Constructs a DefaultEncryptorWithMAC
//! \param passphrase a byte string password
//! \param passphraseLength the length of the byte string password
//! \param attachment a BufferedTransformation to attach to this object
DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
protected:
void FirstPut(const byte *inString) {CRYPTOPP_UNUSED(inString);}
void LastPut(const byte *inString, size_t length);
private:
member_ptr<DefaultMAC> m_mac;
} CRYPTOPP_DEPRECATED ("DefaultEncryptorWithMAC will be changing in the near future because the algorithms are no longer secure");
//! \class DefaultDecryptorWithMAC
//! \brief Password-Based decryptor using TripleDES and HMAC/SHA-1
//! \details DefaultDecryptorWithMAC uses a non-standard mashup function called Mash() to derive key
//! bits from the password. The class also uses 2-key TripleDES (DES_EDE2) for encryption, which only
//! provides about 80-bits of security.
//! \details The purpose of the function Mash() is to take an arbitrary length input string and
//! *deterministically* produce an arbitrary length output string such that (1) it looks random,
//! (2) no information about the input is deducible from it, and (3) it contains as much entropy
//! as it can hold, or the amount of entropy in the input string, whichever is smaller.
class DefaultDecryptorWithMAC : public ProxyFilter
{
public:
//! \class MACBadErr
//! \brief Excpetion thrown when an incorrect MAC is encountered
class MACBadErr : public DefaultDecryptor::Err {public: MACBadErr() : DefaultDecryptor::Err("DefaultDecryptorWithMAC: MAC check failed") {}};
//! \brief Constructs a DefaultDecryptor
//! \param passphrase a C-String password
//! \param attachment a BufferedTransformation to attach to this object
//! \param throwException a flag specifiying whether an Exception should be thrown on error
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
//! \brief Constructs a DefaultDecryptor
//! \param passphrase a byte string password
//! \param passphraseLength the length of the byte string password
//! \param attachment a BufferedTransformation to attach to this object
//! \param throwException a flag specifiying whether an Exception should be thrown on error
DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
DefaultDecryptor::State CurrentState() const;
bool CheckLastMAC() const;
protected:
void FirstPut(const byte *inString) {CRYPTOPP_UNUSED(inString);}
void LastPut(const byte *inString, size_t length);
private:
member_ptr<DefaultMAC> m_mac;
HashVerifier *m_hashVerifier;
bool m_throwException;
} CRYPTOPP_DEPRECATED ("DefaultDecryptorWithMAC will be changing in the near future because the algorithms are no longer secure");
NAMESPACE_END
#endif

View File

@ -0,0 +1,167 @@
// des.h - written and placed in the public domain by Wei Dai
//! \file des.h
//! \brief Classes for DES, 2-key Triple-DES, 3-key Triple-DES and DESX
#ifndef CRYPTOPP_DES_H
#define CRYPTOPP_DES_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class RawDES
//! \brief DES block cipher base class
class CRYPTOPP_DLL RawDES
{
public:
void RawSetKey(CipherDir direction, const byte *userKey);
void RawProcessBlock(word32 &l, word32 &r) const;
protected:
static const word32 Spbox[8][64];
FixedSizeSecBlock<word32, 32> k;
};
//! \class DES_Info
//! \brief DES block cipher information
struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8>
{
// disable DES in DLL version by not exporting this function
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "DES";}
};
//! \class DES
//! \brief DES block cipher
//! \details The DES implementation in Crypto++ ignores the parity bits
//! (the least significant bits of each byte) in the key. However you can use CheckKeyParityBits()
//! and CorrectKeyParityBits() to check or correct the parity bits if you wish.
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#DES">DES</a>
class DES : public DES_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief DES block cipher default operation
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_Info>, public RawDES
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
public:
//! check DES key parity bits
static bool CheckKeyParityBits(const byte *key);
//! correct DES key parity bits
static void CorrectKeyParityBits(byte *key);
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
//! \class DES_EDE2_Info
//! \brief 2-key TripleDES block cipher information
struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
{
CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";}
};
//! \class DES_EDE2
//! \brief 2-key TripleDES block cipher
/// \sa <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE2</a>
class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief DES_EDE2 block cipher default operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE2_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
protected:
RawDES m_des1, m_des2;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
//! \class DES_EDE3_Info
//! \brief 3-key TripleDES block cipher information
struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
{
CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";}
};
//! \class DES_EDE3
//! \brief 3-key TripleDES block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE3</a>
class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief DES_EDE3 block cipher default operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE3_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
protected:
RawDES m_des1, m_des2, m_des3;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
//! \class DES_XEX3_Info
//! \brief DESX block cipher information
struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "DES-XEX3";}
};
//! \class DES_XEX3
//! \brief DESX block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#DESX">DES-XEX3</a>, AKA DESX
class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief DES_XEX3 block cipher default operation
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_XEX3_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
protected:
FixedSizeSecBlock<byte, BLOCKSIZE> m_x1, m_x3;
// VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock
// if we use DES::Encryption here directly without value_ptr.
value_ptr<DES::Encryption> m_des;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
typedef DES::Encryption DESEncryption;
typedef DES::Decryption DESDecryption;
typedef DES_EDE2::Encryption DES_EDE2_Encryption;
typedef DES_EDE2::Decryption DES_EDE2_Decryption;
typedef DES_EDE3::Encryption DES_EDE3_Encryption;
typedef DES_EDE3::Decryption DES_EDE3_Decryption;
typedef DES_XEX3::Encryption DES_XEX3_Encryption;
typedef DES_XEX3::Decryption DES_XEX3_Decryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,176 @@
// dh.h - written and placed in the public domain by Wei Dai
//! \file dh.h
//! \brief Classes for Diffie-Hellman key exchange
#ifndef CRYPTOPP_DH_H
#define CRYPTOPP_DH_H
#include "cryptlib.h"
#include "gfpcrypt.h"
#include "algebra.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class DH_Domain
//! \brief Diffie-Hellman domain
//! \tparam GROUP_PARAMETERS group parameters
//! \tparam COFACTOR_OPTION \ref CofactorMultiplicationOption "cofactor multiplication option"
//! \details A Diffie-Hellman domain is a set of parameters that must be shared
//! by two parties in a key agreement protocol, along with the algorithms
//! for generating key pairs and deriving agreed values.
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
class DH_Domain : public DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element>
{
typedef DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element> Base;
public:
typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element;
typedef DL_KeyAgreementAlgorithm_DH<Element, COFACTOR_OPTION> DH_Algorithm;
typedef DH_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
//! \brief Construct a Diffie-Hellman domain
DH_Domain() {}
//! \brief Construct a Diffie-Hellman domain
//! \param params group parameters and options
DH_Domain(const GroupParameters &params)
: m_groupParameters(params) {}
//! \brief Construct a Diffie-Hellman domain
//! \param bt BufferedTransformation with group parameters and options
DH_Domain(BufferedTransformation &bt)
{m_groupParameters.BERDecode(bt);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T2 template parameter used as a constructor parameter
//! \param v1 RandomNumberGenerator derived class
//! \param v2 second parameter
//! \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
template <class T2>
DH_Domain(RandomNumberGenerator &v1, const T2 &v2)
{m_groupParameters.Initialize(v1, v2);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \param v1 RandomNumberGenerator derived class
//! \param v2 second parameter
//! \param v3 third parameter
//! \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
template <class T2, class T3>
DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3)
{m_groupParameters.Initialize(v1, v2, v3);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \tparam T4 template parameter used as a constructor parameter
//! \param v1 RandomNumberGenerator derived class
//! \param v2 second parameter
//! \param v3 third parameter
//! \param v4 fourth parameter
//! \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
template <class T2, class T3, class T4>
DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2>
DH_Domain(const T1 &v1, const T2 &v2)
{m_groupParameters.Initialize(v1, v2);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \param v3 third parameter
//! \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3>
DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3)
{m_groupParameters.Initialize(v1, v2, v3);}
//! \brief Construct a Diffie-Hellman domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \tparam T4 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \param v3 third parameter
//! \param v4 fourth parameter
//! \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3, class T4>
DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
//! \brief Retrieves the group parameters for this domain
//! \return the group parameters for this domain as a const reference
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
//! \brief Retrieves the group parameters for this domain
//! \return the group parameters for this domain as a non-const reference
GroupParameters & AccessGroupParameters() {return m_groupParameters;}
//! \brief Generate a public key from a private key in this domain
//! \param rng RandomNumberGenerator derived class
//! \param privateKey byte buffer with the previously generated private key
//! \param publicKey byte buffer for the generated public key in this domain
//! \details If using a FIPS 140-2 validated library on Windows, then this class will perform
//! a self test to ensure the key pair is pairwise consistent. Non-FIPS and non-Windows
//! builds of the library do not provide FIPS validated cryptography, so the code should be
//! removed by the optimizer.
//! \pre <tt>COUNTOF(publicKey) == PublicKeyLength()</tt>
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
Base::GeneratePublicKey(rng, privateKey, publicKey);
if (FIPS_140_2_ComplianceEnabled())
{
SecByteBlock privateKey2(this->PrivateKeyLength());
this->GeneratePrivateKey(rng, privateKey2);
SecByteBlock publicKey2(this->PublicKeyLength());
Base::GeneratePublicKey(rng, privateKey2, publicKey2);
SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength());
bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2);
bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey);
if (!agreed1 || !agreed2 || agreedValue != agreedValue2)
throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed");
}
}
static std::string CRYPTOPP_API StaticAlgorithmName()
{return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();}
std::string AlgorithmName() const {return StaticAlgorithmName();}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DH_Domain() {}
#endif
private:
const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
{return Singleton<DH_Algorithm>().Ref();}
DL_GroupParameters<Element> & AccessAbstractGroupParameters()
{return m_groupParameters;}
GroupParameters m_groupParameters;
};
CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>;
//! <a href="http://www.weidai.com/scan-mirror/ka.html#DH">Diffie-Hellman</a> in GF(p) with key validation
typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> DH;
NAMESPACE_END
#endif

View File

@ -0,0 +1,65 @@
// dh2.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile dh2.h
//! \brief Classes for Diffie-Hellman authenticated key exchange
#ifndef CRYPTOPP_DH2_H
#define CRYPTOPP_DH2_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
/// <a href="http://www.weidai.com/scan-mirror/ka.html#DH2">Unified Diffie-Hellman</a>
class DH2 : public AuthenticatedKeyAgreementDomain
{
public:
DH2(SimpleKeyAgreementDomain &domain)
: d1(domain), d2(domain) {}
DH2(SimpleKeyAgreementDomain &staticDomain, SimpleKeyAgreementDomain &ephemeralDomain)
: d1(staticDomain), d2(ephemeralDomain) {}
CryptoParameters & AccessCryptoParameters() {return d1.AccessCryptoParameters();}
unsigned int AgreedValueLength() const
{return d1.AgreedValueLength() + d2.AgreedValueLength();}
unsigned int StaticPrivateKeyLength() const
{return d1.PrivateKeyLength();}
unsigned int StaticPublicKeyLength() const
{return d1.PublicKeyLength();}
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{d1.GeneratePrivateKey(rng, privateKey);}
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{d1.GeneratePublicKey(rng, privateKey, publicKey);}
void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{d1.GenerateKeyPair(rng, privateKey, publicKey);}
unsigned int EphemeralPrivateKeyLength() const
{return d2.PrivateKeyLength();}
unsigned int EphemeralPublicKeyLength() const
{return d2.PublicKeyLength();}
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{d2.GeneratePrivateKey(rng, privateKey);}
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{d2.GeneratePublicKey(rng, privateKey, publicKey);}
void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{d2.GenerateKeyPair(rng, privateKey, publicKey);}
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DH2() {}
#endif
protected:
SimpleKeyAgreementDomain &d1, &d2;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,77 @@
// dll.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile dll.h
//! \brief Functions and definitions required for building the FIPS-140 DLL on Windows
#ifndef CRYPTOPP_DLL_H
#define CRYPTOPP_DLL_H
#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL)
#ifdef CRYPTOPP_CONFIG_H
#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files.
#endif
#define CRYPTOPP_IMPORTS
#endif
#include "aes.h"
#include "cbcmac.h"
#include "ccm.h"
#include "cmac.h"
#include "channels.h"
#include "des.h"
#include "dh.h"
#include "dsa.h"
#include "ec2n.h"
#include "eccrypto.h"
#include "ecp.h"
#include "files.h"
#include "fips140.h"
#include "gcm.h"
#include "hex.h"
#include "hmac.h"
#include "modes.h"
#include "mqueue.h"
#include "nbtheory.h"
#include "osrng.h"
#include "pkcspad.h"
#include "pssr.h"
#include "randpool.h"
#include "rsa.h"
#include "rw.h"
#include "sha.h"
#include "skipjack.h"
#include "trdlocal.h"
#ifdef CRYPTOPP_IMPORTS
#ifdef _DLL
// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain()
#ifdef CRYPTOPP_DEBUG
# pragma comment(lib, "msvcrtd")
# pragma comment(lib, "cryptopp")
#else
# pragma comment(lib, "msvcrt")
# pragma comment(lib, "cryptopp")
#endif
#endif
#endif // #ifdef CRYPTOPP_IMPORTS
#include <new> // for new_handler
NAMESPACE_BEGIN(CryptoPP)
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
#endif
typedef void * (CRYPTOPP_API * PNew)(size_t);
typedef void (CRYPTOPP_API * PDelete)(void *);
typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &);
typedef new_handler (CRYPTOPP_API * PSetNewHandler)(new_handler);
typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler);
NAMESPACE_END
#endif

View File

@ -0,0 +1,99 @@
// dmac.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile dmac.h
//! \brief Classes for DMAC message authentication code
#ifndef CRYPTOPP_DMAC_H
#define CRYPTOPP_DMAC_H
#include "cbcmac.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
template <class T>
class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs<T>, public MessageAuthenticationCode
{
public:
static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";}
CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
DMAC_Base() : m_subkeylength(0), m_counter(0) {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
private:
byte *GenerateSubKeys(const byte *key, size_t keylength);
size_t m_subkeylength;
SecByteBlock m_subkeys;
CBC_MAC<T> m_mac1;
typename T::Encryption m_f2;
unsigned int m_counter;
};
//! DMAC
/*! Based on "CBC MAC for Real-Time Data Sources" by Erez Petrank
and Charles Rackoff. T should be a class derived from BlockCipherDocumentation.
*/
template <class T>
class DMAC : public MessageAuthenticationCodeFinal<DMAC_Base<T> >
{
public:
DMAC() {}
DMAC(const byte *key, size_t length=DMAC_Base<T>::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
};
template <class T>
void DMAC_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
m_subkeylength = T::StaticGetValidKeyLength(T::BLOCKSIZE);
m_subkeys.resize(2*UnsignedMin((unsigned int)T::BLOCKSIZE, m_subkeylength));
m_mac1.SetKey(GenerateSubKeys(key, length), m_subkeylength, params);
m_f2.SetKey(m_subkeys+m_subkeys.size()/2, m_subkeylength, params);
m_counter = 0;
m_subkeys.resize(0);
}
template <class T>
void DMAC_Base<T>::Update(const byte *input, size_t length)
{
m_mac1.Update(input, length);
m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE);
}
template <class T>
void DMAC_Base<T>::TruncatedFinal(byte *mac, size_t size)
{
ThrowIfInvalidTruncatedSize(size);
byte pad[T::BLOCKSIZE];
byte padByte = byte(T::BLOCKSIZE-m_counter);
memset(pad, padByte, padByte);
m_mac1.Update(pad, padByte);
m_mac1.TruncatedFinal(mac, size);
m_f2.ProcessBlock(mac);
m_counter = 0; // reset for next message
}
template <class T>
byte *DMAC_Base<T>::GenerateSubKeys(const byte *key, size_t keylength)
{
typename T::Encryption cipher(key, keylength);
memset(m_subkeys, 0, m_subkeys.size());
cipher.ProcessBlock(m_subkeys);
m_subkeys[m_subkeys.size()/2 + T::BLOCKSIZE - 1] = 1;
cipher.ProcessBlock(m_subkeys+m_subkeys.size()/2);
return m_subkeys;
}
NAMESPACE_END
#endif

View File

@ -0,0 +1,41 @@
// dsa.h - written and placed in the public domain by Wei Dai
//! \file dsa.h
//! \brief Classes for the DSA signature algorithm
#ifndef CRYPTOPP_DSA_H
#define CRYPTOPP_DSA_H
#include "cryptlib.h"
#include "gfpcrypt.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief DSA Signature Format
//! \details The DSA signature format used by Crypto++ is as defined by IEEE P1363.
//! Java nad .Net use the DER format, and OpenPGP uses the OpenPGP format.
enum DSASignatureFormat {
//! \brief Crypto++ native signature encoding format
DSA_P1363,
//! \brief signature encoding format used by Java and .Net
DSA_DER,
//! \brief OpenPGP signature encoding format
DSA_OPENPGP
};
//! \brief Converts between signature encoding formats
//! \param buffer byte buffer for the converted signature encoding
//! \param bufferSize the length of the converted signature encoding buffer
//! \param toFormat the source signature format
//! \param signature byte buffer for the existing signature encoding
//! \param signatureLen the length of the existing signature encoding buffer
//! \param fromFormat the source signature format
//! \details This function converts between these formats, and returns length
//! of signature in the target format. If <tt>toFormat == DSA_P1363</tt>, then
//! <tt>bufferSize</tt> must equal <tt>publicKey.SignatureLength()</tt>
size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat,
const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat);
NAMESPACE_END
#endif

View File

@ -0,0 +1,109 @@
// eax.h - written and placed in the public domain by Wei Dai
//! \file eax.h
//! \brief EAX block cipher mode of operation
#ifndef CRYPTOPP_EAX_H
#define CRYPTOPP_EAX_H
#include "authenc.h"
#include "modes.h"
#include "cmac.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class EAX_Base
//! \brief EAX block cipher base implementation
//! \details Base implementation of the AuthenticatedSymmetricCipher interface
//! \since Crypto++ 5.6.0
class CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase
{
public:
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return GetMAC().GetCipher().AlgorithmName() + std::string("/EAX");}
size_t MinKeyLength() const
{return GetMAC().MinKeyLength();}
size_t MaxKeyLength() const
{return GetMAC().MaxKeyLength();}
size_t DefaultKeyLength() const
{return GetMAC().DefaultKeyLength();}
size_t GetValidKeyLength(size_t n) const
{return GetMAC().GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const
{return GetMAC().IsValidKeyLength(n);}
unsigned int OptimalDataAlignment() const
{return GetMAC().OptimalDataAlignment();}
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return GetMAC().TagSize();}
unsigned int MinIVLength() const
{return 0;}
unsigned int MaxIVLength() const
{return UINT_MAX;}
unsigned int DigestSize() const
{return GetMAC().TagSize();}
lword MaxHeaderLength() const
{return LWORD_MAX;}
lword MaxMessageLength() const
{return LWORD_MAX;}
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const
{return false;}
unsigned int AuthenticationBlockSize() const
{return 1;}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
const CMAC_Base & GetMAC() const {return const_cast<EAX_Base *>(this)->AccessMAC();}
virtual CMAC_Base & AccessMAC() =0;
CTR_Mode_ExternalCipher::Encryption m_ctr;
};
//! \class EAX_Final
//! \brief EAX block cipher final implementation
//! \tparam T_BlockCipher block cipher
//! \tparam T_IsEncryption direction in which to operate the cipher
//! \since Crypto++ 5.6.0
template <class T_BlockCipher, bool T_IsEncryption>
class EAX_Final : public EAX_Base
{
public:
static std::string StaticAlgorithmName()
{return T_BlockCipher::StaticAlgorithmName() + std::string("/EAX");}
bool IsForwardTransformation() const
{return T_IsEncryption;}
private:
CMAC_Base & AccessMAC() {return m_cmac;}
CMAC<T_BlockCipher> m_cmac;
};
#ifdef EAX // EAX is defined to 11 on GCC 3.4.3, OpenSolaris 8.11
#undef EAX
#endif
//! \class EAX
//! \brief EAX block cipher mode of operation
//! \tparam T_BlockCipher block cipher
//! \details \p EAX provides the \p Encryption and \p Decryption typedef. See EAX_Base
//! and EAX_Final for the AuthenticatedSymmetricCipher implementation.
//! \sa <a href="http://www.cryptolounge.org/wiki/EAX">EAX</a> at the Crypto Lounge
//! \since Crypto++ 5.6.0
template <class T_BlockCipher>
struct EAX : public AuthenticatedSymmetricCipherDocumentation
{
typedef EAX_Final<T_BlockCipher, true> Encryption;
typedef EAX_Final<T_BlockCipher, false> Decryption;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,135 @@
// ec2n.h - written and placed in the public domain by Wei Dai
//! \file
//! \headerfile ec2n.h
//! \brief Classes for Elliptic Curves over binary fields
#ifndef CRYPTOPP_EC2N_H
#define CRYPTOPP_EC2N_H
#include "cryptlib.h"
#include "gf2n.h"
#include "integer.h"
#include "algebra.h"
#include "eprecomp.h"
#include "smartptr.h"
#include "pubkey.h"
NAMESPACE_BEGIN(CryptoPP)
//! Elliptic Curve Point
struct CRYPTOPP_DLL EC2NPoint
{
EC2NPoint() : identity(true) {}
EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y)
: identity(false), x(x), y(y) {}
bool operator==(const EC2NPoint &t) const
{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
bool operator< (const EC2NPoint &t) const
{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~EC2NPoint() {}
#endif
bool identity;
PolynomialMod2 x, y;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<EC2NPoint>;
//! Elliptic Curve over GF(2^n)
class CRYPTOPP_DLL EC2N : public AbstractGroup<EC2NPoint>
{
public:
typedef GF2NP Field;
typedef Field::Element FieldElement;
typedef EC2NPoint Point;
EC2N() {}
EC2N(const Field &field, const Field::Element &a, const Field::Element &b)
: m_field(field), m_a(a), m_b(b) {}
// construct from BER encoded parameters
// this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
EC2N(BufferedTransformation &bt);
// encode the fields fieldID and curve of the sequence ECParameters
void DEREncode(BufferedTransformation &bt) const;
bool Equal(const Point &P, const Point &Q) const;
const Point& Identity() const;
const Point& Inverse(const Point &P) const;
bool InversionIsFast() const {return true;}
const Point& Add(const Point &P, const Point &Q) const;
const Point& Double(const Point &P) const;
Point Multiply(const Integer &k, const Point &P) const
{return ScalarMultiply(P, k);}
Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
{return CascadeScalarMultiply(P, k1, Q, k2);}
bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
bool VerifyPoint(const Point &P) const;
unsigned int EncodedPointSize(bool compressed = false) const
{return 1 + (compressed?1:2)*m_field->MaxElementByteLength();}
// returns false if point is compressed and not valid (doesn't check if uncompressed)
bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
Point BERDecodePoint(BufferedTransformation &bt) const;
void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());}
const Field & GetField() const {return *m_field;}
const FieldElement & GetA() const {return m_a;}
const FieldElement & GetB() const {return m_b;}
bool operator==(const EC2N &rhs) const
{return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~EC2N() {}
#endif
private:
clonable_ptr<Field> m_field;
FieldElement m_a, m_b;
mutable Point m_R;
};
CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<EC2N::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<EC2N::Point>;
template <class T> class EcPrecomputation;
//! EC2N precomputation
template<> class EcPrecomputation<EC2N> : public DL_GroupPrecomputation<EC2N::Point>
{
public:
typedef EC2N EllipticCurve;
// DL_GroupPrecomputation
const AbstractGroup<Element> & GetGroup() const {return m_ec;}
Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);}
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);}
// non-inherited
void SetCurve(const EC2N &ec) {m_ec = ec;}
const EC2N & GetCurve() const {return m_ec;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~EcPrecomputation() {}
#endif
private:
EC2N m_ec;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,376 @@
// eccrypto.h - written and placed in the public domain by Wei Dai
//! \file eccrypto.h
//! \brief Classes and functions for Elliptic Curves over prime and binary fields
#ifndef CRYPTOPP_ECCRYPTO_H
#define CRYPTOPP_ECCRYPTO_H
#include "config.h"
#include "cryptlib.h"
#include "pubkey.h"
#include "integer.h"
#include "asn.h"
#include "hmac.h"
#include "sha.h"
#include "gfpcrypt.h"
#include "dh.h"
#include "mqv.h"
#include "hmqv.h"
#include "fhmqv.h"
#include "ecp.h"
#include "ec2n.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief Elliptic Curve Parameters
//! \tparam EC elliptic curve field
//! \details This class corresponds to the ASN.1 sequence of the same name
//! in ANSI X9.62 and SEC 1. EC is currently defined for ECP and EC2N.
template <class EC>
class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> >
{
typedef DL_GroupParameters_EC<EC> ThisClass;
public:
typedef EC EllipticCurve;
typedef typename EllipticCurve::Point Point;
typedef Point Element;
typedef IncompatibleCofactorMultiplication DefaultCofactorOption;
DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {}
DL_GroupParameters_EC(const OID &oid)
: m_compress(false), m_encodeAsOID(false) {Initialize(oid);}
DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
: m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);}
DL_GroupParameters_EC(BufferedTransformation &bt)
: m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}
void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
{
this->m_groupPrecomputation.SetCurve(ec);
this->SetSubgroupGenerator(G);
m_n = n;
m_k = k;
}
void Initialize(const OID &oid);
// NameValuePairs
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
// GeneratibleCryptoMaterial interface
//! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values
/*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
// DL_GroupParameters
const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
const Integer & GetSubgroupOrder() const {return m_n;}
Integer GetCofactor() const;
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const;
bool FastSubgroupCheckAvailable() const {return false;}
void EncodeElement(bool reversible, const Element &element, byte *encoded) const
{
if (reversible)
GetCurve().EncodePoint(encoded, element, m_compress);
else
element.x.Encode(encoded, GetEncodedElementSize(false));
}
virtual unsigned int GetEncodedElementSize(bool reversible) const
{
if (reversible)
return GetCurve().EncodedPointSize(m_compress);
else
return GetCurve().GetField().MaxElementByteLength();
}
Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
{
Point result;
if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true)))
throw DL_BadElement();
if (checkForGroupMembership && !ValidateElement(1, result, NULL))
throw DL_BadElement();
return result;
}
Integer ConvertElementToInteger(const Element &element) const;
Integer GetMaxExponent() const {return GetSubgroupOrder()-1;}
bool IsIdentity(const Element &element) const {return element.identity;}
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";}
// ASN1Key
OID GetAlgorithmID() const;
// used by MQV
Element MultiplyElements(const Element &a, const Element &b) const;
Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
// non-inherited
// enumerate OIDs for recommended parameters, use OID() to get first one
static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid);
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
void SetPointCompression(bool compress) {m_compress = compress;}
bool GetPointCompression() const {return m_compress;}
void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
bool GetEncodeAsOID() const {return m_encodeAsOID;}
const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();}
bool operator==(const ThisClass &rhs) const
{return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);}
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
const Point& GetBasePoint() const {return this->GetSubgroupGenerator();}
const Integer& GetBasePointOrder() const {return this->GetSubgroupOrder();}
void LoadRecommendedParameters(const OID &oid) {Initialize(oid);}
#endif
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_EC() {}
#endif
protected:
unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();}
unsigned int ExponentLength() const {return m_n.ByteCount();}
OID m_oid; // set if parameters loaded from a recommended curve
Integer m_n; // order of base point
mutable Integer m_k; // cofactor
mutable bool m_compress, m_encodeAsOID; // presentation details
};
//! EC public key
template <class EC>
class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> >
{
public:
typedef typename EC::Point Element;
void Initialize(const DL_GroupParameters_EC<EC> &params, const Element &Q)
{this->AccessGroupParameters() = params; this->SetPublicElement(Q);}
void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);}
// X509PublicKey
void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
void DEREncodePublicKey(BufferedTransformation &bt) const;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PublicKey_EC() {}
#endif
};
//! EC private key
template <class EC>
class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> >
{
public:
typedef typename EC::Point Element;
void Initialize(const DL_GroupParameters_EC<EC> &params, const Integer &x)
{this->AccessGroupParameters() = params; this->SetPrivateExponent(x);}
void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x)
{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);}
void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
{this->GenerateRandom(rng, params);}
void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
{this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
// PKCS8PrivateKey
void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
void DEREncodePrivateKey(BufferedTransformation &bt) const;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PrivateKey_EC() {}
#endif
};
//! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a>
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
struct ECDH
{
typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECDH() {}
#endif
};
/// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a>
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
struct ECMQV
{
typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECMQV() {}
#endif
};
//! \brief Hashed Menezes-Qu-Vanstone in ECP or EC2N
//! \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
//! Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
struct ECHMQV
{
typedef HMQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION, HASH> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECHMQV() {}
#endif
};
typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA1 >::Domain ECHMQV160;
typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECHMQV256;
typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECHMQV384;
typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECHMQV512;
//! \brief Fully Hashed Menezes-Qu-Vanstone in ECP or EC2N
//! \details This implementation follows Augustin P. Sarr and Philippe ElbazVincent, and JeanClaude Bajard's
//! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
struct ECFHMQV
{
typedef FHMQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION, HASH> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECFHMQV() {}
#endif
};
typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA1 >::Domain ECFHMQV160;
typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECFHMQV256;
typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECFHMQV384;
typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECFHMQV512;
//! EC keys
template <class EC>
struct DL_Keys_EC
{
typedef DL_PublicKey_EC<EC> PublicKey;
typedef DL_PrivateKey_EC<EC> PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Keys_EC() {}
#endif
};
template <class EC, class H>
struct ECDSA;
//! ECDSA keys
template <class EC>
struct DL_Keys_ECDSA
{
typedef DL_PublicKey_EC<EC> PublicKey;
typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC>, ECDSA<EC, SHA256> > PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Keys_ECDSA() {}
#endif
};
//! ECDSA algorithm
template <class EC>
class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point>
{
public:
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Algorithm_ECDSA() {}
#endif
};
//! ECNR algorithm
template <class EC>
class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point>
{
public:
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Algorithm_ECNR() {}
#endif
};
//! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>
template <class EC, class H>
struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H>
{
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECDSA() {}
#endif
};
//! ECNR
template <class EC, class H = SHA>
struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H>
{
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECNR() {}
#endif
};
//! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a>
/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2.
The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best
efficiency and security. */
template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false>
struct ECIES
: public DL_ES<
DL_Keys_EC<EC>,
DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >,
DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
ECIES<EC> >
{
static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECIES() {}
#endif
#if (CRYPTOPP_GCC_VERSION >= 40500) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20800)
} __attribute__((deprecated ("ECIES will be changing in the near future due to (1) an implementation bug and (2) an interop issue")));
#elif (CRYPTOPP_GCC_VERSION)
} __attribute__((deprecated));
#else
};
#endif
NAMESPACE_END
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
#include "eccrypto.cpp"
#endif
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >;
NAMESPACE_END
#endif

View File

@ -0,0 +1,146 @@
// ecp.h - written and placed in the public domain by Wei Dai
//! \file ecp.h
//! \brief Classes for Elliptic Curves over prime fields
#ifndef CRYPTOPP_ECP_H
#define CRYPTOPP_ECP_H
#include "cryptlib.h"
#include "integer.h"
#include "algebra.h"
#include "modarith.h"
#include "eprecomp.h"
#include "smartptr.h"
#include "pubkey.h"
NAMESPACE_BEGIN(CryptoPP)
//! Elliptical Curve Point
struct CRYPTOPP_DLL ECPPoint
{
ECPPoint() : identity(true) {}
ECPPoint(const Integer &x, const Integer &y)
: identity(false), x(x), y(y) {}
bool operator==(const ECPPoint &t) const
{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
bool operator< (const ECPPoint &t) const
{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECPPoint() {}
#endif
bool identity;
Integer x, y;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<ECPPoint>;
//! Elliptic Curve over GF(p), where p is prime
class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
{
public:
typedef ModularArithmetic Field;
typedef Integer FieldElement;
typedef ECPPoint Point;
ECP() {}
ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false);
ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b)
: m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {}
// construct from BER encoded parameters
// this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
ECP(BufferedTransformation &bt);
// encode the fields fieldID and curve of the sequence ECParameters
void DEREncode(BufferedTransformation &bt) const;
bool Equal(const Point &P, const Point &Q) const;
const Point& Identity() const;
const Point& Inverse(const Point &P) const;
bool InversionIsFast() const {return true;}
const Point& Add(const Point &P, const Point &Q) const;
const Point& Double(const Point &P) const;
Point ScalarMultiply(const Point &P, const Integer &k) const;
Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const;
void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const;
Point Multiply(const Integer &k, const Point &P) const
{return ScalarMultiply(P, k);}
Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
{return CascadeScalarMultiply(P, k1, Q, k2);}
bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
bool VerifyPoint(const Point &P) const;
unsigned int EncodedPointSize(bool compressed = false) const
{return 1 + (compressed?1:2)*GetField().MaxElementByteLength();}
// returns false if point is compressed and not valid (doesn't check if uncompressed)
bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
Point BERDecodePoint(BufferedTransformation &bt) const;
void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
Integer FieldSize() const {return GetField().GetModulus();}
const Field & GetField() const {return *m_fieldPtr;}
const FieldElement & GetA() const {return m_a;}
const FieldElement & GetB() const {return m_b;}
bool operator==(const ECP &rhs) const
{return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ECP() {}
#endif
private:
clonable_ptr<Field> m_fieldPtr;
FieldElement m_a, m_b;
mutable Point m_R;
};
CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<ECP::Point>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<ECP::Point>;
template <class T> class EcPrecomputation;
//! ECP precomputation
template<> class EcPrecomputation<ECP> : public DL_GroupPrecomputation<ECP::Point>
{
public:
typedef ECP EllipticCurve;
// DL_GroupPrecomputation
bool NeedConversions() const {return true;}
Element ConvertIn(const Element &P) const
{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));};
Element ConvertOut(const Element &P) const
{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));}
const AbstractGroup<Element> & GetGroup() const {return *m_ec;}
Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);}
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);}
// non-inherited
void SetCurve(const ECP &ec)
{
m_ec.reset(new ECP(ec, true));
m_ecOriginal = ec;
}
const ECP & GetCurve() const {return *m_ecOriginal;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~EcPrecomputation() {}
#endif
private:
value_ptr<ECP> m_ec, m_ecOriginal;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,144 @@
// elgamal.h - written and placed in the public domain by Wei Dai
//! \file elgamal.h
//! \brief Classes and functions for ElGamal key agreement and encryption schemes
#ifndef CRYPTOPP_ELGAMAL_H
#define CRYPTOPP_ELGAMAL_H
#include "cryptlib.h"
#include "modexppc.h"
#include "integer.h"
#include "gfpcrypt.h"
#include "pubkey.h"
#include "dsa.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
public DL_KeyDerivationAlgorithm<Integer>,
public DL_SymmetricEncryptionAlgorithm
{
public:
void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const
{
CRYPTOPP_UNUSED(groupParams), CRYPTOPP_UNUSED(ephemeralPublicKey), CRYPTOPP_UNUSED(derivationParams);
agreedElement.Encode(derivedKey, derivedLength);
}
size_t GetSymmetricKeyLength(size_t plainTextLength) const
{
CRYPTOPP_UNUSED(plainTextLength);
return GetGroupParameters().GetModulus().ByteCount();
}
size_t GetSymmetricCiphertextLength(size_t plainTextLength) const
{
unsigned int len = GetGroupParameters().GetModulus().ByteCount();
if (plainTextLength <= GetMaxSymmetricPlaintextLength(len))
return len;
else
return 0;
}
size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const
{
unsigned int len = GetGroupParameters().GetModulus().ByteCount();
if (cipherTextLength == len)
return STDMIN(255U, len-3);
else
return 0;
}
void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs &parameters) const
{
CRYPTOPP_UNUSED(parameters);
const Integer &p = GetGroupParameters().GetModulus();
unsigned int modulusLen = p.ByteCount();
SecByteBlock block(modulusLen-1);
rng.GenerateBlock(block, modulusLen-2-plainTextLength);
memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
block[modulusLen-2] = (byte)plainTextLength;
a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen);
}
DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs &parameters) const
{
CRYPTOPP_UNUSED(parameters);
const Integer &p = GetGroupParameters().GetModulus();
unsigned int modulusLen = p.ByteCount();
if (cipherTextLength != modulusLen)
return DecodingResult();
Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p);
m.Encode(plainText, 1);
unsigned int plainTextLength = plainText[0];
if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen))
return DecodingResult();
m >>= 8;
m.Encode(plainText, plainTextLength);
return DecodingResult(plainTextLength);
}
virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ElGamalBase() {}
#endif
};
template <class BASE, class SCHEME_OPTIONS, class KEY>
class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase
{
public:
size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());}
size_t FixedCiphertextLength() const {return this->CiphertextLength(0);}
const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();}
DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const
{return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ElGamalObjectImpl() {}
#endif
protected:
const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;}
const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;}
const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;}
};
struct ElGamalKeys
{
typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters;
typedef DL_PrivateKey_GFP_OldFormat<DL_CryptoKeys_GFP::PrivateKey> PrivateKey;
typedef DL_PublicKey_GFP_OldFormat<DL_CryptoKeys_GFP::PublicKey> PublicKey;
};
//! \class ElGamal
//! \brief ElGamal encryption scheme with non-standard padding
struct ElGamal
{
typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions;
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";}
typedef SchemeOptions::GroupParameters GroupParameters;
//! implements PK_Encryptor interface
typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor;
//! implements PK_Decryptor interface
typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor;
};
typedef ElGamal::Encryptor ElGamalEncryptor;
typedef ElGamal::Decryptor ElGamalDecryptor;
NAMESPACE_END
#endif

View File

@ -0,0 +1,88 @@
// emsa2.h - written and placed in the public domain by Wei Dai
//! \file emsa2.h
//! \brief Classes and functions for various padding schemes used in public key algorithms
#ifndef CRYPTOPP_EMSA2_H
#define CRYPTOPP_EMSA2_H
#include "cryptlib.h"
#include "pubkey.h"
#include "misc.h"
#ifdef CRYPTOPP_IS_DLL
# include "sha.h"
#endif
NAMESPACE_BEGIN(CryptoPP)
template <class H> class EMSA2HashId
{
public:
static const byte id;
};
template <class BASE>
class EMSA2HashIdLookup : public BASE
{
public:
struct HashIdentifierLookup
{
template <class H> struct HashIdentifierLookup2
{
static HashIdentifier Lookup()
{
return HashIdentifier(&EMSA2HashId<H>::id, 1);
}
};
};
};
// EMSA2HashId can be instantiated with the following classes.
class SHA1;
class SHA224;
class SHA256;
class SHA384;
class SHA512;
class RIPEMD128;
class RIPEMD160;
class Whirlpool;
// end of list
#ifdef CRYPTOPP_IS_DLL
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA1>;
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA224>;
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA256>;
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA384>;
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA512>;
#endif
//! _
class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup<PK_DeterministicSignatureMessageEncodingMethod>
{
public:
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";}
size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
{CRYPTOPP_UNUSED(hashIdentifierLength); return 8*digestLength + 31;}
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
const byte *recoverableMessage, size_t recoverableMessageLength,
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
byte *representative, size_t representativeBitLength) const;
};
//! EMSA2, for use with RWSS and RSA_ISO
/*! Only the following hash functions are supported by this signature standard:
\dontinclude emsa2.h
\skip EMSA2HashId can be instantiated
\until end of list
*/
struct P1363_EMSA2 : public SignatureStandard
{
typedef EMSA2Pad SignatureMessageEncodingMethod;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,93 @@
// eprecomp.h - written and placed in the public domain by Wei Dai
//! \file eprecomp.h
//! \brief Classes for precomputation in a group
#ifndef CRYPTOPP_EPRECOMP_H
#define CRYPTOPP_EPRECOMP_H
#include "cryptlib.h"
#include "integer.h"
#include "algebra.h"
#include "stdcpp.h"
NAMESPACE_BEGIN(CryptoPP)
template <class T>
class DL_GroupPrecomputation
{
public:
typedef T Element;
virtual bool NeedConversions() const {return false;}
virtual Element ConvertIn(const Element &v) const {return v;}
virtual Element ConvertOut(const Element &v) const {return v;}
virtual const AbstractGroup<Element> & GetGroup() const =0;
virtual Element BERDecodeElement(BufferedTransformation &bt) const =0;
virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupPrecomputation() {}
#endif
};
template <class T>
class DL_FixedBasePrecomputation
{
public:
typedef T Element;
virtual bool IsInitialized() const =0;
virtual void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base) =0;
virtual const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const =0;
virtual void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) =0;
virtual void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) =0;
virtual void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const =0;
virtual Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const =0;
virtual Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const =0;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_FixedBasePrecomputation() {}
#endif
};
template <class T>
class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation<T>
{
public:
typedef T Element;
DL_FixedBasePrecomputationImpl() : m_windowSize(0) {}
// DL_FixedBasePrecomputation
bool IsInitialized() const
{return !m_bases.empty();}
void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base);
const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const
{return group.NeedConversions() ? m_base : m_bases[0];}
void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage);
void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation);
void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const;
Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_FixedBasePrecomputationImpl() {}
#endif
private:
void PrepareCascade(const DL_GroupPrecomputation<Element> &group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const;
Element m_base;
unsigned int m_windowSize;
Integer m_exponentBase; // what base to represent the exponent in
std::vector<Element> m_bases; // precalculated bases
};
NAMESPACE_END
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
#include "eprecomp.cpp"
#endif
#endif

View File

@ -0,0 +1,133 @@
#ifndef CRYPTOPP_ESIGN_H
#define CRYPTOPP_ESIGN_H
/** \file
This file contains classes that implement the
ESIGN signature schemes as defined in IEEE P1363a.
*/
#include "cryptlib.h"
#include "pubkey.h"
#include "integer.h"
#include "asn.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
class ESIGNFunction : public TrapdoorFunction, public ASN1CryptoMaterial<PublicKey>
{
typedef ESIGNFunction ThisClass;
public:
void Initialize(const Integer &n, const Integer &e)
{m_n = n; m_e = e;}
// PublicKey
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
// CryptoMaterial
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
// TrapdoorFunction
Integer ApplyFunction(const Integer &x) const;
Integer PreimageBound() const {return m_n;}
Integer ImageBound() const {return Integer::Power2(GetK());}
// non-derived
const Integer & GetModulus() const {return m_n;}
const Integer & GetPublicExponent() const {return m_e;}
void SetModulus(const Integer &n) {m_n = n;}
void SetPublicExponent(const Integer &e) {m_e = e;}
protected:
// Covertiy finding on overflow. The library allows small values for research purposes.
unsigned int GetK() const {return SaturatingSubtract(m_n.BitCount()/3, 1U);}
Integer m_n, m_e;
};
//! _
class InvertibleESIGNFunction : public ESIGNFunction, public RandomizedTrapdoorFunctionInverse, public PrivateKey
{
typedef InvertibleESIGNFunction ThisClass;
public:
void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q)
{m_n = n; m_e = e; m_p = p; m_q = q;}
// generate a random private key
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
{GenerateRandomWithKeySize(rng, modulusBits);}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const;
// GeneratibleCryptoMaterial
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
/*! parameters: (ModulusSize) */
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
const Integer& GetPrime1() const {return m_p;}
const Integer& GetPrime2() const {return m_q;}
void SetPrime1(const Integer &p) {m_p = p;}
void SetPrime2(const Integer &q) {m_q = q;}
protected:
Integer m_p, m_q;
};
//! _
template <class T>
class EMSA5Pad : public PK_DeterministicSignatureMessageEncodingMethod
{
public:
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "EMSA5";}
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
const byte *recoverableMessage, size_t recoverableMessageLength,
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
byte *representative, size_t representativeBitLength) const
{
CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(recoverableMessage), CRYPTOPP_UNUSED(recoverableMessageLength);
CRYPTOPP_UNUSED(messageEmpty), CRYPTOPP_UNUSED(hashIdentifier);
SecByteBlock digest(hash.DigestSize());
hash.Final(digest);
size_t representativeByteLength = BitsToBytes(representativeBitLength);
T mgf;
mgf.GenerateAndMask(hash, representative, representativeByteLength, digest, digest.size(), false);
if (representativeBitLength % 8 != 0)
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
}
};
//! EMSA5, for use with ESIGN
struct P1363_EMSA5 : public SignatureStandard
{
typedef EMSA5Pad<P1363_MGF1> SignatureMessageEncodingMethod;
};
struct ESIGN_Keys
{
static std::string StaticAlgorithmName() {return "ESIGN";}
typedef ESIGNFunction PublicKey;
typedef InvertibleESIGNFunction PrivateKey;
};
//! ESIGN, as defined in IEEE P1363a
template <class H, class STANDARD = P1363_EMSA5>
struct ESIGN : public TF_SS<STANDARD, H, ESIGN_Keys>
{
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,139 @@
#ifndef CRYPTOPP_OBJFACT_H
#define CRYPTOPP_OBJFACT_H
#include "cryptlib.h"
#include "misc.h"
#include "stdcpp.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
template <class AbstractClass>
class ObjectFactory
{
public:
virtual ~ObjectFactory () {}
virtual AbstractClass * CreateObject() const =0;
};
//! _
template <class AbstractClass, class ConcreteClass>
class DefaultObjectFactory : public ObjectFactory<AbstractClass>
{
public:
AbstractClass * CreateObject() const
{
return new ConcreteClass;
}
};
//! _
template <class AbstractClass, int instance=0>
class ObjectFactoryRegistry
{
public:
class FactoryNotFound : public Exception
{
public:
FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name) {}
};
~ObjectFactoryRegistry()
{
for (CPP_TYPENAME Map::iterator i = m_map.begin(); i != m_map.end(); ++i)
{
delete (ObjectFactory<AbstractClass> *)i->second;
i->second = NULL;
}
}
void RegisterFactory(const std::string &name, ObjectFactory<AbstractClass> *factory)
{
m_map[name] = factory;
}
const ObjectFactory<AbstractClass> * GetFactory(const char *name) const
{
CPP_TYPENAME Map::const_iterator i = m_map.find(name);
return i == m_map.end() ? NULL : (ObjectFactory<AbstractClass> *)i->second;
}
AbstractClass *CreateObject(const char *name) const
{
const ObjectFactory<AbstractClass> *factory = GetFactory(name);
if (!factory)
throw FactoryNotFound(name);
return factory->CreateObject();
}
// Return a vector containing the factory names. This is easier than returning an iterator.
// from Andrew Pitonyak
std::vector<std::string> GetFactoryNames() const
{
std::vector<std::string> names;
CPP_TYPENAME Map::const_iterator iter;
for (iter = m_map.begin(); iter != m_map.end(); ++iter)
names.push_back(iter->first);
return names;
}
CRYPTOPP_NOINLINE static ObjectFactoryRegistry<AbstractClass, instance> & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT);
private:
// use void * instead of ObjectFactory<AbstractClass> * to save code size
typedef std::map<std::string, void *> Map;
Map m_map;
};
template <class AbstractClass, int instance>
ObjectFactoryRegistry<AbstractClass, instance> & ObjectFactoryRegistry<AbstractClass, instance>::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)
{
static ObjectFactoryRegistry<AbstractClass, instance> s_registry;
return s_registry;
}
template <class AbstractClass, class ConcreteClass, int instance = 0>
struct RegisterDefaultFactoryFor {
RegisterDefaultFactoryFor(const char *name=NULL)
{
// BCB2006 workaround
std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName());
ObjectFactoryRegistry<AbstractClass, instance>::Registry().
RegisterFactory(n, new DefaultObjectFactory<AbstractClass, ConcreteClass>);
}};
template <class SchemeClass>
void RegisterAsymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
RegisterDefaultFactoryFor<PK_Encryptor, CPP_TYPENAME SchemeClass::Encryptor>((const char *)name);
RegisterDefaultFactoryFor<PK_Decryptor, CPP_TYPENAME SchemeClass::Decryptor>((const char *)name);
}
template <class SchemeClass>
void RegisterSignatureSchemeDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
RegisterDefaultFactoryFor<PK_Signer, CPP_TYPENAME SchemeClass::Signer>((const char *)name);
RegisterDefaultFactoryFor<PK_Verifier, CPP_TYPENAME SchemeClass::Verifier>((const char *)name);
}
template <class SchemeClass>
void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
}
template <class SchemeClass>
void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
{
CRYPTOPP_UNUSED(dummy);
RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
}
NAMESPACE_END
#endif

View File

@ -0,0 +1,304 @@
// fhmqv.h - written and placed in the public domain by Jeffrey Walton, Ray Clayton and Uri Blumenthal
// Shamelessly based upon Wei Dai's MQV source files
#ifndef CRYPTOPP_FHMQV_H
#define CRYPTOPP_FHMQV_H
//! \file fhmqv.h
//! \brief Classes for Fully Hashed Menezes-Qu-Vanstone key agreement in GF(p)
//! \since Crypto++ 5.6.4
#include "gfpcrypt.h"
#include "algebra.h"
#include "sha.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p)
//! \details This implementation follows Augustin P. Sarr and Philippe ElbazVincent, and JeanClaude Bajard's
//! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
//! \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain
//! \since Crypto++ 5.6.4
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
class FHMQV_Domain : public AuthenticatedKeyAgreementDomain
{
public:
typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element;
typedef FHMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~FHMQV_Domain() {}
#endif
FHMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
FHMQV_Domain(const GroupParameters &params, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.BERDecode(bt);}
template <class T1>
FHMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1);}
template <class T1, class T2>
FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2);}
template <class T1, class T2, class T3>
FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3);}
template <class T1, class T2, class T3, class T4>
FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
GroupParameters & AccessGroupParameters(){return m_groupParameters;}
CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
//! return length of agreed value produced
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
//! return length of static private keys in this domain
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
//! return length of static public keys in this domain
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
//! generate static private key
/*! \pre size of privateKey == PrivateStaticKeyLength() */
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
//! generate static public key
/*! \pre size of publicKey == PublicStaticKeyLength() */
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
//! return length of ephemeral private keys in this domain
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
}
//! return length of ephemeral public keys in this domain
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
/*! \note The ephemeral public key will always be validated.
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
\pre size of agreedValue == AgreedValueLength()
\pre length of staticPrivateKey == StaticPrivateKeyLength()
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
\pre length of staticOtherPublicKey == StaticPublicKeyLength()
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
*/
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const
{
byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL;
size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
// Depending on the role, this will hold either A's or B's static
// (long term) public key. AA or BB will then point into tt.
SecByteBlock tt(StaticPublicKeyLength());
try
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer)
{
Integer b(staticPrivateKey, StaticPrivateKeyLength());
Element B = params.ExponentiateBase(b);
params.EncodeElement(true, B, tt);
XX = const_cast<byte*>(ephemeralOtherPublicKey);
xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
yys = EphemeralPublicKeyLength();
AA = const_cast<byte*>(staticOtherPublicKey);
aas = StaticPublicKeyLength();
BB = tt.BytePtr();
bbs = tt.SizeInBytes();
}
else if(m_role == RoleClient)
{
Integer a(staticPrivateKey, StaticPrivateKeyLength());
Element A = params.ExponentiateBase(a);
params.EncodeElement(true, A, tt);
XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralOtherPublicKey);
yys = EphemeralPublicKeyLength();
AA = tt.BytePtr();
aas = tt.SizeInBytes();
BB = const_cast<byte*>(staticOtherPublicKey);
bbs = StaticPublicKeyLength();
}
else
{
CRYPTOPP_ASSERT(0);
return false;
}
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. If the other's PublicKey is
// requested to be validated, we manually call ValidateElement at level 3.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL))
return false;
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULL))
return false;
const Integer& q = params.GetSubgroupOrder();
const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
Integer d, e;
SecByteBlock dd(len), ee(len);
Hash(NULL, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
d.Decode(dd.BytePtr(), dd.SizeInBytes());
Hash(NULL, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes());
e.Decode(ee.BytePtr(), ee.SizeInBytes());
Element sigma;
if(m_role == RoleServer)
{
Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer b(staticPrivateKey, StaticPrivateKeyLength());
Integer s_B = (y + e * b) % q;
Element A = params.DecodeElement(AA, false);
Element X = params.DecodeElement(XX, false);
Element t1 = params.ExponentiateElement(A, d);
Element t2 = m_groupParameters.MultiplyElements(X, t1);
sigma = params.ExponentiateElement(t2, s_B);
}
else
{
Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer a(staticPrivateKey, StaticPrivateKeyLength());
Integer s_A = (x + d * a) % q;
Element B = params.DecodeElement(BB, false);
Element Y = params.DecodeElement(YY, false);
Element t1 = params.ExponentiateElement(B, e);
Element t2 = m_groupParameters.MultiplyElements(Y, t1);
sigma = params.ExponentiateElement(t2, s_A);
}
Hash(&sigma, XX, xxs, YY, yys, AA, aas, BB, bbs, agreedValue, AgreedValueLength());
}
catch (DL_BadElement &)
{
return false;
}
return true;
}
protected:
inline void Hash(const Element* sigma,
const byte* e1, size_t e1len, const byte* e2, size_t e2len,
const byte* s1, size_t s1len, const byte* s2, size_t s2len,
byte* digest, size_t dlen) const
{
HASH hash;
size_t idx = 0, req = dlen;
size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE);
if(sigma)
{
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
}
hash.Update(e1, e1len);
hash.Update(e2, e2len);
hash.Update(s1, s1len);
hash.Update(s2, s2len);
hash.TruncatedFinal(digest, blk);
req -= blk;
// All this to catch tail bytes for large curves and small hashes
while(req != 0)
{
hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
idx += (size_t)HASH::DIGESTSIZE;
blk = STDMIN(req, (size_t)HASH::DIGESTSIZE);
hash.TruncatedFinal(&digest[idx], blk);
req -= blk;
}
}
private:
// The paper uses Initiator and Recipient - make it classical.
enum KeyAgreementRole{ RoleServer = 1, RoleClient };
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
GroupParameters m_groupParameters;
KeyAgreementRole m_role;
};
//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p)
//! \details This implementation follows Augustin P. Sarr and Philippe ElbazVincent, and JeanClaude Bajard's
//! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
//! \sa FHMQV, MQV_Domain, HMQV_Domain, AuthenticatedKeyAgreementDomain
//! \since Crypto++ 5.6.4
typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FHMQV;
NAMESPACE_END
#endif

View File

@ -0,0 +1,113 @@
#ifndef CRYPTOPP_FILES_H
#define CRYPTOPP_FILES_H
#include "cryptlib.h"
#include "filters.h"
#include "argnames.h"
#include "smartptr.h"
#include <iostream>
#include <fstream>
NAMESPACE_BEGIN(CryptoPP)
//! file-based implementation of Store interface
class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable
{
public:
class Err : public Exception
{
public:
Err(const std::string &s) : Exception(IO_ERROR, s) {}
};
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}};
class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}};
FileStore() : m_stream(NULL), m_space(NULL), m_len(0), m_waiting(0) {}
FileStore(std::istream &in) : m_stream(NULL), m_space(NULL), m_len(0), m_waiting(0)
{StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));}
FileStore(const char *filename) : m_stream(NULL), m_space(NULL), m_len(0), m_waiting(0)
{StoreInitialize(MakeParameters(Name::InputFileName(), filename ? filename : ""));}
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
FileStore(const wchar_t *filename)
{StoreInitialize(MakeParameters(Name::InputFileNameWide(), filename));}
#endif
std::istream* GetStream() {return m_stream;}
lword MaxRetrievable() const;
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
lword Skip(lword skipMax=ULONG_MAX);
private:
void StoreInitialize(const NameValuePairs &parameters);
member_ptr<std::ifstream> m_file;
std::istream *m_stream;
byte *m_space;
size_t m_len;
bool m_waiting;
};
//! file-based implementation of Source interface
class CRYPTOPP_DLL FileSource : public SourceTemplate<FileStore>
{
public:
typedef FileStore::Err Err;
typedef FileStore::OpenErr OpenErr;
typedef FileStore::ReadErr ReadErr;
FileSource(BufferedTransformation *attachment = NULL)
: SourceTemplate<FileStore>(attachment) {}
FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL)
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));}
FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));}
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
FileSource(const wchar_t *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileNameWide(), filename)(Name::InputBinaryMode(), binary));}
#endif
std::istream* GetStream() {return m_store.GetStream();}
};
//! file-based implementation of Sink interface
class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable
{
public:
class Err : public Exception
{
public:
Err(const std::string &s) : Exception(IO_ERROR, s) {}
};
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}};
class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}};
FileSink() : m_stream(NULL) {}
FileSink(std::ostream &out)
{IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));}
FileSink(const char *filename, bool binary=true)
{IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)(Name::OutputBinaryMode(), binary));}
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
FileSink(const wchar_t *filename, bool binary=true)
{IsolatedInitialize(MakeParameters(Name::OutputFileNameWide(), filename)(Name::OutputBinaryMode(), binary));}
#endif
std::ostream* GetStream() {return m_stream;}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
bool IsolatedFlush(bool hardFlush, bool blocking);
private:
member_ptr<std::ofstream> m_file;
std::ostream *m_stream;
};
NAMESPACE_END
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
// fips140.h - written and placed in the public domain by Wei Dai
//! \file fips140.h
//! \brief Classes and functions for the FIPS 140-2 validated library
//! \details The FIPS validated library is only available on Windows as a DLL. Once compiled,
//! the library is always in FIPS mode contingent upon successful execution of
//! DoPowerUpSelfTest() or DoDllPowerUpSelfTest().
//! \sa <A HREF="http://cryptopp.com/wiki/Visual_Studio">Visual Studio</A> and
//! <A HREF="http://cryptopp.com/wiki/config.h">config.h</A> on the Crypto++ wiki.
#ifndef CRYPTOPP_FIPS140_H
#define CRYPTOPP_FIPS140_H
#include "cryptlib.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class SelfTestFailure
//! Exception thrown when a crypto algorithm is used after a self test fails
//! \details The self tests for an algorithm are performed by Algortihm class
//! when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
class CRYPTOPP_DLL SelfTestFailure : public Exception
{
public:
explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {}
};
//! \brief Determines whether the library provides FIPS validated cryptography
//! \returns true if FIPS 140-2 validated features were enabled at compile time.
//! \details true if FIPS 140-2 validated features were enabled at compile time,
//! false otherwise.
//! \note FIPS mode is enabled at compile time. A program or other module cannot
//! arbitrarily enter or exit the mode.
CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled();
//! \brief Status of the power-up self test
enum PowerUpSelfTestStatus {
//! \brief The self tests have not been performed.
POWER_UP_SELF_TEST_NOT_DONE,
//! \brief The self tests were executed via DoPowerUpSelfTest() or
//! DoDllPowerUpSelfTest(), but the result was failure.
POWER_UP_SELF_TEST_FAILED,
//! \brief The self tests were executed via DoPowerUpSelfTest() or
//! DoDllPowerUpSelfTest(), and the result was success.
POWER_UP_SELF_TEST_PASSED
};
//! \brief Performs the power-up self test
//! \param moduleFilename the fully qualified name of the module
//! \param expectedModuleMac the expected MAC of the components protected by the integrity check
//! \details Performs the power-up self test, and sets the self test status to
//! POWER_UP_SELF_TEST_PASSED or POWER_UP_SELF_TEST_FAILED.
//! \details The self tests for an algorithm are performed by the Algortihm class
//! when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac);
//! \brief Performs the power-up self test on the DLL
//! \details Performs the power-up self test using the filename of this DLL and the
//! embedded module MAC, and sets the self test status to POWER_UP_SELF_TEST_PASSED or
//! POWER_UP_SELF_TEST_FAILED.
//! \details The self tests for an algorithm are performed by the Algortihm class
//! when CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined.
CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest();
//! \brief Sets the power-up self test status to POWER_UP_SELF_TEST_FAILED
//! \details Sets the power-up self test status to POWER_UP_SELF_TEST_FAILED to simulate failure.
CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure();
//! \brief Provides the current power-up self test status
//! \returns the current power-up self test status
CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus();
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)();
#endif
//! \brief Class object that calculates the MAC on the module
//! \returns the MAC for the module
CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC();
//! \brief Verifies the MAC on the module
//! \param moduleFilename the fully qualified name of the module
//! \param expectedModuleMac the expected MAC of the components protected by the integrity check
//! \param pActualMac the actual MAC of the components calculated by the integrity check
//! \param pMacFileLocation the offest of the MAC in the PE/PE+ module
//! \returns true if the MAC is valid, false otherwise
CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULL, unsigned long *pMacFileLocation = NULL);
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test
bool PowerUpSelfTestInProgressOnThisThread();
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress);
void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier);
void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier);
void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
#endif
//! \brief The placeholder used prior to embedding the actual MAC in the module.
//! \details After the DLL is built but before it is MAC'd, the string CRYPTOPP_DUMMY_DLL_MAC
//! is used as a placeholder for the actual MAC. A post-build step is performed which calculates
//! the MAC of the DLL and embeds it in the module. The actual MAC is written by the
//! <tt>cryptest.exe</tt> program using the <tt>mac_dll</tt> subcommand.
#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8"
NAMESPACE_END
#endif

View File

@ -0,0 +1,85 @@
#ifndef CRYPTOPP_FLTRIMPL_H
#define CRYPTOPP_FLTRIMPL_H
#if CRYPTOPP_MSC_VERSION
# pragma warning(push)
# pragma warning(disable: 4100)
#endif
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-value"
#endif
#define FILTER_BEGIN \
switch (m_continueAt) \
{ \
case 0: \
m_inputPosition = 0;
#define FILTER_END_NO_MESSAGE_END_NO_RETURN \
break; \
default: \
CRYPTOPP_ASSERT(false); \
}
#define FILTER_END_NO_MESSAGE_END \
FILTER_END_NO_MESSAGE_END_NO_RETURN \
return 0;
/*
#define FILTER_END \
case -1: \
if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \
return 1; \
FILTER_END_NO_MESSAGE_END
*/
#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \
{\
case site: \
statement; \
if (Output(site, output, length, messageEnd, blocking, channel)) \
return STDMAX(size_t(1), length-m_inputPosition);\
}
#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL)
#define FILTER_OUTPUT(site, output, length, messageEnd) \
FILTER_OUTPUT2(site, 0, output, length, messageEnd)
#define FILTER_OUTPUT_BYTE(site, output) \
FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0)
#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \
{\
case site: \
statement; \
if (OutputModifiable(site, output, length, messageEnd, blocking)) \
return STDMAX(size_t(1), length-m_inputPosition);\
}
#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \
FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd)
#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \
{\
case site: \
statement; \
if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \
return STDMAX(size_t(1), length-m_inputPosition);\
}
#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \
FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable)
#if CRYPTOPP_MSC_VERSION
# pragma warning(pop)
#endif
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic pop
#endif
#endif

View File

@ -0,0 +1,132 @@
// gcm.h - written and placed in the public domain by Wei Dai
//! \file gcm.h
//! \brief GCM block cipher mode of operation
//! \since Crypto++ 5.6.0
#ifndef CRYPTOPP_GCM_H
#define CRYPTOPP_GCM_H
#include "authenc.h"
#include "modes.h"
NAMESPACE_BEGIN(CryptoPP)
//! \enum GCM_TablesOption
//! \brief GCM table size options
enum GCM_TablesOption {
//! \brief Use a table with 2K entries
GCM_2K_Tables,
//! \brief Use a table with 64K entries
GCM_64K_Tables};
//! \class GCM_Base
//! \brief GCM block cipher base implementation
//! \details Base implementation of the AuthenticatedSymmetricCipher interface
//! \since Crypto++ 5.6.0
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase
{
public:
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return GetBlockCipher().AlgorithmName() + std::string("/GCM");}
size_t MinKeyLength() const
{return GetBlockCipher().MinKeyLength();}
size_t MaxKeyLength() const
{return GetBlockCipher().MaxKeyLength();}
size_t DefaultKeyLength() const
{return GetBlockCipher().DefaultKeyLength();}
size_t GetValidKeyLength(size_t n) const
{return GetBlockCipher().GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const
{return GetBlockCipher().IsValidKeyLength(n);}
unsigned int OptimalDataAlignment() const;
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return 12;}
unsigned int MinIVLength() const
{return 1;}
unsigned int MaxIVLength() const
{return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard
unsigned int DigestSize() const
{return 16;}
lword MaxHeaderLength() const
{return (W64LIT(1)<<61)-1;}
lword MaxMessageLength() const
{return ((W64LIT(1)<<39)-256)/8;}
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const
{return false;}
unsigned int AuthenticationBlockSize() const
{return HASH_BLOCKSIZE;}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastConfidentialBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
virtual BlockCipher & AccessBlockCipher() =0;
virtual GCM_TablesOption GetTablesOption() const =0;
const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}
inline void ReverseHashBufferIfNeeded();
class CRYPTOPP_DLL GCTR : public CTR_Mode_ExternalCipher::Encryption
{
protected:
void IncrementCounterBy256();
};
GCTR m_ctr;
static word16 s_reductionTable[256];
static volatile bool s_reductionTableInitialized;
enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16};
};
//! \class GCM_Final
//! \brief GCM block cipher final implementation
//! \tparam T_BlockCipher block cipher
//! \tparam T_TablesOption table size, either \p GCM_2K_Tables or \p GCM_64K_Tables
//! \tparam T_IsEncryption direction in which to operate the cipher
//! \since Crypto++ 5.6.0
template <class T_BlockCipher, GCM_TablesOption T_TablesOption, bool T_IsEncryption>
class GCM_Final : public GCM_Base
{
public:
static std::string StaticAlgorithmName()
{return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");}
bool IsForwardTransformation() const
{return T_IsEncryption;}
private:
GCM_TablesOption GetTablesOption() const {return T_TablesOption;}
BlockCipher & AccessBlockCipher() {return m_cipher;}
typename T_BlockCipher::Encryption m_cipher;
};
//! \class GCM
//! \brief GCM block cipher mode of operation
//! \tparam T_BlockCipher block cipher
//! \tparam T_TablesOption table size, either \p GCM_2K_Tables or \p GCM_64K_Tables
//! \details \p GCM provides the \p Encryption and \p Decryption typedef. See GCM_Base
//! and GCM_Final for the AuthenticatedSymmetricCipher implementation.
//! \sa <a href="http://www.cryptolounge.org/wiki/GCM">GCM</a> at the Crypto Lounge
//! \since Crypto++ 5.6.0
template <class T_BlockCipher, GCM_TablesOption T_TablesOption=GCM_2K_Tables>
struct GCM : public AuthenticatedSymmetricCipherDocumentation
{
typedef GCM_Final<T_BlockCipher, T_TablesOption, true> Encryption;
typedef GCM_Final<T_BlockCipher, T_TablesOption, false> Decryption;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,67 @@
#ifndef CRYPTOPP_GF256_H
#define CRYPTOPP_GF256_H
#include "cryptlib.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! GF(256) with polynomial basis
class GF256
{
public:
typedef byte Element;
typedef int RandomizationParameter;
GF256(byte modulus) : m_modulus(modulus) {}
Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
{CRYPTOPP_UNUSED(ignored); return rng.GenerateByte();}
bool Equal(Element a, Element b) const
{return a==b;}
Element Zero() const
{return 0;}
Element Add(Element a, Element b) const
{return a^b;}
Element& Accumulate(Element &a, Element b) const
{return a^=b;}
Element Inverse(Element a) const
{return a;}
Element Subtract(Element a, Element b) const
{return a^b;}
Element& Reduce(Element &a, Element b) const
{return a^=b;}
Element Double(Element a) const
{CRYPTOPP_UNUSED(a); return 0;}
Element One() const
{return 1;}
Element Multiply(Element a, Element b) const;
Element Square(Element a) const
{return Multiply(a, a);}
bool IsUnit(Element a) const
{return a != 0;}
Element MultiplicativeInverse(Element a) const;
Element Divide(Element a, Element b) const
{return Multiply(a, MultiplicativeInverse(b));}
private:
word m_modulus;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,68 @@
#ifndef CRYPTOPP_GF2_32_H
#define CRYPTOPP_GF2_32_H
#include "cryptlib.h"
#include "secblock.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! GF(2^32) with polynomial basis
class GF2_32
{
public:
typedef word32 Element;
typedef int RandomizationParameter;
GF2_32(word32 modulus=0x0000008D) : m_modulus(modulus) {}
Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
{CRYPTOPP_UNUSED(ignored); return rng.GenerateWord32();}
bool Equal(Element a, Element b) const
{return a==b;}
Element Identity() const
{return 0;}
Element Add(Element a, Element b) const
{return a^b;}
Element& Accumulate(Element &a, Element b) const
{return a^=b;}
Element Inverse(Element a) const
{return a;}
Element Subtract(Element a, Element b) const
{return a^b;}
Element& Reduce(Element &a, Element b) const
{return a^=b;}
Element Double(Element a) const
{CRYPTOPP_UNUSED(a); return 0;}
Element MultiplicativeIdentity() const
{return 1;}
Element Multiply(Element a, Element b) const;
Element Square(Element a) const
{return Multiply(a, a);}
bool IsUnit(Element a) const
{return a != 0;}
Element MultiplicativeInverse(Element a) const;
Element Divide(Element a, Element b) const
{return Multiply(a, MultiplicativeInverse(b));}
private:
word32 m_modulus;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,370 @@
#ifndef CRYPTOPP_GF2N_H
#define CRYPTOPP_GF2N_H
/*! \file */
#include "cryptlib.h"
#include "secblock.h"
#include "algebra.h"
#include "misc.h"
#include "asn.h"
#include <iosfwd>
NAMESPACE_BEGIN(CryptoPP)
//! Polynomial with Coefficients in GF(2)
/*! \nosubgrouping */
class CRYPTOPP_DLL PolynomialMod2
{
public:
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS
//@{
//! divide by zero exception
class DivideByZero : public Exception
{
public:
DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {}
};
typedef unsigned int RandomizationParameter;
//@}
//! \name CREATORS
//@{
//! creates the zero polynomial
PolynomialMod2();
//! copy constructor
PolynomialMod2(const PolynomialMod2& t);
//! convert from word
/*! value should be encoded with the least significant bit as coefficient to x^0
and most significant bit as coefficient to x^(WORD_BITS-1)
bitLength denotes how much memory to allocate initially
*/
PolynomialMod2(word value, size_t bitLength=WORD_BITS);
//! convert from big-endian byte array
PolynomialMod2(const byte *encodedPoly, size_t byteCount)
{Decode(encodedPoly, byteCount);}
//! convert from big-endian form stored in a BufferedTransformation
PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount)
{Decode(encodedPoly, byteCount);}
//! create a random polynomial uniformly distributed over all polynomials with degree less than bitcount
PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount)
{Randomize(rng, bitcount);}
//! return x^i
static PolynomialMod2 CRYPTOPP_API Monomial(size_t i);
//! return x^t0 + x^t1 + x^t2
static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
//! return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
//! return x^(n-1) + ... + x + 1
static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
//!
static const PolynomialMod2 & CRYPTOPP_API Zero();
//!
static const PolynomialMod2 & CRYPTOPP_API One();
//@}
//! \name ENCODE/DECODE
//@{
//! minimum number of bytes to encode this polynomial
/*! MinEncodedSize of 0 is 1 */
unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());}
//! encode in big-endian format
/*! if outputLen < MinEncodedSize, the most significant bytes will be dropped
if outputLen > MinEncodedSize, the most significant bytes will be padded
*/
void Encode(byte *output, size_t outputLen) const;
//!
void Encode(BufferedTransformation &bt, size_t outputLen) const;
//!
void Decode(const byte *input, size_t inputLen);
//!
//* Precondition: bt.MaxRetrievable() >= inputLen
void Decode(BufferedTransformation &bt, size_t inputLen);
//! encode value as big-endian octet string
void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
//! decode value as big-endian octet string
void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
//@}
//! \name ACCESSORS
//@{
//! number of significant bits = Degree() + 1
unsigned int BitCount() const;
//! number of significant bytes = ceiling(BitCount()/8)
unsigned int ByteCount() const;
//! number of significant words = ceiling(ByteCount()/sizeof(word))
unsigned int WordCount() const;
//! return the n-th bit, n=0 being the least significant bit
bool GetBit(size_t n) const {return GetCoefficient(n)!=0;}
//! return the n-th byte
byte GetByte(size_t n) const;
//! the zero polynomial will return a degree of -1
signed int Degree() const {return (signed int)(BitCount()-1U);}
//! degree + 1
unsigned int CoefficientCount() const {return BitCount();}
//! return coefficient for x^i
int GetCoefficient(size_t i) const
{return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;}
//! return coefficient for x^i
int operator[](unsigned int i) const {return GetCoefficient(i);}
//!
bool IsZero() const {return !*this;}
//!
bool Equals(const PolynomialMod2 &rhs) const;
//@}
//! \name MANIPULATORS
//@{
//!
PolynomialMod2& operator=(const PolynomialMod2& t);
//!
PolynomialMod2& operator&=(const PolynomialMod2& t);
//!
PolynomialMod2& operator^=(const PolynomialMod2& t);
//!
PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;}
//!
PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;}
//!
PolynomialMod2& operator*=(const PolynomialMod2& t);
//!
PolynomialMod2& operator/=(const PolynomialMod2& t);
//!
PolynomialMod2& operator%=(const PolynomialMod2& t);
//!
PolynomialMod2& operator<<=(unsigned int);
//!
PolynomialMod2& operator>>=(unsigned int);
//!
void Randomize(RandomNumberGenerator &rng, size_t bitcount);
//!
void SetBit(size_t i, int value = 1);
//! set the n-th byte to value
void SetByte(size_t n, byte value);
//!
void SetCoefficient(size_t i, int value) {SetBit(i, value);}
//!
void swap(PolynomialMod2 &a) {reg.swap(a.reg);}
//@}
//! \name UNARY OPERATORS
//@{
//!
bool operator!() const;
//!
PolynomialMod2 operator+() const {return *this;}
//!
PolynomialMod2 operator-() const {return *this;}
//@}
//! \name BINARY OPERATORS
//@{
//!
PolynomialMod2 And(const PolynomialMod2 &b) const;
//!
PolynomialMod2 Xor(const PolynomialMod2 &b) const;
//!
PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);}
//!
PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);}
//!
PolynomialMod2 Times(const PolynomialMod2 &b) const;
//!
PolynomialMod2 DividedBy(const PolynomialMod2 &b) const;
//!
PolynomialMod2 Modulo(const PolynomialMod2 &b) const;
//!
PolynomialMod2 operator>>(unsigned int n) const;
//!
PolynomialMod2 operator<<(unsigned int n) const;
//@}
//! \name OTHER ARITHMETIC FUNCTIONS
//@{
//! sum modulo 2 of all coefficients
unsigned int Parity() const;
//! check for irreducibility
bool IsIrreducible() const;
//! is always zero since we're working modulo 2
PolynomialMod2 Doubled() const {return Zero();}
//!
PolynomialMod2 Squared() const;
//! only 1 is a unit
bool IsUnit() const {return Equals(One());}
//! return inverse if *this is a unit, otherwise return 0
PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();}
//! greatest common divisor
static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n);
//! calculate multiplicative inverse of *this mod n
PolynomialMod2 InverseMod(const PolynomialMod2 &) const;
//! calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d);
//@}
//! \name INPUT/OUTPUT
//@{
//!
friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a);
//@}
private:
friend class GF2NT;
SecWordBlock reg;
};
//!
inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return a.Equals(b);}
//!
inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return !(a==b);}
//! compares degree
inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return a.Degree() > b.Degree();}
//! compares degree
inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return a.Degree() >= b.Degree();}
//! compares degree
inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return a.Degree() < b.Degree();}
//! compares degree
inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
{return a.Degree() <= b.Degree();}
//!
inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);}
//!
inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);}
//!
inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);}
//!
inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);}
//!
inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);}
//!
inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);}
//!
inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);}
// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations,
// but before the use of QuotientRing<EuclideanDomainOf<PolynomialMod2> > for VC .NET 2003
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<PolynomialMod2>;
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<PolynomialMod2>;
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<PolynomialMod2>;
CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf<PolynomialMod2>;
CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing<EuclideanDomainOf<PolynomialMod2> >;
//! GF(2^n) with Polynomial Basis
class CRYPTOPP_DLL GF2NP : public QuotientRing<EuclideanDomainOf<PolynomialMod2> >
{
public:
GF2NP(const PolynomialMod2 &modulus);
virtual GF2NP * Clone() const {return new GF2NP(*this);}
virtual void DEREncode(BufferedTransformation &bt) const
{CRYPTOPP_UNUSED(bt); CRYPTOPP_ASSERT(false);} // no ASN.1 syntax yet for general polynomial basis
void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
void BERDecodeElement(BufferedTransformation &in, Element &a) const;
bool Equal(const Element &a, const Element &b) const
{CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);}
bool IsUnit(const Element &a) const
{CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree()); return !!a;}
unsigned int MaxElementBitLength() const
{return m;}
unsigned int MaxElementByteLength() const
{return (unsigned int)BitsToBytes(MaxElementBitLength());}
Element SquareRoot(const Element &a) const;
Element HalfTrace(const Element &a) const;
// returns z such that z^2 + z == a
Element SolveQuadraticEquation(const Element &a) const;
protected:
unsigned int m;
};
//! GF(2^n) with Trinomial Basis
class CRYPTOPP_DLL GF2NT : public GF2NP
{
public:
// polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
GF2NT(unsigned int t0, unsigned int t1, unsigned int t2);
GF2NP * Clone() const {return new GF2NT(*this);}
void DEREncode(BufferedTransformation &bt) const;
const Element& Multiply(const Element &a, const Element &b) const;
const Element& Square(const Element &a) const
{return Reduced(a.Squared());}
const Element& MultiplicativeInverse(const Element &a) const;
private:
const Element& Reduced(const Element &a) const;
unsigned int t0, t1;
mutable PolynomialMod2 result;
};
//! GF(2^n) with Pentanomial Basis
class CRYPTOPP_DLL GF2NPP : public GF2NP
{
public:
// polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4
GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4)
: GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {}
GF2NP * Clone() const {return new GF2NPP(*this);}
void DEREncode(BufferedTransformation &bt) const;
private:
unsigned int t0, t1, t2, t3;
};
// construct new GF2NP from the ASN.1 sequence Characteristic-two
CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt);
NAMESPACE_END
#ifndef __BORLANDC__
NAMESPACE_BEGIN(std)
template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b)
{
a.swap(b);
}
NAMESPACE_END
#endif
#endif

View File

@ -0,0 +1,636 @@
#ifndef CRYPTOPP_GFPCRYPT_H
#define CRYPTOPP_GFPCRYPT_H
/** \file
Implementation of schemes based on DL over GF(p)
*/
#include "config.h"
#if CRYPTOPP_MSC_VERSION
# pragma warning(push)
# pragma warning(disable: 4189)
#endif
#include "cryptlib.h"
#include "pubkey.h"
#include "integer.h"
#include "modexppc.h"
#include "algparam.h"
#include "smartptr.h"
#include "sha.h"
#include "asn.h"
#include "hmac.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
//! _
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
{
typedef DL_GroupParameters_IntegerBased ThisClass;
public:
void Initialize(const DL_GroupParameters_IntegerBased &params)
{Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
{GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
void Initialize(const Integer &p, const Integer &g)
{SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
void Initialize(const Integer &p, const Integer &q, const Integer &g)
{SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
// ASN1Object interface
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
// GeneratibleCryptoMaterial interface
/*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
// DL_GroupParameters
const Integer & GetSubgroupOrder() const {return m_q;}
Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
// Cygwin i386 crash at -O3; see .
void EncodeElement(bool reversible, const Element &element, byte *encoded) const;
unsigned int GetEncodedElementSize(bool reversible) const;
#else
void EncodeElement(bool reversible, const Element &element, byte *encoded) const
{CRYPTOPP_UNUSED(reversible); element.Encode(encoded, GetModulus().ByteCount());}
unsigned int GetEncodedElementSize(bool reversible) const
{CRYPTOPP_UNUSED(reversible); return GetModulus().ByteCount();}
#endif
Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
Integer ConvertElementToInteger(const Element &element) const
{return element;}
Integer GetMaxExponent() const;
static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
OID GetAlgorithmID() const;
virtual const Integer & GetModulus() const =0;
virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
void SetSubgroupOrder(const Integer &q)
{m_q = q; ParametersChanged();}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_IntegerBased() {}
#endif
protected:
Integer ComputeGroupOrder(const Integer &modulus) const
{return modulus-(GetFieldType() == 1 ? 1 : -1);}
// GF(p) = 1, GF(p^2) = 2
virtual int GetFieldType() const =0;
virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
private:
Integer m_q;
};
//! _
template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
{
typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
public:
typedef typename GROUP_PRECOMP::Element Element;
// GeneratibleCryptoMaterial interface
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
void AssignFrom(const NameValuePairs &source)
{AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
// DL_GroupParameters
const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
// IntegerGroupParameters
const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together
{this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
// non-inherited
bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
{return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
{return !operator==(rhs);}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_IntegerBasedImpl() {}
#endif
};
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
//! GF(p) group parameters
class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
{
public:
// DL_GroupParameters
bool IsIdentity(const Integer &element) const {return element == Integer::One();}
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
// NameValuePairs interface
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
}
// used by MQV
Element MultiplyElements(const Element &a, const Element &b) const;
Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_GFP() {}
#endif
protected:
int GetFieldType() const {return 1;}
};
//! GF(p) group parameters that default to same primes
class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
{
public:
typedef NoCofactorMultiplication DefaultCofactorOption;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_GFP_DefaultSafePrime() {}
#endif
protected:
unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
};
//! GDSA algorithm
template <class T>
class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
{
public:
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
{
const Integer &q = params.GetSubgroupOrder();
r %= q;
Integer kInv = k.InverseMod(q);
s = (kInv * (x*r + e)) % q;
CRYPTOPP_ASSERT(!!r && !!s);
}
bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
{
const Integer &q = params.GetSubgroupOrder();
if (r>=q || r<1 || s>=q || s<1)
return false;
Integer w = s.InverseMod(q);
Integer u1 = (e * w) % q;
Integer u2 = (r * w) % q;
// verify r == (g^u1 * y^u2 mod p) mod q
return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Algorithm_GDSA() {}
#endif
};
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
//! NR algorithm
template <class T>
class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
{
public:
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";}
void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
{
const Integer &q = params.GetSubgroupOrder();
r = (r + e) % q;
s = (k - x*r) % q;
CRYPTOPP_ASSERT(!!r);
}
bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
{
const Integer &q = params.GetSubgroupOrder();
if (r>=q || r<1 || s>=q)
return false;
// check r == (m_g^s * m_y^r + m) mod m_q
return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Algorithm_NR() {}
#endif
};
/*! DSA public key format is defined in 7.3.3 of RFC 2459. The
private key format is defined in 12.9 of PKCS #11 v2.10. */
template <class GP>
class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
{
public:
void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
{this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
void Initialize(const Integer &p, const Integer &g, const Integer &y)
{this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
{this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
// X509PublicKey
void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
{this->SetPublicElement(Integer(bt));}
void DEREncodePublicKey(BufferedTransformation &bt) const
{this->GetPublicElement().DEREncode(bt);}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PublicKey_GFP() {}
#endif
};
//! DL private key (in GF(p) groups)
template <class GP>
class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
{
public:
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
{this->GenerateRandomWithKeySize(rng, modulusBits);}
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
{this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
{this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
{this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
void Initialize(const Integer &p, const Integer &g, const Integer &x)
{this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
{this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PrivateKey_GFP() {}
#endif
};
//! DL signing/verification keys (in GF(p) groups)
struct DL_SignatureKeys_GFP
{
typedef DL_GroupParameters_GFP GroupParameters;
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_SignatureKeys_GFP() {}
#endif
};
//! DL encryption/decryption keys (in GF(p) groups)
struct DL_CryptoKeys_GFP
{
typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_CryptoKeys_GFP() {}
#endif
};
//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
template <class BASE>
class DL_PublicKey_GFP_OldFormat : public BASE
{
public:
void BERDecode(BufferedTransformation &bt)
{
BERSequenceDecoder seq(bt);
Integer v1(seq);
Integer v2(seq);
Integer v3(seq);
if (seq.EndReached())
{
this->AccessGroupParameters().Initialize(v1, v1/2, v2);
this->SetPublicElement(v3);
}
else
{
Integer v4(seq);
this->AccessGroupParameters().Initialize(v1, v2, v3);
this->SetPublicElement(v4);
}
seq.MessageEnd();
}
void DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder seq(bt);
this->GetGroupParameters().GetModulus().DEREncode(seq);
if (this->GetGroupParameters().GetCofactor() != 2)
this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
this->GetGroupParameters().GetGenerator().DEREncode(seq);
this->GetPublicElement().DEREncode(seq);
seq.MessageEnd();
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PublicKey_GFP_OldFormat() {}
#endif
};
//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
template <class BASE>
class DL_PrivateKey_GFP_OldFormat : public BASE
{
public:
void BERDecode(BufferedTransformation &bt)
{
BERSequenceDecoder seq(bt);
Integer v1(seq);
Integer v2(seq);
Integer v3(seq);
Integer v4(seq);
if (seq.EndReached())
{
this->AccessGroupParameters().Initialize(v1, v1/2, v2);
this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q
}
else
{
Integer v5(seq);
this->AccessGroupParameters().Initialize(v1, v2, v3);
this->SetPrivateExponent(v5);
}
seq.MessageEnd();
}
void DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder seq(bt);
this->GetGroupParameters().GetModulus().DEREncode(seq);
if (this->GetGroupParameters().GetCofactor() != 2)
this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
this->GetGroupParameters().GetGenerator().DEREncode(seq);
this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
this->GetPrivateExponent().DEREncode(seq);
seq.MessageEnd();
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_PrivateKey_GFP_OldFormat() {}
#endif
};
//! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
template <class H>
struct GDSA : public DL_SS<
DL_SignatureKeys_GFP,
DL_Algorithm_GDSA<Integer>,
DL_SignatureMessageEncodingMethod_DSA,
H>
{
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~GDSA() {}
#endif
};
//! <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
template <class H>
struct NR : public DL_SS<
DL_SignatureKeys_GFP,
DL_Algorithm_NR<Integer>,
DL_SignatureMessageEncodingMethod_NR,
H>
{
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~NR() {}
#endif
};
//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard
class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
{
public:
/*! also checks that the lengths of p and q are allowed by the DSA standard */
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
/*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
/*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
{return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_DSA() {}
#endif
};
template <class H>
class DSA2;
//! DSA keys
struct DL_Keys_DSA
{
typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> > PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Keys_DSA() {}
#endif
};
//! <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
// class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class)
template <class H>
class DSA2 : public DL_SS<
DL_Keys_DSA,
DL_Algorithm_GDSA<Integer>,
DL_SignatureMessageEncodingMethod_DSA,
H,
DSA2<H> >
{
public:
static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
#endif
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DSA2() {}
#endif
};
//! DSA with SHA-1, typedef'd for backwards compatibility
typedef DSA2<SHA> DSA;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> >;
//! the XOR encryption method, for use with DL-based cryptosystems
template <class MAC, bool DHAES_MODE>
class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
{
public:
bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
size_t GetSymmetricKeyLength(size_t plaintextLength) const
{return plaintextLength + MAC::DEFAULT_KEYLENGTH;}
size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
{return plaintextLength + MAC::DIGESTSIZE;}
size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
{return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);}
void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
{
CRYPTOPP_UNUSED(rng);
const byte *cipherKey = NULL, *macKey = NULL;
if (DHAES_MODE)
{
macKey = key;
cipherKey = key + MAC::DEFAULT_KEYLENGTH;
}
else
{
cipherKey = key;
macKey = key + plaintextLength;
}
ConstByteArrayParameter encodingParameters;
parameters.GetValue(Name::EncodingParameters(), encodingParameters);
if (plaintextLength) // Coverity finding
xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
MAC mac(macKey);
mac.Update(ciphertext, plaintextLength);
mac.Update(encodingParameters.begin(), encodingParameters.size());
if (DHAES_MODE)
{
byte L[8] = {0,0,0,0};
PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
mac.Update(L, 8);
}
mac.Final(ciphertext + plaintextLength);
}
DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
{
size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
const byte *cipherKey, *macKey;
if (DHAES_MODE)
{
macKey = key;
cipherKey = key + MAC::DEFAULT_KEYLENGTH;
}
else
{
cipherKey = key;
macKey = key + plaintextLength;
}
ConstByteArrayParameter encodingParameters;
parameters.GetValue(Name::EncodingParameters(), encodingParameters);
MAC mac(macKey);
mac.Update(ciphertext, plaintextLength);
mac.Update(encodingParameters.begin(), encodingParameters.size());
if (DHAES_MODE)
{
byte L[8] = {0,0,0,0};
PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
mac.Update(L, 8);
}
if (!mac.Verify(ciphertext + plaintextLength))
return DecodingResult();
if (plaintextLength) // Coverity finding
xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
return DecodingResult(plaintextLength);
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_EncryptionAlgorithm_Xor() {}
#endif
};
//! _
template <class T, bool DHAES_MODE, class KDF>
class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
{
public:
bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
void Derive(const DL_GroupParameters<T> &params, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &parameters) const
{
SecByteBlock agreedSecret;
if (DHAES_MODE)
{
agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
}
else
{
agreedSecret.New(params.GetEncodedElementSize(false));
params.EncodeElement(false, agreedElement, agreedSecret);
}
ConstByteArrayParameter derivationParameters;
parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_KeyDerivationAlgorithm_P1363() {}
#endif
};
//! Discrete Log Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">DLIES</a>
template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
struct DLIES
: public DL_ES<
DL_CryptoKeys_GFP,
DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
DLIES<> >
{
static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DLIES() {}
#endif
};
NAMESPACE_END
#if CRYPTOPP_MSC_VERSION
# pragma warning(pop)
#endif
#endif

View File

@ -0,0 +1,69 @@
// gost.h - written and placed in the public domain by Wei Dai
//! \file gost.h
//! \brief Classes for the GIST block cipher
#ifndef CRYPTOPP_GOST_H
#define CRYPTOPP_GOST_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class GOST_Info
//! \brief GOST block cipher information
struct GOST_Info : public FixedBlockSize<8>, public FixedKeyLength<32>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "GOST";}
};
//! \class GOST
//! \brief GOST block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#GOST">GOST</a>
class GOST : public GOST_Info, public BlockCipherDocumentation
{
//! \class Base
//! \brief GOST block cipher default operation
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<GOST_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
protected:
static void PrecalculateSTable();
static const byte sBox[8][16];
static volatile bool sTableCalculated;
static word32 sTable[4][256];
FixedSizeSecBlock<word32, 8> m_key;
};
//! \class Enc
//! \brief GOST block cipher encryption operation
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \class Dec
//! \brief GOST block cipher decryption operation
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
typedef GOST::Encryption GOSTEncryption;
typedef GOST::Decryption GOSTDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,101 @@
// gzip.h - written and placed in the public domain by Wei Dai
//! \file gzip.h
//! \brief GZIP compression and decompression (RFC 1952)
#ifndef CRYPTOPP_GZIP_H
#define CRYPTOPP_GZIP_H
#include "cryptlib.h"
#include "zdeflate.h"
#include "zinflate.h"
#include "crc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Gzip
//! \brief GZIP Compression (RFC 1952)
class Gzip : public Deflator
{
public:
//! \brief Construct a Gzip compressor
//! \param attachment an attached transformation
//! \param deflateLevel the deflate level
//! \param log2WindowSize the window size
//! \param detectUncompressible flag to detect if data is compressible
//! \details detectUncompressible makes it faster to process uncompressible files, but
//! if a file has both compressible and uncompressible parts, it may fail to compress
//! some of the compressible parts.
Gzip(BufferedTransformation *attachment=NULL, unsigned int deflateLevel=DEFAULT_DEFLATE_LEVEL, unsigned int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true)
: Deflator(attachment, deflateLevel, log2WindowSize, detectUncompressible), m_totalLen(0) {}
//! \brief Construct a Gzip compressor
//! \param parameters a set of NameValuePairs to initialize this object
//! \param attachment an attached transformation
//! \details Possible parameter names: Log2WindowSize, DeflateLevel, DetectUncompressible
Gzip(const NameValuePairs &parameters, BufferedTransformation *attachment=NULL)
: Deflator(parameters, attachment), m_totalLen(0) {}
protected:
enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header
DEFLATED=8, FAST=4, SLOW=2};
void WritePrestreamHeader();
void ProcessUncompressedData(const byte *string, size_t length);
void WritePoststreamTail();
word32 m_totalLen;
CRC32 m_crc;
};
//! \class Gunzip
//! \brief GZIP Decompression (RFC 1952)
class Gunzip : public Inflator
{
public:
typedef Inflator::Err Err;
//! \class HeaderErr
//! \brief Exception thrown when a header decoding error occurs
class HeaderErr : public Err {public: HeaderErr() : Err(INVALID_DATA_FORMAT, "Gunzip: header decoding error") {}};
//! \class TailErr
//! \brief Exception thrown when the tail is too short
class TailErr : public Err {public: TailErr() : Err(INVALID_DATA_FORMAT, "Gunzip: tail too short") {}};
//! \class CrcErr
//! \brief Exception thrown when a CRC error occurs
class CrcErr : public Err {public: CrcErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: CRC check error") {}};
//! \class LengthErr
//! \brief Exception thrown when a length error occurs
class LengthErr : public Err {public: LengthErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: length check error") {}};
//! \brief Construct a Gunzip decompressor
//! \param attachment an attached transformation
//! \param repeat decompress multiple compressed streams in series
//! \param autoSignalPropagation 0 to turn off MessageEnd signal
Gunzip(BufferedTransformation *attachment = NULL, bool repeat = false, int autoSignalPropagation = -1);
protected:
enum {
//! \brief First header magic value
MAGIC1=0x1f,
//! \brief Second header magic value
MAGIC2=0x8b,
//! \brief Deflated flag
DEFLATED=8
};
enum FLAG_MASKS {
CONTINUED=2, EXTRA_FIELDS=4, FILENAME=8, COMMENTS=16, ENCRYPTED=32};
unsigned int MaxPrestreamHeaderSize() const {return 1024;}
void ProcessPrestreamHeader();
void ProcessDecompressedData(const byte *string, size_t length);
unsigned int MaxPoststreamTailSize() const {return 8;}
void ProcessPoststreamTail();
word32 m_length;
CRC32 m_crc;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,52 @@
// hex.h - written and placed in the public domain by Wei Dai
//! \file hex.h
//! \brief Classes for HexEncoder and HexDecoder
#ifndef CRYPTOPP_HEX_H
#define CRYPTOPP_HEX_H
#include "cryptlib.h"
#include "basecode.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class HexEncoder
//! \brief Converts given data to base 16
class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter
{
public:
//! \brief Construct a HexEncoder
//! \param attachment a BufferedTrasformation to attach to this object
//! \param uppercase a flag indicating uppercase output
//! \param groupSize the size of the output grouping
//! \param separator the separator to use between groups
//! \param terminator the terminator append after processing
HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int groupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), groupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! \class HexDecoder
//! \brief Decode base 16 data back to bytes
class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder
{
public:
//! \brief Construct a HexDecoder
//! \param attachment a BufferedTrasformation to attach to this object
HexDecoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {}
void IsolatedInitialize(const NameValuePairs &parameters);
private:
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,109 @@
// hkdf.h - written and placed in public domain by Jeffrey Walton. Copyright assigned to Crypto++ project.
//! \file hkdf.h
//! \brief Classes for HKDF from RFC 5869
//! \since Crypto++ 5.6.3
#ifndef CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
#define CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
#include "cryptlib.h"
#include "hrtimer.h"
#include "secblock.h"
#include "hmac.h"
NAMESPACE_BEGIN(CryptoPP)
//! abstract base class for key derivation function
class KeyDerivationFunction
{
public:
//! maximum number of bytes which can be produced under a secuirty context
virtual size_t MaxDerivedKeyLength() const =0;
virtual bool Usesinfo() const =0;
//! derive a key from secret
virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info=NULL, size_t infoLen=0) const =0;
virtual ~KeyDerivationFunction() {}
};
//! \brief Extract-and-Expand Key Derivation Function (HKDF)
//! \tparam T HashTransformation class
//! \sa <A HREF="http://eprint.iacr.org/2010/264">Cryptographic Extraction and Key Derivation: The HKDF Scheme</A>
//! and <A HREF="http://tools.ietf.org/html/rfc5869">HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</A>
//! \since Crypto++ 5.6.3
template <class T>
class HKDF : public KeyDerivationFunction
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = T::DIGESTSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = T::DIGESTSIZE)
static const char* StaticAlgorithmName () {
static const std::string name(std::string("HKDF(") + std::string(T::StaticAlgorithmName()) + std::string(")"));
return name.c_str();
}
size_t MaxDerivedKeyLength() const {return static_cast<size_t>(T::DIGESTSIZE) * 255;}
bool Usesinfo() const {return true;}
unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const;
protected:
// If salt is missing (NULL), then use the NULL vector. Missing is different than EMPTY (0 length). The length
// of s_NullVector used depends on the Hash function. SHA-256 will use 32 bytes of s_NullVector.
typedef byte NullVectorType[SALTSIZE];
static const NullVectorType& GetNullVector() {
static const NullVectorType s_NullVector = {0};
return s_NullVector;
}
};
template <class T>
unsigned int HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const
{
static const size_t DIGEST_SIZE = static_cast<size_t>(T::DIGESTSIZE);
const unsigned int req = static_cast<unsigned int>(derivedLen);
CRYPTOPP_ASSERT(secret && secretLen);
CRYPTOPP_ASSERT(derived && derivedLen);
CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
if (derivedLen > MaxDerivedKeyLength())
throw InvalidArgument("HKDF: derivedLen must be less than or equal to MaxDerivedKeyLength");
HMAC<T> hmac;
FixedSizeSecBlock<byte, DIGEST_SIZE> prk, buffer;
// Extract
const byte* key = (salt ? salt : GetNullVector());
const size_t klen = (salt ? saltLen : DIGEST_SIZE);
hmac.SetKey(key, klen);
hmac.CalculateDigest(prk, secret, secretLen);
// Expand
hmac.SetKey(prk.data(), prk.size());
byte block = 0;
while (derivedLen > 0)
{
if (block++) {hmac.Update(buffer, buffer.size());}
if (info && infoLen) {hmac.Update(info, infoLen);}
hmac.CalculateDigest(buffer, &block, 1);
#if CRYPTOPP_MSC_VERSION
const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
memcpy_s(derived, segmentLen, buffer, segmentLen);
#else
const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
std::memcpy(derived, buffer, segmentLen);
#endif
derived += segmentLen;
derivedLen -= segmentLen;
}
return req;
}
NAMESPACE_END
#endif // CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H

View File

@ -0,0 +1,75 @@
// hmac.h - written and placed in the public domain by Wei Dai
//! \file hmac.h
//! \brief Classes for HMAC message authentication codes
#ifndef CRYPTOPP_HMAC_H
#define CRYPTOPP_HMAC_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class HMAC_Base
//! \brief HMAC information
//! \details HMAC_Base derives from VariableKeyLength and MessageAuthenticationCode
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HMAC_Base : public VariableKeyLength<16, 0, INT_MAX>, public MessageAuthenticationCode
{
public:
//! \brief Construct a HMAC_Base
HMAC_Base() : m_innerHashKeyed(false) {}
void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
void Restart();
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int OptimalBlockSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().OptimalBlockSize();}
unsigned int DigestSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().DigestSize();}
protected:
virtual HashTransformation & AccessHash() =0;
byte * AccessIpad() {return m_buf;}
byte * AccessOpad() {return m_buf + AccessHash().BlockSize();}
byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();}
private:
void KeyInnerHash();
SecByteBlock m_buf;
bool m_innerHashKeyed;
};
//! \class HMAC
//! \brief HMAC
//! \tparam T HashTransformation derived class
//! \details HMAC derives from MessageAuthenticationCodeImpl. It calculates the HMAC using
//! <tt>HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text))</tt>.
//! \sa <a href="http://www.weidai.com/scan-mirror/mac.html#HMAC">HMAC</a>
template <class T>
class HMAC : public MessageAuthenticationCodeImpl<HMAC_Base, HMAC<T> >
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
//! \brief Construct a HMAC
HMAC() {}
//! \brief Construct a HMAC
//! \param key the HMAC key
//! \param length the size of the HMAC key
HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";}
std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";}
private:
HashTransformation & AccessHash() {return m_hash;}
T m_hash;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,312 @@
// hmqv.h - written and placed in the public domain by Uri Blumenthal
// Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files
#ifndef CRYPTOPP_HMQV_H
#define CRYPTOPP_HMQV_H
//! \file hmqv.h
//! \brief Classes for Hashed Menezes-Qu-Vanstone key agreement in GF(p)
//! \since Crypto++ 5.6.4
#include "gfpcrypt.h"
#include "algebra.h"
#include "sha.h"
NAMESPACE_BEGIN(CryptoPP)
//! \brief Hashed Menezes-Qu-Vanstone in GF(p)
//! \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
//! Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
//! \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain
//! \since Crypto++ 5.6.4
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
class HMQV_Domain: public AuthenticatedKeyAgreementDomain
{
public:
typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element;
typedef HMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~HMQV_Domain() {}
#endif
HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
HMQV_Domain(const GroupParameters &params, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
HMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.BERDecode(bt);}
template <class T1>
HMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1);}
template <class T1, class T2>
HMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2);}
template <class T1, class T2, class T3>
HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3);}
template <class T1, class T2, class T3, class T4>
HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
GroupParameters & AccessGroupParameters(){return m_groupParameters;}
CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
//! return length of agreed value produced
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
//! return length of static private keys in this domain
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
//! return length of static public keys in this domain
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
//! generate static private key
/*! \pre size of privateKey == PrivateStaticKeyLength() */
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
//! generate static public key
/*! \pre size of publicKey == PublicStaticKeyLength() */
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
//! return length of ephemeral private keys in this domain
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
}
//! return length of ephemeral public keys in this domain
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
/*! \note The ephemeral public key will always be validated.
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
\pre size of agreedValue == AgreedValueLength()
\pre length of staticPrivateKey == StaticPrivateKeyLength()
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
\pre length of staticOtherPublicKey == StaticPublicKeyLength()
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
*/
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const
{
byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL;
size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
// Depending on the role, this will hold either A's or B's static
// (long term) public key. AA or BB will then point into tt.
SecByteBlock tt(StaticPublicKeyLength());
try
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer)
{
Integer b(staticPrivateKey, StaticPrivateKeyLength());
Element B = params.ExponentiateBase(b);
params.EncodeElement(true, B, tt);
XX = const_cast<byte*>(ephemeralOtherPublicKey);
xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
yys = EphemeralPublicKeyLength();
AA = const_cast<byte*>(staticOtherPublicKey);
aas = StaticPublicKeyLength();
BB = tt.BytePtr();
bbs = tt.SizeInBytes();
}
else if(m_role == RoleClient)
{
Integer a(staticPrivateKey, StaticPrivateKeyLength());
Element A = params.ExponentiateBase(a);
params.EncodeElement(true, A, tt);
XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralOtherPublicKey);
yys = EphemeralPublicKeyLength();
AA = tt.BytePtr();
aas = tt.SizeInBytes();
BB = const_cast<byte*>(staticOtherPublicKey);
bbs = StaticPublicKeyLength();
}
else
{
CRYPTOPP_ASSERT(0);
return false;
}
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. If the other's PublicKey is
// requested to be validated, we manually call ValidateElement at level 3.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL))
return false;
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULL))
return false;
// const Integer& p = params.GetGroupOrder(); // not used, remove later
const Integer& q = params.GetSubgroupOrder();
const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
Integer d, e;
SecByteBlock dd(len), ee(len);
// Compute $d = \hat{H}(X, \hat{B})$
Hash(NULL, XX, xxs, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
d.Decode(dd.BytePtr(), dd.SizeInBytes());
// Compute $e = \hat{H}(Y, \hat{A})$
Hash(NULL, YY, yys, AA, aas, ee.BytePtr(), ee.SizeInBytes());
e.Decode(ee.BytePtr(), ee.SizeInBytes());
Element sigma;
if(m_role == RoleServer)
{
Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer b(staticPrivateKey, StaticPrivateKeyLength());
Integer s_B = (y + e * b) % q;
Element A = params.DecodeElement(AA, false);
Element X = params.DecodeElement(XX, false);
Element t1 = params.ExponentiateElement(A, d);
Element t2 = m_groupParameters.MultiplyElements(X, t1);
// $\sigma_B}=(X \cdot A^{d})^{s_B}
sigma = params.ExponentiateElement(t2, s_B);
}
else
{
Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer a(staticPrivateKey, StaticPrivateKeyLength());
Integer s_A = (x + d * a) % q;
Element B = params.DecodeElement(BB, false);
Element Y = params.DecodeElement(YY, false);
Element t1 = params.ExponentiateElement(B, e);
Element t2 = m_groupParameters.MultiplyElements(Y, t1);
// $\sigma_A}=(Y \cdot B^{e})^{s_A}
sigma = params.ExponentiateElement(t2, s_A);
}
Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength());
}
catch (DL_BadElement &)
{
return false;
}
return true;
}
protected:
// Hash invocation by client and server differ only in what keys
// each provides.
inline void Hash(const Element* sigma,
const byte* e1, size_t e1len, // Ephemeral key and key length
const byte* s1, size_t s1len, // Static key and key length
byte* digest, size_t dlen) const
{
HASH hash;
size_t idx = 0, req = dlen;
size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE);
if(sigma)
{
if (e1len != 0 || s1len != 0) {
CRYPTOPP_ASSERT(0);
}
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
} else {
if (e1len == 0 || s1len == 0) {
CRYPTOPP_ASSERT(0);
}
hash.Update(e1, e1len);
hash.Update(s1, s1len);
}
hash.TruncatedFinal(digest, blk);
req -= blk;
// All this to catch tail bytes for large curves and small hashes
while(req != 0)
{
hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
idx += (size_t)HASH::DIGESTSIZE;
blk = STDMIN(req, (size_t)HASH::DIGESTSIZE);
hash.TruncatedFinal(&digest[idx], blk);
req -= blk;
}
}
private:
// The paper uses Initiator and Recipient - make it classical.
enum KeyAgreementRole{ RoleServer = 1, RoleClient };
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
GroupParameters m_groupParameters;
KeyAgreementRole m_role;
};
//! \brief Hashed Menezes-Qu-Vanstone in GF(p)
//! \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
//! Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
//! \sa HMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
//! \since Crypto++ 5.6.4
typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HMQV;
NAMESPACE_END
#endif

View File

@ -0,0 +1,67 @@
#ifndef CRYPTOPP_HRTIMER_H
#define CRYPTOPP_HRTIMER_H
#include "config.h"
#if !defined(HIGHRES_TIMER_AVAILABLE) || (defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE))
#include <time.h>
#endif
NAMESPACE_BEGIN(CryptoPP)
#ifdef HIGHRES_TIMER_AVAILABLE
typedef word64 TimerWord;
#else
typedef clock_t TimerWord;
#endif
//! \class TimerBase
//! \brief Base class for timers
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
{
public:
enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
TimerBase(Unit unit, bool stuckAtZero)
: m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false)
, m_start(0), m_last(0) {}
virtual TimerWord GetCurrentTimerValue() =0; // GetCurrentTime is a macro in MSVC 6.0
virtual TimerWord TicksPerSecond() =0; // this is not the resolution, just a conversion factor into seconds
void StartTimer();
double ElapsedTimeAsDouble();
unsigned long ElapsedTime();
private:
double ConvertTo(TimerWord t, Unit unit);
Unit m_timerUnit; // HPUX workaround: m_unit is a system macro on HPUX
bool m_stuckAtZero, m_started;
TimerWord m_start, m_last;
};
//! \class ThreadUserTimer
//! \brief Measure CPU time spent executing instructions of this thread (if supported by OS)
//! \note ThreadUserTimer only works correctly on Windows NT or later desktops and servers.
//! On Unix-based it reports process time. On Windows Phone and Windows Store it reports wall
//! clock time with performance counter precision. On all others it reports wall clock time.
class ThreadUserTimer : public TimerBase
{
public:
ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
TimerWord GetCurrentTimerValue();
TimerWord TicksPerSecond();
};
//! high resolution timer
class CRYPTOPP_DLL Timer : public TimerBase
{
public:
Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
TimerWord GetCurrentTimerValue();
TimerWord TicksPerSecond();
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,161 @@
// ida.h - written and placed in the public domain by Wei Dai
//! \file ida.h
//! \brief Classes for Information Dispersal Algorithm (IDA)
#ifndef CRYPTOPP_IDA_H
#define CRYPTOPP_IDA_H
#include "cryptlib.h"
#include "mqueue.h"
#include "filters.h"
#include "channels.h"
#include "secblock.h"
#include "stdcpp.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
/// base class for secret sharing and information dispersal
class RawIDA : public AutoSignaling<Unflushable<Multichannel<Filter> > >
{
public:
RawIDA(BufferedTransformation *attachment=NULL)
: m_threshold (0), m_channelsReady(0), m_channelsFinished(0)
{Detach(attachment);}
unsigned int GetThreshold() const {return m_threshold;}
void AddOutputChannel(word32 channelId);
void ChannelData(word32 channelId, const byte *inString, size_t length, bool messageEnd);
lword InputBuffered(word32 channelId) const;
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
{
if (!blocking)
throw BlockingInputOnly("RawIDA");
ChannelData(StringToWord<word32>(channel), begin, length, messageEnd != 0);
return 0;
}
protected:
virtual void FlushOutputQueues();
virtual void OutputMessageEnds();
unsigned int InsertInputChannel(word32 channelId);
unsigned int LookupInputChannel(word32 channelId) const;
void ComputeV(unsigned int);
void PrepareInterpolation();
void ProcessInputQueues();
typedef std::map<word32, unsigned int> InputChannelMap;
InputChannelMap m_inputChannelMap;
InputChannelMap::iterator m_lastMapPosition;
std::vector<MessageQueue> m_inputQueues;
std::vector<word32> m_inputChannelIds, m_outputChannelIds, m_outputToInput;
std::vector<std::string> m_outputChannelIdStrings;
std::vector<ByteQueue> m_outputQueues;
int m_threshold;
unsigned int m_channelsReady, m_channelsFinished;
std::vector<SecBlock<word32> > m_v;
SecBlock<word32> m_u, m_w, m_y;
};
/// a variant of Shamir's Secret Sharing Algorithm
class SecretSharing : public CustomFlushPropagation<Filter>
{
public:
SecretSharing(RandomNumberGenerator &rng, int threshold, int nShares, BufferedTransformation *attachment=NULL, bool addPadding=true)
: m_rng(rng), m_ida(new OutputProxy(*this, true))
{
Detach(attachment);
IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding));
}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);}
protected:
RandomNumberGenerator &m_rng;
RawIDA m_ida;
bool m_pad;
};
/// a variant of Shamir's Secret Sharing Algorithm
class SecretRecovery : public RawIDA
{
public:
SecretRecovery(int threshold, BufferedTransformation *attachment=NULL, bool removePadding=true)
: RawIDA(attachment)
{IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
protected:
void FlushOutputQueues();
void OutputMessageEnds();
bool m_pad;
};
/// a variant of Rabin's Information Dispersal Algorithm
class InformationDispersal : public CustomFlushPropagation<Filter>
{
public:
InformationDispersal(int threshold, int nShares, BufferedTransformation *attachment=NULL, bool addPadding=true)
: m_ida(new OutputProxy(*this, true)), m_pad(false), m_nextChannel(0)
{
Detach(attachment);
IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding));
}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);}
protected:
RawIDA m_ida;
bool m_pad;
unsigned int m_nextChannel;
};
/// a variant of Rabin's Information Dispersal Algorithm
class InformationRecovery : public RawIDA
{
public:
InformationRecovery(int threshold, BufferedTransformation *attachment=NULL, bool removePadding=true)
: RawIDA(attachment), m_pad(false)
{IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
protected:
void FlushOutputQueues();
void OutputMessageEnds();
bool m_pad;
ByteQueue m_queue;
};
class PaddingRemover : public Unflushable<Filter>
{
public:
PaddingRemover(BufferedTransformation *attachment=NULL)
: m_possiblePadding(false), m_zeroCount(0) {Detach(attachment);}
void IsolatedInitialize(const NameValuePairs &parameters)
{CRYPTOPP_UNUSED(parameters); m_possiblePadding = false;}
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
// GetPossiblePadding() == false at the end of a message indicates incorrect padding
bool GetPossiblePadding() const {return m_possiblePadding;}
private:
bool m_possiblePadding;
lword m_zeroCount;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,66 @@
// idea.h - written and placed in the public domain by Wei Dai
//! \file idea.h
//! \brief Classes for the IDEA block cipher
#ifndef CRYPTOPP_IDEA_H
#define CRYPTOPP_IDEA_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class IDEA_Info
//! \brief IDEA block cipher information
struct IDEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public FixedRounds<8>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "IDEA";}
};
//! \class IDEA
//! \brief IDEA block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#IDEA">IDEA</a>
class IDEA : public IDEA_Info, public BlockCipherDocumentation
{
public: // made public for internal purposes
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
typedef word Word;
#else
typedef hword Word;
#endif
private:
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<IDEA_Info>
{
public:
unsigned int OptimalDataAlignment() const {return 2;}
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
private:
void EnKey(const byte *);
void DeKey();
FixedSizeSecBlock<Word, 6*ROUNDS+4> m_key;
#ifdef IDEA_LARGECACHE
static inline void LookupMUL(word &a, word b);
void LookupKeyLogs();
static void BuildLogTables();
static volatile bool tablesBuilt;
static word16 log[0x10000], antilog[0x10000];
#endif
};
public:
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
};
typedef IDEA::Encryption IDEAEncryption;
typedef IDEA::Decryption IDEADecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,614 @@
// integer.h - written and placed in the public domain by Wei Dai
//! \file integer.h
//! \brief Multiple precision integer with arithmetic operations
//! \details The Integer class can represent positive and negative integers
//! with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
//! \details Internally, the library uses a sign magnitude representation, and the class
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
//! used to hold the representation. The second is a Sign, and its is used to track
//! the sign of the Integer.
#ifndef CRYPTOPP_INTEGER_H
#define CRYPTOPP_INTEGER_H
#include "cryptlib.h"
#include "secblock.h"
#include "stdcpp.h"
#include <iosfwd>
NAMESPACE_BEGIN(CryptoPP)
//! \struct InitializeInteger
//! Performs static intialization of the Integer class
struct InitializeInteger
{
InitializeInteger();
};
// http://github.com/weidai11/cryptopp/issues/256
#if defined(CRYPTOPP_WORD128_AVAILABLE)
typedef SecBlock<word, AllocatorWithCleanup<word, true> > IntegerSecBlock;
#else
typedef SecBlock<word, AllocatorWithCleanup<word, CRYPTOPP_BOOL_X86> > IntegerSecBlock;
#endif
//! \brief Multiple precision integer with arithmetic operations
//! \details The Integer class can represent positive and negative integers
//! with absolute value less than (256**sizeof(word))<sup>(256**sizeof(int))</sup>.
//! \details Internally, the library uses a sign magnitude representation, and the class
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
//! used to hold the representation. The second is a Sign, and its is used to track
//! the sign of the Integer.
//! \nosubgrouping
class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object
{
public:
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS
//@{
//! \brief Exception thrown when division by 0 is encountered
class DivideByZero : public Exception
{
public:
DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {}
};
//! \brief Exception thrown when a random number cannot be found that
//! satisfies the condition
class RandomNumberNotFound : public Exception
{
public:
RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {}
};
//! \enum Sign
//! \brief Used internally to represent the integer
//! \details Sign is used internally to represent the integer. It is also used in a few API functions.
//! \sa Signedness
enum Sign {
//! \brief the value is positive or 0
POSITIVE=0,
//! \brief the value is negative
NEGATIVE=1};
//! \enum Signedness
//! \brief Used when importing and exporting integers
//! \details Signedness is usually used in API functions.
//! \sa Sign
enum Signedness {
//! \brief an unsigned value
UNSIGNED,
//! \brief a signed value
SIGNED};
//! \enum RandomNumberType
//! \brief Properties of a random integer
enum RandomNumberType {
//! \brief a number with no special properties
ANY,
//! \brief a number which is probabilistically prime
PRIME};
//@}
//! \name CREATORS
//@{
//! \brief Creates the zero integer
Integer();
//! copy constructor
Integer(const Integer& t);
//! \brief Convert from signed long
Integer(signed long value);
//! \brief Convert from lword
//! \param sign enumeration indicating Sign
//! \param value the long word
Integer(Sign sign, lword value);
//! \brief Convert from two words
//! \param sign enumeration indicating Sign
//! \param highWord the high word
//! \param lowWord the low word
Integer(Sign sign, word highWord, word lowWord);
//! \brief Convert from a C-string
//! \param str C-string value
//! \param order byte order
//! \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case
//! insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10.
//! \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
//! integers with curve25519, Poly1305 and Microsoft CAPI.
explicit Integer(const char *str, ByteOrder order = BIG_ENDIAN_ORDER);
//! \brief Convert from a wide C-string
//! \param str wide C-string value
//! \param order byte order
//! \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case
//! insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10.
//! \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
//! integers with curve25519, Poly1305 and Microsoft CAPI.
explicit Integer(const wchar_t *str, ByteOrder order = BIG_ENDIAN_ORDER);
//! \brief Convert from a big-endian byte array
//! \param encodedInteger big-endian byte array
//! \param byteCount length of the byte array
//! \param sign enumeration indicating Signedness
//! \param order byte order
//! \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
//! integers with curve25519, Poly1305 and Microsoft CAPI.
Integer(const byte *encodedInteger, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER);
//! \brief Convert from a big-endian array
//! \param bt BufferedTransformation object with big-endian byte array
//! \param byteCount length of the byte array
//! \param sign enumeration indicating Signedness
//! \param order byte order
//! \details Byte order was added at Crypto++ 5.7 to allow use of little-endian
//! integers with curve25519, Poly1305 and Microsoft CAPI.
Integer(BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER);
//! \brief Convert from a BER encoded byte array
//! \param bt BufferedTransformation object with BER encoded byte array
explicit Integer(BufferedTransformation &bt);
//! \brief Create a random integer
//! \param rng RandomNumberGenerator used to generate material
//! \param bitCount the number of bits in the resulting integer
//! \details The random integer created is uniformly distributed over <tt>[0, 2<sup>bitCount</sup>]</tt>.
Integer(RandomNumberGenerator &rng, size_t bitCount);
//! \brief Integer representing 0
//! \returns an Integer representing 0
//! \details Zero() avoids calling constructors for frequently used integers
static const Integer & CRYPTOPP_API Zero();
//! \brief Integer representing 1
//! \returns an Integer representing 1
//! \details One() avoids calling constructors for frequently used integers
static const Integer & CRYPTOPP_API One();
//! \brief Integer representing 2
//! \returns an Integer representing 2
//! \details Two() avoids calling constructors for frequently used integers
static const Integer & CRYPTOPP_API Two();
//! \brief Create a random integer of special form
//! \param rng RandomNumberGenerator used to generate material
//! \param min the minimum value
//! \param max the maximum value
//! \param rnType RandomNumberType to specify the type
//! \param equiv the equivalence class based on the parameter \p mod
//! \param mod the modulus used to reduce the equivalence class
//! \throw RandomNumberNotFound if the set is empty.
//! \details Ideally, the random integer created should be uniformly distributed
//! over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
//! However the actual distribution may not be uniform because sequential
//! search is used to find an appropriate number from a random starting
//! point.
//! \details May return (with very small probability) a pseudoprime when a prime
//! is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
//! is declared in nbtheory.h.
Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One());
//! \brief Exponentiates to a power of 2
//! \returns the Integer 2<sup>e</sup>
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
static Integer CRYPTOPP_API Power2(size_t e);
//@}
//! \name ENCODE/DECODE
//@{
//! \brief The minimum number of bytes to encode this integer
//! \param sign enumeration indicating Signedness
//! \note The MinEncodedSize() of 0 is 1.
size_t MinEncodedSize(Signedness sign=UNSIGNED) const;
//! \brief Encode in big-endian format
//! \param output big-endian byte array
//! \param outputLen length of the byte array
//! \param sign enumeration indicating Signedness
//! \details Unsigned means encode absolute value, signed means encode two's complement if negative.
//! \details outputLen can be used to ensure an Integer is encoded to an exact size (rather than a
//! minimum size). An exact size is useful, for example, when encoding to a field element size.
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const;
//! \brief Encode in big-endian format
//! \param bt BufferedTransformation object
//! \param outputLen length of the encoding
//! \param sign enumeration indicating Signedness
//! \details Unsigned means encode absolute value, signed means encode two's complement if negative.
//! \details outputLen can be used to ensure an Integer is encoded to an exact size (rather than a
//! minimum size). An exact size is useful, for example, when encoding to a field element size.
void Encode(BufferedTransformation &bt, size_t outputLen, Signedness sign=UNSIGNED) const;
//! \brief Encode in DER format
//! \param bt BufferedTransformation object
//! \details Encodes the Integer using Distinguished Encoding Rules
//! The result is placed into a BufferedTransformation object
void DEREncode(BufferedTransformation &bt) const;
//! encode absolute value as big-endian octet string
//! \param bt BufferedTransformation object
//! \param length the number of mytes to decode
void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
//! \brief Encode absolute value in OpenPGP format
//! \param output big-endian byte array
//! \param bufferSize length of the byte array
//! \returns length of the output
//! \details OpenPGPEncode places result into a BufferedTransformation object and returns the
//! number of bytes used for the encoding
size_t OpenPGPEncode(byte *output, size_t bufferSize) const;
//! \brief Encode absolute value in OpenPGP format
//! \param bt BufferedTransformation object
//! \returns length of the output
//! \details OpenPGPEncode places result into a BufferedTransformation object and returns the
//! number of bytes used for the encoding
size_t OpenPGPEncode(BufferedTransformation &bt) const;
//! \brief Decode from big-endian byte array
//! \param input big-endian byte array
//! \param inputLen length of the byte array
//! \param sign enumeration indicating Signedness
void Decode(const byte *input, size_t inputLen, Signedness sign=UNSIGNED);
//! \brief Decode nonnegative value from big-endian byte array
//! \param bt BufferedTransformation object
//! \param inputLen length of the byte array
//! \param sign enumeration indicating Signedness
//! \note <tt>bt.MaxRetrievable() \>= inputLen</tt>.
void Decode(BufferedTransformation &bt, size_t inputLen, Signedness sign=UNSIGNED);
//! \brief Decode from BER format
//! \param input big-endian byte array
//! \param inputLen length of the byte array
void BERDecode(const byte *input, size_t inputLen);
//! \brief Decode from BER format
//! \param bt BufferedTransformation object
void BERDecode(BufferedTransformation &bt);
//! \brief Decode nonnegative value from big-endian octet string
//! \param bt BufferedTransformation object
//! \param length length of the byte array
void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
//! \brief Exception thrown when an error is encountered decoding an OpenPGP integer
class OpenPGPDecodeErr : public Exception
{
public:
OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {}
};
//! \brief Decode from OpenPGP format
//! \param input big-endian byte array
//! \param inputLen length of the byte array
void OpenPGPDecode(const byte *input, size_t inputLen);
//! \brief Decode from OpenPGP format
//! \param bt BufferedTransformation object
void OpenPGPDecode(BufferedTransformation &bt);
//@}
//! \name ACCESSORS
//@{
//! \brief Determines if the Integer is convertable to Long
//! \returns true if *this can be represented as a signed long
//! \sa ConvertToLong()
bool IsConvertableToLong() const;
//! \brief Convert the Integer to Long
//! \return equivalent signed long if possible, otherwise undefined
//! \sa IsConvertableToLong()
signed long ConvertToLong() const;
//! \brief Determines the number of bits required to represent the Integer
//! \returns number of significant bits = floor(log2(abs(*this))) + 1
unsigned int BitCount() const;
//! \brief Determines the number of bytes required to represent the Integer
//! \returns number of significant bytes = ceiling(BitCount()/8)
unsigned int ByteCount() const;
//! \brief Determines the number of words required to represent the Integer
//! \returns number of significant words = ceiling(ByteCount()/sizeof(word))
unsigned int WordCount() const;
//! \brief Provides the i-th bit of the Integer
//! \returns the i-th bit, i=0 being the least significant bit
bool GetBit(size_t i) const;
//! \brief Provides the i-th byte of the Integer
//! \returns the i-th byte
byte GetByte(size_t i) const;
//! \brief Provides the low order bits of the Integer
//! \returns n lowest bits of *this >> i
lword GetBits(size_t i, size_t n) const;
//! \brief Determines if the Integer is 0
//! \returns true if the Integer is 0, false otherwise
bool IsZero() const {return !*this;}
//! \brief Determines if the Integer is non-0
//! \returns true if the Integer is non-0, false otherwise
bool NotZero() const {return !IsZero();}
//! \brief Determines if the Integer is negative
//! \returns true if the Integer is negative, false otherwise
bool IsNegative() const {return sign == NEGATIVE;}
//! \brief Determines if the Integer is non-negative
//! \returns true if the Integer is non-negative, false otherwise
bool NotNegative() const {return !IsNegative();}
//! \brief Determines if the Integer is positive
//! \returns true if the Integer is positive, false otherwise
bool IsPositive() const {return NotNegative() && NotZero();}
//! \brief Determines if the Integer is non-positive
//! \returns true if the Integer is non-positive, false otherwise
bool NotPositive() const {return !IsPositive();}
//! \brief Determines if the Integer is even parity
//! \returns true if the Integer is even, false otherwise
bool IsEven() const {return GetBit(0) == 0;}
//! \brief Determines if the Integer is odd parity
//! \returns true if the Integer is odd, false otherwise
bool IsOdd() const {return GetBit(0) == 1;}
//@}
//! \name MANIPULATORS
//@{
//!
Integer& operator=(const Integer& t);
//!
Integer& operator+=(const Integer& t);
//!
Integer& operator-=(const Integer& t);
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer& operator*=(const Integer& t) {return *this = Times(t);}
//!
Integer& operator/=(const Integer& t) {return *this = DividedBy(t);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer& operator%=(const Integer& t) {return *this = Modulo(t);}
//!
Integer& operator/=(word t) {return *this = DividedBy(t);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer& operator%=(word t) {return *this = Integer(POSITIVE, 0, Modulo(t));}
//!
Integer& operator<<=(size_t);
//!
Integer& operator>>=(size_t);
//! \brief Set this Integer to random integer
//! \param rng RandomNumberGenerator used to generate material
//! \param bitCount the number of bits in the resulting integer
//! \details The random integer created is uniformly distributed over <tt>[0, 2<sup>bitCount</sup>]</tt>.
void Randomize(RandomNumberGenerator &rng, size_t bitCount);
//! \brief Set this Integer to random integer
//! \param rng RandomNumberGenerator used to generate material
//! \param min the minimum value
//! \param max the maximum value
//! \details The random integer created is uniformly distributed over <tt>[min, max]</tt>.
void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max);
//! \brief Set this Integer to random integer of special form
//! \param rng RandomNumberGenerator used to generate material
//! \param min the minimum value
//! \param max the maximum value
//! \param rnType RandomNumberType to specify the type
//! \param equiv the equivalence class based on the parameter \p mod
//! \param mod the modulus used to reduce the equivalence class
//! \throw RandomNumberNotFound if the set is empty.
//! \details Ideally, the random integer created should be uniformly distributed
//! over <tt>{x | min \<= x \<= max</tt> and \p x is of rnType and <tt>x \% mod == equiv}</tt>.
//! However the actual distribution may not be uniform because sequential
//! search is used to find an appropriate number from a random starting
//! point.
//! \details May return (with very small probability) a pseudoprime when a prime
//! is requested and <tt>max \> lastSmallPrime*lastSmallPrime</tt>. \p lastSmallPrime
//! is declared in nbtheory.h.
bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One());
bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs);
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
{
if (!GenerateRandomNoThrow(rng, params))
throw RandomNumberNotFound();
}
//! \brief Set the n-th bit to value
//! \details 0-based numbering.
void SetBit(size_t n, bool value=1);
//! \brief Set the n-th byte to value
//! \details 0-based numbering.
void SetByte(size_t n, byte value);
//! \brief Reverse the Sign of the Integer
void Negate();
//! \brief Sets the Integer to positive
void SetPositive() {sign = POSITIVE;}
//! \brief Sets the Integer to negative
void SetNegative() {if (!!(*this)) sign = NEGATIVE;}
//! \brief Swaps this Integer with another Integer
void swap(Integer &a);
//@}
//! \name UNARY OPERATORS
//@{
//!
bool operator!() const;
//!
Integer operator+() const {return *this;}
//!
Integer operator-() const;
//!
Integer& operator++();
//!
Integer& operator--();
//!
Integer operator++(int) {Integer temp = *this; ++*this; return temp;}
//!
Integer operator--(int) {Integer temp = *this; --*this; return temp;}
//@}
//! \name BINARY OPERATORS
//@{
//! \brief Perform signed comparison
//! \param a the Integer to comapre
//! \retval -1 if <tt>*this < a</tt>
//! \retval 0 if <tt>*this = a</tt>
//! \retval 1 if <tt>*this > a</tt>
int Compare(const Integer& a) const;
//!
Integer Plus(const Integer &b) const;
//!
Integer Minus(const Integer &b) const;
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer Times(const Integer &b) const;
//!
Integer DividedBy(const Integer &b) const;
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer Modulo(const Integer &b) const;
//!
Integer DividedBy(word b) const;
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
word Modulo(word b) const;
//!
Integer operator>>(size_t n) const {return Integer(*this)>>=n;}
//!
Integer operator<<(size_t n) const {return Integer(*this)<<=n;}
//@}
//! \name OTHER ARITHMETIC FUNCTIONS
//@{
//!
Integer AbsoluteValue() const;
//!
Integer Doubled() const {return Plus(*this);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer Squared() const {return Times(*this);}
//! extract square root, if negative return 0, else return floor of square root
Integer SquareRoot() const;
//! return whether this integer is a perfect square
bool IsSquare() const;
//! is 1 or -1
bool IsUnit() const;
//! return inverse if 1 or -1, otherwise return 0
Integer MultiplicativeInverse() const;
//! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d);
//! use a faster division algorithm when divisor is short
static void CRYPTOPP_API Divide(word &r, Integer &q, const Integer &a, word d);
//! returns same result as Divide(r, q, a, Power2(n)), but faster
static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n);
//! greatest common divisor
static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n);
//! calculate multiplicative inverse of *this mod n
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
Integer InverseMod(const Integer &n) const;
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
word InverseMod(word n) const;
//@}
//! \name INPUT/OUTPUT
//@{
//! \brief Extraction operator
//! \param in a reference to a std::istream
//! \param a a reference to an Integer
//! \returns a reference to a std::istream reference
friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a);
//!
//! \brief Insertion operator
//! \param out a reference to a std::ostream
//! \param a a constant reference to an Integer
//! \returns a reference to a std::ostream reference
//! \details The output integer responds to std::hex, std::oct, std::hex, std::upper and
//! std::lower. The output includes the suffix \a \b h (for hex), \a \b . (\a \b dot, for dec)
//! and \a \b o (for octal). There is currently no way to supress the suffix.
//! \details If you want to print an Integer without the suffix or using an arbitrary base, then
//! use IntToString<Integer>().
//! \sa IntToString<Integer>
friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a);
//@}
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
//! modular multiplication
CRYPTOPP_DLL friend Integer CRYPTOPP_API a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m);
//! modular exponentiation
CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m);
#endif
private:
Integer(word value, size_t length);
int PositiveCompare(const Integer &t) const;
IntegerSecBlock reg;
Sign sign;
#ifndef CRYPTOPP_DOXYGEN_PROCESSING
friend class ModularArithmetic;
friend class MontgomeryRepresentation;
friend class HalfMontgomeryRepresentation;
friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b);
friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b);
friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b);
friend void PositiveDivide(Integer &remainder, Integer &quotient, const Integer &dividend, const Integer &divisor);
#endif
};
//!
inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;}
//!
inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;}
//!
inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;}
//!
inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;}
//!
inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;}
//!
inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;}
//!
inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);}
//!
inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);}
//!
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);}
//!
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);}
//!
//! \sa a_times_b_mod_c() and a_exp_b_mod_c()
inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);}
NAMESPACE_END
#ifndef __BORLANDC__
NAMESPACE_BEGIN(std)
inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b)
{
a.swap(b);
}
NAMESPACE_END
#endif
#endif

View File

@ -0,0 +1,187 @@
#ifndef CRYPTOPP_ITERHASH_H
#define CRYPTOPP_ITERHASH_H
#include "cryptlib.h"
#include "secblock.h"
#include "misc.h"
#include "simple.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class HashInputTooLong
//! \brief Exception thrown when trying to hash more data than is allowed by a hash function
class CRYPTOPP_DLL HashInputTooLong : public InvalidDataFormat
{
public:
explicit HashInputTooLong(const std::string &alg)
: InvalidDataFormat("IteratedHashBase: input data exceeds maximum allowed by hash function " + alg) {}
};
//! \class IteratedHashBase
//! \brief Iterated hash base class
//! \tparam T Hash word type
//! \tparam BASE HashTransformation derived class
//! \details IteratedHashBase provides an interface for block-based iterated hashes
//! \sa HashTransformation, MessageAuthenticationCode
template <class T, class BASE>
class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE
{
public:
typedef T HashWordType;
//! \brief Construct an IteratedHashBase
IteratedHashBase() : m_countLo(0), m_countHi(0) {}
//! \brief Provides the input block size most efficient for this cipher.
//! \return The input block size that is most efficient for the cipher
//! \details The base class implementation returns MandatoryBlockSize().
//! \note Optimal input length is
//! <tt>n * OptimalBlockSize() - GetOptimalBlockSizeUsed()</tt> for any <tt>n \> 0</tt>.
unsigned int OptimalBlockSize() const {return this->BlockSize();}
//! \brief Provides input and output data alignment for optimal performance.
//! \return the input data alignment that provides optimal performance
//! \details OptimalDataAlignment returnes the natural alignment of the hash word.
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<T>();}
//! \brief Updates a hash with additional input
//! \param input the additional input as a buffer
//! \param length the size of the buffer, in bytes
void Update(const byte *input, size_t length);
//! \brief Requests space which can be written into by the caller
//! \param size the requested size of the buffer
//! \details The purpose of this method is to help avoid extra memory allocations.
//! \details size is an \a IN and \a OUT parameter and used as a hint. When the call is made,
//! size is the requested size of the buffer. When the call returns, size is the size of
//! the array returned to the caller.
//! \details The base class implementation sets size to 0 and returns NULL.
//! \note Some objects, like ArraySink, cannot create a space because its fixed.
byte * CreateUpdateSpace(size_t &size);
//! \brief Restart the hash
//! \details Discards the current state, and restart for a new message
void Restart();
//! \brief Computes the hash of the current message
//! \param digest a pointer to the buffer to receive the hash
//! \param digestSize the size of the truncated digest, in bytes
//! \details TruncatedFinal() call Final() and then copies digestSize bytes to digest.
//! The hash is restarted the hash for the next message.
void TruncatedFinal(byte *digest, size_t digestSize);
protected:
inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
inline T GetBitCountLo() const {return m_countLo << 3;}
void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
virtual void Init() =0;
virtual ByteOrder GetByteOrder() const =0;
virtual void HashEndianCorrectedBlock(const HashWordType *data) =0;
virtual size_t HashMultipleBlocks(const T *input, size_t length);
void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());}
virtual T* DataBuf() =0;
virtual T* StateBuf() =0;
private:
T m_countLo, m_countHi;
};
//! \class IteratedHash
//! \brief Iterated hash base class
//! \tparam T_HashWordType Hash word type
//! \tparam T_Endianness Endianness type of hash
//! \tparam T_BlockSize Block size of the hash
//! \tparam T_Base HashTransformation derived class
//! \details IteratedHash provides a default implementation for block-based iterated hashes
//! \sa HashTransformation, MessageAuthenticationCode
template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, class T_Base = HashTransformation>
class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase<T_HashWordType, T_Base>
{
public:
typedef T_Endianness ByteOrderClass;
typedef T_HashWordType HashWordType;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~IteratedHash() { }
#endif
CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize)
// BCB2006 workaround: can't use BLOCKSIZE here
CRYPTOPP_COMPILE_ASSERT((T_BlockSize & (T_BlockSize - 1)) == 0); // blockSize is a power of 2
//! \brief Provides the block size of the hash
//! \return the block size of the hash, in bytes
//! \details BlockSize() returns <tt>T_BlockSize</tt>.
unsigned int BlockSize() const {return T_BlockSize;}
//! \brief Provides the byte order of the hash
//! \returns the byte order of the hash as an enumeration
//! \details GetByteOrder() returns <tt>T_Endianness::ToEnum()</tt>.
//! \sa ByteOrder()
ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();}
//! \brief Adjusts the byte ordering of the hash
//! \param out the output buffer
//! \param in the input buffer
//! \param byteCount the size of the buffers, in bytes
//! \details CorrectEndianess() calls ConditionalByteReverse() using <tt>T_Endianness</tt>.
inline void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount)
{
ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount);
}
protected:
T_HashWordType* DataBuf() {return this->m_data;}
FixedSizeSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType)> m_data;
};
//! \class IteratedHashWithStaticTransform
//! \brief Iterated hash with a static transformation function
//! \tparam T_HashWordType Hash word type
//! \tparam T_Endianness Endianness type of hash
//! \tparam T_BlockSize Block size of the hash
//! \tparam T_StateSize Internal state size of the hash
//! \tparam T_Transform HashTransformation derived class
//! \tparam T_DigestSize Digest size of the hash
//! \tparam T_StateAligned Flag indicating if state is 16-byte aligned
//! \sa HashTransformation, MessageAuthenticationCode
template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, unsigned int T_StateSize, class T_Transform, unsigned int T_DigestSize = 0, bool T_StateAligned = false>
class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform
: public ClonableImpl<T_Transform, AlgorithmImpl<IteratedHash<T_HashWordType, T_Endianness, T_BlockSize>, T_Transform> >
{
public:
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~IteratedHashWithStaticTransform() { }
#endif
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize)
//! \brief Provides the digest size of the hash
//! \return the digest size of the hash, in bytes
//! \details DigestSize() returns <tt>DIGESTSIZE</tt>.
unsigned int DigestSize() const {return DIGESTSIZE;};
protected:
IteratedHashWithStaticTransform() {this->Init();}
void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);}
void Init() {T_Transform::InitState(this->m_state);}
T_HashWordType* StateBuf() {return this->m_state;}
FixedSizeAlignedSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType), T_StateAligned> m_state;
};
#ifndef __GNUC__
CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word64, HashTransformation>;
CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word64, MessageAuthenticationCode>;
CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word32, HashTransformation>;
CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word32, MessageAuthenticationCode>;
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,108 @@
// keccak.h - written and placed in the public domain by Wei Dai
//! \file keccak.h
//! \brief Classes for Keccak message digests
//! \details The Crypto++ Keccak implementation uses F1600 with XOF d=0x01.
//! FIPS 202 conformance (XOF d=0x06) is available in SHA3 classes.
//! \details Keccak will likely change in the future to accomodate extensibility of the
//! round function and the XOF functions.
//! \sa <a href="http://en.wikipedia.org/wiki/Keccak">Keccak</a>
//! \since Crypto++ 5.6.4
#ifndef CRYPTOPP_KECCAK_H
#define CRYPTOPP_KECCAK_H
#include "cryptlib.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class Keccak
//! \brief Keccak message digest base class
//! \details The Crypto++ Keccak implementation uses F1600 with XOF d=0x01.
//! FIPS 202 conformance (XOF d=0x06) is available in SHA3 classes.
//! \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
//! Library users should instantiate a derived class, and only use Keccak
//! as a base class reference or pointer.
//! \details Keccak will likely change in the future to accomodate extensibility of the
//! round function and the XOF functions.
//! \details Perform the following to specify a different digest size. The class will use F1600,
//! XOF d=0x01, and a new vaue for <tt>r()</tt> (which will be <tt>200-2*24 = 152</tt>).
//! <pre> Keccack_192 : public Keccack
//! {
//! public:
//! CRYPTOPP_CONSTANT(DIGESTSIZE = 24)
//! Keccack_192() : Keccack(DIGESTSIZE) {}
//! };
//! </pre>
//!
//! \sa SHA3, Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
//! \since Crypto++ 5.6.4
class Keccak : public HashTransformation
{
public:
//! \brief Construct a Keccak
//! \param digestSize the digest size, in bytes
//! \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
//! Library users should instantiate a derived class, and only use Keccak
//! as a base class reference or pointer.
//! \since Crypto++ 5.6.4
Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
unsigned int DigestSize() const {return m_digestSize;}
std::string AlgorithmName() const {return "Keccak-" + IntToString(m_digestSize*8);}
CRYPTOPP_CONSTEXPR static const char* StaticAlgorithmName() { return "Keccak"; }
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
void Update(const byte *input, size_t length);
void Restart();
void TruncatedFinal(byte *hash, size_t size);
//unsigned int BlockSize() const { return r(); } // that's the idea behind it
protected:
inline unsigned int r() const {return 200 - 2 * m_digestSize;}
FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter;
};
//! \class Keccak_224
//! \tparam DigestSize controls the digest size as a template parameter instead of a per-class constant
//! \brief Keccak-X message digest, template for more fine-grained typedefs
//! \since Crypto++ 5.7.0
template<unsigned int T_DigestSize>
class Keccak_Final : public Keccak
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
//! \brief Construct a Keccak-X message digest
Keccak_Final() : Keccak(DIGESTSIZE) {}
static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
unsigned int BlockSize() const { return BLOCKSIZE; }
private:
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
};
//! \class Keccak_224
//! \brief Keccak-224 message digest
//! \since Crypto++ 5.6.4
typedef Keccak_Final<28> Keccak_224;
//! \class Keccak_256
//! \brief Keccak-256 message digest
//! \since Crypto++ 5.6.4
typedef Keccak_Final<32> Keccak_256;
//! \class Keccak_384
//! \brief Keccak-384 message digest
//! \since Crypto++ 5.6.4
typedef Keccak_Final<48> Keccak_384;
//! \class Keccak_512
//! \brief Keccak-512 message digest
//! \since Crypto++ 5.6.4
typedef Keccak_Final<64> Keccak_512;
NAMESPACE_END
#endif

View File

@ -0,0 +1,144 @@
// lubyrack.h - written and placed in the public domain by Wei Dai
//! \file lubyrack.h
//! \brief Classes for the Luby-Rackoff block cipher
#ifndef CRYPTOPP_LUBYRACK_H
#define CRYPTOPP_LUBYRACK_H
#include "simple.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
template <class T> struct DigestSizeDoubleWorkaround // VC60 workaround
{
CRYPTOPP_CONSTANT(RESULT = 2*T::DIGESTSIZE)
};
//! \class LR_Info
//! \brief Luby-Rackoff block cipher information
template <class T>
struct LR_Info : public VariableKeyLength<16, 0, 2*(INT_MAX/2), 2>, public FixedBlockSize<DigestSizeDoubleWorkaround<T>::RESULT>
{
static std::string StaticAlgorithmName() {return std::string("LR/")+T::StaticAlgorithmName();}
};
//! \class LR
//! \brief Luby-Rackoff block cipher
template <class T>
class LR : public LR_Info<T>, public BlockCipherDocumentation
{
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<LR_Info<T> >
{
public:
// VC60 workaround: have to define these functions within class definition
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
{
this->AssertValidKeyLength(length);
L = length/2;
buffer.New(2*S);
digest.New(S);
key.Assign(userKey, 2*L);
}
protected:
CRYPTOPP_CONSTANT(S=T::DIGESTSIZE)
unsigned int L; // key length / 2
SecByteBlock key;
mutable T hm;
mutable SecByteBlock buffer, digest;
};
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
#define KL this->key
#define KR this->key+this->L
#define BL this->buffer
#define BR this->buffer+this->S
#define IL inBlock
#define IR inBlock+this->S
#define OL outBlock
#define OR outBlock+this->S
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
this->hm.Update(KL, this->L);
this->hm.Update(IL, this->S);
this->hm.Final(BR);
xorbuf(BR, IR, this->S);
this->hm.Update(KR, this->L);
this->hm.Update(BR, this->S);
this->hm.Final(BL);
xorbuf(BL, IL, this->S);
this->hm.Update(KL, this->L);
this->hm.Update(BL, this->S);
this->hm.Final(this->digest);
xorbuf(BR, this->digest, this->S);
this->hm.Update(KR, this->L);
this->hm.Update(OR, this->S);
this->hm.Final(this->digest);
xorbuf(BL, this->digest, this->S);
if (xorBlock)
xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
else
memcpy_s(outBlock, 2*this->S, this->buffer, 2*this->S);
}
};
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
this->hm.Update(KR, this->L);
this->hm.Update(IR, this->S);
this->hm.Final(BL);
xorbuf(BL, IL, this->S);
this->hm.Update(KL, this->L);
this->hm.Update(BL, this->S);
this->hm.Final(BR);
xorbuf(BR, IR, this->S);
this->hm.Update(KR, this->L);
this->hm.Update(BR, this->S);
this->hm.Final(this->digest);
xorbuf(BL, this->digest, this->S);
this->hm.Update(KL, this->L);
this->hm.Update(OL, this->S);
this->hm.Final(this->digest);
xorbuf(BR, this->digest, this->S);
if (xorBlock)
xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
else
memcpy(outBlock, this->buffer, 2*this->S);
}
#undef KL
#undef KR
#undef BL
#undef BR
#undef IL
#undef IR
#undef OL
#undef OR
};
public:
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,306 @@
#ifndef CRYPTOPP_LUC_H
#define CRYPTOPP_LUC_H
/** \file
*/
#include "cryptlib.h"
#include "gfpcrypt.h"
#include "integer.h"
#include "algebra.h"
#include "secblock.h"
#if CRYPTOPP_MSC_VERSION
# pragma warning(push)
# pragma warning(disable: 4127 4189)
#endif
#include "pkcspad.h"
#include "integer.h"
#include "oaep.h"
#include "dh.h"
#include <limits.h>
NAMESPACE_BEGIN(CryptoPP)
//! The LUC function.
/*! This class is here for historical and pedagogical interest. It has no
practical advantages over other trapdoor functions and probably shouldn't
be used in production software. The discrete log based LUC schemes
defined later in this .h file may be of more practical interest.
*/
class LUCFunction : public TrapdoorFunction, public PublicKey
{
typedef LUCFunction ThisClass;
public:
void Initialize(const Integer &n, const Integer &e)
{m_n = n; m_e = e;}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
Integer ApplyFunction(const Integer &x) const;
Integer PreimageBound() const {return m_n;}
Integer ImageBound() const {return m_n;}
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
// non-derived interface
const Integer & GetModulus() const {return m_n;}
const Integer & GetPublicExponent() const {return m_e;}
void SetModulus(const Integer &n) {m_n = n;}
void SetPublicExponent(const Integer &e) {m_e = e;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~LUCFunction() {}
#endif
protected:
Integer m_n, m_e;
};
//! _
class InvertibleLUCFunction : public LUCFunction, public TrapdoorFunctionInverse, public PrivateKey
{
typedef InvertibleLUCFunction ThisClass;
public:
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &eStart=17);
void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q, const Integer &u)
{m_n = n; m_e = e; m_p = p; m_q = q; m_u = u;}
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
void AssignFrom(const NameValuePairs &source);
/*! parameters: (ModulusSize, PublicExponent (default 17)) */
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
// non-derived interface
const Integer& GetPrime1() const {return m_p;}
const Integer& GetPrime2() const {return m_q;}
const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
void SetPrime1(const Integer &p) {m_p = p;}
void SetPrime2(const Integer &q) {m_q = q;}
void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~InvertibleLUCFunction() {}
#endif
protected:
Integer m_p, m_q, m_u;
};
struct LUC
{
static std::string StaticAlgorithmName() {return "LUC";}
typedef LUCFunction PublicKey;
typedef InvertibleLUCFunction PrivateKey;
};
//! LUC cryptosystem
template <class STANDARD>
struct LUCES : public TF_ES<STANDARD, LUC>
{
};
//! LUC signature scheme with appendix
template <class STANDARD, class H>
struct LUCSS : public TF_SS<STANDARD, H, LUC>
{
};
// analagous to the RSA schemes defined in PKCS #1 v2.0
typedef LUCES<OAEP<SHA> >::Decryptor LUCES_OAEP_SHA_Decryptor;
typedef LUCES<OAEP<SHA> >::Encryptor LUCES_OAEP_SHA_Encryptor;
typedef LUCSS<PKCS1v15, SHA>::Signer LUCSSA_PKCS1v15_SHA_Signer;
typedef LUCSS<PKCS1v15, SHA>::Verifier LUCSSA_PKCS1v15_SHA_Verifier;
// ********************************************************
// no actual precomputation
class DL_GroupPrecomputation_LUC : public DL_GroupPrecomputation<Integer>
{
public:
const AbstractGroup<Element> & GetGroup() const {CRYPTOPP_ASSERT(false); throw 0;}
Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);}
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);}
// non-inherited
void SetModulus(const Integer &v) {m_p = v;}
const Integer & GetModulus() const {return m_p;}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupPrecomputation_LUC() {}
#endif
private:
Integer m_p;
};
//! _
class DL_BasePrecomputation_LUC : public DL_FixedBasePrecomputation<Integer>
{
public:
// DL_FixedBasePrecomputation
bool IsInitialized() const {return m_g.NotZero();}
void SetBase(const DL_GroupPrecomputation<Element> &group, const Integer &base)
{CRYPTOPP_UNUSED(group); m_g = base;}
const Integer & GetBase(const DL_GroupPrecomputation<Element> &group) const
{CRYPTOPP_UNUSED(group); return m_g;}
void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage)
{CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(maxExpBits); CRYPTOPP_UNUSED(storage);}
void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation)
{CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(storedPrecomputation);}
void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const
{CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(storedPrecomputation);}
Integer Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
Integer CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Integer> &pc2, const Integer &exponent2) const
{
CRYPTOPP_UNUSED(group); CRYPTOPP_UNUSED(exponent); CRYPTOPP_UNUSED(pc2); CRYPTOPP_UNUSED(exponent2);
// shouldn't be called
throw NotImplemented("DL_BasePrecomputation_LUC: CascadeExponentiate not implemented");
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_BasePrecomputation_LUC() {}
#endif
private:
Integer m_g;
};
//! _
class DL_GroupParameters_LUC : public DL_GroupParameters_IntegerBasedImpl<DL_GroupPrecomputation_LUC, DL_BasePrecomputation_LUC>
{
public:
// DL_GroupParameters
bool IsIdentity(const Integer &element) const {return element == Integer::Two();}
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
Element MultiplyElements(const Element &a, const Element &b) const
{
CRYPTOPP_UNUSED(a); CRYPTOPP_UNUSED(b);
throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented");
}
Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
{
CRYPTOPP_UNUSED(element1); CRYPTOPP_UNUSED(exponent1); CRYPTOPP_UNUSED(element2); CRYPTOPP_UNUSED(exponent2);
throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented");
}
// NameValuePairs interface
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_LUC() {}
#endif
private:
int GetFieldType() const {return 2;}
};
//! _
class DL_GroupParameters_LUC_DefaultSafePrime : public DL_GroupParameters_LUC
{
public:
typedef NoCofactorMultiplication DefaultCofactorOption;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_GroupParameters_LUC_DefaultSafePrime() {}
#endif
protected:
unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
};
//! _
class DL_Algorithm_LUC_HMP : public DL_ElgamalLikeSignatureAlgorithm<Integer>
{
public:
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "LUC-HMP";}
void Sign(const DL_GroupParameters<Integer> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const;
bool Verify(const DL_GroupParameters<Integer> &params, const DL_PublicKey<Integer> &publicKey, const Integer &e, const Integer &r, const Integer &s) const;
size_t RLen(const DL_GroupParameters<Integer> &params) const
{return params.GetGroupOrder().ByteCount();}
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_Algorithm_LUC_HMP() {}
#endif
};
//! _
struct DL_SignatureKeys_LUC
{
typedef DL_GroupParameters_LUC GroupParameters;
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_SignatureKeys_LUC() {}
#endif
};
//! LUC-HMP, based on "Digital signature schemes based on Lucas functions" by Patrick Horster, Markus Michels, Holger Petersen
template <class H>
struct LUC_HMP : public DL_SS<DL_SignatureKeys_LUC, DL_Algorithm_LUC_HMP, DL_SignatureMessageEncodingMethod_DSA, H>
{
};
//! _
struct DL_CryptoKeys_LUC
{
typedef DL_GroupParameters_LUC_DefaultSafePrime GroupParameters;
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~DL_CryptoKeys_LUC() {}
#endif
};
//! LUC-IES
template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
struct LUC_IES
: public DL_ES<
DL_CryptoKeys_LUC,
DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
LUC_IES<> >
{
static std::string StaticAlgorithmName() {return "LUC-IES";} // non-standard name
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~LUC_IES() {}
#endif
};
// ********************************************************
//! LUC-DH
typedef DH_Domain<DL_GroupParameters_LUC_DefaultSafePrime> LUC_DH;
NAMESPACE_END
#if CRYPTOPP_MSC_VERSION
# pragma warning(pop)
#endif
#endif

View File

@ -0,0 +1,59 @@
// mars.h - written and placed in the public domain by Wei Dai
//! \file mars.h
//! \brief Classes for the MARS block cipher (IBM AES submission)
#ifndef CRYPTOPP_MARS_H
#define CRYPTOPP_MARS_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class MARS_Info
//! \brief MARS block cipher information
struct MARS_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 56, 8>
{
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "MARS";}
};
//! \class MARS
//! \brief MARS block cipher
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#MARS">MARS</a>
class MARS : public MARS_Info, public BlockCipherDocumentation
{
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<MARS_Info>
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
protected:
static const word32 Sbox[512];
FixedSizeSecBlock<word32, 40> m_k;
};
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
public:
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
typedef MARS::Encryption MARSEncryption;
typedef MARS::Decryption MARSDecryption;
NAMESPACE_END
#endif

View File

@ -0,0 +1,46 @@
#ifndef CRYPTOPP_MD2_H
#define CRYPTOPP_MD2_H
#include "cryptlib.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
namespace Weak1 {
/// <a href="http://www.cryptolounge.org/wiki/MD2">MD2</a>
class MD2 : public HashTransformation
{
public:
MD2();
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
unsigned int BlockSize() const {return BLOCKSIZE;}
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "MD2";}
CRYPTOPP_CONSTANT(DIGESTSIZE = 16)
CRYPTOPP_CONSTANT(BLOCKSIZE = 16)
private:
void Transform();
void Init();
SecByteBlock m_X, m_C, m_buf;
unsigned int m_count;
};
}
#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
#else
using namespace Weak1; // import Weak1 into CryptoPP with warning
#ifdef __GNUC__
#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
#else
#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
#endif
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,35 @@
#ifndef CRYPTOPP_MD4_H
#define CRYPTOPP_MD4_H
#include "iterhash.h"
NAMESPACE_BEGIN(CryptoPP)
namespace Weak1 {
//! <a href="http://www.weidai.com/scan-mirror/md.html#MD4">MD4</a>
/*! \warning MD4 is considered insecure, and should not be used
unless you absolutely need it for compatibility. */
class MD4 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, 16, MD4>
{
public:
static void InitState(HashWordType *state);
static void Transform(word32 *digest, const word32 *data);
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "MD4";}
};
}
#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
#else
using namespace Weak1; // import Weak1 into CryptoPP with warning
#ifdef __GNUC__
#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
#else
#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
#endif
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,33 @@
#ifndef CRYPTOPP_MD5_H
#define CRYPTOPP_MD5_H
#include "iterhash.h"
NAMESPACE_BEGIN(CryptoPP)
namespace Weak1 {
//! <a href="http://www.cryptolounge.org/wiki/MD5">MD5</a>
class MD5 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, 16, MD5>
{
public:
static void InitState(HashWordType *state);
static void Transform(word32 *digest, const word32 *data);
CRYPTOPP_CONSTEXPR static const char *StaticAlgorithmName() {return "MD5";}
};
}
#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
#else
using namespace Weak1; // import Weak1 into CryptoPP with warning
#ifdef __GNUC__
#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
#else
#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
#endif
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,79 @@
// mdc.h - written and placed in the public domain by Wei Dai
#ifndef CRYPTOPP_MDC_H
#define CRYPTOPP_MDC_H
//! \file mdc.h
//! \brief Classes for the MDC message digest
#include "seckey.h"
#include "secblock.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class MDC_Info
//! \brief MDC_Info cipher information
template <class T>
struct MDC_Info : public FixedBlockSize<T::DIGESTSIZE>, public FixedKeyLength<T::BLOCKSIZE>
{
static std::string StaticAlgorithmName() {return std::string("MDC/")+T::StaticAlgorithmName();}
};
//! \class MDC
//! \brief MDC cipher
//! \details MDC() is a construction by Peter Gutmann to turn an iterated hash function into a PRF
//! \sa <a href="http://www.weidai.com/scan-mirror/cs.html#MDC">MDC</a>
template <class T>
class MDC : public MDC_Info<T>
{
//! \class Enc
//! \brief MDC cipher encryption operation
class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl<MDC_Info<T> >
{
typedef typename T::HashWordType HashWordType;
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
{
this->AssertValidKeyLength(length);
memcpy_s(m_key, m_key.size(), userKey, this->KEYLENGTH);
T::CorrectEndianess(Key(), Key(), this->KEYLENGTH);
}
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
T::CorrectEndianess(Buffer(), (HashWordType *)inBlock, this->BLOCKSIZE);
T::Transform(Buffer(), Key());
if (xorBlock)
{
T::CorrectEndianess(Buffer(), Buffer(), this->BLOCKSIZE);
xorbuf(outBlock, xorBlock, m_buffer, this->BLOCKSIZE);
}
else
T::CorrectEndianess((HashWordType *)outBlock, Buffer(), this->BLOCKSIZE);
}
bool IsPermutation() const {return false;}
unsigned int OptimalDataAlignment() const {return sizeof(HashWordType);}
private:
HashWordType *Key() {return (HashWordType *)m_key.data();}
const HashWordType *Key() const {return (const HashWordType *)m_key.data();}
HashWordType *Buffer() const {return (HashWordType *)m_buffer.data();}
// VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup
FixedSizeSecBlock<byte, MDC_Info<T>::KEYLENGTH, AllocatorWithCleanup<byte> > m_key;
mutable FixedSizeSecBlock<byte, MDC_Info<T>::BLOCKSIZE, AllocatorWithCleanup<byte> > m_buffer;
};
public:
//! use BlockCipher interface
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,212 @@
// mersenne.h - written and placed in public domain by Jeffrey Walton.
// Copyright assigned to Crypto++ project.
//! \file mersenne.h
//! \brief Class file for Mersenne Twister
//! \warning MersenneTwister is suitable for Monte-Carlo simulations, where uniformaly distrubuted
//! numbers are required quickly. It should not be used for cryptographic purposes.
//! \since Crypto++ 5.6.3
#ifndef CRYPTOPP_MERSENNE_TWISTER_H
#define CRYPTOPP_MERSENNE_TWISTER_H
#include "cryptlib.h"
#include "secblock.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class MersenneTwister
//! \brief Mersenne Twister class for Monte-Carlo simulations
//! \tparam K Magic constant
//! \tparam M Period parameter
//! \tparam N Size of the state vector
//! \tparam F Multiplier constant
//! \tparam S Initial seed
//! \details Provides the MersenneTwister implementation. The class is a header-only implementation.
//! \warning MersenneTwister is suitable for simulations, where uniformaly distrubuted numbers are
//! required quickly. It should not be used for cryptographic purposes.
//! \sa MT19937, MT19937ar
//! \since Crypto++ 5.6.3
template <unsigned int K, unsigned int M, unsigned int N, unsigned int F, unsigned long S>
class MersenneTwister : public RandomNumberGenerator
{
public:
//! \brief Construct a Mersenne Twister
//! \param seed 32-bit seed
//! \details Defaults to template parameter S due to changing algorithm
//! parameters over time
MersenneTwister(unsigned long seed = S) : m_seed(seed), m_idx(N)
{
m_state[0] = seed;
for (unsigned int i = 1; i < N+1; i++)
m_state[i] = word32(F * (m_state[i-1] ^ (m_state[i-1] >> 30)) + i);
}
//! \brief Generate random array of bytes
//! \param output byte buffer
//! \param size length of the buffer, in bytes
//! \details Bytes are written to output in big endian order. If output length
//! is not a multiple of word32, then unused bytes are not accumulated for subsequent
//! calls to GenerateBlock. Rather, the unused tail bytes are discarded, and the
//! stream is continued at the next word32 boundary from the state array.
void GenerateBlock(byte *output, size_t size)
{
// Handle word32 size blocks
word32 temp;
for (size_t i=0; i < size/4; i++, output += 4)
{
#if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS) && defined(IS_LITTLE_ENDIAN)
*((word32*)output) = ByteReverse(NextMersenneWord());
#elif defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS)
*((word32*)output) = NextMersenneWord();
#else
temp = NextMersenneWord();
output[3] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 0);
output[2] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 1);
output[1] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 2);
output[0] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 3);
#endif
}
// No tail bytes
if (size%4 == 0)
{
// Wipe temp
*((volatile word32*)&temp) = 0;
return;
}
// Handle tail bytes
temp = NextMersenneWord();
switch (size%4)
{
case 3: output[2] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 1); /* fall through */
case 2: output[1] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 2); /* fall through */
case 1: output[0] = CRYPTOPP_GET_BYTE_AS_BYTE(temp, 3); break;
default: CRYPTOPP_ASSERT(0); ;;
}
// Wipe temp
*((volatile word32*)&temp) = 0;
}
//! \brief Generate a random 32-bit word in the range min to max, inclusive
//! \returns random 32-bit word in the range min to max, inclusive
//! \details If the 32-bit candidate is not within the range, then it is discarded
//! and a new candidate is used.
word32 GenerateWord32(word32 min=0, word32 max=0xffffffffL)
{
const word32 range = max-min;
if (range == 0xffffffffL)
return NextMersenneWord();
const int maxBits = BitPrecision(range);
word32 value;
do{
value = Crop(NextMersenneWord(), maxBits);
} while (value > range);
return value+min;
}
//! \brief Generate and discard n bytes
//! \param n the number of bytes to discard, rounded up to a <tt>word32</tt> size
//! \details If n is not a multiple of <tt>word32</tt>, then unused bytes are
//! not accumulated for subsequent calls to GenerateBlock. Rather, the unused
//! tail bytes are discarded, and the stream is continued at the next
//! <tt>word32</tt> boundary from the state array.
void DiscardBytes(size_t n)
{
for(size_t i=0; i < RoundUpToMultipleOf(n, 4U); i++)
NextMersenneWord();
}
protected:
//! \brief Returns the next 32-bit word from the state array
//! \returns the next 32-bit word from the state array
//! \details fetches the next word frm the state array, performs bit operations on
//! it, and then returns the value to the caller.
word32 NextMersenneWord()
{
if (m_idx >= N) { Twist(); }
word32 temp = m_state[m_idx++];
temp ^= (temp >> 11);
temp ^= (temp << 7) & 0x9D2C5680; // 0x9D2C5680 (2636928640)
temp ^= (temp << 15) & 0xEFC60000; // 0xEFC60000 (4022730752)
return temp ^ (temp >> 18);
}
//! \brief Performs the twist operaton on the state array
void Twist()
{
static const unsigned long magic[2]={0x0UL, K};
word32 kk, temp;
CRYPTOPP_ASSERT(N >= M);
for (kk=0;kk<N-M;kk++)
{
temp = (m_state[kk] & 0x80000000)|(m_state[kk+1] & 0x7FFFFFFF);
m_state[kk] = m_state[kk+M] ^ (temp >> 1) ^ magic[temp & 0x1UL];
}
for (;kk<N-1;kk++)
{
temp = (m_state[kk] & 0x80000000)|(m_state[kk+1] & 0x7FFFFFFF);
m_state[kk] = m_state[kk+(M-N)] ^ (temp >> 1) ^ magic[temp & 0x1UL];
}
temp = (m_state[N-1] & 0x80000000)|(m_state[0] & 0x7FFFFFFF);
m_state[N-1] = m_state[M-1] ^ (temp >> 1) ^ magic[temp & 0x1UL];
// Reset index
m_idx = 0;
// Wipe temp
*((volatile word32*)&temp) = 0;
}
private:
//! \brief 32-bit word state array of size N
FixedSizeSecBlock<word32, N+1> m_state;
//! \brief the value used to seed the generator
unsigned int m_seed;
//! \brief the current index into the state array
unsigned int m_idx;
};
//! \class MT19937
//! \brief Original MT19937 generator provided in the ACM paper.
//! \details MT19937 uses 4537 as default initial seed.
//! \sa MT19937ar, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">Mersenne twister:
//! a 623-dimensionally equidistributed uniform pseudo-random number generator</A>
//! \since Crypto++ 5.6.3
#if CRYPTOPP_DOXYGEN_PROCESSING
class MT19937 : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> {};
#else
typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x10DCD /*69069*/, 4537> MT19937;
#endif
//! \class MT19937ar
//! \brief Updated MT19937 generator adapted to provide an array for initialization.
//! \details MT19937 uses 5489 as default initial seed. Use this generator when interoperating with C++11's
//! mt19937 class.
//! \sa MT19937, <A HREF="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">Mersenne Twister
//! with improved initialization</A>
//! \since Crypto++ 5.6.3
#if CRYPTOPP_DOXYGEN_PROCESSING
class MT19937ar : public MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> {};
#else
typedef MersenneTwister<0x9908B0DF /*2567483615*/, 397, 624, 0x6C078965 /*1812433253*/, 5489> MT19937ar;
#endif
NAMESPACE_END
#endif // CRYPTOPP_MERSENNE_TWISTER_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,321 @@
// modarith.h - written and placed in the public domain by Wei Dai
//! \file modarith.h
//! \brief Class file for performing modular arithmetic.
#ifndef CRYPTOPP_MODARITH_H
#define CRYPTOPP_MODARITH_H
// implementations are in integer.cpp
#include "cryptlib.h"
#include "integer.h"
#include "algebra.h"
#include "secblock.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<Integer>;
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<Integer>;
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<Integer>;
//! \class ModularArithmetic
//! \brief Ring of congruence classes modulo n
//! \details This implementation represents each congruence class as the smallest
//! non-negative integer in that class.
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
class CRYPTOPP_DLL ModularArithmetic : public AbstractRing<Integer>
{
public:
typedef int RandomizationParameter;
typedef Integer Element;
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~ModularArithmetic() {}
#endif
//! \brief Construct a ModularArithmetic
//! \param modulus congruence class modulus
ModularArithmetic(const Integer &modulus = Integer::One())
: AbstractRing<Integer>(), m_modulus(modulus), m_result((word)0, modulus.reg.size()) {}
//! \brief Copy construct a ModularArithmetic
//! \param ma other ModularArithmetic
ModularArithmetic(const ModularArithmetic &ma)
: AbstractRing<Integer>(), m_modulus(ma.m_modulus), m_result((word)0, ma.m_modulus.reg.size()) {}
//! \brief Construct a ModularArithmetic
//! \param bt BER encoded ModularArithmetic
ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters
//! \brief Clone a ModularArithmetic
//! \returns pointer to a new ModularArithmetic
//! \details Clone effectively copy constructs a new ModularArithmetic. The caller is
//! responsible for deleting the pointer returned from this method.
virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);}
//! \brief Encodes in DER format
//! \param bt BufferedTransformation object
void DEREncode(BufferedTransformation &bt) const;
//! \brief Encodes element in DER format
//! \param out BufferedTransformation object
//! \param a Element to encode
void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
//! \brief Decodes element in DER format
//! \param in BufferedTransformation object
//! \param a Element to decode
void BERDecodeElement(BufferedTransformation &in, Element &a) const;
//! \brief Retrieves the modulus
//! \returns the modulus
const Integer& GetModulus() const {return m_modulus;}
//! \brief Sets the modulus
//! \param newModulus the new modulus
void SetModulus(const Integer &newModulus)
{m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());}
//! \brief Retrieves the representation
//! \returns true if the representation is MontgomeryRepresentation, false otherwise
virtual bool IsMontgomeryRepresentation() const {return false;}
//! \brief Reduces an element in the congruence class
//! \param a element to convert
//! \returns the reduced element
//! \details ConvertIn is useful for derived classes, like MontgomeryRepresentation, which
//! must convert between representations.
virtual Integer ConvertIn(const Integer &a) const
{return a%m_modulus;}
//! \brief Reduces an element in the congruence class
//! \param a element to convert
//! \returns the reduced element
//! \details ConvertOut is useful for derived classes, like MontgomeryRepresentation, which
//! must convert between representations.
virtual Integer ConvertOut(const Integer &a) const
{return a;}
//! \brief TODO
//! \param a element to convert
const Integer& Half(const Integer &a) const;
//! \brief Compare two elements for equality
//! \param a first element
//! \param b second element
//! \returns true if the elements are equal, false otherwise
//! \details Equal() tests the elements for equality using <tt>a==b</tt>
bool Equal(const Integer &a, const Integer &b) const
{return a==b;}
//! \brief Provides the Identity element
//! \returns the Identity element
const Integer& Identity() const
{return Integer::Zero();}
//! \brief Adds elements in the ring
//! \param a first element
//! \param b second element
//! \returns the sum of <tt>a</tt> and <tt>b</tt>
const Integer& Add(const Integer &a, const Integer &b) const;
//! \brief TODO
//! \param a first element
//! \param b second element
//! \returns TODO
Integer& Accumulate(Integer &a, const Integer &b) const;
//! \brief Inverts the element in the ring
//! \param a first element
//! \returns the inverse of the element
const Integer& Inverse(const Integer &a) const;
//! \brief Subtracts elements in the ring
//! \param a first element
//! \param b second element
//! \returns the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
const Integer& Subtract(const Integer &a, const Integer &b) const;
//! \brief TODO
//! \param a first element
//! \param b second element
//! \returns TODO
Integer& Reduce(Integer &a, const Integer &b) const;
//! \brief Doubles an element in the ring
//! \param a the element
//! \returns the element doubled
//! \details Double returns <tt>Add(a, a)</tt>. The element <tt>a</tt> must provide an Add member function.
const Integer& Double(const Integer &a) const
{return Add(a, a);}
//! \brief Retrieves the multiplicative identity
//! \returns the multiplicative identity
//! \details the base class implementations returns 1.
const Integer& MultiplicativeIdentity() const
{return Integer::One();}
//! \brief Multiplies elements in the ring
//! \param a the multiplicand
//! \param b the multiplier
//! \returns the product of a and b
//! \details Multiply returns <tt>a*b\%n</tt>.
const Integer& Multiply(const Integer &a, const Integer &b) const
{return m_result1 = a*b%m_modulus;}
//! \brief Square an element in the ring
//! \param a the element
//! \returns the element squared
//! \details Square returns <tt>a*a\%n</tt>. The element <tt>a</tt> must provide a Square member function.
const Integer& Square(const Integer &a) const
{return m_result1 = a.Squared()%m_modulus;}
//! \brief Determines whether an element is a unit in the ring
//! \param a the element
//! \returns true if the element is a unit after reduction, false otherwise.
bool IsUnit(const Integer &a) const
{return Integer::Gcd(a, m_modulus).IsUnit();}
//! \brief Calculate the multiplicative inverse of an element in the ring
//! \param a the element
//! \details MultiplicativeInverse returns <tt>a<sup>-1</sup>\%n</tt>. The element <tt>a</tt> must
//! provide a InverseMod member function.
const Integer& MultiplicativeInverse(const Integer &a) const
{return m_result1 = a.InverseMod(m_modulus);}
//! \brief Divides elements in the ring
//! \param a the dividend
//! \param b the divisor
//! \returns the quotient
//! \details Divide returns <tt>a*b<sup>-1</sup>\%n</tt>.
const Integer& Divide(const Integer &a, const Integer &b) const
{return Multiply(a, MultiplicativeInverse(b));}
//! \brief TODO
//! \param x first element
//! \param e1 first exponent
//! \param y second element
//! \param e2 second exponent
//! \returns TODO
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const;
//! \brief Exponentiates a base to multiple exponents in the ring
//! \param results an array of Elements
//! \param base the base to raise to the exponents
//! \param exponents an array of exponents
//! \param exponentsCount the number of exponents in the array
//! \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the
//! result at the respective position in the results array.
//! \details SimultaneousExponentiate() must be implemented in a derived class.
//! \pre <tt>COUNTOF(results) == exponentsCount</tt>
//! \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
//! \brief Provides the maximum bit size of an element in the ring
//! \returns maximum bit size of an element
unsigned int MaxElementBitLength() const
{return (m_modulus-1).BitCount();}
//! \brief Provides the maximum byte size of an element in the ring
//! \returns maximum byte size of an element
unsigned int MaxElementByteLength() const
{return (m_modulus-1).ByteCount();}
//! \brief Provides a random element in the ring
//! \param rng RandomNumberGenerator used to generate material
//! \param ignore_for_now unused
//! \returns a random element that is uniformly distributed
//! \details RandomElement constructs a new element in the range <tt>[0,n-1]</tt>, inclusive.
//! The element's class must provide a constructor with the signature <tt>Element(RandomNumberGenerator rng,
//! Element min, Element max)</tt>.
Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0) const
// left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct
{
CRYPTOPP_UNUSED(ignore_for_now);
return Element(rng, Integer::Zero(), m_modulus - Integer::One()) ;
}
//! \brief Compares two ModularArithmetic for equality
//! \param rhs other ModularArithmetic
//! \returns true if this is equal to the other, false otherwise
//! \details The operator tests for equality using <tt>this.m_modulus == rhs.m_modulus</tt>.
bool operator==(const ModularArithmetic &rhs) const
{return m_modulus == rhs.m_modulus;}
static const RandomizationParameter DefaultRandomizationParameter ;
protected:
Integer m_modulus;
mutable Integer m_result, m_result1;
};
// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ;
//! \class MontgomeryRepresentation
//! \brief Performs modular arithmetic in Montgomery representation for increased speed
//! \details The Montgomery representation represents each congruence class <tt>[a]</tt> as
//! <tt>a*r\%n</tt>, where <tt>r</tt> is a convenient power of 2.
//! \details <tt>const Element&</tt> returned by member functions are references
//! to internal data members. Since each object may have only
//! one such data member for holding results, the following code
//! will produce incorrect results:
//! <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
//! But this should be fine:
//! <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic
{
public:
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual ~MontgomeryRepresentation() {}
#endif
//! \brief Construct a IsMontgomeryRepresentation
//! \param modulus congruence class modulus
//! \note The modulus must be odd.
MontgomeryRepresentation(const Integer &modulus);
//! \brief Clone a MontgomeryRepresentation
//! \returns pointer to a new MontgomeryRepresentation
//! \details Clone effectively copy constructs a new MontgomeryRepresentation. The caller is
//! responsible for deleting the pointer returned from this method.
virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);}
bool IsMontgomeryRepresentation() const {return true;}
Integer ConvertIn(const Integer &a) const
{return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;}
Integer ConvertOut(const Integer &a) const;
const Integer& MultiplicativeIdentity() const
{return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;}
const Integer& Multiply(const Integer &a, const Integer &b) const;
const Integer& Square(const Integer &a) const;
const Integer& MultiplicativeInverse(const Integer &a) const;
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
{return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
{AbstractRing<Integer>::SimultaneousExponentiate(results, base, exponents, exponentsCount);}
private:
Integer m_u;
mutable IntegerSecBlock m_workspace;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,485 @@
// modes.h - written and placed in the public domain by Wei Dai
//! \file modes.h
//! \brief Class file for modes of operation.
#ifndef CRYPTOPP_MODES_H
#define CRYPTOPP_MODES_H
#include "cryptlib.h"
#include "secblock.h"
#include "misc.h"
#include "strciphr.h"
#include "argnames.h"
#include "algparam.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class CipherModeDocumentation
//! \brief Block cipher mode of operation information
//! \details Each class derived from this one defines two types, Encryption and Decryption,
//! both of which implement the SymmetricCipher interface.
//! For each mode there are two classes, one of which is a template class,
//! and the other one has a name that ends in "_ExternalCipher".
//! The "external cipher" mode objects hold a reference to the underlying block cipher,
//! instead of holding an instance of it. The reference must be passed in to the constructor.
//! For the "cipher holder" classes, the CIPHER template parameter should be a class
//! derived from BlockCipherDocumentation, for example DES or AES.
//! \details See NIST SP 800-38A for definitions of these modes. See
//! AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes.
struct CipherModeDocumentation : public SymmetricCipherDocumentation
{
};
//! \class CipherModeBase
//! \brief Block cipher mode of operation information
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher
{
public:
size_t MinKeyLength() const {return m_cipher->MinKeyLength();}
size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();}
size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
unsigned int IVSize() const {return BlockSize();}
virtual IV_Requirement IVRequirement() const =0;
void SetCipher(BlockCipher &cipher)
{
this->ThrowIfResynchronizable();
this->m_cipher = &cipher;
this->ResizeBuffers();
}
void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
{
this->ThrowIfInvalidIV(iv);
this->m_cipher = &cipher;
this->ResizeBuffers();
this->SetFeedbackSize(feedbackSize);
if (this->IsResynchronizable())
this->Resynchronize(iv);
}
protected:
CipherModeBase() : m_cipher(NULL) {}
inline unsigned int BlockSize() const {CRYPTOPP_ASSERT(m_register.size() > 0); return (unsigned int)m_register.size();}
virtual void SetFeedbackSize(unsigned int feedbackSize)
{
if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
}
// Thanks to Zireael, http://github.com/weidai11/cryptopp/pull/46
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
virtual void ResizeBuffers();
#else
virtual void ResizeBuffers()
{
m_register.New(m_cipher->BlockSize());
}
#endif
BlockCipher *m_cipher;
AlignedSecByteBlock m_register;
};
//! \class ModePolicyCommonTemplate
//! \brief Block cipher mode of operation common operations
//! \tparam POLICY_INTERFACE common operations
template <class POLICY_INTERFACE>
class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
{
unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
};
template <class POLICY_INTERFACE>
void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
m_cipher->SetKey(key, length, params);
ResizeBuffers();
int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
SetFeedbackSize(feedbackSize);
}
//! \class CFB_ModePolicy
//! \brief CFB block cipher mode of operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
{
public:
IV_Requirement IVRequirement() const {return RANDOM_IV;}
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
protected:
unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
bool CanIterate() const {return m_feedbackSize == BlockSize();}
void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
void TransformRegister();
void CipherResynchronize(const byte *iv, size_t length);
void SetFeedbackSize(unsigned int feedbackSize);
void ResizeBuffers();
SecByteBlock m_temp;
unsigned int m_feedbackSize;
};
inline void CopyOrZero(void *dest, const void *src, size_t s)
{
if (src)
memcpy_s(dest, s, src, s);
else
memset(dest, 0, s);
}
//! \class OFB_ModePolicy
//! \brief OFB block cipher mode of operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
{
public:
bool CipherIsRandomAccess() const {return false;}
IV_Requirement IVRequirement() const {return UNIQUE_IV;}
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
private:
unsigned int GetBytesPerIteration() const {return BlockSize();}
unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
};
//! \class CTR_ModePolicy
//! \brief CTR block cipher mode of operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
{
public:
bool CipherIsRandomAccess() const {return true;}
IV_Requirement IVRequirement() const {return RANDOM_IV;}
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
protected:
virtual void IncrementCounterBy256();
unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
unsigned int GetBytesPerIteration() const {return BlockSize();}
unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
void WriteKeystream(byte *buffer, size_t iterationCount)
{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
bool CanOperateKeystream() const {return true;}
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
void SeekToIteration(lword iterationCount);
AlignedSecByteBlock m_counterArray;
};
//! \class BlockOrientedCipherModeBase
//! \brief Block cipher mode of operation default implementation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
{
public:
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
unsigned int MandatoryBlockSize() const {return BlockSize();}
bool IsRandomAccess() const {return false;}
bool IsSelfInverting() const {return false;}
bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
protected:
bool RequireAlignedInput() const {return true;}
// Thanks to Zireael, http://github.com/weidai11/cryptopp/pull/46
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
void ResizeBuffers();
#else
void ResizeBuffers()
{
CipherModeBase::ResizeBuffers();
m_buffer.New(BlockSize());
}
#endif
SecByteBlock m_buffer;
};
//! \class ECB_OneWay
//! \brief ECB block cipher mode of operation default implementation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
{
public:
void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
{m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
void ProcessData(byte *outString, const byte *inString, size_t length);
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
};
//! \class CBC_ModeBase
//! \brief CBC block cipher mode of operation default implementation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase
{
public:
IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
bool RequireAlignedInput() const {return false;}
unsigned int MinLastBlockSize() const {return 0;}
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";}
};
//! \class CBC_Encryption
//! \brief CBC block cipher mode of operation encryption operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
{
public:
void ProcessData(byte *outString, const byte *inString, size_t length);
};
//! \class CBC_CTS_Encryption
//! \brief CBC-CTS block cipher mode of operation encryption operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
{
public:
void SetStolenIV(byte *iv) {m_stolenIV = iv;}
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";}
protected:
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
CBC_Encryption::UncheckedSetKey(key, length, params);
m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
}
byte *m_stolenIV;
};
//! \class CBC_Decryption
//! \brief CBC block cipher mode of operation decryption operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
{
public:
void ProcessData(byte *outString, const byte *inString, size_t length);
protected:
// Thanks to Zireael, http://github.com/weidai11/cryptopp/pull/46
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
void ResizeBuffers();
#else
void ResizeBuffers()
{
BlockOrientedCipherModeBase::ResizeBuffers();
m_temp.New(BlockSize());
}
#endif
AlignedSecByteBlock m_temp;
};
//! \class CBC_CTS_Decryption
//! \brief CBC-CTS block cipher mode of operation decryption operation
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
{
public:
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
};
//! \class CipherModeFinalTemplate_CipherHolder
//! \brief Block cipher mode of operation aggregate
template <class CIPHER, class BASE>
class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
{
public:
CipherModeFinalTemplate_CipherHolder()
{
this->m_cipher = &this->m_object;
this->ResizeBuffers();
}
CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length)
{
this->m_cipher = &this->m_object;
this->SetKey(key, length);
}
CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
{
this->m_cipher = &this->m_object;
this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize())));
}
CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
{
this->m_cipher = &this->m_object;
this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize));
}
static std::string CRYPTOPP_API StaticAlgorithmName()
{return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();}
};
//! \class CipherModeFinalTemplate_ExternalCipher
//! \tparam BASE CipherModeFinalTemplate_CipherHolder base class
//! \details
template <class BASE>
class CipherModeFinalTemplate_ExternalCipher : public BASE
{
public:
CipherModeFinalTemplate_ExternalCipher() {}
CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
{this->SetCipher(cipher);}
CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
{this->SetCipherWithIV(cipher, iv, feedbackSize);}
std::string AlgorithmName() const
{return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
};
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
//! \class CFB_Mode
//! \brief CFB block cipher mode of operation.
template <class CIPHER>
struct CFB_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
};
//! \class CFB_Mode_ExternalCipher
//! \brief CFB mode, external cipher.
struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
};
//! \class CFB_FIPS_Mode
//! \brief CFB block cipher mode of operation providing FIPS validated cryptography.
//! \details Requires full block plaintext according to FIPS 800-38A
template <class CIPHER>
struct CFB_FIPS_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
};
//! \class CFB_FIPS_Mode_ExternalCipher
//! \brief CFB mode, external cipher, providing FIPS validated cryptography.
//! \details Requires full block plaintext according to FIPS 800-38A
struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
//! \class OFB_Mode
//! \brief OFB block cipher mode of operation.
template <class CIPHER>
struct OFB_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
typedef Encryption Decryption;
};
//! \class OFB_Mode_ExternalCipher
//! \brief OFB mode, external cipher.
struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
typedef Encryption Decryption;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > >;
//! \class CTR_Mode
//! \brief CTR block cipher mode of operation.
template <class CIPHER>
struct CTR_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
typedef Encryption Decryption;
};
//! \class CTR_Mode_ExternalCipher
//! \brief CTR mode, external cipher.
struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
typedef Encryption Decryption;
};
//! \class ECB_Mode
//! \brief ECB block cipher mode of operation.
template <class CIPHER>
struct ECB_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
};
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
//! \class ECB_Mode_ExternalCipher
//! \brief ECB mode, external cipher.
struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
typedef Encryption Decryption;
};
//! CBC mode
template <class CIPHER>
struct CBC_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
};
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
//! CBC mode, external cipher
struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
};
//! CBC mode with ciphertext stealing
template <class CIPHER>
struct CBC_CTS_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
};
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
//! \class CBC_CTS_Mode_ExternalCipher
//! \brief CBC mode with ciphertext stealing, external cipher
struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
};
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
typedef OFB_Mode_ExternalCipher::Encryption OFB;
typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
#endif
NAMESPACE_END
#endif

View File

@ -0,0 +1,37 @@
#ifndef CRYPTOPP_MODEXPPC_H
#define CRYPTOPP_MODEXPPC_H
#include "cryptlib.h"
#include "modarith.h"
#include "integer.h"
#include "algebra.h"
#include "eprecomp.h"
#include "smartptr.h"
#include "pubkey.h"
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<Integer>;
class ModExpPrecomputation : public DL_GroupPrecomputation<Integer>
{
public:
// DL_GroupPrecomputation
bool NeedConversions() const {return true;}
Element ConvertIn(const Element &v) const {return m_mr->ConvertIn(v);}
virtual Element ConvertOut(const Element &v) const {return m_mr->ConvertOut(v);}
const AbstractGroup<Element> & GetGroup() const {return m_mr->MultiplicativeGroup();}
Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);}
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);}
// non-inherited
void SetModulus(const Integer &v) {m_mr.reset(new MontgomeryRepresentation(v));}
const Integer & GetModulus() const {return m_mr->GetModulus();}
private:
value_ptr<MontgomeryRepresentation> m_mr;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,105 @@
#ifndef CRYPTOPP_MQUEUE_H
#define CRYPTOPP_MQUEUE_H
#include "cryptlib.h"
#include "queue.h"
#include "filters.h"
#include "misc.h"
#include <deque>
NAMESPACE_BEGIN(CryptoPP)
//! Message Queue
class CRYPTOPP_DLL MessageQueue : public AutoSignaling<BufferedTransformation>
{
public:
MessageQueue(unsigned int nodeSize=256);
void IsolatedInitialize(const NameValuePairs &parameters)
{m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);}
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
CRYPTOPP_UNUSED(blocking);
m_queue.Put(begin, length);
m_lengths.back() += length;
if (messageEnd)
{
m_lengths.push_back(0);
m_messageCounts.back()++;
}
return 0;
}
bool IsolatedFlush(bool hardFlush, bool blocking)
{CRYPTOPP_UNUSED(hardFlush), CRYPTOPP_UNUSED(blocking); return false;}
bool IsolatedMessageSeriesEnd(bool blocking)
{CRYPTOPP_UNUSED(blocking); m_messageCounts.push_back(0); return false;}
lword MaxRetrievable() const
{return m_lengths.front();}
bool AnyRetrievable() const
{return m_lengths.front() > 0;}
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
lword TotalBytesRetrievable() const
{return m_queue.MaxRetrievable();}
unsigned int NumberOfMessages() const
{return (unsigned int)m_lengths.size()-1;}
bool GetNextMessage();
unsigned int NumberOfMessagesInThisSeries() const
{return m_messageCounts[0];}
unsigned int NumberOfMessageSeries() const
{return (unsigned int)m_messageCounts.size()-1;}
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
const byte * Spy(size_t &contiguousSize) const;
void swap(MessageQueue &rhs);
private:
ByteQueue m_queue;
std::deque<lword> m_lengths;
std::deque<unsigned int> m_messageCounts;
};
//! A filter that checks messages on two channels for equality
class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable<Multichannel<Filter> >
{
public:
struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}};
/*! if throwIfNotEqual is false, this filter will output a '\\0' byte when it detects a mismatch, '\\1' otherwise */
EqualityComparisonFilter(BufferedTransformation *attachment=NULL, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1")
: m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false)
, m_firstChannel(firstChannel), m_secondChannel(secondChannel)
{Detach(attachment);}
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
private:
unsigned int MapChannel(const std::string &channel) const;
bool HandleMismatchDetected(bool blocking);
bool m_throwIfNotEqual, m_mismatchDetected;
std::string m_firstChannel, m_secondChannel;
MessageQueue m_q[2];
};
NAMESPACE_END
#ifndef __BORLANDC__
NAMESPACE_BEGIN(std)
template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b)
{
a.swap(b);
}
NAMESPACE_END
#endif
#endif

View File

@ -0,0 +1,221 @@
// mqv.h - written and placed in the public domain by Wei Dai
//! \file mqv.h
//! \brief Classes for MenezesQuVanstone (MQV) key agreement
#ifndef CRYPTOPP_MQV_H
#define CRYPTOPP_MQV_H
#include "cryptlib.h"
#include "gfpcrypt.h"
#include "modarith.h"
#include "integer.h"
#include "algebra.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class MQV_Domain
//! \brief MQV domain for performing authenticated key agreement
//! \tparam GROUP_PARAMETERS doamin parameters
//! \tparam COFACTOR_OPTION cofactor option
//! \details GROUP_PARAMETERS paramters include the curve coefcients and the base point.
//! Binary curves use a polynomial to represent its characteristic, while prime curves
//! use a prime number.
//! \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
class MQV_Domain : public AuthenticatedKeyAgreementDomain
{
public:
typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element;
typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
//! \brief Construct a MQV domain
MQV_Domain() {}
//! \brief Construct a MQV domain
//! \param params group parameters and options
MQV_Domain(const GroupParameters &params)
: m_groupParameters(params) {}
//! \brief Construct a MQV domain
//! \param bt BufferedTransformation with group parameters and options
MQV_Domain(BufferedTransformation &bt)
{m_groupParameters.BERDecode(bt);}
//! \brief Construct a MQV domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2>
MQV_Domain(T1 v1, T2 v2)
{m_groupParameters.Initialize(v1, v2);}
//! \brief Construct a MQV domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \param v3 third parameter
//! \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3>
MQV_Domain(T1 v1, T2 v2, T3 v3)
{m_groupParameters.Initialize(v1, v2, v3);}
//! \brief Construct a MQV domain
//! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter
//! \tparam T3 template parameter used as a constructor parameter
//! \tparam T4 template parameter used as a constructor parameter
//! \param v1 first parameter
//! \param v2 second parameter
//! \param v3 third parameter
//! \param v4 third parameter
//! \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3, class T4>
MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
//! \brief Retrieves the group parameters for this domain
//! \return the group parameters for this domain as a const reference
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
//! \brief Retrieves the group parameters for this domain
//! \return the group parameters for this domain as a non-const reference
GroupParameters & AccessGroupParameters() {return m_groupParameters;}
//! \brief Retrieves the crypto parameters for this domain
//! \return the crypto parameters for this domain as a non-const reference
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
//! \brief Provides the size of the agreed value
//! \return size of agreed value produced in this domain
//! \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>, which means the
//! element is encoded in a non-reversible format. A non-reversible format means its a raw byte array,
//! and it lacks presentation format like an ASN.1 BIT_STRING or OCTET_STRING.
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
//! \brief Provides the size of the static private key
//! \return size of static private keys in this domain
//! \details The length is calculated using the byte count of the subgroup order.
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
//! \brief Provides the size of the static public key
//! \return size of static public keys in this domain
//! \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>, which means the
//! element is encoded in a reversible format. A reversible format means it has a presentation format,
//! and its an ANS.1 encoded element or point.
unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
//! \brief Generate static private key in this domain
//! \param rng a RandomNumberGenerator derived class
//! \param privateKey a byte buffer for the generated private key in this domain
//! \details The private key is a random scalar used as an exponent in the range <tt>[1,MaxExponent()]</tt>.
//! \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
//! \brief Generate a static public key from a private key in this domain
//! \param rng a RandomNumberGenerator derived class
//! \param privateKey a byte buffer with the previously generated private key
//! \param publicKey a byte buffer for the generated public key in this domain
//! \details The public key is an element or point on the curve, and its stored in a revrsible format.
//! A reversible format means it has a presentation format, and its an ANS.1 encoded element or point.
//! \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
}
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const
{
try
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
Integer s(staticPrivateKey, StaticPrivateKeyLength());
Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
const Integer &r = params.GetSubgroupOrder();
Integer h2 = Integer::Power2((r.BitCount()+1)/2);
Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
{
Element P = params.ExponentiateElement(WW, tt);
P = m_groupParameters.MultiplyElements(P, VV);
Element R[2];
const Integer e2[2] = {r, e};
params.SimultaneousExponentiate(R, P, e2, 2);
if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
return false;
params.EncodeElement(false, R[1], agreedValue);
}
else
{
const Integer &k = params.GetCofactor();
if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
e = ModularArithmetic(r).Divide(e, k);
Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
if (params.IsIdentity(P))
return false;
params.EncodeElement(false, P, agreedValue);
}
}
catch (DL_BadElement &)
{
return false;
}
return true;
}
private:
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
GroupParameters m_groupParameters;
};
//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a>
//! \sa MQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
NAMESPACE_END
#endif

View File

@ -0,0 +1,173 @@
// nbtheory.h - written and placed in the public domain by Wei Dai
//! \file nbtheory.h
//! \brief Classes and functions for number theoretic operations
#ifndef CRYPTOPP_NBTHEORY_H
#define CRYPTOPP_NBTHEORY_H
#include "cryptlib.h"
#include "integer.h"
#include "algparam.h"
NAMESPACE_BEGIN(CryptoPP)
// obtain pointer to small prime table and get its size
CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size);
// ************ primality testing ****************
//! \brief Generates a provable prime
//! \param rng a RandomNumberGenerator to produce keying material
//! \param bits the number of bits in the prime number
//! \returns Integer() meeting Maurer's tests for primality
CRYPTOPP_DLL Integer CRYPTOPP_API MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
//! \brief Generates a provable prime
//! \param rng a RandomNumberGenerator to produce keying material
//! \param bits the number of bits in the prime number
//! \returns Integer() meeting Mihailescu's tests for primality
//! \details Mihailescu's methods performs a search using algorithmic progressions.
CRYPTOPP_DLL Integer CRYPTOPP_API MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
//! \brief Tests whether a number is a small prime
//! \param p a candidate prime to test
//! \returns true if p is a small prime, false otherwise
//! \details Internally, the library maintains a table fo the first 32719 prime numbers
//! in sorted order. IsSmallPrime() searches the table and returns true if p is
//! in the table.
CRYPTOPP_DLL bool CRYPTOPP_API IsSmallPrime(const Integer &p);
//!
//! \returns true if p is divisible by some prime less than bound.
//! \details TrialDivision() true if p is divisible by some prime less than bound. bound not be
//! greater than the largest entry in the prime table, which is 32719.
CRYPTOPP_DLL bool CRYPTOPP_API TrialDivision(const Integer &p, unsigned bound);
// returns true if p is NOT divisible by small primes
CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p);
// These is no reason to use these two, use the ones below instead
CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Integer &b);
CRYPTOPP_DLL bool CRYPTOPP_API IsLucasProbablePrime(const Integer &n);
CRYPTOPP_DLL bool CRYPTOPP_API IsStrongProbablePrime(const Integer &n, const Integer &b);
CRYPTOPP_DLL bool CRYPTOPP_API IsStrongLucasProbablePrime(const Integer &n);
// Rabin-Miller primality test, i.e. repeating the strong probable prime test
// for several rounds with random bases
CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds);
//! \brief Verifies a prime number
//! \param p a candidate prime to test
//! \returns true if p is a probable prime, false otherwise
//! \details IsPrime() is suitable for testing candidate primes when creating them. Internally,
//! IsPrime() utilizes SmallDivisorsTest(), IsStrongProbablePrime() and IsStrongLucasProbablePrime().
CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p);
//! \brief Verifies a prime number
//! \param rng a RandomNumberGenerator for randomized testing
//! \param p a candidate prime to test
//! \param level the level of thoroughness of testing
//! \returns true if p is a strong probable prime, false otherwise
//! \details VerifyPrime() is suitable for testing candidate primes created by others. Internally,
//! VerifyPrime() utilizes IsPrime() and one-round RabinMillerTest(). If the candiate passes and
//! level is greater than 1, then 10 round RabinMillerTest() primality testing is performed.
CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1);
//! \class PrimeSelector
//! \brief Application callback to signal suitability of a cabdidate prime
class CRYPTOPP_DLL PrimeSelector
{
public:
const PrimeSelector *GetSelectorPointer() const {return this;}
virtual bool IsAcceptable(const Integer &candidate) const =0;
};
//! \brief Finds a random prime of special form
//! \param p an Integer reference to receive the prime
//! \param max the maximum value
//! \param equiv the equivalence class based on the parameter mod
//! \param mod the modulus used to reduce the equivalence class
//! \param pSelector pointer to a PrimeSelector function for the application to signal suitability
//! \returns true if and only if FirstPrime() finds a prime and returns the prime through p. If FirstPrime()
//! returns false, then no such prime exists and the value of p is undefined
//! \details FirstPrime() uses a fast sieve to find the first probable prime
//! in <tt>{x | p<=x<=max and x%mod==equiv}</tt>
CRYPTOPP_DLL bool CRYPTOPP_API FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector);
CRYPTOPP_DLL unsigned int CRYPTOPP_API PrimeSearchInterval(const Integer &max);
CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength);
// ********** other number theoretic functions ************
inline Integer GCD(const Integer &a, const Integer &b)
{return Integer::Gcd(a,b);}
inline bool RelativelyPrime(const Integer &a, const Integer &b)
{return Integer::Gcd(a,b) == Integer::One();}
inline Integer LCM(const Integer &a, const Integer &b)
{return a/Integer::Gcd(a,b)*b;}
inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
{return a.InverseMod(b);}
// use Chinese Remainder Theorem to calculate x given x mod p and x mod q, and u = inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u);
// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise
// check a number theory book for what Jacobi symbol means when b is not prime
CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b);
// calculates the Lucas function V_e(p, 1) mod n
CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n);
// calculates x such that m==Lucas(e, x, p*q), p q primes, u=inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u);
inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m)
{return a_exp_b_mod_c(a, e, m);}
// returns x such that x*x%p == a, p prime
CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p);
// returns x such that a==ModularExponentiation(x, e, p*q), p q primes,
// and e relatively prime to (p-1)*(q-1)
// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1))
// and u=inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u);
// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime
// returns true if solutions exist
CRYPTOPP_DLL bool CRYPTOPP_API SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p);
// returns log base 2 of estimated number of operations to calculate discrete log or factor a number
CRYPTOPP_DLL unsigned int CRYPTOPP_API DiscreteLogWorkFactor(unsigned int bitlength);
CRYPTOPP_DLL unsigned int CRYPTOPP_API FactoringWorkFactor(unsigned int bitlength);
// ********************************************************
//! generator of prime numbers of special forms
class CRYPTOPP_DLL PrimeAndGenerator
{
public:
PrimeAndGenerator() {}
// generate a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is also prime
// Precondition: pbits > 5
// warning: this is slow, because primes of this form are harder to find
PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits)
{Generate(delta, rng, pbits, pbits-1);}
// generate a random prime p of the form 2*r*q+delta, where q is also prime
// Precondition: qbits > 4 && pbits > qbits
PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits)
{Generate(delta, rng, pbits, qbits);}
void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits);
const Integer& Prime() const {return p;}
const Integer& SubPrime() const {return q;}
const Integer& Generator() const {return g;}
private:
Integer p, q, g;
};
NAMESPACE_END
#endif

View File

@ -0,0 +1,234 @@
#ifndef CRYPTOPP_NETWORK_H
#define CRYPTOPP_NETWORK_H
#include "config.h"
#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
#include "filters.h"
#include "hrtimer.h"
#include "stdcpp.h"
NAMESPACE_BEGIN(CryptoPP)
class LimitedBandwidth
{
public:
LimitedBandwidth(lword maxBytesPerSecond = 0)
: m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS)
, m_nextTransceiveTime(0)
{ m_timer.StartTimer(); }
lword GetMaxBytesPerSecond() const
{ return m_maxBytesPerSecond; }
void SetMaxBytesPerSecond(lword v)
{ m_maxBytesPerSecond = v; }
lword ComputeCurrentTransceiveLimit();
double TimeToNextTransceive();
void NoteTransceive(lword size);
public:
/*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount();
the 0 is because the ScheduleEvent() method is used instead of adding a wait object */
unsigned int GetMaxWaitObjectCount() const { return 0; }
void GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack);
private:
lword m_maxBytesPerSecond;
typedef std::deque<std::pair<double, lword> > OpQueue;
OpQueue m_ops;
Timer m_timer;
double m_nextTransceiveTime;
void ComputeNextTransceiveTime();
double GetCurTimeAndCleanUp();
};
//! a Source class that can pump from a device for a specified amount of time.
class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth
{
public:
NonblockingSource(BufferedTransformation *attachment)
: m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);}
//! \name NONBLOCKING SOURCE
//@{
//! pump up to maxSize bytes using at most maxTime milliseconds
/*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */
size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n');
lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n')
{
GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter);
return maxSize;
}
lword TimedPump(unsigned long maxTime)
{return GeneralPump(LWORD_MAX, maxTime);}
lword PumpLine(byte delimiter='\n', lword maxSize=1024)
{return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);}
size_t Pump2(lword &byteCount, bool blocking=true)
{return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);}
size_t PumpMessages2(unsigned int &messageCount, bool blocking=true);
//@}
protected:
virtual size_t DoPump(lword &byteCount, bool blockingOutput,
unsigned long maxTime, bool checkDelimiter, byte delimiter) =0;
bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
private:
bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit;
};
//! Network Receiver
class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable
{
public:
virtual bool MustWaitToReceive() {return false;}
virtual bool MustWaitForResult() {return false;}
//! receive data from network source, returns whether result is immediately available
virtual bool Receive(byte* buf, size_t bufLen) =0;
virtual unsigned int GetReceiveResult() =0;
virtual bool EofReceived() const =0;
};
class CRYPTOPP_NO_VTABLE NonblockingSinkInfo
{
public:
virtual ~NonblockingSinkInfo() {}
virtual size_t GetMaxBufferSize() const =0;
virtual size_t GetCurrentBufferSize() const =0;
virtual bool EofPending() const =0;
//! compute the current speed of this sink in bytes per second
virtual float ComputeCurrentSpeed() =0;
//! get the maximum observed speed of this sink in bytes per second
virtual float GetMaxObservedSpeed() const =0;
};
//! a Sink class that queues input and can flush to a device for a specified amount of time.
class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth
{
public:
NonblockingSink() : m_blockedBySpeedLimit(false) {}
bool IsolatedFlush(bool hardFlush, bool blocking);
//! flush to device for no more than maxTime milliseconds
/*! This function will repeatedly attempt to flush data to some device, until
the queue is empty, or a total of maxTime milliseconds have elapsed.
If maxTime == 0, at least one attempt will be made to flush some data, but
it is likely that not all queued data will be flushed, even if the device
is ready to receive more data without waiting. If you want to flush as much data
as possible without waiting for the device, call this function in a loop.
For example: while (sink.TimedFlush(0) > 0) {}
\return number of bytes flushed
*/
lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
virtual void SetMaxBufferSize(size_t maxBufferSize) =0;
//! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize()
virtual void SetAutoFlushBound(size_t bound) =0;
protected:
virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0;
bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
private:
bool m_blockedBySpeedLimit;
};
//! Network Sender
class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable
{
public:
virtual bool MustWaitToSend() {return false;}
virtual bool MustWaitForResult() {return false;}
virtual void Send(const byte* buf, size_t bufLen) =0;
virtual unsigned int GetSendResult() =0;
virtual bool MustWaitForEof() {return false;}
virtual void SendEof() =0;
virtual bool EofSent() {return false;} // implement if MustWaitForEof() == true
};
//! Network Source
class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource
{
public:
NetworkSource(BufferedTransformation *attachment);
unsigned int GetMaxWaitObjectCount() const;
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();}
protected:
size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter);
virtual NetworkReceiver & AccessReceiver() =0;
const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();}
private:
SecByteBlock m_buf;
size_t m_putSize, m_dataBegin, m_dataEnd;
bool m_waitingForResult, m_outputBlocked;
};
//! Network Sink
class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
{
public:
NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
unsigned int GetMaxWaitObjectCount() const;
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));}
void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;}
size_t GetMaxBufferSize() const {return m_maxBufferSize;}
size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();}
void ClearBuffer() { m_buffer.Clear(); }
bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; }
//! compute the current speed of this sink in bytes per second
float ComputeCurrentSpeed();
//! get the maximum observed speed of this sink in bytes per second
float GetMaxObservedSpeed() const;
protected:
lword DoFlush(unsigned long maxTime, size_t targetSize);
virtual NetworkSender & AccessSender() =0;
const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();}
private:
enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE };
size_t m_maxBufferSize, m_autoFlushBound;
bool m_needSendResult, m_wasBlocked;
EofState m_eofState;
ByteQueue m_buffer;
size_t m_skipBytes;
Timer m_speedTimer;
float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed;
};
NAMESPACE_END
#endif // SOCKETS_AVAILABLE
#endif // CRYPTOPP_NETWORK_H

View File

@ -0,0 +1,6 @@
#ifndef CRYPTOPP_NR_H
#define CRYPTOPP_NR_H
#include "gfpcrypt.h"
#endif

View File

@ -0,0 +1,43 @@
#ifndef CRYPTOPP_OAEP_H
#define CRYPTOPP_OAEP_H
#include "cryptlib.h"
#include "pubkey.h"
#include "sha.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
class CRYPTOPP_DLL OAEP_Base : public PK_EncryptionMessageEncodingMethod
{
public:
bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
size_t MaxUnpaddedLength(size_t paddedLength) const;
void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs &parameters) const;
DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs &parameters) const;
protected:
virtual unsigned int DigestSize() const =0;
virtual HashTransformation * NewHash() const =0;
virtual MaskGeneratingFunction * NewMGF() const =0;
};
//! <a href="http://www.weidai.com/scan-mirror/ca.html#cem_OAEP-MGF1">EME-OAEP</a>, for use with classes derived from TF_ES
template <class H, class MGF=P1363_MGF1>
class OAEP : public OAEP_Base, public EncryptionStandard
{
public:
static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
typedef OAEP<H, MGF> EncryptionMessageEncodingMethod;
protected:
unsigned int DigestSize() const {return H::DIGESTSIZE;}
HashTransformation * NewHash() const {return new H;}
MaskGeneratingFunction * NewMGF() const {return new MGF;}
};
CRYPTOPP_DLL_TEMPLATE_CLASS OAEP<SHA>;
NAMESPACE_END
#endif

View File

@ -0,0 +1,135 @@
// oids.h - written and placed in the public domain by Wei Dai
//! \file oids.h
//! \brief ASN.1 object identifiers for algorthms and schemes
#ifndef CRYPTOPP_OIDS_H
#define CRYPTOPP_OIDS_H
#include "asn.h"
NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(ASN1)
#define DEFINE_OID(value, name) inline OID name() {return value;}
DEFINE_OID(1, iso)
DEFINE_OID(iso()+2, member_body)
DEFINE_OID(member_body()+840, iso_us)
DEFINE_OID(iso_us()+10040, ansi_x9_57)
DEFINE_OID(ansi_x9_57()+4+1, id_dsa)
DEFINE_OID(iso_us()+10045, ansi_x9_62)
DEFINE_OID(ansi_x9_62()+1, id_fieldType)
DEFINE_OID(id_fieldType()+1, prime_field)
DEFINE_OID(id_fieldType()+2, characteristic_two_field)
DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis)
DEFINE_OID(id_characteristic_two_basis()+1, gnBasis)
DEFINE_OID(id_characteristic_two_basis()+2, tpBasis)
DEFINE_OID(id_characteristic_two_basis()+3, ppBasis)
DEFINE_OID(ansi_x9_62()+2, id_publicKeyType)
DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey)
DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves)
DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime)
DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1)
DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1)
DEFINE_OID(iso_us()+113549, rsadsi)
DEFINE_OID(rsadsi()+1, pkcs)
DEFINE_OID(pkcs()+1, pkcs_1)
DEFINE_OID(pkcs_1()+1, rsaEncryption);
DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm)
DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2)
DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5)
DEFINE_OID(iso()+3, identified_organization)
// Arc from http://tools.ietf.org/html/draft-josefsson-pkix-newcurves
DEFINE_OID(identified_organization()+6, dod)
DEFINE_OID(dod()+1, internet)
DEFINE_OID(internet()+4, internet_private)
DEFINE_OID(internet_private()+1, enterprise)
DEFINE_OID(enterprise()+11591,GNU)
DEFINE_OID(GNU()+15,ellipticCurve)
DEFINE_OID(ellipticCurve()+1,id_curve25519)
DEFINE_OID(ellipticCurve()+2,id_curve448)
DEFINE_OID(ellipticCurve()+3,id_curve25519ph)
DEFINE_OID(ellipticCurve()+4,id_curve448ph)
DEFINE_OID(identified_organization()+14, oiw);
DEFINE_OID(oiw()+3, oiw_secsig);
DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms);
DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1);
DEFINE_OID(identified_organization()+36, teletrust);
DEFINE_OID(teletrust()+3, teletrust_algorithm)
DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160)
DEFINE_OID(teletrust_algorithm()+3+2+8+1, teletrust_ellipticCurve)
DEFINE_OID(teletrust_ellipticCurve()+1+1, brainpoolP160r1)
DEFINE_OID(teletrust_ellipticCurve()+1+3, brainpoolP192r1)
DEFINE_OID(teletrust_ellipticCurve()+1+5, brainpoolP224r1)
DEFINE_OID(teletrust_ellipticCurve()+1+7, brainpoolP256r1)
DEFINE_OID(teletrust_ellipticCurve()+1+9, brainpoolP320r1)
DEFINE_OID(teletrust_ellipticCurve()+1+11, brainpoolP384r1)
DEFINE_OID(teletrust_ellipticCurve()+1+13, brainpoolP512r1)
DEFINE_OID(identified_organization()+132, certicom);
DEFINE_OID(certicom()+0, certicom_ellipticCurve);
// these are sorted by curve type and then by OID
// first curves based on GF(p)
DEFINE_OID(certicom_ellipticCurve()+6, secp112r1);
DEFINE_OID(certicom_ellipticCurve()+7, secp112r2);
DEFINE_OID(certicom_ellipticCurve()+8, secp160r1);
DEFINE_OID(certicom_ellipticCurve()+9, secp160k1);
DEFINE_OID(certicom_ellipticCurve()+10, secp256k1);
DEFINE_OID(certicom_ellipticCurve()+28, secp128r1);
DEFINE_OID(certicom_ellipticCurve()+29, secp128r2);
DEFINE_OID(certicom_ellipticCurve()+30, secp160r2);
DEFINE_OID(certicom_ellipticCurve()+31, secp192k1);
DEFINE_OID(certicom_ellipticCurve()+32, secp224k1);
DEFINE_OID(certicom_ellipticCurve()+33, secp224r1);
DEFINE_OID(certicom_ellipticCurve()+34, secp384r1);
DEFINE_OID(certicom_ellipticCurve()+35, secp521r1);
// then curves based on GF(2^n)
DEFINE_OID(certicom_ellipticCurve()+1, sect163k1);
DEFINE_OID(certicom_ellipticCurve()+2, sect163r1);
DEFINE_OID(certicom_ellipticCurve()+3, sect239k1);
DEFINE_OID(certicom_ellipticCurve()+4, sect113r1);
DEFINE_OID(certicom_ellipticCurve()+5, sect113r2);
DEFINE_OID(certicom_ellipticCurve()+15, sect163r2);
DEFINE_OID(certicom_ellipticCurve()+16, sect283k1);
DEFINE_OID(certicom_ellipticCurve()+17, sect283r1);
DEFINE_OID(certicom_ellipticCurve()+22, sect131r1);
DEFINE_OID(certicom_ellipticCurve()+23, sect131r2);
DEFINE_OID(certicom_ellipticCurve()+24, sect193r1);
DEFINE_OID(certicom_ellipticCurve()+25, sect193r2);
DEFINE_OID(certicom_ellipticCurve()+26, sect233k1);
DEFINE_OID(certicom_ellipticCurve()+27, sect233r1);
DEFINE_OID(certicom_ellipticCurve()+36, sect409k1);
DEFINE_OID(certicom_ellipticCurve()+37, sect409r1);
DEFINE_OID(certicom_ellipticCurve()+38, sect571k1);
DEFINE_OID(certicom_ellipticCurve()+39, sect571r1);
DEFINE_OID(2, joint_iso_ccitt)
DEFINE_OID(joint_iso_ccitt()+16, country)
DEFINE_OID(country()+840, joint_iso_ccitt_us)
DEFINE_OID(joint_iso_ccitt_us()+1, us_organization)
DEFINE_OID(us_organization()+101, us_gov)
DEFINE_OID(us_gov()+3, csor)
DEFINE_OID(csor()+4, nistalgorithms)
DEFINE_OID(nistalgorithms()+1, aes)
DEFINE_OID(aes()+1, id_aes128_ECB)
DEFINE_OID(aes()+2, id_aes128_cbc)
DEFINE_OID(aes()+3, id_aes128_ofb)
DEFINE_OID(aes()+4, id_aes128_cfb)
DEFINE_OID(aes()+21, id_aes192_ECB)
DEFINE_OID(aes()+22, id_aes192_cbc)
DEFINE_OID(aes()+23, id_aes192_ofb)
DEFINE_OID(aes()+24, id_aes192_cfb)
DEFINE_OID(aes()+41, id_aes256_ECB)
DEFINE_OID(aes()+42, id_aes256_cbc)
DEFINE_OID(aes()+43, id_aes256_ofb)
DEFINE_OID(aes()+44, id_aes256_cfb)
DEFINE_OID(nistalgorithms()+2, nist_hashalgs)
DEFINE_OID(nist_hashalgs()+1, id_sha256)
DEFINE_OID(nist_hashalgs()+2, id_sha384)
DEFINE_OID(nist_hashalgs()+3, id_sha512)
NAMESPACE_END
NAMESPACE_END
#endif

View File

@ -0,0 +1,267 @@
// osrng.h - written and placed in the public domain by Wei Dai
//! \file osrng.h
//! \brief Classes for access to the operating system's random number generators
#ifndef CRYPTOPP_OSRNG_H
#define CRYPTOPP_OSRNG_H
#include "config.h"
#if !defined(OS_NO_DEPENDENCE) && defined(OS_RNG_AVAILABLE)
#include "cryptlib.h"
#include "randpool.h"
#include "smartptr.h"
#include "fips140.h"
#include "rng.h"
#include "aes.h"
#include "sha.h"
NAMESPACE_BEGIN(CryptoPP)
//! \class OS_RNG_Err
//! \brief Exception thrown when an operating system error is encountered
class CRYPTOPP_DLL OS_RNG_Err : public Exception
{
public:
//! \brief Constructs an OS_RNG_Err
//! \param operation the operation or API call when the error occurs
OS_RNG_Err(const std::string &operation);
};
#ifdef NONBLOCKING_RNG_AVAILABLE
#ifdef CRYPTOPP_WIN32_AVAILABLE
//! \class MicrosoftCryptoProvider
//! \brief Wrapper for Microsoft crypto service provider
//! \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI, \def WORKAROUND_MS_BUG_Q258000
class CRYPTOPP_DLL MicrosoftCryptoProvider
{
public:
//! \brief Construct a MicrosoftCryptoProvider
MicrosoftCryptoProvider();
~MicrosoftCryptoProvider();
// type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h>
#if defined(USE_MS_CRYPTOAPI)
# if defined(__CYGWIN__) && defined(__x86_64__)
typedef unsigned long long ProviderHandle;
# elif defined(WIN64) || defined(_WIN64)
typedef unsigned __int64 ProviderHandle;
# else
typedef unsigned long ProviderHandle;
# endif
#elif defined(USE_MS_CNGAPI)
typedef void *PVOID;
typedef PVOID ProviderHandle;
#endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI
//! \brief Retrieves the provider handle
//! \returns CryptoAPI provider handle
//! \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()
//! acquires then handle and CryptReleaseContext() releases the handle
//! upon destruction. If USE_MS_CNGAPI is in effect, then
//! BCryptOpenAlgorithmProvider() acquires then handle and
//! BCryptCloseAlgorithmProvider() releases the handle upon destruction.
ProviderHandle GetProviderHandle() const {return m_hProvider;}
private:
ProviderHandle m_hProvider;
};
#if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI)
# pragma comment(lib, "advapi32.lib")
#endif
#if defined(_MSC_VER) && defined(USE_MS_CNGAPI)
# pragma comment(lib, "bcrypt.lib")
#endif
#endif //CRYPTOPP_WIN32_AVAILABLE
//! \class NonblockingRng
//! \brief Wrapper class for /dev/random and /dev/srandom
//! \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()
//! on Windows, or /dev/urandom on Unix and compatibles.
class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
{
public:
//! \brief Construct a NonblockingRng
NonblockingRng();
~NonblockingRng();
//! \brief Generate random array of bytes
//! \param output the byte buffer
//! \param size the length of the buffer, in bytes
//! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
void GenerateBlock(byte *output, size_t size);
protected:
#ifdef CRYPTOPP_WIN32_AVAILABLE
MicrosoftCryptoProvider m_Provider;
#else
int m_fd;
#endif
};
#endif
#if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
//! \class BlockingRng
//! \brief Wrapper class for /dev/random and /dev/srandom
//! \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
{
public:
//! \brief Construct a BlockingRng
BlockingRng();
~BlockingRng();
//! \brief Generate random array of bytes
//! \param output the byte buffer
//! \param size the length of the buffer, in bytes
//! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
void GenerateBlock(byte *output, size_t size);
protected:
int m_fd;
};
#endif
//! OS_GenerateRandomBlock
//! \brief Generate random array of bytes
//! \param blocking specifies whther a bobcking or non-blocking generator should be used
//! \param output the byte buffer
//! \param size the length of the buffer, in bytes
//! \details OS_GenerateRandomBlock() uses the underlying operating system's
//! random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
//! \details On Unix and compatibles, /dev/urandom is called if blocking is false using
//! NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
//! by way of BlockingRng, if available.
CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
//! \class AutoSeededRandomPool
//! \brief Automatically Seeded Randomness Pool
//! \details This class seeds itself using an operating system provided RNG.
//! AutoSeededRandomPool was suggested by Leonard Janke.
class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
{
public:
//! \brief Construct an AutoSeededRandomPool
//! \param blocking controls seeding with BlockingRng or NonblockingRng
//! \param seedSize the size of the seed, in bytes
//! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
//! The parameter is ignored if only one of these is available.
explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
{Reseed(blocking, seedSize);}
//! \brief Reseed an AutoSeededRandomPool
//! \param blocking controls seeding with BlockingRng or NonblockingRng
//! \param seedSize the size of the seed, in bytes
void Reseed(bool blocking = false, unsigned int seedSize = 32);
};
//! \class AutoSeededX917RNG
//! \tparam BLOCK_CIPHER a block cipher
//! \brief Automatically Seeded X9.17 RNG
//! \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
//! If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
//! used, then its a X9.31 conforming generator.
//! \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER can be any
//! BlockTransformation derived class.
//! \sa X917RNG, DefaultAutoSeededRNG
template <class BLOCK_CIPHER>
class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
{
public:
//! \brief Construct an AutoSeededX917RNG
//! \param blocking controls seeding with BlockingRng or NonblockingRng
//! \param autoSeed controls auto seeding of the generator
//! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
//! The parameter is ignored if only one of these is available.
//! \sa X917RNG
explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
{if (autoSeed) Reseed(blocking);}
//! \brief Reseed an AutoSeededX917RNG
//! \param blocking controls seeding with BlockingRng or NonblockingRng
//! \param additionalEntropy additional entropy to add to the generator
//! \param length the size of the additional entropy, in bytes
//! \details Internally, the generator uses SHA256 to extract the entropy from
//! from the seed and then stretch the material for the block cipher's key
//! and initialization vector.
void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0);
//! \brief Deterministically reseed an AutoSeededX917RNG for testing
//! \param key the key to use for the deterministic reseeding
//! \param keylength the size of the key, in bytes
//! \param seed the seed to use for the deterministic reseeding
//! \param timeVector a time vector to use for deterministic reseeding
//! \details This is a testing interface for testing purposes, and should \a NOT
//! be used in production.
void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
bool CanIncorporateEntropy() const {return true;}
void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
{m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
private:
member_ptr<RandomNumberGenerator> m_rng;
};
template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
{
m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
}
template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
{
SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
const byte *key;
do
{
OS_GenerateRandomBlock(blocking, seed, seed.size());
if (length > 0)
{
SHA256 hash;
hash.Update(seed, seed.size());
hash.Update(input, length);
hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
}
key = seed + BLOCK_CIPHER::BLOCKSIZE;
} // check that seed and key don't have same value
while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
}
CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
//! \class DefaultAutoSeededRNG
//! \brief A typedef providing a default generator
//! \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
//! If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
//! AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
class DefaultAutoSeededRNG {}
#else
// AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
#else
typedef AutoSeededRandomPool DefaultAutoSeededRNG;
#endif
#endif // CRYPTOPP_DOXYGEN_PROCESSING
NAMESPACE_END
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More