summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNvinside <Nvinside@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-09-28 21:16:09 +0000
committerNvinside <Nvinside@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-09-28 21:16:09 +0000
commit13988df650ab3b6f4909161d1f7cedac4f393a0f (patch)
tree1b63cef77b260d21b61bf4a7c8ebf717e99284c5
parentc797e6fa50865060670b9d1b8db497a1f2335b77 (diff)
This is part 2 of 4, this also fixes some x64 errors, warnings and allow you to build a full debug unicode
huuuuuge tipo fixes warning fixed (not all but many for this time) Prepare for a gpg-error change Support of ia32 AES instructions gpg error change Msvc compiler fixes Allow transient-key for ecdsa (würg-grund :D ) spelling fixes added new trigger events add a entropy gatherer for W32CE and some other stuff gcc fixes boooooooooooooost performance of SHA-512 and SHA-256 ... unfortunately that is all ;( ..... some work i'll be add maybe later this week git-svn-id: http://mirotr.googlecode.com/svn/trunk@38 eced67a3-f377-a0ae-92ae-d6de1850b05a
-rw-r--r--MirOTR.sln52
-rw-r--r--MirOTR/MirOTR.vcxproj48
-rw-r--r--MirOTR/svcs_proto.cpp61
-rw-r--r--ekhtml/vc9/EkHtml.vcxproj6
-rw-r--r--gpg.vs/libgcrypt-1.4.6.vs/libgcrypt146lib.vcxproj5
-rw-r--r--libgcrypt-1.4.6/cipher/cipher.c4304
-rw-r--r--libgcrypt-1.4.6/cipher/ecc.c23
-rw-r--r--libgcrypt-1.4.6/cipher/md.c2764
-rw-r--r--libgcrypt-1.4.6/cipher/primegen.c3724
-rw-r--r--libgcrypt-1.4.6/cipher/pubkey.c5498
-rw-r--r--libgcrypt-1.4.6/cipher/rijndael.c2506
-rw-r--r--libgcrypt-1.4.6/cipher/serpent.c1956
-rw-r--r--libgcrypt-1.4.6/cipher/sha512.c1258
-rw-r--r--libgcrypt-1.4.6/mpi/longlong.h3156
-rw-r--r--libgcrypt-1.4.6/mpi/mpi-bit.c730
-rw-r--r--libgcrypt-1.4.6/mpi/mpi-div.c716
-rw-r--r--libgcrypt-1.4.6/mpi/mpi-scan.c264
-rw-r--r--libgcrypt-1.4.6/mpi/mpicoder.c1503
-rw-r--r--libgcrypt-1.4.6/mpi/mpiutil.c923
-rw-r--r--libgcrypt-1.4.6/random/random-csprng.c2805
-rw-r--r--libgcrypt-1.4.6/random/random-fips.c23
-rw-r--r--libgcrypt-1.4.6/random/rndw32.c2
-rw-r--r--libgcrypt-1.4.6/src/ath.c140
-rw-r--r--libgcrypt-1.4.6/src/fips.c4
-rw-r--r--libgcrypt-1.4.6/src/gcrypt.h698
-rw-r--r--libgcrypt-1.4.6/src/gcrypt.h.in3684
-rw-r--r--libgcrypt-1.4.6/src/misc.c2
-rw-r--r--libgcrypt-1.4.6/src/sexp.c3950
-rw-r--r--libotr-3.2.0/src/auth.c2034
-rw-r--r--libotr-3.2.0/src/auth.h66
-rw-r--r--libotr-3.2.0/src/context.c332
-rw-r--r--libotr-3.2.0/src/message.c1420
-rw-r--r--libotr-3.2.0/src/privkey.c688
-rw-r--r--otr.vs/libotr-3.2.0.vs/libotr320.vcxproj2
34 files changed, 22722 insertions, 22625 deletions
diff --git a/MirOTR.sln b/MirOTR.sln
index c0fed68..5f3956d 100644
--- a/MirOTR.sln
+++ b/MirOTR.sln
@@ -17,30 +17,38 @@ Global
Release Unicode|x64 = Release Unicode|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|Win32.ActiveCfg = Debug|x64
- {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|x64.ActiveCfg = Release|x64
- {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|x64.Build.0 = Release|x64
- {53F841E8-284F-4545-9176-B131896E43F8}.Release Unicode|Win32.ActiveCfg = Release|x64
+ {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|Win32.ActiveCfg = Debug|Win32
+ {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|Win32.Build.0 = Debug|Win32
+ {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|x64.ActiveCfg = Debug|x64
+ {53F841E8-284F-4545-9176-B131896E43F8}.Debug Unicode|x64.Build.0 = Debug|x64
+ {53F841E8-284F-4545-9176-B131896E43F8}.Release Unicode|Win32.ActiveCfg = Release|Win32
+ {53F841E8-284F-4545-9176-B131896E43F8}.Release Unicode|Win32.Build.0 = Release|Win32
{53F841E8-284F-4545-9176-B131896E43F8}.Release Unicode|x64.ActiveCfg = Release|x64
{53F841E8-284F-4545-9176-B131896E43F8}.Release Unicode|x64.Build.0 = Release|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|Win32.ActiveCfg = Debug|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|x64.ActiveCfg = Release|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|x64.Build.0 = Release|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|Win32.ActiveCfg = Release|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|x64.ActiveCfg = Release|x64
- {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|x64.Build.0 = Release|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|Win32.ActiveCfg = Debug|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|x64.ActiveCfg = Release|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|x64.Build.0 = Release|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|Win32.ActiveCfg = Release|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|x64.ActiveCfg = Release|x64
- {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|x64.Build.0 = Release|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|Win32.ActiveCfg = Debug|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|x64.ActiveCfg = Release|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|x64.Build.0 = Release|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|Win32.ActiveCfg = Release|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|x64.ActiveCfg = Release|x64
- {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|x64.Build.0 = Release|x64
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|x64.ActiveCfg = Debug Unicode|x64
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Debug Unicode|x64.Build.0 = Debug Unicode|x64
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|x64.ActiveCfg = Release Unicode|x64
+ {1423FC8F-AA52-4562-8275-4BF0838CA378}.Release Unicode|x64.Build.0 = Release Unicode|x64
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|x64.ActiveCfg = Debug Unicode|x64
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Debug Unicode|x64.Build.0 = Debug Unicode|x64
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|x64.ActiveCfg = Release Unicode|x64
+ {40FE7861-E54E-4DA9-BE4D-A5178014E477}.Release Unicode|x64.Build.0 = Release Unicode|x64
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|x64.ActiveCfg = Debug Unicode|x64
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Debug Unicode|x64.Build.0 = Debug Unicode|x64
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|x64.ActiveCfg = Release Unicode|x64
+ {2C050CAF-D8AA-468A-B1A7-89F3BE99D3C8}.Release Unicode|x64.Build.0 = Release Unicode|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MirOTR/MirOTR.vcxproj b/MirOTR/MirOTR.vcxproj
index 363782b..8833f62 100644
--- a/MirOTR/MirOTR.vcxproj
+++ b/MirOTR/MirOTR.vcxproj
@@ -36,7 +36,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -60,17 +61,16 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\obj\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\obj\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\obj\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\obj\$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
@@ -85,6 +85,7 @@
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Users\CHEF-KOCH\Desktop\x64\mirotr\miranda\include;$(IncludePath)</IncludePath>
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">*.obj%3b*.ilk%3b*.tlb%3b*.tli%3b*.tlh%3b*.tmp%3b*.rsp%3b*.pch%3b*.pgc%3b*.pgd%3b*.meta%3b$(TargetPath)%3b$(TargetDir)$(ProjectName).*%3b$(TargetDir)$(RootNamespace).*;$(ExtensionsToDeleteOnClean)</ExtensionsToDeleteOnClean>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -93,33 +94,40 @@
<AdditionalIncludeDirectories>$(SolutionDir)\miranda\include;$(SolutionDir)\libotr-3.2.0\src;$(SolutionDir)\libgcrypt-1.4.6\src;$(SolutionDir)\libgpg-error-1.9\src;$(SolutionDir)\ekhtml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MIROTR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
- <ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
</ClCompile>
<Link>
- <AdditionalDependencies>libgcrypt.lib;libotr.lib;Comctl32.lib;EkHtml.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(SolutionDir)\gpg.vs\bin.vs\libgcrypt\$(Platform)\debug\static;$(SolutionDir)\otr.vs\bin.vs\libotr\$(Platform)\debug\static;$(SolutionDir)\ekhtml\vc9\$(Platform)\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>$(SolutionDir)\gpg.vs\bin.vs\libgcrypt\$(Platform)\Debug\static;$(SolutionDir)\otr.vs\bin.vs\libotr\$(Platform)\Debug\static;$(SolutionDir)\ekhtml\vc9\$(Platform)\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
+ <AdditionalDependencies>libgcrypt.lib;libotr.lib;Comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).dll</OutputFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
</Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_MBCS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalOptions>/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions)</AdditionalOptions>
- <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(SolutionDir)\miranda\include;$(SolutionDir)\libotr-3.2.0\src;$(SolutionDir)\libgcrypt-1.4.6\src;$(SolutionDir)\libgpg-error-1.9\src;$(SolutionDir)\ekhtml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MIROTR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<ProgramDataBaseFileName>$(TargetDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <StringPooling>true</StringPooling>
</ClCompile>
<Link>
<AdditionalDependencies>libgcrypt.lib;libotr.lib;Comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -132,7 +140,7 @@
<ClCompile>
<AdditionalOptions>/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_NON_CONFORMING_SWPRINTFS" %(AdditionalOptions)</AdditionalOptions>
<Optimization>Full</Optimization>
- <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>$(SolutionDir)\miranda\include;$(SolutionDir)\libotr-3.2.0\src;$(SolutionDir)\libgcrypt-1.4.6\src;$(SolutionDir)\libgpg-error-1.9\src;$(SolutionDir)\ekhtml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -145,18 +153,19 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<StringPooling>true</StringPooling>
<FloatingPointModel>Fast</FloatingPointModel>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <OmitFramePointers>true</OmitFramePointers>
+ <OmitFramePointers>false</OmitFramePointers>
+ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
</ClCompile>
<Link>
<AdditionalDependencies>libgcrypt.lib;libotr.lib;Comctl32.lib;EkHtml.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(SolutionDir)\gpg.vs\bin.vs\libgcrypt\$(Platform)\release\static;$(SolutionDir)\otr.vs\bin.vs\libotr\$(Platform)\release\static;$(SolutionDir)\ekhtml\vc9\$(Platform)\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>$(SolutionDir)\gpg.vs\bin.vs\libgcrypt\$(Platform)\release\static;$(SolutionDir)\otr.vs\bin.vs\libotr\$(Platform)\release\static;$(SolutionDir)\ekhtml\vc9\$(Platform)\Release Unicode\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
- <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+ <ImportLibrary>
+ </ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -174,6 +183,7 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <StringPooling>true</StringPooling>
</ClCompile>
<Link>
<AdditionalDependencies>libgcrypt.lib;libotr.lib;Comctl32.lib;EkHtml.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -182,6 +192,8 @@
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/MirOTR/svcs_proto.cpp b/MirOTR/svcs_proto.cpp
index d1991fb..c4b193c 100644
--- a/MirOTR/svcs_proto.cpp
+++ b/MirOTR/svcs_proto.cpp
@@ -2,6 +2,10 @@
#include "svcs_proto.h"
#include "striphtml.h"
#include "entities.h"
+#include <winuser.h>
+#include <sys\stat.h>
+#include <ole.h>
+#include <wtypes.h>
//TODO: Social-Millionaire-Dialoge
INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
@@ -16,7 +20,7 @@ INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts
- return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
if(!proto || !ccs->hContact) return 1; // error
gcry_error_t err;
@@ -67,7 +71,7 @@ INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
/* Be *sure* not to send out plaintext */
ShowError(TranslateT(LANG_ENCRYPTION_ERROR));
/* should not be needed
- char t[3] = {0, 0, 0};
+ char t[3] = {0, 0, 0};
if(ccs->wParam & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
if (strlen(oldmessage)) memcpy(oldmessage, t,3 );
} else {
@@ -87,7 +91,7 @@ INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
// move the last fragment to newmessage, oldmessage_utf will be buffer later
newmessage = oldmessage_utf;
- WPARAM oldflags = ccs->wParam;
+ WPARAM oldflags = ccs->wParam;
if(ccs->wParam & PREF_UTF) {
ccs->lParam = (LPARAM)newmessage;
} else if(ccs->wParam & PREF_UNICODE) {
@@ -102,22 +106,23 @@ INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){
ccs->lParam = (LPARAM)newmessage;
}
if (otr_context_get_trust(context) >= TRUST_UNVERIFIED) ccs->wParam;
- INT_PTR ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ INT_PTR ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam);
-/*#ifdef _DEBUG
+#ifdef _DEBUG
if(ccs->wParam & PREF_UNICODE)
- MessageBox(0, (wchar_t *)ccs->lParam, _T("OTR - sending raw message"), MB_OK);
+ MessageBox(0, (const char *)ccs->lParam, _T("OTR - sending raw message"), MB_OK);
else
- MessageBoxA(0, (char *)ccs->lParam, ("OTR - sending raw message"), MB_OK);
- #endif*/
+ MessageBoxA(0, (char *)ccs->lParam, ("OTR - sending raw message"), MB_OK);
+ #endif
// reset to original values
+
ccs->lParam = (LPARAM)oldmessage;
ccs->wParam = oldflags;
otrl_message_free(newmessage);
- return ret;
-
- }
+ return ret;
+
+ }
return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
}
@@ -144,7 +149,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
#ifdef _DEBUG
if(pre->flags & PREF_UNICODE)
- MessageBox(0, (wchar_t *)pre->szMessage, _T("OTR - receiving message"), MB_OK);
+ MessageBox(0, (const char *)pre->szMessage, _T("OTR - receiving message"), MB_OK);
else
MessageBoxA(0, (char *)pre->szMessage, ("OTR - receiving message"), MB_OK);
#endif
@@ -195,7 +200,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
if (tlv) {
- /* Notify the user that the other side disconnected. */
+ /* Notify the user that the other side disconnected. */
TCHAR buff[256];
mir_sntprintf(buff, 256, TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(ccs->hContact));
//MessageBox(0, buff, Translate("OTR Information"), MB_OK);
@@ -279,7 +284,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
if (nextMsg != OTRL_SMP_EXPECT4)
otr_abort_smp(context);
else {
- SMPDialogUpdate(context, 100);
+ SMPDialogUpdate(context, 100);
//otrg_dialog_update_smp(context, 1.0);
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
}
@@ -287,7 +292,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
if (tlv) {
SMPDialogUpdate(context, 0);
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
}
}
}
@@ -295,23 +300,23 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
/* If we're supposed to ignore this incoming message (because it's a
* protocol message), set it to NULL, so that other plugins that
- * catch receiving-im-msg don't return 0, and cause it to be
+ * catch receiving-im-msg don't return 0, and cause it to be
* displayed anyway. */
if (ignore_msg) {
/* should not be required ;)
- char t[3] = {0, 0, 0};
- char t[3] = {0, 0, 0};
+ char t[3] = {0, 0, 0};
+ char t[3] = {0, 0, 0};
if(pre->flags & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t,3 );
} else {
if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t, 1);
- }
- */
+ }
+ */
if (newmessage) otrl_message_free(newmessage);
return 1;
} else if (newmessage) {
//bool free=false;
- DWORD flags = pre->flags;
+ DWORD flags = pre->flags;
/* if(pre->flags & PREF_UTF) {
oldmessage_utf = newmessage;
} else if(pre->flags & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
@@ -320,8 +325,8 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
} else {
mir_utf8decode(newmessage, NULL);
oldmessage_utf = newmessage;
- } */
-
+ } */
+
//pre->szMessage = oldmessage_utf;
pre->flags &= ~PREF_UNICODE;
pre->flags |= PREF_UTF; // just use UTF, so we do not have to recode the message
@@ -360,7 +365,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
otrl_message_free(newmessage);
// if (free) mir_free(oldmessage_utf);
- return ret;
+ return ret;
}
return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
@@ -370,7 +375,7 @@ INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
* are received. */
void otr_abort_smp(ConnContext *context)
{
- otrl_message_abort_smp(otr_user_state, &ops, context->app_data, context);
+ otrl_message_abort_smp(otr_user_state, &ops, context->app_data, context);
}
/* Start the Socialist Millionaires' Protocol over the current connection,
@@ -379,8 +384,8 @@ void otr_abort_smp(ConnContext *context)
void otr_start_smp(ConnContext *context, const char *question,
const unsigned char *secret, size_t secretlen)
{
- otrl_message_initiate_smp_q(otr_user_state, &ops, context->app_data,
- context, question, secret, secretlen);
+ otrl_message_initiate_smp_q(otr_user_state, &ops, context->app_data,
+ context, question, secret, secretlen);
}
/* Continue the Socialist Millionaires' Protocol over the current connection,
@@ -389,5 +394,5 @@ void otr_continue_smp(ConnContext *context,
const unsigned char *secret, size_t secretlen)
{
otrl_message_respond_smp(otr_user_state, &ops, context->app_data,
- context, secret, secretlen);
+ context, secret, secretlen);
} \ No newline at end of file
diff --git a/ekhtml/vc9/EkHtml.vcxproj b/ekhtml/vc9/EkHtml.vcxproj
index 12e4f00..628013b 100644
--- a/ekhtml/vc9/EkHtml.vcxproj
+++ b/ekhtml/vc9/EkHtml.vcxproj
@@ -36,7 +36,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
+ <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -80,6 +80,7 @@
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">*.obj%3b*.ilk%3b*.tlb%3b*.tli%3b*.tlh%3b*.tmp%3b*.rsp%3b*.pch%3b*.pgc%3b*.pgd%3b*.meta%3b$(TargetPath)%3b$(TargetDir)$(ProjectName).*%3b$(TargetDir)$(RootNamespace).*;$(ExtensionsToDeleteOnClean)</ExtensionsToDeleteOnClean>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
<ClCompile>
@@ -89,8 +90,7 @@
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
diff --git a/gpg.vs/libgcrypt-1.4.6.vs/libgcrypt146lib.vcxproj b/gpg.vs/libgcrypt-1.4.6.vs/libgcrypt146lib.vcxproj
index b14fafd..5f9572b 100644
--- a/gpg.vs/libgcrypt-1.4.6.vs/libgcrypt146lib.vcxproj
+++ b/gpg.vs/libgcrypt-1.4.6.vs/libgcrypt146lib.vcxproj
@@ -26,6 +26,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -84,6 +85,7 @@
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">*.obj%3b*.ilk%3b*.tlb%3b*.tli%3b*.tlh%3b*.tmp%3b*.rsp%3b*.pch%3b*.pgc%3b*.pgd%3b*.meta%3b$(TargetPath)%3b$(TargetDir)$(ProjectName).*%3b$(TargetDir)$(RootNamespace).*</ExtensionsToDeleteOnClean>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<ClCompile>
@@ -161,7 +163,8 @@
<ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <MinimalRebuild>true</MinimalRebuild>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
diff --git a/libgcrypt-1.4.6/cipher/cipher.c b/libgcrypt-1.4.6/cipher/cipher.c
index 8cfe54f..1948b91 100644
--- a/libgcrypt-1.4.6/cipher/cipher.c
+++ b/libgcrypt-1.4.6/cipher/cipher.c
@@ -1,2133 +1,2171 @@
-/* cipher.c - cipher dispatcher
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "g10lib.h"
-#include "cipher.h"
-#include "ath.h"
-
-#define MAX_BLOCKSIZE 16
-#define TABLE_SIZE 14
-#define CTX_MAGIC_NORMAL 0x24091964
-#define CTX_MAGIC_SECURE 0x46919042
-
-#undef NEED_16BYTE_ALIGNED_CONTEXT
-#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
-#define NEED_16BYTE_ALIGNED_CONTEXT 1
-#endif
-
-/* A dummy extraspec so that we do not need to tests the extraspec
- field from the module specification against NULL and instead
- directly test the respective fields of extraspecs. */
-static cipher_extra_spec_t dummy_extra_spec;
-
-/* This is the list of the default ciphers, which are included in
- libgcrypt. */
-static struct cipher_table_entry
-{
- gcry_cipher_spec_t *cipher;
- cipher_extra_spec_t *extraspec;
- unsigned int algorithm;
- int fips_allowed;
-} cipher_table[] =
- {
-#if USE_BLOWFISH
- { &_gcry_cipher_spec_blowfish,
- &dummy_extra_spec, GCRY_CIPHER_BLOWFISH },
-#endif
-#if USE_DES
- { &_gcry_cipher_spec_des,
- &dummy_extra_spec, GCRY_CIPHER_DES },
- { &_gcry_cipher_spec_tripledes,
- &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 },
-#endif
-#if USE_ARCFOUR
- { &_gcry_cipher_spec_arcfour,
- &dummy_extra_spec, GCRY_CIPHER_ARCFOUR },
-#endif
-#if USE_CAST5
- { &_gcry_cipher_spec_cast5,
- &dummy_extra_spec, GCRY_CIPHER_CAST5 },
-#endif
-#if USE_AES
- { &_gcry_cipher_spec_aes,
- &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 },
- { &_gcry_cipher_spec_aes192,
- &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 },
- { &_gcry_cipher_spec_aes256,
- &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 },
-#endif
-#if USE_TWOFISH
- { &_gcry_cipher_spec_twofish,
- &dummy_extra_spec, GCRY_CIPHER_TWOFISH },
- { &_gcry_cipher_spec_twofish128,
- &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 },
-#endif
-#if USE_SERPENT
- { &_gcry_cipher_spec_serpent128,
- &dummy_extra_spec, GCRY_CIPHER_SERPENT128 },
- { &_gcry_cipher_spec_serpent192,
- &dummy_extra_spec, GCRY_CIPHER_SERPENT192 },
- { &_gcry_cipher_spec_serpent256,
- &dummy_extra_spec, GCRY_CIPHER_SERPENT256 },
-#endif
-#if USE_RFC2268
- { &_gcry_cipher_spec_rfc2268_40,
- &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 },
-#endif
-#if USE_SEED
- { &_gcry_cipher_spec_seed,
- &dummy_extra_spec, GCRY_CIPHER_SEED },
-#endif
-#if USE_CAMELLIA
- { &_gcry_cipher_spec_camellia128,
- &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 },
- { &_gcry_cipher_spec_camellia192,
- &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 },
- { &_gcry_cipher_spec_camellia256,
- &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 },
-#endif
- { NULL }
- };
-
-/* List of registered ciphers. */
-static gcry_module_t ciphers_registered;
-
-/* This is the lock protecting CIPHERS_REGISTERED. */
-static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER;
-
-/* Flag to check wether the default ciphers have already been
- registered. */
-static int default_ciphers_registered;
-
-/* Convenient macro for registering the default ciphers. */
-#define REGISTER_DEFAULT_CIPHERS \
- do \
- { \
- ath_mutex_lock (&ciphers_registered_lock); \
- if (! default_ciphers_registered) \
- { \
- cipher_register_default (); \
- default_ciphers_registered = 1; \
- } \
- ath_mutex_unlock (&ciphers_registered_lock); \
- } \
- while (0)
-
-
-/* A VIA processor with the Padlock engine requires an alignment of
- most data on a 16 byte boundary. Because we trick out the compiler
- while allocating the context, the align attribute as used in
- rijndael.c does not work on its own. Thus we need to make sure
- that the entire context structure is a aligned on that boundary.
- We achieve this by defining a new type and use that instead of our
- usual alignment type. */
-typedef union
-{
- PROPERLY_ALIGNED_TYPE foo;
-#ifdef NEED_16BYTE_ALIGNED_CONTEXT
- char bar[16] __attribute__ ((aligned (16)));
-#endif
- char c[1];
-} cipher_context_alignment_t;
-
-
-/* The handle structure. */
-struct gcry_cipher_handle
-{
- int magic;
- size_t actual_handle_size; /* Allocated size of this handle. */
- size_t handle_offset; /* Offset to the malloced block. */
- gcry_cipher_spec_t *cipher;
- cipher_extra_spec_t *extraspec;
- gcry_module_t module;
-
- /* The algorithm id. This is a hack required because the module
- interface does not easily allow to retrieve this value. */
- int algo;
-
- /* A structure with function pointers for bulk operations. Due to
- limitations of the module system (we don't want to change the
- API) we need to keep these function pointers here. The cipher
- open function intializes them and the actual encryption routines
- use them if they are not NULL. */
- struct {
- void (*cfb_enc)(void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks);
- void (*cfb_dec)(void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks);
- void (*cbc_enc)(void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks, int cbc_mac);
- void (*cbc_dec)(void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks);
- } bulk;
-
-
- int mode;
- unsigned int flags;
-
- struct {
- unsigned int key:1; /* Set to 1 if a key has been set. */
- unsigned int iv:1; /* Set to 1 if a IV has been set. */
- } marks;
-
- /* The initialization vector. To help code optimization we make
- sure that it is aligned on an unsigned long and u32 boundary. */
- union {
- unsigned long dummy_iv;
- u32 dummy_u32_iv;
- unsigned char iv[MAX_BLOCKSIZE];
- } u_iv;
-
- unsigned char lastiv[MAX_BLOCKSIZE];
- int unused; /* Number of unused bytes in the IV. */
-
- unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */
-
-
- /* What follows are two contexts of the cipher in use. The first
- one needs to be aligned well enough for the cipher operation
- whereas the second one is a copy created by cipher_setkey and
- used by cipher_reset. That second copy has no need for proper
- aligment because it is only accessed by memcpy. */
- cipher_context_alignment_t context;
-};
-
-
-
-/* These dummy functions are used in case a cipher implementation
- refuses to provide it's own functions. */
-
-static gcry_err_code_t
-dummy_setkey (void *c, const unsigned char *key, unsigned int keylen)
-{
- (void)c;
- (void)key;
- (void)keylen;
- return GPG_ERR_NO_ERROR;
-}
-
-static void
-dummy_encrypt_block (void *c,
- unsigned char *outbuf, const unsigned char *inbuf)
-{
- (void)c;
- (void)outbuf;
- (void)inbuf;
- BUG();
-}
-
-static void
-dummy_decrypt_block (void *c,
- unsigned char *outbuf, const unsigned char *inbuf)
-{
- (void)c;
- (void)outbuf;
- (void)inbuf;
- BUG();
-}
-
-static void
-dummy_encrypt_stream (void *c,
- unsigned char *outbuf, const unsigned char *inbuf,
- unsigned int n)
-{
- (void)c;
- (void)outbuf;
- (void)inbuf;
- (void)n;
- BUG();
-}
-
-static void
-dummy_decrypt_stream (void *c,
- unsigned char *outbuf, const unsigned char *inbuf,
- unsigned int n)
-{
- (void)c;
- (void)outbuf;
- (void)inbuf;
- (void)n;
- BUG();
-}
-
-
-/* Internal function. Register all the ciphers included in
- CIPHER_TABLE. Note, that this function gets only used by the macro
- REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */
-static void
-cipher_register_default (void)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- int i;
-
- for (i = 0; !err && cipher_table[i].cipher; i++)
- {
- if (! cipher_table[i].cipher->setkey)
- cipher_table[i].cipher->setkey = dummy_setkey;
- if (! cipher_table[i].cipher->encrypt)
- cipher_table[i].cipher->encrypt = dummy_encrypt_block;
- if (! cipher_table[i].cipher->decrypt)
- cipher_table[i].cipher->decrypt = dummy_decrypt_block;
- if (! cipher_table[i].cipher->stencrypt)
- cipher_table[i].cipher->stencrypt = dummy_encrypt_stream;
- if (! cipher_table[i].cipher->stdecrypt)
- cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream;
-
- if ( fips_mode () && !cipher_table[i].fips_allowed )
- continue;
-
- err = _gcry_module_add (&ciphers_registered,
- cipher_table[i].algorithm,
- (void *) cipher_table[i].cipher,
- (void *) cipher_table[i].extraspec,
- NULL);
- }
-
- if (err)
- BUG ();
-}
-
-/* Internal callback function. Used via _gcry_module_lookup. */
-static int
-gcry_cipher_lookup_func_name (void *spec, void *data)
-{
- gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
- char *name = (char *) data;
- const char **aliases = cipher->aliases;
- int i, ret = ! stricmp (name, cipher->name);
-
- if (aliases)
- for (i = 0; aliases[i] && (! ret); i++)
- ret = ! stricmp (name, aliases[i]);
-
- return ret;
-}
-
-/* Internal callback function. Used via _gcry_module_lookup. */
-static int
-gcry_cipher_lookup_func_oid (void *spec, void *data)
-{
- gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
- char *oid = (char *) data;
- gcry_cipher_oid_spec_t *oid_specs = cipher->oids;
- int ret = 0, i;
-
- if (oid_specs)
- for (i = 0; oid_specs[i].oid && (! ret); i++)
- if (! stricmp (oid, oid_specs[i].oid))
- ret = 1;
-
- return ret;
-}
-
-/* Internal function. Lookup a cipher entry by it's name. */
-static gcry_module_t
-gcry_cipher_lookup_name (const char *name)
-{
- gcry_module_t cipher;
-
- cipher = _gcry_module_lookup (ciphers_registered, (void *) name,
- gcry_cipher_lookup_func_name);
-
- return cipher;
-}
-
-/* Internal function. Lookup a cipher entry by it's oid. */
-static gcry_module_t
-gcry_cipher_lookup_oid (const char *oid)
-{
- gcry_module_t cipher;
-
- cipher = _gcry_module_lookup (ciphers_registered, (void *) oid,
- gcry_cipher_lookup_func_oid);
-
- return cipher;
-}
-
-/* Register a new cipher module whose specification can be found in
- CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID
- and a pointer representhing this module is stored in MODULE. */
-gcry_error_t
-_gcry_cipher_register (gcry_cipher_spec_t *cipher,
- cipher_extra_spec_t *extraspec,
- int *algorithm_id,
- gcry_module_t *module)
-{
- gcry_err_code_t err = 0;
- gcry_module_t mod;
-
- /* We do not support module loading in fips mode. */
- if (fips_mode ())
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
- ath_mutex_lock (&ciphers_registered_lock);
- err = _gcry_module_add (&ciphers_registered, 0,
- (void *)cipher,
- (void *)(extraspec? extraspec : &dummy_extra_spec),
- &mod);
- ath_mutex_unlock (&ciphers_registered_lock);
-
- if (! err)
- {
- *module = mod;
- *algorithm_id = mod->mod_id;
- }
-
- return gcry_error (err);
-}
-
-/* Unregister the cipher identified by MODULE, which must have been
- registered with gcry_cipher_register. */
-void
-gcry_cipher_unregister (gcry_module_t module)
-{
- ath_mutex_lock (&ciphers_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&ciphers_registered_lock);
-}
-
-/* Locate the OID in the oid table and return the index or -1 when not
- found. An opitonal "oid." or "OID." prefix in OID is ignored, the
- OID is expected to be in standard IETF dotted notation. The
- internal algorithm number is returned in ALGORITHM unless it
- ispassed as NULL. A pointer to the specification of the module
- implementing this algorithm is return in OID_SPEC unless passed as
- NULL.*/
-static int
-search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec)
-{
- gcry_module_t module;
- int ret = 0;
-
- if (oid && ((! strncmp (oid, "oid.", 4))
- || (! strncmp (oid, "OID.", 4))))
- oid += 4;
-
- module = gcry_cipher_lookup_oid (oid);
- if (module)
- {
- gcry_cipher_spec_t *cipher = module->spec;
- int i;
-
- for (i = 0; cipher->oids[i].oid && !ret; i++)
- if (! stricmp (oid, cipher->oids[i].oid))
- {
- if (algorithm)
- *algorithm = module->mod_id;
- if (oid_spec)
- *oid_spec = cipher->oids[i];
- ret = 1;
- }
- _gcry_module_release (module);
- }
-
- return ret;
-}
-
-/* Map STRING to the cipher algorithm identifier. Returns the
- algorithm ID of the cipher for the given name or 0 if the name is
- not known. It is valid to pass NULL for STRING which results in a
- return value of 0. */
-int
-gcry_cipher_map_name (const char *string)
-{
- gcry_module_t cipher;
- int ret, algorithm = 0;
-
- if (! string)
- return 0;
-
- REGISTER_DEFAULT_CIPHERS;
-
- /* If the string starts with a digit (optionally prefixed with
- either "OID." or "oid."), we first look into our table of ASN.1
- object identifiers to figure out the algorithm */
-
- ath_mutex_lock (&ciphers_registered_lock);
-
- ret = search_oid (string, &algorithm, NULL);
- if (! ret)
- {
- cipher = gcry_cipher_lookup_name (string);
- if (cipher)
- {
- algorithm = cipher->mod_id;
- _gcry_module_release (cipher);
- }
- }
-
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return algorithm;
-}
-
-
-/* Given a STRING with an OID in dotted decimal notation, this
- function returns the cipher mode (GCRY_CIPHER_MODE_*) associated
- with that OID or 0 if no mode is known. Passing NULL for string
- yields a return value of 0. */
-int
-gcry_cipher_mode_from_oid (const char *string)
-{
- gcry_cipher_oid_spec_t oid_spec;
- int ret = 0, mode = 0;
-
- if (!string)
- return 0;
-
- ath_mutex_lock (&ciphers_registered_lock);
- ret = search_oid (string, NULL, &oid_spec);
- if (ret)
- mode = oid_spec.mode;
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return mode;
-}
-
-
-/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
- string representation of the algorithm name. For unknown algorithm
- IDs this function returns "?". */
-static const char *
-cipher_algo_to_string (int algorithm)
-{
- gcry_module_t cipher;
- const char *name;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
- if (cipher)
- {
- name = ((gcry_cipher_spec_t *) cipher->spec)->name;
- _gcry_module_release (cipher);
- }
- else
- name = "?";
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return name;
-}
-
-/* Map the cipher algorithm identifier ALGORITHM to a string
- representing this algorithm. This string is the default name as
- used by Libgcrypt. An pointer to an empty string is returned for
- an unknown algorithm. NULL is never returned. */
-const char *
-gcry_cipher_algo_name (int algorithm)
-{
- return cipher_algo_to_string (algorithm);
-}
-
-
-/* Flag the cipher algorithm with the identifier ALGORITHM as
- disabled. There is no error return, the function does nothing for
- unknown algorithms. Disabled algorithms are vitually not available
- in Libgcrypt. */
-static void
-disable_cipher_algo (int algorithm)
-{
- gcry_module_t cipher;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
- if (cipher)
- {
- if (! (cipher->flags & FLAG_MODULE_DISABLED))
- cipher->flags |= FLAG_MODULE_DISABLED;
- _gcry_module_release (cipher);
- }
- ath_mutex_unlock (&ciphers_registered_lock);
-}
-
-
-/* Return 0 if the cipher algorithm with identifier ALGORITHM is
- available. Returns a basic error code value if it is not
- available. */
-static gcry_err_code_t
-check_cipher_algo (int algorithm)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_module_t cipher;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
- if (cipher)
- {
- if (cipher->flags & FLAG_MODULE_DISABLED)
- err = GPG_ERR_CIPHER_ALGO;
- _gcry_module_release (cipher);
- }
- else
- err = GPG_ERR_CIPHER_ALGO;
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return err;
-}
-
-
-/* Return the standard length of the key for the cipher algorithm with
- the identifier ALGORITHM. This function expects a valid algorithm
- and will abort if the algorithm is not available or the length of
- the key is not known. */
-static unsigned int
-cipher_get_keylen (int algorithm)
-{
- gcry_module_t cipher;
- unsigned len = 0;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
- if (cipher)
- {
- len = ((gcry_cipher_spec_t *) cipher->spec)->keylen;
- if (!len)
- log_bug ("cipher %d w/o key length\n", algorithm);
- _gcry_module_release (cipher);
- }
- else
- log_bug ("cipher %d not found\n", algorithm);
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return len;
-}
-
-/* Return the block length of the cipher algorithm with the identifier
- ALGORITHM. This function expects a valid algorithm and will abort
- if the algorithm is not available or the length of the key is not
- known. */
-static unsigned int
-cipher_get_blocksize (int algorithm)
-{
- gcry_module_t cipher;
- unsigned len = 0;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
- if (cipher)
- {
- len = ((gcry_cipher_spec_t *) cipher->spec)->blocksize;
- if (! len)
- log_bug ("cipher %d w/o blocksize\n", algorithm);
- _gcry_module_release (cipher);
- }
- else
- log_bug ("cipher %d not found\n", algorithm);
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return len;
-}
-
-
-/*
- Open a cipher handle for use with cipher algorithm ALGORITHM, using
- the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
- handle in HANDLE. Put NULL into HANDLE and return an error code if
- something goes wrong. FLAGS may be used to modify the
- operation. The defined flags are:
-
- GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory.
- GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP.
- GCRY_CIPHER_CBC_CTS: Enable CTS mode.
- GCRY_CIPHER_CBC_MAC: Enable MAC mode.
-
- Values for these flags may be combined using OR.
- */
-gcry_error_t
-gcry_cipher_open (gcry_cipher_hd_t *handle,
- int algo, int mode, unsigned int flags)
-{
- int secure = (flags & GCRY_CIPHER_SECURE);
- gcry_cipher_spec_t *cipher = NULL;
- cipher_extra_spec_t *extraspec = NULL;
- gcry_module_t module = NULL;
- gcry_cipher_hd_t h = NULL;
- gcry_err_code_t err = 0;
-
- /* If the application missed to call the random poll function, we do
- it here to ensure that it is used once in a while. */
- _gcry_fast_random_poll ();
-
- REGISTER_DEFAULT_CIPHERS;
-
- /* Fetch the according module and check wether the cipher is marked
- available for use. */
- ath_mutex_lock (&ciphers_registered_lock);
- module = _gcry_module_lookup_id (ciphers_registered, algo);
- if (module)
- {
- /* Found module. */
-
- if (module->flags & FLAG_MODULE_DISABLED)
- {
- /* Not available for use. */
- err = GPG_ERR_CIPHER_ALGO;
- _gcry_module_release (module);
- }
- else
- {
- cipher = (gcry_cipher_spec_t *) module->spec;
- extraspec = module->extraspec;
- }
- }
- else
- err = GPG_ERR_CIPHER_ALGO;
- ath_mutex_unlock (&ciphers_registered_lock);
-
- /* check flags */
- if ((! err)
- && ((flags & ~(0
- | GCRY_CIPHER_SECURE
- | GCRY_CIPHER_ENABLE_SYNC
- | GCRY_CIPHER_CBC_CTS
- | GCRY_CIPHER_CBC_MAC))
- || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
- err = GPG_ERR_CIPHER_ALGO;
-
- /* check that a valid mode has been requested */
- if (! err)
- switch (mode)
- {
- case GCRY_CIPHER_MODE_ECB:
- case GCRY_CIPHER_MODE_CBC:
- case GCRY_CIPHER_MODE_CFB:
- case GCRY_CIPHER_MODE_OFB:
- case GCRY_CIPHER_MODE_CTR:
- case GCRY_CIPHER_MODE_AESWRAP:
- if ((cipher->encrypt == dummy_encrypt_block)
- || (cipher->decrypt == dummy_decrypt_block))
- err = GPG_ERR_INV_CIPHER_MODE;
- break;
-
- case GCRY_CIPHER_MODE_STREAM:
- if ((cipher->stencrypt == dummy_encrypt_stream)
- || (cipher->stdecrypt == dummy_decrypt_stream))
- err = GPG_ERR_INV_CIPHER_MODE;
- break;
-
- case GCRY_CIPHER_MODE_NONE:
- /* This mode may be used for debugging. It copies the main
- text verbatim to the ciphertext. We do not allow this in
- fips mode or if no debug flag has been set. */
- if (fips_mode () || !_gcry_get_debug_flag (0))
- err = GPG_ERR_INV_CIPHER_MODE;
- break;
-
- default:
- err = GPG_ERR_INV_CIPHER_MODE;
- }
-
- /* Perform selftest here and mark this with a flag in cipher_table?
- No, we should not do this as it takes too long. Further it does
- not make sense to exclude algorithms with failing selftests at
- runtime: If a selftest fails there is something seriously wrong
- with the system and thus we better die immediately. */
-
- if (! err)
- {
- size_t size = (sizeof (*h)
- + 2 * cipher->contextsize
- - sizeof (cipher_context_alignment_t)
-#ifdef NEED_16BYTE_ALIGNED_CONTEXT
- + 15 /* Space for leading alignment gap. */
-#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
- );
-
- if (secure)
- h = gcry_calloc_secure (1, size);
- else
- h = gcry_calloc (1, size);
-
- if (! h)
- err = gpg_err_code_from_errno (errno);
- else
- {
- size_t off = 0;
-
-#ifdef NEED_16BYTE_ALIGNED_CONTEXT
- if ( ((unsigned long)h & 0x0f) )
- {
- /* The malloced block is not aligned on a 16 byte
- boundary. Correct for this. */
- off = 16 - ((unsigned long)h & 0x0f);
- h = (void*)((char*)h + off);
- }
-#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
-
- h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
- h->actual_handle_size = size - off;
- h->handle_offset = off;
- h->cipher = cipher;
- h->extraspec = extraspec;
- h->module = module;
- h->algo = algo;
- h->mode = mode;
- h->flags = flags;
-
- /* Setup bulk encryption routines. */
- switch (algo)
- {
-#ifdef USE_AES
- case GCRY_CIPHER_AES128:
- case GCRY_CIPHER_AES192:
- case GCRY_CIPHER_AES256:
- h->bulk.cfb_enc = _gcry_aes_cfb_enc;
- h->bulk.cfb_dec = _gcry_aes_cfb_dec;
- h->bulk.cbc_enc = _gcry_aes_cbc_enc;
- h->bulk.cbc_dec = _gcry_aes_cbc_dec;
- break;
-#endif /*USE_AES*/
-
- default:
- break;
- }
- }
- }
-
- /* Done. */
-
- if (err)
- {
- if (module)
- {
- /* Release module. */
- ath_mutex_lock (&ciphers_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&ciphers_registered_lock);
- }
- }
-
- *handle = err ? NULL : h;
-
- return gcry_error (err);
-}
-
-
-/* Release all resources associated with the cipher handle H. H may be
- NULL in which case this is a no-operation. */
-void
-gcry_cipher_close (gcry_cipher_hd_t h)
-{
- size_t off;
-
- if (!h)
- return;
-
- if ((h->magic != CTX_MAGIC_SECURE)
- && (h->magic != CTX_MAGIC_NORMAL))
- _gcry_fatal_error(GPG_ERR_INTERNAL,
- "gcry_cipher_close: already closed/invalid handle");
- else
- h->magic = 0;
-
- /* Release module. */
- ath_mutex_lock (&ciphers_registered_lock);
- _gcry_module_release (h->module);
- ath_mutex_unlock (&ciphers_registered_lock);
-
- /* We always want to wipe out the memory even when the context has
- been allocated in secure memory. The user might have disabled
- secure memory or is using his own implementation which does not
- do the wiping. To accomplish this we need to keep track of the
- actual size of this structure because we have no way to known
- how large the allocated area was when using a standard malloc. */
- off = h->handle_offset;
- wipememory (h, h->actual_handle_size);
-
- gcry_free ((char*)h - off);
-}
-
-
-/* Set the key to be used for the encryption context C to KEY with
- length KEYLEN. The length should match the required length. */
-static gcry_error_t
-cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen)
-{
- gcry_err_code_t ret;
-
- ret = (*c->cipher->setkey) (&c->context.c, key, keylen);
- if (!ret)
- {
- /* Duplicate initial context. */
- memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize),
- (void *) &c->context.c,
- c->cipher->contextsize);
- c->marks.key = 1;
- }
- else
- c->marks.key = 0;
-
- return gcry_error (ret);
-}
-
-
-/* Set the IV to be used for the encryption context C to IV with
- length IVLEN. The length should match the required length. */
-static void
-cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
-{
- memset (c->u_iv.iv, 0, c->cipher->blocksize);
- if (iv)
- {
- if (ivlen != c->cipher->blocksize)
- {
- log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
- ivlen, (unsigned int)c->cipher->blocksize);
- fips_signal_error ("IV length does not match blocklength");
- }
- if (ivlen > c->cipher->blocksize)
- ivlen = c->cipher->blocksize;
- memcpy (c->u_iv.iv, iv, ivlen);
- c->marks.iv = 1;
- }
- else
- c->marks.iv = 0;
-
- c->unused = 0;
-}
-
-
-/* Reset the cipher context to the initial context. This is basically
- the same as an release followed by a new. */
-static void
-cipher_reset (gcry_cipher_hd_t c)
-{
- memcpy (&c->context.c,
- (char *) &c->context.c + c->cipher->contextsize,
- c->cipher->contextsize);
- memset (&c->marks, 0, sizeof c->marks);
- memset (c->u_iv.iv, 0, c->cipher->blocksize);
- memset (c->lastiv, 0, c->cipher->blocksize);
- memset (c->ctr, 0, c->cipher->blocksize);
-}
-
-
-static void
-do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nblocks )
-{
- unsigned int n;
-
- for (n=0; n < nblocks; n++ )
- {
- c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
- inbuf += c->cipher->blocksize;
- outbuf += c->cipher->blocksize;
- }
-}
-
-static void
-do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nblocks )
-{
- unsigned int n;
-
- for (n=0; n < nblocks; n++ )
- {
- c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
- inbuf += c->cipher->blocksize;
- outbuf += c->cipher->blocksize;
- }
-}
-
-
-static void
-do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
-{
- unsigned int n;
- unsigned char *ivp;
- int i;
- size_t blocksize = c->cipher->blocksize;
- unsigned nblocks = nbytes / blocksize;
-
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
- {
- if ((nbytes % blocksize) == 0)
- nblocks--;
- }
-
- if (c->bulk.cbc_enc)
- {
- c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
- (c->flags & GCRY_CIPHER_CBC_MAC));
- inbuf += nblocks * blocksize;
- if (!(c->flags & GCRY_CIPHER_CBC_MAC))
- outbuf += nblocks * blocksize;
- }
- else
- {
- for (n=0; n < nblocks; n++ )
- {
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- outbuf[i] = inbuf[i] ^ *ivp++;
- c->cipher->encrypt ( &c->context.c, outbuf, outbuf );
- memcpy (c->u_iv.iv, outbuf, blocksize );
- inbuf += blocksize;
- if (!(c->flags & GCRY_CIPHER_CBC_MAC))
- outbuf += blocksize;
- }
- }
-
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
- {
- /* We have to be careful here, since outbuf might be equal to
- inbuf. */
- int restbytes;
- unsigned char b;
-
- if ((nbytes % blocksize) == 0)
- restbytes = blocksize;
- else
- restbytes = nbytes % blocksize;
-
- outbuf -= blocksize;
- for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
- {
- b = inbuf[i];
- outbuf[blocksize + i] = outbuf[i];
- outbuf[i] = b ^ *ivp++;
- }
- for (; i < blocksize; i++)
- outbuf[i] = 0 ^ *ivp++;
-
- c->cipher->encrypt (&c->context.c, outbuf, outbuf);
- memcpy (c->u_iv.iv, outbuf, blocksize);
- }
-}
-
-
-static void
-do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes)
-{
- unsigned int n;
- unsigned char *ivp;
- int i;
- size_t blocksize = c->cipher->blocksize;
- unsigned int nblocks = nbytes / blocksize;
-
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
- {
- nblocks--;
- if ((nbytes % blocksize) == 0)
- nblocks--;
- memcpy (c->lastiv, c->u_iv.iv, blocksize);
- }
-
- if (c->bulk.cbc_dec)
- {
- c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
- inbuf += nblocks * blocksize;
- outbuf += nblocks * blocksize;
- }
- else
- {
- for (n=0; n < nblocks; n++ )
- {
- /* Because outbuf and inbuf might be the same, we have to
- * save the original ciphertext block. We use LASTIV for
- * this here because it is not used otherwise. */
- memcpy (c->lastiv, inbuf, blocksize);
- c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- outbuf[i] ^= *ivp++;
- memcpy(c->u_iv.iv, c->lastiv, blocksize );
- inbuf += c->cipher->blocksize;
- outbuf += c->cipher->blocksize;
- }
- }
-
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
- {
- int restbytes;
-
- if ((nbytes % blocksize) == 0)
- restbytes = blocksize;
- else
- restbytes = nbytes % blocksize;
-
- memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
- memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
-
- c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
- for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ )
- outbuf[i] ^= *ivp++;
-
- memcpy(outbuf + blocksize, outbuf, restbytes);
- for(i=restbytes; i < blocksize; i++)
- c->u_iv.iv[i] = outbuf[i];
- c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv);
- for(ivp=c->lastiv,i=0; i < blocksize; i++ )
- outbuf[i] ^= *ivp++;
- /* c->lastiv is now really lastlastiv, does this matter? */
- }
-}
-
-
-static void
-do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
-{
- unsigned char *ivp;
- size_t blocksize = c->cipher->blocksize;
- size_t blocksize_x_2 = blocksize + blocksize;
-
- if ( nbytes <= c->unused )
- {
- /* Short enough to be encoded by the remaining XOR mask. */
- /* XOR the input with the IV and store input into IV. */
- for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
- nbytes;
- nbytes--, c->unused-- )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- return;
- }
-
- if ( c->unused )
- {
- /* XOR the input with the IV and store input into IV */
- nbytes -= c->unused;
- for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- }
-
- /* Now we can process complete blocks. We use a loop as long as we
- have at least 2 blocks and use conditions for the rest. This
- also allows to use a bulk encryption function if available. */
- if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc)
- {
- unsigned int nblocks = nbytes / blocksize;
- c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
- outbuf += nblocks * blocksize;
- inbuf += nblocks * blocksize;
- nbytes -= nblocks * blocksize;
- }
- else
- {
- while ( nbytes >= blocksize_x_2 )
- {
- int i;
- /* Encrypt the IV. */
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- /* XOR the input with the IV and store input into IV. */
- for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- nbytes -= blocksize;
- }
- }
-
- if ( nbytes >= blocksize )
- {
- int i;
- /* Save the current IV and then encrypt the IV. */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- /* XOR the input with the IV and store input into IV */
- for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- nbytes -= blocksize;
- }
- if ( nbytes )
- {
- /* Save the current IV and then encrypt the IV. */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- c->unused = blocksize;
- /* Apply the XOR. */
- c->unused -= nbytes;
- for(ivp=c->u_iv.iv; nbytes; nbytes-- )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- }
-}
-
-
-static void
-do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
-{
- unsigned char *ivp;
- unsigned long temp;
- int i;
- size_t blocksize = c->cipher->blocksize;
- size_t blocksize_x_2 = blocksize + blocksize;
-
- if (nbytes <= c->unused)
- {
- /* Short enough to be encoded by the remaining XOR mask. */
- /* XOR the input with the IV and store input into IV. */
- for (ivp=c->u_iv.iv+blocksize - c->unused;
- nbytes;
- nbytes--, c->unused--)
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- return;
- }
-
- if (c->unused)
- {
- /* XOR the input with the IV and store input into IV. */
- nbytes -= c->unused;
- for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- }
-
- /* Now we can process complete blocks. We use a loop as long as we
- have at least 2 blocks and use conditions for the rest. This
- also allows to use a bulk encryption function if available. */
- if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec)
- {
- unsigned int nblocks = nbytes / blocksize;
- c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
- outbuf += nblocks * blocksize;
- inbuf += nblocks * blocksize;
- nbytes -= nblocks * blocksize;
- }
- else
- {
- while (nbytes >= blocksize_x_2 )
- {
- /* Encrypt the IV. */
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- /* XOR the input with the IV and store input into IV. */
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- nbytes -= blocksize;
- }
- }
-
- if (nbytes >= blocksize )
- {
- /* Save the current IV and then encrypt the IV. */
- memcpy ( c->lastiv, c->u_iv.iv, blocksize);
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- /* XOR the input with the IV and store input into IV */
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- nbytes -= blocksize;
- }
-
- if (nbytes)
- {
- /* Save the current IV and then encrypt the IV. */
- memcpy ( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- c->unused = blocksize;
- /* Apply the XOR. */
- c->unused -= nbytes;
- for (ivp=c->u_iv.iv; nbytes; nbytes-- )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- }
-}
-
-
-static void
-do_ofb_encrypt( gcry_cipher_hd_t c,
- byte *outbuf, const byte *inbuf, unsigned nbytes )
-{
- byte *ivp;
- size_t blocksize = c->cipher->blocksize;
-
- if ( nbytes <= c->unused )
- {
- /* Short enough to be encoded by the remaining XOR mask. */
- /* XOR the input with the IV */
- for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
- nbytes;
- nbytes--, c->unused-- )
- *outbuf++ = (*ivp++ ^ *inbuf++);
- return;
- }
-
- if( c->unused )
- {
- nbytes -= c->unused;
- for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
- *outbuf++ = (*ivp++ ^ *inbuf++);
- }
-
- /* Now we can process complete blocks. */
- while ( nbytes >= blocksize )
- {
- int i;
- /* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
-
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- *outbuf++ = (*ivp++ ^ *inbuf++);
- nbytes -= blocksize;
- }
- if ( nbytes )
- { /* process the remaining bytes */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- c->unused = blocksize;
- c->unused -= nbytes;
- for(ivp=c->u_iv.iv; nbytes; nbytes-- )
- *outbuf++ = (*ivp++ ^ *inbuf++);
- }
-}
-
-static void
-do_ofb_decrypt( gcry_cipher_hd_t c,
- byte *outbuf, const byte *inbuf, unsigned int nbytes )
-{
- byte *ivp;
- size_t blocksize = c->cipher->blocksize;
-
- if( nbytes <= c->unused )
- {
- /* Short enough to be encoded by the remaining XOR mask. */
- for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--)
- *outbuf++ = *ivp++ ^ *inbuf++;
- return;
- }
-
- if ( c->unused )
- {
- nbytes -= c->unused;
- for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
- *outbuf++ = *ivp++ ^ *inbuf++;
- }
-
- /* Now we can process complete blocks. */
- while ( nbytes >= blocksize )
- {
- int i;
- /* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
- *outbuf++ = *ivp++ ^ *inbuf++;
- nbytes -= blocksize;
- }
- if ( nbytes )
- { /* Process the remaining bytes. */
- /* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
- c->unused = blocksize;
- c->unused -= nbytes;
- for (ivp=c->u_iv.iv; nbytes; nbytes-- )
- *outbuf++ = *ivp++ ^ *inbuf++;
- }
-}
-
-
-static void
-do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nbytes )
-{
- unsigned int n;
- byte tmp[MAX_BLOCKSIZE];
- int i;
-
- for(n=0; n < nbytes; n++)
- {
- if ((n % c->cipher->blocksize) == 0)
- {
- c->cipher->encrypt (&c->context.c, tmp, c->ctr);
-
- for (i = c->cipher->blocksize; i > 0; i--)
- {
- c->ctr[i-1]++;
- if (c->ctr[i-1] != 0)
- break;
- }
- }
-
- /* XOR input with encrypted counter and store in output. */
- outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize];
- }
-}
-
-static void
-do_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nbytes )
-{
- do_ctr_encrypt (c, outbuf, inbuf, nbytes);
-}
-
-
-/* Perform the AES-Wrap algorithm as specified by RFC3394. We
- implement this as a mode usable with any cipher algorithm of
- blocksize 128. */
-static gcry_err_code_t
-do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
- const byte *inbuf, unsigned int inbuflen )
-{
- int j, x;
- unsigned int n, i;
- unsigned char *r, *a, *b;
- unsigned char t[8];
-
-#if MAX_BLOCKSIZE < 8
-#error Invalid block size
-#endif
- /* We require a cipher with a 128 bit block length. */
- if (c->cipher->blocksize != 16)
- return GPG_ERR_INV_LENGTH;
-
- /* The output buffer must be able to hold the input data plus one
- additional block. */
- if (outbuflen < inbuflen + 8)
- return GPG_ERR_BUFFER_TOO_SHORT;
- /* Input data must be multiple of 64 bits. */
- if (inbuflen % 8)
- return GPG_ERR_INV_ARG;
-
- n = inbuflen / 8;
-
- /* We need at least two 64 bit blocks. */
- if (n < 2)
- return GPG_ERR_INV_ARG;
-
- r = outbuf;
- a = outbuf; /* We store A directly in OUTBUF. */
- b = c->ctr; /* B is also used to concatenate stuff. */
-
- /* If an IV has been set we use that IV as the Alternative Initial
- Value; if it has not been set we use the standard value. */
- if (c->marks.iv)
- memcpy (a, c->u_iv.iv, 8);
- else
- memset (a, 0xa6, 8);
-
- /* Copy the inbuf to the outbuf. */
- memmove (r+8, inbuf, inbuflen);
-
- memset (t, 0, sizeof t); /* t := 0. */
-
- for (j = 0; j <= 5; j++)
- {
- for (i = 1; i <= n; i++)
- {
- /* B := AES_k( A | R[i] ) */
- memcpy (b, a, 8);
- memcpy (b+8, r+i*8, 8);
- c->cipher->encrypt (&c->context.c, b, b);
- /* t := t + 1 */
- for (x = 7; x >= 0; x--)
- {
- t[x]++;
- if (t[x])
- break;
- }
- /* A := MSB_64(B) ^ t */
- for (x=0; x < 8; x++)
- a[x] = b[x] ^ t[x];
- /* R[i] := LSB_64(B) */
- memcpy (r+i*8, b+8, 8);
- }
- }
-
- return 0;
-}
-
-/* Perform the AES-Unwrap algorithm as specified by RFC3394. We
- implement this as a mode usable with any cipher algorithm of
- blocksize 128. */
-static gcry_err_code_t
-do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
- const byte *inbuf, unsigned int inbuflen)
-{
- int j, x;
- unsigned int n, i;
- unsigned char *r, *a, *b;
- unsigned char t[8];
-
-#if MAX_BLOCKSIZE < 8
-#error Invalid block size
-#endif
- /* We require a cipher with a 128 bit block length. */
- if (c->cipher->blocksize != 16)
- return GPG_ERR_INV_LENGTH;
-
- /* The output buffer must be able to hold the input data minus one
- additional block. Fixme: The caller has more restrictive checks
- - we may want to fix them for this mode. */
- if (outbuflen + 8 < inbuflen)
- return GPG_ERR_BUFFER_TOO_SHORT;
- /* Input data must be multiple of 64 bits. */
- if (inbuflen % 8)
- return GPG_ERR_INV_ARG;
-
- n = inbuflen / 8;
-
- /* We need at least three 64 bit blocks. */
- if (n < 3)
- return GPG_ERR_INV_ARG;
-
- r = outbuf;
- a = c->lastiv; /* We use c->LASTIV as buffer for A. */
- b = c->ctr; /* B is also used to concatenate stuff. */
-
- /* Copy the inbuf to the outbuf and save A. */
- memcpy (a, inbuf, 8);
- memmove (r, inbuf+8, inbuflen-8);
- n--; /* Reduce to actual number of data blocks. */
-
- /* t := 6 * n */
- i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */
- for (x=0; x < 8 && x < sizeof (i); x++)
- t[7-x] = i >> (8*x);
- for (; x < 8; x++)
- t[7-x] = 0;
-
- for (j = 5; j >= 0; j--)
- {
- for (i = n; i >= 1; i--)
- {
- /* B := AES_k^1( (A ^ t)| R[i] ) */
- for (x = 0; x < 8; x++)
- b[x] = a[x] ^ t[x];
- memcpy (b+8, r+(i-1)*8, 8);
- c->cipher->decrypt (&c->context.c, b, b);
- /* t := t - 1 */
- for (x = 7; x >= 0; x--)
- {
- t[x]--;
- if (t[x] != 0xff)
- break;
- }
- /* A := MSB_64(B) */
- memcpy (a, b, 8);
- /* R[i] := LSB_64(B) */
- memcpy (r+(i-1)*8, b+8, 8);
- }
- }
-
- /* If an IV has been set we compare against this Alternative Initial
- Value; if it has not been set we compare against the standard IV. */
- if (c->marks.iv)
- j = memcmp (a, c->u_iv.iv, 8);
- else
- {
- for (j=0, x=0; x < 8; x++)
- if (a[x] != 0xa6)
- {
- j=1;
- break;
- }
- }
- return j? GPG_ERR_CHECKSUM : 0;
-}
-
-
-/****************
- * Encrypt INBUF to OUTBUF with the mode selected at open.
- * inbuf and outbuf may overlap or be the same.
- * Depending on the mode some contraints apply to NBYTES.
- */
-static gcry_err_code_t
-cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf,
- const byte *inbuf, unsigned int nbytes)
-{
- gcry_err_code_t rc = GPG_ERR_NO_ERROR;
-
- switch( c->mode ) {
- case GCRY_CIPHER_MODE_ECB:
- if (!(nbytes%c->cipher->blocksize))
- do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize );
- else
- rc = GPG_ERR_INV_ARG;
- break;
- case GCRY_CIPHER_MODE_CBC:
- if (!(nbytes%c->cipher->blocksize)
- || (nbytes > c->cipher->blocksize
- && (c->flags & GCRY_CIPHER_CBC_CTS)))
- do_cbc_encrypt(c, outbuf, inbuf, nbytes );
- else
- rc = GPG_ERR_INV_ARG;
- break;
- case GCRY_CIPHER_MODE_CFB:
- do_cfb_encrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_OFB:
- do_ofb_encrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_CTR:
- do_ctr_encrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_STREAM:
- c->cipher->stencrypt ( &c->context.c,
- outbuf, (byte*)/*arggg*/inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_NONE:
- if (fips_mode () || !_gcry_get_debug_flag (0))
- {
- fips_signal_error ("cipher mode NONE used");
- rc = GPG_ERR_INV_CIPHER_MODE;
- }
- else
- {
- if ( inbuf != outbuf )
- memmove (outbuf, inbuf, nbytes);
- }
- break;
- default:
- log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
- rc = GPG_ERR_INV_CIPHER_MODE;
- break;
- }
- return rc;
-}
-
-
-/****************
- * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has
- * been requested.
- */
-gcry_error_t
-gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
- const void *in, size_t inlen)
-{
- gcry_err_code_t err;
-
- if (h->mode == GCRY_CIPHER_MODE_AESWRAP)
- {
- /* Hack to implement AESWRAP without touching the other modes.
- The actual function has been taken from the current
- development version which does all error checking in each
- mode function. */
- if (!in)
- err = do_aeswrap_encrypt (h, out, outsize, out, outsize);
- else
- err = do_aeswrap_encrypt (h, out, outsize, in, inlen);
- }
- else if (!in)
- {
- /* Caller requested in-place encryption. */
- /* Actually cipher_encrypt() does not need to know about it, but
- * we may change it in the future to get better performance. */
- err = cipher_encrypt (h, out, out, outsize);
- }
- else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ?
- h->cipher->blocksize : inlen))
- err = GPG_ERR_TOO_SHORT;
- else if ((h->mode == GCRY_CIPHER_MODE_ECB
- || (h->mode == GCRY_CIPHER_MODE_CBC
- && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
- && (inlen > h->cipher->blocksize)))))
- && (inlen % h->cipher->blocksize))
- err = GPG_ERR_INV_ARG;
- else
- err = cipher_encrypt (h, out, in, inlen);
-
- if (err && out)
- memset (out, 0x42, outsize); /* Failsafe: Make sure that the
- plaintext will never make it into
- OUT. */
-
- return gcry_error (err);
-}
-
-
-
-/****************
- * Decrypt INBUF to OUTBUF with the mode selected at open.
- * inbuf and outbuf may overlap or be the same.
- * Depending on the mode some some contraints apply to NBYTES.
- */
-static gcry_err_code_t
-cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nbytes)
-{
- gcry_err_code_t rc = GPG_ERR_NO_ERROR;
-
- switch( c->mode ) {
- case GCRY_CIPHER_MODE_ECB:
- if (!(nbytes%c->cipher->blocksize))
- do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize );
- else
- rc = GPG_ERR_INV_ARG;
- break;
- case GCRY_CIPHER_MODE_CBC:
- if (!(nbytes%c->cipher->blocksize)
- || (nbytes > c->cipher->blocksize
- && (c->flags & GCRY_CIPHER_CBC_CTS)))
- do_cbc_decrypt(c, outbuf, inbuf, nbytes );
- else
- rc = GPG_ERR_INV_ARG;
- break;
- case GCRY_CIPHER_MODE_CFB:
- do_cfb_decrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_OFB:
- do_ofb_decrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_CTR:
- do_ctr_decrypt(c, outbuf, inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_STREAM:
- c->cipher->stdecrypt ( &c->context.c,
- outbuf, (byte*)/*arggg*/inbuf, nbytes );
- break;
- case GCRY_CIPHER_MODE_NONE:
- if (fips_mode () || !_gcry_get_debug_flag (0))
- {
- fips_signal_error ("cipher mode NONE used");
- rc = GPG_ERR_INV_CIPHER_MODE;
- }
- else
- {
- if (inbuf != outbuf)
- memmove (outbuf, inbuf, nbytes);
- }
- break;
- default:
- log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
- rc = GPG_ERR_INV_CIPHER_MODE;
- break;
- }
- return rc;
-}
-
-
-gcry_error_t
-gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
- const void *in, size_t inlen)
-{
- gcry_err_code_t err = 0;
-
- if (h->mode == GCRY_CIPHER_MODE_AESWRAP)
- {
- /* Hack to implement AESWRAP without touching the other modes.
- The actual function has been taken from the current
- development version which does all error checking in each
- mode function. */
- if (!in)
- err = do_aeswrap_decrypt (h, out, outsize, out, outsize);
- else
- err = do_aeswrap_decrypt (h, out, outsize, in, inlen);
- }
- else if (!in)
- {
- /* Caller requested in-place encryption. */
- /* Actually cipher_encrypt() does not need to know about it, but
- * we may change it in the future to get better performance. */
- err = cipher_decrypt (h, out, out, outsize);
- }
- else if (outsize < inlen)
- err = GPG_ERR_TOO_SHORT;
- else if (((h->mode == GCRY_CIPHER_MODE_ECB)
- || ((h->mode == GCRY_CIPHER_MODE_CBC)
- && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
- && (inlen > h->cipher->blocksize)))))
- && (inlen % h->cipher->blocksize) != 0)
- err = GPG_ERR_INV_ARG;
- else
- err = cipher_decrypt (h, out, in, inlen);
-
- return gcry_error (err);
-}
-
-
-
-/****************
- * Used for PGP's somewhat strange CFB mode. Only works if
- * the corresponding flag is set.
- */
-static void
-cipher_sync (gcry_cipher_hd_t c)
-{
- if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
- {
- memmove (c->u_iv.iv + c->unused,
- c->u_iv.iv, c->cipher->blocksize - c->unused);
- memcpy (c->u_iv.iv,
- c->lastiv + c->cipher->blocksize - c->unused, c->unused);
- c->unused = 0;
- }
-}
-
-
-gcry_error_t
-_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
-{
- return cipher_setkey (hd, (void*)key, keylen);
-}
-
-
-gcry_error_t
-_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
-{
- cipher_setiv (hd, iv, ivlen);
- return 0;
-}
-
-/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
- block size length, or (NULL,0) to set the CTR to the all-zero
- block. */
-gpg_error_t
-_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
-{
- if (ctr && ctrlen == hd->cipher->blocksize)
- memcpy (hd->ctr, ctr, hd->cipher->blocksize);
- else if (!ctr || !ctrlen)
- memset (hd->ctr, 0, hd->cipher->blocksize);
- else
- return gpg_error (GPG_ERR_INV_ARG);
- return 0;
-}
-
-
-gcry_error_t
-gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
-{
- gcry_err_code_t rc = GPG_ERR_NO_ERROR;
-
- switch (cmd)
- {
- case GCRYCTL_SET_KEY: /* Deprecated; use gcry_cipher_setkey. */
- rc = cipher_setkey( h, buffer, buflen );
- break;
-
- case GCRYCTL_SET_IV: /* Deprecated; use gcry_cipher_setiv. */
- cipher_setiv( h, buffer, buflen );
- break;
-
- case GCRYCTL_RESET:
- cipher_reset (h);
- break;
-
- case GCRYCTL_CFB_SYNC:
- cipher_sync( h );
- break;
-
- case GCRYCTL_SET_CBC_CTS:
- if (buflen)
- if (h->flags & GCRY_CIPHER_CBC_MAC)
- rc = GPG_ERR_INV_FLAG;
- else
- h->flags |= GCRY_CIPHER_CBC_CTS;
- else
- h->flags &= ~GCRY_CIPHER_CBC_CTS;
- break;
-
- case GCRYCTL_SET_CBC_MAC:
- if (buflen)
- if (h->flags & GCRY_CIPHER_CBC_CTS)
- rc = GPG_ERR_INV_FLAG;
- else
- h->flags |= GCRY_CIPHER_CBC_MAC;
- else
- h->flags &= ~GCRY_CIPHER_CBC_MAC;
- break;
-
- case GCRYCTL_DISABLE_ALGO:
- /* This command expects NULL for H and BUFFER to point to an
- integer with the algo number. */
- if( h || !buffer || buflen != sizeof(int) )
- return gcry_error (GPG_ERR_CIPHER_ALGO);
- disable_cipher_algo( *(int*)buffer );
- break;
-
- case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */
- if (buffer && buflen == h->cipher->blocksize)
- memcpy (h->ctr, buffer, h->cipher->blocksize);
- else if (buffer == NULL || buflen == 0)
- memset (h->ctr, 0, h->cipher->blocksize);
- else
- rc = GPG_ERR_INV_ARG;
- break;
-
- case 61: /* Disable weak key detection (private). */
- if (h->extraspec->set_extra_info)
- rc = h->extraspec->set_extra_info
- (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
- else
- rc = GPG_ERR_NOT_SUPPORTED;
- break;
-
- case 62: /* Return current input vector (private). */
- /* This is the input block as used in CFB and OFB mode which has
- initially been set as IV. The returned format is:
- 1 byte Actual length of the block in bytes.
- n byte The block.
- If the provided buffer is too short, an error is returned. */
- if (buflen < (1 + h->cipher->blocksize))
- rc = GPG_ERR_TOO_SHORT;
- else
- {
- unsigned char *ivp;
- unsigned char *dst = buffer;
- int n = h->unused;
-
- if (!n)
- n = h->cipher->blocksize;
- gcry_assert (n <= h->cipher->blocksize);
- *dst++ = n;
- ivp = h->u_iv.iv + h->cipher->blocksize - n;
- while (n--)
- *dst++ = *ivp++;
- }
- break;
-
- default:
- rc = GPG_ERR_INV_OP;
- }
-
- return gcry_error (rc);
-}
-
-
-/* Return information about the cipher handle H. CMD is the kind of
- information requested. BUFFER and NBYTES are reserved for now.
-
- There are no values for CMD yet defined.
-
- The fucntion always returns GPG_ERR_INV_OP.
-
- */
-gcry_error_t
-gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- (void)h;
- (void)buffer;
- (void)nbytes;
-
- switch (cmd)
- {
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-/* Return information about the given cipher algorithm ALGO.
-
- WHAT select the kind of information returned:
-
- GCRYCTL_GET_KEYLEN:
- Return the length of the key. If the algorithm ALGO
- supports multiple key lengths, the maximum supported key length
- is returned. The key length is returned as number of octets.
- BUFFER and NBYTES must be zero.
-
- GCRYCTL_GET_BLKLEN:
- Return the blocklength of the algorithm ALGO counted in octets.
- BUFFER and NBYTES must be zero.
-
- GCRYCTL_TEST_ALGO:
- Returns 0 if the specified algorithm ALGO is available for use.
- BUFFER and NBYTES must be zero.
-
- Note: Because this function is in most cases used to return an
- integer value, we can make it easier for the caller to just look at
- the return value. The caller will in all cases consult the value
- and thereby detecting whether a error occured or not (i.e. while
- checking the block size)
- */
-gcry_error_t
-gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- unsigned int ui;
-
- switch (what)
- {
- case GCRYCTL_GET_KEYLEN:
- if (buffer || (! nbytes))
- err = GPG_ERR_CIPHER_ALGO;
- else
- {
- ui = cipher_get_keylen (algo);
- if ((ui > 0) && (ui <= 512))
- *nbytes = (size_t) ui / 8;
- else
- /* The only reason is an invalid algo or a strange
- blocksize. */
- err = GPG_ERR_CIPHER_ALGO;
- }
- break;
-
- case GCRYCTL_GET_BLKLEN:
- if (buffer || (! nbytes))
- err = GPG_ERR_CIPHER_ALGO;
- else
- {
- ui = cipher_get_blocksize (algo);
- if ((ui > 0) && (ui < 10000))
- *nbytes = ui;
- else
- /* The only reason is an invalid algo or a strange
- blocksize. */
- err = GPG_ERR_CIPHER_ALGO;
- }
- break;
-
- case GCRYCTL_TEST_ALGO:
- if (buffer || nbytes)
- err = GPG_ERR_INV_ARG;
- else
- err = check_cipher_algo (algo);
- break;
-
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-
-/* This function returns length of the key for algorithm ALGO. If the
- algorithm supports multiple key lengths, the maximum supported key
- length is returned. On error 0 is returned. The key length is
- returned as number of octets.
-
- This is a convenience functions which should be preferred over
- gcry_cipher_algo_info because it allows for proper type
- checking. */
-size_t
-gcry_cipher_get_algo_keylen (int algo)
-{
- size_t n;
-
- if (gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n))
- n = 0;
- return n;
-}
-
-/* This functions returns the blocklength of the algorithm ALGO
- counted in octets. On error 0 is returned.
-
- This is a convenience functions which should be preferred over
- gcry_cipher_algo_info because it allows for proper type
- checking. */
-size_t
-gcry_cipher_get_algo_blklen (int algo)
-{
- size_t n;
-
- if (gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n))
- n = 0;
- return n;
-}
-
-/* Explicitly initialize this module. */
-gcry_err_code_t
-_gcry_cipher_init (void)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- REGISTER_DEFAULT_CIPHERS;
-
- return err;
-}
-
-/* Get a list consisting of the IDs of the loaded cipher modules. If
- LIST is zero, write the number of loaded cipher modules to
- LIST_LENGTH and return. If LIST is non-zero, the first
- *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
- according size. In case there are less cipher modules than
- *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
-gcry_error_t
-gcry_cipher_list (int *list, int *list_length)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- ath_mutex_lock (&ciphers_registered_lock);
- err = _gcry_module_list (ciphers_registered, list, list_length);
- ath_mutex_unlock (&ciphers_registered_lock);
-
- return err;
-}
-
-
-/* Run the selftests for cipher algorithm ALGO with optional reporting
- function REPORT. */
-gpg_error_t
-_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
-{
- gcry_module_t module = NULL;
- cipher_extra_spec_t *extraspec = NULL;
- gcry_err_code_t ec = 0;
-
- REGISTER_DEFAULT_CIPHERS;
-
- ath_mutex_lock (&ciphers_registered_lock);
- module = _gcry_module_lookup_id (ciphers_registered, algo);
- if (module && !(module->flags & FLAG_MODULE_DISABLED))
- extraspec = module->extraspec;
- ath_mutex_unlock (&ciphers_registered_lock);
- if (extraspec && extraspec->selftest)
- ec = extraspec->selftest (algo, extended, report);
- else
- {
- ec = GPG_ERR_CIPHER_ALGO;
- if (report)
- report ("cipher", algo, "module",
- module && !(module->flags & FLAG_MODULE_DISABLED)?
- "no selftest available" :
- module? "algorithm disabled" : "algorithm not found");
- }
-
- if (module)
- {
- ath_mutex_lock (&ciphers_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&ciphers_registered_lock);
- }
- return gpg_error (ec);
-}
+/* cipher.c - cipher dispatcher
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ * 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "ath.h"
+
+#define MAX_BLOCKSIZE 16
+#define TABLE_SIZE 14
+#define CTX_MAGIC_NORMAL 0x24091964
+#define CTX_MAGIC_SECURE 0x46919042
+
+#undef NEED_16BYTE_ALIGNED_CONTEXT
+#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
+#define NEED_16BYTE_ALIGNED_CONTEXT 1
+#endif
+
+/* A dummy extraspec so that we do not need to tests the extraspec
+ field from the module specification against NULL and instead
+ directly test the respective fields of extraspecs. */
+static cipher_extra_spec_t dummy_extra_spec;
+
+/* This is the list of the default ciphers, which are included in
+ libgcrypt. */
+static struct cipher_table_entry
+{
+ gcry_cipher_spec_t *cipher;
+ cipher_extra_spec_t *extraspec;
+ unsigned int algorithm;
+ int fips_allowed;
+} cipher_table[] =
+ {
+#if USE_BLOWFISH
+ { &_gcry_cipher_spec_blowfish,
+ &dummy_extra_spec, GCRY_CIPHER_BLOWFISH },
+#endif
+#if USE_DES
+ { &_gcry_cipher_spec_des,
+ &dummy_extra_spec, GCRY_CIPHER_DES },
+ { &_gcry_cipher_spec_tripledes,
+ &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 },
+#endif
+#if USE_ARCFOUR
+ { &_gcry_cipher_spec_arcfour,
+ &dummy_extra_spec, GCRY_CIPHER_ARCFOUR },
+#endif
+#if USE_CAST5
+ { &_gcry_cipher_spec_cast5,
+ &dummy_extra_spec, GCRY_CIPHER_CAST5 },
+#endif
+#if USE_AES
+ { &_gcry_cipher_spec_aes,
+ &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 },
+ { &_gcry_cipher_spec_aes192,
+ &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 },
+ { &_gcry_cipher_spec_aes256,
+ &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 },
+#endif
+#if USE_TWOFISH
+ { &_gcry_cipher_spec_twofish,
+ &dummy_extra_spec, GCRY_CIPHER_TWOFISH },
+ { &_gcry_cipher_spec_twofish128,
+ &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 },
+#endif
+#if USE_SERPENT
+ { &_gcry_cipher_spec_serpent128,
+ &dummy_extra_spec, GCRY_CIPHER_SERPENT128 },
+ { &_gcry_cipher_spec_serpent192,
+ &dummy_extra_spec, GCRY_CIPHER_SERPENT192 },
+ { &_gcry_cipher_spec_serpent256,
+ &dummy_extra_spec, GCRY_CIPHER_SERPENT256 },
+#endif
+#if USE_RFC2268
+ { &_gcry_cipher_spec_rfc2268_40,
+ &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 },
+#endif
+#if USE_SEED
+ { &_gcry_cipher_spec_seed,
+ &dummy_extra_spec, GCRY_CIPHER_SEED },
+#endif
+#if USE_CAMELLIA
+ { &_gcry_cipher_spec_camellia128,
+ &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 },
+ { &_gcry_cipher_spec_camellia192,
+ &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 },
+ { &_gcry_cipher_spec_camellia256,
+ &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 },
+#endif
+ { NULL }
+ };
+
+/* List of registered ciphers. */
+static gcry_module_t ciphers_registered;
+
+/* This is the lock protecting CIPHERS_REGISTERED. */
+static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER;
+
+/* Flag to check whether the default ciphers have already been
+ registered. */
+static int default_ciphers_registered;
+
+/* Convenient macro for registering the default ciphers. */
+#define REGISTER_DEFAULT_CIPHERS \
+ do \
+ { \
+ ath_mutex_lock (&ciphers_registered_lock); \
+ if (! default_ciphers_registered) \
+ { \
+ cipher_register_default (); \
+ default_ciphers_registered = 1; \
+ } \
+ ath_mutex_unlock (&ciphers_registered_lock); \
+ } \
+ while (0)
+
+
+/* A VIA processor with the Padlock engine requires an alignment of
+ most data on a 16 byte boundary. Because we trick out the compiler
+ while allocating the context, the align attribute as used in
+ rijndael.c does not work on its own. Thus we need to make sure
+ that the entire context structure is a aligned on that boundary.
+ We achieve this by defining a new type and use that instead of our
+ usual alignment type. */
+typedef union
+{
+ PROPERLY_ALIGNED_TYPE foo;
+#ifdef NEED_16BYTE_ALIGNED_CONTEXT
+ char bar[16] __attribute__ ((aligned (16)));
+#endif
+ char c[1];
+} cipher_context_alignment_t;
+
+
+/* The handle structure. */
+struct gcry_cipher_handle
+{
+ int magic;
+ size_t actual_handle_size; /* Allocated size of this handle. */
+ size_t handle_offset; /* Offset to the malloced block. */
+ gcry_cipher_spec_t *cipher;
+ cipher_extra_spec_t *extraspec;
+ gcry_module_t module;
+
+ /* The algorithm id. This is a hack required because the module
+ interface does not easily allow to retrieve this value. */
+ int algo;
+
+ /* A structure with function pointers for bulk operations. Due to
+ limitations of the module system (we don't want to change the
+ API) we need to keep these function pointers here. The cipher
+ open function intializes them and the actual encryption routines
+ use them if they are not NULL. */
+ struct {
+ void (*cfb_enc)(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks);
+ void (*cfb_dec)(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks);
+ void (*cbc_enc)(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks, int cbc_mac);
+ void (*cbc_dec)(void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks);
+ } bulk;
+
+
+ int mode;
+ unsigned int flags;
+
+ struct {
+ unsigned int key:1; /* Set to 1 if a key has been set. */
+ unsigned int iv:1; /* Set to 1 if a IV has been set. */
+ } marks;
+
+ /* The initialization vector. To help code optimization we make
+ sure that it is aligned on an unsigned long and u32 boundary. */
+ union {
+ unsigned long dummy_iv;
+ u32 dummy_u32_iv;
+ unsigned char iv[MAX_BLOCKSIZE];
+ } u_iv;
+
+ unsigned char lastiv[MAX_BLOCKSIZE];
+ int unused; /* Number of unused bytes in the IV. */
+
+ unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */
+
+
+ /* What follows are two contexts of the cipher in use. The first
+ one needs to be aligned well enough for the cipher operation
+ whereas the second one is a copy created by cipher_setkey and
+ used by cipher_reset. That second copy has no need for proper
+ aligment because it is only accessed by memcpy. */
+ cipher_context_alignment_t context;
+};
+
+
+
+/* These dummy functions are used in case a cipher implementation
+ refuses to provide it's own functions. */
+
+static gcry_err_code_t
+dummy_setkey (void *c, const unsigned char *key, unsigned int keylen)
+{
+ (void)c;
+ (void)key;
+ (void)keylen;
+ return GPG_ERR_NO_ERROR;
+}
+
+static void
+dummy_encrypt_block (void *c,
+ unsigned char *outbuf, const unsigned char *inbuf)
+{
+ (void)c;
+ (void)outbuf;
+ (void)inbuf;
+ BUG();
+}
+
+static void
+dummy_decrypt_block (void *c,
+ unsigned char *outbuf, const unsigned char *inbuf)
+{
+ (void)c;
+ (void)outbuf;
+ (void)inbuf;
+ BUG();
+}
+
+static void
+dummy_encrypt_stream (void *c,
+ unsigned char *outbuf, const unsigned char *inbuf,
+ unsigned int n)
+{
+ (void)c;
+ (void)outbuf;
+ (void)inbuf;
+ (void)n;
+ BUG();
+}
+
+static void
+dummy_decrypt_stream (void *c,
+ unsigned char *outbuf, const unsigned char *inbuf,
+ unsigned int n)
+{
+ (void)c;
+ (void)outbuf;
+ (void)inbuf;
+ (void)n;
+ BUG();
+}
+
+
+/* Internal function. Register all the ciphers included in
+ CIPHER_TABLE. Note, that this function gets only used by the macro
+ REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */
+static void
+cipher_register_default (void)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ int i;
+
+ for (i = 0; !err && cipher_table[i].cipher; i++)
+ {
+ if (! cipher_table[i].cipher->setkey)
+ cipher_table[i].cipher->setkey = dummy_setkey;
+ if (! cipher_table[i].cipher->encrypt)
+ cipher_table[i].cipher->encrypt = dummy_encrypt_block;
+ if (! cipher_table[i].cipher->decrypt)
+ cipher_table[i].cipher->decrypt = dummy_decrypt_block;
+ if (! cipher_table[i].cipher->stencrypt)
+ cipher_table[i].cipher->stencrypt = dummy_encrypt_stream;
+ if (! cipher_table[i].cipher->stdecrypt)
+ cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream;
+
+ if ( fips_mode () && !cipher_table[i].fips_allowed )
+ continue;
+
+ err = _gcry_module_add (&ciphers_registered,
+ cipher_table[i].algorithm,
+ (void *) cipher_table[i].cipher,
+ (void *) cipher_table[i].extraspec,
+ NULL);
+ }
+
+ if (err)
+ BUG ();
+}
+
+/* Internal callback function. Used via _gcry_module_lookup. */
+static int
+gcry_cipher_lookup_func_name (void *spec, void *data)
+{
+ gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
+ char *name = (char *) data;
+ const char **aliases = cipher->aliases;
+ int i, ret = ! stricmp (name, cipher->name);
+
+ if (aliases)
+ for (i = 0; aliases[i] && (! ret); i++)
+ ret = ! stricmp (name, aliases[i]);
+
+ return ret;
+}
+
+/* Internal callback function. Used via _gcry_module_lookup. */
+static int
+gcry_cipher_lookup_func_oid (void *spec, void *data)
+{
+ gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec;
+ char *oid = (char *) data;
+ gcry_cipher_oid_spec_t *oid_specs = cipher->oids;
+ int ret = 0, i;
+
+ if (oid_specs)
+ for (i = 0; oid_specs[i].oid && (! ret); i++)
+ if (! stricmp (oid, oid_specs[i].oid))
+ ret = 1;
+
+ return ret;
+}
+
+/* Internal function. Lookup a cipher entry by it's name. */
+static gcry_module_t
+gcry_cipher_lookup_name (const char *name)
+{
+ gcry_module_t cipher;
+
+ cipher = _gcry_module_lookup (ciphers_registered, (void *) name,
+ gcry_cipher_lookup_func_name);
+
+ return cipher;
+}
+
+/* Internal function. Lookup a cipher entry by it's oid. */
+static gcry_module_t
+gcry_cipher_lookup_oid (const char *oid)
+{
+ gcry_module_t cipher;
+
+ cipher = _gcry_module_lookup (ciphers_registered, (void *) oid,
+ gcry_cipher_lookup_func_oid);
+
+ return cipher;
+}
+
+/* Register a new cipher module whose specification can be found in
+ CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID
+ and a pointer representhing this module is stored in MODULE. */
+gcry_error_t
+_gcry_cipher_register (gcry_cipher_spec_t *cipher,
+ cipher_extra_spec_t *extraspec,
+ int *algorithm_id,
+ gcry_module_t *module)
+{
+ gcry_err_code_t err = 0;
+ gcry_module_t mod;
+
+ /* We do not support module loading in fips mode. */
+ if (fips_mode ())
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ err = _gcry_module_add (&ciphers_registered, 0,
+ (void *)cipher,
+ (void *)(extraspec? extraspec : &dummy_extra_spec),
+ &mod);
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ if (! err)
+ {
+ *module = mod;
+ *algorithm_id = mod->mod_id;
+ }
+
+ return gcry_error (err);
+}
+
+/* Unregister the cipher identified by MODULE, which must have been
+ registered with gcry_cipher_register. */
+void
+gcry_cipher_unregister (gcry_module_t module)
+{
+ ath_mutex_lock (&ciphers_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&ciphers_registered_lock);
+}
+
+/* Locate the OID in the oid table and return the index or -1 when not
+ found. An opitonal "oid." or "OID." prefix in OID is ignored, the
+ OID is expected to be in standard IETF dotted notation. The
+ internal algorithm number is returned in ALGORITHM unless it
+ ispassed as NULL. A pointer to the specification of the module
+ implementing this algorithm is return in OID_SPEC unless passed as
+ NULL.*/
+static int
+search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec)
+{
+ gcry_module_t module;
+ int ret = 0;
+
+ if (oid && ((! strncmp (oid, "oid.", 4))
+ || (! strncmp (oid, "OID.", 4))))
+ oid += 4;
+
+ module = gcry_cipher_lookup_oid (oid);
+ if (module)
+ {
+ gcry_cipher_spec_t *cipher = module->spec;
+ int i;
+
+ for (i = 0; cipher->oids[i].oid && !ret; i++)
+ if (! stricmp (oid, cipher->oids[i].oid))
+ {
+ if (algorithm)
+ *algorithm = module->mod_id;
+ if (oid_spec)
+ *oid_spec = cipher->oids[i];
+ ret = 1;
+ }
+ _gcry_module_release (module);
+ }
+
+ return ret;
+}
+
+/* Map STRING to the cipher algorithm identifier. Returns the
+ algorithm ID of the cipher for the given name or 0 if the name is
+ not known. It is valid to pass NULL for STRING which results in a
+ return value of 0. */
+int
+gcry_cipher_map_name (const char *string)
+{
+ gcry_module_t cipher;
+ int ret, algorithm = 0;
+
+ if (! string)
+ return 0;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ /* If the string starts with a digit (optionally prefixed with
+ either "OID." or "oid."), we first look into our table of ASN.1
+ object identifiers to figure out the algorithm */
+
+ ath_mutex_lock (&ciphers_registered_lock);
+
+ ret = search_oid (string, &algorithm, NULL);
+ if (! ret)
+ {
+ cipher = gcry_cipher_lookup_name (string);
+ if (cipher)
+ {
+ algorithm = cipher->mod_id;
+ _gcry_module_release (cipher);
+ }
+ }
+
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return algorithm;
+}
+
+
+/* Given a STRING with an OID in dotted decimal notation, this
+ function returns the cipher mode (GCRY_CIPHER_MODE_*) associated
+ with that OID or 0 if no mode is known. Passing NULL for string
+ yields a return value of 0. */
+int
+gcry_cipher_mode_from_oid (const char *string)
+{
+ gcry_cipher_oid_spec_t oid_spec;
+ int ret = 0, mode = 0;
+
+ if (!string)
+ return 0;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ ret = search_oid (string, NULL, &oid_spec);
+ if (ret)
+ mode = oid_spec.mode;
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return mode;
+}
+
+
+/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
+ string representation of the algorithm name. For unknown algorithm
+ IDs this function returns "?". */
+static const char *
+cipher_algo_to_string (int algorithm)
+{
+ gcry_module_t cipher;
+ const char *name;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
+ if (cipher)
+ {
+ name = ((gcry_cipher_spec_t *) cipher->spec)->name;
+ _gcry_module_release (cipher);
+ }
+ else
+ name = "?";
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return name;
+}
+
+/* Map the cipher algorithm identifier ALGORITHM to a string
+ representing this algorithm. This string is the default name as
+ used by Libgcrypt. An pointer to an empty string is returned for
+ an unknown algorithm. NULL is never returned. */
+const char *
+gcry_cipher_algo_name (int algorithm)
+{
+ return cipher_algo_to_string (algorithm);
+}
+
+
+/* Flag the cipher algorithm with the identifier ALGORITHM as
+ disabled. There is no error return, the function does nothing for
+ unknown algorithms. Disabled algorithms are vitually not available
+ in Libgcrypt. */
+static void
+disable_cipher_algo (int algorithm)
+{
+ gcry_module_t cipher;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
+ if (cipher)
+ {
+ if (! (cipher->flags & FLAG_MODULE_DISABLED))
+ cipher->flags |= FLAG_MODULE_DISABLED;
+ _gcry_module_release (cipher);
+ }
+ ath_mutex_unlock (&ciphers_registered_lock);
+}
+
+
+/* Return 0 if the cipher algorithm with identifier ALGORITHM is
+ available. Returns a basic error code value if it is not
+ available. */
+static gcry_err_code_t
+check_cipher_algo (int algorithm)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_module_t cipher;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
+ if (cipher)
+ {
+ if (cipher->flags & FLAG_MODULE_DISABLED)
+ err = GPG_ERR_CIPHER_ALGO;
+ _gcry_module_release (cipher);
+ }
+ else
+ err = GPG_ERR_CIPHER_ALGO;
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return err;
+}
+
+
+/* Return the standard length of the key for the cipher algorithm with
+ the identifier ALGORITHM. This function expects a valid algorithm
+ and will abort if the algorithm is not available or the length of
+ the key is not known. */
+static unsigned int
+cipher_get_keylen (int algorithm)
+{
+ gcry_module_t cipher;
+ unsigned len = 0;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
+ if (cipher)
+ {
+ len = ((gcry_cipher_spec_t *) cipher->spec)->keylen;
+ if (!len)
+ log_bug ("cipher %d w/o key length\n", algorithm);
+ _gcry_module_release (cipher);
+ }
+ else
+ log_bug ("cipher %d not found\n", algorithm);
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return len;
+}
+
+/* Return the block length of the cipher algorithm with the identifier
+ ALGORITHM. This function expects a valid algorithm and will abort
+ if the algorithm is not available or the length of the key is not
+ known. */
+static unsigned int
+cipher_get_blocksize (int algorithm)
+{
+ gcry_module_t cipher;
+ unsigned len = 0;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
+ if (cipher)
+ {
+ len = ((gcry_cipher_spec_t *) cipher->spec)->blocksize;
+ if (! len)
+ log_bug ("cipher %d w/o blocksize\n", algorithm);
+ _gcry_module_release (cipher);
+ }
+ else
+ log_bug ("cipher %d not found\n", algorithm);
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return len;
+}
+
+
+/*
+ Open a cipher handle for use with cipher algorithm ALGORITHM, using
+ the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
+ handle in HANDLE. Put NULL into HANDLE and return an error code if
+ something goes wrong. FLAGS may be used to modify the
+ operation. The defined flags are:
+
+ GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory.
+ GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP.
+ GCRY_CIPHER_CBC_CTS: Enable CTS mode.
+ GCRY_CIPHER_CBC_MAC: Enable MAC mode.
+
+ Values for these flags may be combined using OR.
+ */
+gcry_error_t
+gcry_cipher_open (gcry_cipher_hd_t *handle,
+ int algo, int mode, unsigned int flags)
+{
+ int secure = (flags & GCRY_CIPHER_SECURE);
+ gcry_cipher_spec_t *cipher = NULL;
+ cipher_extra_spec_t *extraspec = NULL;
+ gcry_module_t module = NULL;
+ gcry_cipher_hd_t h = NULL;
+ gcry_err_code_t err = 0;
+
+ /* If the application missed to call the random poll function, we do
+ it here to ensure that it is used once in a while. */
+ _gcry_fast_random_poll ();
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ /* Fetch the according module and check whether the cipher is marked
+ available for use. */
+ ath_mutex_lock (&ciphers_registered_lock);
+ module = _gcry_module_lookup_id (ciphers_registered, algo);
+ if (module)
+ {
+ /* Found module. */
+
+ if (module->flags & FLAG_MODULE_DISABLED)
+ {
+ /* Not available for use. */
+ err = GPG_ERR_CIPHER_ALGO;
+ }
+ else
+ {
+ cipher = (gcry_cipher_spec_t *) module->spec;
+ extraspec = module->extraspec;
+ }
+ }
+ else
+ err = GPG_ERR_CIPHER_ALGO;
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ /* check flags */
+ if ((! err)
+ && ((flags & ~(0
+ | GCRY_CIPHER_SECURE
+ | GCRY_CIPHER_ENABLE_SYNC
+ | GCRY_CIPHER_CBC_CTS
+ | GCRY_CIPHER_CBC_MAC))
+ || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
+ err = GPG_ERR_CIPHER_ALGO;
+
+ /* check that a valid mode has been requested */
+ if (! err)
+ switch (mode)
+ {
+ case GCRY_CIPHER_MODE_ECB:
+ case GCRY_CIPHER_MODE_CBC:
+ case GCRY_CIPHER_MODE_CFB:
+ case GCRY_CIPHER_MODE_OFB:
+ case GCRY_CIPHER_MODE_CTR:
+ case GCRY_CIPHER_MODE_AESWRAP:
+ if ((cipher->encrypt == dummy_encrypt_block)
+ || (cipher->decrypt == dummy_decrypt_block))
+ err = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
+ case GCRY_CIPHER_MODE_STREAM:
+ if ((cipher->stencrypt == dummy_encrypt_stream)
+ || (cipher->stdecrypt == dummy_decrypt_stream))
+ err = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
+ case GCRY_CIPHER_MODE_NONE:
+ /* This mode may be used for debugging. It copies the main
+ text verbatim to the ciphertext. We do not allow this in
+ fips mode or if no debug flag has been set. */
+ if (fips_mode () || !_gcry_get_debug_flag (0))
+ err = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
+ default:
+ err = GPG_ERR_INV_CIPHER_MODE;
+ }
+
+ /* Perform selftest here and mark this with a flag in cipher_table?
+ No, we should not do this as it takes too long. Further it does
+ not make sense to exclude algorithms with failing selftests at
+ runtime: If a selftest fails there is something seriously wrong
+ with the system and thus we better die immediately. */
+
+ if (! err)
+ {
+ size_t size = (sizeof (*h)
+ + 2 * cipher->contextsize
+ - sizeof (cipher_context_alignment_t)
+#ifdef NEED_16BYTE_ALIGNED_CONTEXT
+ + 15 /* Space for leading alignment gap. */
+#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
+ );
+
+ if (secure)
+ h = gcry_calloc_secure (1, size);
+ else
+ h = gcry_calloc (1, size);
+
+ if (! h)
+ err = gpg_err_code_from_errno (errno);
+ else
+ {
+ size_t off = 0;
+
+#ifdef NEED_16BYTE_ALIGNED_CONTEXT
+ if ( ((unsigned long)h & 0x0f) )
+ {
+ /* The malloced block is not aligned on a 16 byte
+ boundary. Correct for this. */
+ off = 16 - ((unsigned long)h & 0x0f);
+ h = (void*)((char*)h + off);
+ }
+#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
+
+ h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+ h->actual_handle_size = size - off;
+ h->handle_offset = off;
+ h->cipher = cipher;
+ h->extraspec = extraspec;
+ h->module = module;
+ h->algo = algo;
+ h->mode = mode;
+ h->flags = flags;
+
+ /* Setup bulk encryption routines. */
+ switch (algo)
+ {
+#ifdef USE_AES
+ case GCRY_CIPHER_AES128:
+ case GCRY_CIPHER_AES192:
+ case GCRY_CIPHER_AES256:
+ h->bulk.cfb_enc = _gcry_aes_cfb_enc;
+ h->bulk.cfb_dec = _gcry_aes_cfb_dec;
+ h->bulk.cbc_enc = _gcry_aes_cbc_enc;
+ h->bulk.cbc_dec = _gcry_aes_cbc_dec;
+ break;
+#endif /*USE_AES*/
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /* Done. */
+
+ if (err)
+ {
+ if (module)
+ {
+ /* Release module. */
+ ath_mutex_lock (&ciphers_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&ciphers_registered_lock);
+ }
+ }
+
+ *handle = err ? NULL : h;
+
+ return gcry_error (err);
+}
+
+
+/* Release all resources associated with the cipher handle H. H may be
+ NULL in which case this is a no-operation. */
+void
+gcry_cipher_close (gcry_cipher_hd_t h)
+{
+ size_t off;
+
+ if (!h)
+ return;
+
+ if ((h->magic != CTX_MAGIC_SECURE)
+ && (h->magic != CTX_MAGIC_NORMAL))
+ _gcry_fatal_error(GPG_ERR_INTERNAL,
+ "gcry_cipher_close: already closed/invalid handle");
+ else
+ h->magic = 0;
+
+ /* Release module. */
+ ath_mutex_lock (&ciphers_registered_lock);
+ _gcry_module_release (h->module);
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ /* We always want to wipe out the memory even when the context has
+ been allocated in secure memory. The user might have disabled
+ secure memory or is using his own implementation which does not
+ do the wiping. To accomplish this we need to keep track of the
+ actual size of this structure because we have no way to known
+ how large the allocated area was when using a standard malloc. */
+ off = h->handle_offset;
+ wipememory (h, h->actual_handle_size);
+
+ gcry_free ((char*)h - off);
+}
+
+
+/* Set the key to be used for the encryption context C to KEY with
+ length KEYLEN. The length should match the required length. */
+static gcry_error_t
+cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen)
+{
+ gcry_err_code_t ret;
+
+ ret = (*c->cipher->setkey) (&c->context.c, key, keylen);
+ if (!ret)
+ {
+ /* Duplicate initial context. */
+ memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize),
+ (void *) &c->context.c,
+ c->cipher->contextsize);
+ c->marks.key = 1;
+ }
+ else
+ c->marks.key = 0;
+
+ return gcry_error (ret);
+}
+
+
+/* Set the IV to be used for the encryption context C to IV with
+ length IVLEN. The length should match the required length. */
+static void
+cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
+{
+ memset (c->u_iv.iv, 0, c->cipher->blocksize);
+ if (iv)
+ {
+ if (ivlen != c->cipher->blocksize)
+ {
+ log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
+ ivlen, (unsigned int)c->cipher->blocksize);
+ fips_signal_error ("IV length does not match blocklength");
+ }
+ if (ivlen > c->cipher->blocksize)
+ ivlen = c->cipher->blocksize;
+ memcpy (c->u_iv.iv, iv, ivlen);
+ c->marks.iv = 1;
+ }
+ else
+ c->marks.iv = 0;
+ c->unused = 0;
+}
+
+
+/* Reset the cipher context to the initial context. This is basically
+ the same as an release followed by a new. */
+static void
+cipher_reset (gcry_cipher_hd_t c)
+{
+ memcpy (&c->context.c,
+ (char *) &c->context.c + c->cipher->contextsize,
+ c->cipher->contextsize);
+ memset (&c->marks, 0, sizeof c->marks);
+ memset (c->u_iv.iv, 0, c->cipher->blocksize);
+ memset (c->lastiv, 0, c->cipher->blocksize);
+ memset (c->ctr, 0, c->cipher->blocksize);
+}
+
+
+
+static gcry_err_code_t
+do_ecb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned int blocksize = c->cipher->blocksize;
+ unsigned int n, nblocks;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+
+ nblocks = inbuflen / c->cipher->blocksize;
+
+ for (n=0; n < nblocks; n++ )
+ {
+ c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+ inbuf += blocksize;
+ outbuf += blocksize;
+ }
+ return 0;
+}
+
+static gcry_err_code_t
+do_ecb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned int blocksize = c->cipher->blocksize;
+ unsigned int n, nblocks;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+ nblocks = inbuflen / c->cipher->blocksize;
+
+ for (n=0; n < nblocks; n++ )
+ {
+ c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf );
+ inbuf += blocksize;
+ outbuf += blocksize;
+ }
+
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_cbc_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned int n;
+ unsigned char *ivp;
+ int i;
+ size_t blocksize = c->cipher->blocksize;
+ unsigned nblocks = inbuflen / blocksize;
+
+ if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen))
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % c->cipher->blocksize)
+ && !(inbuflen > c->cipher->blocksize
+ && (c->flags & GCRY_CIPHER_CBC_CTS)))
+ return GPG_ERR_INV_LENGTH;
+
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+ {
+ if ((inbuflen % blocksize) == 0)
+ nblocks--;
+ }
+
+ if (c->bulk.cbc_enc)
+ {
+ c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
+ (c->flags & GCRY_CIPHER_CBC_MAC));
+ inbuf += nblocks * blocksize;
+ if (!(c->flags & GCRY_CIPHER_CBC_MAC))
+ outbuf += nblocks * blocksize;
+ }
+ else
+ {
+ for (n=0; n < nblocks; n++ )
+ {
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ outbuf[i] = inbuf[i] ^ *ivp++;
+ c->cipher->encrypt ( &c->context.c, outbuf, outbuf );
+ memcpy (c->u_iv.iv, outbuf, blocksize );
+ inbuf += blocksize;
+ if (!(c->flags & GCRY_CIPHER_CBC_MAC))
+ outbuf += blocksize;
+ }
+ }
+
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+ {
+ /* We have to be careful here, since outbuf might be equal to
+ inbuf. */
+ int restbytes;
+ unsigned char b;
+
+ if ((inbuflen % blocksize) == 0)
+ restbytes = blocksize;
+ else
+ restbytes = inbuflen % blocksize;
+
+ outbuf -= blocksize;
+ for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
+ {
+ b = inbuf[i];
+ outbuf[blocksize + i] = outbuf[i];
+ outbuf[i] = b ^ *ivp++;
+ }
+ for (; i < blocksize; i++)
+ outbuf[i] = 0 ^ *ivp++;
+
+ c->cipher->encrypt (&c->context.c, outbuf, outbuf);
+ memcpy (c->u_iv.iv, outbuf, blocksize);
+ }
+
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_cbc_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned int n;
+ unsigned char *ivp;
+ int i;
+ size_t blocksize = c->cipher->blocksize;
+ unsigned int nblocks = inbuflen / blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % c->cipher->blocksize)
+ && !(inbuflen > c->cipher->blocksize
+ && (c->flags & GCRY_CIPHER_CBC_CTS)))
+ return GPG_ERR_INV_LENGTH;
+
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+ {
+ nblocks--;
+ if ((inbuflen % blocksize) == 0)
+ nblocks--;
+ memcpy (c->lastiv, c->u_iv.iv, blocksize);
+ }
+
+ if (c->bulk.cbc_dec)
+ {
+ c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
+ inbuf += nblocks * blocksize;
+ outbuf += nblocks * blocksize;
+ }
+ else
+ {
+ for (n=0; n < nblocks; n++ )
+ {
+ /* Because outbuf and inbuf might be the same, we have to
+ * save the original ciphertext block. We use LASTIV for
+ * this here because it is not used otherwise. */
+ memcpy (c->lastiv, inbuf, blocksize);
+ c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ outbuf[i] ^= *ivp++;
+ memcpy(c->u_iv.iv, c->lastiv, blocksize );
+ inbuf += c->cipher->blocksize;
+ outbuf += c->cipher->blocksize;
+ }
+ }
+
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+ {
+ int restbytes;
+
+ if ((inbuflen % blocksize) == 0)
+ restbytes = blocksize;
+ else
+ restbytes = inbuflen % blocksize;
+
+ memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
+ memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
+
+ c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
+ for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ )
+ outbuf[i] ^= *ivp++;
+
+ memcpy(outbuf + blocksize, outbuf, restbytes);
+ for(i=restbytes; i < blocksize; i++)
+ c->u_iv.iv[i] = outbuf[i];
+ c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv);
+ for(ivp=c->lastiv,i=0; i < blocksize; i++ )
+ outbuf[i] ^= *ivp++;
+ /* c->lastiv is now really lastlastiv, does this matter? */
+ }
+
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_cfb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned char *ivp;
+ size_t blocksize = c->cipher->blocksize;
+ size_t blocksize_x_2 = blocksize + blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ( inbuflen <= c->unused )
+ {
+ /* Short enough to be encoded by the remaining XOR mask. */
+ /* XOR the input with the IV and store input into IV. */
+ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
+ inbuflen;
+ inbuflen--, c->unused-- )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ return 0;
+ }
+
+ if ( c->unused )
+ {
+ /* XOR the input with the IV and store input into IV */
+ inbuflen -= c->unused;
+ for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ }
+
+ /* Now we can process complete blocks. We use a loop as long as we
+ have at least 2 blocks and use conditions for the rest. This
+ also allows to use a bulk encryption function if available. */
+ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
+ {
+ unsigned int nblocks = inbuflen / blocksize;
+ c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
+ outbuf += nblocks * blocksize;
+ inbuf += nblocks * blocksize;
+ inbuflen -= nblocks * blocksize;
+ }
+ else
+ {
+ while ( inbuflen >= blocksize_x_2 )
+ {
+ int i;
+ /* Encrypt the IV. */
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ /* XOR the input with the IV and store input into IV. */
+ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ inbuflen -= blocksize;
+ }
+ }
+
+ if ( inbuflen >= blocksize )
+ {
+ int i;
+ /* Save the current IV and then encrypt the IV. */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ /* XOR the input with the IV and store input into IV */
+ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ inbuflen -= blocksize;
+ }
+ if ( inbuflen )
+ {
+ /* Save the current IV and then encrypt the IV. */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ c->unused = blocksize;
+ /* Apply the XOR. */
+ c->unused -= inbuflen;
+ for(ivp=c->u_iv.iv; inbuflen; inbuflen-- )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ }
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_cfb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned char *ivp;
+ unsigned long temp;
+ int i;
+ size_t blocksize = c->cipher->blocksize;
+ size_t blocksize_x_2 = blocksize + blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if (inbuflen <= c->unused)
+ {
+ /* Short enough to be encoded by the remaining XOR mask. */
+ /* XOR the input with the IV and store input into IV. */
+ for (ivp=c->u_iv.iv+blocksize - c->unused;
+ inbuflen;
+ inbuflen--, c->unused--)
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ return 0;
+ }
+
+ if (c->unused)
+ {
+ /* XOR the input with the IV and store input into IV. */
+ inbuflen -= c->unused;
+ for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ }
+
+ /* Now we can process complete blocks. We use a loop as long as we
+ have at least 2 blocks and use conditions for the rest. This
+ also allows to use a bulk encryption function if available. */
+ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
+ {
+ unsigned int nblocks = inbuflen / blocksize;
+ c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
+ outbuf += nblocks * blocksize;
+ inbuf += nblocks * blocksize;
+ inbuflen -= nblocks * blocksize;
+ }
+ else
+ {
+ while (inbuflen >= blocksize_x_2 )
+ {
+ /* Encrypt the IV. */
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ /* XOR the input with the IV and store input into IV. */
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ inbuflen -= blocksize;
+ }
+ }
+
+ if (inbuflen >= blocksize )
+ {
+ /* Save the current IV and then encrypt the IV. */
+ memcpy ( c->lastiv, c->u_iv.iv, blocksize);
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ /* XOR the input with the IV and store input into IV */
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ inbuflen -= blocksize;
+ }
+
+ if (inbuflen)
+ {
+ /* Save the current IV and then encrypt the IV. */
+ memcpy ( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ c->unused = blocksize;
+ /* Apply the XOR. */
+ c->unused -= inbuflen;
+ for (ivp=c->u_iv.iv; inbuflen; inbuflen-- )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ }
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_ofb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned char *ivp;
+ size_t blocksize = c->cipher->blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ( inbuflen <= c->unused )
+ {
+ /* Short enough to be encoded by the remaining XOR mask. */
+ /* XOR the input with the IV */
+ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
+ inbuflen;
+ inbuflen--, c->unused-- )
+ *outbuf++ = (*ivp++ ^ *inbuf++);
+ return 0;
+ }
+
+ if( c->unused )
+ {
+ inbuflen -= c->unused;
+ for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
+ *outbuf++ = (*ivp++ ^ *inbuf++);
+ }
+
+ /* Now we can process complete blocks. */
+ while ( inbuflen >= blocksize )
+ {
+ int i;
+ /* Encrypt the IV (and save the current one). */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ *outbuf++ = (*ivp++ ^ *inbuf++);
+ inbuflen -= blocksize;
+ }
+ if ( inbuflen )
+ { /* process the remaining bytes */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ c->unused = blocksize;
+ c->unused -= inbuflen;
+ for(ivp=c->u_iv.iv; inbuflen; inbuflen-- )
+ *outbuf++ = (*ivp++ ^ *inbuf++);
+ }
+ return 0;
+}
+
+static gcry_err_code_t
+do_ofb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned char *ivp;
+ size_t blocksize = c->cipher->blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if( inbuflen <= c->unused )
+ {
+ /* Short enough to be encoded by the remaining XOR mask. */
+ for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--)
+ *outbuf++ = *ivp++ ^ *inbuf++;
+ return 0;
+ }
+
+ if ( c->unused )
+ {
+ inbuflen -= c->unused;
+ for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
+ *outbuf++ = *ivp++ ^ *inbuf++;
+ }
+
+ /* Now we can process complete blocks. */
+ while ( inbuflen >= blocksize )
+ {
+ int i;
+ /* Encrypt the IV (and save the current one). */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
+ *outbuf++ = *ivp++ ^ *inbuf++;
+ inbuflen -= blocksize;
+ }
+ if ( inbuflen )
+ { /* Process the remaining bytes. */
+ /* Encrypt the IV (and save the current one). */
+ memcpy( c->lastiv, c->u_iv.iv, blocksize );
+ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ c->unused = blocksize;
+ c->unused -= inbuflen;
+ for (ivp=c->u_iv.iv; inbuflen; inbuflen-- )
+ *outbuf++ = *ivp++ ^ *inbuf++;
+ }
+ return 0;
+}
+
+
+static gcry_err_code_t
+do_ctr_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ unsigned int n;
+ unsigned char tmp[MAX_BLOCKSIZE];
+ int i;
+ unsigned int blocksize = c->cipher->blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+
+ for (n=0; n < inbuflen; n++)
+ {
+ if ((n % blocksize) == 0)
+ {
+ c->cipher->encrypt (&c->context.c, tmp, c->ctr);
+
+ for (i = blocksize; i > 0; i--)
+ {
+ c->ctr[i-1]++;
+ if (c->ctr[i-1] != 0)
+ break;
+ }
+ }
+
+ /* XOR input with encrypted counter and store in output. */
+ outbuf[n] = inbuf[n] ^ tmp[n % blocksize];
+ }
+
+ wipememory (tmp, sizeof tmp);
+ return 0;
+}
+
+static gcry_err_code_t
+do_ctr_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
+{
+ return do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+}
+
+
+/* Perform the AES-Wrap algorithm as specified by RFC3394. We
+ implement this as a mode usable with any cipher algorithm of
+ blocksize 128. */
+static gcry_err_code_t
+do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
+ const byte *inbuf, unsigned int inbuflen )
+{
+ int j, x;
+ unsigned int n, i;
+ unsigned char *r, *a, *b;
+ unsigned char t[8];
+
+#if MAX_BLOCKSIZE < 8
+#error Invalid block size
+#endif
+ /* We require a cipher with a 128 bit block length. */
+ if (c->cipher->blocksize != 16)
+ return GPG_ERR_INV_LENGTH;
+
+ /* The output buffer must be able to hold the input data plus one
+ additional block. */
+ if (outbuflen < inbuflen + 8)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ /* Input data must be multiple of 64 bits. */
+ if (inbuflen % 8)
+ return GPG_ERR_INV_ARG;
+
+ n = inbuflen / 8;
+
+ /* We need at least two 64 bit blocks. */
+ if (n < 2)
+ return GPG_ERR_INV_ARG;
+
+ r = outbuf;
+ a = outbuf; /* We store A directly in OUTBUF. */
+ b = c->ctr; /* B is also used to concatenate stuff. */
+
+ /* If an IV has been set we use that IV as the Alternative Initial
+ Value; if it has not been set we use the standard value. */
+ if (c->marks.iv)
+ memcpy (a, c->u_iv.iv, 8);
+ else
+ memset (a, 0xa6, 8);
+
+ /* Copy the inbuf to the outbuf. */
+ memmove (r+8, inbuf, inbuflen);
+
+ memset (t, 0, sizeof t); /* t := 0. */
+
+ for (j = 0; j <= 5; j++)
+ {
+ for (i = 1; i <= n; i++)
+ {
+ /* B := AES_k( A | R[i] ) */
+ memcpy (b, a, 8);
+ memcpy (b+8, r+i*8, 8);
+ c->cipher->encrypt (&c->context.c, b, b);
+ /* t := t + 1 */
+ for (x = 7; x >= 0; x--)
+ {
+ t[x]++;
+ if (t[x])
+ break;
+ }
+ /* A := MSB_64(B) ^ t */
+ for (x=0; x < 8; x++)
+ a[x] = b[x] ^ t[x];
+ /* R[i] := LSB_64(B) */
+ memcpy (r+i*8, b+8, 8);
+ }
+ }
+
+ return 0;
+}
+
+/* Perform the AES-Unwrap algorithm as specified by RFC3394. We
+ implement this as a mode usable with any cipher algorithm of
+ blocksize 128. */
+static gcry_err_code_t
+do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
+ const byte *inbuf, unsigned int inbuflen)
+{
+ int j, x;
+ unsigned int n, i;
+ unsigned char *r, *a, *b;
+ unsigned char t[8];
+
+#if MAX_BLOCKSIZE < 8
+#error Invalid block size
+#endif
+ /* We require a cipher with a 128 bit block length. */
+ if (c->cipher->blocksize != 16)
+ return GPG_ERR_INV_LENGTH;
+
+ /* The output buffer must be able to hold the input data minus one
+ additional block. Fixme: The caller has more restrictive checks
+ - we may want to fix them for this mode. */
+ if (outbuflen + 8 < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ /* Input data must be multiple of 64 bits. */
+ if (inbuflen % 8)
+ return GPG_ERR_INV_ARG;
+
+ n = inbuflen / 8;
+
+ /* We need at least three 64 bit blocks. */
+ if (n < 3)
+ return GPG_ERR_INV_ARG;
+
+ r = outbuf;
+ a = c->lastiv; /* We use c->LASTIV as buffer for A. */
+ b = c->ctr; /* B is also used to concatenate stuff. */
+
+ /* Copy the inbuf to the outbuf and save A. */
+ memcpy (a, inbuf, 8);
+ memmove (r, inbuf+8, inbuflen-8);
+ n--; /* Reduce to actual number of data blocks. */
+
+ /* t := 6 * n */
+ i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */
+ for (x=0; x < 8 && x < sizeof (i); x++)
+ t[7-x] = i >> (8*x);
+ for (; x < 8; x++)
+ t[7-x] = 0;
+
+ for (j = 5; j >= 0; j--)
+ {
+ for (i = n; i >= 1; i--)
+ {
+ /* B := AES_k^1( (A ^ t)| R[i] ) */
+ for (x = 0; x < 8; x++)
+ b[x] = a[x] ^ t[x];
+ memcpy (b+8, r+(i-1)*8, 8);
+ c->cipher->decrypt (&c->context.c, b, b);
+ /* t := t - 1 */
+ for (x = 7; x >= 0; x--)
+ {
+ t[x]--;
+ if (t[x] != 0xff)
+ break;
+ }
+ /* A := MSB_64(B) */
+ memcpy (a, b, 8);
+ /* R[i] := LSB_64(B) */
+ memcpy (r+(i-1)*8, b+8, 8);
+ }
+ }
+
+ /* If an IV has been set we compare against this Alternative Initial
+ Value; if it has not been set we compare against the standard IV. */
+ if (c->marks.iv)
+ j = memcmp (a, c->u_iv.iv, 8);
+ else
+ {
+ for (j=0, x=0; x < 8; x++)
+ if (a[x] != 0xa6)
+ {
+ j=1;
+ break;
+ }
+ }
+ return j? GPG_ERR_CHECKSUM : 0;
+}
+
+
+/****************
+ * Encrypt INBUF to OUTBUF with the mode selected at open.
+ * inbuf and outbuf may overlap or be the same.
+ * Depending on the mode some constraints apply to INBUFLEN.
+ */
+static gcry_err_code_t
+cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
+ const byte *inbuf, unsigned int inbuflen)
+{
+ gcry_err_code_t rc;
+
+ switch (c->mode)
+ {
+ case GCRY_CIPHER_MODE_ECB:
+ rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CBC:
+ rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CFB:
+ rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_OFB:
+ rc = do_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CTR:
+ rc = do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_AESWRAP:
+ rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_STREAM:
+ c->cipher->stencrypt (&c->context.c,
+ outbuf, (byte*)/*arggg*/inbuf, inbuflen);
+ rc = 0;
+ break;
+
+ case GCRY_CIPHER_MODE_NONE:
+ if (fips_mode () || !_gcry_get_debug_flag (0))
+ {
+ fips_signal_error ("cipher mode NONE used");
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ }
+ else
+ {
+ if (inbuf != outbuf)
+ memmove (outbuf, inbuf, inbuflen);
+ rc = 0;
+ }
+ break;
+
+ default:
+ log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+ }
+
+ return rc;
+}
+
+
+/****************
+ * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has
+ * been requested.
+ */
+gcry_error_t
+gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
+ const void *in, size_t inlen)
+{
+ gcry_err_code_t err;
+
+ if (!in) /* Caller requested in-place encryption. */
+ err = cipher_encrypt (h, out, outsize, out, outsize);
+ else
+ err = cipher_encrypt (h, out, outsize, in, inlen);
+
+ /* Failsafe: Make sure that the plaintext will never make it into
+ OUT if the encryption returned an error. */
+ if (err && out)
+ memset (out, 0x42, outsize);
+
+ return gcry_error (err);
+}
+
+
+
+/****************
+ * Decrypt INBUF to OUTBUF with the mode selected at open.
+ * inbuf and outbuf may overlap or be the same.
+ * Depending on the mode some some contraints apply to INBUFLEN.
+ */
+static gcry_err_code_t
+cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
+ const byte *inbuf, unsigned int inbuflen)
+{
+ gcry_err_code_t rc;
+
+ switch (c->mode)
+ {
+ case GCRY_CIPHER_MODE_ECB:
+ rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CBC:
+ rc = do_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CFB:
+ rc = do_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_OFB:
+ rc = do_ofb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_CTR:
+ rc = do_ctr_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_AESWRAP:
+ rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
+ case GCRY_CIPHER_MODE_STREAM:
+ c->cipher->stdecrypt (&c->context.c,
+ outbuf, (byte*)/*arggg*/inbuf, inbuflen);
+ rc = 0;
+ break;
+
+ case GCRY_CIPHER_MODE_NONE:
+ if (fips_mode () || !_gcry_get_debug_flag (0))
+ {
+ fips_signal_error ("cipher mode NONE used");
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ }
+ else
+ {
+ if (inbuf != outbuf)
+ memmove (outbuf, inbuf, inbuflen);
+ rc = 0;
+ }
+ break;
+
+ default:
+ log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
+ rc = GPG_ERR_INV_CIPHER_MODE;
+ break;
+ }
+
+ return rc;
+}
+
+
+gcry_error_t
+gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
+ const void *in, size_t inlen)
+{
+ gcry_err_code_t err;
+
+ if (!in) /* Caller requested in-place encryption. */
+ err = cipher_decrypt (h, out, outsize, out, outsize);
+ else
+ err = cipher_decrypt (h, out, outsize, in, inlen);
+
+ return gcry_error (err);
+}
+
+
+
+/****************
+ * Used for PGP's somewhat strange CFB mode. Only works if
+ * the corresponding flag is set.
+ */
+static void
+cipher_sync (gcry_cipher_hd_t c)
+{
+ if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
+ {
+ memmove (c->u_iv.iv + c->unused,
+ c->u_iv.iv, c->cipher->blocksize - c->unused);
+ memcpy (c->u_iv.iv,
+ c->lastiv + c->cipher->blocksize - c->unused, c->unused);
+ c->unused = 0;
+ }
+}
+
+
+gcry_error_t
+_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
+{
+ return cipher_setkey (hd, (void*)key, keylen);
+}
+
+
+gcry_error_t
+_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
+{
+ cipher_setiv (hd, iv, ivlen);
+ return 0;
+}
+
+/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
+ block size length, or (NULL,0) to set the CTR to the all-zero
+ block. */
+gpg_error_t
+_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
+{
+ if (ctr && ctrlen == hd->cipher->blocksize)
+ memcpy (hd->ctr, ctr, hd->cipher->blocksize);
+ else if (!ctr || !ctrlen)
+ memset (hd->ctr, 0, hd->cipher->blocksize);
+ else
+ return gpg_error (GPG_ERR_INV_ARG);
+ return 0;
+}
+
+
+gcry_error_t
+gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
+{
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
+
+ switch (cmd)
+ {
+ case GCRYCTL_SET_KEY: /* Deprecated; use gcry_cipher_setkey. */
+ rc = cipher_setkey( h, buffer, buflen );
+ break;
+
+ case GCRYCTL_SET_IV: /* Deprecated; use gcry_cipher_setiv. */
+ cipher_setiv( h, buffer, buflen );
+ break;
+
+ case GCRYCTL_RESET:
+ cipher_reset (h);
+ break;
+
+ case GCRYCTL_CFB_SYNC:
+ cipher_sync( h );
+ break;
+
+ case GCRYCTL_SET_CBC_CTS:
+ if (buflen)
+ if (h->flags & GCRY_CIPHER_CBC_MAC)
+ rc = GPG_ERR_INV_FLAG;
+ else
+ h->flags |= GCRY_CIPHER_CBC_CTS;
+ else
+ h->flags &= ~GCRY_CIPHER_CBC_CTS;
+ break;
+
+ case GCRYCTL_SET_CBC_MAC:
+ if (buflen)
+ if (h->flags & GCRY_CIPHER_CBC_CTS)
+ rc = GPG_ERR_INV_FLAG;
+ else
+ h->flags |= GCRY_CIPHER_CBC_MAC;
+ else
+ h->flags &= ~GCRY_CIPHER_CBC_MAC;
+ break;
+
+ case GCRYCTL_DISABLE_ALGO:
+ /* This command expects NULL for H and BUFFER to point to an
+ integer with the algo number. */
+ if( h || !buffer || buflen != sizeof(int) )
+ return gcry_error (GPG_ERR_CIPHER_ALGO);
+ disable_cipher_algo( *(int*)buffer );
+ break;
+
+ case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */
+ if (buffer && buflen == h->cipher->blocksize)
+ memcpy (h->ctr, buffer, h->cipher->blocksize);
+ else if (buffer == NULL || buflen == 0)
+ memset (h->ctr, 0, h->cipher->blocksize);
+ else
+ rc = GPG_ERR_INV_ARG;
+ break;
+
+ case 61: /* Disable weak key detection (private). */
+ if (h->extraspec->set_extra_info)
+ rc = h->extraspec->set_extra_info
+ (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
+ else
+ rc = GPG_ERR_NOT_SUPPORTED;
+ break;
+
+ case 62: /* Return current input vector (private). */
+ /* This is the input block as used in CFB and OFB mode which has
+ initially been set as IV. The returned format is:
+ 1 byte Actual length of the block in bytes.
+ n byte The block.
+ If the provided buffer is too short, an error is returned. */
+ if (buflen < (1 + h->cipher->blocksize))
+ rc = GPG_ERR_TOO_SHORT;
+ else
+ {
+ unsigned char *ivp;
+ unsigned char *dst = buffer;
+ int n = h->unused;
+
+ if (!n)
+ n = h->cipher->blocksize;
+ gcry_assert (n <= h->cipher->blocksize);
+ *dst++ = n;
+ ivp = h->u_iv.iv + h->cipher->blocksize - n;
+ while (n--)
+ *dst++ = *ivp++;
+ }
+ break;
+
+ default:
+ rc = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (rc);
+}
+
+
+/* Return information about the cipher handle H. CMD is the kind of
+ information requested. BUFFER and NBYTES are reserved for now.
+
+ There are no values for CMD yet defined.
+
+ The function always returns GPG_ERR_INV_OP.
+
+ */
+gcry_error_t
+gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ (void)h;
+ (void)buffer;
+ (void)nbytes;
+
+ switch (cmd)
+ {
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+/* Return information about the given cipher algorithm ALGO.
+
+ WHAT select the kind of information returned:
+
+ GCRYCTL_GET_KEYLEN:
+ Return the length of the key. If the algorithm ALGO
+ supports multiple key lengths, the maximum supported key length
+ is returned. The key length is returned as number of octets.
+ BUFFER and NBYTES must be zero.
+
+ GCRYCTL_GET_BLKLEN:
+ Return the blocklength of the algorithm ALGO counted in octets.
+ BUFFER and NBYTES must be zero.
+
+ GCRYCTL_TEST_ALGO:
+ Returns 0 if the specified algorithm ALGO is available for use.
+ BUFFER and NBYTES must be zero.
+
+ Note: Because this function is in most cases used to return an
+ integer value, we can make it easier for the caller to just look at
+ the return value. The caller will in all cases consult the value
+ and thereby detecting whether a error occurred or not (i.e. while
+ checking the block size)
+ */
+gcry_error_t
+gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ unsigned int ui;
+
+ switch (what)
+ {
+ case GCRYCTL_GET_KEYLEN:
+ if (buffer || (! nbytes))
+ err = GPG_ERR_CIPHER_ALGO;
+ else
+ {
+ ui = cipher_get_keylen (algo);
+ if ((ui > 0) && (ui <= 512))
+ *nbytes = (size_t) ui / 8;
+ else
+ /* The only reason is an invalid algo or a strange
+ blocksize. */
+ err = GPG_ERR_CIPHER_ALGO;
+ }
+ break;
+
+ case GCRYCTL_GET_BLKLEN:
+ if (buffer || (! nbytes))
+ err = GPG_ERR_CIPHER_ALGO;
+ else
+ {
+ ui = cipher_get_blocksize (algo);
+ if ((ui > 0) && (ui < 10000))
+ *nbytes = ui;
+ else
+ /* The only reason is an invalid algo or a strange
+ blocksize. */
+ err = GPG_ERR_CIPHER_ALGO;
+ }
+ break;
+
+ case GCRYCTL_TEST_ALGO:
+ if (buffer || nbytes)
+ err = GPG_ERR_INV_ARG;
+ else
+ err = check_cipher_algo (algo);
+ break;
+
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+
+/* This function returns length of the key for algorithm ALGO. If the
+ algorithm supports multiple key lengths, the maximum supported key
+ length is returned. On error 0 is returned. The key length is
+ returned as number of octets.
+
+ This is a convenience functions which should be preferred over
+ gcry_cipher_algo_info because it allows for proper type
+ checking. */
+size_t
+gcry_cipher_get_algo_keylen (int algo)
+{
+ size_t n;
+
+ if (gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n))
+ n = 0;
+ return n;
+}
+
+/* This functions returns the blocklength of the algorithm ALGO
+ counted in octets. On error 0 is returned.
+
+ This is a convenience functions which should be preferred over
+ gcry_cipher_algo_info because it allows for proper type
+ checking. */
+size_t
+gcry_cipher_get_algo_blklen (int algo)
+{
+ size_t n;
+
+ if (gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n))
+ n = 0;
+ return n;
+}
+
+/* Explicitly initialize this module. */
+gcry_err_code_t
+_gcry_cipher_init (void)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ return err;
+}
+
+/* Get a list consisting of the IDs of the loaded cipher modules. If
+ LIST is zero, write the number of loaded cipher modules to
+ LIST_LENGTH and return. If LIST is non-zero, the first
+ *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
+ according size. In case there are less cipher modules than
+ *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
+gcry_error_t
+gcry_cipher_list (int *list, int *list_length)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ err = _gcry_module_list (ciphers_registered, list, list_length);
+ ath_mutex_unlock (&ciphers_registered_lock);
+
+ return err;
+}
+
+
+/* Run the selftests for cipher algorithm ALGO with optional reporting
+ function REPORT. */
+gpg_error_t
+_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
+{
+ gcry_module_t module = NULL;
+ cipher_extra_spec_t *extraspec = NULL;
+ gcry_err_code_t ec = 0;
+
+ REGISTER_DEFAULT_CIPHERS;
+
+ ath_mutex_lock (&ciphers_registered_lock);
+ module = _gcry_module_lookup_id (ciphers_registered, algo);
+ if (module && !(module->flags & FLAG_MODULE_DISABLED))
+ extraspec = module->extraspec;
+ ath_mutex_unlock (&ciphers_registered_lock);
+ if (extraspec && extraspec->selftest)
+ ec = extraspec->selftest (algo, extended, report);
+ else
+ {
+ ec = GPG_ERR_CIPHER_ALGO;
+ if (report)
+ report ("cipher", algo, "module",
+ module && !(module->flags & FLAG_MODULE_DISABLED)?
+ "no selftest available" :
+ module? "algorithm disabled" : "algorithm not found");
+ }
+
+ if (module)
+ {
+ ath_mutex_lock (&ciphers_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&ciphers_registered_lock);
+ }
+ return gpg_error (ec);
+}
diff --git a/libgcrypt-1.4.6/cipher/ecc.c b/libgcrypt-1.4.6/cipher/ecc.c
index fcbd8e3..bcfab05 100644
--- a/libgcrypt-1.4.6/cipher/ecc.c
+++ b/libgcrypt-1.4.6/cipher/ecc.c
@@ -1,5 +1,5 @@
/* ecc.c - Elliptic Curve Cryptography
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc.
This file is part of Libgcrypt.
@@ -504,6 +504,7 @@ generate_curve (unsigned int nbits, const char *name,
*/
static gpg_err_code_t
generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
+ int transient_key,
gcry_mpi_t g_x, gcry_mpi_t g_y,
gcry_mpi_t q_x, gcry_mpi_t q_y)
{
@@ -512,6 +513,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
gcry_mpi_t d;
mpi_point_t Q;
mpi_ec_t ctx;
+ gcry_random_level_t random_level;
err = generate_curve (nbits, name, &E, &nbits);
if (err)
@@ -528,9 +530,11 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
log_mpidump ("ecc generation Gz", E.G.z);
}
+ random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
if (DBG_CIPHER)
- log_debug ("choosing a random x of size %u\n", nbits);
- d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM);
+ log_debug ("choosing a random x of size %u%s\n", nbits,
+ transient_key? " (transient-key)":"");
+ d = gen_k (E.n, random_level);
/* Compute Q. */
point_init (&Q);
@@ -962,6 +966,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
gcry_mpi_t g_x, g_y, q_x, q_y;
char *curve_name = NULL;
gcry_sexp_t l1;
+ int transient_key = 0;
(void)algo;
(void)evalue;
@@ -978,6 +983,14 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
if (!curve_name)
return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
}
+
+ /* Parse the optional transient-key flag. */
+ l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
+ if (l1)
+ {
+ transient_key = 1;
+ gcry_sexp_release (l1);
+ }
}
/* NBITS is required if no curve name has been given. */
@@ -988,7 +1001,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
g_y = mpi_new (0);
q_x = mpi_new (0);
q_y = mpi_new (0);
- ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y);
+ ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y);
gcry_free (curve_name);
if (ec)
return ec;
@@ -1266,7 +1279,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
}
/* Check that all parameters are known and normalize all MPIs (that
- should not be required but we use an internal fucntion later and
+ should not be required but we use an internal function later and
thus we better make 100% sure that they are normalized). */
for (idx = 0; idx < 6; idx++)
if (!values[idx])
diff --git a/libgcrypt-1.4.6/cipher/md.c b/libgcrypt-1.4.6/cipher/md.c
index 84c7799..5f9dbc6 100644
--- a/libgcrypt-1.4.6/cipher/md.c
+++ b/libgcrypt-1.4.6/cipher/md.c
@@ -1,1382 +1,1382 @@
-/* md.c - message digest dispatcher
- * Copyright (C) 1998, 1999, 2002, 2003, 2006,
- * 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "g10lib.h"
-#include "cipher.h"
-#include "ath.h"
-
-#include "rmd.h"
-
-/* A dummy extraspec so that we do not need to tests the extraspec
- field from the module specification against NULL and instead
- directly test the respective fields of extraspecs. */
-static md_extra_spec_t dummy_extra_spec;
-
-
-/* This is the list of the digest implementations included in
- libgcrypt. */
-static struct digest_table_entry
-{
- gcry_md_spec_t *digest;
- md_extra_spec_t *extraspec;
- unsigned int algorithm;
- int fips_allowed;
-} digest_table[] =
- {
-#if USE_CRC
- /* We allow the CRC algorithms even in FIPS mode because they are
- actually no cryptographic primitives. */
- { &_gcry_digest_spec_crc32,
- &dummy_extra_spec, GCRY_MD_CRC32, 1 },
- { &_gcry_digest_spec_crc32_rfc1510,
- &dummy_extra_spec, GCRY_MD_CRC32_RFC1510, 1 },
- { &_gcry_digest_spec_crc24_rfc2440,
- &dummy_extra_spec, GCRY_MD_CRC24_RFC2440, 1 },
-#endif
-#if USE_MD4
- { &_gcry_digest_spec_md4,
- &dummy_extra_spec, GCRY_MD_MD4 },
-#endif
-#if USE_MD5
- { &_gcry_digest_spec_md5,
- &dummy_extra_spec, GCRY_MD_MD5, 1 },
-#endif
-#if USE_RMD160
- { &_gcry_digest_spec_rmd160,
- &dummy_extra_spec, GCRY_MD_RMD160 },
-#endif
-#if USE_SHA1
- { &_gcry_digest_spec_sha1,
- &_gcry_digest_extraspec_sha1, GCRY_MD_SHA1, 1 },
-#endif
-#if USE_SHA256
- { &_gcry_digest_spec_sha256,
- &_gcry_digest_extraspec_sha256, GCRY_MD_SHA256, 1 },
- { &_gcry_digest_spec_sha224,
- &_gcry_digest_extraspec_sha224, GCRY_MD_SHA224, 1 },
-#endif
-#if USE_SHA512
- { &_gcry_digest_spec_sha512,
- &_gcry_digest_extraspec_sha512, GCRY_MD_SHA512, 1 },
- { &_gcry_digest_spec_sha384,
- &_gcry_digest_extraspec_sha384, GCRY_MD_SHA384, 1 },
-#endif
-#if USE_TIGER
- { &_gcry_digest_spec_tiger,
- &dummy_extra_spec, GCRY_MD_TIGER },
- { &_gcry_digest_spec_tiger1,
- &dummy_extra_spec, GCRY_MD_TIGER1 },
- { &_gcry_digest_spec_tiger2,
- &dummy_extra_spec, GCRY_MD_TIGER2 },
-#endif
-#if USE_WHIRLPOOL
- { &_gcry_digest_spec_whirlpool,
- &dummy_extra_spec, GCRY_MD_WHIRLPOOL },
-#endif
- { NULL },
- };
-
-/* List of registered digests. */
-static gcry_module_t digests_registered;
-
-/* This is the lock protecting DIGESTS_REGISTERED. */
-static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER;
-
-/* Flag to check wether the default ciphers have already been
- registered. */
-static int default_digests_registered;
-
-typedef struct gcry_md_list
-{
- gcry_md_spec_t *digest;
- gcry_module_t module;
- struct gcry_md_list *next;
- size_t actual_struct_size; /* Allocated size of this structure. */
- PROPERLY_ALIGNED_TYPE context;
-} GcryDigestEntry;
-
-/* this structure is put right after the gcry_md_hd_t buffer, so that
- * only one memory block is needed. */
-struct gcry_md_context
-{
- int magic;
- size_t actual_handle_size; /* Allocated size of this handle. */
- int secure;
- FILE *debug;
- int finalized;
- GcryDigestEntry *list;
- byte *macpads;
- int macpads_Bsize; /* Blocksize as used for the HMAC pads. */
-};
-
-
-#define CTX_MAGIC_NORMAL 0x11071961
-#define CTX_MAGIC_SECURE 0x16917011
-
-/* Convenient macro for registering the default digests. */
-#define REGISTER_DEFAULT_DIGESTS \
- do \
- { \
- ath_mutex_lock (&digests_registered_lock); \
- if (! default_digests_registered) \
- { \
- md_register_default (); \
- default_digests_registered = 1; \
- } \
- ath_mutex_unlock (&digests_registered_lock); \
- } \
- while (0)
-
-
-static const char * digest_algo_to_string( int algo );
-static gcry_err_code_t check_digest_algo (int algo);
-static gcry_err_code_t md_open (gcry_md_hd_t *h, int algo,
- int secure, int hmac);
-static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
-static gcry_err_code_t md_copy (gcry_md_hd_t a, gcry_md_hd_t *b);
-static void md_close (gcry_md_hd_t a);
-static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
-static void md_final(gcry_md_hd_t a);
-static byte *md_read( gcry_md_hd_t a, int algo );
-static int md_get_algo( gcry_md_hd_t a );
-static int md_digest_length( int algo );
-static const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen );
-static void md_start_debug ( gcry_md_hd_t a, const char *suffix );
-static void md_stop_debug ( gcry_md_hd_t a );
-
-
-
-
-/* Internal function. Register all the ciphers included in
- CIPHER_TABLE. Returns zero on success or an error code. */
-static void
-md_register_default (void)
-{
- gcry_err_code_t err = 0;
- int i;
-
- for (i = 0; !err && digest_table[i].digest; i++)
- {
- if ( fips_mode ())
- {
- if (!digest_table[i].fips_allowed)
- continue;
- if (digest_table[i].algorithm == GCRY_MD_MD5
- && _gcry_enforced_fips_mode () )
- continue; /* Do not register in enforced fips mode. */
- }
-
- err = _gcry_module_add (&digests_registered,
- digest_table[i].algorithm,
- (void *) digest_table[i].digest,
- (void *) digest_table[i].extraspec,
- NULL);
- }
-
- if (err)
- BUG ();
-}
-
-/* Internal callback function. */
-static int
-gcry_md_lookup_func_name (void *spec, void *data)
-{
- gcry_md_spec_t *digest = (gcry_md_spec_t *) spec;
- char *name = (char *) data;
-
- return (! stricmp (digest->name, name));
-}
-
-/* Internal callback function. Used via _gcry_module_lookup. */
-static int
-gcry_md_lookup_func_oid (void *spec, void *data)
-{
- gcry_md_spec_t *digest = (gcry_md_spec_t *) spec;
- char *oid = (char *) data;
- gcry_md_oid_spec_t *oid_specs = digest->oids;
- int ret = 0, i;
-
- if (oid_specs)
- {
- for (i = 0; oid_specs[i].oidstring && (! ret); i++)
- if (! stricmp (oid, oid_specs[i].oidstring))
- ret = 1;
- }
-
- return ret;
-}
-
-/* Internal function. Lookup a digest entry by it's name. */
-static gcry_module_t
-gcry_md_lookup_name (const char *name)
-{
- gcry_module_t digest;
-
- digest = _gcry_module_lookup (digests_registered, (void *) name,
- gcry_md_lookup_func_name);
-
- return digest;
-}
-
-/* Internal function. Lookup a cipher entry by it's oid. */
-static gcry_module_t
-gcry_md_lookup_oid (const char *oid)
-{
- gcry_module_t digest;
-
- digest = _gcry_module_lookup (digests_registered, (void *) oid,
- gcry_md_lookup_func_oid);
-
- return digest;
-}
-
-/* Register a new digest module whose specification can be found in
- DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID
- and a pointer representhing this module is stored in MODULE. */
-gcry_error_t
-_gcry_md_register (gcry_md_spec_t *digest,
- md_extra_spec_t *extraspec,
- unsigned int *algorithm_id,
- gcry_module_t *module)
-{
- gcry_err_code_t err = 0;
- gcry_module_t mod;
-
- /* We do not support module loading in fips mode. */
- if (fips_mode ())
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
- ath_mutex_lock (&digests_registered_lock);
- err = _gcry_module_add (&digests_registered, 0,
- (void *) digest,
- (void *)(extraspec? extraspec : &dummy_extra_spec),
- &mod);
- ath_mutex_unlock (&digests_registered_lock);
-
- if (! err)
- {
- *module = mod;
- *algorithm_id = mod->mod_id;
- }
-
- return gcry_error (err);
-}
-
-/* Unregister the digest identified by ID, which must have been
- registered with gcry_digest_register. */
-void
-gcry_md_unregister (gcry_module_t module)
-{
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&digests_registered_lock);
-}
-
-
-static int
-search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec)
-{
- gcry_module_t module;
- int ret = 0;
-
- if (oid && ((! strncmp (oid, "oid.", 4))
- || (! strncmp (oid, "OID.", 4))))
- oid += 4;
-
- module = gcry_md_lookup_oid (oid);
- if (module)
- {
- gcry_md_spec_t *digest = module->spec;
- int i;
-
- for (i = 0; digest->oids[i].oidstring && !ret; i++)
- if (! stricmp (oid, digest->oids[i].oidstring))
- {
- if (algorithm)
- *algorithm = module->mod_id;
- if (oid_spec)
- *oid_spec = digest->oids[i];
- ret = 1;
- }
- _gcry_module_release (module);
- }
-
- return ret;
-}
-
-/****************
- * Map a string to the digest algo
- */
-int
-gcry_md_map_name (const char *string)
-{
- gcry_module_t digest;
- int ret, algorithm = 0;
-
- if (! string)
- return 0;
-
- REGISTER_DEFAULT_DIGESTS;
-
- /* If the string starts with a digit (optionally prefixed with
- either "OID." or "oid."), we first look into our table of ASN.1
- object identifiers to figure out the algorithm */
-
- ath_mutex_lock (&digests_registered_lock);
-
- ret = search_oid (string, &algorithm, NULL);
- if (! ret)
- {
- /* Not found, search a matching digest name. */
- digest = gcry_md_lookup_name (string);
- if (digest)
- {
- algorithm = digest->mod_id;
- _gcry_module_release (digest);
- }
- }
- ath_mutex_unlock (&digests_registered_lock);
-
- return algorithm;
-}
-
-
-/****************
- * Map a digest algo to a string
- */
-static const char *
-digest_algo_to_string (int algorithm)
-{
- const char *name = NULL;
- gcry_module_t digest;
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- digest = _gcry_module_lookup_id (digests_registered, algorithm);
- if (digest)
- {
- name = ((gcry_md_spec_t *) digest->spec)->name;
- _gcry_module_release (digest);
- }
- ath_mutex_unlock (&digests_registered_lock);
-
- return name;
-}
-
-/****************
- * This function simply returns the name of the algorithm or some constant
- * string when there is no algo. It will never return NULL.
- * Use the macro gcry_md_test_algo() to check whether the algorithm
- * is valid.
- */
-const char *
-gcry_md_algo_name (int algorithm)
-{
- const char *s = digest_algo_to_string (algorithm);
- return s ? s : "?";
-}
-
-
-static gcry_err_code_t
-check_digest_algo (int algorithm)
-{
- gcry_err_code_t rc = 0;
- gcry_module_t digest;
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- digest = _gcry_module_lookup_id (digests_registered, algorithm);
- if (digest)
- _gcry_module_release (digest);
- else
- rc = GPG_ERR_DIGEST_ALGO;
- ath_mutex_unlock (&digests_registered_lock);
-
- return rc;
-}
-
-
-
-/****************
- * Open a message digest handle for use with algorithm ALGO.
- * More algorithms may be added by md_enable(). The initial algorithm
- * may be 0.
- */
-static gcry_err_code_t
-md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- int bufsize = secure ? 512 : 1024;
- struct gcry_md_context *ctx;
- gcry_md_hd_t hd;
- size_t n;
-
- /* Allocate a memory area to hold the caller visible buffer with it's
- * control information and the data required by this module. Set the
- * context pointer at the beginning to this area.
- * We have to use this strange scheme because we want to hide the
- * internal data but have a variable sized buffer.
- *
- * +---+------+---........------+-------------+
- * !ctx! bctl ! buffer ! private !
- * +---+------+---........------+-------------+
- * ! ^
- * !---------------------------!
- *
- * We have to make sure that private is well aligned.
- */
- n = sizeof (struct gcry_md_handle) + bufsize;
- n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
- / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
-
- /* Allocate and set the Context pointer to the private data */
- if (secure)
- hd = gcry_malloc_secure (n + sizeof (struct gcry_md_context));
- else
- hd = gcry_malloc (n + sizeof (struct gcry_md_context));
-
- if (! hd)
- err = gpg_err_code_from_errno (errno);
-
- if (! err)
- {
- hd->ctx = ctx = (struct gcry_md_context *) ((char *) hd + n);
- /* Setup the globally visible data (bctl in the diagram).*/
- hd->bufsize = n - sizeof (struct gcry_md_handle) + 1;
- hd->bufpos = 0;
-
- /* Initialize the private data. */
- memset (hd->ctx, 0, sizeof *hd->ctx);
- ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
- ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
- ctx->secure = secure;
-
- if (hmac)
- {
- switch (algo)
- {
- case GCRY_MD_SHA384:
- case GCRY_MD_SHA512:
- ctx->macpads_Bsize = 128;
- break;
- default:
- ctx->macpads_Bsize = 64;
- break;
- }
- ctx->macpads = gcry_malloc_secure (2*(ctx->macpads_Bsize));
- if (!ctx->macpads)
- {
- err = gpg_err_code_from_errno (errno);
- md_close (hd);
- }
- }
- }
-
- if (! err)
- {
- /* Hmmm, should we really do that? - yes [-wk] */
- _gcry_fast_random_poll ();
-
- if (algo)
- {
- err = md_enable (hd, algo);
- if (err)
- md_close (hd);
- }
- }
-
- if (! err)
- *h = hd;
-
- return err;
-}
-
-/* Create a message digest object for algorithm ALGO. FLAGS may be
- given as an bitwise OR of the gcry_md_flags values. ALGO may be
- given as 0 if the algorithms to be used are later set using
- gcry_md_enable. H is guaranteed to be a valid handle or NULL on
- error. */
-gcry_error_t
-gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_md_hd_t hd;
-
- if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)))
- err = GPG_ERR_INV_ARG;
- else
- {
- err = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE),
- (flags & GCRY_MD_FLAG_HMAC));
- }
-
- *h = err? NULL : hd;
- return gcry_error (err);
-}
-
-
-
-static gcry_err_code_t
-md_enable (gcry_md_hd_t hd, int algorithm)
-{
- struct gcry_md_context *h = hd->ctx;
- gcry_md_spec_t *digest = NULL;
- GcryDigestEntry *entry;
- gcry_module_t module;
- gcry_err_code_t err = 0;
-
- for (entry = h->list; entry; entry = entry->next)
- if (entry->module->mod_id == algorithm)
- return err; /* already enabled */
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- module = _gcry_module_lookup_id (digests_registered, algorithm);
- ath_mutex_unlock (&digests_registered_lock);
- if (! module)
- {
- log_debug ("md_enable: algorithm %d not available\n", algorithm);
- err = GPG_ERR_DIGEST_ALGO;
- }
- else
- digest = (gcry_md_spec_t *) module->spec;
-
-
- if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
- {
- _gcry_inactivate_fips_mode ("MD5 used");
- if (_gcry_enforced_fips_mode () )
- {
- /* We should never get to here because we do not register
- MD5 in enforced fips mode. But better throw an error. */
- err = GPG_ERR_DIGEST_ALGO;
- }
- }
-
- if (!err)
- {
- size_t size = (sizeof (*entry)
- + digest->contextsize
- - sizeof (entry->context));
-
- /* And allocate a new list entry. */
- if (h->secure)
- entry = gcry_malloc_secure (size);
- else
- entry = gcry_malloc (size);
-
- if (! entry)
- err = gpg_err_code_from_errno (errno);
- else
- {
- entry->digest = digest;
- entry->module = module;
- entry->next = h->list;
- entry->actual_struct_size = size;
- h->list = entry;
-
- /* And init this instance. */
- entry->digest->init (&entry->context.c);
- }
- }
-
- if (err)
- {
- if (module)
- {
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&digests_registered_lock);
- }
- }
-
- return err;
-}
-
-
-gcry_error_t
-gcry_md_enable (gcry_md_hd_t hd, int algorithm)
-{
- return gcry_error (md_enable (hd, algorithm));
-}
-
-static gcry_err_code_t
-md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- struct gcry_md_context *a = ahd->ctx;
- struct gcry_md_context *b;
- GcryDigestEntry *ar, *br;
- gcry_md_hd_t bhd;
- size_t n;
-
- if (ahd->bufpos)
- md_write (ahd, NULL, 0);
-
- n = (char *) ahd->ctx - (char *) ahd;
- if (a->secure)
- bhd = gcry_malloc_secure (n + sizeof (struct gcry_md_context));
- else
- bhd = gcry_malloc (n + sizeof (struct gcry_md_context));
-
- if (! bhd)
- err = gpg_err_code_from_errno (errno);
-
- if (! err)
- {
- bhd->ctx = b = (struct gcry_md_context *) ((char *) bhd + n);
- /* No need to copy the buffer due to the write above. */
- gcry_assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1));
- bhd->bufsize = ahd->bufsize;
- bhd->bufpos = 0;
- gcry_assert (! ahd->bufpos);
- memcpy (b, a, sizeof *a);
- b->list = NULL;
- b->debug = NULL;
- if (a->macpads)
- {
- b->macpads = gcry_malloc_secure (2*(a->macpads_Bsize));
- if (! b->macpads)
- {
- err = gpg_err_code_from_errno (errno);
- md_close (bhd);
- }
- else
- memcpy (b->macpads, a->macpads, (2*(a->macpads_Bsize)));
- }
- }
-
- /* Copy the complete list of algorithms. The copied list is
- reversed, but that doesn't matter. */
- if (!err)
- {
- for (ar = a->list; ar; ar = ar->next)
- {
- if (a->secure)
- br = gcry_malloc_secure (sizeof *br
- + ar->digest->contextsize
- - sizeof(ar->context));
- else
- br = gcry_malloc (sizeof *br
- + ar->digest->contextsize
- - sizeof (ar->context));
- if (!br)
- {
- err = gpg_err_code_from_errno (errno);
- md_close (bhd);
- break;
- }
-
- memcpy (br, ar, (sizeof (*br) + ar->digest->contextsize
- - sizeof (ar->context)));
- br->next = b->list;
- b->list = br;
-
- /* Add a reference to the module. */
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_use (br->module);
- ath_mutex_unlock (&digests_registered_lock);
- }
- }
-
- if (a->debug && !err)
- md_start_debug (bhd, "unknown");
-
- if (!err)
- *b_hd = bhd;
-
- return err;
-}
-
-gcry_error_t
-gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
-{
- gcry_err_code_t err;
-
- err = md_copy (hd, handle);
- if (err)
- *handle = NULL;
- return gcry_error (err);
-}
-
-/*
- * Reset all contexts and discard any buffered stuff. This may be used
- * instead of a md_close(); md_open().
- */
-void
-gcry_md_reset (gcry_md_hd_t a)
-{
- GcryDigestEntry *r;
-
- /* Note: We allow this even in fips non operational mode. */
-
- a->bufpos = a->ctx->finalized = 0;
-
- for (r = a->ctx->list; r; r = r->next)
- {
- memset (r->context.c, 0, r->digest->contextsize);
- (*r->digest->init) (&r->context.c);
- }
- if (a->ctx->macpads)
- md_write (a, a->ctx->macpads, a->ctx->macpads_Bsize); /* inner pad */
-}
-
-static void
-md_close (gcry_md_hd_t a)
-{
- GcryDigestEntry *r, *r2;
-
- if (! a)
- return;
- if (a->ctx->debug)
- md_stop_debug (a);
- for (r = a->ctx->list; r; r = r2)
- {
- r2 = r->next;
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_release (r->module);
- ath_mutex_unlock (&digests_registered_lock);
- wipememory (r, r->actual_struct_size);
- gcry_free (r);
- }
-
- if (a->ctx->macpads)
- {
- wipememory (a->ctx->macpads, 2*(a->ctx->macpads_Bsize));
- gcry_free(a->ctx->macpads);
- }
-
- wipememory (a, a->ctx->actual_handle_size);
- gcry_free(a);
-}
-
-void
-gcry_md_close (gcry_md_hd_t hd)
-{
- /* Note: We allow this even in fips non operational mode. */
- md_close (hd);
-}
-
-static void
-md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
-{
- GcryDigestEntry *r;
-
- if (a->ctx->debug)
- {
- if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1)
- BUG();
- if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1)
- BUG();
- }
-
- for (r = a->ctx->list; r; r = r->next)
- {
- if (a->bufpos)
- (*r->digest->write) (&r->context.c, a->buf, a->bufpos);
- (*r->digest->write) (&r->context.c, inbuf, inlen);
- }
- a->bufpos = 0;
-}
-
-void
-gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen)
-{
- md_write (hd, inbuf, inlen);
-}
-
-static void
-md_final (gcry_md_hd_t a)
-{
- GcryDigestEntry *r;
-
- if (a->ctx->finalized)
- return;
-
- if (a->bufpos)
- md_write (a, NULL, 0);
-
- for (r = a->ctx->list; r; r = r->next)
- (*r->digest->final) (&r->context.c);
-
- a->ctx->finalized = 1;
-
- if (a->ctx->macpads)
- {
- /* Finish the hmac. */
- int algo = md_get_algo (a);
- byte *p = md_read (a, algo);
- size_t dlen = md_digest_length (algo);
- gcry_md_hd_t om;
- gcry_err_code_t err = md_open (&om, algo, a->ctx->secure, 0);
-
- if (err)
- _gcry_fatal_error (err, NULL);
- md_write (om,
- (a->ctx->macpads)+(a->ctx->macpads_Bsize),
- a->ctx->macpads_Bsize);
- md_write (om, p, dlen);
- md_final (om);
- /* Replace our digest with the mac (they have the same size). */
- memcpy (p, md_read (om, algo), dlen);
- md_close (om);
- }
-}
-
-static gcry_err_code_t
-prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen)
-{
- int i;
- int algo = md_get_algo (hd);
- unsigned char *helpkey = NULL;
- unsigned char *ipad, *opad;
-
- if (!algo)
- return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
-
- if ( keylen > hd->ctx->macpads_Bsize )
- {
- helpkey = gcry_malloc_secure (md_digest_length (algo));
- if (!helpkey)
- return gpg_err_code_from_errno (errno);
- gcry_md_hash_buffer (algo, helpkey, key, keylen);
- key = helpkey;
- keylen = md_digest_length (algo);
- gcry_assert ( keylen <= hd->ctx->macpads_Bsize );
- }
-
- memset ( hd->ctx->macpads, 0, 2*(hd->ctx->macpads_Bsize) );
- ipad = hd->ctx->macpads;
- opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize);
- memcpy ( ipad, key, keylen );
- memcpy ( opad, key, keylen );
- for (i=0; i < hd->ctx->macpads_Bsize; i++ )
- {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
- gcry_free (helpkey);
-
- return GPG_ERR_NO_ERROR;
-}
-
-gcry_error_t
-gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
-{
- gcry_err_code_t rc = 0;
-
- switch (cmd)
- {
- case GCRYCTL_FINALIZE:
- md_final (hd);
- break;
- case GCRYCTL_SET_KEY:
- rc = gcry_err_code (gcry_md_setkey (hd, buffer, buflen));
- break;
- case GCRYCTL_START_DUMP:
- md_start_debug (hd, buffer);
- break;
- case GCRYCTL_STOP_DUMP:
- md_stop_debug ( hd );
- break;
- default:
- rc = GPG_ERR_INV_OP;
- }
- return gcry_error (rc);
-}
-
-gcry_error_t
-gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
-{
- gcry_err_code_t rc = GPG_ERR_NO_ERROR;
-
- if (!hd->ctx->macpads)
- rc = GPG_ERR_CONFLICT;
- else
- {
- rc = prepare_macpads (hd, key, keylen);
- if (! rc)
- gcry_md_reset (hd);
- }
-
- return gcry_error (rc);
-}
-
-/* The new debug interface. If SUFFIX is a string it creates an debug
- file for the context HD. IF suffix is NULL, the file is closed and
- debugging is stopped. */
-void
-gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
-{
- if (suffix)
- md_start_debug (hd, suffix);
- else
- md_stop_debug (hd);
-}
-
-
-
-/****************
- * if ALGO is null get the digest for the used algo (which should be only one)
- */
-static byte *
-md_read( gcry_md_hd_t a, int algo )
-{
- GcryDigestEntry *r = a->ctx->list;
-
- if (! algo)
- {
- /* Return the first algorithm. */
- if (r)
- {
- if (r->next)
- log_debug ("more than one algorithm in md_read(0)\n");
- return r->digest->read( &r->context.c );
- }
- }
- else
- {
- for (r = a->ctx->list; r; r = r->next)
- if (r->module->mod_id == algo)
- return r->digest->read (&r->context.c);
- }
- BUG();
- return NULL;
-}
-
-/*
- * Read out the complete digest, this function implictly finalizes
- * the hash.
- */
-byte *
-gcry_md_read (gcry_md_hd_t hd, int algo)
-{
- /* This function is expected to always return a digest, thus we
- can't return an error which we actually should do in
- non-operational state. */
- gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
- return md_read (hd, algo);
-}
-
-
-/*
- * Read out an intermediate digest. Not yet functional.
- */
-gcry_err_code_t
-gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
-{
- (void)hd;
- (void)algo;
- (void)buffer;
- (void)buflen;
-
- /*md_digest ... */
- fips_signal_error ("unimplemented function called");
- return GPG_ERR_INTERNAL;
-}
-
-
-/*
- * Shortcut function to hash a buffer with a given algo. The only
- * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The
- * supplied digest buffer must be large enough to store the resulting
- * hash. No error is returned, the function will abort on an invalid
- * algo. DISABLED_ALGOS are ignored here. */
-void
-gcry_md_hash_buffer (int algo, void *digest,
- const void *buffer, size_t length)
-{
- if (algo == GCRY_MD_SHA1)
- _gcry_sha1_hash_buffer (digest, buffer, length);
- else if (algo == GCRY_MD_RMD160 && !fips_mode () )
- _gcry_rmd160_hash_buffer (digest, buffer, length);
- else
- {
- /* For the others we do not have a fast function, so we use the
- normal functions. */
- gcry_md_hd_t h;
- gpg_err_code_t err;
-
- if (algo == GCRY_MD_MD5 && fips_mode ())
- {
- _gcry_inactivate_fips_mode ("MD5 used");
- if (_gcry_enforced_fips_mode () )
- {
- /* We should never get to here because we do not register
- MD5 in enforced fips mode. */
- _gcry_fips_noreturn ();
- }
- }
-
- err = md_open (&h, algo, 0, 0);
- if (err)
- log_bug ("gcry_md_open failed for algo %d: %s",
- algo, gpg_strerror (gcry_error(err)));
- md_write (h, (byte *) buffer, length);
- md_final (h);
- memcpy (digest, md_read (h, algo), md_digest_length (algo));
- md_close (h);
- }
-}
-
-static int
-md_get_algo (gcry_md_hd_t a)
-{
- GcryDigestEntry *r = a->ctx->list;
-
- if (r && r->next)
- {
- fips_signal_error ("possible usage error");
- log_error ("WARNING: more than one algorithm in md_get_algo()\n");
- }
- return r ? r->module->mod_id : 0;
-}
-
-int
-gcry_md_get_algo (gcry_md_hd_t hd)
-{
- return md_get_algo (hd);
-}
-
-
-/****************
- * Return the length of the digest
- */
-static int
-md_digest_length (int algorithm)
-{
- gcry_module_t digest;
- int mdlen = 0;
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- digest = _gcry_module_lookup_id (digests_registered, algorithm);
- if (digest)
- {
- mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen;
- _gcry_module_release (digest);
- }
- ath_mutex_unlock (&digests_registered_lock);
-
- return mdlen;
-}
-
-/****************
- * Return the length of the digest in bytes.
- * This function will return 0 in case of errors.
- */
-unsigned int
-gcry_md_get_algo_dlen (int algorithm)
-{
- return md_digest_length (algorithm);
-}
-
-
-/* Hmmm: add a mode to enumerate the OIDs
- * to make g10/sig-check.c more portable */
-static const byte *
-md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
-{
- const byte *asnoid = NULL;
- gcry_module_t digest;
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- digest = _gcry_module_lookup_id (digests_registered, algorithm);
- if (digest)
- {
- if (asnlen)
- *asnlen = ((gcry_md_spec_t *) digest->spec)->asnlen;
- if (mdlen)
- *mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen;
- asnoid = ((gcry_md_spec_t *) digest->spec)->asnoid;
- _gcry_module_release (digest);
- }
- else
- log_bug ("no ASN.1 OID for md algo %d\n", algorithm);
- ath_mutex_unlock (&digests_registered_lock);
-
- return asnoid;
-}
-
-
-
-/****************
- * Return information about the given cipher algorithm
- * WHAT select the kind of information returned:
- * GCRYCTL_TEST_ALGO:
- * Returns 0 when the specified algorithm is available for use.
- * buffer and nbytes must be zero.
- * GCRYCTL_GET_ASNOID:
- * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
- * the required length is returned.
- *
- * Note: Because this function is in most cases used to return an
- * integer value, we can make it easier for the caller to just look at
- * the return value. The caller will in all cases consult the value
- * and thereby detecting whether a error occured or not (i.e. while checking
- * the block size)
- */
-gcry_error_t
-gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- switch (what)
- {
- case GCRYCTL_TEST_ALGO:
- if (buffer || nbytes)
- err = GPG_ERR_INV_ARG;
- else
- err = check_digest_algo (algo);
- break;
-
- case GCRYCTL_GET_ASNOID:
- /* We need to check that the algo is available because
- md_asn_oid would otherwise raise an assertion. */
- err = check_digest_algo (algo);
- if (!err)
- {
- const char unsigned *asn;
- size_t asnlen;
-
- asn = md_asn_oid (algo, &asnlen, NULL);
- if (buffer && (*nbytes >= asnlen))
- {
- memcpy (buffer, asn, asnlen);
- *nbytes = asnlen;
- }
- else if (!buffer && nbytes)
- *nbytes = asnlen;
- else
- {
- if (buffer)
- err = GPG_ERR_TOO_SHORT;
- else
- err = GPG_ERR_INV_ARG;
- }
- }
- break;
-
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-
-static void
-md_start_debug ( gcry_md_hd_t md, const char *suffix )
-{
- static int idx=0;
- char buf[50];
-
- if (fips_mode ())
- return;
-
- if ( md->ctx->debug )
- {
- log_debug("Oops: md debug already started\n");
- return;
- }
- idx++;
- snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix );
- md->ctx->debug = fopen(buf, "w");
- if ( !md->ctx->debug )
- log_debug("md debug: can't open %s\n", buf );
-}
-
-static void
-md_stop_debug( gcry_md_hd_t md )
-{
- if ( md->ctx->debug )
- {
- if ( md->bufpos )
- md_write ( md, NULL, 0 );
- fclose (md->ctx->debug);
- md->ctx->debug = NULL;
- }
-
-#ifdef HAVE_U64_TYPEDEF
- { /* a kludge to pull in the __muldi3 for Solaris */
- volatile u32 a = (u32)(ulong)md;
- volatile u64 b = 42;
- volatile u64 c;
- c = a * b;
- }
-#endif
-}
-
-
-
-/*
- * Return information about the digest handle.
- * GCRYCTL_IS_SECURE:
- * Returns 1 when the handle works on secured memory
- * otherwise 0 is returned. There is no error return.
- * GCRYCTL_IS_ALGO_ENABLED:
- * Returns 1 if the algo is enabled for that handle.
- * The algo must be passed as the address of an int.
- */
-gcry_error_t
-gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- switch (cmd)
- {
- case GCRYCTL_IS_SECURE:
- *nbytes = h->ctx->secure;
- break;
-
- case GCRYCTL_IS_ALGO_ENABLED:
- {
- GcryDigestEntry *r;
- int algo;
-
- if ( !buffer || (nbytes && (*nbytes != sizeof (int))))
- err = GPG_ERR_INV_ARG;
- else
- {
- algo = *(int*)buffer;
-
- *nbytes = 0;
- for(r=h->ctx->list; r; r = r->next ) {
- if (r->module->mod_id == algo)
- {
- *nbytes = 1;
- break;
- }
- }
- }
- break;
- }
-
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-
-/* Explicitly initialize this module. */
-gcry_err_code_t
-_gcry_md_init (void)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- REGISTER_DEFAULT_DIGESTS;
-
- return err;
-}
-
-
-int
-gcry_md_is_secure (gcry_md_hd_t a)
-{
- size_t value;
-
- if (gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value))
- value = 1; /* It seems to be better to assume secure memory on
- error. */
- return value;
-}
-
-
-int
-gcry_md_is_enabled (gcry_md_hd_t a, int algo)
-{
- size_t value;
-
- value = sizeof algo;
- if (gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value))
- value = 0;
- return value;
-}
-
-/* Get a list consisting of the IDs of the loaded message digest
- modules. If LIST is zero, write the number of loaded message
- digest modules to LIST_LENGTH and return. If LIST is non-zero, the
- first *LIST_LENGTH algorithm IDs are stored in LIST, which must be
- of according size. In case there are less message digest modules
- than *LIST_LENGTH, *LIST_LENGTH is updated to the correct
- number. */
-gcry_error_t
-gcry_md_list (int *list, int *list_length)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- ath_mutex_lock (&digests_registered_lock);
- err = _gcry_module_list (digests_registered, list, list_length);
- ath_mutex_unlock (&digests_registered_lock);
-
- return err;
-}
-
-
-/* Run the selftests for digest algorithm ALGO with optional reporting
- function REPORT. */
-gpg_error_t
-_gcry_md_selftest (int algo, int extended, selftest_report_func_t report)
-{
- gcry_module_t module = NULL;
- cipher_extra_spec_t *extraspec = NULL;
- gcry_err_code_t ec = 0;
-
- REGISTER_DEFAULT_DIGESTS;
-
- ath_mutex_lock (&digests_registered_lock);
- module = _gcry_module_lookup_id (digests_registered, algo);
- if (module && !(module->flags & FLAG_MODULE_DISABLED))
- extraspec = module->extraspec;
- ath_mutex_unlock (&digests_registered_lock);
- if (extraspec && extraspec->selftest)
- ec = extraspec->selftest (algo, extended, report);
- else
- {
- ec = GPG_ERR_DIGEST_ALGO;
- if (report)
- report ("digest", algo, "module",
- module && !(module->flags & FLAG_MODULE_DISABLED)?
- "no selftest available" :
- module? "algorithm disabled" : "algorithm not found");
- }
-
- if (module)
- {
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&digests_registered_lock);
- }
- return gpg_error (ec);
-}
+/* md.c - message digest dispatcher
+ * Copyright (C) 1998, 1999, 2002, 2003, 2006,
+ * 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "ath.h"
+
+#include "rmd.h"
+
+/* A dummy extraspec so that we do not need to tests the extraspec
+ field from the module specification against NULL and instead
+ directly test the respective fields of extraspecs. */
+static md_extra_spec_t dummy_extra_spec;
+
+
+/* This is the list of the digest implementations included in
+ libgcrypt. */
+static struct digest_table_entry
+{
+ gcry_md_spec_t *digest;
+ md_extra_spec_t *extraspec;
+ unsigned int algorithm;
+ int fips_allowed;
+} digest_table[] =
+ {
+#if USE_CRC
+ /* We allow the CRC algorithms even in FIPS mode because they are
+ actually no cryptographic primitives. */
+ { &_gcry_digest_spec_crc32,
+ &dummy_extra_spec, GCRY_MD_CRC32, 1 },
+ { &_gcry_digest_spec_crc32_rfc1510,
+ &dummy_extra_spec, GCRY_MD_CRC32_RFC1510, 1 },
+ { &_gcry_digest_spec_crc24_rfc2440,
+ &dummy_extra_spec, GCRY_MD_CRC24_RFC2440, 1 },
+#endif
+#if USE_MD4
+ { &_gcry_digest_spec_md4,
+ &dummy_extra_spec, GCRY_MD_MD4 },
+#endif
+#if USE_MD5
+ { &_gcry_digest_spec_md5,
+ &dummy_extra_spec, GCRY_MD_MD5, 1 },
+#endif
+#if USE_RMD160
+ { &_gcry_digest_spec_rmd160,
+ &dummy_extra_spec, GCRY_MD_RMD160 },
+#endif
+#if USE_SHA1
+ { &_gcry_digest_spec_sha1,
+ &_gcry_digest_extraspec_sha1, GCRY_MD_SHA1, 1 },
+#endif
+#if USE_SHA256
+ { &_gcry_digest_spec_sha256,
+ &_gcry_digest_extraspec_sha256, GCRY_MD_SHA256, 1 },
+ { &_gcry_digest_spec_sha224,
+ &_gcry_digest_extraspec_sha224, GCRY_MD_SHA224, 1 },
+#endif
+#if USE_SHA512
+ { &_gcry_digest_spec_sha512,
+ &_gcry_digest_extraspec_sha512, GCRY_MD_SHA512, 1 },
+ { &_gcry_digest_spec_sha384,
+ &_gcry_digest_extraspec_sha384, GCRY_MD_SHA384, 1 },
+#endif
+#if USE_TIGER
+ { &_gcry_digest_spec_tiger,
+ &dummy_extra_spec, GCRY_MD_TIGER },
+ { &_gcry_digest_spec_tiger1,
+ &dummy_extra_spec, GCRY_MD_TIGER1 },
+ { &_gcry_digest_spec_tiger2,
+ &dummy_extra_spec, GCRY_MD_TIGER2 },
+#endif
+#if USE_WHIRLPOOL
+ { &_gcry_digest_spec_whirlpool,
+ &dummy_extra_spec, GCRY_MD_WHIRLPOOL },
+#endif
+ { NULL },
+ };
+
+/* List of registered digests. */
+static gcry_module_t digests_registered;
+
+/* This is the lock protecting DIGESTS_REGISTERED. */
+static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER;
+
+/* Flag to check whether the default ciphers have already been
+ registered. */
+static int default_digests_registered;
+
+typedef struct gcry_md_list
+{
+ gcry_md_spec_t *digest;
+ gcry_module_t module;
+ struct gcry_md_list *next;
+ size_t actual_struct_size; /* Allocated size of this structure. */
+ PROPERLY_ALIGNED_TYPE context;
+} GcryDigestEntry;
+
+/* this structure is put right after the gcry_md_hd_t buffer, so that
+ * only one memory block is needed. */
+struct gcry_md_context
+{
+ int magic;
+ size_t actual_handle_size; /* Allocated size of this handle. */
+ int secure;
+ FILE *debug;
+ int finalized;
+ GcryDigestEntry *list;
+ byte *macpads;
+ int macpads_Bsize; /* Blocksize as used for the HMAC pads. */
+};
+
+
+#define CTX_MAGIC_NORMAL 0x11071961
+#define CTX_MAGIC_SECURE 0x16917011
+
+/* Convenient macro for registering the default digests. */
+#define REGISTER_DEFAULT_DIGESTS \
+ do \
+ { \
+ ath_mutex_lock (&digests_registered_lock); \
+ if (! default_digests_registered) \
+ { \
+ md_register_default (); \
+ default_digests_registered = 1; \
+ } \
+ ath_mutex_unlock (&digests_registered_lock); \
+ } \
+ while (0)
+
+
+static const char * digest_algo_to_string( int algo );
+static gcry_err_code_t check_digest_algo (int algo);
+static gcry_err_code_t md_open (gcry_md_hd_t *h, int algo,
+ int secure, int hmac);
+static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
+static gcry_err_code_t md_copy (gcry_md_hd_t a, gcry_md_hd_t *b);
+static void md_close (gcry_md_hd_t a);
+static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
+static void md_final(gcry_md_hd_t a);
+static byte *md_read( gcry_md_hd_t a, int algo );
+static int md_get_algo( gcry_md_hd_t a );
+static int md_digest_length( int algo );
+static const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen );
+static void md_start_debug ( gcry_md_hd_t a, const char *suffix );
+static void md_stop_debug ( gcry_md_hd_t a );
+
+
+
+
+/* Internal function. Register all the ciphers included in
+ CIPHER_TABLE. Returns zero on success or an error code. */
+static void
+md_register_default (void)
+{
+ gcry_err_code_t err = 0;
+ int i;
+
+ for (i = 0; !err && digest_table[i].digest; i++)
+ {
+ if ( fips_mode ())
+ {
+ if (!digest_table[i].fips_allowed)
+ continue;
+ if (digest_table[i].algorithm == GCRY_MD_MD5
+ && _gcry_enforced_fips_mode () )
+ continue; /* Do not register in enforced fips mode. */
+ }
+
+ err = _gcry_module_add (&digests_registered,
+ digest_table[i].algorithm,
+ (void *) digest_table[i].digest,
+ (void *) digest_table[i].extraspec,
+ NULL);
+ }
+
+ if (err)
+ BUG ();
+}
+
+/* Internal callback function. */
+static int
+gcry_md_lookup_func_name (void *spec, void *data)
+{
+ gcry_md_spec_t *digest = (gcry_md_spec_t *) spec;
+ char *name = (char *) data;
+
+ return (! _stricmp (digest->name, name));
+}
+
+/* Internal callback function. Used via _gcry_module_lookup. */
+static int
+gcry_md_lookup_func_oid (void *spec, void *data)
+{
+ gcry_md_spec_t *digest = (gcry_md_spec_t *) spec;
+ char *oid = (char *) data;
+ gcry_md_oid_spec_t *oid_specs = digest->oids;
+ int ret = 0, i;
+
+ if (oid_specs)
+ {
+ for (i = 0; oid_specs[i].oidstring && (! ret); i++)
+ if (! _stricmp (oid, oid_specs[i].oidstring))
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* Internal function. Lookup a digest entry by it's name. */
+static gcry_module_t
+gcry_md_lookup_name (const char *name)
+{
+ gcry_module_t digest;
+
+ digest = _gcry_module_lookup (digests_registered, (void *) name,
+ gcry_md_lookup_func_name);
+
+ return digest;
+}
+
+/* Internal function. Lookup a cipher entry by it's oid. */
+static gcry_module_t
+gcry_md_lookup_oid (const char *oid)
+{
+ gcry_module_t digest;
+
+ digest = _gcry_module_lookup (digests_registered, (void *) oid,
+ gcry_md_lookup_func_oid);
+
+ return digest;
+}
+
+/* Register a new digest module whose specification can be found in
+ DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID
+ and a pointer representhing this module is stored in MODULE. */
+gcry_error_t
+_gcry_md_register (gcry_md_spec_t *digest,
+ md_extra_spec_t *extraspec,
+ unsigned int *algorithm_id,
+ gcry_module_t *module)
+{
+ gcry_err_code_t err = 0;
+ gcry_module_t mod;
+
+ /* We do not support module loading in fips mode. */
+ if (fips_mode ())
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ ath_mutex_lock (&digests_registered_lock);
+ err = _gcry_module_add (&digests_registered, 0,
+ (void *) digest,
+ (void *)(extraspec? extraspec : &dummy_extra_spec),
+ &mod);
+ ath_mutex_unlock (&digests_registered_lock);
+
+ if (! err)
+ {
+ *module = mod;
+ *algorithm_id = mod->mod_id;
+ }
+
+ return gcry_error (err);
+}
+
+/* Unregister the digest identified by ID, which must have been
+ registered with gcry_digest_register. */
+void
+gcry_md_unregister (gcry_module_t module)
+{
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&digests_registered_lock);
+}
+
+
+static int
+search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec)
+{
+ gcry_module_t module;
+ int ret = 0;
+
+ if (oid && ((! strncmp (oid, "oid.", 4))
+ || (! strncmp (oid, "OID.", 4))))
+ oid += 4;
+
+ module = gcry_md_lookup_oid (oid);
+ if (module)
+ {
+ gcry_md_spec_t *digest = module->spec;
+ int i;
+
+ for (i = 0; digest->oids[i].oidstring && !ret; i++)
+ if (! _stricmp (oid, digest->oids[i].oidstring))
+ {
+ if (algorithm)
+ *algorithm = module->mod_id;
+ if (oid_spec)
+ *oid_spec = digest->oids[i];
+ ret = 1;
+ }
+ _gcry_module_release (module);
+ }
+
+ return ret;
+}
+
+/****************
+ * Map a string to the digest algo
+ */
+int
+gcry_md_map_name (const char *string)
+{
+ gcry_module_t digest;
+ int ret, algorithm = 0;
+
+ if (! string)
+ return 0;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ /* If the string starts with a digit (optionally prefixed with
+ either "OID." or "oid."), we first look into our table of ASN.1
+ object identifiers to figure out the algorithm */
+
+ ath_mutex_lock (&digests_registered_lock);
+
+ ret = search_oid (string, &algorithm, NULL);
+ if (! ret)
+ {
+ /* Not found, search a matching digest name. */
+ digest = gcry_md_lookup_name (string);
+ if (digest)
+ {
+ algorithm = digest->mod_id;
+ _gcry_module_release (digest);
+ }
+ }
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return algorithm;
+}
+
+
+/****************
+ * Map a digest algo to a string
+ */
+static const char *
+digest_algo_to_string (int algorithm)
+{
+ const char *name = NULL;
+ gcry_module_t digest;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ digest = _gcry_module_lookup_id (digests_registered, algorithm);
+ if (digest)
+ {
+ name = ((gcry_md_spec_t *) digest->spec)->name;
+ _gcry_module_release (digest);
+ }
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return name;
+}
+
+/****************
+ * This function simply returns the name of the algorithm or some constant
+ * string when there is no algo. It will never return NULL.
+ * Use the macro gcry_md_test_algo() to check whether the algorithm
+ * is valid.
+ */
+const char *
+gcry_md_algo_name (int algorithm)
+{
+ const char *s = digest_algo_to_string (algorithm);
+ return s ? s : "?";
+}
+
+
+static gcry_err_code_t
+check_digest_algo (int algorithm)
+{
+ gcry_err_code_t rc = 0;
+ gcry_module_t digest;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ digest = _gcry_module_lookup_id (digests_registered, algorithm);
+ if (digest)
+ _gcry_module_release (digest);
+ else
+ rc = GPG_ERR_DIGEST_ALGO;
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return rc;
+}
+
+
+
+/****************
+ * Open a message digest handle for use with algorithm ALGO.
+ * More algorithms may be added by md_enable(). The initial algorithm
+ * may be 0.
+ */
+static gcry_err_code_t
+md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ int bufsize = secure ? 512 : 1024;
+ struct gcry_md_context *ctx;
+ gcry_md_hd_t hd;
+ size_t n;
+
+ /* Allocate a memory area to hold the caller visible buffer with it's
+ * control information and the data required by this module. Set the
+ * context pointer at the beginning to this area.
+ * We have to use this strange scheme because we want to hide the
+ * internal data but have a variable sized buffer.
+ *
+ * +---+------+---........------+-------------+
+ * !ctx! bctl ! buffer ! private !
+ * +---+------+---........------+-------------+
+ * ! ^
+ * !---------------------------!
+ *
+ * We have to make sure that private is well aligned.
+ */
+ n = sizeof (struct gcry_md_handle) + bufsize;
+ n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
+ / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
+
+ /* Allocate and set the Context pointer to the private data */
+ if (secure)
+ hd = gcry_malloc_secure (n + sizeof (struct gcry_md_context));
+ else
+ hd = gcry_malloc (n + sizeof (struct gcry_md_context));
+
+ if (! hd)
+ err = gpg_err_code_from_errno (errno);
+
+ if (! err)
+ {
+ hd->ctx = ctx = (struct gcry_md_context *) ((char *) hd + n);
+ /* Setup the globally visible data (bctl in the diagram).*/
+ hd->bufsize = n - sizeof (struct gcry_md_handle) + 1;
+ hd->bufpos = 0;
+
+ /* Initialize the private data. */
+ memset (hd->ctx, 0, sizeof *hd->ctx);
+ ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+ ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
+ ctx->secure = secure;
+
+ if (hmac)
+ {
+ switch (algo)
+ {
+ case GCRY_MD_SHA384:
+ case GCRY_MD_SHA512:
+ ctx->macpads_Bsize = 128;
+ break;
+ default:
+ ctx->macpads_Bsize = 64;
+ break;
+ }
+ ctx->macpads = gcry_malloc_secure (2*(ctx->macpads_Bsize));
+ if (!ctx->macpads)
+ {
+ err = gpg_err_code_from_errno (errno);
+ md_close (hd);
+ }
+ }
+ }
+
+ if (! err)
+ {
+ /* Hmmm, should we really do that? - yes [-wk] */
+ _gcry_fast_random_poll ();
+
+ if (algo)
+ {
+ err = md_enable (hd, algo);
+ if (err)
+ md_close (hd);
+ }
+ }
+
+ if (! err)
+ *h = hd;
+
+ return err;
+}
+
+/* Create a message digest object for algorithm ALGO. FLAGS may be
+ given as an bitwise OR of the gcry_md_flags values. ALGO may be
+ given as 0 if the algorithms to be used are later set using
+ gcry_md_enable. H is guaranteed to be a valid handle or NULL on
+ error. */
+gcry_error_t
+gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_md_hd_t hd;
+
+ if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)))
+ err = GPG_ERR_INV_ARG;
+ else
+ {
+ err = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE),
+ (flags & GCRY_MD_FLAG_HMAC));
+ }
+
+ *h = err? NULL : hd;
+ return gcry_error (err);
+}
+
+
+
+static gcry_err_code_t
+md_enable (gcry_md_hd_t hd, int algorithm)
+{
+ struct gcry_md_context *h = hd->ctx;
+ gcry_md_spec_t *digest = NULL;
+ GcryDigestEntry *entry;
+ gcry_module_t module;
+ gcry_err_code_t err = 0;
+
+ for (entry = h->list; entry; entry = entry->next)
+ if (entry->module->mod_id == algorithm)
+ return err; /* already enabled */
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ module = _gcry_module_lookup_id (digests_registered, algorithm);
+ ath_mutex_unlock (&digests_registered_lock);
+ if (! module)
+ {
+ log_debug ("md_enable: algorithm %d not available\n", algorithm);
+ err = GPG_ERR_DIGEST_ALGO;
+ }
+ else
+ digest = (gcry_md_spec_t *) module->spec;
+
+
+ if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
+ {
+ _gcry_inactivate_fips_mode ("MD5 used");
+ if (_gcry_enforced_fips_mode () )
+ {
+ /* We should never get to here because we do not register
+ MD5 in enforced fips mode. But better throw an error. */
+ err = GPG_ERR_DIGEST_ALGO;
+ }
+ }
+
+ if (!err)
+ {
+ size_t size = (sizeof (*entry)
+ + digest->contextsize
+ - sizeof (entry->context));
+
+ /* And allocate a new list entry. */
+ if (h->secure)
+ entry = gcry_malloc_secure (size);
+ else
+ entry = gcry_malloc (size);
+
+ if (! entry)
+ err = gpg_err_code_from_errno (errno);
+ else
+ {
+ entry->digest = digest;
+ entry->module = module;
+ entry->next = h->list;
+ entry->actual_struct_size = size;
+ h->list = entry;
+
+ /* And init this instance. */
+ entry->digest->init (&entry->context.c);
+ }
+ }
+
+ if (err)
+ {
+ if (module)
+ {
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&digests_registered_lock);
+ }
+ }
+
+ return err;
+}
+
+
+gcry_error_t
+gcry_md_enable (gcry_md_hd_t hd, int algorithm)
+{
+ return gcry_error (md_enable (hd, algorithm));
+}
+
+static gcry_err_code_t
+md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ struct gcry_md_context *a = ahd->ctx;
+ struct gcry_md_context *b;
+ GcryDigestEntry *ar, *br;
+ gcry_md_hd_t bhd;
+ size_t n;
+
+ if (ahd->bufpos)
+ md_write (ahd, NULL, 0);
+
+ n = (char *) ahd->ctx - (char *) ahd;
+ if (a->secure)
+ bhd = gcry_malloc_secure (n + sizeof (struct gcry_md_context));
+ else
+ bhd = gcry_malloc (n + sizeof (struct gcry_md_context));
+
+ if (! bhd)
+ err = gpg_err_code_from_errno (errno);
+
+ if (! err)
+ {
+ bhd->ctx = b = (struct gcry_md_context *) ((char *) bhd + n);
+ /* No need to copy the buffer due to the write above. */
+ gcry_assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1));
+ bhd->bufsize = ahd->bufsize;
+ bhd->bufpos = 0;
+ gcry_assert (! ahd->bufpos);
+ memcpy (b, a, sizeof *a);
+ b->list = NULL;
+ b->debug = NULL;
+ if (a->macpads)
+ {
+ b->macpads = gcry_malloc_secure (2*(a->macpads_Bsize));
+ if (! b->macpads)
+ {
+ err = gpg_err_code_from_errno (errno);
+ md_close (bhd);
+ }
+ else
+ memcpy (b->macpads, a->macpads, (2*(a->macpads_Bsize)));
+ }
+ }
+
+ /* Copy the complete list of algorithms. The copied list is
+ reversed, but that doesn't matter. */
+ if (!err)
+ {
+ for (ar = a->list; ar; ar = ar->next)
+ {
+ if (a->secure)
+ br = gcry_malloc_secure (sizeof *br
+ + ar->digest->contextsize
+ - sizeof(ar->context));
+ else
+ br = gcry_malloc (sizeof *br
+ + ar->digest->contextsize
+ - sizeof (ar->context));
+ if (!br)
+ {
+ err = gpg_err_code_from_errno (errno);
+ md_close (bhd);
+ break;
+ }
+
+ memcpy (br, ar, (sizeof (*br) + ar->digest->contextsize
+ - sizeof (ar->context)));
+ br->next = b->list;
+ b->list = br;
+
+ /* Add a reference to the module. */
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_use (br->module);
+ ath_mutex_unlock (&digests_registered_lock);
+ }
+ }
+
+ if (a->debug && !err)
+ md_start_debug (bhd, "unknown");
+
+ if (!err)
+ *b_hd = bhd;
+
+ return err;
+}
+
+gcry_error_t
+gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
+{
+ gcry_err_code_t err;
+
+ err = md_copy (hd, handle);
+ if (err)
+ *handle = NULL;
+ return gcry_error (err);
+}
+
+/*
+ * Reset all contexts and discard any buffered stuff. This may be used
+ * instead of a md_close(); md_open().
+ */
+void
+gcry_md_reset (gcry_md_hd_t a)
+{
+ GcryDigestEntry *r;
+
+ /* Note: We allow this even in fips non operational mode. */
+
+ a->bufpos = a->ctx->finalized = 0;
+
+ for (r = a->ctx->list; r; r = r->next)
+ {
+ memset (r->context.c, 0, r->digest->contextsize);
+ (*r->digest->init) (&r->context.c);
+ }
+ if (a->ctx->macpads)
+ md_write (a, a->ctx->macpads, a->ctx->macpads_Bsize); /* inner pad */
+}
+
+static void
+md_close (gcry_md_hd_t a)
+{
+ GcryDigestEntry *r, *r2;
+
+ if (! a)
+ return;
+ if (a->ctx->debug)
+ md_stop_debug (a);
+ for (r = a->ctx->list; r; r = r2)
+ {
+ r2 = r->next;
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_release (r->module);
+ ath_mutex_unlock (&digests_registered_lock);
+ wipememory (r, r->actual_struct_size);
+ gcry_free (r);
+ }
+
+ if (a->ctx->macpads)
+ {
+ wipememory (a->ctx->macpads, 2*(a->ctx->macpads_Bsize));
+ gcry_free(a->ctx->macpads);
+ }
+
+ wipememory (a, a->ctx->actual_handle_size);
+ gcry_free(a);
+}
+
+void
+gcry_md_close (gcry_md_hd_t hd)
+{
+ /* Note: We allow this even in fips non operational mode. */
+ md_close (hd);
+}
+
+static void
+md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
+{
+ GcryDigestEntry *r;
+
+ if (a->ctx->debug)
+ {
+ if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1)
+ BUG();
+ if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1)
+ BUG();
+ }
+
+ for (r = a->ctx->list; r; r = r->next)
+ {
+ if (a->bufpos)
+ (*r->digest->write) (&r->context.c, a->buf, a->bufpos);
+ (*r->digest->write) (&r->context.c, inbuf, inlen);
+ }
+ a->bufpos = 0;
+}
+
+void
+gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen)
+{
+ md_write (hd, inbuf, inlen);
+}
+
+static void
+md_final (gcry_md_hd_t a)
+{
+ GcryDigestEntry *r;
+
+ if (a->ctx->finalized)
+ return;
+
+ if (a->bufpos)
+ md_write (a, NULL, 0);
+
+ for (r = a->ctx->list; r; r = r->next)
+ (*r->digest->final) (&r->context.c);
+
+ a->ctx->finalized = 1;
+
+ if (a->ctx->macpads)
+ {
+ /* Finish the hmac. */
+ int algo = md_get_algo (a);
+ byte *p = md_read (a, algo);
+ size_t dlen = md_digest_length (algo);
+ gcry_md_hd_t om;
+ gcry_err_code_t err = md_open (&om, algo, a->ctx->secure, 0);
+
+ if (err)
+ _gcry_fatal_error (err, NULL);
+ md_write (om,
+ (a->ctx->macpads)+(a->ctx->macpads_Bsize),
+ a->ctx->macpads_Bsize);
+ md_write (om, p, dlen);
+ md_final (om);
+ /* Replace our digest with the mac (they have the same size). */
+ memcpy (p, md_read (om, algo), dlen);
+ md_close (om);
+ }
+}
+
+static gcry_err_code_t
+prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen)
+{
+ int i;
+ int algo = md_get_algo (hd);
+ unsigned char *helpkey = NULL;
+ unsigned char *ipad, *opad;
+
+ if (!algo)
+ return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
+
+ if ( keylen > hd->ctx->macpads_Bsize )
+ {
+ helpkey = gcry_malloc_secure (md_digest_length (algo));
+ if (!helpkey)
+ return gpg_err_code_from_errno (errno);
+ gcry_md_hash_buffer (algo, helpkey, key, keylen);
+ key = helpkey;
+ keylen = md_digest_length (algo);
+ gcry_assert ( keylen <= hd->ctx->macpads_Bsize );
+ }
+
+ memset ( hd->ctx->macpads, 0, 2*(hd->ctx->macpads_Bsize) );
+ ipad = hd->ctx->macpads;
+ opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize);
+ memcpy ( ipad, key, keylen );
+ memcpy ( opad, key, keylen );
+ for (i=0; i < hd->ctx->macpads_Bsize; i++ )
+ {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+ gcry_free (helpkey);
+
+ return GPG_ERR_NO_ERROR;
+}
+
+gcry_error_t
+gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
+{
+ gcry_err_code_t rc = 0;
+
+ switch (cmd)
+ {
+ case GCRYCTL_FINALIZE:
+ md_final (hd);
+ break;
+ case GCRYCTL_SET_KEY:
+ rc = gcry_err_code (gcry_md_setkey (hd, buffer, buflen));
+ break;
+ case GCRYCTL_START_DUMP:
+ md_start_debug (hd, buffer);
+ break;
+ case GCRYCTL_STOP_DUMP:
+ md_stop_debug ( hd );
+ break;
+ default:
+ rc = GPG_ERR_INV_OP;
+ }
+ return gcry_error (rc);
+}
+
+gcry_error_t
+gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
+{
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
+
+ if (!hd->ctx->macpads)
+ rc = GPG_ERR_CONFLICT;
+ else
+ {
+ rc = prepare_macpads (hd, key, keylen);
+ if (! rc)
+ gcry_md_reset (hd);
+ }
+
+ return gcry_error (rc);
+}
+
+/* The new debug interface. If SUFFIX is a string it creates an debug
+ file for the context HD. IF suffix is NULL, the file is closed and
+ debugging is stopped. */
+void
+gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
+{
+ if (suffix)
+ md_start_debug (hd, suffix);
+ else
+ md_stop_debug (hd);
+}
+
+
+
+/****************
+ * if ALGO is null get the digest for the used algo (which should be only one)
+ */
+static byte *
+md_read( gcry_md_hd_t a, int algo )
+{
+ GcryDigestEntry *r = a->ctx->list;
+
+ if (! algo)
+ {
+ /* Return the first algorithm */
+ if (r)
+ {
+ if (r->next)
+ log_debug ("more than one algorithm in md_read(0)\n");
+ return r->digest->read (&r->context.c);
+ }
+ }
+ else
+ {
+ for (r = a->ctx->list; r; r = r->next)
+ if (r->module->mod_id == algo)
+ return r->digest->read (&r->context.c);
+ }
+ BUG();
+ return NULL;
+}
+
+/*
+ * Read out the complete digest, this function implictly finalizes
+ * the hash.
+ */
+byte *
+gcry_md_read (gcry_md_hd_t hd, int algo)
+{
+ /* This function is expected to always return a digest, thus we
+ can't return an error which we actually should do in
+ non-operational state. */
+ gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
+ return md_read (hd, algo);
+}
+
+
+/*
+ * Read out an intermediate digest. Not yet functional.
+ */
+gcry_err_code_t
+gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
+{
+ (void)hd;
+ (void)algo;
+ (void)buffer;
+ (void)buflen;
+
+ /*md_digest ... */
+ fips_signal_error ("unimplemented function called");
+ return GPG_ERR_INTERNAL;
+}
+
+
+/*
+ * Shortcut function to hash a buffer with a given algo. The only
+ * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The
+ * supplied digest buffer must be large enough to store the resulting
+ * hash. No error is returned, the function will abort on an invalid
+ * algo. DISABLED_ALGOS are ignored here. */
+void
+gcry_md_hash_buffer (int algo, void *digest,
+ const void *buffer, size_t length)
+{
+ if (algo == GCRY_MD_SHA1)
+ _gcry_sha1_hash_buffer (digest, buffer, length);
+ else if (algo == GCRY_MD_RMD160 && !fips_mode () )
+ _gcry_rmd160_hash_buffer (digest, buffer, length);
+ else
+ {
+ /* For the others we do not have a fast function, so we use the
+ normal functions. */
+ gcry_md_hd_t h;
+ gpg_err_code_t err;
+
+ if (algo == GCRY_MD_MD5 && fips_mode ())
+ {
+ _gcry_inactivate_fips_mode ("MD5 used");
+ if (_gcry_enforced_fips_mode () )
+ {
+ /* We should never get to here because we do not register
+ MD5 in enforced fips mode. */
+ _gcry_fips_noreturn ();
+ }
+ }
+
+ err = md_open (&h, algo, 0, 0);
+ if (err)
+ log_bug ("gcry_md_open failed for algo %d: %s",
+ algo, gpg_strerror (gcry_error(err)));
+ md_write (h, (byte *) buffer, length);
+ md_final (h);
+ memcpy (digest, md_read (h, algo), md_digest_length (algo));
+ md_close (h);
+ }
+}
+
+static int
+md_get_algo (gcry_md_hd_t a)
+{
+ GcryDigestEntry *r = a->ctx->list;
+
+ if (r && r->next)
+ {
+ fips_signal_error ("possible usage error");
+ log_error ("WARNING: more than one algorithm in md_get_algo()\n");
+ }
+ return r ? r->module->mod_id : 0;
+}
+
+int
+gcry_md_get_algo (gcry_md_hd_t hd)
+{
+ return md_get_algo (hd);
+}
+
+
+/****************
+ * Return the length of the digest
+ */
+static int
+md_digest_length (int algorithm)
+{
+ gcry_module_t digest;
+ int mdlen = 0;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ digest = _gcry_module_lookup_id (digests_registered, algorithm);
+ if (digest)
+ {
+ mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen;
+ _gcry_module_release (digest);
+ }
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return mdlen;
+}
+
+/****************
+ * Return the length of the digest in bytes.
+ * This function will return 0 in case of errors.
+ */
+unsigned int
+gcry_md_get_algo_dlen (int algorithm)
+{
+ return md_digest_length (algorithm);
+}
+
+
+/* Hmmm: add a mode to enumerate the OIDs
+ * to make g10/sig-check.c more portable */
+static const byte *
+md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
+{
+ const byte *asnoid = NULL;
+ gcry_module_t digest;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ digest = _gcry_module_lookup_id (digests_registered, algorithm);
+ if (digest)
+ {
+ if (asnlen)
+ *asnlen = ((gcry_md_spec_t *) digest->spec)->asnlen;
+ if (mdlen)
+ *mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen;
+ asnoid = ((gcry_md_spec_t *) digest->spec)->asnoid;
+ _gcry_module_release (digest);
+ }
+ else
+ log_bug ("no ASN.1 OID for md algo %d\n", algorithm);
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return asnoid;
+}
+
+
+
+/****************
+ * Return information about the given cipher algorithm
+ * WHAT select the kind of information returned:
+ * GCRYCTL_TEST_ALGO:
+ * Returns 0 when the specified algorithm is available for use.
+ * buffer and nbytes must be zero.
+ * GCRYCTL_GET_ASNOID:
+ * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
+ * the required length is returned.
+ *
+ * Note: Because this function is in most cases used to return an
+ * integer value, we can make it easier for the caller to just look at
+ * the return value. The caller will in all cases consult the value
+ * and thereby detecting whether a error occurred or not (i.e. while checking
+ * the block size)
+ */
+gcry_error_t
+gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ switch (what)
+ {
+ case GCRYCTL_TEST_ALGO:
+ if (buffer || nbytes)
+ err = GPG_ERR_INV_ARG;
+ else
+ err = check_digest_algo (algo);
+ break;
+
+ case GCRYCTL_GET_ASNOID:
+ /* We need to check that the algo is available because
+ md_asn_oid would otherwise raise an assertion. */
+ err = check_digest_algo (algo);
+ if (!err)
+ {
+ const char unsigned *asn;
+ size_t asnlen;
+
+ asn = md_asn_oid (algo, &asnlen, NULL);
+ if (buffer && (*nbytes >= asnlen))
+ {
+ memcpy (buffer, asn, asnlen);
+ *nbytes = asnlen;
+ }
+ else if (!buffer && nbytes)
+ *nbytes = asnlen;
+ else
+ {
+ if (buffer)
+ err = GPG_ERR_TOO_SHORT;
+ else
+ err = GPG_ERR_INV_ARG;
+ }
+ }
+ break;
+
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+
+static void
+md_start_debug ( gcry_md_hd_t md, const char *suffix )
+{
+ static int idx=0;
+ char buf[50];
+
+ if (fips_mode ())
+ return;
+
+ if ( md->ctx->debug )
+ {
+ log_debug("Oops: md debug already started\n");
+ return;
+ }
+ idx++;
+ snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix );
+ md->ctx->debug = fopen(buf, "w");
+ if ( !md->ctx->debug )
+ log_debug("md debug: can't open %s\n", buf );
+}
+
+static void
+md_stop_debug( gcry_md_hd_t md )
+{
+ if ( md->ctx->debug )
+ {
+ if ( md->bufpos )
+ md_write ( md, NULL, 0 );
+ fclose (md->ctx->debug);
+ md->ctx->debug = NULL;
+ }
+
+#ifdef HAVE_U64_TYPEDEF
+ { /* a kludge to pull in the __muldi3 for Solaris */
+ volatile u32 a = (u32)(ulong)md;
+ volatile u64 b = 42;
+ volatile u64 c;
+ c = a * b;
+ }
+#endif
+}
+
+
+
+/*
+ * Return information about the digest handle.
+ * GCRYCTL_IS_SECURE:
+ * Returns 1 when the handle works on secured memory
+ * otherwise 0 is returned. There is no error return.
+ * GCRYCTL_IS_ALGO_ENABLED:
+ * Returns 1 if the algo is enabled for that handle.
+ * The algo must be passed as the address of an int.
+ */
+gcry_error_t
+gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ switch (cmd)
+ {
+ case GCRYCTL_IS_SECURE:
+ *nbytes = h->ctx->secure;
+ break;
+
+ case GCRYCTL_IS_ALGO_ENABLED:
+ {
+ GcryDigestEntry *r;
+ int algo;
+
+ if ( !buffer || (nbytes && (*nbytes != sizeof (int))))
+ err = GPG_ERR_INV_ARG;
+ else
+ {
+ algo = *(int*)buffer;
+
+ *nbytes = 0;
+ for(r=h->ctx->list; r; r = r->next ) {
+ if (r->module->mod_id == algo)
+ {
+ *nbytes = 1;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+
+/* Explicitly initialize this module. */
+gcry_err_code_t
+_gcry_md_init (void)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ return err;
+}
+
+
+int
+gcry_md_is_secure (gcry_md_hd_t a)
+{
+ size_t value;
+
+ if (gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value))
+ value = 1; /* It seems to be better to assume secure memory on
+ error. */
+ return value;
+}
+
+
+int
+gcry_md_is_enabled (gcry_md_hd_t a, int algo)
+{
+ size_t value;
+
+ value = sizeof algo;
+ if (gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value))
+ value = 0;
+ return value;
+}
+
+/* Get a list consisting of the IDs of the loaded message digest
+ modules. If LIST is zero, write the number of loaded message
+ digest modules to LIST_LENGTH and return. If LIST is non-zero, the
+ first *LIST_LENGTH algorithm IDs are stored in LIST, which must be
+ of according size. In case there are less message digest modules
+ than *LIST_LENGTH, *LIST_LENGTH is updated to the correct
+ number. */
+gcry_error_t
+gcry_md_list (int *list, int *list_length)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ ath_mutex_lock (&digests_registered_lock);
+ err = _gcry_module_list (digests_registered, list, list_length);
+ ath_mutex_unlock (&digests_registered_lock);
+
+ return err;
+}
+
+
+/* Run the selftests for digest algorithm ALGO with optional reporting
+ function REPORT. */
+gpg_error_t
+_gcry_md_selftest (int algo, int extended, selftest_report_func_t report)
+{
+ gcry_module_t module = NULL;
+ cipher_extra_spec_t *extraspec = NULL;
+ gcry_err_code_t ec = 0;
+
+ REGISTER_DEFAULT_DIGESTS;
+
+ ath_mutex_lock (&digests_registered_lock);
+ module = _gcry_module_lookup_id (digests_registered, algo);
+ if (module && !(module->flags & FLAG_MODULE_DISABLED))
+ extraspec = module->extraspec;
+ ath_mutex_unlock (&digests_registered_lock);
+ if (extraspec && extraspec->selftest)
+ ec = extraspec->selftest (algo, extended, report);
+ else
+ {
+ ec = GPG_ERR_DIGEST_ALGO;
+ if (report)
+ report ("digest", algo, "module",
+ module && !(module->flags & FLAG_MODULE_DISABLED)?
+ "no selftest available" :
+ module? "algorithm disabled" : "algorithm not found");
+ }
+
+ if (module)
+ {
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&digests_registered_lock);
+ }
+ return gpg_error (ec);
+}
diff --git a/libgcrypt-1.4.6/cipher/primegen.c b/libgcrypt-1.4.6/cipher/primegen.c
index b869bee..50dc560 100644
--- a/libgcrypt-1.4.6/cipher/primegen.c
+++ b/libgcrypt-1.4.6/cipher/primegen.c
@@ -1,1862 +1,1862 @@
-/* primegen.c - prime number generator
- * Copyright (C) 1998, 2000, 2001, 2002, 2003
- * 2004, 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "g10lib.h"
-#include "mpi.h"
-#include "cipher.h"
-#include "ath.h"
-
-static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel,
- int (*extra_check)(void *, gcry_mpi_t),
- void *extra_check_arg);
-static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds,
- gcry_prime_check_func_t cb_func, void *cb_arg );
-static int is_prime (gcry_mpi_t n, int steps, unsigned int *count);
-static void m_out_of_n( char *array, int m, int n );
-
-static void (*progress_cb) (void *,const char*,int,int, int );
-static void *progress_cb_data;
-
-/* Note: 2 is not included because it can be tested more easily by
- looking at bit 0. The last entry in this list is marked by a zero */
-static ushort small_prime_numbers[] = {
- 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
- 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
- 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
- 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
- 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
- 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
- 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
- 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
- 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
- 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
- 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
- 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
- 709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
- 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
- 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
- 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
- 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
- 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
- 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
- 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
- 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277,
- 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307,
- 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
- 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
- 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
- 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
- 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
- 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
- 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
- 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,
- 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
- 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
- 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
- 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
- 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111,
- 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161,
- 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243,
- 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
- 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
- 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411,
- 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
- 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
- 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633,
- 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
- 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729,
- 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
- 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
- 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917,
- 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
- 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,
- 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137,
- 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
- 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
- 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
- 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391,
- 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
- 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533,
- 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583,
- 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
- 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
- 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779,
- 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
- 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917,
- 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
- 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
- 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111,
- 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
- 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243,
- 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
- 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391,
- 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
- 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519,
- 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
- 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
- 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799,
- 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
- 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951,
- 4957, 4967, 4969, 4973, 4987, 4993, 4999,
- 0
-};
-static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1;
-
-
-
-/* An object and a list to build up a global pool of primes. See
- save_pool_prime and get_pool_prime. */
-struct primepool_s
-{
- struct primepool_s *next;
- gcry_mpi_t prime; /* If this is NULL the entry is not used. */
- unsigned int nbits;
- gcry_random_level_t randomlevel;
-};
-struct primepool_s *primepool;
-/* Mutex used to protect access to the primepool. */
-static ath_mutex_t primepool_lock = ATH_MUTEX_INITIALIZER;
-
-
-
-/* Save PRIME which has been generated at RANDOMLEVEL for later
- use. Needs to be called while primepool_lock is being hold. Note
- that PRIME should be considered released after calling this
- function. */
-static void
-save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel)
-{
- struct primepool_s *item, *item2;
- size_t n;
-
- for (n=0, item = primepool; item; item = item->next, n++)
- if (!item->prime)
- break;
- if (!item && n > 100)
- {
- /* Remove some of the entries. Our strategy is removing
- the last third from the list. */
- int i;
-
- for (i=0, item2 = primepool; item2; item2 = item2->next)
- {
- if (i >= n/3*2)
- {
- gcry_mpi_release (item2->prime);
- item2->prime = NULL;
- if (!item)
- item = item2;
- }
- }
- }
- if (!item)
- {
- item = gcry_calloc (1, sizeof *item);
- if (!item)
- {
- /* Out of memory. Silently giving up. */
- gcry_mpi_release (prime);
- return;
- }
- item->next = primepool;
- primepool = item;
- }
- item->prime = prime;
- item->nbits = mpi_get_nbits (prime);
- item->randomlevel = randomlevel;
-}
-
-
-/* Return a prime for the prime pool or NULL if none has been found.
- The prime needs to match NBITS and randomlevel. This function needs
- to be called why the primepool_look is being hold. */
-static gcry_mpi_t
-get_pool_prime (unsigned int nbits, gcry_random_level_t randomlevel)
-{
- struct primepool_s *item;
-
- for (item = primepool; item; item = item->next)
- if (item->prime
- && item->nbits == nbits && item->randomlevel == randomlevel)
- {
- gcry_mpi_t prime = item->prime;
- item->prime = NULL;
- gcry_assert (nbits == mpi_get_nbits (prime));
- return prime;
- }
- return NULL;
-}
-
-
-
-
-
-
-void
-_gcry_register_primegen_progress ( void (*cb)(void *,const char*,int,int,int),
- void *cb_data )
-{
- progress_cb = cb;
- progress_cb_data = cb_data;
-}
-
-
-static void
-progress( int c )
-{
- if ( progress_cb )
- progress_cb ( progress_cb_data, "primegen", c, 0, 0 );
-}
-
-
-/****************
- * Generate a prime number (stored in secure memory)
- */
-gcry_mpi_t
-_gcry_generate_secret_prime (unsigned int nbits,
- gcry_random_level_t random_level,
- int (*extra_check)(void*, gcry_mpi_t),
- void *extra_check_arg)
-{
- gcry_mpi_t prime;
-
- prime = gen_prime (nbits, 1, random_level, extra_check, extra_check_arg);
- progress('\n');
- return prime;
-}
-
-
-/* Generate a prime number which may be public, i.e. not allocated in
- secure memory. */
-gcry_mpi_t
-_gcry_generate_public_prime (unsigned int nbits,
- gcry_random_level_t random_level,
- int (*extra_check)(void*, gcry_mpi_t),
- void *extra_check_arg)
-{
- gcry_mpi_t prime;
-
- prime = gen_prime (nbits, 0, random_level, extra_check, extra_check_arg);
- progress('\n');
- return prime;
-}
-
-
-/* Core prime generation function. The algorithm used to generate
- practically save primes is due to Lim and Lee as described in the
- CRYPTO '97 proceedings (ISBN3540633847) page 260.
-
- NEED_Q_FACTOR: If true make sure that at least one factor is of
- size qbits. This is for example required for DSA.
- PRIME_GENERATED: Adresss of a variable where the resulting prime
- number will be stored.
- PBITS: Requested size of the prime number. At least 48.
- QBITS: One factor of the prime needs to be of this size. Maybe 0
- if this is not required. See also MODE.
- G: If not NULL an MPI which will receive a generator for the prime
- for use with Elgamal.
- RET_FACTORS: if not NULL, an array with all factors are stored at
- that address.
- ALL_FACTORS: If set to true all factors of prime-1 are returned.
- RANDOMLEVEL: How strong should the random numers be.
- FLAGS: Prime generation bit flags. Currently supported:
- GCRY_PRIME_FLAG_SECRET - The prime needs to be kept secret.
- CB_FUNC, CB_ARG: Callback to be used for extra checks.
-
- */
-static gcry_err_code_t
-prime_generate_internal (int need_q_factor,
- gcry_mpi_t *prime_generated, unsigned int pbits,
- unsigned int qbits, gcry_mpi_t g,
- gcry_mpi_t **ret_factors,
- gcry_random_level_t randomlevel, unsigned int flags,
- int all_factors,
- gcry_prime_check_func_t cb_func, void *cb_arg)
-{
- gcry_err_code_t err = 0;
- gcry_mpi_t *factors_new = NULL; /* Factors to return to the
- caller. */
- gcry_mpi_t *factors = NULL; /* Current factors. */
- gcry_random_level_t poolrandomlevel; /* Random level used for pool primes. */
- gcry_mpi_t *pool = NULL; /* Pool of primes. */
- int *pool_in_use = NULL; /* Array with currently used POOL elements. */
- unsigned char *perms = NULL; /* Permutations of POOL. */
- gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */
- unsigned int fbits = 0; /* Length of prime factors. */
- unsigned int n = 0; /* Number of factors. */
- unsigned int m = 0; /* Number of primes in pool. */
- gcry_mpi_t q = NULL; /* First prime factor. */
- gcry_mpi_t prime = NULL; /* Prime candidate. */
- unsigned int nprime = 0; /* Bits of PRIME. */
- unsigned int req_qbits; /* The original QBITS value. */
- gcry_mpi_t val_2; /* For check_prime(). */
- int is_locked = 0; /* Flag to help unlocking the primepool. */
- unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET);
- unsigned int count1 = 0, count2 = 0;
- unsigned int i = 0, j = 0;
-
- if (pbits < 48)
- return GPG_ERR_INV_ARG;
-
- /* We won't use a too strong random elvel for the pooled subprimes. */
- poolrandomlevel = (randomlevel > GCRY_STRONG_RANDOM?
- GCRY_STRONG_RANDOM : randomlevel);
-
-
- /* If QBITS is not given, assume a reasonable value. */
- if (!qbits)
- qbits = pbits / 3;
-
- req_qbits = qbits;
-
- /* Find number of needed prime factors N. */
- for (n = 1; (pbits - qbits - 1) / n >= qbits; n++)
- ;
- n--;
-
- val_2 = mpi_alloc_set_ui (2);
-
- if ((! n) || ((need_q_factor) && (n < 2)))
- {
- err = GPG_ERR_INV_ARG;
- goto leave;
- }
-
- if (need_q_factor)
- {
- n--; /* Need one factor less because we want a specific Q-FACTOR. */
- fbits = (pbits - 2 * req_qbits -1) / n;
- qbits = pbits - req_qbits - n * fbits;
- }
- else
- {
- fbits = (pbits - req_qbits -1) / n;
- qbits = pbits - n * fbits;
- }
-
- if (DBG_CIPHER)
- log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
- pbits, req_qbits, qbits, fbits, n);
-
- /* Allocate an integer to old the new prime. */
- prime = gcry_mpi_new (pbits);
-
- /* Generate first prime factor. */
- q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
-
- /* Generate a specific Q-Factor if requested. */
- if (need_q_factor)
- q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL);
-
- /* Allocate an array to hold all factors + 2 for later usage. */
- factors = gcry_calloc (n + 2, sizeof (*factors));
- if (!factors)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- /* Allocate an array to track pool usage. */
- pool_in_use = gcry_malloc (n * sizeof *pool_in_use);
- if (!pool_in_use)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
- for (i=0; i < n; i++)
- pool_in_use[i] = -1;
-
- /* Make a pool of 3n+5 primes (this is an arbitrary value). We
- require at least 30 primes for are useful selection process.
-
- Fixme: We need to research the best formula for sizing the pool.
- */
- m = n * 3 + 5;
- if (need_q_factor) /* Need some more in this case. */
- m += 5;
- if (m < 30)
- m = 30;
- pool = gcry_calloc (m , sizeof (*pool));
- if (! pool)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- /* Permutate over the pool of primes until we find a prime of the
- requested length. */
- do
- {
- next_try:
- for (i=0; i < n; i++)
- pool_in_use[i] = -1;
-
- if (!perms)
- {
- /* Allocate new primes. This is done right at the beginning
- of the loop and if we have later run out of primes. */
- for (i = 0; i < m; i++)
- {
- mpi_free (pool[i]);
- pool[i] = NULL;
- }
-
- /* Init m_out_of_n(). */
- perms = gcry_calloc (1, m);
- if (!perms)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- if (ath_mutex_lock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 1;
- for (i = 0; i < n; i++)
- {
- perms[i] = 1;
- /* At a maximum we use strong random for the factors.
- This saves us a lot of entropy. Given that Q and
- possible Q-factor are also used in the final prime
- this should be acceptable. We also don't allocate in
- secure memory to save on that scare resource too. If
- Q has been allocated in secure memory, the final
- prime will be saved there anyway. This is because
- our MPI routines take care of that. GnuPG has worked
- this way ever since. */
- pool[i] = NULL;
- if (is_locked)
- {
- pool[i] = get_pool_prime (fbits, poolrandomlevel);
- if (!pool[i])
- {
- if (ath_mutex_unlock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 0;
- }
- }
- if (!pool[i])
- pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL);
- pool_in_use[i] = i;
- factors[i] = pool[i];
- }
- if (is_locked && ath_mutex_unlock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 0;
- }
- else
- {
- /* Get next permutation. */
- m_out_of_n ( (char*)perms, n, m);
- if (ath_mutex_lock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 1;
- for (i = j = 0; (i < m) && (j < n); i++)
- if (perms[i])
- {
- /* If the subprime has not yet beed generated do it now. */
- if (!pool[i] && is_locked)
- {
- pool[i] = get_pool_prime (fbits, poolrandomlevel);
- if (!pool[i])
- {
- if (ath_mutex_unlock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 0;
- }
- }
- if (!pool[i])
- pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL);
- pool_in_use[j] = i;
- factors[j++] = pool[i];
- }
- if (is_locked && ath_mutex_unlock (&primepool_lock))
- {
- err = GPG_ERR_INTERNAL;
- goto leave;
- }
- is_locked = 0;
- if (i == n)
- {
- /* Ran out of permutations: Allocate new primes. */
- gcry_free (perms);
- perms = NULL;
- progress ('!');
- goto next_try;
- }
- }
-
- /* Generate next prime candidate:
- p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1.
- */
- mpi_set (prime, q);
- mpi_mul_ui (prime, prime, 2);
- if (need_q_factor)
- mpi_mul (prime, prime, q_factor);
- for(i = 0; i < n; i++)
- mpi_mul (prime, prime, factors[i]);
- mpi_add_ui (prime, prime, 1);
- nprime = mpi_get_nbits (prime);
-
- if (nprime < pbits)
- {
- if (++count1 > 20)
- {
- count1 = 0;
- qbits++;
- progress('>');
- mpi_free (q);
- q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
- goto next_try;
- }
- }
- else
- count1 = 0;
-
- if (nprime > pbits)
- {
- if (++count2 > 20)
- {
- count2 = 0;
- qbits--;
- progress('<');
- mpi_free (q);
- q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
- goto next_try;
- }
- }
- else
- count2 = 0;
- }
- while (! ((nprime == pbits) && check_prime (prime, val_2, 5,
- cb_func, cb_arg)));
-
- if (DBG_CIPHER)
- {
- progress ('\n');
- log_mpidump ("prime : ", prime);
- log_mpidump ("factor q: ", q);
- if (need_q_factor)
- log_mpidump ("factor q0: ", q_factor);
- for (i = 0; i < n; i++)
- log_mpidump ("factor pi: ", factors[i]);
- log_debug ("bit sizes: prime=%u, q=%u",
- mpi_get_nbits (prime), mpi_get_nbits (q));
- if (need_q_factor)
- log_debug (", q0=%u", mpi_get_nbits (q_factor));
- for (i = 0; i < n; i++)
- log_debug (", p%d=%u", i, mpi_get_nbits (factors[i]));
- progress('\n');
- }
-
- if (ret_factors)
- {
- /* Caller wants the factors. */
- factors_new = gcry_calloc (n + 4, sizeof (*factors_new));
- if (! factors_new)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- if (all_factors)
- {
- i = 0;
- factors_new[i++] = gcry_mpi_set_ui (NULL, 2);
- factors_new[i++] = mpi_copy (q);
- if (need_q_factor)
- factors_new[i++] = mpi_copy (q_factor);
- for(j=0; j < n; j++)
- factors_new[i++] = mpi_copy (factors[j]);
- }
- else
- {
- i = 0;
- if (need_q_factor)
- {
- factors_new[i++] = mpi_copy (q_factor);
- for (; i <= n; i++)
- factors_new[i] = mpi_copy (factors[i]);
- }
- else
- for (; i < n; i++ )
- factors_new[i] = mpi_copy (factors[i]);
- }
- }
-
- if (g)
- {
- /* Create a generator (start with 3). */
- gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime));
- gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime));
- gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime));
-
- if (need_q_factor)
- err = GPG_ERR_NOT_IMPLEMENTED;
- else
- {
- factors[n] = q;
- factors[n + 1] = mpi_alloc_set_ui (2);
- mpi_sub_ui (pmin1, prime, 1);
- mpi_set_ui (g, 2);
- do
- {
- mpi_add_ui (g, g, 1);
- if (DBG_CIPHER)
- {
- log_debug ("checking g:");
- gcry_mpi_dump (g);
- log_printf ("\n");
- }
- else
- progress('^');
- for (i = 0; i < n + 2; i++)
- {
- mpi_fdiv_q (tmp, pmin1, factors[i]);
- /* No mpi_pow(), but it is okay to use this with mod
- prime. */
- gcry_mpi_powm (b, g, tmp, prime);
- if (! mpi_cmp_ui (b, 1))
- break;
- }
- if (DBG_CIPHER)
- progress('\n');
- }
- while (i < n + 2);
-
- mpi_free (factors[n+1]);
- mpi_free (tmp);
- mpi_free (b);
- mpi_free (pmin1);
- }
- }
-
- if (! DBG_CIPHER)
- progress ('\n');
-
-
- leave:
- if (pool)
- {
- is_locked = !ath_mutex_lock (&primepool_lock);
- for(i = 0; i < m; i++)
- {
- if (pool[i])
- {
- for (j=0; j < n; j++)
- if (pool_in_use[j] == i)
- break;
- if (j == n && is_locked)
- {
- /* This pooled subprime has not been used. */
- save_pool_prime (pool[i], poolrandomlevel);
- }
- else
- mpi_free (pool[i]);
- }
- }
- if (is_locked && ath_mutex_unlock (&primepool_lock))
- err = GPG_ERR_INTERNAL;
- is_locked = 0;
- gcry_free (pool);
- }
- gcry_free (pool_in_use);
- if (factors)
- gcry_free (factors); /* Factors are shallow copies. */
- if (perms)
- gcry_free (perms);
-
- mpi_free (val_2);
- mpi_free (q);
- mpi_free (q_factor);
-
- if (! err)
- {
- *prime_generated = prime;
- if (ret_factors)
- *ret_factors = factors_new;
- }
- else
- {
- if (factors_new)
- {
- for (i = 0; factors_new[i]; i++)
- mpi_free (factors_new[i]);
- gcry_free (factors_new);
- }
- mpi_free (prime);
- }
-
- return err;
-}
-
-
-/* Generate a prime used for discrete logarithm algorithms; i.e. this
- prime will be public and no strong random is required. */
-gcry_mpi_t
-_gcry_generate_elg_prime (int mode, unsigned pbits, unsigned qbits,
- gcry_mpi_t g, gcry_mpi_t **ret_factors)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_mpi_t prime = NULL;
-
- err = prime_generate_internal ((mode == 1), &prime, pbits, qbits, g,
- ret_factors, GCRY_WEAK_RANDOM, 0, 0,
- NULL, NULL);
-
- return prime;
-}
-
-
-static gcry_mpi_t
-gen_prime (unsigned int nbits, int secret, int randomlevel,
- int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg)
-{
- gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result;
- int i;
- unsigned int x, step;
- unsigned int count1, count2;
- int *mods;
-
-/* if ( DBG_CIPHER ) */
-/* log_debug ("generate a prime of %u bits ", nbits ); */
-
- if (nbits < 16)
- log_fatal ("can't generate a prime with less than %d bits\n", 16);
-
- mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods );
- /* Make nbits fit into gcry_mpi_t implementation. */
- val_2 = mpi_alloc_set_ui( 2 );
- val_3 = mpi_alloc_set_ui( 3);
- prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits );
- result = mpi_alloc_like( prime );
- pminus1= mpi_alloc_like( prime );
- ptest = mpi_alloc_like( prime );
- count1 = count2 = 0;
- for (;;)
- { /* try forvever */
- int dotcount=0;
-
- /* generate a random number */
- gcry_mpi_randomize( prime, nbits, randomlevel );
-
- /* Set high order bit to 1, set low order bit to 1. If we are
- generating a secret prime we are most probably doing that
- for RSA, to make sure that the modulus does have the
- requested key size we set the 2 high order bits. */
- mpi_set_highbit (prime, nbits-1);
- if (secret)
- mpi_set_bit (prime, nbits-2);
- mpi_set_bit(prime, 0);
-
- /* Calculate all remainders. */
- for (i=0; (x = small_prime_numbers[i]); i++ )
- mods[i] = mpi_fdiv_r_ui(NULL, prime, x);
-
- /* Now try some primes starting with prime. */
- for(step=0; step < 20000; step += 2 )
- {
- /* Check against all the small primes we have in mods. */
- count1++;
- for (i=0; (x = small_prime_numbers[i]); i++ )
- {
- while ( mods[i] + step >= x )
- mods[i] -= x;
- if ( !(mods[i] + step) )
- break;
- }
- if ( x )
- continue; /* Found a multiple of an already known prime. */
-
- mpi_add_ui( ptest, prime, step );
-
- /* Do a fast Fermat test now. */
- count2++;
- mpi_sub_ui( pminus1, ptest, 1);
- gcry_mpi_powm( result, val_2, pminus1, ptest );
- if ( !mpi_cmp_ui( result, 1 ) )
- {
- /* Not composite, perform stronger tests */
- if (is_prime(ptest, 5, &count2 ))
- {
- if (!mpi_test_bit( ptest, nbits-1-secret ))
- {
- progress('\n');
- log_debug ("overflow in prime generation\n");
- break; /* Stop loop, continue with a new prime. */
- }
-
- if (extra_check && extra_check (extra_check_arg, ptest))
- {
- /* The extra check told us that this prime is
- not of the caller's taste. */
- progress ('/');
- }
- else
- {
- /* Got it. */
- mpi_free(val_2);
- mpi_free(val_3);
- mpi_free(result);
- mpi_free(pminus1);
- mpi_free(prime);
- gcry_free(mods);
- return ptest;
- }
- }
- }
- if (++dotcount == 10 )
- {
- progress('.');
- dotcount = 0;
- }
- }
- progress(':'); /* restart with a new random value */
- }
-}
-
-/****************
- * Returns: true if this may be a prime
- * RM_ROUNDS gives the number of Rabin-Miller tests to run.
- */
-static int
-check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds,
- gcry_prime_check_func_t cb_func, void *cb_arg)
-{
- int i;
- unsigned int x;
- unsigned int count=0;
-
- /* Check against small primes. */
- for (i=0; (x = small_prime_numbers[i]); i++ )
- {
- if ( mpi_divisible_ui( prime, x ) )
- return 0;
- }
-
- /* A quick Fermat test. */
- {
- gcry_mpi_t result = mpi_alloc_like( prime );
- gcry_mpi_t pminus1 = mpi_alloc_like( prime );
- mpi_sub_ui( pminus1, prime, 1);
- gcry_mpi_powm( result, val_2, pminus1, prime );
- mpi_free( pminus1 );
- if ( mpi_cmp_ui( result, 1 ) )
- {
- /* Is composite. */
- mpi_free( result );
- progress('.');
- return 0;
- }
- mpi_free( result );
- }
-
- if (!cb_func || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_MAYBE_PRIME, prime))
- {
- /* Perform stronger tests. */
- if ( is_prime( prime, rm_rounds, &count ) )
- {
- if (!cb_func
- || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_GOT_PRIME, prime))
- return 1; /* Probably a prime. */
- }
- }
- progress('.');
- return 0;
-}
-
-
-/*
- * Return true if n is probably a prime
- */
-static int
-is_prime (gcry_mpi_t n, int steps, unsigned int *count)
-{
- gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs( n ) );
- gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs( n ) );
- gcry_mpi_t z = mpi_alloc( mpi_get_nlimbs( n ) );
- gcry_mpi_t nminus1 = mpi_alloc( mpi_get_nlimbs( n ) );
- gcry_mpi_t a2 = mpi_alloc_set_ui( 2 );
- gcry_mpi_t q;
- unsigned i, j, k;
- int rc = 0;
- unsigned nbits = mpi_get_nbits( n );
-
- if (steps < 5) /* Make sure that we do at least 5 rounds. */
- steps = 5;
-
- mpi_sub_ui( nminus1, n, 1 );
-
- /* Find q and k, so that n = 1 + 2^k * q . */
- q = mpi_copy ( nminus1 );
- k = mpi_trailing_zeros ( q );
- mpi_tdiv_q_2exp (q, q, k);
-
- for (i=0 ; i < steps; i++ )
- {
- ++*count;
- if( !i )
- {
- mpi_set_ui( x, 2 );
- }
- else
- {
- gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM );
-
- /* Make sure that the number is smaller than the prime and
- keep the randomness of the high bit. */
- if ( mpi_test_bit ( x, nbits-2) )
- {
- mpi_set_highbit ( x, nbits-2); /* Clear all higher bits. */
- }
- else
- {
- mpi_set_highbit( x, nbits-2 );
- mpi_clear_bit( x, nbits-2 );
- }
- gcry_assert (mpi_cmp (x, nminus1) < 0 && mpi_cmp_ui (x, 1) > 0);
- }
- gcry_mpi_powm ( y, x, q, n);
- if ( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) )
- {
- for ( j=1; j < k && mpi_cmp( y, nminus1 ); j++ )
- {
- gcry_mpi_powm(y, y, a2, n);
- if( !mpi_cmp_ui( y, 1 ) )
- goto leave; /* Not a prime. */
- }
- if (mpi_cmp( y, nminus1 ) )
- goto leave; /* Not a prime. */
- }
- progress('+');
- }
- rc = 1; /* May be a prime. */
-
- leave:
- mpi_free( x );
- mpi_free( y );
- mpi_free( z );
- mpi_free( nminus1 );
- mpi_free( q );
- mpi_free( a2 );
-
- return rc;
-}
-
-
-/* Given ARRAY of size N with M elements set to true produce a
- modified array with the next permutation of M elements. Note, that
- ARRAY is used in a one-bit-per-byte approach. To detected the last
- permutation it is useful to intialize the array with the first M
- element set to true and use this test:
- m_out_of_n (array, m, n);
- for (i = j = 0; i < n && j < m; i++)
- if (array[i])
- j++;
- if (j == m)
- goto ready;
-
- This code is based on the algorithm 452 from the "Collected
- Algorithms From ACM, Volume II" by C. N. Liu and D. T. Tang.
-*/
-static void
-m_out_of_n ( char *array, int m, int n )
-{
- int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0;
-
- if( !m || m >= n )
- return;
-
- /* Need to handle this simple case separately. */
- if( m == 1 )
- {
- for (i=0; i < n; i++ )
- {
- if ( array[i] )
- {
- array[i++] = 0;
- if( i >= n )
- i = 0;
- array[i] = 1;
- return;
- }
- }
- BUG();
- }
-
-
- for (j=1; j < n; j++ )
- {
- if ( array[n-1] == array[n-j-1])
- continue;
- j1 = j;
- break;
- }
-
- if ( (m & 1) )
- {
- /* M is odd. */
- if( array[n-1] )
- {
- if( j1 & 1 )
- {
- k1 = n - j1;
- k2 = k1+2;
- if( k2 > n )
- k2 = n;
- goto leave;
- }
- goto scan;
- }
- k2 = n - j1 - 1;
- if( k2 == 0 )
- {
- k1 = i;
- k2 = n - j1;
- }
- else if( array[k2] && array[k2-1] )
- k1 = n;
- else
- k1 = k2 + 1;
- }
- else
- {
- /* M is even. */
- if( !array[n-1] )
- {
- k1 = n - j1;
- k2 = k1 + 1;
- goto leave;
- }
-
- if( !(j1 & 1) )
- {
- k1 = n - j1;
- k2 = k1+2;
- if( k2 > n )
- k2 = n;
- goto leave;
- }
- scan:
- jp = n - j1 - 1;
- for (i=1; i <= jp; i++ )
- {
- i1 = jp + 2 - i;
- if( array[i1-1] )
- {
- if( array[i1-2] )
- {
- k1 = i1 - 1;
- k2 = n - j1;
- }
- else
- {
- k1 = i1 - 1;
- k2 = n + 1 - j1;
- }
- goto leave;
- }
- }
- k1 = 1;
- k2 = n + 1 - m;
- }
- leave:
- /* Now complement the two selected bits. */
- array[k1-1] = !array[k1-1];
- array[k2-1] = !array[k2-1];
-}
-
-
-/* Generate a new prime number of PRIME_BITS bits and store it in
- PRIME. If FACTOR_BITS is non-zero, one of the prime factors of
- (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is
- non-zero, allocate a new, NULL-terminated array holding the prime
- factors and store it in FACTORS. FLAGS might be used to influence
- the prime number generation process. */
-gcry_error_t
-gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits,
- unsigned int factor_bits, gcry_mpi_t **factors,
- gcry_prime_check_func_t cb_func, void *cb_arg,
- gcry_random_level_t random_level,
- unsigned int flags)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_mpi_t *factors_generated = NULL;
- gcry_mpi_t prime_generated = NULL;
- unsigned int mode = 0;
-
- if (!prime)
- return gpg_error (GPG_ERR_INV_ARG);
- *prime = NULL;
-
- if (flags & GCRY_PRIME_FLAG_SPECIAL_FACTOR)
- mode = 1;
-
- /* Generate. */
- err = prime_generate_internal ((mode==1), &prime_generated, prime_bits,
- factor_bits, NULL,
- factors? &factors_generated : NULL,
- random_level, flags, 1,
- cb_func, cb_arg);
-
- if (! err)
- if (cb_func)
- {
- /* Additional check. */
- if ( !cb_func (cb_arg, GCRY_PRIME_CHECK_AT_FINISH, prime_generated))
- {
- /* Failed, deallocate resources. */
- unsigned int i;
-
- mpi_free (prime_generated);
- if (factors)
- {
- for (i = 0; factors_generated[i]; i++)
- mpi_free (factors_generated[i]);
- gcry_free (factors_generated);
- }
- err = GPG_ERR_GENERAL;
- }
- }
-
- if (! err)
- {
- if (factors)
- *factors = factors_generated;
- *prime = prime_generated;
- }
-
- return gcry_error (err);
-}
-
-/* Check wether the number X is prime. */
-gcry_error_t
-gcry_prime_check (gcry_mpi_t x, unsigned int flags)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */
-
- (void)flags;
-
- /* We use 64 rounds because the prime we are going to test is not
- guaranteed to be a random one. */
- if (! check_prime (x, val_2, 64, NULL, NULL))
- err = GPG_ERR_NO_PRIME;
-
- mpi_free (val_2);
-
- return gcry_error (err);
-}
-
-/* Find a generator for PRIME where the factorization of (prime-1) is
- in the NULL terminated array FACTORS. Return the generator as a
- newly allocated MPI in R_G. If START_G is not NULL, use this as s
- atart for the search. Returns 0 on success.*/
-gcry_error_t
-gcry_prime_group_generator (gcry_mpi_t *r_g,
- gcry_mpi_t prime, gcry_mpi_t *factors,
- gcry_mpi_t start_g)
-{
- gcry_mpi_t tmp = gcry_mpi_new (0);
- gcry_mpi_t b = gcry_mpi_new (0);
- gcry_mpi_t pmin1 = gcry_mpi_new (0);
- gcry_mpi_t g = start_g? gcry_mpi_copy (start_g) : gcry_mpi_set_ui (NULL, 3);
- int first = 1;
- int i, n;
-
- if (!factors || !r_g || !prime)
- return gpg_error (GPG_ERR_INV_ARG);
- *r_g = NULL;
-
- for (n=0; factors[n]; n++)
- ;
- if (n < 2)
- return gpg_error (GPG_ERR_INV_ARG);
-
- /* Extra sanity check - usually disabled. */
-/* mpi_set (tmp, factors[0]); */
-/* for(i = 1; i < n; i++) */
-/* mpi_mul (tmp, tmp, factors[i]); */
-/* mpi_add_ui (tmp, tmp, 1); */
-/* if (mpi_cmp (prime, tmp)) */
-/* return gpg_error (GPG_ERR_INV_ARG); */
-
- gcry_mpi_sub_ui (pmin1, prime, 1);
- do
- {
- if (first)
- first = 0;
- else
- gcry_mpi_add_ui (g, g, 1);
-
- if (DBG_CIPHER)
- {
- log_debug ("checking g:");
- gcry_mpi_dump (g);
- log_debug ("\n");
- }
- else
- progress('^');
-
- for (i = 0; i < n; i++)
- {
- mpi_fdiv_q (tmp, pmin1, factors[i]);
- gcry_mpi_powm (b, g, tmp, prime);
- if (! mpi_cmp_ui (b, 1))
- break;
- }
- if (DBG_CIPHER)
- progress('\n');
- }
- while (i < n);
-
- gcry_mpi_release (tmp);
- gcry_mpi_release (b);
- gcry_mpi_release (pmin1);
- *r_g = g;
-
- return 0;
-}
-
-/* Convenience function to release the factors array. */
-void
-gcry_prime_release_factors (gcry_mpi_t *factors)
-{
- if (factors)
- {
- int i;
-
- for (i=0; factors[i]; i++)
- mpi_free (factors[i]);
- gcry_free (factors);
- }
-}
-
-
-
-/* Helper for _gcry_derive_x931_prime. */
-static gcry_mpi_t
-find_x931_prime (const gcry_mpi_t pfirst)
-{
- gcry_mpi_t val_2 = mpi_alloc_set_ui (2);
- gcry_mpi_t prime;
-
- prime = gcry_mpi_copy (pfirst);
- /* If P is even add 1. */
- mpi_set_bit (prime, 0);
-
- /* We use 64 Rabin-Miller rounds which is better and thus
- sufficient. We do not have a Lucas test implementaion thus we
- can't do it in the X9.31 preferred way of running a few
- Rabin-Miller followed by one Lucas test. */
- while ( !check_prime (prime, val_2, 64, NULL, NULL) )
- mpi_add_ui (prime, prime, 2);
-
- mpi_free (val_2);
-
- return prime;
-}
-
-
-/* Generate a prime using the algorithm from X9.31 appendix B.4.
-
- This function requires that the provided public exponent E is odd.
- XP, XP1 and XP2 are the seed values. All values are mandatory.
-
- On success the prime is returned. If R_P1 or R_P2 are given the
- internal values P1 and P2 are saved at these addresses. On error
- NULL is returned. */
-gcry_mpi_t
-_gcry_derive_x931_prime (const gcry_mpi_t xp,
- const gcry_mpi_t xp1, const gcry_mpi_t xp2,
- const gcry_mpi_t e,
- gcry_mpi_t *r_p1, gcry_mpi_t *r_p2)
-{
- gcry_mpi_t p1, p2, p1p2, yp0;
-
- if (!xp || !xp1 || !xp2)
- return NULL;
- if (!e || !mpi_test_bit (e, 0))
- return NULL; /* We support only odd values for E. */
-
- p1 = find_x931_prime (xp1);
- p2 = find_x931_prime (xp2);
- p1p2 = mpi_alloc_like (xp);
- mpi_mul (p1p2, p1, p2);
-
- {
- gcry_mpi_t r1, tmp;
-
- /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */
- tmp = mpi_alloc_like (p1);
- mpi_invm (tmp, p2, p1);
- mpi_mul (tmp, tmp, p2);
- r1 = tmp;
-
- tmp = mpi_alloc_like (p2);
- mpi_invm (tmp, p1, p2);
- mpi_mul (tmp, tmp, p1);
- mpi_sub (r1, r1, tmp);
-
- /* Fixup a negative value. */
- if (mpi_is_neg (r1))
- mpi_add (r1, r1, p1p2);
-
- /* yp0 = xp + (r1 - xp mod p1*p2) */
- yp0 = tmp; tmp = NULL;
- mpi_subm (yp0, r1, xp, p1p2);
- mpi_add (yp0, yp0, xp);
- mpi_free (r1);
-
- /* Fixup a negative value. */
- if (mpi_cmp (yp0, xp) < 0 )
- mpi_add (yp0, yp0, p1p2);
- }
-
- /* yp0 is now the first integer greater than xp with p1 being a
- large prime factor of yp0-1 and p2 a large prime factor of yp0+1. */
-
- /* Note that the first example from X9.31 (D.1.1) which uses
- (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)
- (Xq2 #134E4CAA16D2350A21D775C404#)
- (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
- 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325
- 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34
- 321DE34A#))))
- returns an yp0 of
- #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
- 7C9953388F97DDDC3E1CA19C35CA659EDC2FC4E3
- BF20CB896EE37E098A906313271422162CB6C642
- 75C1201F#
- and not
- #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
- 7C9953388F97DDDC3E1CA19C35CA659EDC2FC2E6
- C88FE299D52D78BE405A97E01FD71DD7819ECB91
- FA85A076#
- as stated in the standard. This seems to be a bug in X9.31.
- */
-
- {
- gcry_mpi_t val_2 = mpi_alloc_set_ui (2);
- gcry_mpi_t gcdtmp = mpi_alloc_like (yp0);
- int gcdres;
-
- mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body. */
- mpi_sub_ui (yp0, yp0, 1); /* Ditto. */
- for (;;)
- {
- gcdres = gcry_mpi_gcd (gcdtmp, e, yp0);
- mpi_add_ui (yp0, yp0, 1);
- if (!gcdres)
- progress ('/'); /* gcd (e, yp0-1) != 1 */
- else if (check_prime (yp0, val_2, 64, NULL, NULL))
- break; /* Found. */
- /* We add p1p2-1 because yp0 is incremented after the gcd test. */
- mpi_add (yp0, yp0, p1p2);
- }
- mpi_free (gcdtmp);
- mpi_free (val_2);
- }
-
- mpi_free (p1p2);
-
- progress('\n');
- if (r_p1)
- *r_p1 = p1;
- else
- mpi_free (p1);
- if (r_p2)
- *r_p2 = p2;
- else
- mpi_free (p2);
- return yp0;
-}
-
-
-
-/* Generate the two prime used for DSA using the algorithm specified
- in FIPS 186-2. PBITS is the desired length of the prime P and a
- QBITS the length of the prime Q. If SEED is not supplied and
- SEEDLEN is 0 the function generates an appropriate SEED. On
- success the generated primes are stored at R_Q and R_P, the counter
- value is stored at R_COUNTER and the seed actually used for
- generation is stored at R_SEED and R_SEEDVALUE. */
-gpg_err_code_t
-_gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits,
- const void *seed, size_t seedlen,
- gcry_mpi_t *r_q, gcry_mpi_t *r_p,
- int *r_counter,
- void **r_seed, size_t *r_seedlen)
-{
- gpg_err_code_t ec;
- unsigned char seed_help_buffer[160/8]; /* Used to hold a generated SEED. */
- unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */
- unsigned char digest[160/8]; /* Helper buffer for SHA-1 digest. */
- gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */
- gcry_mpi_t tmpval = NULL; /* Helper variable. */
- int i;
-
- unsigned char value_u[160/8];
- int value_n, value_b, value_k;
- int counter;
- gcry_mpi_t value_w = NULL;
- gcry_mpi_t value_x = NULL;
- gcry_mpi_t prime_q = NULL;
- gcry_mpi_t prime_p = NULL;
-
- /* FIPS 186-2 allows only for 1024/160 bit. */
- if (pbits != 1024 || qbits != 160)
- return GPG_ERR_INV_KEYLEN;
-
- if (!seed && !seedlen)
- ; /* No seed value given: We are asked to generate it. */
- else if (!seed || seedlen < qbits/8)
- return GPG_ERR_INV_ARG;
-
- /* Allocate a buffer to later compute SEED+some_increment. */
- seed_plus = gcry_malloc (seedlen < 20? 20:seedlen);
- if (!seed_plus)
- {
- ec = gpg_err_code_from_syserror ();
- goto leave;
- }
-
- val_2 = mpi_alloc_set_ui (2);
- value_n = (pbits - 1) / qbits;
- value_b = (pbits - 1) - value_n * qbits;
- value_w = gcry_mpi_new (pbits);
- value_x = gcry_mpi_new (pbits);
-
- restart:
- /* Generate Q. */
- for (;;)
- {
- /* Step 1: Generate a (new) seed unless one has been supplied. */
- if (!seed)
- {
- seedlen = sizeof seed_help_buffer;
- gcry_create_nonce (seed_help_buffer, seedlen);
- seed = seed_help_buffer;
- }
-
- /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */
- memcpy (seed_plus, seed, seedlen);
- for (i=seedlen-1; i >= 0; i--)
- {
- seed_plus[i]++;
- if (seed_plus[i])
- break;
- }
- gcry_md_hash_buffer (GCRY_MD_SHA1, value_u, seed, seedlen);
- gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
- for (i=0; i < sizeof value_u; i++)
- value_u[i] ^= digest[i];
-
- /* Step 3: Form q from U */
- gcry_mpi_release (prime_q); prime_q = NULL;
- ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
- value_u, sizeof value_u, NULL));
- if (ec)
- goto leave;
- mpi_set_highbit (prime_q, qbits-1 );
- mpi_set_bit (prime_q, 0);
-
- /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */
- if (check_prime (prime_q, val_2, 64, NULL, NULL))
- break; /* Yes, Q is prime. */
-
- /* Step 5. */
- seed = NULL; /* Force a new seed at Step 1. */
- }
-
- /* Step 6. Note that we do no use an explicit offset but increment
- SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */
- counter = 0;
-
- /* Generate P. */
- prime_p = gcry_mpi_new (pbits);
- for (;;)
- {
- /* Step 7: For k = 0,...n let
- V_k = sha1(seed+offset+k) mod 2^{qbits}
- Step 8: W = V_0 + V_1*2^160 +
- ...
- + V_{n-1}*2^{(n-1)*160}
- + (V_{n} mod 2^b)*2^{n*160}
- */
- mpi_set_ui (value_w, 0);
- for (value_k=0; value_k <= value_n; value_k++)
- {
- /* There is no need to have an explicit offset variable: In
- the first round we shall have an offset of 2, this is
- achieved by using SEED_PLUS which is already at SEED+1,
- thus we just need to increment it once again. The
- requirement for the next round is to update offset by N,
- which we implictly did at the end of this loop, and then
- to add one; this one is the same as in the first round. */
- for (i=seedlen-1; i >= 0; i--)
- {
- seed_plus[i]++;
- if (seed_plus[i])
- break;
- }
- gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
-
- gcry_mpi_release (tmpval); tmpval = NULL;
- ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
- digest, sizeof digest, NULL));
- if (ec)
- goto leave;
- if (value_k == value_n)
- mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */
- mpi_lshift (tmpval, tmpval, value_k*qbits);
- mpi_add (value_w, value_w, tmpval);
- }
-
- /* Step 8 continued: X = W + 2^{L-1} */
- mpi_set_ui (value_x, 0);
- mpi_set_highbit (value_x, pbits-1);
- mpi_add (value_x, value_x, value_w);
-
- /* Step 9: c = X mod 2q, p = X - (c - 1) */
- mpi_mul_2exp (tmpval, prime_q, 1);
- mpi_mod (tmpval, value_x, tmpval);
- mpi_sub_ui (tmpval, tmpval, 1);
- mpi_sub (prime_p, value_x, tmpval);
-
- /* Step 10: If p < 2^{L-1} skip the primality test. */
- /* Step 11 and 12: Primality test. */
- if (mpi_get_nbits (prime_p) >= pbits-1
- && check_prime (prime_p, val_2, 64, NULL, NULL) )
- break; /* Yes, P is prime, continue with Step 15. */
-
- /* Step 13: counter = counter + 1, offset = offset + n + 1. */
- counter++;
-
- /* Step 14: If counter >= 2^12 goto Step 1. */
- if (counter >= 4096)
- goto restart;
- }
-
- /* Step 15: Save p, q, counter and seed. */
-/* log_debug ("fips186-2 pbits p=%u q=%u counter=%d\n", */
-/* mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */
-/* log_printhex("fips186-2 seed:", seed, seedlen); */
-/* log_mpidump ("fips186-2 prime p", prime_p); */
-/* log_mpidump ("fips186-2 prime q", prime_q); */
- if (r_q)
- {
- *r_q = prime_q;
- prime_q = NULL;
- }
- if (r_p)
- {
- *r_p = prime_p;
- prime_p = NULL;
- }
- if (r_counter)
- *r_counter = counter;
- if (r_seed && r_seedlen)
- {
- memcpy (seed_plus, seed, seedlen);
- *r_seed = seed_plus;
- seed_plus = NULL;
- *r_seedlen = seedlen;
- }
-
-
- leave:
- gcry_mpi_release (tmpval);
- gcry_mpi_release (value_x);
- gcry_mpi_release (value_w);
- gcry_mpi_release (prime_p);
- gcry_mpi_release (prime_q);
- gcry_free (seed_plus);
- gcry_mpi_release (val_2);
- return ec;
-}
-
-
-
-/* WARNING: The code below has not yet been tested! However, it is
- not yet used. We need to wait for FIPS 186-3 final and for test
- vectors.
-
- Generate the two prime used for DSA using the algorithm specified
- in FIPS 186-3, A.1.1.2. PBITS is the desired length of the prime P
- and a QBITS the length of the prime Q. If SEED is not supplied and
- SEEDLEN is 0 the function generates an appropriate SEED. On
- success the generated primes are stored at R_Q and R_P, the counter
- value is stored at R_COUNTER and the seed actually used for
- generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm
- used is stored at R_HASHALGO.
-
- Note that this function is very similar to the fips186_2 code. Due
- to the minor differences, other buffer sizes and for documentarion,
- we use a separate function.
-*/
-gpg_err_code_t
-_gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
- const void *seed, size_t seedlen,
- gcry_mpi_t *r_q, gcry_mpi_t *r_p,
- int *r_counter,
- void **r_seed, size_t *r_seedlen,
- int *r_hashalgo)
-{
- gpg_err_code_t ec;
- unsigned char seed_help_buffer[256/8]; /* Used to hold a generated SEED. */
- unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */
- unsigned char digest[256/8]; /* Helper buffer for SHA-1 digest. */
- gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */
- gcry_mpi_t tmpval = NULL; /* Helper variable. */
- int hashalgo; /* The id of the Approved Hash Function. */
- int i;
-
- unsigned char value_u[256/8];
- int value_n, value_b, value_j;
- int counter;
- gcry_mpi_t value_w = NULL;
- gcry_mpi_t value_x = NULL;
- gcry_mpi_t prime_q = NULL;
- gcry_mpi_t prime_p = NULL;
-
- gcry_assert (sizeof seed_help_buffer == sizeof digest
- && sizeof seed_help_buffer == sizeof value_u);
-
- /* Step 1: Check the requested prime lengths. */
- /* Note that due to the size of our buffers QBITS is limited to 256. */
- if (pbits == 1024 && qbits == 160)
- hashalgo = GCRY_MD_SHA1;
- else if (pbits == 2048 && qbits == 224)
- hashalgo = GCRY_MD_SHA224;
- else if (pbits == 2048 && qbits == 256)
- hashalgo = GCRY_MD_SHA256;
- else if (pbits == 3072 && qbits == 256)
- hashalgo = GCRY_MD_SHA256;
- else
- return GPG_ERR_INV_KEYLEN;
-
- /* Also check that the hash algorithm is available. */
- ec = gpg_err_code (gcry_md_test_algo (hashalgo));
- if (ec)
- return ec;
- gcry_assert (qbits/8 <= sizeof digest);
- gcry_assert (gcry_md_get_algo_dlen (hashalgo) == qbits/8);
-
-
- /* Step 2: Check seedlen. */
- if (!seed && !seedlen)
- ; /* No seed value given: We are asked to generate it. */
- else if (!seed || seedlen < qbits/8)
- return GPG_ERR_INV_ARG;
-
- /* Allocate a buffer to later compute SEED+some_increment and a few
- helper variables. */
- seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer?
- sizeof seed_help_buffer : seedlen);
- if (!seed_plus)
- {
- ec = gpg_err_code_from_syserror ();
- goto leave;
- }
- val_2 = mpi_alloc_set_ui (2);
- value_w = gcry_mpi_new (pbits);
- value_x = gcry_mpi_new (pbits);
-
- /* Step 3: n = \lceil L / outlen \rceil - 1 */
- value_n = (pbits + qbits - 1) / qbits - 1;
- /* Step 4: b = L - 1 - (n * outlen) */
- value_b = pbits - 1 - (value_n * qbits);
-
- restart:
- /* Generate Q. */
- for (;;)
- {
- /* Step 5: Generate a (new) seed unless one has been supplied. */
- if (!seed)
- {
- seedlen = qbits/8;
- gcry_assert (seedlen <= sizeof seed_help_buffer);
- gcry_create_nonce (seed_help_buffer, seedlen);
- seed = seed_help_buffer;
- }
-
- /* Step 6: U = hash(seed) */
- gcry_md_hash_buffer (hashalgo, value_u, seed, seedlen);
-
- /* Step 7: q = 2^{N-1} + U + 1 - (U mod 2) */
- if ( !(value_u[qbits/8-1] & 0x01) )
- {
- for (i=qbits/8-1; i >= 0; i--)
- {
- value_u[i]++;
- if (value_u[i])
- break;
- }
- }
- gcry_mpi_release (prime_q); prime_q = NULL;
- ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
- value_u, sizeof value_u, NULL));
- if (ec)
- goto leave;
- mpi_set_highbit (prime_q, qbits-1 );
-
- /* Step 8: Test whether Q is prime using 64 round of Rabin-Miller.
- According to table C.1 this is sufficient for all
- supported prime sizes (i.e. up 3072/256). */
- if (check_prime (prime_q, val_2, 64, NULL, NULL))
- break; /* Yes, Q is prime. */
-
- /* Step 8. */
- seed = NULL; /* Force a new seed at Step 5. */
- }
-
- /* Step 11. Note that we do no use an explicit offset but increment
- SEED_PLUS accordingly. */
- memcpy (seed_plus, seed, seedlen);
- counter = 0;
-
- /* Generate P. */
- prime_p = gcry_mpi_new (pbits);
- for (;;)
- {
- /* Step 11.1: For j = 0,...n let
- V_j = hash(seed+offset+j)
- Step 11.2: W = V_0 + V_1*2^outlen +
- ...
- + V_{n-1}*2^{(n-1)*outlen}
- + (V_{n} mod 2^b)*2^{n*outlen}
- */
- mpi_set_ui (value_w, 0);
- for (value_j=0; value_j <= value_n; value_j++)
- {
- /* There is no need to have an explicit offset variable: In
- the first round we shall have an offset of 1 and a j of
- 0. This is achieved by incrementing SEED_PLUS here. For
- the next round offset is implicitly updated by using
- SEED_PLUS again. */
- for (i=seedlen-1; i >= 0; i--)
- {
- seed_plus[i]++;
- if (seed_plus[i])
- break;
- }
- gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
-
- gcry_mpi_release (tmpval); tmpval = NULL;
- ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
- digest, sizeof digest, NULL));
- if (ec)
- goto leave;
- if (value_j == value_n)
- mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */
- mpi_lshift (tmpval, tmpval, value_j*qbits);
- mpi_add (value_w, value_w, tmpval);
- }
-
- /* Step 11.3: X = W + 2^{L-1} */
- mpi_set_ui (value_x, 0);
- mpi_set_highbit (value_x, pbits-1);
- mpi_add (value_x, value_x, value_w);
-
- /* Step 11.4: c = X mod 2q */
- mpi_mul_2exp (tmpval, prime_q, 1);
- mpi_mod (tmpval, value_x, tmpval);
-
- /* Step 11.5: p = X - (c - 1) */
- mpi_sub_ui (tmpval, tmpval, 1);
- mpi_sub (prime_p, value_x, tmpval);
-
- /* Step 11.6: If p < 2^{L-1} skip the primality test. */
- /* Step 11.7 and 11.8: Primality test. */
- if (mpi_get_nbits (prime_p) >= pbits-1
- && check_prime (prime_p, val_2, 64, NULL, NULL) )
- break; /* Yes, P is prime, continue with Step 15. */
-
- /* Step 11.9: counter = counter + 1, offset = offset + n + 1.
- If counter >= 4L goto Step 5. */
- counter++;
- if (counter >= 4*pbits)
- goto restart;
- }
-
- /* Step 12: Save p, q, counter and seed. */
- log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n",
- mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter);
- log_printhex("fips186-3 seed:", seed, seedlen);
- log_mpidump ("fips186-3 prime p", prime_p);
- log_mpidump ("fips186-3 prime q", prime_q);
- if (r_q)
- {
- *r_q = prime_q;
- prime_q = NULL;
- }
- if (r_p)
- {
- *r_p = prime_p;
- prime_p = NULL;
- }
- if (r_counter)
- *r_counter = counter;
- if (r_seed && r_seedlen)
- {
- memcpy (seed_plus, seed, seedlen);
- *r_seed = seed_plus;
- seed_plus = NULL;
- *r_seedlen = seedlen;
- }
- if (r_hashalgo)
- *r_hashalgo = hashalgo;
-
- leave:
- gcry_mpi_release (tmpval);
- gcry_mpi_release (value_x);
- gcry_mpi_release (value_w);
- gcry_mpi_release (prime_p);
- gcry_mpi_release (prime_q);
- gcry_free (seed_plus);
- gcry_mpi_release (val_2);
- return ec;
-}
-
+/* primegen.c - prime number generator
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003
+ * 2004, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "cipher.h"
+#include "ath.h"
+
+static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel,
+ int (*extra_check)(void *, gcry_mpi_t),
+ void *extra_check_arg);
+static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds,
+ gcry_prime_check_func_t cb_func, void *cb_arg );
+static int is_prime (gcry_mpi_t n, int steps, unsigned int *count);
+static void m_out_of_n( char *array, int m, int n );
+
+static void (*progress_cb) (void *,const char*,int,int, int );
+static void *progress_cb_data;
+
+/* Note: 2 is not included because it can be tested more easily by
+ looking at bit 0. The last entry in this list is marked by a zero */
+static ushort small_prime_numbers[] = {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+ 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
+ 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
+ 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
+ 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
+ 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
+ 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
+ 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
+ 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
+ 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
+ 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
+ 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+ 709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
+ 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
+ 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
+ 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
+ 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
+ 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
+ 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
+ 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
+ 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277,
+ 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307,
+ 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
+ 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
+ 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
+ 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
+ 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
+ 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
+ 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
+ 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,
+ 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
+ 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
+ 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
+ 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
+ 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111,
+ 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161,
+ 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243,
+ 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
+ 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411,
+ 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
+ 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
+ 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633,
+ 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
+ 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729,
+ 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
+ 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
+ 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917,
+ 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,
+ 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137,
+ 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
+ 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
+ 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
+ 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391,
+ 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
+ 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533,
+ 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583,
+ 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
+ 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
+ 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779,
+ 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
+ 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917,
+ 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
+ 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
+ 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111,
+ 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
+ 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243,
+ 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
+ 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391,
+ 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
+ 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519,
+ 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
+ 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
+ 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799,
+ 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
+ 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951,
+ 4957, 4967, 4969, 4973, 4987, 4993, 4999,
+ 0
+};
+static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1;
+
+
+
+/* An object and a list to build up a global pool of primes. See
+ save_pool_prime and get_pool_prime. */
+struct primepool_s
+{
+ struct primepool_s *next;
+ gcry_mpi_t prime; /* If this is NULL the entry is not used. */
+ unsigned int nbits;
+ gcry_random_level_t randomlevel;
+};
+struct primepool_s *primepool;
+/* Mutex used to protect access to the primepool. */
+static ath_mutex_t primepool_lock = ATH_MUTEX_INITIALIZER;
+
+
+
+/* Save PRIME which has been generated at RANDOMLEVEL for later
+ use. Needs to be called while primepool_lock is being hold. Note
+ that PRIME should be considered released after calling this
+ function. */
+static void
+save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel)
+{
+ struct primepool_s *item, *item2;
+ size_t n;
+
+ for (n=0, item = primepool; item; item = item->next, n++)
+ if (!item->prime)
+ break;
+ if (!item && n > 100)
+ {
+ /* Remove some of the entries. Our strategy is removing
+ the last third from the list. */
+ int i;
+
+ for (i=0, item2 = primepool; item2; item2 = item2->next)
+ {
+ if (i >= n/3*2)
+ {
+ gcry_mpi_release (item2->prime);
+ item2->prime = NULL;
+ if (!item)
+ item = item2;
+ }
+ }
+ }
+ if (!item)
+ {
+ item = gcry_calloc (1, sizeof *item);
+ if (!item)
+ {
+ /* Out of memory. Silently giving up. */
+ gcry_mpi_release (prime);
+ return;
+ }
+ item->next = primepool;
+ primepool = item;
+ }
+ item->prime = prime;
+ item->nbits = mpi_get_nbits (prime);
+ item->randomlevel = randomlevel;
+}
+
+
+/* Return a prime for the prime pool or NULL if none has been found.
+ The prime needs to match NBITS and randomlevel. This function needs
+ to be called why the primepool_look is being hold. */
+static gcry_mpi_t
+get_pool_prime (unsigned int nbits, gcry_random_level_t randomlevel)
+{
+ struct primepool_s *item;
+
+ for (item = primepool; item; item = item->next)
+ if (item->prime
+ && item->nbits == nbits && item->randomlevel == randomlevel)
+ {
+ gcry_mpi_t prime = item->prime;
+ item->prime = NULL;
+ gcry_assert (nbits == mpi_get_nbits (prime));
+ return prime;
+ }
+ return NULL;
+}
+
+
+
+
+
+
+void
+_gcry_register_primegen_progress ( void (*cb)(void *,const char*,int,int,int),
+ void *cb_data )
+{
+ progress_cb = cb;
+ progress_cb_data = cb_data;
+}
+
+
+static void
+progress( int c )
+{
+ if ( progress_cb )
+ progress_cb ( progress_cb_data, "primegen", c, 0, 0 );
+}
+
+
+/****************
+ * Generate a prime number (stored in secure memory)
+ */
+gcry_mpi_t
+_gcry_generate_secret_prime (unsigned int nbits,
+ gcry_random_level_t random_level,
+ int (*extra_check)(void*, gcry_mpi_t),
+ void *extra_check_arg)
+{
+ gcry_mpi_t prime;
+
+ prime = gen_prime (nbits, 1, random_level, extra_check, extra_check_arg);
+ progress('\n');
+ return prime;
+}
+
+
+/* Generate a prime number which may be public, i.e. not allocated in
+ secure memory. */
+gcry_mpi_t
+_gcry_generate_public_prime (unsigned int nbits,
+ gcry_random_level_t random_level,
+ int (*extra_check)(void*, gcry_mpi_t),
+ void *extra_check_arg)
+{
+ gcry_mpi_t prime;
+
+ prime = gen_prime (nbits, 0, random_level, extra_check, extra_check_arg);
+ progress('\n');
+ return prime;
+}
+
+
+/* Core prime generation function. The algorithm used to generate
+ practically save primes is due to Lim and Lee as described in the
+ CRYPTO '97 proceedings (ISBN3540633847) page 260.
+
+ NEED_Q_FACTOR: If true make sure that at least one factor is of
+ size qbits. This is for example required for DSA.
+ PRIME_GENERATED: Adresss of a variable where the resulting prime
+ number will be stored.
+ PBITS: Requested size of the prime number. At least 48.
+ QBITS: One factor of the prime needs to be of this size. Maybe 0
+ if this is not required. See also MODE.
+ G: If not NULL an MPI which will receive a generator for the prime
+ for use with Elgamal.
+ RET_FACTORS: if not NULL, an array with all factors are stored at
+ that address.
+ ALL_FACTORS: If set to true all factors of prime-1 are returned.
+ RANDOMLEVEL: How strong should the random numers be.
+ FLAGS: Prime generation bit flags. Currently supported:
+ GCRY_PRIME_FLAG_SECRET - The prime needs to be kept secret.
+ CB_FUNC, CB_ARG: Callback to be used for extra checks.
+
+ */
+static gcry_err_code_t
+prime_generate_internal (int need_q_factor,
+ gcry_mpi_t *prime_generated, unsigned int pbits,
+ unsigned int qbits, gcry_mpi_t g,
+ gcry_mpi_t **ret_factors,
+ gcry_random_level_t randomlevel, unsigned int flags,
+ int all_factors,
+ gcry_prime_check_func_t cb_func, void *cb_arg)
+{
+ gcry_err_code_t err = 0;
+ gcry_mpi_t *factors_new = NULL; /* Factors to return to the
+ caller. */
+ gcry_mpi_t *factors = NULL; /* Current factors. */
+ gcry_random_level_t poolrandomlevel; /* Random level used for pool primes. */
+ gcry_mpi_t *pool = NULL; /* Pool of primes. */
+ int *pool_in_use = NULL; /* Array with currently used POOL elements. */
+ unsigned char *perms = NULL; /* Permutations of POOL. */
+ gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */
+ unsigned int fbits = 0; /* Length of prime factors. */
+ unsigned int n = 0; /* Number of factors. */
+ unsigned int m = 0; /* Number of primes in pool. */
+ gcry_mpi_t q = NULL; /* First prime factor. */
+ gcry_mpi_t prime = NULL; /* Prime candidate. */
+ unsigned int nprime = 0; /* Bits of PRIME. */
+ unsigned int req_qbits; /* The original QBITS value. */
+ gcry_mpi_t val_2; /* For check_prime(). */
+ int is_locked = 0; /* Flag to help unlocking the primepool. */
+ unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET);
+ unsigned int count1 = 0, count2 = 0;
+ unsigned int i = 0, j = 0;
+
+ if (pbits < 48)
+ return GPG_ERR_INV_ARG;
+
+ /* We won't use a too strong random elvel for the pooled subprimes. */
+ poolrandomlevel = (randomlevel > GCRY_STRONG_RANDOM?
+ GCRY_STRONG_RANDOM : randomlevel);
+
+
+ /* If QBITS is not given, assume a reasonable value. */
+ if (!qbits)
+ qbits = pbits / 3;
+
+ req_qbits = qbits;
+
+ /* Find number of needed prime factors N. */
+ for (n = 1; (pbits - qbits - 1) / n >= qbits; n++)
+ ;
+ n--;
+
+ val_2 = mpi_alloc_set_ui (2);
+
+ if ((! n) || ((need_q_factor) && (n < 2)))
+ {
+ err = GPG_ERR_INV_ARG;
+ goto leave;
+ }
+
+ if (need_q_factor)
+ {
+ n--; /* Need one factor less because we want a specific Q-FACTOR. */
+ fbits = (pbits - 2 * req_qbits -1) / n;
+ qbits = pbits - req_qbits - n * fbits;
+ }
+ else
+ {
+ fbits = (pbits - req_qbits -1) / n;
+ qbits = pbits - n * fbits;
+ }
+
+ if (DBG_CIPHER)
+ log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
+ pbits, req_qbits, qbits, fbits, n);
+
+ /* Allocate an integer to old the new prime. */
+ prime = gcry_mpi_new (pbits);
+
+ /* Generate first prime factor. */
+ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
+
+ /* Generate a specific Q-Factor if requested. */
+ if (need_q_factor)
+ q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL);
+
+ /* Allocate an array to hold all factors + 2 for later usage. */
+ factors = gcry_calloc (n + 2, sizeof (*factors));
+ if (!factors)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ /* Allocate an array to track pool usage. */
+ pool_in_use = gcry_malloc (n * sizeof *pool_in_use);
+ if (!pool_in_use)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ for (i=0; i < n; i++)
+ pool_in_use[i] = -1;
+
+ /* Make a pool of 3n+5 primes (this is an arbitrary value). We
+ require at least 30 primes for are useful selection process.
+
+ Fixme: We need to research the best formula for sizing the pool.
+ */
+ m = n * 3 + 5;
+ if (need_q_factor) /* Need some more in this case. */
+ m += 5;
+ if (m < 30)
+ m = 30;
+ pool = gcry_calloc (m , sizeof (*pool));
+ if (! pool)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ /* Permutate over the pool of primes until we find a prime of the
+ requested length. */
+ do
+ {
+ next_try:
+ for (i=0; i < n; i++)
+ pool_in_use[i] = -1;
+
+ if (!perms)
+ {
+ /* Allocate new primes. This is done right at the beginning
+ of the loop and if we have later run out of primes. */
+ for (i = 0; i < m; i++)
+ {
+ mpi_free (pool[i]);
+ pool[i] = NULL;
+ }
+
+ /* Init m_out_of_n(). */
+ perms = gcry_calloc (1, m);
+ if (!perms)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ if (ath_mutex_lock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 1;
+ for (i = 0; i < n; i++)
+ {
+ perms[i] = 1;
+ /* At a maximum we use strong random for the factors.
+ This saves us a lot of entropy. Given that Q and
+ possible Q-factor are also used in the final prime
+ this should be acceptable. We also don't allocate in
+ secure memory to save on that scare resource too. If
+ Q has been allocated in secure memory, the final
+ prime will be saved there anyway. This is because
+ our MPI routines take care of that. GnuPG has worked
+ this way ever since. */
+ pool[i] = NULL;
+ if (is_locked)
+ {
+ pool[i] = get_pool_prime (fbits, poolrandomlevel);
+ if (!pool[i])
+ {
+ if (ath_mutex_unlock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 0;
+ }
+ }
+ if (!pool[i])
+ pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL);
+ pool_in_use[i] = i;
+ factors[i] = pool[i];
+ }
+ if (is_locked && ath_mutex_unlock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 0;
+ }
+ else
+ {
+ /* Get next permutation. */
+ m_out_of_n ( (char*)perms, n, m);
+ if (ath_mutex_lock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 1;
+ for (i = j = 0; (i < m) && (j < n); i++)
+ if (perms[i])
+ {
+ /* If the subprime has not yet beed generated do it now. */
+ if (!pool[i] && is_locked)
+ {
+ pool[i] = get_pool_prime (fbits, poolrandomlevel);
+ if (!pool[i])
+ {
+ if (ath_mutex_unlock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 0;
+ }
+ }
+ if (!pool[i])
+ pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL);
+ pool_in_use[j] = i;
+ factors[j++] = pool[i];
+ }
+ if (is_locked && ath_mutex_unlock (&primepool_lock))
+ {
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+ is_locked = 0;
+ if (i == n)
+ {
+ /* Ran out of permutations: Allocate new primes. */
+ gcry_free (perms);
+ perms = NULL;
+ progress ('!');
+ goto next_try;
+ }
+ }
+
+ /* Generate next prime candidate:
+ p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1.
+ */
+ mpi_set (prime, q);
+ mpi_mul_ui (prime, prime, 2);
+ if (need_q_factor)
+ mpi_mul (prime, prime, q_factor);
+ for(i = 0; i < n; i++)
+ mpi_mul (prime, prime, factors[i]);
+ mpi_add_ui (prime, prime, 1);
+ nprime = mpi_get_nbits (prime);
+
+ if (nprime < pbits)
+ {
+ if (++count1 > 20)
+ {
+ count1 = 0;
+ qbits++;
+ progress('>');
+ mpi_free (q);
+ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
+ goto next_try;
+ }
+ }
+ else
+ count1 = 0;
+
+ if (nprime > pbits)
+ {
+ if (++count2 > 20)
+ {
+ count2 = 0;
+ qbits--;
+ progress('<');
+ mpi_free (q);
+ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL);
+ goto next_try;
+ }
+ }
+ else
+ count2 = 0;
+ }
+ while (! ((nprime == pbits) && check_prime (prime, val_2, 5,
+ cb_func, cb_arg)));
+
+ if (DBG_CIPHER)
+ {
+ progress ('\n');
+ log_mpidump ("prime : ", prime);
+ log_mpidump ("factor q: ", q);
+ if (need_q_factor)
+ log_mpidump ("factor q0: ", q_factor);
+ for (i = 0; i < n; i++)
+ log_mpidump ("factor pi: ", factors[i]);
+ log_debug ("bit sizes: prime=%u, q=%u",
+ mpi_get_nbits (prime), mpi_get_nbits (q));
+ if (need_q_factor)
+ log_debug (", q0=%u", mpi_get_nbits (q_factor));
+ for (i = 0; i < n; i++)
+ log_debug (", p%d=%u", i, mpi_get_nbits (factors[i]));
+ progress('\n');
+ }
+
+ if (ret_factors)
+ {
+ /* Caller wants the factors. */
+ factors_new = gcry_calloc (n + 4, sizeof (*factors_new));
+ if (! factors_new)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ if (all_factors)
+ {
+ i = 0;
+ factors_new[i++] = gcry_mpi_set_ui (NULL, 2);
+ factors_new[i++] = mpi_copy (q);
+ if (need_q_factor)
+ factors_new[i++] = mpi_copy (q_factor);
+ for(j=0; j < n; j++)
+ factors_new[i++] = mpi_copy (factors[j]);
+ }
+ else
+ {
+ i = 0;
+ if (need_q_factor)
+ {
+ factors_new[i++] = mpi_copy (q_factor);
+ for (; i <= n; i++)
+ factors_new[i] = mpi_copy (factors[i]);
+ }
+ else
+ for (; i < n; i++ )
+ factors_new[i] = mpi_copy (factors[i]);
+ }
+ }
+
+ if (g)
+ {
+ /* Create a generator (start with 3). */
+ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime));
+ gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime));
+ gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime));
+
+ if (need_q_factor)
+ err = GPG_ERR_NOT_IMPLEMENTED;
+ else
+ {
+ factors[n] = q;
+ factors[n + 1] = mpi_alloc_set_ui (2);
+ mpi_sub_ui (pmin1, prime, 1);
+ mpi_set_ui (g, 2);
+ do
+ {
+ mpi_add_ui (g, g, 1);
+ if (DBG_CIPHER)
+ {
+ log_debug ("checking g:");
+ gcry_mpi_dump (g);
+ log_printf ("\n");
+ }
+ else
+ progress('^');
+ for (i = 0; i < n + 2; i++)
+ {
+ mpi_fdiv_q (tmp, pmin1, factors[i]);
+ /* No mpi_pow(), but it is okay to use this with mod
+ prime. */
+ gcry_mpi_powm (b, g, tmp, prime);
+ if (! mpi_cmp_ui (b, 1))
+ break;
+ }
+ if (DBG_CIPHER)
+ progress('\n');
+ }
+ while (i < n + 2);
+
+ mpi_free (factors[n+1]);
+ mpi_free (tmp);
+ mpi_free (b);
+ mpi_free (pmin1);
+ }
+ }
+
+ if (! DBG_CIPHER)
+ progress ('\n');
+
+
+ leave:
+ if (pool)
+ {
+ is_locked = !ath_mutex_lock (&primepool_lock);
+ for(i = 0; i < m; i++)
+ {
+ if (pool[i])
+ {
+ for (j=0; j < n; j++)
+ if (pool_in_use[j] == i)
+ break;
+ if (j == n && is_locked)
+ {
+ /* This pooled subprime has not been used. */
+ save_pool_prime (pool[i], poolrandomlevel);
+ }
+ else
+ mpi_free (pool[i]);
+ }
+ }
+ if (is_locked && ath_mutex_unlock (&primepool_lock))
+ err = GPG_ERR_INTERNAL;
+ is_locked = 0;
+ gcry_free (pool);
+ }
+ gcry_free (pool_in_use);
+ if (factors)
+ gcry_free (factors); /* Factors are shallow copies. */
+ if (perms)
+ gcry_free (perms);
+
+ mpi_free (val_2);
+ mpi_free (q);
+ mpi_free (q_factor);
+
+ if (! err)
+ {
+ *prime_generated = prime;
+ if (ret_factors)
+ *ret_factors = factors_new;
+ }
+ else
+ {
+ if (factors_new)
+ {
+ for (i = 0; factors_new[i]; i++)
+ mpi_free (factors_new[i]);
+ gcry_free (factors_new);
+ }
+ mpi_free (prime);
+ }
+
+ return err;
+}
+
+
+/* Generate a prime used for discrete logarithm algorithms; i.e. this
+ prime will be public and no strong random is required. */
+gcry_mpi_t
+_gcry_generate_elg_prime (int mode, unsigned pbits, unsigned qbits,
+ gcry_mpi_t g, gcry_mpi_t **ret_factors)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_mpi_t prime = NULL;
+
+ err = prime_generate_internal ((mode == 1), &prime, pbits, qbits, g,
+ ret_factors, GCRY_WEAK_RANDOM, 0, 0,
+ NULL, NULL);
+
+ return prime;
+}
+
+
+static gcry_mpi_t
+gen_prime (unsigned int nbits, int secret, int randomlevel,
+ int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg)
+{
+ gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result;
+ int i;
+ unsigned int x, step;
+ unsigned int count1, count2;
+ int *mods;
+
+/* if ( DBG_CIPHER ) */
+/* log_debug ("generate a prime of %u bits ", nbits ); */
+
+ if (nbits < 16)
+ log_fatal ("can't generate a prime with less than %d bits\n", 16);
+
+ mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods );
+ /* Make nbits fit into gcry_mpi_t implementation. */
+ val_2 = mpi_alloc_set_ui( 2 );
+ val_3 = mpi_alloc_set_ui( 3);
+ prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits );
+ result = mpi_alloc_like( prime );
+ pminus1= mpi_alloc_like( prime );
+ ptest = mpi_alloc_like( prime );
+ count1 = count2 = 0;
+ for (;;)
+ { /* try forvever */
+ int dotcount=0;
+
+ /* generate a random number */
+ gcry_mpi_randomize( prime, nbits, randomlevel );
+
+ /* Set high order bit to 1, set low order bit to 1. If we are
+ generating a secret prime we are most probably doing that
+ for RSA, to make sure that the modulus does have the
+ requested key size we set the 2 high order bits. */
+ mpi_set_highbit (prime, nbits-1);
+ if (secret)
+ mpi_set_bit (prime, nbits-2);
+ mpi_set_bit(prime, 0);
+
+ /* Calculate all remainders. */
+ for (i=0; (x = small_prime_numbers[i]); i++ )
+ mods[i] = mpi_fdiv_r_ui(NULL, prime, x);
+
+ /* Now try some primes starting with prime. */
+ for(step=0; step < 20000; step += 2 )
+ {
+ /* Check against all the small primes we have in mods. */
+ count1++;
+ for (i=0; (x = small_prime_numbers[i]); i++ )
+ {
+ while ( mods[i] + step >= x )
+ mods[i] -= x;
+ if ( !(mods[i] + step) )
+ break;
+ }
+ if ( x )
+ continue; /* Found a multiple of an already known prime. */
+
+ mpi_add_ui( ptest, prime, step );
+
+ /* Do a fast Fermat test now. */
+ count2++;
+ mpi_sub_ui( pminus1, ptest, 1);
+ gcry_mpi_powm( result, val_2, pminus1, ptest );
+ if ( !mpi_cmp_ui( result, 1 ) )
+ {
+ /* Not composite, perform stronger tests */
+ if (is_prime(ptest, 5, &count2 ))
+ {
+ if (!mpi_test_bit( ptest, nbits-1-secret ))
+ {
+ progress('\n');
+ log_debug ("overflow in prime generation\n");
+ break; /* Stop loop, continue with a new prime. */
+ }
+
+ if (extra_check && extra_check (extra_check_arg, ptest))
+ {
+ /* The extra check told us that this prime is
+ not of the caller's taste. */
+ progress ('/');
+ }
+ else
+ {
+ /* Got it. */
+ mpi_free(val_2);
+ mpi_free(val_3);
+ mpi_free(result);
+ mpi_free(pminus1);
+ mpi_free(prime);
+ gcry_free(mods);
+ return ptest;
+ }
+ }
+ }
+ if (++dotcount == 10 )
+ {
+ progress('.');
+ dotcount = 0;
+ }
+ }
+ progress(':'); /* restart with a new random value */
+ }
+}
+
+/****************
+ * Returns: true if this may be a prime
+ * RM_ROUNDS gives the number of Rabin-Miller tests to run.
+ */
+static int
+check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds,
+ gcry_prime_check_func_t cb_func, void *cb_arg)
+{
+ int i;
+ unsigned int x;
+ unsigned int count=0;
+
+ /* Check against small primes. */
+ for (i=0; (x = small_prime_numbers[i]); i++ )
+ {
+ if ( mpi_divisible_ui( prime, x ) )
+ return 0;
+ }
+
+ /* A quick Fermat test. */
+ {
+ gcry_mpi_t result = mpi_alloc_like( prime );
+ gcry_mpi_t pminus1 = mpi_alloc_like( prime );
+ mpi_sub_ui( pminus1, prime, 1);
+ gcry_mpi_powm( result, val_2, pminus1, prime );
+ mpi_free( pminus1 );
+ if ( mpi_cmp_ui( result, 1 ) )
+ {
+ /* Is composite. */
+ mpi_free( result );
+ progress('.');
+ return 0;
+ }
+ mpi_free( result );
+ }
+
+ if (!cb_func || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_MAYBE_PRIME, prime))
+ {
+ /* Perform stronger tests. */
+ if ( is_prime( prime, rm_rounds, &count ) )
+ {
+ if (!cb_func
+ || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_GOT_PRIME, prime))
+ return 1; /* Probably a prime. */
+ }
+ }
+ progress('.');
+ return 0;
+}
+
+
+/*
+ * Return true if n is probably a prime
+ */
+static int
+is_prime (gcry_mpi_t n, int steps, unsigned int *count)
+{
+ gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs( n ) );
+ gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs( n ) );
+ gcry_mpi_t z = mpi_alloc( mpi_get_nlimbs( n ) );
+ gcry_mpi_t nminus1 = mpi_alloc( mpi_get_nlimbs( n ) );
+ gcry_mpi_t a2 = mpi_alloc_set_ui( 2 );
+ gcry_mpi_t q;
+ unsigned i, j, k;
+ int rc = 0;
+ unsigned nbits = mpi_get_nbits( n );
+
+ if (steps < 5) /* Make sure that we do at least 5 rounds. */
+ steps = 5;
+
+ mpi_sub_ui( nminus1, n, 1 );
+
+ /* Find q and k, so that n = 1 + 2^k * q . */
+ q = mpi_copy ( nminus1 );
+ k = mpi_trailing_zeros ( q );
+ mpi_tdiv_q_2exp (q, q, k);
+
+ for (i=0 ; i < steps; i++ )
+ {
+ ++*count;
+ if( !i )
+ {
+ mpi_set_ui( x, 2 );
+ }
+ else
+ {
+ gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM );
+
+ /* Make sure that the number is smaller than the prime and
+ keep the randomness of the high bit. */
+ if ( mpi_test_bit ( x, nbits-2) )
+ {
+ mpi_set_highbit ( x, nbits-2); /* Clear all higher bits. */
+ }
+ else
+ {
+ mpi_set_highbit( x, nbits-2 );
+ mpi_clear_bit( x, nbits-2 );
+ }
+ gcry_assert (mpi_cmp (x, nminus1) < 0 && mpi_cmp_ui (x, 1) > 0);
+ }
+ gcry_mpi_powm ( y, x, q, n);
+ if ( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) )
+ {
+ for ( j=1; j < k && mpi_cmp( y, nminus1 ); j++ )
+ {
+ gcry_mpi_powm(y, y, a2, n);
+ if( !mpi_cmp_ui( y, 1 ) )
+ goto leave; /* Not a prime. */
+ }
+ if (mpi_cmp( y, nminus1 ) )
+ goto leave; /* Not a prime. */
+ }
+ progress('+');
+ }
+ rc = 1; /* May be a prime. */
+
+ leave:
+ mpi_free( x );
+ mpi_free( y );
+ mpi_free( z );
+ mpi_free( nminus1 );
+ mpi_free( q );
+ mpi_free( a2 );
+
+ return rc;
+}
+
+
+/* Given ARRAY of size N with M elements set to true produce a
+ modified array with the next permutation of M elements. Note, that
+ ARRAY is used in a one-bit-per-byte approach. To detected the last
+ permutation it is useful to initialize the array with the first M
+ element set to true and use this test:
+ m_out_of_n (array, m, n);
+ for (i = j = 0; i < n && j < m; i++)
+ if (array[i])
+ j++;
+ if (j == m)
+ goto ready;
+
+ This code is based on the algorithm 452 from the "Collected
+ Algorithms From ACM, Volume II" by C. N. Liu and D. T. Tang.
+*/
+static void
+m_out_of_n ( char *array, int m, int n )
+{
+ int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0;
+
+ if( !m || m >= n )
+ return;
+
+ /* Need to handle this simple case separately. */
+ if( m == 1 )
+ {
+ for (i=0; i < n; i++ )
+ {
+ if ( array[i] )
+ {
+ array[i++] = 0;
+ if( i >= n )
+ i = 0;
+ array[i] = 1;
+ return;
+ }
+ }
+ BUG();
+ }
+
+
+ for (j=1; j < n; j++ )
+ {
+ if ( array[n-1] == array[n-j-1])
+ continue;
+ j1 = j;
+ break;
+ }
+
+ if ( (m & 1) )
+ {
+ /* M is odd. */
+ if( array[n-1] )
+ {
+ if( j1 & 1 )
+ {
+ k1 = n - j1;
+ k2 = k1+2;
+ if( k2 > n )
+ k2 = n;
+ goto leave;
+ }
+ goto scan;
+ }
+ k2 = n - j1 - 1;
+ if( k2 == 0 )
+ {
+ k1 = i;
+ k2 = n - j1;
+ }
+ else if( array[k2] && array[k2-1] )
+ k1 = n;
+ else
+ k1 = k2 + 1;
+ }
+ else
+ {
+ /* M is even. */
+ if( !array[n-1] )
+ {
+ k1 = n - j1;
+ k2 = k1 + 1;
+ goto leave;
+ }
+
+ if( !(j1 & 1) )
+ {
+ k1 = n - j1;
+ k2 = k1+2;
+ if( k2 > n )
+ k2 = n;
+ goto leave;
+ }
+ scan:
+ jp = n - j1 - 1;
+ for (i=1; i <= jp; i++ )
+ {
+ i1 = jp + 2 - i;
+ if( array[i1-1] )
+ {
+ if( array[i1-2] )
+ {
+ k1 = i1 - 1;
+ k2 = n - j1;
+ }
+ else
+ {
+ k1 = i1 - 1;
+ k2 = n + 1 - j1;
+ }
+ goto leave;
+ }
+ }
+ k1 = 1;
+ k2 = n + 1 - m;
+ }
+ leave:
+ /* Now complement the two selected bits. */
+ array[k1-1] = !array[k1-1];
+ array[k2-1] = !array[k2-1];
+}
+
+
+/* Generate a new prime number of PRIME_BITS bits and store it in
+ PRIME. If FACTOR_BITS is non-zero, one of the prime factors of
+ (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is
+ non-zero, allocate a new, NULL-terminated array holding the prime
+ factors and store it in FACTORS. FLAGS might be used to influence
+ the prime number generation process. */
+gcry_error_t
+gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits,
+ unsigned int factor_bits, gcry_mpi_t **factors,
+ gcry_prime_check_func_t cb_func, void *cb_arg,
+ gcry_random_level_t random_level,
+ unsigned int flags)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_mpi_t *factors_generated = NULL;
+ gcry_mpi_t prime_generated = NULL;
+ unsigned int mode = 0;
+
+ if (!prime)
+ return gpg_error (GPG_ERR_INV_ARG);
+ *prime = NULL;
+
+ if (flags & GCRY_PRIME_FLAG_SPECIAL_FACTOR)
+ mode = 1;
+
+ /* Generate. */
+ err = prime_generate_internal ((mode==1), &prime_generated, prime_bits,
+ factor_bits, NULL,
+ factors? &factors_generated : NULL,
+ random_level, flags, 1,
+ cb_func, cb_arg);
+
+ if (! err)
+ if (cb_func)
+ {
+ /* Additional check. */
+ if ( !cb_func (cb_arg, GCRY_PRIME_CHECK_AT_FINISH, prime_generated))
+ {
+ /* Failed, deallocate resources. */
+ unsigned int i;
+
+ mpi_free (prime_generated);
+ if (factors)
+ {
+ for (i = 0; factors_generated[i]; i++)
+ mpi_free (factors_generated[i]);
+ gcry_free (factors_generated);
+ }
+ err = GPG_ERR_GENERAL;
+ }
+ }
+
+ if (! err)
+ {
+ if (factors)
+ *factors = factors_generated;
+ *prime = prime_generated;
+ }
+
+ return gcry_error (err);
+}
+
+/* Check whether the number X is prime. */
+gcry_error_t
+gcry_prime_check (gcry_mpi_t x, unsigned int flags)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */
+
+ (void)flags;
+
+ /* We use 64 rounds because the prime we are going to test is not
+ guaranteed to be a random one. */
+ if (! check_prime (x, val_2, 64, NULL, NULL))
+ err = GPG_ERR_NO_PRIME;
+
+ mpi_free (val_2);
+
+ return gcry_error (err);
+}
+
+/* Find a generator for PRIME where the factorization of (prime-1) is
+ in the NULL terminated array FACTORS. Return the generator as a
+ newly allocated MPI in R_G. If START_G is not NULL, use this as s
+ atart for the search. Returns 0 on success.*/
+gcry_error_t
+gcry_prime_group_generator (gcry_mpi_t *r_g,
+ gcry_mpi_t prime, gcry_mpi_t *factors,
+ gcry_mpi_t start_g)
+{
+ gcry_mpi_t tmp = gcry_mpi_new (0);
+ gcry_mpi_t b = gcry_mpi_new (0);
+ gcry_mpi_t pmin1 = gcry_mpi_new (0);
+ gcry_mpi_t g = start_g? gcry_mpi_copy (start_g) : gcry_mpi_set_ui (NULL, 3);
+ int first = 1;
+ int i, n;
+
+ if (!factors || !r_g || !prime)
+ return gpg_error (GPG_ERR_INV_ARG);
+ *r_g = NULL;
+
+ for (n=0; factors[n]; n++)
+ ;
+ if (n < 2)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ /* Extra sanity check - usually disabled. */
+/* mpi_set (tmp, factors[0]); */
+/* for(i = 1; i < n; i++) */
+/* mpi_mul (tmp, tmp, factors[i]); */
+/* mpi_add_ui (tmp, tmp, 1); */
+/* if (mpi_cmp (prime, tmp)) */
+/* return gpg_error (GPG_ERR_INV_ARG); */
+
+ gcry_mpi_sub_ui (pmin1, prime, 1);
+ do
+ {
+ if (first)
+ first = 0;
+ else
+ gcry_mpi_add_ui (g, g, 1);
+
+ if (DBG_CIPHER)
+ {
+ log_debug ("checking g:");
+ gcry_mpi_dump (g);
+ log_debug ("\n");
+ }
+ else
+ progress('^');
+
+ for (i = 0; i < n; i++)
+ {
+ mpi_fdiv_q (tmp, pmin1, factors[i]);
+ gcry_mpi_powm (b, g, tmp, prime);
+ if (! mpi_cmp_ui (b, 1))
+ break;
+ }
+ if (DBG_CIPHER)
+ progress('\n');
+ }
+ while (i < n);
+
+ gcry_mpi_release (tmp);
+ gcry_mpi_release (b);
+ gcry_mpi_release (pmin1);
+ *r_g = g;
+
+ return 0;
+}
+
+/* Convenience function to release the factors array. */
+void
+gcry_prime_release_factors (gcry_mpi_t *factors)
+{
+ if (factors)
+ {
+ int i;
+
+ for (i=0; factors[i]; i++)
+ mpi_free (factors[i]);
+ gcry_free (factors);
+ }
+}
+
+
+
+/* Helper for _gcry_derive_x931_prime. */
+static gcry_mpi_t
+find_x931_prime (const gcry_mpi_t pfirst)
+{
+ gcry_mpi_t val_2 = mpi_alloc_set_ui (2);
+ gcry_mpi_t prime;
+
+ prime = gcry_mpi_copy (pfirst);
+ /* If P is even add 1. */
+ mpi_set_bit (prime, 0);
+
+ /* We use 64 Rabin-Miller rounds which is better and thus
+ sufficient. We do not have a Lucas test implementaion thus we
+ can't do it in the X9.31 preferred way of running a few
+ Rabin-Miller followed by one Lucas test. */
+ while ( !check_prime (prime, val_2, 64, NULL, NULL) )
+ mpi_add_ui (prime, prime, 2);
+
+ mpi_free (val_2);
+
+ return prime;
+}
+
+
+/* Generate a prime using the algorithm from X9.31 appendix B.4.
+
+ This function requires that the provided public exponent E is odd.
+ XP, XP1 and XP2 are the seed values. All values are mandatory.
+
+ On success the prime is returned. If R_P1 or R_P2 are given the
+ internal values P1 and P2 are saved at these addresses. On error
+ NULL is returned. */
+gcry_mpi_t
+_gcry_derive_x931_prime (const gcry_mpi_t xp,
+ const gcry_mpi_t xp1, const gcry_mpi_t xp2,
+ const gcry_mpi_t e,
+ gcry_mpi_t *r_p1, gcry_mpi_t *r_p2)
+{
+ gcry_mpi_t p1, p2, p1p2, yp0;
+
+ if (!xp || !xp1 || !xp2)
+ return NULL;
+ if (!e || !mpi_test_bit (e, 0))
+ return NULL; /* We support only odd values for E. */
+
+ p1 = find_x931_prime (xp1);
+ p2 = find_x931_prime (xp2);
+ p1p2 = mpi_alloc_like (xp);
+ mpi_mul (p1p2, p1, p2);
+
+ {
+ gcry_mpi_t r1, tmp;
+
+ /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */
+ tmp = mpi_alloc_like (p1);
+ mpi_invm (tmp, p2, p1);
+ mpi_mul (tmp, tmp, p2);
+ r1 = tmp;
+
+ tmp = mpi_alloc_like (p2);
+ mpi_invm (tmp, p1, p2);
+ mpi_mul (tmp, tmp, p1);
+ mpi_sub (r1, r1, tmp);
+
+ /* Fixup a negative value. */
+ if (mpi_is_neg (r1))
+ mpi_add (r1, r1, p1p2);
+
+ /* yp0 = xp + (r1 - xp mod p1*p2) */
+ yp0 = tmp; tmp = NULL;
+ mpi_subm (yp0, r1, xp, p1p2);
+ mpi_add (yp0, yp0, xp);
+ mpi_free (r1);
+
+ /* Fixup a negative value. */
+ if (mpi_cmp (yp0, xp) < 0 )
+ mpi_add (yp0, yp0, p1p2);
+ }
+
+ /* yp0 is now the first integer greater than xp with p1 being a
+ large prime factor of yp0-1 and p2 a large prime factor of yp0+1. */
+
+ /* Note that the first example from X9.31 (D.1.1) which uses
+ (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)
+ (Xq2 #134E4CAA16D2350A21D775C404#)
+ (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+ 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325
+ 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34
+ 321DE34A#))))
+ returns an yp0 of
+ #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+ 7C9953388F97DDDC3E1CA19C35CA659EDC2FC4E3
+ BF20CB896EE37E098A906313271422162CB6C642
+ 75C1201F#
+ and not
+ #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+ 7C9953388F97DDDC3E1CA19C35CA659EDC2FC2E6
+ C88FE299D52D78BE405A97E01FD71DD7819ECB91
+ FA85A076#
+ as stated in the standard. This seems to be a bug in X9.31.
+ */
+
+ {
+ gcry_mpi_t val_2 = mpi_alloc_set_ui (2);
+ gcry_mpi_t gcdtmp = mpi_alloc_like (yp0);
+ int gcdres;
+
+ mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body. */
+ mpi_sub_ui (yp0, yp0, 1); /* Ditto. */
+ for (;;)
+ {
+ gcdres = gcry_mpi_gcd (gcdtmp, e, yp0);
+ mpi_add_ui (yp0, yp0, 1);
+ if (!gcdres)
+ progress ('/'); /* gcd (e, yp0-1) != 1 */
+ else if (check_prime (yp0, val_2, 64, NULL, NULL))
+ break; /* Found. */
+ /* We add p1p2-1 because yp0 is incremented after the gcd test. */
+ mpi_add (yp0, yp0, p1p2);
+ }
+ mpi_free (gcdtmp);
+ mpi_free (val_2);
+ }
+
+ mpi_free (p1p2);
+
+ progress('\n');
+ if (r_p1)
+ *r_p1 = p1;
+ else
+ mpi_free (p1);
+ if (r_p2)
+ *r_p2 = p2;
+ else
+ mpi_free (p2);
+ return yp0;
+}
+
+
+
+/* Generate the two prime used for DSA using the algorithm specified
+ in FIPS 186-2. PBITS is the desired length of the prime P and a
+ QBITS the length of the prime Q. If SEED is not supplied and
+ SEEDLEN is 0 the function generates an appropriate SEED. On
+ success the generated primes are stored at R_Q and R_P, the counter
+ value is stored at R_COUNTER and the seed actually used for
+ generation is stored at R_SEED and R_SEEDVALUE. */
+gpg_err_code_t
+_gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits,
+ const void *seed, size_t seedlen,
+ gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+ int *r_counter,
+ void **r_seed, size_t *r_seedlen)
+{
+ gpg_err_code_t ec;
+ unsigned char seed_help_buffer[160/8]; /* Used to hold a generated SEED. */
+ unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */
+ unsigned char digest[160/8]; /* Helper buffer for SHA-1 digest. */
+ gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */
+ gcry_mpi_t tmpval = NULL; /* Helper variable. */
+ int i;
+
+ unsigned char value_u[160/8];
+ int value_n, value_b, value_k;
+ int counter;
+ gcry_mpi_t value_w = NULL;
+ gcry_mpi_t value_x = NULL;
+ gcry_mpi_t prime_q = NULL;
+ gcry_mpi_t prime_p = NULL;
+
+ /* FIPS 186-2 allows only for 1024/160 bit. */
+ if (pbits != 1024 || qbits != 160)
+ return GPG_ERR_INV_KEYLEN;
+
+ if (!seed && !seedlen)
+ ; /* No seed value given: We are asked to generate it. */
+ else if (!seed || seedlen < qbits/8)
+ return GPG_ERR_INV_ARG;
+
+ /* Allocate a buffer to later compute SEED+some_increment. */
+ seed_plus = gcry_malloc (seedlen < 20? 20:seedlen);
+ if (!seed_plus)
+ {
+ ec = gpg_err_code_from_syserror ();
+ goto leave;
+ }
+
+ val_2 = mpi_alloc_set_ui (2);
+ value_n = (pbits - 1) / qbits;
+ value_b = (pbits - 1) - value_n * qbits;
+ value_w = gcry_mpi_new (pbits);
+ value_x = gcry_mpi_new (pbits);
+
+ restart:
+ /* Generate Q. */
+ for (;;)
+ {
+ /* Step 1: Generate a (new) seed unless one has been supplied. */
+ if (!seed)
+ {
+ seedlen = sizeof seed_help_buffer;
+ gcry_create_nonce (seed_help_buffer, seedlen);
+ seed = seed_help_buffer;
+ }
+
+ /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */
+ memcpy (seed_plus, seed, seedlen);
+ for (i=seedlen-1; i >= 0; i--)
+ {
+ seed_plus[i]++;
+ if (seed_plus[i])
+ break;
+ }
+ gcry_md_hash_buffer (GCRY_MD_SHA1, value_u, seed, seedlen);
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+ for (i=0; i < sizeof value_u; i++)
+ value_u[i] ^= digest[i];
+
+ /* Step 3: Form q from U */
+ gcry_mpi_release (prime_q); prime_q = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
+ value_u, sizeof value_u, NULL));
+ if (ec)
+ goto leave;
+ mpi_set_highbit (prime_q, qbits-1 );
+ mpi_set_bit (prime_q, 0);
+
+ /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */
+ if (check_prime (prime_q, val_2, 64, NULL, NULL))
+ break; /* Yes, Q is prime. */
+
+ /* Step 5. */
+ seed = NULL; /* Force a new seed at Step 1. */
+ }
+
+ /* Step 6. Note that we do no use an explicit offset but increment
+ SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */
+ counter = 0;
+
+ /* Generate P. */
+ prime_p = gcry_mpi_new (pbits);
+ for (;;)
+ {
+ /* Step 7: For k = 0,...n let
+ V_k = sha1(seed+offset+k) mod 2^{qbits}
+ Step 8: W = V_0 + V_1*2^160 +
+ ...
+ + V_{n-1}*2^{(n-1)*160}
+ + (V_{n} mod 2^b)*2^{n*160}
+ */
+ mpi_set_ui (value_w, 0);
+ for (value_k=0; value_k <= value_n; value_k++)
+ {
+ /* There is no need to have an explicit offset variable: In
+ the first round we shall have an offset of 2, this is
+ achieved by using SEED_PLUS which is already at SEED+1,
+ thus we just need to increment it once again. The
+ requirement for the next round is to update offset by N,
+ which we implictly did at the end of this loop, and then
+ to add one; this one is the same as in the first round. */
+ for (i=seedlen-1; i >= 0; i--)
+ {
+ seed_plus[i]++;
+ if (seed_plus[i])
+ break;
+ }
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+
+ gcry_mpi_release (tmpval); tmpval = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
+ digest, sizeof digest, NULL));
+ if (ec)
+ goto leave;
+ if (value_k == value_n)
+ mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */
+ mpi_lshift (tmpval, tmpval, value_k*qbits);
+ mpi_add (value_w, value_w, tmpval);
+ }
+
+ /* Step 8 continued: X = W + 2^{L-1} */
+ mpi_set_ui (value_x, 0);
+ mpi_set_highbit (value_x, pbits-1);
+ mpi_add (value_x, value_x, value_w);
+
+ /* Step 9: c = X mod 2q, p = X - (c - 1) */
+ mpi_mul_2exp (tmpval, prime_q, 1);
+ mpi_mod (tmpval, value_x, tmpval);
+ mpi_sub_ui (tmpval, tmpval, 1);
+ mpi_sub (prime_p, value_x, tmpval);
+
+ /* Step 10: If p < 2^{L-1} skip the primality test. */
+ /* Step 11 and 12: Primality test. */
+ if (mpi_get_nbits (prime_p) >= pbits-1
+ && check_prime (prime_p, val_2, 64, NULL, NULL) )
+ break; /* Yes, P is prime, continue with Step 15. */
+
+ /* Step 13: counter = counter + 1, offset = offset + n + 1. */
+ counter++;
+
+ /* Step 14: If counter >= 2^12 goto Step 1. */
+ if (counter >= 4096)
+ goto restart;
+ }
+
+ /* Step 15: Save p, q, counter and seed. */
+/* log_debug ("fips186-2 pbits p=%u q=%u counter=%d\n", */
+/* mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */
+/* log_printhex("fips186-2 seed:", seed, seedlen); */
+/* log_mpidump ("fips186-2 prime p", prime_p); */
+/* log_mpidump ("fips186-2 prime q", prime_q); */
+ if (r_q)
+ {
+ *r_q = prime_q;
+ prime_q = NULL;
+ }
+ if (r_p)
+ {
+ *r_p = prime_p;
+ prime_p = NULL;
+ }
+ if (r_counter)
+ *r_counter = counter;
+ if (r_seed && r_seedlen)
+ {
+ memcpy (seed_plus, seed, seedlen);
+ *r_seed = seed_plus;
+ seed_plus = NULL;
+ *r_seedlen = seedlen;
+ }
+
+
+ leave:
+ gcry_mpi_release (tmpval);
+ gcry_mpi_release (value_x);
+ gcry_mpi_release (value_w);
+ gcry_mpi_release (prime_p);
+ gcry_mpi_release (prime_q);
+ gcry_free (seed_plus);
+ gcry_mpi_release (val_2);
+ return ec;
+}
+
+
+
+/* WARNING: The code below has not yet been tested! However, it is
+ not yet used. We need to wait for FIPS 186-3 final and for test
+ vectors.
+
+ Generate the two prime used for DSA using the algorithm specified
+ in FIPS 186-3, A.1.1.2. PBITS is the desired length of the prime P
+ and a QBITS the length of the prime Q. If SEED is not supplied and
+ SEEDLEN is 0 the function generates an appropriate SEED. On
+ success the generated primes are stored at R_Q and R_P, the counter
+ value is stored at R_COUNTER and the seed actually used for
+ generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm
+ used is stored at R_HASHALGO.
+
+ Note that this function is very similar to the fips186_2 code. Due
+ to the minor differences, other buffer sizes and for documentarion,
+ we use a separate function.
+*/
+gpg_err_code_t
+_gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
+ const void *seed, size_t seedlen,
+ gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+ int *r_counter,
+ void **r_seed, size_t *r_seedlen,
+ int *r_hashalgo)
+{
+ gpg_err_code_t ec;
+ unsigned char seed_help_buffer[256/8]; /* Used to hold a generated SEED. */
+ unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */
+ unsigned char digest[256/8]; /* Helper buffer for SHA-1 digest. */
+ gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */
+ gcry_mpi_t tmpval = NULL; /* Helper variable. */
+ int hashalgo; /* The id of the Approved Hash Function. */
+ int i;
+
+ unsigned char value_u[256/8];
+ int value_n, value_b, value_j;
+ int counter;
+ gcry_mpi_t value_w = NULL;
+ gcry_mpi_t value_x = NULL;
+ gcry_mpi_t prime_q = NULL;
+ gcry_mpi_t prime_p = NULL;
+
+ gcry_assert (sizeof seed_help_buffer == sizeof digest
+ && sizeof seed_help_buffer == sizeof value_u);
+
+ /* Step 1: Check the requested prime lengths. */
+ /* Note that due to the size of our buffers QBITS is limited to 256. */
+ if (pbits == 1024 && qbits == 160)
+ hashalgo = GCRY_MD_SHA1;
+ else if (pbits == 2048 && qbits == 224)
+ hashalgo = GCRY_MD_SHA224;
+ else if (pbits == 2048 && qbits == 256)
+ hashalgo = GCRY_MD_SHA256;
+ else if (pbits == 3072 && qbits == 256)
+ hashalgo = GCRY_MD_SHA256;
+ else
+ return GPG_ERR_INV_KEYLEN;
+
+ /* Also check that the hash algorithm is available. */
+ ec = gpg_err_code (gcry_md_test_algo (hashalgo));
+ if (ec)
+ return ec;
+ gcry_assert (qbits/8 <= sizeof digest);
+ gcry_assert (gcry_md_get_algo_dlen (hashalgo) == qbits/8);
+
+
+ /* Step 2: Check seedlen. */
+ if (!seed && !seedlen)
+ ; /* No seed value given: We are asked to generate it. */
+ else if (!seed || seedlen < qbits/8)
+ return GPG_ERR_INV_ARG;
+
+ /* Allocate a buffer to later compute SEED+some_increment and a few
+ helper variables. */
+ seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer?
+ sizeof seed_help_buffer : seedlen);
+ if (!seed_plus)
+ {
+ ec = gpg_err_code_from_syserror ();
+ goto leave;
+ }
+ val_2 = mpi_alloc_set_ui (2);
+ value_w = gcry_mpi_new (pbits);
+ value_x = gcry_mpi_new (pbits);
+
+ /* Step 3: n = \lceil L / outlen \rceil - 1 */
+ value_n = (pbits + qbits - 1) / qbits - 1;
+ /* Step 4: b = L - 1 - (n * outlen) */
+ value_b = pbits - 1 - (value_n * qbits);
+
+ restart:
+ /* Generate Q. */
+ for (;;)
+ {
+ /* Step 5: Generate a (new) seed unless one has been supplied. */
+ if (!seed)
+ {
+ seedlen = qbits/8;
+ gcry_assert (seedlen <= sizeof seed_help_buffer);
+ gcry_create_nonce (seed_help_buffer, seedlen);
+ seed = seed_help_buffer;
+ }
+
+ /* Step 6: U = hash(seed) */
+ gcry_md_hash_buffer (hashalgo, value_u, seed, seedlen);
+
+ /* Step 7: q = 2^{N-1} + U + 1 - (U mod 2) */
+ if ( !(value_u[qbits/8-1] & 0x01) )
+ {
+ for (i=qbits/8-1; i >= 0; i--)
+ {
+ value_u[i]++;
+ if (value_u[i])
+ break;
+ }
+ }
+ gcry_mpi_release (prime_q); prime_q = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
+ value_u, sizeof value_u, NULL));
+ if (ec)
+ goto leave;
+ mpi_set_highbit (prime_q, qbits-1 );
+
+ /* Step 8: Test whether Q is prime using 64 round of Rabin-Miller.
+ According to table C.1 this is sufficient for all
+ supported prime sizes (i.e. up 3072/256). */
+ if (check_prime (prime_q, val_2, 64, NULL, NULL))
+ break; /* Yes, Q is prime. */
+
+ /* Step 8. */
+ seed = NULL; /* Force a new seed at Step 5. */
+ }
+
+ /* Step 11. Note that we do no use an explicit offset but increment
+ SEED_PLUS accordingly. */
+ memcpy (seed_plus, seed, seedlen);
+ counter = 0;
+
+ /* Generate P. */
+ prime_p = gcry_mpi_new (pbits);
+ for (;;)
+ {
+ /* Step 11.1: For j = 0,...n let
+ V_j = hash(seed+offset+j)
+ Step 11.2: W = V_0 + V_1*2^outlen +
+ ...
+ + V_{n-1}*2^{(n-1)*outlen}
+ + (V_{n} mod 2^b)*2^{n*outlen}
+ */
+ mpi_set_ui (value_w, 0);
+ for (value_j=0; value_j <= value_n; value_j++)
+ {
+ /* There is no need to have an explicit offset variable: In
+ the first round we shall have an offset of 1 and a j of
+ 0. This is achieved by incrementing SEED_PLUS here. For
+ the next round offset is implicitly updated by using
+ SEED_PLUS again. */
+ for (i=seedlen-1; i >= 0; i--)
+ {
+ seed_plus[i]++;
+ if (seed_plus[i])
+ break;
+ }
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+
+ gcry_mpi_release (tmpval); tmpval = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
+ digest, sizeof digest, NULL));
+ if (ec)
+ goto leave;
+ if (value_j == value_n)
+ mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */
+ mpi_lshift (tmpval, tmpval, value_j*qbits);
+ mpi_add (value_w, value_w, tmpval);
+ }
+
+ /* Step 11.3: X = W + 2^{L-1} */
+ mpi_set_ui (value_x, 0);
+ mpi_set_highbit (value_x, pbits-1);
+ mpi_add (value_x, value_x, value_w);
+
+ /* Step 11.4: c = X mod 2q */
+ mpi_mul_2exp (tmpval, prime_q, 1);
+ mpi_mod (tmpval, value_x, tmpval);
+
+ /* Step 11.5: p = X - (c - 1) */
+ mpi_sub_ui (tmpval, tmpval, 1);
+ mpi_sub (prime_p, value_x, tmpval);
+
+ /* Step 11.6: If p < 2^{L-1} skip the primality test. */
+ /* Step 11.7 and 11.8: Primality test. */
+ if (mpi_get_nbits (prime_p) >= pbits-1
+ && check_prime (prime_p, val_2, 64, NULL, NULL) )
+ break; /* Yes, P is prime, continue with Step 15. */
+
+ /* Step 11.9: counter = counter + 1, offset = offset + n + 1.
+ If counter >= 4L goto Step 5. */
+ counter++;
+ if (counter >= 4*pbits)
+ goto restart;
+ }
+
+ /* Step 12: Save p, q, counter and seed. */
+ log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n",
+ mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter);
+ log_printhex("fips186-3 seed:", seed, seedlen);
+ log_mpidump ("fips186-3 prime p", prime_p);
+ log_mpidump ("fips186-3 prime q", prime_q);
+ if (r_q)
+ {
+ *r_q = prime_q;
+ prime_q = NULL;
+ }
+ if (r_p)
+ {
+ *r_p = prime_p;
+ prime_p = NULL;
+ }
+ if (r_counter)
+ *r_counter = counter;
+ if (r_seed && r_seedlen)
+ {
+ memcpy (seed_plus, seed, seedlen);
+ *r_seed = seed_plus;
+ seed_plus = NULL;
+ *r_seedlen = seedlen;
+ }
+ if (r_hashalgo)
+ *r_hashalgo = hashalgo;
+
+ leave:
+ gcry_mpi_release (tmpval);
+ gcry_mpi_release (value_x);
+ gcry_mpi_release (value_w);
+ gcry_mpi_release (prime_p);
+ gcry_mpi_release (prime_q);
+ gcry_free (seed_plus);
+ gcry_mpi_release (val_2);
+ return ec;
+}
+
diff --git a/libgcrypt-1.4.6/cipher/pubkey.c b/libgcrypt-1.4.6/cipher/pubkey.c
index 08abcbf..28d18f9 100644
--- a/libgcrypt-1.4.6/cipher/pubkey.c
+++ b/libgcrypt-1.4.6/cipher/pubkey.c
@@ -1,2749 +1,2749 @@
-/* pubkey.c - pubkey dispatcher
- * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
- * 2007, 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "g10lib.h"
-#include "mpi.h"
-#include "cipher.h"
-#include "ath.h"
-
-
-static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
- gcry_mpi_t *data, gcry_mpi_t *skey,
- int flags);
-static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
- gcry_mpi_t hash, gcry_mpi_t *skey);
-static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
- gcry_mpi_t *data, gcry_mpi_t *pkey,
- int (*cmp) (void *, gcry_mpi_t),
- void *opaque);
-
-
-/* A dummy extraspec so that we do not need to tests the extraspec
- field from the module specification against NULL and instead
- directly test the respective fields of extraspecs. */
-static pk_extra_spec_t dummy_extra_spec;
-
-
-/* This is the list of the default public-key ciphers included in
- libgcrypt. FIPS_ALLOWED indicated whether the algorithm is used in
- FIPS mode. */
-static struct pubkey_table_entry
-{
- gcry_pk_spec_t *pubkey;
- pk_extra_spec_t *extraspec;
- unsigned int algorithm;
- int fips_allowed;
-} pubkey_table[] =
- {
-#if USE_RSA
- { &_gcry_pubkey_spec_rsa,
- &_gcry_pubkey_extraspec_rsa, GCRY_PK_RSA, 1},
-#endif
-#if USE_ELGAMAL
- { &_gcry_pubkey_spec_elg,
- &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG },
- { &_gcry_pubkey_spec_elg,
- &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG_E },
-#endif
-#if USE_DSA
- { &_gcry_pubkey_spec_dsa,
- &_gcry_pubkey_extraspec_dsa, GCRY_PK_DSA, 1 },
-#endif
-#if USE_ECC
- { &_gcry_pubkey_spec_ecdsa,
- &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 },
-#endif
- { NULL, 0 },
- };
-
-/* List of registered ciphers. */
-static gcry_module_t pubkeys_registered;
-
-/* This is the lock protecting PUBKEYS_REGISTERED. */
-static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;;
-
-/* Flag to check wether the default pubkeys have already been
- registered. */
-static int default_pubkeys_registered;
-
-/* Convenient macro for registering the default digests. */
-#define REGISTER_DEFAULT_PUBKEYS \
- do \
- { \
- ath_mutex_lock (&pubkeys_registered_lock); \
- if (! default_pubkeys_registered) \
- { \
- pk_register_default (); \
- default_pubkeys_registered = 1; \
- } \
- ath_mutex_unlock (&pubkeys_registered_lock); \
- } \
- while (0)
-
-/* These dummy functions are used in case a cipher implementation
- refuses to provide it's own functions. */
-
-static gcry_err_code_t
-dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
- gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
- (void)algorithm;
- (void)nbits;
- (void)dummy;
- (void)skey;
- (void)retfactors;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static gcry_err_code_t
-dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
-{
- (void)algorithm;
- (void)skey;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static gcry_err_code_t
-dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *pkey, int flags)
-{
- (void)algorithm;
- (void)resarr;
- (void)data;
- (void)pkey;
- (void)flags;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static gcry_err_code_t
-dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags)
-{
- (void)algorithm;
- (void)result;
- (void)data;
- (void)skey;
- (void)flags;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static gcry_err_code_t
-dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *skey)
-{
- (void)algorithm;
- (void)resarr;
- (void)data;
- (void)skey;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static gcry_err_code_t
-dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
- gcry_mpi_t *pkey,
- int (*cmp) (void *, gcry_mpi_t), void *opaquev)
-{
- (void)algorithm;
- (void)hash;
- (void)data;
- (void)pkey;
- (void)cmp;
- (void)opaquev;
- fips_signal_error ("using dummy public key function");
- return GPG_ERR_NOT_IMPLEMENTED;
-}
-
-static unsigned
-dummy_get_nbits (int algorithm, gcry_mpi_t *pkey)
-{
- (void)algorithm;
- (void)pkey;
- fips_signal_error ("using dummy public key function");
- return 0;
-}
-
-/* Internal function. Register all the pubkeys included in
- PUBKEY_TABLE. Returns zero on success or an error code. */
-static void
-pk_register_default (void)
-{
- gcry_err_code_t err = 0;
- int i;
-
- for (i = 0; (! err) && pubkey_table[i].pubkey; i++)
- {
-#define pubkey_use_dummy(func) \
- if (! pubkey_table[i].pubkey->func) \
- pubkey_table[i].pubkey->func = dummy_##func;
-
- pubkey_use_dummy (generate);
- pubkey_use_dummy (check_secret_key);
- pubkey_use_dummy (encrypt);
- pubkey_use_dummy (decrypt);
- pubkey_use_dummy (sign);
- pubkey_use_dummy (verify);
- pubkey_use_dummy (get_nbits);
-#undef pubkey_use_dummy
-
- err = _gcry_module_add (&pubkeys_registered,
- pubkey_table[i].algorithm,
- (void *) pubkey_table[i].pubkey,
- (void *) pubkey_table[i].extraspec,
- NULL);
- }
-
- if (err)
- BUG ();
-}
-
-/* Internal callback function. Used via _gcry_module_lookup. */
-static int
-gcry_pk_lookup_func_name (void *spec, void *data)
-{
- gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec;
- char *name = (char *) data;
- const char **aliases = pubkey->aliases;
- int ret = stricmp (name, pubkey->name);
-
- while (ret && *aliases)
- ret = stricmp (name, *aliases++);
-
- return ! ret;
-}
-
-/* Internal function. Lookup a pubkey entry by it's name. */
-static gcry_module_t
-gcry_pk_lookup_name (const char *name)
-{
- gcry_module_t pubkey;
-
- pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name,
- gcry_pk_lookup_func_name);
-
- return pubkey;
-}
-
-/* Register a new pubkey module whose specification can be found in
- PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID
- and a pointer representhing this module is stored in MODULE. */
-gcry_error_t
-_gcry_pk_register (gcry_pk_spec_t *pubkey,
- pk_extra_spec_t *extraspec,
- unsigned int *algorithm_id,
- gcry_module_t *module)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_module_t mod;
-
- /* We do not support module loading in fips mode. */
- if (fips_mode ())
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
- ath_mutex_lock (&pubkeys_registered_lock);
- err = _gcry_module_add (&pubkeys_registered, 0,
- (void *) pubkey,
- (void *)(extraspec? extraspec : &dummy_extra_spec),
- &mod);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (! err)
- {
- *module = mod;
- *algorithm_id = mod->mod_id;
- }
-
- return err;
-}
-
-/* Unregister the pubkey identified by ID, which must have been
- registered with gcry_pk_register. */
-void
-gcry_pk_unregister (gcry_module_t module)
-{
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
-}
-
-static void
-release_mpi_array (gcry_mpi_t *array)
-{
- for (; *array; array++)
- {
- mpi_free(*array);
- *array = NULL;
- }
-}
-
-/****************
- * Map a string to the pubkey algo
- */
-int
-gcry_pk_map_name (const char *string)
-{
- gcry_module_t pubkey;
- int algorithm = 0;
-
- if (!string)
- return 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = gcry_pk_lookup_name (string);
- if (pubkey)
- {
- algorithm = pubkey->mod_id;
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return algorithm;
-}
-
-
-/* Map the public key algorithm whose ID is contained in ALGORITHM to
- a string representation of the algorithm name. For unknown
- algorithm IDs this functions returns "?". */
-const char *
-gcry_pk_algo_name (int algorithm)
-{
- gcry_module_t pubkey;
- const char *name;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- name = ((gcry_pk_spec_t *) pubkey->spec)->name;
- _gcry_module_release (pubkey);
- }
- else
- name = "?";
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return name;
-}
-
-
-/* A special version of gcry_pk_algo name to return the first aliased
- name of the algorithm. This is required to adhere to the spki
- specs where the algorithm names are lowercase. */
-const char *
-_gcry_pk_aliased_algo_name (int algorithm)
-{
- const char *name = NULL;
- gcry_module_t module;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec;
-
- name = pubkey->aliases? *pubkey->aliases : NULL;
- if (!name || !*name)
- name = pubkey->name;
- _gcry_module_release (module);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return name;
-}
-
-
-static void
-disable_pubkey_algo (int algorithm)
-{
- gcry_module_t pubkey;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- if (! (pubkey-> flags & FLAG_MODULE_DISABLED))
- pubkey->flags |= FLAG_MODULE_DISABLED;
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-}
-
-
-/****************
- * A USE of 0 means: don't care.
- */
-static gcry_err_code_t
-check_pubkey_algo (int algorithm, unsigned use)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_pk_spec_t *pubkey;
- gcry_module_t module;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- if (((use & GCRY_PK_USAGE_SIGN)
- && (! (pubkey->use & GCRY_PK_USAGE_SIGN)))
- || ((use & GCRY_PK_USAGE_ENCR)
- && (! (pubkey->use & GCRY_PK_USAGE_ENCR))))
- err = GPG_ERR_WRONG_PUBKEY_ALGO;
- else if (module->flags & FLAG_MODULE_DISABLED)
- err = GPG_ERR_PUBKEY_ALGO;
- _gcry_module_release (module);
- }
- else
- err = GPG_ERR_PUBKEY_ALGO;
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return err;
-}
-
-
-/****************
- * Return the number of public key material numbers
- */
-static int
-pubkey_get_npkey (int algorithm)
-{
- gcry_module_t pubkey;
- int npkey = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey);
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return npkey;
-}
-
-/****************
- * Return the number of secret key material numbers
- */
-static int
-pubkey_get_nskey (int algorithm)
-{
- gcry_module_t pubkey;
- int nskey = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey);
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return nskey;
-}
-
-/****************
- * Return the number of signature material numbers
- */
-static int
-pubkey_get_nsig (int algorithm)
-{
- gcry_module_t pubkey;
- int nsig = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig);
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return nsig;
-}
-
-/****************
- * Return the number of encryption material numbers
- */
-static int
-pubkey_get_nenc (int algorithm)
-{
- gcry_module_t pubkey;
- int nenc = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc);
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return nenc;
-}
-
-
-/* Generate a new public key with algorithm ALGORITHM of size NBITS
- and return it at SKEY. USE_E depends on the ALGORITHM. GENPARMS
- is passed to the algorithm module if it features an extended
- generation function. RETFACTOR is used by some algorithms to
- return certain additional information which are in general not
- required.
-
- The function returns the error code number or 0 on success. */
-static gcry_err_code_t
-pubkey_generate (int algorithm,
- unsigned int nbits,
- unsigned long use_e,
- gcry_sexp_t genparms,
- gcry_mpi_t *skey, gcry_mpi_t **retfactors,
- gcry_sexp_t *r_extrainfo)
-{
- gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO;
- gcry_module_t pubkey;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- pk_extra_spec_t *extraspec = pubkey->extraspec;
-
- if (extraspec && extraspec->ext_generate)
- {
- /* Use the extended generate function. */
- ec = extraspec->ext_generate
- (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo);
- }
- else
- {
- /* Use the standard generate function. */
- ec = ((gcry_pk_spec_t *) pubkey->spec)->generate
- (algorithm, nbits, use_e, skey, retfactors);
- }
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return ec;
-}
-
-
-static gcry_err_code_t
-pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey)
-{
- gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
- gcry_module_t pubkey;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key
- (algorithm, skey);
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return err;
-}
-
-
-/****************
- * This is the interface to the public key encryption. Encrypt DATA
- * with PKEY and put it into RESARR which should be an array of MPIs
- * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
- * check with pubkey_get_nenc() )
- */
-static gcry_err_code_t
-pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *pkey, int flags)
-{
- gcry_pk_spec_t *pubkey;
- gcry_module_t module;
- gcry_err_code_t rc;
- int i;
-
- /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as
- an extra failsafe protection we explicitly test for fips mode
- here. */
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_encrypt: algo=%d\n", algorithm);
- for(i = 0; i < pubkey_get_npkey (algorithm); i++)
- log_mpidump (" pkey:", pkey[i]);
- log_mpidump (" data:", data);
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
- rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags);
- _gcry_module_release (module);
- goto ready;
- }
- rc = GPG_ERR_PUBKEY_ALGO;
-
- ready:
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- {
- for(i = 0; i < pubkey_get_nenc (algorithm); i++)
- log_mpidump(" encr:", resarr[i] );
- }
- return rc;
-}
-
-
-/****************
- * This is the interface to the public key decryption.
- * ALGO gives the algorithm to use and this implicitly determines
- * the size of the arrays.
- * result is a pointer to a mpi variable which will receive a
- * newly allocated mpi or NULL in case of an error.
- */
-static gcry_err_code_t
-pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags)
-{
- gcry_pk_spec_t *pubkey;
- gcry_module_t module;
- gcry_err_code_t rc;
- int i;
-
- *result = NULL; /* so the caller can always do a mpi_free */
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_decrypt: algo=%d\n", algorithm);
- for(i = 0; i < pubkey_get_nskey (algorithm); i++)
- log_mpidump (" skey:", skey[i]);
- for(i = 0; i < pubkey_get_nenc (algorithm); i++)
- log_mpidump (" data:", data[i]);
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
- rc = pubkey->decrypt (algorithm, result, data, skey, flags);
- _gcry_module_release (module);
- goto ready;
- }
-
- rc = GPG_ERR_PUBKEY_ALGO;
-
- ready:
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- log_mpidump (" plain:", *result);
-
- return rc;
-}
-
-
-/****************
- * This is the interface to the public key signing.
- * Sign data with skey and put the result into resarr which
- * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
- * algorithm allows this - check with pubkey_get_nsig() )
- */
-static gcry_err_code_t
-pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
- gcry_mpi_t *skey)
-{
- gcry_pk_spec_t *pubkey;
- gcry_module_t module;
- gcry_err_code_t rc;
- int i;
-
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_sign: algo=%d\n", algorithm);
- for(i = 0; i < pubkey_get_nskey (algorithm); i++)
- log_mpidump (" skey:", skey[i]);
- log_mpidump(" data:", data );
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
- rc = pubkey->sign (algorithm, resarr, data, skey);
- _gcry_module_release (module);
- goto ready;
- }
-
- rc = GPG_ERR_PUBKEY_ALGO;
-
- ready:
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (!rc && DBG_CIPHER && !fips_mode ())
- for (i = 0; i < pubkey_get_nsig (algorithm); i++)
- log_mpidump (" sig:", resarr[i]);
-
- return rc;
-}
-
-/****************
- * Verify a public key signature.
- * Return 0 if the signature is good
- */
-static gcry_err_code_t
-pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
- gcry_mpi_t *pkey,
- int (*cmp)(void *, gcry_mpi_t), void *opaquev)
-{
- gcry_pk_spec_t *pubkey;
- gcry_module_t module;
- gcry_err_code_t rc;
- int i;
-
- if (DBG_CIPHER && !fips_mode ())
- {
- log_debug ("pubkey_verify: algo=%d\n", algorithm);
- for (i = 0; i < pubkey_get_npkey (algorithm); i++)
- log_mpidump (" pkey:", pkey[i]);
- for (i = 0; i < pubkey_get_nsig (algorithm); i++)
- log_mpidump (" sig:", data[i]);
- log_mpidump (" hash:", hash);
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (module)
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
- rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev);
- _gcry_module_release (module);
- goto ready;
- }
-
- rc = GPG_ERR_PUBKEY_ALGO;
-
- ready:
- ath_mutex_unlock (&pubkeys_registered_lock);
- return rc;
-}
-
-
-/* Internal function. */
-static gcry_err_code_t
-sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
- gcry_mpi_t *elements, const char *algo_name)
-{
- gcry_err_code_t err = 0;
- int i, idx;
- const char *name;
- gcry_sexp_t list;
-
- for (name = element_names, idx = 0; *name && !err; name++, idx++)
- {
- list = gcry_sexp_find_token (key_sexp, name, 1);
- if (!list)
- elements[idx] = NULL;
- else
- {
- elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (list);
- if (!elements[idx])
- err = GPG_ERR_INV_OBJ;
- }
- }
-
- if (!err)
- {
- /* Check that all elements are available. */
- for (name = element_names, idx = 0; *name; name++, idx++)
- if (!elements[idx])
- break;
- if (*name)
- {
- err = GPG_ERR_NO_OBJ;
- /* Some are missing. Before bailing out we test for
- optional parameters. */
- if (algo_name && !strcmp (algo_name, "RSA")
- && !strcmp (element_names, "nedpqu") )
- {
- /* This is RSA. Test whether we got N, E and D and that
- the optional P, Q and U are all missing. */
- if (elements[0] && elements[1] && elements[2]
- && !elements[3] && !elements[4] && !elements[5])
- err = 0;
- }
- }
- }
-
-
- if (err)
- {
- for (i = 0; i < idx; i++)
- if (elements[i])
- gcry_free (elements[i]);
- }
- return err;
-}
-
-
-/* Internal function used for ecc. Note, that this function makes use
- of its intimate knowledge about the ECC parameters from ecc.c. */
-static gcry_err_code_t
-sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
- gcry_mpi_t *elements, pk_extra_spec_t *extraspec)
-
-{
- gcry_err_code_t err = 0;
- int idx;
- const char *name;
- gcry_sexp_t list;
-
- /* Clear the array for easier error cleanup. */
- for (name = element_names, idx = 0; *name; name++, idx++)
- elements[idx] = NULL;
- gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */
-
- /* Init the array with the available curve parameters. */
- for (name = element_names, idx = 0; *name && !err; name++, idx++)
- {
- list = gcry_sexp_find_token (key_sexp, name, 1);
- if (!list)
- elements[idx] = NULL;
- else
- {
- elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (list);
- if (!elements[idx])
- {
- err = GPG_ERR_INV_OBJ;
- goto leave;
- }
- }
- }
-
- /* Check whether a curve parameter has been given and then fill any
- missing elements. */
- list = gcry_sexp_find_token (key_sexp, "curve", 5);
- if (list)
- {
- if (extraspec->get_param)
- {
- char *curve;
- gcry_mpi_t params[6];
-
- for (idx = 0; idx < DIM(params); idx++)
- params[idx] = NULL;
-
- curve = _gcry_sexp_nth_string (list, 1);
- gcry_sexp_release (list);
- if (!curve)
- {
- /* No curve name given (or out of core). */
- err = GPG_ERR_INV_OBJ;
- goto leave;
- }
- err = extraspec->get_param (curve, params);
- gcry_free (curve);
- if (err)
- goto leave;
-
- for (idx = 0; idx < DIM(params); idx++)
- {
- if (!elements[idx])
- elements[idx] = params[idx];
- else
- mpi_free (params[idx]);
- }
- }
- else
- {
- gcry_sexp_release (list);
- err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
- goto leave;
- }
- }
-
- /* Check that all parameters are known. */
- for (name = element_names, idx = 0; *name; name++, idx++)
- if (!elements[idx])
- {
- err = GPG_ERR_NO_OBJ;
- goto leave;
- }
-
- leave:
- if (err)
- {
- for (name = element_names, idx = 0; *name; name++, idx++)
- if (elements[idx])
- gcry_free (elements[idx]);
- }
- return err;
-}
-
-
-
-/****************
- * Convert a S-Exp with either a private or a public key to our
- * internal format. Currently we do only support the following
- * algorithms:
- * dsa
- * rsa
- * openpgp-dsa
- * openpgp-rsa
- * openpgp-elg
- * openpgp-elg-sig
- * ecdsa
- * Provide a SE with the first element be either "private-key" or
- * or "public-key". It is followed by a list with its first element
- * be one of the above algorithm identifiers and the remaning
- * elements are pairs with parameter-id and value.
- * NOTE: we look through the list to find a list beginning with
- * "private-key" or "public-key" - the first one found is used.
- *
- * Returns: A pointer to an allocated array of MPIs if the return value is
- * zero; the caller has to release this array.
- *
- * Example of a DSA public key:
- * (private-key
- * (dsa
- * (p <mpi>)
- * (g <mpi>)
- * (y <mpi>)
- * (x <mpi>)
- * )
- * )
- * The <mpi> are expected to be in GCRYMPI_FMT_USG
- */
-static gcry_err_code_t
-sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
- gcry_module_t *retalgo)
-{
- gcry_err_code_t err = 0;
- gcry_sexp_t list, l2;
- char *name;
- const char *elems;
- gcry_mpi_t *array;
- gcry_module_t module;
- gcry_pk_spec_t *pubkey;
- pk_extra_spec_t *extraspec;
- int is_ecc;
-
- /* Check that the first element is valid. */
- list = gcry_sexp_find_token (sexp,
- want_private? "private-key":"public-key", 0);
- if (!list)
- return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
-
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- name = _gcry_sexp_nth_string (list, 0);
- if (!name)
- {
- gcry_sexp_release ( list );
- return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- /* Fixme: We should make sure that an ECC key is always named "ecc"
- and not "ecdsa". "ecdsa" should be used for the signature
- itself. We need a function to test whether an algorithm given
- with a key is compatible with an application of the key (signing,
- encryption). For RSA this is easy, but ECC is the first
- algorithm which has many flavours. */
- is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") );
- gcry_free (name);
-
- if (!module)
- {
- gcry_sexp_release (list);
- return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
- }
- else
- {
- pubkey = (gcry_pk_spec_t *) module->spec;
- extraspec = module->extraspec;
- }
-
- elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
- array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
- if (!array)
- err = gpg_err_code_from_errno (errno);
- if (!err)
- {
- if (is_ecc)
- err = sexp_elements_extract_ecc (list, elems, array, extraspec);
- else
- err = sexp_elements_extract (list, elems, array, pubkey->name);
- }
-
- gcry_sexp_release (list);
-
- if (err)
- {
- gcry_free (array);
-
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
- else
- {
- *retarray = array;
- *retalgo = module;
- }
-
- return err;
-}
-
-
-static gcry_err_code_t
-sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
- gcry_module_t *retalgo)
-{
- gcry_err_code_t err = 0;
- gcry_sexp_t list, l2;
- char *name;
- const char *elems;
- gcry_mpi_t *array;
- gcry_module_t module;
- gcry_pk_spec_t *pubkey;
-
- /* Check that the first element is valid. */
- list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
- if (!list)
- return GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */
-
- l2 = gcry_sexp_nth (list, 1);
- if (!l2)
- {
- gcry_sexp_release (list);
- return GPG_ERR_NO_OBJ; /* No cadr for the sig object. */
- }
- name = _gcry_sexp_nth_string (l2, 0);
- if (!name)
- {
- gcry_sexp_release (list);
- gcry_sexp_release (l2);
- return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
- }
- else if (!strcmp (name, "flags"))
- {
- /* Skip flags, since they are not used but here just for the
- sake of consistent S-expressions. */
- gcry_free (name);
- gcry_sexp_release (l2);
- l2 = gcry_sexp_nth (list, 2);
- if (!l2)
- {
- gcry_sexp_release (list);
- return GPG_ERR_INV_OBJ;
- }
- name = _gcry_sexp_nth_string (l2, 0);
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name);
- ath_mutex_unlock (&pubkeys_registered_lock);
- gcry_free (name);
- name = NULL;
-
- if (!module)
- {
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
- return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
- }
- else
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- elems = pubkey->elements_sig;
- array = gcry_calloc (strlen (elems) + 1 , sizeof *array );
- if (!array)
- err = gpg_err_code_from_errno (errno);
-
- if (!err)
- err = sexp_elements_extract (list, elems, array, NULL);
-
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
-
- if (err)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- gcry_free (array);
- }
- else
- {
- *retarray = array;
- *retalgo = module;
- }
-
- return err;
-}
-
-
-/****************
- * Take sexp and return an array of MPI as used for our internal decrypt
- * function.
- * s_data = (enc-val
- * [(flags [pkcs1])]
- * (<algo>
- * (<param_name1> <mpi>)
- * ...
- * (<param_namen> <mpi>)
- * ))
- * RET_MODERN is set to true when at least an empty flags list has been found.
- */
-static gcry_err_code_t
-sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
- int *ret_modern, int *ret_want_pkcs1, int *flags)
-{
- gcry_err_code_t err = 0;
- gcry_sexp_t list = NULL, l2 = NULL;
- gcry_pk_spec_t *pubkey = NULL;
- gcry_module_t module = NULL;
- char *name = NULL;
- size_t n;
- int parsed_flags = 0;
- const char *elems;
- gcry_mpi_t *array = NULL;
-
- *ret_want_pkcs1 = 0;
- *ret_modern = 0;
-
- /* Check that the first element is valid. */
- list = gcry_sexp_find_token (sexp, "enc-val" , 0);
- if (!list)
- {
- err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object. */
- goto leave;
- }
-
- l2 = gcry_sexp_nth (list, 1);
- if (!l2)
- {
- err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
- goto leave;
- }
-
- /* Extract identifier of sublist. */
- name = _gcry_sexp_nth_string (l2, 0);
- if (!name)
- {
- err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
- goto leave;
- }
-
- if (!strcmp (name, "flags"))
- {
- /* There is a flags element - process it. */
- const char *s;
- int i;
-
- *ret_modern = 1;
- for (i = gcry_sexp_length (l2) - 1; i > 0; i--)
- {
- s = gcry_sexp_nth_data (l2, i, &n);
- if (! s)
- ; /* Not a data element - ignore. */
- else if (n == 3 && !memcmp (s, "raw", 3))
- ; /* This is just a dummy as it is the default. */
- else if (n == 5 && !memcmp (s, "pkcs1", 5))
- *ret_want_pkcs1 = 1;
- else if (n == 11 && ! memcmp (s, "no-blinding", 11))
- parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
- else
- {
- err = GPG_ERR_INV_FLAG;
- goto leave;
- }
- }
-
- /* Get the next which has the actual data. */
- gcry_sexp_release (l2);
- l2 = gcry_sexp_nth (list, 2);
- if (!l2)
- {
- err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
- goto leave;
- }
-
- /* Extract sublist identifier. */
- gcry_free (name);
- name = _gcry_sexp_nth_string (l2, 0);
- if (!name)
- {
- err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
- goto leave;
- }
-
- gcry_sexp_release (list);
- list = l2;
- l2 = NULL;
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (!module)
- {
- err = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
- goto leave;
- }
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- elems = pubkey->elements_enc;
- array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
- if (!array)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- err = sexp_elements_extract (list, elems, array, NULL);
-
- leave:
- gcry_sexp_release (list);
- gcry_sexp_release (l2);
- gcry_free (name);
-
- if (err)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- gcry_free (array);
- }
- else
- {
- *retarray = array;
- *retalgo = module;
- *flags = parsed_flags;
- }
-
- return err;
-}
-
-/* Take the hash value and convert into an MPI, suitable for
- passing to the low level functions. We currently support the
- old style way of passing just a MPI and the modern interface which
- allows to pass flags so that we can choose between raw and pkcs1
- padding - may be more padding options later.
-
- (<mpi>)
- or
- (data
- [(flags [pkcs1])]
- [(hash <algo> <value>)]
- [(value <text>)]
- )
-
- Either the VALUE or the HASH element must be present for use
- with signatures. VALUE is used for encryption.
-
- NBITS is the length of the key in bits.
-
-*/
-static gcry_err_code_t
-sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
- int for_encryption, int *flags)
-{
- gcry_err_code_t rc = 0;
- gcry_sexp_t ldata, lhash, lvalue;
- int i;
- size_t n;
- const char *s;
- int is_raw = 0, is_pkcs1 = 0, unknown_flag=0;
- int parsed_flags = 0, dummy_flags;
-
- if (! flags)
- flags = &dummy_flags;
-
- *ret_mpi = NULL;
- ldata = gcry_sexp_find_token (input, "data", 0);
- if (!ldata)
- { /* assume old style */
- *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
- return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
- }
-
- /* see whether there is a flags object */
- {
- gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
- if (lflags)
- { /* parse the flags list. */
- for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
- {
- s = gcry_sexp_nth_data (lflags, i, &n);
- if (!s)
- ; /* not a data element*/
- else if ( n == 3 && !memcmp (s, "raw", 3))
- is_raw = 1;
- else if ( n == 5 && !memcmp (s, "pkcs1", 5))
- is_pkcs1 = 1;
- else if (n == 11 && ! memcmp (s, "no-blinding", 11))
- parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
- else
- unknown_flag = 1;
- }
- gcry_sexp_release (lflags);
- }
- }
-
- if (!is_pkcs1 && !is_raw)
- is_raw = 1; /* default to raw */
-
- /* Get HASH or MPI */
- lhash = gcry_sexp_find_token (ldata, "hash", 0);
- lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
-
- if (!(!lhash ^ !lvalue))
- rc = GPG_ERR_INV_OBJ; /* none or both given */
- else if (unknown_flag)
- rc = GPG_ERR_INV_FLAG;
- else if (is_raw && is_pkcs1 && !for_encryption)
- rc = GPG_ERR_CONFLICT;
- else if (is_raw && lvalue)
- {
- *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0);
- if (!*ret_mpi)
- rc = GPG_ERR_INV_OBJ;
- }
- else if (is_pkcs1 && lvalue && for_encryption)
- {
- /* Create pkcs#1 block type 2 padding. */
- unsigned char *frame = NULL;
- size_t nframe = (nbits+7) / 8;
- const void * value;
- size_t valuelen;
- unsigned char *p;
-
- if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
- rc = GPG_ERR_INV_OBJ;
- else if (valuelen + 7 > nframe || !nframe)
- {
- /* Can't encode a VALUELEN value in a NFRAME bytes frame. */
- rc = GPG_ERR_TOO_SHORT; /* the key is too short */
- }
- else if ( !(frame = gcry_malloc_secure (nframe)))
- rc = gpg_err_code_from_errno (errno);
- else
- {
- n = 0;
- frame[n++] = 0;
- frame[n++] = 2; /* block type */
- i = nframe - 3 - valuelen;
- gcry_assert (i > 0);
- p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
- /* Replace zero bytes by new values. */
- for (;;)
- {
- int j, k;
- unsigned char *pp;
-
- /* Count the zero bytes. */
- for (j=k=0; j < i; j++)
- {
- if (!p[j])
- k++;
- }
- if (!k)
- break; /* Okay: no (more) zero bytes. */
-
- k += k/128 + 3; /* Better get some more. */
- pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
- for (j=0; j < i && k; )
- {
- if (!p[j])
- p[j] = pp[--k];
- if (p[j])
- j++;
- }
- gcry_free (pp);
- }
- memcpy (frame+n, p, i);
- n += i;
- gcry_free (p);
-
- frame[n++] = 0;
- memcpy (frame+n, value, valuelen);
- n += valuelen;
- gcry_assert (n == nframe);
-
- /* FIXME, error checking? */
- gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
- }
-
- gcry_free(frame);
- }
- else if (is_pkcs1 && lhash && !for_encryption)
- {
- /* Create pkcs#1 block type 1 padding. */
- if (gcry_sexp_length (lhash) != 3)
- rc = GPG_ERR_INV_OBJ;
- else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
- rc = GPG_ERR_INV_OBJ;
- else
- {
- static struct { const char *name; int algo; } hashnames[] =
- { { "sha1", GCRY_MD_SHA1 },
- { "md5", GCRY_MD_MD5 },
- { "sha256", GCRY_MD_SHA256 },
- { "ripemd160", GCRY_MD_RMD160 },
- { "rmd160", GCRY_MD_RMD160 },
- { "sha384", GCRY_MD_SHA384 },
- { "sha512", GCRY_MD_SHA512 },
- { "sha224", GCRY_MD_SHA224 },
- { "md2", GCRY_MD_MD2 },
- { "md4", GCRY_MD_MD4 },
- { "tiger", GCRY_MD_TIGER },
- { "haval", GCRY_MD_HAVAL },
- { NULL, 0 }
- };
- int algo;
- byte asn[100];
- byte *frame = NULL;
- size_t nframe = (nbits+7) / 8;
- const void * value;
- size_t valuelen;
- size_t asnlen, dlen;
-
- for (i=0; hashnames[i].name; i++)
- {
- if ( strlen (hashnames[i].name) == n
- && !memcmp (hashnames[i].name, s, n))
- break;
- }
- if (hashnames[i].name)
- algo = hashnames[i].algo;
- else
- {
- /* In case of not listed or dynamically allocated hash
- algorithm we fall back to this somewhat slower
- method. Further, it also allows to use OIDs as
- algorithm names. */
- char *tmpname;
-
- tmpname = gcry_malloc (n+1);
- if (!tmpname)
- algo = 0; /* Out of core - silently give up. */
- else
- {
- memcpy (tmpname, s, n);
- tmpname[n] = 0;
- algo = gcry_md_map_name (tmpname);
- gcry_free (tmpname);
- }
- }
-
- asnlen = DIM(asn);
- dlen = gcry_md_get_algo_dlen (algo);
-
- if (!algo)
- rc = GPG_ERR_DIGEST_ALGO;
- else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
- || !valuelen )
- rc = GPG_ERR_INV_OBJ;
- else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
- {
- /* We don't have yet all of the above algorithms. */
- rc = GPG_ERR_NOT_IMPLEMENTED;
- }
- else if ( valuelen != dlen )
- {
- /* Hash value does not match the length of digest for
- the given algorithm. */
- rc = GPG_ERR_CONFLICT;
- }
- else if( !dlen || dlen + asnlen + 4 > nframe)
- {
- /* Can't encode an DLEN byte digest MD into a NFRAME
- byte frame. */
- rc = GPG_ERR_TOO_SHORT;
- }
- else if ( !(frame = gcry_malloc (nframe)) )
- rc = gpg_err_code_from_errno (errno);
- else
- { /* Assemble the pkcs#1 block type 1. */
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - valuelen - asnlen - 3 ;
- gcry_assert (i > 1);
- memset (frame+n, 0xff, i );
- n += i;
- frame[n++] = 0;
- memcpy (frame+n, asn, asnlen);
- n += asnlen;
- memcpy (frame+n, value, valuelen );
- n += valuelen;
- gcry_assert (n == nframe);
-
- /* Convert it into an MPI. FIXME: error checking? */
- gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
- }
-
- gcry_free (frame);
- }
- }
- else
- rc = GPG_ERR_CONFLICT;
-
- gcry_sexp_release (ldata);
- gcry_sexp_release (lhash);
- gcry_sexp_release (lvalue);
-
- if (!rc)
- *flags = parsed_flags;
-
- return rc;
-}
-
-
-/*
- Do a PK encrypt operation
-
- Caller has to provide a public key as the SEXP pkey and data as a
- SEXP with just one MPI in it. Alternativly S_DATA might be a
- complex S-Expression, similar to the one used for signature
- verification. This provides a flag which allows to handle PKCS#1
- block type 2 padding. The function returns a a sexp which may be
- passed to to pk_decrypt.
-
- Returns: 0 or an errorcode.
-
- s_data = See comment for sexp_data_to_mpi
- s_pkey = <key-as-defined-in-sexp_to_key>
- r_ciph = (enc-val
- (<algo>
- (<param_name1> <mpi>)
- ...
- (<param_namen> <mpi>)
- ))
-
-*/
-gcry_error_t
-gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
-{
- gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
- const char *algo_name, *algo_elems;
- int flags;
- gcry_err_code_t rc;
- gcry_pk_spec_t *pubkey = NULL;
- gcry_module_t module = NULL;
-
- *r_ciph = NULL;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- /* Get the key. */
- rc = sexp_to_key (s_pkey, 0, &pkey, &module);
- if (rc)
- goto leave;
-
- gcry_assert (module);
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- /* If aliases for the algorithm name exists, take the first one
- instead of the regular name to adhere to SPKI conventions. We
- assume that the first alias name is the lowercase version of the
- regular one. This change is required for compatibility with
- 1.1.12 generated S-expressions. */
- algo_name = pubkey->aliases? *pubkey->aliases : NULL;
- if (!algo_name || !*algo_name)
- algo_name = pubkey->name;
-
- algo_elems = pubkey->elements_enc;
-
- /* Get the stuff we want to encrypt. */
- rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1,
- &flags);
- if (rc)
- goto leave;
-
- /* Now we can encrypt DATA to CIPH. */
- ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
- if (!ciph)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags);
- mpi_free (data);
- data = NULL;
- if (rc)
- goto leave;
-
- /* We did it. Now build the return list */
- {
- char *string, *p;
- int i;
- size_t nelem = strlen (algo_elems);
- size_t needed = 19 + strlen (algo_name) + (nelem * 5);
- void **arg_list;
-
- /* Build the string. */
- string = p = gcry_malloc (needed);
- if (!string)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- p = stpcpy ( p, "(enc-val(" );
- p = stpcpy ( p, algo_name );
- for (i=0; algo_elems[i]; i++ )
- {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy ( p, "%m)" );
- }
- strcpy ( p, "))" );
-
- /* And now the ugly part: We don't have a function to pass an
- * array to a format string, so we have to do it this way :-(. */
- /* FIXME: There is now such a format specifier, so we can
- change the code to be more clear. */
- arg_list = malloc (nelem * sizeof *arg_list);
- if (!arg_list)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- for (i = 0; i < nelem; i++)
- arg_list[i] = ciph + i;
-
- rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
- free (arg_list);
- if (rc)
- BUG ();
- gcry_free (string);
- }
-
- leave:
- if (pkey)
- {
- release_mpi_array (pkey);
- gcry_free (pkey);
- }
-
- if (ciph)
- {
- release_mpi_array (ciph);
- gcry_free (ciph);
- }
-
- if (module)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
-
- return gcry_error (rc);
-}
-
-/*
- Do a PK decrypt operation
-
- Caller has to provide a secret key as the SEXP skey and data in a
- format as created by gcry_pk_encrypt. For historic reasons the
- function returns simply an MPI as an S-expression part; this is
- deprecated and the new method should be used which returns a real
- S-expressionl this is selected by adding at least an empty flags
- list to S_DATA.
-
- Returns: 0 or an errorcode.
-
- s_data = (enc-val
- [(flags)]
- (<algo>
- (<param_name1> <mpi>)
- ...
- (<param_namen> <mpi>)
- ))
- s_skey = <key-as-defined-in-sexp_to_key>
- r_plain= Either an incomplete S-expression without the parentheses
- or if the flags list is used (even if empty) a real S-expression:
- (value PLAIN).
- */
-gcry_error_t
-gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
-{
- gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL;
- int modern, want_pkcs1, flags;
- gcry_err_code_t rc;
- gcry_module_t module_enc = NULL, module_key = NULL;
- gcry_pk_spec_t *pubkey = NULL;
-
- *r_plain = NULL;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- rc = sexp_to_key (s_skey, 1, &skey, &module_key);
- if (rc)
- goto leave;
-
- rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags);
- if (rc)
- goto leave;
-
- if (module_key->mod_id != module_enc->mod_id)
- {
- rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */
- goto leave;
- }
-
- pubkey = (gcry_pk_spec_t *) module_key->spec;
-
- rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags);
- if (rc)
- goto leave;
-
- if (gcry_sexp_build (r_plain, NULL, modern? "(value %m)" : "%m", plain))
- BUG ();
-
- leave:
- if (skey)
- {
- release_mpi_array (skey);
- gcry_free (skey);
- }
-
- if (plain)
- mpi_free (plain);
-
- if (data)
- {
- release_mpi_array (data);
- gcry_free (data);
- }
-
- if (module_key || module_enc)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- if (module_key)
- _gcry_module_release (module_key);
- if (module_enc)
- _gcry_module_release (module_enc);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
-
- return gcry_error (rc);
-}
-
-
-
-/*
- Create a signature.
-
- Caller has to provide a secret key as the SEXP skey and data
- expressed as a SEXP list hash with only one element which should
- instantly be available as a MPI. Alternatively the structure given
- below may be used for S_HASH, it provides the abiliy to pass flags
- to the operation; the only flag defined by now is "pkcs1" which
- does PKCS#1 block type 1 style padding.
-
- Returns: 0 or an errorcode.
- In case of 0 the function returns a new SEXP with the
- signature value; the structure of this signature depends on the
- other arguments but is always suitable to be passed to
- gcry_pk_verify
-
- s_hash = See comment for sexp_data_to_mpi
-
- s_skey = <key-as-defined-in-sexp_to_key>
- r_sig = (sig-val
- (<algo>
- (<param_name1> <mpi>)
- ...
- (<param_namen> <mpi>))
- [(hash algo)])
-
- Note that (hash algo) in R_SIG is not used.
-*/
-gcry_error_t
-gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
-{
- gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL;
- gcry_pk_spec_t *pubkey = NULL;
- gcry_module_t module = NULL;
- const char *algo_name, *algo_elems;
- int i;
- gcry_err_code_t rc;
-
- *r_sig = NULL;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- rc = sexp_to_key (s_skey, 1, &skey, &module);
- if (rc)
- goto leave;
-
- gcry_assert (module);
- pubkey = (gcry_pk_spec_t *) module->spec;
- algo_name = pubkey->aliases? *pubkey->aliases : NULL;
- if (!algo_name || !*algo_name)
- algo_name = pubkey->name;
-
- algo_elems = pubkey->elements_sig;
-
- /* Get the stuff we want to sign. Note that pk_get_nbits does also
- work on a private key. */
- rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey),
- &hash, 0, NULL);
- if (rc)
- goto leave;
-
- result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
- if (!result)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- rc = pubkey_sign (module->mod_id, result, hash, skey);
- if (rc)
- goto leave;
-
- {
- char *string, *p;
- size_t nelem, needed = strlen (algo_name) + 20;
- void **arg_list;
-
- nelem = strlen (algo_elems);
-
- /* Count elements, so that we can allocate enough space. */
- needed += 10 * nelem;
-
- /* Build the string. */
- string = p = gcry_malloc (needed);
- if (!string)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- p = stpcpy (p, "(sig-val(");
- p = stpcpy (p, algo_name);
- for (i = 0; algo_elems[i]; i++)
- {
- *p++ = '(';
- *p++ = algo_elems[i];
- p = stpcpy (p, "%m)");
- }
- strcpy (p, "))");
-
- arg_list = malloc (nelem * sizeof *arg_list);
- if (!arg_list)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
-
- for (i = 0; i < nelem; i++)
- arg_list[i] = result + i;
-
- rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
- free (arg_list);
- if (rc)
- BUG ();
- gcry_free (string);
- }
-
- leave:
- if (skey)
- {
- release_mpi_array (skey);
- gcry_free (skey);
- }
-
- if (hash)
- mpi_free (hash);
-
- if (result)
- {
- release_mpi_array (result);
- gcry_free (result);
- }
-
- return gcry_error (rc);
-}
-
-
-/*
- Verify a signature.
-
- Caller has to supply the public key pkey, the signature sig and his
- hashvalue data. Public key has to be a standard public key given
- as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
- must be an S-Exp like the one in sign too. */
-gcry_error_t
-gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
-{
- gcry_module_t module_key = NULL, module_sig = NULL;
- gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL;
- gcry_err_code_t rc;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- rc = sexp_to_key (s_pkey, 0, &pkey, &module_key);
- if (rc)
- goto leave;
-
- rc = sexp_to_sig (s_sig, &sig, &module_sig);
- if (rc)
- goto leave;
-
- /* Fixme: Check that the algorithm of S_SIG is compatible to the one
- of S_PKEY. */
-
- if (module_key->mod_id != module_sig->mod_id)
- {
- rc = GPG_ERR_CONFLICT;
- goto leave;
- }
-
- rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0);
- if (rc)
- goto leave;
-
- rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, NULL, NULL);
-
- leave:
- if (pkey)
- {
- release_mpi_array (pkey);
- gcry_free (pkey);
- }
- if (sig)
- {
- release_mpi_array (sig);
- gcry_free (sig);
- }
- if (hash)
- mpi_free (hash);
-
- if (module_key || module_sig)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- if (module_key)
- _gcry_module_release (module_key);
- if (module_sig)
- _gcry_module_release (module_sig);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
-
- return gcry_error (rc);
-}
-
-
-/*
- Test a key.
-
- This may be used either for a public or a secret key to see whether
- the internal structure is okay.
-
- Returns: 0 or an errorcode.
-
- s_key = <key-as-defined-in-sexp_to_key> */
-gcry_error_t
-gcry_pk_testkey (gcry_sexp_t s_key)
-{
- gcry_module_t module = NULL;
- gcry_mpi_t *key = NULL;
- gcry_err_code_t rc;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- /* Note we currently support only secret key checking. */
- rc = sexp_to_key (s_key, 1, &key, &module);
- if (! rc)
- {
- rc = pubkey_check_secret_key (module->mod_id, key);
- release_mpi_array (key);
- gcry_free (key);
- }
- return gcry_error (rc);
-}
-
-
-/*
- Create a public key pair and return it in r_key.
- How the key is created depends on s_parms:
- (genkey
- (algo
- (parameter_name_1 ....)
- ....
- (parameter_name_n ....)
- ))
- The key is returned in a format depending on the
- algorithm. Both, private and secret keys are returned
- and optionally some additional informatin.
- For elgamal we return this structure:
- (key-data
- (public-key
- (elg
- (p <mpi>)
- (g <mpi>)
- (y <mpi>)
- )
- )
- (private-key
- (elg
- (p <mpi>)
- (g <mpi>)
- (y <mpi>)
- (x <mpi>)
- )
- )
- (misc-key-info
- (pm1-factors n1 n2 ... nn)
- ))
- */
-gcry_error_t
-gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
-{
- gcry_pk_spec_t *pubkey = NULL;
- gcry_module_t module = NULL;
- gcry_sexp_t list = NULL;
- gcry_sexp_t l2 = NULL;
- gcry_sexp_t l3 = NULL;
- char *name = NULL;
- size_t n;
- gcry_err_code_t rc = GPG_ERR_NO_ERROR;
- int i;
- const char *algo_name = NULL;
- int algo;
- const char *sec_elems = NULL, *pub_elems = NULL;
- gcry_mpi_t skey[12];
- gcry_mpi_t *factors = NULL;
- gcry_sexp_t extrainfo = NULL;
- unsigned int nbits = 0;
- unsigned long use_e = 0;
-
- skey[0] = NULL;
- *r_key = NULL;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- list = gcry_sexp_find_token (s_parms, "genkey", 0);
- if (!list)
- {
- rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
- goto leave;
- }
-
- l2 = gcry_sexp_cadr (list);
- gcry_sexp_release (list);
- list = l2;
- l2 = NULL;
- if (! list)
- {
- rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
- goto leave;
- }
-
- name = _gcry_sexp_nth_string (list, 0);
- if (!name)
- {
- rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
- goto leave;
- }
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name);
- ath_mutex_unlock (&pubkeys_registered_lock);
- gcry_free (name);
- name = NULL;
- if (!module)
- {
- rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
- goto leave;
- }
-
- pubkey = (gcry_pk_spec_t *) module->spec;
- algo = module->mod_id;
- algo_name = pubkey->aliases? *pubkey->aliases : NULL;
- if (!algo_name || !*algo_name)
- algo_name = pubkey->name;
- pub_elems = pubkey->elements_pkey;
- sec_elems = pubkey->elements_skey;
- if (strlen (sec_elems) >= DIM(skey))
- BUG ();
-
- /* Handle the optional rsa-use-e element. Actually this belong into
- the algorithm module but we have this parameter in the public
- module API, so we need to parse it right here. */
- l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
- if (l2)
- {
- char buf[50];
- const char *s;
-
- s = gcry_sexp_nth_data (l2, 1, &n);
- if ( !s || n >= DIM (buf) - 1 )
- {
- rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
- goto leave;
- }
- memcpy (buf, s, n);
- buf[n] = 0;
- use_e = strtoul (buf, NULL, 0);
- gcry_sexp_release (l2);
- l2 = NULL;
- }
- else
- use_e = 65537; /* Not given, use the value generated by old versions. */
-
-
- /* Get the "nbits" parameter. */
- l2 = gcry_sexp_find_token (list, "nbits", 0);
- if (l2)
- {
- char buf[50];
- const char *s;
-
- s = gcry_sexp_nth_data (l2, 1, &n);
- if (!s || n >= DIM (buf) - 1 )
- {
- rc = GPG_ERR_INV_OBJ; /* NBITS given without a cdr. */
- goto leave;
- }
- memcpy (buf, s, n);
- buf[n] = 0;
- nbits = (unsigned int)strtoul (buf, NULL, 0);
- gcry_sexp_release (l2); l2 = NULL;
- }
- else
- nbits = 0;
-
- /* Pass control to the algorithm module. */
- rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey,
- &factors, &extrainfo);
- gcry_sexp_release (list); list = NULL;
- if (rc)
- goto leave;
-
- /* Key generation succeeded: Build an S-expression. */
- {
- char *string, *p;
- size_t nelem=0, nelem_cp = 0, needed=0;
- gcry_mpi_t mpis[30];
-
- /* Estimate size of format string. */
- nelem = strlen (pub_elems) + strlen (sec_elems);
- if (factors)
- {
- for (i = 0; factors[i]; i++)
- nelem++;
- }
- nelem_cp = nelem;
-
- needed += nelem * 10;
- /* (+5 is for EXTRAINFO ("%S")). */
- needed += 2 * strlen (algo_name) + 300 + 5;
- if (nelem > DIM (mpis))
- BUG ();
-
- /* Build the string. */
- nelem = 0;
- string = p = gcry_malloc (needed);
- if (!string)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- p = stpcpy (p, "(key-data");
- p = stpcpy (p, "(public-key(");
- p = stpcpy (p, algo_name);
- for(i = 0; pub_elems[i]; i++)
- {
- *p++ = '(';
- *p++ = pub_elems[i];
- p = stpcpy (p, "%m)");
- mpis[nelem++] = skey[i];
- }
- p = stpcpy (p, "))");
- p = stpcpy (p, "(private-key(");
- p = stpcpy (p, algo_name);
- for (i = 0; sec_elems[i]; i++)
- {
- *p++ = '(';
- *p++ = sec_elems[i];
- p = stpcpy (p, "%m)");
- mpis[nelem++] = skey[i];
- }
- p = stpcpy (p, "))");
-
- /* Hack to make release_mpi_array() work. */
- skey[i] = NULL;
-
- if (extrainfo)
- {
- /* If we have extrainfo we should not have any factors. */
- p = stpcpy (p, "%S");
- }
- else if (factors && factors[0])
- {
- p = stpcpy (p, "(misc-key-info(pm1-factors");
- for(i = 0; factors[i]; i++)
- {
- p = stpcpy (p, "%m");
- mpis[nelem++] = factors[i];
- }
- p = stpcpy (p, "))");
- }
- strcpy (p, ")");
- gcry_assert (p - string < needed);
-
- while (nelem < DIM (mpis))
- mpis[nelem++] = NULL;
-
- {
- int elem_n = strlen (pub_elems) + strlen (sec_elems);
- void **arg_list;
-
- /* Allocate one extra for EXTRAINFO ("%S"). */
- arg_list = gcry_calloc (nelem_cp+1, sizeof *arg_list);
- if (!arg_list)
- {
- rc = gpg_err_code_from_errno (errno);
- goto leave;
- }
- for (i = 0; i < elem_n; i++)
- arg_list[i] = mpis + i;
- if (extrainfo)
- arg_list[i] = &extrainfo;
- else if (factors && factors[0])
- {
- for (; i < nelem_cp; i++)
- arg_list[i] = factors + i - elem_n;
- }
-
- rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
- gcry_free (arg_list);
- if (rc)
- BUG ();
- gcry_assert (DIM (mpis) == 30); /* Reminder to make sure that
- the array gets increased if
- new parameters are added. */
- }
- gcry_free (string);
- }
-
- leave:
- gcry_free (name);
- gcry_sexp_release (extrainfo);
- release_mpi_array (skey);
- /* Don't free SKEY itself, it is an stack allocated array. */
-
- if (factors)
- {
- release_mpi_array ( factors );
- gcry_free (factors);
- }
-
- gcry_sexp_release (l3);
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
-
- if (module)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
-
- return gcry_error (rc);
-}
-
-
-/*
- Get the number of nbits from the public key.
-
- Hmmm: Should we have really this function or is it better to have a
- more general function to retrieve different properties of the key? */
-unsigned int
-gcry_pk_get_nbits (gcry_sexp_t key)
-{
- gcry_module_t module = NULL;
- gcry_pk_spec_t *pubkey;
- gcry_mpi_t *keyarr = NULL;
- unsigned int nbits = 0;
- gcry_err_code_t rc;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- rc = sexp_to_key (key, 0, &keyarr, &module);
- if (rc == GPG_ERR_INV_OBJ)
- rc = sexp_to_key (key, 1, &keyarr, &module);
- if (rc)
- return 0; /* Error - 0 is a suitable indication for that. */
-
- pubkey = (gcry_pk_spec_t *) module->spec;
- nbits = (*pubkey->get_nbits) (module->mod_id, keyarr);
-
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- release_mpi_array (keyarr);
- gcry_free (keyarr);
-
- return nbits;
-}
-
-
-/* Return the so called KEYGRIP which is the SHA-1 hash of the public
- key parameters expressed in a way depended on the algorithm.
-
- ARRAY must either be 20 bytes long or NULL; in the latter case a
- newly allocated array of that size is returned, otherwise ARRAY or
- NULL is returned to indicate an error which is most likely an
- unknown algorithm. The function accepts public or secret keys. */
-unsigned char *
-gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
-{
- gcry_sexp_t list = NULL, l2 = NULL;
- gcry_pk_spec_t *pubkey = NULL;
- gcry_module_t module = NULL;
- pk_extra_spec_t *extraspec;
- const char *s;
- char *name = NULL;
- int idx;
- const char *elems;
- gcry_md_hd_t md = NULL;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- /* Check that the first element is valid. */
- list = gcry_sexp_find_token (key, "public-key", 0);
- if (! list)
- list = gcry_sexp_find_token (key, "private-key", 0);
- if (! list)
- list = gcry_sexp_find_token (key, "protected-private-key", 0);
- if (! list)
- list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
- if (! list)
- return NULL; /* No public- or private-key object. */
-
- l2 = gcry_sexp_cadr (list);
- gcry_sexp_release (list);
- list = l2;
- l2 = NULL;
-
- name = _gcry_sexp_nth_string (list, 0);
- if (!name)
- goto fail; /* Invalid structure of object. */
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- if (!module)
- goto fail; /* Unknown algorithm. */
-
- pubkey = (gcry_pk_spec_t *) module->spec;
- extraspec = module->extraspec;
-
- elems = pubkey->elements_grip;
- if (!elems)
- goto fail; /* No grip parameter. */
-
- if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
- goto fail;
-
- if (extraspec && extraspec->comp_keygrip)
- {
- /* Module specific method to compute a keygrip. */
- if (extraspec->comp_keygrip (md, list))
- goto fail;
- }
- else
- {
- /* Generic method to compute a keygrip. */
- for (idx = 0, s = elems; *s; s++, idx++)
- {
- const char *data;
- size_t datalen;
- char buf[30];
-
- l2 = gcry_sexp_find_token (list, s, 1);
- if (! l2)
- goto fail;
- data = gcry_sexp_nth_data (l2, 1, &datalen);
- if (! data)
- goto fail;
-
- snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
- gcry_md_write (md, buf, strlen (buf));
- gcry_md_write (md, data, datalen);
- gcry_sexp_release (l2);
- gcry_md_write (md, ")", 1);
- }
- }
-
- if (!array)
- {
- array = gcry_malloc (20);
- if (! array)
- goto fail;
- }
-
- memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
- gcry_md_close (md);
- gcry_sexp_release (list);
- return array;
-
- fail:
- gcry_free (name);
- gcry_sexp_release (l2);
- gcry_md_close (md);
- gcry_sexp_release (list);
- return NULL;
-}
-
-
-gcry_error_t
-gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- switch (cmd)
- {
- case GCRYCTL_DISABLE_ALGO:
- /* This one expects a buffer pointing to an integer with the
- algo number. */
- if ((! buffer) || (buflen != sizeof (int)))
- err = GPG_ERR_INV_ARG;
- else
- disable_pubkey_algo (*((int *) buffer));
- break;
-
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-
-/* Return information about the given algorithm
-
- WHAT selects the kind of information returned:
-
- GCRYCTL_TEST_ALGO:
- Returns 0 when the specified algorithm is available for use.
- Buffer must be NULL, nbytes may have the address of a variable
- with the required usage of the algorithm. It may be 0 for don't
- care or a combination of the GCRY_PK_USAGE_xxx flags;
-
- GCRYCTL_GET_ALGO_USAGE:
- Return the usage glafs for the give algo. An invalid alog
- does return 0. Disabled algos are ignored here becuase we
- only want to know whether the algo is at all capable of
- the usage.
-
- Note: Because this function is in most cases used to return an
- integer value, we can make it easier for the caller to just look at
- the return value. The caller will in all cases consult the value
- and thereby detecting whether a error occured or not (i.e. while
- checking the block size) */
-gcry_error_t
-gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- switch (what)
- {
- case GCRYCTL_TEST_ALGO:
- {
- int use = nbytes ? *nbytes : 0;
- if (buffer)
- err = GPG_ERR_INV_ARG;
- else if (check_pubkey_algo (algorithm, use))
- err = GPG_ERR_PUBKEY_ALGO;
- break;
- }
-
- case GCRYCTL_GET_ALGO_USAGE:
- {
- gcry_module_t pubkey;
- int use = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- {
- use = ((gcry_pk_spec_t *) pubkey->spec)->use;
- _gcry_module_release (pubkey);
- }
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- /* FIXME? */
- *nbytes = use;
-
- break;
- }
-
- case GCRYCTL_GET_ALGO_NPKEY:
- {
- /* FIXME? */
- int npkey = pubkey_get_npkey (algorithm);
- *nbytes = npkey;
- break;
- }
- case GCRYCTL_GET_ALGO_NSKEY:
- {
- /* FIXME? */
- int nskey = pubkey_get_nskey (algorithm);
- *nbytes = nskey;
- break;
- }
- case GCRYCTL_GET_ALGO_NSIGN:
- {
- /* FIXME? */
- int nsign = pubkey_get_nsig (algorithm);
- *nbytes = nsign;
- break;
- }
- case GCRYCTL_GET_ALGO_NENCR:
- {
- /* FIXME? */
- int nencr = pubkey_get_nenc (algorithm);
- *nbytes = nencr;
- break;
- }
-
- default:
- err = GPG_ERR_INV_OP;
- }
-
- return gcry_error (err);
-}
-
-
-/* Explicitly initialize this module. */
-gcry_err_code_t
-_gcry_pk_init (void)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- return err;
-}
-
-
-gcry_err_code_t
-_gcry_pk_module_lookup (int algorithm, gcry_module_t *module)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_module_t pubkey;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
- if (pubkey)
- *module = pubkey;
- else
- err = GPG_ERR_PUBKEY_ALGO;
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return err;
-}
-
-
-void
-_gcry_pk_module_release (gcry_module_t module)
-{
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
-}
-
-/* Get a list consisting of the IDs of the loaded pubkey modules. If
- LIST is zero, write the number of loaded pubkey modules to
- LIST_LENGTH and return. If LIST is non-zero, the first
- *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
- according size. In case there are less pubkey modules than
- *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
-gcry_error_t
-gcry_pk_list (int *list, int *list_length)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- err = _gcry_module_list (pubkeys_registered, list, list_length);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- return err;
-}
-
-
-/* Run the selftests for pubkey algorithm ALGO with optional reporting
- function REPORT. */
-gpg_error_t
-_gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
-{
- gcry_module_t module = NULL;
- pk_extra_spec_t *extraspec = NULL;
- gcry_err_code_t ec = 0;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = _gcry_module_lookup_id (pubkeys_registered, algo);
- if (module && !(module->flags & FLAG_MODULE_DISABLED))
- extraspec = module->extraspec;
- ath_mutex_unlock (&pubkeys_registered_lock);
- if (extraspec && extraspec->selftest)
- ec = extraspec->selftest (algo, extended, report);
- else
- {
- ec = GPG_ERR_PUBKEY_ALGO;
- if (report)
- report ("pubkey", algo, "module",
- module && !(module->flags & FLAG_MODULE_DISABLED)?
- "no selftest available" :
- module? "algorithm disabled" : "algorithm not found");
- }
-
- if (module)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
- return gpg_error (ec);
-}
-
-
-/* This function is only used by ac.c! */
-gcry_err_code_t
-_gcry_pk_get_elements (int algo, char **enc, char **sig)
-{
- gcry_module_t pubkey;
- gcry_pk_spec_t *spec;
- gcry_err_code_t err;
- char *enc_cp;
- char *sig_cp;
-
- REGISTER_DEFAULT_PUBKEYS;
-
- enc_cp = NULL;
- sig_cp = NULL;
- spec = NULL;
-
- pubkey = _gcry_module_lookup_id (pubkeys_registered, algo);
- if (! pubkey)
- {
- err = GPG_ERR_INTERNAL;
- goto out;
- }
- spec = pubkey->spec;
-
- if (enc)
- {
- enc_cp = strdup (spec->elements_enc);
- if (! enc_cp)
- {
- err = gpg_err_code_from_errno (errno);
- goto out;
- }
- }
-
- if (sig)
- {
- sig_cp = strdup (spec->elements_sig);
- if (! sig_cp)
- {
- err = gpg_err_code_from_errno (errno);
- goto out;
- }
- }
-
- if (enc)
- *enc = enc_cp;
- if (sig)
- *sig = sig_cp;
- err = 0;
-
- out:
-
- _gcry_module_release (pubkey);
- if (err)
- {
- free (enc_cp);
- free (sig_cp);
- }
-
- return err;
-}
+/* pubkey.c - pubkey dispatcher
+ * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
+ * 2007, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "cipher.h"
+#include "ath.h"
+
+
+static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
+ gcry_mpi_t *data, gcry_mpi_t *skey,
+ int flags);
+static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
+ gcry_mpi_t hash, gcry_mpi_t *skey);
+static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
+ gcry_mpi_t *data, gcry_mpi_t *pkey,
+ int (*cmp) (void *, gcry_mpi_t),
+ void *opaque);
+
+
+/* A dummy extraspec so that we do not need to tests the extraspec
+ field from the module specification against NULL and instead
+ directly test the respective fields of extraspecs. */
+static pk_extra_spec_t dummy_extra_spec;
+
+
+/* This is the list of the default public-key ciphers included in
+ libgcrypt. FIPS_ALLOWED indicated whether the algorithm is used in
+ FIPS mode. */
+static struct pubkey_table_entry
+{
+ gcry_pk_spec_t *pubkey;
+ pk_extra_spec_t *extraspec;
+ unsigned int algorithm;
+ int fips_allowed;
+} pubkey_table[] =
+ {
+#if USE_RSA
+ { &_gcry_pubkey_spec_rsa,
+ &_gcry_pubkey_extraspec_rsa, GCRY_PK_RSA, 1},
+#endif
+#if USE_ELGAMAL
+ { &_gcry_pubkey_spec_elg,
+ &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG },
+ { &_gcry_pubkey_spec_elg,
+ &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG_E },
+#endif
+#if USE_DSA
+ { &_gcry_pubkey_spec_dsa,
+ &_gcry_pubkey_extraspec_dsa, GCRY_PK_DSA, 1 },
+#endif
+#if USE_ECC
+ { &_gcry_pubkey_spec_ecdsa,
+ &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 },
+#endif
+ { NULL, 0 },
+ };
+
+/* List of registered ciphers. */
+static gcry_module_t pubkeys_registered;
+
+/* This is the lock protecting PUBKEYS_REGISTERED. */
+static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;;
+
+/* Flag to check whether the default pubkeys have already been
+ registered. */
+static int default_pubkeys_registered;
+
+/* Convenient macro for registering the default digests. */
+#define REGISTER_DEFAULT_PUBKEYS \
+ do \
+ { \
+ ath_mutex_lock (&pubkeys_registered_lock); \
+ if (! default_pubkeys_registered) \
+ { \
+ pk_register_default (); \
+ default_pubkeys_registered = 1; \
+ } \
+ ath_mutex_unlock (&pubkeys_registered_lock); \
+ } \
+ while (0)
+
+/* These dummy functions are used in case a cipher implementation
+ refuses to provide it's own functions. */
+
+static gcry_err_code_t
+dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
+ gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+{
+ (void)algorithm;
+ (void)nbits;
+ (void)dummy;
+ (void)skey;
+ (void)retfactors;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static gcry_err_code_t
+dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
+{
+ (void)algorithm;
+ (void)skey;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static gcry_err_code_t
+dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
+ gcry_mpi_t *pkey, int flags)
+{
+ (void)algorithm;
+ (void)resarr;
+ (void)data;
+ (void)pkey;
+ (void)flags;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static gcry_err_code_t
+dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
+ gcry_mpi_t *skey, int flags)
+{
+ (void)algorithm;
+ (void)result;
+ (void)data;
+ (void)skey;
+ (void)flags;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static gcry_err_code_t
+dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
+ gcry_mpi_t *skey)
+{
+ (void)algorithm;
+ (void)resarr;
+ (void)data;
+ (void)skey;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static gcry_err_code_t
+dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
+ gcry_mpi_t *pkey,
+ int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+{
+ (void)algorithm;
+ (void)hash;
+ (void)data;
+ (void)pkey;
+ (void)cmp;
+ (void)opaquev;
+ fips_signal_error ("using dummy public key function");
+ return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+static unsigned
+dummy_get_nbits (int algorithm, gcry_mpi_t *pkey)
+{
+ (void)algorithm;
+ (void)pkey;
+ fips_signal_error ("using dummy public key function");
+ return 0;
+}
+
+/* Internal function. Register all the pubkeys included in
+ PUBKEY_TABLE. Returns zero on success or an error code. */
+static void
+pk_register_default (void)
+{
+ gcry_err_code_t err = 0;
+ int i;
+
+ for (i = 0; (! err) && pubkey_table[i].pubkey; i++)
+ {
+#define pubkey_use_dummy(func) \
+ if (! pubkey_table[i].pubkey->func) \
+ pubkey_table[i].pubkey->func = dummy_##func;
+
+ pubkey_use_dummy (generate);
+ pubkey_use_dummy (check_secret_key);
+ pubkey_use_dummy (encrypt);
+ pubkey_use_dummy (decrypt);
+ pubkey_use_dummy (sign);
+ pubkey_use_dummy (verify);
+ pubkey_use_dummy (get_nbits);
+#undef pubkey_use_dummy
+
+ err = _gcry_module_add (&pubkeys_registered,
+ pubkey_table[i].algorithm,
+ (void *) pubkey_table[i].pubkey,
+ (void *) pubkey_table[i].extraspec,
+ NULL);
+ }
+
+ if (err)
+ BUG ();
+}
+
+/* Internal callback function. Used via _gcry_module_lookup. */
+static int
+gcry_pk_lookup_func_name (void *spec, void *data)
+{
+ gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec;
+ char *name = (char *) data;
+ const char **aliases = pubkey->aliases;
+ int ret = _stricmp (name, pubkey->name);
+
+ while (ret && *aliases)
+ ret = _stricmp (name, *aliases++);
+
+ return ! ret;
+}
+
+/* Internal function. Lookup a pubkey entry by it's name. */
+static gcry_module_t
+gcry_pk_lookup_name (const char *name)
+{
+ gcry_module_t pubkey;
+
+ pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name,
+ gcry_pk_lookup_func_name);
+
+ return pubkey;
+}
+
+/* Register a new pubkey module whose specification can be found in
+ PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID
+ and a pointer representhing this module is stored in MODULE. */
+gcry_error_t
+_gcry_pk_register (gcry_pk_spec_t *pubkey,
+ pk_extra_spec_t *extraspec,
+ unsigned int *algorithm_id,
+ gcry_module_t *module)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_module_t mod;
+
+ /* We do not support module loading in fips mode. */
+ if (fips_mode ())
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ err = _gcry_module_add (&pubkeys_registered, 0,
+ (void *) pubkey,
+ (void *)(extraspec? extraspec : &dummy_extra_spec),
+ &mod);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (! err)
+ {
+ *module = mod;
+ *algorithm_id = mod->mod_id;
+ }
+
+ return err;
+}
+
+/* Unregister the pubkey identified by ID, which must have been
+ registered with gcry_pk_register. */
+void
+gcry_pk_unregister (gcry_module_t module)
+{
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+}
+
+static void
+release_mpi_array (gcry_mpi_t *array)
+{
+ for (; *array; array++)
+ {
+ mpi_free(*array);
+ *array = NULL;
+ }
+}
+
+/****************
+ * Map a string to the pubkey algo
+ */
+int
+gcry_pk_map_name (const char *string)
+{
+ gcry_module_t pubkey;
+ int algorithm = 0;
+
+ if (!string)
+ return 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = gcry_pk_lookup_name (string);
+ if (pubkey)
+ {
+ algorithm = pubkey->mod_id;
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return algorithm;
+}
+
+
+/* Map the public key algorithm whose ID is contained in ALGORITHM to
+ a string representation of the algorithm name. For unknown
+ algorithm IDs this functions returns "?". */
+const char *
+gcry_pk_algo_name (int algorithm)
+{
+ gcry_module_t pubkey;
+ const char *name;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ name = ((gcry_pk_spec_t *) pubkey->spec)->name;
+ _gcry_module_release (pubkey);
+ }
+ else
+ name = "?";
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return name;
+}
+
+
+/* A special version of gcry_pk_algo name to return the first aliased
+ name of the algorithm. This is required to adhere to the spki
+ specs where the algorithm names are lowercase. */
+const char *
+_gcry_pk_aliased_algo_name (int algorithm)
+{
+ const char *name = NULL;
+ gcry_module_t module;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec;
+
+ name = pubkey->aliases? *pubkey->aliases : NULL;
+ if (!name || !*name)
+ name = pubkey->name;
+ _gcry_module_release (module);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return name;
+}
+
+
+static void
+disable_pubkey_algo (int algorithm)
+{
+ gcry_module_t pubkey;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ if (! (pubkey-> flags & FLAG_MODULE_DISABLED))
+ pubkey->flags |= FLAG_MODULE_DISABLED;
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+}
+
+
+/****************
+ * A USE of 0 means: don't care.
+ */
+static gcry_err_code_t
+check_pubkey_algo (int algorithm, unsigned use)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_pk_spec_t *pubkey;
+ gcry_module_t module;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+
+ if (((use & GCRY_PK_USAGE_SIGN)
+ && (! (pubkey->use & GCRY_PK_USAGE_SIGN)))
+ || ((use & GCRY_PK_USAGE_ENCR)
+ && (! (pubkey->use & GCRY_PK_USAGE_ENCR))))
+ err = GPG_ERR_WRONG_PUBKEY_ALGO;
+ else if (module->flags & FLAG_MODULE_DISABLED)
+ err = GPG_ERR_PUBKEY_ALGO;
+ _gcry_module_release (module);
+ }
+ else
+ err = GPG_ERR_PUBKEY_ALGO;
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return err;
+}
+
+
+/****************
+ * Return the number of public key material numbers
+ */
+static int
+pubkey_get_npkey (int algorithm)
+{
+ gcry_module_t pubkey;
+ int npkey = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey);
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return npkey;
+}
+
+/****************
+ * Return the number of secret key material numbers
+ */
+static int
+pubkey_get_nskey (int algorithm)
+{
+ gcry_module_t pubkey;
+ int nskey = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey);
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return nskey;
+}
+
+/****************
+ * Return the number of signature material numbers
+ */
+static int
+pubkey_get_nsig (int algorithm)
+{
+ gcry_module_t pubkey;
+ int nsig = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig);
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return nsig;
+}
+
+/****************
+ * Return the number of encryption material numbers
+ */
+static int
+pubkey_get_nenc (int algorithm)
+{
+ gcry_module_t pubkey;
+ int nenc = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc);
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return nenc;
+}
+
+
+/* Generate a new public key with algorithm ALGORITHM of size NBITS
+ and return it at SKEY. USE_E depends on the ALGORITHM. GENPARMS
+ is passed to the algorithm module if it features an extended
+ generation function. RETFACTOR is used by some algorithms to
+ return certain additional information which are in general not
+ required.
+
+ The function returns the error code number or 0 on success. */
+static gcry_err_code_t
+pubkey_generate (int algorithm,
+ unsigned int nbits,
+ unsigned long use_e,
+ gcry_sexp_t genparms,
+ gcry_mpi_t *skey, gcry_mpi_t **retfactors,
+ gcry_sexp_t *r_extrainfo)
+{
+ gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO;
+ gcry_module_t pubkey;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ pk_extra_spec_t *extraspec = pubkey->extraspec;
+
+ if (extraspec && extraspec->ext_generate)
+ {
+ /* Use the extended generate function. */
+ ec = extraspec->ext_generate
+ (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo);
+ }
+ else
+ {
+ /* Use the standard generate function. */
+ ec = ((gcry_pk_spec_t *) pubkey->spec)->generate
+ (algorithm, nbits, use_e, skey, retfactors);
+ }
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return ec;
+}
+
+
+static gcry_err_code_t
+pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey)
+{
+ gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
+ gcry_module_t pubkey;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key
+ (algorithm, skey);
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return err;
+}
+
+
+/****************
+ * This is the interface to the public key encryption. Encrypt DATA
+ * with PKEY and put it into RESARR which should be an array of MPIs
+ * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
+ * check with pubkey_get_nenc() )
+ */
+static gcry_err_code_t
+pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
+ gcry_mpi_t *pkey, int flags)
+{
+ gcry_pk_spec_t *pubkey;
+ gcry_module_t module;
+ gcry_err_code_t rc;
+ int i;
+
+ /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as
+ an extra failsafe protection we explicitly test for fips mode
+ here. */
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("pubkey_encrypt: algo=%d\n", algorithm);
+ for(i = 0; i < pubkey_get_npkey (algorithm); i++)
+ log_mpidump (" pkey:", pkey[i]);
+ log_mpidump (" data:", data);
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags);
+ _gcry_module_release (module);
+ goto ready;
+ }
+ rc = GPG_ERR_PUBKEY_ALGO;
+
+ ready:
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!rc && DBG_CIPHER && !fips_mode ())
+ {
+ for(i = 0; i < pubkey_get_nenc (algorithm); i++)
+ log_mpidump(" encr:", resarr[i] );
+ }
+ return rc;
+}
+
+
+/****************
+ * This is the interface to the public key decryption.
+ * ALGO gives the algorithm to use and this implicitly determines
+ * the size of the arrays.
+ * result is a pointer to a mpi variable which will receive a
+ * newly allocated mpi or NULL in case of an error.
+ */
+static gcry_err_code_t
+pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
+ gcry_mpi_t *skey, int flags)
+{
+ gcry_pk_spec_t *pubkey;
+ gcry_module_t module;
+ gcry_err_code_t rc;
+ int i;
+
+ *result = NULL; /* so the caller can always do a mpi_free */
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("pubkey_decrypt: algo=%d\n", algorithm);
+ for(i = 0; i < pubkey_get_nskey (algorithm); i++)
+ log_mpidump (" skey:", skey[i]);
+ for(i = 0; i < pubkey_get_nenc (algorithm); i++)
+ log_mpidump (" data:", data[i]);
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ rc = pubkey->decrypt (algorithm, result, data, skey, flags);
+ _gcry_module_release (module);
+ goto ready;
+ }
+
+ rc = GPG_ERR_PUBKEY_ALGO;
+
+ ready:
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!rc && DBG_CIPHER && !fips_mode ())
+ log_mpidump (" plain:", *result);
+
+ return rc;
+}
+
+
+/****************
+ * This is the interface to the public key signing.
+ * Sign data with skey and put the result into resarr which
+ * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
+ * algorithm allows this - check with pubkey_get_nsig() )
+ */
+static gcry_err_code_t
+pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
+ gcry_mpi_t *skey)
+{
+ gcry_pk_spec_t *pubkey;
+ gcry_module_t module;
+ gcry_err_code_t rc;
+ int i;
+
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("pubkey_sign: algo=%d\n", algorithm);
+ for(i = 0; i < pubkey_get_nskey (algorithm); i++)
+ log_mpidump (" skey:", skey[i]);
+ log_mpidump(" data:", data );
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ rc = pubkey->sign (algorithm, resarr, data, skey);
+ _gcry_module_release (module);
+ goto ready;
+ }
+
+ rc = GPG_ERR_PUBKEY_ALGO;
+
+ ready:
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!rc && DBG_CIPHER && !fips_mode ())
+ for (i = 0; i < pubkey_get_nsig (algorithm); i++)
+ log_mpidump (" sig:", resarr[i]);
+
+ return rc;
+}
+
+/****************
+ * Verify a public key signature.
+ * Return 0 if the signature is good
+ */
+static gcry_err_code_t
+pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
+ gcry_mpi_t *pkey,
+ int (*cmp)(void *, gcry_mpi_t), void *opaquev)
+{
+ gcry_pk_spec_t *pubkey;
+ gcry_module_t module;
+ gcry_err_code_t rc;
+ int i;
+
+ if (DBG_CIPHER && !fips_mode ())
+ {
+ log_debug ("pubkey_verify: algo=%d\n", algorithm);
+ for (i = 0; i < pubkey_get_npkey (algorithm); i++)
+ log_mpidump (" pkey:", pkey[i]);
+ for (i = 0; i < pubkey_get_nsig (algorithm); i++)
+ log_mpidump (" sig:", data[i]);
+ log_mpidump (" hash:", hash);
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (module)
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev);
+ _gcry_module_release (module);
+ goto ready;
+ }
+
+ rc = GPG_ERR_PUBKEY_ALGO;
+
+ ready:
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ return rc;
+}
+
+
+/* Internal function. */
+static gcry_err_code_t
+sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
+ gcry_mpi_t *elements, const char *algo_name)
+{
+ gcry_err_code_t err = 0;
+ int i, idx;
+ const char *name;
+ gcry_sexp_t list;
+
+ for (name = element_names, idx = 0; *name && !err; name++, idx++)
+ {
+ list = gcry_sexp_find_token (key_sexp, name, 1);
+ if (!list)
+ elements[idx] = NULL;
+ else
+ {
+ elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release (list);
+ if (!elements[idx])
+ err = GPG_ERR_INV_OBJ;
+ }
+ }
+
+ if (!err)
+ {
+ /* Check that all elements are available. */
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ if (!elements[idx])
+ break;
+ if (*name)
+ {
+ err = GPG_ERR_NO_OBJ;
+ /* Some are missing. Before bailing out we test for
+ optional parameters. */
+ if (algo_name && !strcmp (algo_name, "RSA")
+ && !strcmp (element_names, "nedpqu") )
+ {
+ /* This is RSA. Test whether we got N, E and D and that
+ the optional P, Q and U are all missing. */
+ if (elements[0] && elements[1] && elements[2]
+ && !elements[3] && !elements[4] && !elements[5])
+ err = 0;
+ }
+ }
+ }
+
+
+ if (err)
+ {
+ for (i = 0; i < idx; i++)
+ if (elements[i])
+ gcry_free (elements[i]);
+ }
+ return err;
+}
+
+
+/* Internal function used for ecc. Note, that this function makes use
+ of its intimate knowledge about the ECC parameters from ecc.c. */
+static gcry_err_code_t
+sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
+ gcry_mpi_t *elements, pk_extra_spec_t *extraspec)
+
+{
+ gcry_err_code_t err = 0;
+ int idx;
+ const char *name;
+ gcry_sexp_t list;
+
+ /* Clear the array for easier error cleanup. */
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ elements[idx] = NULL;
+ gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */
+
+ /* Init the array with the available curve parameters. */
+ for (name = element_names, idx = 0; *name && !err; name++, idx++)
+ {
+ list = gcry_sexp_find_token (key_sexp, name, 1);
+ if (!list)
+ elements[idx] = NULL;
+ else
+ {
+ elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release (list);
+ if (!elements[idx])
+ {
+ err = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+ }
+ }
+
+ /* Check whether a curve parameter has been given and then fill any
+ missing elements. */
+ list = gcry_sexp_find_token (key_sexp, "curve", 5);
+ if (list)
+ {
+ if (extraspec->get_param)
+ {
+ char *curve;
+ gcry_mpi_t params[6];
+
+ for (idx = 0; idx < DIM(params); idx++)
+ params[idx] = NULL;
+
+ curve = _gcry_sexp_nth_string (list, 1);
+ gcry_sexp_release (list);
+ if (!curve)
+ {
+ /* No curve name given (or out of core). */
+ err = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+ err = extraspec->get_param (curve, params);
+ gcry_free (curve);
+ if (err)
+ goto leave;
+
+ for (idx = 0; idx < DIM(params); idx++)
+ {
+ if (!elements[idx])
+ elements[idx] = params[idx];
+ else
+ mpi_free (params[idx]);
+ }
+ }
+ else
+ {
+ gcry_sexp_release (list);
+ err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
+ goto leave;
+ }
+ }
+
+ /* Check that all parameters are known. */
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ if (!elements[idx])
+ {
+ err = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+
+ leave:
+ if (err)
+ {
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ if (elements[idx])
+ gcry_free (elements[idx]);
+ }
+ return err;
+}
+
+
+
+/****************
+ * Convert a S-Exp with either a private or a public key to our
+ * internal format. Currently we do only support the following
+ * algorithms:
+ * dsa
+ * rsa
+ * openpgp-dsa
+ * openpgp-rsa
+ * openpgp-elg
+ * openpgp-elg-sig
+ * ecdsa
+ * Provide a SE with the first element be either "private-key" or
+ * or "public-key". It is followed by a list with its first element
+ * be one of the above algorithm identifiers and the remaning
+ * elements are pairs with parameter-id and value.
+ * NOTE: we look through the list to find a list beginning with
+ * "private-key" or "public-key" - the first one found is used.
+ *
+ * Returns: A pointer to an allocated array of MPIs if the return value is
+ * zero; the caller has to release this array.
+ *
+ * Example of a DSA public key:
+ * (private-key
+ * (dsa
+ * (p <mpi>)
+ * (g <mpi>)
+ * (y <mpi>)
+ * (x <mpi>)
+ * )
+ * )
+ * The <mpi> are expected to be in GCRYMPI_FMT_USG
+ */
+static gcry_err_code_t
+sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
+ gcry_module_t *retalgo)
+{
+ gcry_err_code_t err = 0;
+ gcry_sexp_t list, l2;
+ char *name;
+ const char *elems;
+ gcry_mpi_t *array;
+ gcry_module_t module;
+ gcry_pk_spec_t *pubkey;
+ pk_extra_spec_t *extraspec;
+ int is_ecc;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token (sexp,
+ want_private? "private-key":"public-key", 0);
+ if (!list)
+ return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
+
+ l2 = gcry_sexp_cadr( list );
+ gcry_sexp_release ( list );
+ list = l2;
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
+ {
+ gcry_sexp_release ( list );
+ return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ /* Fixme: We should make sure that an ECC key is always named "ecc"
+ and not "ecdsa". "ecdsa" should be used for the signature
+ itself. We need a function to test whether an algorithm given
+ with a key is compatible with an application of the key (signing,
+ encryption). For RSA this is easy, but ECC is the first
+ algorithm which has many flavours. */
+ is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") );
+ gcry_free (name);
+
+ if (!module)
+ {
+ gcry_sexp_release (list);
+ return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ }
+ else
+ {
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ extraspec = module->extraspec;
+ }
+
+ elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
+ array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
+ if (!array)
+ err = gpg_err_code_from_errno (errno);
+ if (!err)
+ {
+ if (is_ecc)
+ err = sexp_elements_extract_ecc (list, elems, array, extraspec);
+ else
+ err = sexp_elements_extract (list, elems, array, pubkey->name);
+ }
+
+ gcry_sexp_release (list);
+
+ if (err)
+ {
+ gcry_free (array);
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+ else
+ {
+ *retarray = array;
+ *retalgo = module;
+ }
+
+ return err;
+}
+
+
+static gcry_err_code_t
+sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
+ gcry_module_t *retalgo)
+{
+ gcry_err_code_t err = 0;
+ gcry_sexp_t list, l2;
+ char *name;
+ const char *elems;
+ gcry_mpi_t *array;
+ gcry_module_t module;
+ gcry_pk_spec_t *pubkey;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
+ if (!list)
+ return GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */
+
+ l2 = gcry_sexp_nth (list, 1);
+ if (!l2)
+ {
+ gcry_sexp_release (list);
+ return GPG_ERR_NO_OBJ; /* No cadr for the sig object. */
+ }
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
+ {
+ gcry_sexp_release (list);
+ gcry_sexp_release (l2);
+ return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
+ }
+ else if (!strcmp (name, "flags"))
+ {
+ /* Skip flags, since they are not used but here just for the
+ sake of consistent S-expressions. */
+ gcry_free (name);
+ gcry_sexp_release (l2);
+ l2 = gcry_sexp_nth (list, 2);
+ if (!l2)
+ {
+ gcry_sexp_release (list);
+ return GPG_ERR_INV_OBJ;
+ }
+ name = _gcry_sexp_nth_string (l2, 0);
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ gcry_free (name);
+ name = NULL;
+
+ if (!module)
+ {
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+ return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ }
+ else
+ pubkey = (gcry_pk_spec_t *) module->spec;
+
+ elems = pubkey->elements_sig;
+ array = gcry_calloc (strlen (elems) + 1 , sizeof *array );
+ if (!array)
+ err = gpg_err_code_from_errno (errno);
+
+ if (!err)
+ err = sexp_elements_extract (list, elems, array, NULL);
+
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+
+ if (err)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ gcry_free (array);
+ }
+ else
+ {
+ *retarray = array;
+ *retalgo = module;
+ }
+
+ return err;
+}
+
+
+/****************
+ * Take sexp and return an array of MPI as used for our internal decrypt
+ * function.
+ * s_data = (enc-val
+ * [(flags [pkcs1])]
+ * (<algo>
+ * (<param_name1> <mpi>)
+ * ...
+ * (<param_namen> <mpi>)
+ * ))
+ * RET_MODERN is set to true when at least an empty flags list has been found.
+ */
+static gcry_err_code_t
+sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
+ int *ret_modern, int *ret_want_pkcs1, int *flags)
+{
+ gcry_err_code_t err = 0;
+ gcry_sexp_t list = NULL, l2 = NULL;
+ gcry_pk_spec_t *pubkey = NULL;
+ gcry_module_t module = NULL;
+ char *name = NULL;
+ size_t n;
+ int parsed_flags = 0;
+ const char *elems;
+ gcry_mpi_t *array = NULL;
+
+ *ret_want_pkcs1 = 0;
+ *ret_modern = 0;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token (sexp, "enc-val" , 0);
+ if (!list)
+ {
+ err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object. */
+ goto leave;
+ }
+
+ l2 = gcry_sexp_nth (list, 1);
+ if (!l2)
+ {
+ err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
+ goto leave;
+ }
+
+ /* Extract identifier of sublist. */
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
+ {
+ err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
+ goto leave;
+ }
+
+ if (!strcmp (name, "flags"))
+ {
+ /* There is a flags element - process it. */
+ const char *s;
+ int i;
+
+ *ret_modern = 1;
+ for (i = gcry_sexp_length (l2) - 1; i > 0; i--)
+ {
+ s = gcry_sexp_nth_data (l2, i, &n);
+ if (! s)
+ ; /* Not a data element - ignore. */
+ else if (n == 3 && !memcmp (s, "raw", 3))
+ ; /* This is just a dummy as it is the default. */
+ else if (n == 5 && !memcmp (s, "pkcs1", 5))
+ *ret_want_pkcs1 = 1;
+ else if (n == 11 && ! memcmp (s, "no-blinding", 11))
+ parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
+ else
+ {
+ err = GPG_ERR_INV_FLAG;
+ goto leave;
+ }
+ }
+
+ /* Get the next which has the actual data. */
+ gcry_sexp_release (l2);
+ l2 = gcry_sexp_nth (list, 2);
+ if (!l2)
+ {
+ err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
+ goto leave;
+ }
+
+ /* Extract sublist identifier. */
+ gcry_free (name);
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
+ {
+ err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
+ goto leave;
+ }
+
+ gcry_sexp_release (list);
+ list = l2;
+ l2 = NULL;
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!module)
+ {
+ err = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ goto leave;
+ }
+ pubkey = (gcry_pk_spec_t *) module->spec;
+
+ elems = pubkey->elements_enc;
+ array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
+ if (!array)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ err = sexp_elements_extract (list, elems, array, NULL);
+
+ leave:
+ gcry_sexp_release (list);
+ gcry_sexp_release (l2);
+ gcry_free (name);
+
+ if (err)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ gcry_free (array);
+ }
+ else
+ {
+ *retarray = array;
+ *retalgo = module;
+ *flags = parsed_flags;
+ }
+
+ return err;
+}
+
+/* Take the hash value and convert into an MPI, suitable for
+ passing to the low level functions. We currently support the
+ old style way of passing just a MPI and the modern interface which
+ allows to pass flags so that we can choose between raw and pkcs1
+ padding - may be more padding options later.
+
+ (<mpi>)
+ or
+ (data
+ [(flags [pkcs1])]
+ [(hash <algo> <value>)]
+ [(value <text>)]
+ )
+
+ Either the VALUE or the HASH element must be present for use
+ with signatures. VALUE is used for encryption.
+
+ NBITS is the length of the key in bits.
+
+*/
+static gcry_err_code_t
+sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
+ int for_encryption, int *flags)
+{
+ gcry_err_code_t rc = 0;
+ gcry_sexp_t ldata, lhash, lvalue;
+ int i;
+ size_t n;
+ const char *s;
+ int is_raw = 0, is_pkcs1 = 0, unknown_flag=0;
+ int parsed_flags = 0, dummy_flags;
+
+ if (! flags)
+ flags = &dummy_flags;
+
+ *ret_mpi = NULL;
+ ldata = gcry_sexp_find_token (input, "data", 0);
+ if (!ldata)
+ { /* assume old style */
+ *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
+ return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
+ }
+
+ /* see whether there is a flags object */
+ {
+ gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
+ if (lflags)
+ { /* parse the flags list. */
+ for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
+ {
+ s = gcry_sexp_nth_data (lflags, i, &n);
+ if (!s)
+ ; /* not a data element*/
+ else if ( n == 3 && !memcmp (s, "raw", 3))
+ is_raw = 1;
+ else if ( n == 5 && !memcmp (s, "pkcs1", 5))
+ is_pkcs1 = 1;
+ else if (n == 11 && ! memcmp (s, "no-blinding", 11))
+ parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
+ else
+ unknown_flag = 1;
+ }
+ gcry_sexp_release (lflags);
+ }
+ }
+
+ if (!is_pkcs1 && !is_raw)
+ is_raw = 1; /* default to raw */
+
+ /* Get HASH or MPI */
+ lhash = gcry_sexp_find_token (ldata, "hash", 0);
+ lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
+
+ if (!(!lhash ^ !lvalue))
+ rc = GPG_ERR_INV_OBJ; /* none or both given */
+ else if (unknown_flag)
+ rc = GPG_ERR_INV_FLAG;
+ else if (is_raw && is_pkcs1 && !for_encryption)
+ rc = GPG_ERR_CONFLICT;
+ else if (is_raw && lvalue)
+ {
+ *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0);
+ if (!*ret_mpi)
+ rc = GPG_ERR_INV_OBJ;
+ }
+ else if (is_pkcs1 && lvalue && for_encryption)
+ {
+ /* Create pkcs#1 block type 2 padding. */
+ unsigned char *frame = NULL;
+ size_t nframe = (nbits+7) / 8;
+ const void * value;
+ size_t valuelen;
+ unsigned char *p;
+
+ if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
+ rc = GPG_ERR_INV_OBJ;
+ else if (valuelen + 7 > nframe || !nframe)
+ {
+ /* Can't encode a VALUELEN value in a NFRAME bytes frame. */
+ rc = GPG_ERR_TOO_SHORT; /* the key is too short */
+ }
+ else if ( !(frame = gcry_malloc_secure (nframe)))
+ rc = gpg_err_code_from_errno (errno);
+ else
+ {
+ n = 0;
+ frame[n++] = 0;
+ frame[n++] = 2; /* block type */
+ i = nframe - 3 - valuelen;
+ gcry_assert (i > 0);
+ p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
+ /* Replace zero bytes by new values. */
+ for (;;)
+ {
+ int j, k;
+ unsigned char *pp;
+
+ /* Count the zero bytes. */
+ for (j=k=0; j < i; j++)
+ {
+ if (!p[j])
+ k++;
+ }
+ if (!k)
+ break; /* Okay: no (more) zero bytes. */
+
+ k += k/128 + 3; /* Better get some more. */
+ pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
+ for (j=0; j < i && k; )
+ {
+ if (!p[j])
+ p[j] = pp[--k];
+ if (p[j])
+ j++;
+ }
+ gcry_free (pp);
+ }
+ memcpy (frame+n, p, i);
+ n += i;
+ gcry_free (p);
+
+ frame[n++] = 0;
+ memcpy (frame+n, value, valuelen);
+ n += valuelen;
+ gcry_assert (n == nframe);
+
+ /* FIXME, error checking? */
+ gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
+ }
+
+ gcry_free(frame);
+ }
+ else if (is_pkcs1 && lhash && !for_encryption)
+ {
+ /* Create pkcs#1 block type 1 padding. */
+ if (gcry_sexp_length (lhash) != 3)
+ rc = GPG_ERR_INV_OBJ;
+ else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
+ rc = GPG_ERR_INV_OBJ;
+ else
+ {
+ static struct { const char *name; int algo; } hashnames[] =
+ { { "sha1", GCRY_MD_SHA1 },
+ { "md5", GCRY_MD_MD5 },
+ { "sha256", GCRY_MD_SHA256 },
+ { "ripemd160", GCRY_MD_RMD160 },
+ { "rmd160", GCRY_MD_RMD160 },
+ { "sha384", GCRY_MD_SHA384 },
+ { "sha512", GCRY_MD_SHA512 },
+ { "sha224", GCRY_MD_SHA224 },
+ { "md2", GCRY_MD_MD2 },
+ { "md4", GCRY_MD_MD4 },
+ { "tiger", GCRY_MD_TIGER },
+ { "haval", GCRY_MD_HAVAL },
+ { NULL, 0 }
+ };
+ int algo;
+ byte asn[100];
+ byte *frame = NULL;
+ size_t nframe = (nbits+7) / 8;
+ const void * value;
+ size_t valuelen;
+ size_t asnlen, dlen;
+
+ for (i=0; hashnames[i].name; i++)
+ {
+ if ( strlen (hashnames[i].name) == n
+ && !memcmp (hashnames[i].name, s, n))
+ break;
+ }
+ if (hashnames[i].name)
+ algo = hashnames[i].algo;
+ else
+ {
+ /* In case of not listed or dynamically allocated hash
+ algorithm we fall back to this somewhat slower
+ method. Further, it also allows to use OIDs as
+ algorithm names. */
+ char *tmpname;
+
+ tmpname = gcry_malloc (n+1);
+ if (!tmpname)
+ algo = 0; /* Out of core - silently give up. */
+ else
+ {
+ memcpy (tmpname, s, n);
+ tmpname[n] = 0;
+ algo = gcry_md_map_name (tmpname);
+ gcry_free (tmpname);
+ }
+ }
+
+ asnlen = DIM(asn);
+ dlen = gcry_md_get_algo_dlen (algo);
+
+ if (!algo)
+ rc = GPG_ERR_DIGEST_ALGO;
+ else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
+ || !valuelen )
+ rc = GPG_ERR_INV_OBJ;
+ else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
+ {
+ /* We don't have yet all of the above algorithms. */
+ rc = GPG_ERR_NOT_IMPLEMENTED;
+ }
+ else if ( valuelen != dlen )
+ {
+ /* Hash value does not match the length of digest for
+ the given algorithm. */
+ rc = GPG_ERR_CONFLICT;
+ }
+ else if( !dlen || dlen + asnlen + 4 > nframe)
+ {
+ /* Can't encode an DLEN byte digest MD into a NFRAME
+ byte frame. */
+ rc = GPG_ERR_TOO_SHORT;
+ }
+ else if ( !(frame = gcry_malloc (nframe)) )
+ rc = gpg_err_code_from_errno (errno);
+ else
+ { /* Assemble the pkcs#1 block type 1. */
+ n = 0;
+ frame[n++] = 0;
+ frame[n++] = 1; /* block type */
+ i = nframe - valuelen - asnlen - 3 ;
+ gcry_assert (i > 1);
+ memset (frame+n, 0xff, i );
+ n += i;
+ frame[n++] = 0;
+ memcpy (frame+n, asn, asnlen);
+ n += asnlen;
+ memcpy (frame+n, value, valuelen );
+ n += valuelen;
+ gcry_assert (n == nframe);
+
+ /* Convert it into an MPI. FIXME: error checking? */
+ gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
+ }
+
+ gcry_free (frame);
+ }
+ }
+ else
+ rc = GPG_ERR_CONFLICT;
+
+ gcry_sexp_release (ldata);
+ gcry_sexp_release (lhash);
+ gcry_sexp_release (lvalue);
+
+ if (!rc)
+ *flags = parsed_flags;
+
+ return rc;
+}
+
+
+/*
+ Do a PK encrypt operation
+
+ Caller has to provide a public key as the SEXP pkey and data as a
+ SEXP with just one MPI in it. Alternatively S_DATA might be a
+ complex S-Expression, similar to the one used for signature
+ verification. This provides a flag which allows to handle PKCS#1
+ block type 2 padding. The function returns a a sexp which may be
+ passed to to pk_decrypt.
+
+ Returns: 0 or an errorcode.
+
+ s_data = See comment for sexp_data_to_mpi
+ s_pkey = <key-as-defined-in-sexp_to_key>
+ r_ciph = (enc-val
+ (<algo>
+ (<param_name1> <mpi>)
+ ...
+ (<param_namen> <mpi>)
+ ))
+
+*/
+gcry_error_t
+gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
+{
+ gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
+ const char *algo_name, *algo_elems;
+ int flags;
+ gcry_err_code_t rc;
+ gcry_pk_spec_t *pubkey = NULL;
+ gcry_module_t module = NULL;
+
+ *r_ciph = NULL;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ /* Get the key. */
+ rc = sexp_to_key (s_pkey, 0, &pkey, &module);
+ if (rc)
+ goto leave;
+
+ gcry_assert (module);
+ pubkey = (gcry_pk_spec_t *) module->spec;
+
+ /* If aliases for the algorithm name exists, take the first one
+ instead of the regular name to adhere to SPKI conventions. We
+ assume that the first alias name is the lowercase version of the
+ regular one. This change is required for compatibility with
+ 1.1.12 generated S-expressions. */
+ algo_name = pubkey->aliases? *pubkey->aliases : NULL;
+ if (!algo_name || !*algo_name)
+ algo_name = pubkey->name;
+
+ algo_elems = pubkey->elements_enc;
+
+ /* Get the stuff we want to encrypt. */
+ rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1,
+ &flags);
+ if (rc)
+ goto leave;
+
+ /* Now we can encrypt DATA to CIPH. */
+ ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
+ if (!ciph)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags);
+ mpi_free (data);
+ data = NULL;
+ if (rc)
+ goto leave;
+
+ /* We did it. Now build the return list */
+ {
+ char *string, *p;
+ int i;
+ size_t nelem = strlen (algo_elems);
+ size_t needed = 19 + strlen (algo_name) + (nelem * 5);
+ void **arg_list;
+
+ /* Build the string. */
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ p = stpcpy ( p, "(enc-val(" );
+ p = stpcpy ( p, algo_name );
+ for (i=0; algo_elems[i]; i++ )
+ {
+ *p++ = '(';
+ *p++ = algo_elems[i];
+ p = stpcpy ( p, "%m)" );
+ }
+ strcpy ( p, "))" );
+
+ /* And now the ugly part: We don't have a function to pass an
+ * array to a format string, so we have to do it this way :-(. */
+ /* FIXME: There is now such a format specifier, so we can
+ change the code to be more clear. */
+ arg_list = malloc (nelem * sizeof *arg_list);
+ if (!arg_list)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ for (i = 0; i < nelem; i++)
+ arg_list[i] = ciph + i;
+
+ rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
+ free (arg_list);
+ if (rc)
+ BUG ();
+ gcry_free (string);
+ }
+
+ leave:
+ if (pkey)
+ {
+ release_mpi_array (pkey);
+ gcry_free (pkey);
+ }
+
+ if (ciph)
+ {
+ release_mpi_array (ciph);
+ gcry_free (ciph);
+ }
+
+ if (module)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+
+ return gcry_error (rc);
+}
+
+/*
+ Do a PK decrypt operation
+
+ Caller has to provide a secret key as the SEXP skey and data in a
+ format as created by gcry_pk_encrypt. For historic reasons the
+ function returns simply an MPI as an S-expression part; this is
+ deprecated and the new method should be used which returns a real
+ S-expressionl this is selected by adding at least an empty flags
+ list to S_DATA.
+
+ Returns: 0 or an errorcode.
+
+ s_data = (enc-val
+ [(flags)]
+ (<algo>
+ (<param_name1> <mpi>)
+ ...
+ (<param_namen> <mpi>)
+ ))
+ s_skey = <key-as-defined-in-sexp_to_key>
+ r_plain= Either an incomplete S-expression without the parentheses
+ or if the flags list is used (even if empty) a real S-expression:
+ (value PLAIN).
+ */
+gcry_error_t
+gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
+{
+ gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL;
+ int modern, want_pkcs1, flags;
+ gcry_err_code_t rc;
+ gcry_module_t module_enc = NULL, module_key = NULL;
+ gcry_pk_spec_t *pubkey = NULL;
+
+ *r_plain = NULL;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ rc = sexp_to_key (s_skey, 1, &skey, &module_key);
+ if (rc)
+ goto leave;
+
+ rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags);
+ if (rc)
+ goto leave;
+
+ if (module_key->mod_id != module_enc->mod_id)
+ {
+ rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */
+ goto leave;
+ }
+
+ pubkey = (gcry_pk_spec_t *) module_key->spec;
+
+ rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags);
+ if (rc)
+ goto leave;
+
+ if (gcry_sexp_build (r_plain, NULL, modern? "(value %m)" : "%m", plain))
+ BUG ();
+
+ leave:
+ if (skey)
+ {
+ release_mpi_array (skey);
+ gcry_free (skey);
+ }
+
+ if (plain)
+ mpi_free (plain);
+
+ if (data)
+ {
+ release_mpi_array (data);
+ gcry_free (data);
+ }
+
+ if (module_key || module_enc)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ if (module_key)
+ _gcry_module_release (module_key);
+ if (module_enc)
+ _gcry_module_release (module_enc);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+
+ return gcry_error (rc);
+}
+
+
+
+/*
+ Create a signature.
+
+ Caller has to provide a secret key as the SEXP skey and data
+ expressed as a SEXP list hash with only one element which should
+ instantly be available as a MPI. Alternatively the structure given
+ below may be used for S_HASH, it provides the abiliy to pass flags
+ to the operation; the only flag defined by now is "pkcs1" which
+ does PKCS#1 block type 1 style padding.
+
+ Returns: 0 or an errorcode.
+ In case of 0 the function returns a new SEXP with the
+ signature value; the structure of this signature depends on the
+ other arguments but is always suitable to be passed to
+ gcry_pk_verify
+
+ s_hash = See comment for sexp_data_to_mpi
+
+ s_skey = <key-as-defined-in-sexp_to_key>
+ r_sig = (sig-val
+ (<algo>
+ (<param_name1> <mpi>)
+ ...
+ (<param_namen> <mpi>))
+ [(hash algo)])
+
+ Note that (hash algo) in R_SIG is not used.
+*/
+gcry_error_t
+gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
+{
+ gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL;
+ gcry_pk_spec_t *pubkey = NULL;
+ gcry_module_t module = NULL;
+ const char *algo_name, *algo_elems;
+ int i;
+ gcry_err_code_t rc;
+
+ *r_sig = NULL;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ rc = sexp_to_key (s_skey, 1, &skey, &module);
+ if (rc)
+ goto leave;
+
+ gcry_assert (module);
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ algo_name = pubkey->aliases? *pubkey->aliases : NULL;
+ if (!algo_name || !*algo_name)
+ algo_name = pubkey->name;
+
+ algo_elems = pubkey->elements_sig;
+
+ /* Get the stuff we want to sign. Note that pk_get_nbits does also
+ work on a private key. */
+ rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey),
+ &hash, 0, NULL);
+ if (rc)
+ goto leave;
+
+ result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
+ if (!result)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ rc = pubkey_sign (module->mod_id, result, hash, skey);
+ if (rc)
+ goto leave;
+
+ {
+ char *string, *p;
+ size_t nelem, needed = strlen (algo_name) + 20;
+ void **arg_list;
+
+ nelem = strlen (algo_elems);
+
+ /* Count elements, so that we can allocate enough space. */
+ needed += 10 * nelem;
+
+ /* Build the string. */
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ p = stpcpy (p, "(sig-val(");
+ p = stpcpy (p, algo_name);
+ for (i = 0; algo_elems[i]; i++)
+ {
+ *p++ = '(';
+ *p++ = algo_elems[i];
+ p = stpcpy (p, "%m)");
+ }
+ strcpy (p, "))");
+
+ arg_list = malloc (nelem * sizeof *arg_list);
+ if (!arg_list)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+
+ for (i = 0; i < nelem; i++)
+ arg_list[i] = result + i;
+
+ rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
+ free (arg_list);
+ if (rc)
+ BUG ();
+ gcry_free (string);
+ }
+
+ leave:
+ if (skey)
+ {
+ release_mpi_array (skey);
+ gcry_free (skey);
+ }
+
+ if (hash)
+ mpi_free (hash);
+
+ if (result)
+ {
+ release_mpi_array (result);
+ gcry_free (result);
+ }
+
+ return gcry_error (rc);
+}
+
+
+/*
+ Verify a signature.
+
+ Caller has to supply the public key pkey, the signature sig and his
+ hashvalue data. Public key has to be a standard public key given
+ as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
+ must be an S-Exp like the one in sign too. */
+gcry_error_t
+gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
+{
+ gcry_module_t module_key = NULL, module_sig = NULL;
+ gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL;
+ gcry_err_code_t rc;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ rc = sexp_to_key (s_pkey, 0, &pkey, &module_key);
+ if (rc)
+ goto leave;
+
+ rc = sexp_to_sig (s_sig, &sig, &module_sig);
+ if (rc)
+ goto leave;
+
+ /* Fixme: Check that the algorithm of S_SIG is compatible to the one
+ of S_PKEY. */
+
+ if (module_key->mod_id != module_sig->mod_id)
+ {
+ rc = GPG_ERR_CONFLICT;
+ goto leave;
+ }
+
+ rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0);
+ if (rc)
+ goto leave;
+
+ rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, NULL, NULL);
+
+ leave:
+ if (pkey)
+ {
+ release_mpi_array (pkey);
+ gcry_free (pkey);
+ }
+ if (sig)
+ {
+ release_mpi_array (sig);
+ gcry_free (sig);
+ }
+ if (hash)
+ mpi_free (hash);
+
+ if (module_key || module_sig)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ if (module_key)
+ _gcry_module_release (module_key);
+ if (module_sig)
+ _gcry_module_release (module_sig);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+
+ return gcry_error (rc);
+}
+
+
+/*
+ Test a key.
+
+ This may be used either for a public or a secret key to see whether
+ the internal structure is okay.
+
+ Returns: 0 or an errorcode.
+
+ s_key = <key-as-defined-in-sexp_to_key> */
+gcry_error_t
+gcry_pk_testkey (gcry_sexp_t s_key)
+{
+ gcry_module_t module = NULL;
+ gcry_mpi_t *key = NULL;
+ gcry_err_code_t rc;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ /* Note we currently support only secret key checking. */
+ rc = sexp_to_key (s_key, 1, &key, &module);
+ if (! rc)
+ {
+ rc = pubkey_check_secret_key (module->mod_id, key);
+ release_mpi_array (key);
+ gcry_free (key);
+ }
+ return gcry_error (rc);
+}
+
+
+/*
+ Create a public key pair and return it in r_key.
+ How the key is created depends on s_parms:
+ (genkey
+ (algo
+ (parameter_name_1 ....)
+ ....
+ (parameter_name_n ....)
+ ))
+ The key is returned in a format depending on the
+ algorithm. Both, private and secret keys are returned
+ and optionally some additional informatin.
+ For elgamal we return this structure:
+ (key-data
+ (public-key
+ (elg
+ (p <mpi>)
+ (g <mpi>)
+ (y <mpi>)
+ )
+ )
+ (private-key
+ (elg
+ (p <mpi>)
+ (g <mpi>)
+ (y <mpi>)
+ (x <mpi>)
+ )
+ )
+ (misc-key-info
+ (pm1-factors n1 n2 ... nn)
+ ))
+ */
+gcry_error_t
+gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
+{
+ gcry_pk_spec_t *pubkey = NULL;
+ gcry_module_t module = NULL;
+ gcry_sexp_t list = NULL;
+ gcry_sexp_t l2 = NULL;
+ gcry_sexp_t l3 = NULL;
+ char *name = NULL;
+ size_t n;
+ gcry_err_code_t rc = GPG_ERR_NO_ERROR;
+ int i;
+ const char *algo_name = NULL;
+ int algo;
+ const char *sec_elems = NULL, *pub_elems = NULL;
+ gcry_mpi_t skey[12];
+ gcry_mpi_t *factors = NULL;
+ gcry_sexp_t extrainfo = NULL;
+ unsigned int nbits = 0;
+ unsigned long use_e = 0;
+
+ skey[0] = NULL;
+ *r_key = NULL;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ list = gcry_sexp_find_token (s_parms, "genkey", 0);
+ if (!list)
+ {
+ rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
+ goto leave;
+ }
+
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ l2 = NULL;
+ if (! list)
+ {
+ rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
+ goto leave;
+ }
+
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
+ {
+ rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
+ goto leave;
+ }
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ gcry_free (name);
+ name = NULL;
+ if (!module)
+ {
+ rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ goto leave;
+ }
+
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ algo = module->mod_id;
+ algo_name = pubkey->aliases? *pubkey->aliases : NULL;
+ if (!algo_name || !*algo_name)
+ algo_name = pubkey->name;
+ pub_elems = pubkey->elements_pkey;
+ sec_elems = pubkey->elements_skey;
+ if (strlen (sec_elems) >= DIM(skey))
+ BUG ();
+
+ /* Handle the optional rsa-use-e element. Actually this belong into
+ the algorithm module but we have this parameter in the public
+ module API, so we need to parse it right here. */
+ l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
+ if (l2)
+ {
+ char buf[50];
+ const char *s;
+
+ s = gcry_sexp_nth_data (l2, 1, &n);
+ if ( !s || n >= DIM (buf) - 1 )
+ {
+ rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
+ goto leave;
+ }
+ memcpy (buf, s, n);
+ buf[n] = 0;
+ use_e = strtoul (buf, NULL, 0);
+ gcry_sexp_release (l2);
+ l2 = NULL;
+ }
+ else
+ use_e = 65537; /* Not given, use the value generated by old versions. */
+
+
+ /* Get the "nbits" parameter. */
+ l2 = gcry_sexp_find_token (list, "nbits", 0);
+ if (l2)
+ {
+ char buf[50];
+ const char *s;
+
+ s = gcry_sexp_nth_data (l2, 1, &n);
+ if (!s || n >= DIM (buf) - 1 )
+ {
+ rc = GPG_ERR_INV_OBJ; /* NBITS given without a cdr. */
+ goto leave;
+ }
+ memcpy (buf, s, n);
+ buf[n] = 0;
+ nbits = (unsigned int)strtoul (buf, NULL, 0);
+ gcry_sexp_release (l2); l2 = NULL;
+ }
+ else
+ nbits = 0;
+
+ /* Pass control to the algorithm module. */
+ rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey,
+ &factors, &extrainfo);
+ gcry_sexp_release (list); list = NULL;
+ if (rc)
+ goto leave;
+
+ /* Key generation succeeded: Build an S-expression. */
+ {
+ char *string, *p;
+ size_t nelem=0, nelem_cp = 0, needed=0;
+ gcry_mpi_t mpis[30];
+
+ /* Estimate size of format string. */
+ nelem = strlen (pub_elems) + strlen (sec_elems);
+ if (factors)
+ {
+ for (i = 0; factors[i]; i++)
+ nelem++;
+ }
+ nelem_cp = nelem;
+
+ needed += nelem * 10;
+ /* (+5 is for EXTRAINFO ("%S")). */
+ needed += 2 * strlen (algo_name) + 300 + 5;
+ if (nelem > DIM (mpis))
+ BUG ();
+
+ /* Build the string. */
+ nelem = 0;
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ p = stpcpy (p, "(key-data");
+ p = stpcpy (p, "(public-key(");
+ p = stpcpy (p, algo_name);
+ for(i = 0; pub_elems[i]; i++)
+ {
+ *p++ = '(';
+ *p++ = pub_elems[i];
+ p = stpcpy (p, "%m)");
+ mpis[nelem++] = skey[i];
+ }
+ p = stpcpy (p, "))");
+ p = stpcpy (p, "(private-key(");
+ p = stpcpy (p, algo_name);
+ for (i = 0; sec_elems[i]; i++)
+ {
+ *p++ = '(';
+ *p++ = sec_elems[i];
+ p = stpcpy (p, "%m)");
+ mpis[nelem++] = skey[i];
+ }
+ p = stpcpy (p, "))");
+
+ /* Hack to make release_mpi_array() work. */
+ skey[i] = NULL;
+
+ if (extrainfo)
+ {
+ /* If we have extrainfo we should not have any factors. */
+ p = stpcpy (p, "%S");
+ }
+ else if (factors && factors[0])
+ {
+ p = stpcpy (p, "(misc-key-info(pm1-factors");
+ for(i = 0; factors[i]; i++)
+ {
+ p = stpcpy (p, "%m");
+ mpis[nelem++] = factors[i];
+ }
+ p = stpcpy (p, "))");
+ }
+ strcpy (p, ")");
+ gcry_assert (p - string < needed);
+
+ while (nelem < DIM (mpis))
+ mpis[nelem++] = NULL;
+
+ {
+ int elem_n = strlen (pub_elems) + strlen (sec_elems);
+ void **arg_list;
+
+ /* Allocate one extra for EXTRAINFO ("%S"). */
+ arg_list = gcry_calloc (nelem_cp+1, sizeof *arg_list);
+ if (!arg_list)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ for (i = 0; i < elem_n; i++)
+ arg_list[i] = mpis + i;
+ if (extrainfo)
+ arg_list[i] = &extrainfo;
+ else if (factors && factors[0])
+ {
+ for (; i < nelem_cp; i++)
+ arg_list[i] = factors + i - elem_n;
+ }
+
+ rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
+ gcry_free (arg_list);
+ if (rc)
+ BUG ();
+ gcry_assert (DIM (mpis) == 30); /* Reminder to make sure that
+ the array gets increased if
+ new parameters are added. */
+ }
+ gcry_free (string);
+ }
+
+ leave:
+ gcry_free (name);
+ gcry_sexp_release (extrainfo);
+ release_mpi_array (skey);
+ /* Don't free SKEY itself, it is an stack allocated array. */
+
+ if (factors)
+ {
+ release_mpi_array ( factors );
+ gcry_free (factors);
+ }
+
+ gcry_sexp_release (l3);
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+
+ if (module)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+
+ return gcry_error (rc);
+}
+
+
+/*
+ Get the number of nbits from the public key.
+
+ Hmmm: Should we have really this function or is it better to have a
+ more general function to retrieve different properties of the key? */
+unsigned int
+gcry_pk_get_nbits (gcry_sexp_t key)
+{
+ gcry_module_t module = NULL;
+ gcry_pk_spec_t *pubkey;
+ gcry_mpi_t *keyarr = NULL;
+ unsigned int nbits = 0;
+ gcry_err_code_t rc;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ rc = sexp_to_key (key, 0, &keyarr, &module);
+ if (rc == GPG_ERR_INV_OBJ)
+ rc = sexp_to_key (key, 1, &keyarr, &module);
+ if (rc)
+ return 0; /* Error - 0 is a suitable indication for that. */
+
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ nbits = (*pubkey->get_nbits) (module->mod_id, keyarr);
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ release_mpi_array (keyarr);
+ gcry_free (keyarr);
+
+ return nbits;
+}
+
+
+/* Return the so called KEYGRIP which is the SHA-1 hash of the public
+ key parameters expressed in a way depending on the algorithm.
+
+ ARRAY must either be 20 bytes long or NULL; in the latter case a
+ newly allocated array of that size is returned, otherwise ARRAY or
+ NULL is returned to indicate an error which is most likely an
+ unknown algorithm. The function accepts public or secret keys. */
+unsigned char *
+gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
+{
+ gcry_sexp_t list = NULL, l2 = NULL;
+ gcry_pk_spec_t *pubkey = NULL;
+ gcry_module_t module = NULL;
+ pk_extra_spec_t *extraspec;
+ const char *s;
+ char *name = NULL;
+ int idx;
+ const char *elems;
+ gcry_md_hd_t md = NULL;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token (key, "public-key", 0);
+ if (! list)
+ list = gcry_sexp_find_token (key, "private-key", 0);
+ if (! list)
+ list = gcry_sexp_find_token (key, "protected-private-key", 0);
+ if (! list)
+ list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
+ if (! list)
+ return NULL; /* No public- or private-key object. */
+
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ l2 = NULL;
+
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
+ goto fail; /* Invalid structure of object. */
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!module)
+ goto fail; /* Unknown algorithm. */
+
+ pubkey = (gcry_pk_spec_t *) module->spec;
+ extraspec = module->extraspec;
+
+ elems = pubkey->elements_grip;
+ if (!elems)
+ goto fail; /* No grip parameter. */
+
+ if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
+ goto fail;
+
+ if (extraspec && extraspec->comp_keygrip)
+ {
+ /* Module specific method to compute a keygrip. */
+ if (extraspec->comp_keygrip (md, list))
+ goto fail;
+ }
+ else
+ {
+ /* Generic method to compute a keygrip. */
+ for (idx = 0, s = elems; *s; s++, idx++)
+ {
+ const char *data;
+ size_t datalen;
+ char buf[30];
+
+ l2 = gcry_sexp_find_token (list, s, 1);
+ if (! l2)
+ goto fail;
+ data = gcry_sexp_nth_data (l2, 1, &datalen);
+ if (! data)
+ goto fail;
+
+ snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
+ gcry_md_write (md, buf, strlen (buf));
+ gcry_md_write (md, data, datalen);
+ gcry_sexp_release (l2);
+ gcry_md_write (md, ")", 1);
+ }
+ }
+
+ if (!array)
+ {
+ array = gcry_malloc (20);
+ if (! array)
+ goto fail;
+ }
+
+ memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
+ gcry_md_close (md);
+ gcry_sexp_release (list);
+ return array;
+
+ fail:
+ gcry_free (name);
+ gcry_sexp_release (l2);
+ gcry_md_close (md);
+ gcry_sexp_release (list);
+ return NULL;
+}
+
+
+gcry_error_t
+gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ switch (cmd)
+ {
+ case GCRYCTL_DISABLE_ALGO:
+ /* This one expects a buffer pointing to an integer with the
+ algo number. */
+ if ((! buffer) || (buflen != sizeof (int)))
+ err = GPG_ERR_INV_ARG;
+ else
+ disable_pubkey_algo (*((int *) buffer));
+ break;
+
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+
+/* Return information about the given algorithm
+
+ WHAT selects the kind of information returned:
+
+ GCRYCTL_TEST_ALGO:
+ Returns 0 when the specified algorithm is available for use.
+ Buffer must be NULL, nbytes may have the address of a variable
+ with the required usage of the algorithm. It may be 0 for don't
+ care or a combination of the GCRY_PK_USAGE_xxx flags;
+
+ GCRYCTL_GET_ALGO_USAGE:
+ Return the usage glafs for the give algo. An invalid alog
+ does return 0. Disabled algos are ignored here because we
+ only want to know whether the algo is at all capable of
+ the usage.
+
+ Note: Because this function is in most cases used to return an
+ integer value, we can make it easier for the caller to just look at
+ the return value. The caller will in all cases consult the value
+ and thereby detecting whether a error occurred or not (i.e. while
+ checking the block size) */
+gcry_error_t
+gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ switch (what)
+ {
+ case GCRYCTL_TEST_ALGO:
+ {
+ int use = nbytes ? *nbytes : 0;
+ if (buffer)
+ err = GPG_ERR_INV_ARG;
+ else if (check_pubkey_algo (algorithm, use))
+ err = GPG_ERR_PUBKEY_ALGO;
+ break;
+ }
+
+ case GCRYCTL_GET_ALGO_USAGE:
+ {
+ gcry_module_t pubkey;
+ int use = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ {
+ use = ((gcry_pk_spec_t *) pubkey->spec)->use;
+ _gcry_module_release (pubkey);
+ }
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ /* FIXME? */
+ *nbytes = use;
+
+ break;
+ }
+
+ case GCRYCTL_GET_ALGO_NPKEY:
+ {
+ /* FIXME? */
+ int npkey = pubkey_get_npkey (algorithm);
+ *nbytes = npkey;
+ break;
+ }
+ case GCRYCTL_GET_ALGO_NSKEY:
+ {
+ /* FIXME? */
+ int nskey = pubkey_get_nskey (algorithm);
+ *nbytes = nskey;
+ break;
+ }
+ case GCRYCTL_GET_ALGO_NSIGN:
+ {
+ /* FIXME? */
+ int nsign = pubkey_get_nsig (algorithm);
+ *nbytes = nsign;
+ break;
+ }
+ case GCRYCTL_GET_ALGO_NENCR:
+ {
+ /* FIXME? */
+ int nencr = pubkey_get_nenc (algorithm);
+ *nbytes = nencr;
+ break;
+ }
+
+ default:
+ err = GPG_ERR_INV_OP;
+ }
+
+ return gcry_error (err);
+}
+
+
+/* Explicitly initialize this module. */
+gcry_err_code_t
+_gcry_pk_init (void)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ return err;
+}
+
+
+gcry_err_code_t
+_gcry_pk_module_lookup (int algorithm, gcry_module_t *module)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_module_t pubkey;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
+ if (pubkey)
+ *module = pubkey;
+ else
+ err = GPG_ERR_PUBKEY_ALGO;
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return err;
+}
+
+
+void
+_gcry_pk_module_release (gcry_module_t module)
+{
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+}
+
+/* Get a list consisting of the IDs of the loaded pubkey modules. If
+ LIST is zero, write the number of loaded pubkey modules to
+ LIST_LENGTH and return. If LIST is non-zero, the first
+ *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
+ according size. In case there are less pubkey modules than
+ *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
+gcry_error_t
+gcry_pk_list (int *list, int *list_length)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ err = _gcry_module_list (pubkeys_registered, list, list_length);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ return err;
+}
+
+
+/* Run the selftests for pubkey algorithm ALGO with optional reporting
+ function REPORT. */
+gpg_error_t
+_gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
+{
+ gcry_module_t module = NULL;
+ pk_extra_spec_t *extraspec = NULL;
+ gcry_err_code_t ec = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = _gcry_module_lookup_id (pubkeys_registered, algo);
+ if (module && !(module->flags & FLAG_MODULE_DISABLED))
+ extraspec = module->extraspec;
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ if (extraspec && extraspec->selftest)
+ ec = extraspec->selftest (algo, extended, report);
+ else
+ {
+ ec = GPG_ERR_PUBKEY_ALGO;
+ if (report)
+ report ("pubkey", algo, "module",
+ module && !(module->flags & FLAG_MODULE_DISABLED)?
+ "no selftest available" :
+ module? "algorithm disabled" : "algorithm not found");
+ }
+
+ if (module)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+ return gpg_error (ec);
+}
+
+
+/* This function is only used by ac.c! */
+gcry_err_code_t
+_gcry_pk_get_elements (int algo, char **enc, char **sig)
+{
+ gcry_module_t pubkey;
+ gcry_pk_spec_t *spec;
+ gcry_err_code_t err;
+ char *enc_cp;
+ char *sig_cp;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ enc_cp = NULL;
+ sig_cp = NULL;
+ spec = NULL;
+
+ pubkey = _gcry_module_lookup_id (pubkeys_registered, algo);
+ if (! pubkey)
+ {
+ err = GPG_ERR_INTERNAL;
+ goto out;
+ }
+ spec = pubkey->spec;
+
+ if (enc)
+ {
+ enc_cp = _strdup (spec->elements_enc);
+ if (! enc_cp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto out;
+ }
+ }
+
+ if (sig)
+ {
+ sig_cp = strdup (spec->elements_sig);
+ if (! sig_cp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto out;
+ }
+ }
+
+ if (enc)
+ *enc = enc_cp;
+ if (sig)
+ *sig = sig_cp;
+ err = 0;
+
+ out:
+
+ _gcry_module_release (pubkey);
+ if (err)
+ {
+ free (enc_cp);
+ free (sig_cp);
+ }
+
+ return err;
+}
diff --git a/libgcrypt-1.4.6/cipher/rijndael.c b/libgcrypt-1.4.6/cipher/rijndael.c
index d43b349..1df703a 100644
--- a/libgcrypt-1.4.6/cipher/rijndael.c
+++ b/libgcrypt-1.4.6/cipher/rijndael.c
@@ -1,1253 +1,1253 @@
-/* Rijndael (AES) for GnuPG
- * Copyright (C) 2000, 2001, 2002, 2003, 2007,
- * 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- *******************************************************************
- * The code here is based on the optimized implementation taken from
- * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000,
- * which carries this notice:
- *------------------------------------------
- * rijndael-alg-fst.c v2.3 April '2000
- *
- * Optimised ANSI C code
- *
- * authors: v1.0: Antoon Bosselaers
- * v2.0: Vincent Rijmen
- * v2.3: Paulo Barreto
- *
- * This code is placed in the public domain.
- *------------------------------------------
- *
- * The SP800-38a document is available at:
- * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
- *
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h> /* for memcmp() */
-
-#include "types.h" /* for byte and u32 typedefs */
-#include "g10lib.h"
-#include "cipher.h"
-
-#define MAXKC (256/32)
-#define MAXROUNDS 14
-#define BLOCKSIZE (128/8)
-
-
-/* USE_PADLOCK indicates whether to compile the padlock specific
- code. */
-#undef USE_PADLOCK
-#ifdef ENABLE_PADLOCK_SUPPORT
-# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
-# define USE_PADLOCK
-# endif
-#endif /*ENABLE_PADLOCK_SUPPORT*/
-
-static const char *selftest(void);
-
-typedef struct
-{
- int ROUNDS; /* Key-length-dependent number of rounds. */
- int decryption_prepared; /* The decryption key schedule is available. */
-#ifdef USE_PADLOCK
- int use_padlock; /* Padlock shall be used. */
- /* The key as passed to the padlock engine. */
- unsigned char padlock_key[16] __attribute__ ((aligned (16)));
-#endif
- union
- {
- PROPERLY_ALIGNED_TYPE dummy;
- byte keyschedule[MAXROUNDS+1][4][4];
- } u1;
- union
- {
- PROPERLY_ALIGNED_TYPE dummy;
- byte keyschedule[MAXROUNDS+1][4][4];
- } u2;
-} RIJNDAEL_context;
-
-#define keySched u1.keyschedule
-#define keySched2 u2.keyschedule
-
-/* All the numbers. */
-#include "rijndael-tables.h"
-
-
-/* Perform the key setup. */
-static gcry_err_code_t
-do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
-{
- static int initialized = 0;
- static const char *selftest_failed=0;
- int ROUNDS;
- int i,j, r, t, rconpointer = 0;
- int KC;
- union
- {
- PROPERLY_ALIGNED_TYPE dummy;
- byte k[MAXKC][4];
- } k;
-#define k k.k
- union
- {
- PROPERLY_ALIGNED_TYPE dummy;
- byte tk[MAXKC][4];
- } tk;
-#define tk tk.tk
-
- /* The on-the-fly self tests are only run in non-fips mode. In fips
- mode explicit self-tests are required. Actually the on-the-fly
- self-tests are not fully thread-safe and it might happen that a
- failed self-test won't get noticed in another thread.
-
- FIXME: We might want to have a central registry of succeeded
- self-tests. */
- if (!fips_mode () && !initialized)
- {
- initialized = 1;
- selftest_failed = selftest ();
- if (selftest_failed)
- log_error ("%s\n", selftest_failed );
- }
- if (selftest_failed)
- return GPG_ERR_SELFTEST_FAILED;
-
- ctx->decryption_prepared = 0;
-#ifdef USE_PADLOCK
- ctx->use_padlock = 0;
-#endif
-
- if( keylen == 128/8 )
- {
- ROUNDS = 10;
- KC = 4;
-#ifdef USE_PADLOCK
- if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
- {
- ctx->use_padlock = 1;
- memcpy (ctx->padlock_key, key, keylen);
- }
-#endif
- }
- else if ( keylen == 192/8 )
- {
- ROUNDS = 12;
- KC = 6;
- }
- else if ( keylen == 256/8 )
- {
- ROUNDS = 14;
- KC = 8;
- }
- else
- return GPG_ERR_INV_KEYLEN;
-
- ctx->ROUNDS = ROUNDS;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- {
- /* Nothing to do as we support only hardware key generation for
- now. */
- }
- else
-#endif /*USE_PADLOCK*/
- {
-#define W (ctx->keySched)
- for (i = 0; i < keylen; i++)
- {
- k[i >> 2][i & 3] = key[i];
- }
-
- for (j = KC-1; j >= 0; j--)
- {
- *((u32*)tk[j]) = *((u32*)k[j]);
- }
- r = 0;
- t = 0;
- /* Copy values into round key array. */
- for (j = 0; (j < KC) && (r < ROUNDS + 1); )
- {
- for (; (j < KC) && (t < 4); j++, t++)
- {
- *((u32*)W[r][t]) = *((u32*)tk[j]);
- }
- if (t == 4)
- {
- r++;
- t = 0;
- }
- }
-
- while (r < ROUNDS + 1)
- {
- /* While not enough round key material calculated calculate
- new values. */
- tk[0][0] ^= S[tk[KC-1][1]];
- tk[0][1] ^= S[tk[KC-1][2]];
- tk[0][2] ^= S[tk[KC-1][3]];
- tk[0][3] ^= S[tk[KC-1][0]];
- tk[0][0] ^= rcon[rconpointer++];
-
- if (KC != 8)
- {
- for (j = 1; j < KC; j++)
- {
- *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
- }
- }
- else
- {
- for (j = 1; j < KC/2; j++)
- {
- *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
- }
- tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
- tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
- tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
- tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
- for (j = KC/2 + 1; j < KC; j++)
- {
- *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
- }
- }
-
- /* Copy values into round key array. */
- for (j = 0; (j < KC) && (r < ROUNDS + 1); )
- {
- for (; (j < KC) && (t < 4); j++, t++)
- {
- *((u32*)W[r][t]) = *((u32*)tk[j]);
- }
- if (t == 4)
- {
- r++;
- t = 0;
- }
- }
- }
-#undef W
- }
-
- return 0;
-#undef tk
-#undef k
-}
-
-
-static gcry_err_code_t
-rijndael_setkey (void *context, const byte *key, const unsigned keylen)
-{
- RIJNDAEL_context *ctx = context;
-
- int rc = do_setkey (ctx, key, keylen);
- _gcry_burn_stack ( 100 + 16*sizeof(int));
- return rc;
-}
-
-
-/* Make a decryption key from an encryption key. */
-static void
-prepare_decryption( RIJNDAEL_context *ctx )
-{
- int r;
- union
- {
- PROPERLY_ALIGNED_TYPE dummy;
- byte *w;
- } w;
-#define w w.w
-
- for (r=0; r < MAXROUNDS+1; r++ )
- {
- *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]);
- *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]);
- *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]);
- *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]);
- }
-#define W (ctx->keySched2)
- for (r = 1; r < ctx->ROUNDS; r++)
- {
- w = W[r][0];
- *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
- ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
-
- w = W[r][1];
- *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
- ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
-
- w = W[r][2];
- *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
- ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
-
- w = W[r][3];
- *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
- ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
- }
-#undef W
-#undef w
-}
-
-
-
-/* Encrypt one block. A and B need to be aligned on a 4 byte
- boundary. A and B may be the same. */
-static void
-do_encrypt_aligned (const RIJNDAEL_context *ctx,
- unsigned char *b, const unsigned char *a)
-{
-#define rk (ctx->keySched)
- int ROUNDS = ctx->ROUNDS;
- int r;
- union
- {
- u32 tempu32[4]; /* Force correct alignment. */
- byte temp[4][4];
- } u;
-
- *((u32*)u.temp[0]) = *((u32*)(a )) ^ *((u32*)rk[0][0]);
- *((u32*)u.temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[0][1]);
- *((u32*)u.temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[0][2]);
- *((u32*)u.temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[0][3]);
- *((u32*)(b )) = (*((u32*)T1[u.temp[0][0]])
- ^ *((u32*)T2[u.temp[1][1]])
- ^ *((u32*)T3[u.temp[2][2]])
- ^ *((u32*)T4[u.temp[3][3]]));
- *((u32*)(b + 4)) = (*((u32*)T1[u.temp[1][0]])
- ^ *((u32*)T2[u.temp[2][1]])
- ^ *((u32*)T3[u.temp[3][2]])
- ^ *((u32*)T4[u.temp[0][3]]));
- *((u32*)(b + 8)) = (*((u32*)T1[u.temp[2][0]])
- ^ *((u32*)T2[u.temp[3][1]])
- ^ *((u32*)T3[u.temp[0][2]])
- ^ *((u32*)T4[u.temp[1][3]]));
- *((u32*)(b +12)) = (*((u32*)T1[u.temp[3][0]])
- ^ *((u32*)T2[u.temp[0][1]])
- ^ *((u32*)T3[u.temp[1][2]])
- ^ *((u32*)T4[u.temp[2][3]]));
-
- for (r = 1; r < ROUNDS-1; r++)
- {
- *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]);
- *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]);
- *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]);
- *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]);
-
- *((u32*)(b )) = (*((u32*)T1[u.temp[0][0]])
- ^ *((u32*)T2[u.temp[1][1]])
- ^ *((u32*)T3[u.temp[2][2]])
- ^ *((u32*)T4[u.temp[3][3]]));
- *((u32*)(b + 4)) = (*((u32*)T1[u.temp[1][0]])
- ^ *((u32*)T2[u.temp[2][1]])
- ^ *((u32*)T3[u.temp[3][2]])
- ^ *((u32*)T4[u.temp[0][3]]));
- *((u32*)(b + 8)) = (*((u32*)T1[u.temp[2][0]])
- ^ *((u32*)T2[u.temp[3][1]])
- ^ *((u32*)T3[u.temp[0][2]])
- ^ *((u32*)T4[u.temp[1][3]]));
- *((u32*)(b +12)) = (*((u32*)T1[u.temp[3][0]])
- ^ *((u32*)T2[u.temp[0][1]])
- ^ *((u32*)T3[u.temp[1][2]])
- ^ *((u32*)T4[u.temp[2][3]]));
- }
-
- /* Last round is special. */
- *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[ROUNDS-1][0]);
- *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[ROUNDS-1][1]);
- *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[ROUNDS-1][2]);
- *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[ROUNDS-1][3]);
- b[ 0] = T1[u.temp[0][0]][1];
- b[ 1] = T1[u.temp[1][1]][1];
- b[ 2] = T1[u.temp[2][2]][1];
- b[ 3] = T1[u.temp[3][3]][1];
- b[ 4] = T1[u.temp[1][0]][1];
- b[ 5] = T1[u.temp[2][1]][1];
- b[ 6] = T1[u.temp[3][2]][1];
- b[ 7] = T1[u.temp[0][3]][1];
- b[ 8] = T1[u.temp[2][0]][1];
- b[ 9] = T1[u.temp[3][1]][1];
- b[10] = T1[u.temp[0][2]][1];
- b[11] = T1[u.temp[1][3]][1];
- b[12] = T1[u.temp[3][0]][1];
- b[13] = T1[u.temp[0][1]][1];
- b[14] = T1[u.temp[1][2]][1];
- b[15] = T1[u.temp[2][3]][1];
- *((u32*)(b )) ^= *((u32*)rk[ROUNDS][0]);
- *((u32*)(b+ 4)) ^= *((u32*)rk[ROUNDS][1]);
- *((u32*)(b+ 8)) ^= *((u32*)rk[ROUNDS][2]);
- *((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]);
-#undef rk
-}
-
-
-static void
-do_encrypt (const RIJNDAEL_context *ctx,
- unsigned char *bx, const unsigned char *ax)
-{
- /* BX and AX are not necessary correctly aligned. Thus we need to
- copy them here. */
- union
- {
- u32 dummy[4];
- byte a[16];
- } a;
- union
- {
- u32 dummy[4];
- byte b[16];
- } b;
-
- memcpy (a.a, ax, 16);
- do_encrypt_aligned (ctx, b.b, a.a);
- memcpy (bx, b.b, 16);
-}
-
-
-/* Encrypt or decrypt one block using the padlock engine. A and B may
- be the same. */
-#ifdef USE_PADLOCK
-static void
-do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag,
- unsigned char *bx, const unsigned char *ax)
-{
- /* BX and AX are not necessary correctly aligned. Thus we need to
- copy them here. */
- unsigned char a[16] __attribute__ ((aligned (16)));
- unsigned char b[16] __attribute__ ((aligned (16)));
- unsigned int cword[4] __attribute__ ((aligned (16)));
-
- /* The control word fields are:
- 127:12 11:10 9 8 7 6 5 4 3:0
- RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */
- cword[0] = (ctx->ROUNDS & 15); /* (The mask is just a safeguard.) */
- cword[1] = 0;
- cword[2] = 0;
- cword[3] = 0;
- if (decrypt_flag)
- cword[0] |= 0x00000200;
-
- memcpy (a, ax, 16);
-
- asm volatile
- ("pushfl\n\t" /* Force key reload. */
- "popfl\n\t"
- "xchg %3, %%ebx\n\t" /* Load key. */
- "movl $1, %%ecx\n\t" /* Init counter for just one block. */
- ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */
- "xchg %3, %%ebx\n" /* Restore GOT register. */
- : /* No output */
- : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlock_key)
- : "%ecx", "cc", "memory"
- );
-
- memcpy (bx, b, 16);
-
-}
-#endif /*USE_PADLOCK*/
-
-
-static void
-rijndael_encrypt (void *context, byte *b, const byte *a)
-{
- RIJNDAEL_context *ctx = context;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- {
- do_padlock (ctx, 0, b, a);
- _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
- }
- else
-#endif /*USE_PADLOCK*/
- {
- do_encrypt (ctx, b, a);
- _gcry_burn_stack (48 + 2*sizeof(int));
- }
-}
-
-
-/* Bulk encryption of complete blocks in CFB mode. Caller needs to
- make sure that IV is aligned on an unsigned long boundary. This
- function is only intended for the bulk encryption feature of
- cipher.c. */
-void
-_gcry_aes_cfb_enc (void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks)
-{
- RIJNDAEL_context *ctx = context;
- unsigned char *outbuf = outbuf_arg;
- const unsigned char *inbuf = inbuf_arg;
- unsigned char *ivp;
- int i;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- {
- /* Fixme: Let Padlock do the CFBing. */
- for ( ;nblocks; nblocks-- )
- {
- /* Encrypt the IV. */
- do_padlock (ctx, 0, iv, iv);
- /* XOR the input with the IV and store input into IV. */
- for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- }
- }
- else
-#endif /* USE_PADLOCK*/
- {
- for ( ;nblocks; nblocks-- )
- {
- /* Encrypt the IV. */
- do_encrypt_aligned (ctx, iv, iv);
- /* XOR the input with the IV and store input into IV. */
- for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
- *outbuf++ = (*ivp++ ^= *inbuf++);
- }
- }
-
- _gcry_burn_stack (48 + 2*sizeof(int));
-}
-
-
-/* Bulk encryption of complete blocks in CBC mode. Caller needs to
- make sure that IV is aligned on an unsigned long boundary. This
- function is only intended for the bulk encryption feature of
- cipher.c. */
-void
-_gcry_aes_cbc_enc (void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks, int cbc_mac)
-{
- RIJNDAEL_context *ctx = context;
- unsigned char *outbuf = outbuf_arg;
- const unsigned char *inbuf = inbuf_arg;
- unsigned char *ivp;
- int i;
-
- for ( ;nblocks; nblocks-- )
- {
- for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
- outbuf[i] = inbuf[i] ^ *ivp++;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- do_padlock (ctx, 0, outbuf, outbuf);
- else
-#endif /*USE_PADLOCK*/
- do_encrypt (ctx, outbuf, outbuf );
-
- memcpy (iv, outbuf, BLOCKSIZE);
- inbuf += BLOCKSIZE;
- if (!cbc_mac)
- outbuf += BLOCKSIZE;
- }
-
- _gcry_burn_stack (48 + 2*sizeof(int));
-}
-
-
-
-/* Decrypt one block. A and B need to be aligned on a 4 byte boundary
- and the decryption must have been prepared. A and B may be the
- same. */
-static void
-do_decrypt_aligned (RIJNDAEL_context *ctx,
- unsigned char *b, const unsigned char *a)
-{
-#define rk (ctx->keySched2)
- int ROUNDS = ctx->ROUNDS;
- int r;
- union
- {
- u32 tempu32[4]; /* Force correct alignment. */
- byte temp[4][4];
- } u;
-
-
- *((u32*)u.temp[0]) = *((u32*)(a )) ^ *((u32*)rk[ROUNDS][0]);
- *((u32*)u.temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[ROUNDS][1]);
- *((u32*)u.temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[ROUNDS][2]);
- *((u32*)u.temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[ROUNDS][3]);
-
- *((u32*)(b )) = (*((u32*)T5[u.temp[0][0]])
- ^ *((u32*)T6[u.temp[3][1]])
- ^ *((u32*)T7[u.temp[2][2]])
- ^ *((u32*)T8[u.temp[1][3]]));
- *((u32*)(b+ 4)) = (*((u32*)T5[u.temp[1][0]])
- ^ *((u32*)T6[u.temp[0][1]])
- ^ *((u32*)T7[u.temp[3][2]])
- ^ *((u32*)T8[u.temp[2][3]]));
- *((u32*)(b+ 8)) = (*((u32*)T5[u.temp[2][0]])
- ^ *((u32*)T6[u.temp[1][1]])
- ^ *((u32*)T7[u.temp[0][2]])
- ^ *((u32*)T8[u.temp[3][3]]));
- *((u32*)(b+12)) = (*((u32*)T5[u.temp[3][0]])
- ^ *((u32*)T6[u.temp[2][1]])
- ^ *((u32*)T7[u.temp[1][2]])
- ^ *((u32*)T8[u.temp[0][3]]));
-
- for (r = ROUNDS-1; r > 1; r--)
- {
- *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]);
- *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]);
- *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]);
- *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]);
- *((u32*)(b )) = (*((u32*)T5[u.temp[0][0]])
- ^ *((u32*)T6[u.temp[3][1]])
- ^ *((u32*)T7[u.temp[2][2]])
- ^ *((u32*)T8[u.temp[1][3]]));
- *((u32*)(b+ 4)) = (*((u32*)T5[u.temp[1][0]])
- ^ *((u32*)T6[u.temp[0][1]])
- ^ *((u32*)T7[u.temp[3][2]])
- ^ *((u32*)T8[u.temp[2][3]]));
- *((u32*)(b+ 8)) = (*((u32*)T5[u.temp[2][0]])
- ^ *((u32*)T6[u.temp[1][1]])
- ^ *((u32*)T7[u.temp[0][2]])
- ^ *((u32*)T8[u.temp[3][3]]));
- *((u32*)(b+12)) = (*((u32*)T5[u.temp[3][0]])
- ^ *((u32*)T6[u.temp[2][1]])
- ^ *((u32*)T7[u.temp[1][2]])
- ^ *((u32*)T8[u.temp[0][3]]));
- }
-
- /* Last round is special. */
- *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[1][0]);
- *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[1][1]);
- *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[1][2]);
- *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[1][3]);
- b[ 0] = S5[u.temp[0][0]];
- b[ 1] = S5[u.temp[3][1]];
- b[ 2] = S5[u.temp[2][2]];
- b[ 3] = S5[u.temp[1][3]];
- b[ 4] = S5[u.temp[1][0]];
- b[ 5] = S5[u.temp[0][1]];
- b[ 6] = S5[u.temp[3][2]];
- b[ 7] = S5[u.temp[2][3]];
- b[ 8] = S5[u.temp[2][0]];
- b[ 9] = S5[u.temp[1][1]];
- b[10] = S5[u.temp[0][2]];
- b[11] = S5[u.temp[3][3]];
- b[12] = S5[u.temp[3][0]];
- b[13] = S5[u.temp[2][1]];
- b[14] = S5[u.temp[1][2]];
- b[15] = S5[u.temp[0][3]];
- *((u32*)(b )) ^= *((u32*)rk[0][0]);
- *((u32*)(b+ 4)) ^= *((u32*)rk[0][1]);
- *((u32*)(b+ 8)) ^= *((u32*)rk[0][2]);
- *((u32*)(b+12)) ^= *((u32*)rk[0][3]);
-#undef rk
-}
-
-
-/* Decrypt one block. AX and BX may be the same. */
-static void
-do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax)
-{
- /* BX and AX are not necessary correctly aligned. Thus we need to
- copy them here. */
- union
- {
- u32 dummy[4];
- byte a[16];
- } a;
- union
- {
- u32 dummy[4];
- byte b[16];
- } b;
-
- if ( !ctx->decryption_prepared )
- {
- prepare_decryption ( ctx );
- _gcry_burn_stack (64);
- ctx->decryption_prepared = 1;
- }
-
- memcpy (a.a, ax, 16);
- do_decrypt_aligned (ctx, b.b, a.a);
- memcpy (bx, b.b, 16);
-#undef rk
-}
-
-
-
-
-static void
-rijndael_decrypt (void *context, byte *b, const byte *a)
-{
- RIJNDAEL_context *ctx = context;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- {
- do_padlock (ctx, 1, b, a);
- _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
- }
- else
-#endif /*USE_PADLOCK*/
- {
- do_decrypt (ctx, b, a);
- _gcry_burn_stack (48+2*sizeof(int));
- }
-}
-
-
-/* Bulk decryption of complete blocks in CFB mode. Caller needs to
- make sure that IV is aligned on an unisgned lonhg boundary. This
- function is only intended for the bulk encryption feature of
- cipher.c. */
-void
-_gcry_aes_cfb_dec (void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks)
-{
- RIJNDAEL_context *ctx = context;
- unsigned char *outbuf = outbuf_arg;
- const unsigned char *inbuf = inbuf_arg;
- unsigned char *ivp;
- unsigned char temp;
- int i;
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- {
- /* Fixme: Let Padlock do the CFBing. */
- for ( ;nblocks; nblocks-- )
- {
- do_padlock (ctx, 0, iv, iv);
- for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- }
- }
- else
-#endif /*USE_PADLOCK*/
- {
- for ( ;nblocks; nblocks-- )
- {
- do_encrypt_aligned (ctx, iv, iv);
- for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
- {
- temp = *inbuf++;
- *outbuf++ = *ivp ^ temp;
- *ivp++ = temp;
- }
- }
- }
-
- _gcry_burn_stack (48 + 2*sizeof(int));
-}
-
-
-/* Bulk decryption of complete blocks in CBC mode. Caller needs to
- make sure that IV is aligned on an unsigned long boundary. This
- function is only intended for the bulk encryption feature of
- cipher.c. */
-void
-_gcry_aes_cbc_dec (void *context, unsigned char *iv,
- void *outbuf_arg, const void *inbuf_arg,
- unsigned int nblocks)
-{
- RIJNDAEL_context *ctx = context;
- unsigned char *outbuf = outbuf_arg;
- const unsigned char *inbuf = inbuf_arg;
- unsigned char *ivp;
- int i;
- unsigned char savebuf[BLOCKSIZE];
-
- for ( ;nblocks; nblocks-- )
- {
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy (savebuf, inbuf, BLOCKSIZE);
-
-#ifdef USE_PADLOCK
- if (ctx->use_padlock)
- do_padlock (ctx, 1, outbuf, inbuf);
- else
-#endif /*USE_PADLOCK*/
- do_decrypt (ctx, outbuf, inbuf);
-
- for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
- outbuf[i] ^= *ivp++;
- memcpy (iv, savebuf, BLOCKSIZE);
- inbuf += BLOCKSIZE;
- outbuf += BLOCKSIZE;
- }
-
- _gcry_burn_stack (48 + 2*sizeof(int) + BLOCKSIZE + 4*sizeof (char*));
-}
-
-
-
-
-/* Run the self-tests for AES 128. Returns NULL on success. */
-static const char*
-selftest_basic_128 (void)
-{
- RIJNDAEL_context ctx;
- unsigned char scratch[16];
-
- /* The test vectors are from the AES supplied ones; more or less
- randomly taken from ecb_tbl.txt (I=42,81,14) */
- static const unsigned char plaintext_128[16] =
- {
- 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
- 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
- };
- static const unsigned char key_128[16] =
- {
- 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
- 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
- };
- static const unsigned char ciphertext_128[16] =
- {
- 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
- 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
- };
-
- rijndael_setkey (&ctx, key_128, sizeof (key_128));
- rijndael_encrypt (&ctx, scratch, plaintext_128);
- if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128)))
- return "AES-128 test encryption failed.";
- rijndael_decrypt (&ctx, scratch, scratch);
- if (memcmp (scratch, plaintext_128, sizeof (plaintext_128)))
- return "AES-128 test decryption failed.";
-
- return NULL;
-}
-
-/* Run the self-tests for AES 192. Returns NULL on success. */
-static const char*
-selftest_basic_192 (void)
-{
- RIJNDAEL_context ctx;
- unsigned char scratch[16];
-
- static unsigned char plaintext_192[16] =
- {
- 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
- 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
- };
- static unsigned char key_192[24] =
- {
- 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
- 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
- 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
- };
- static const unsigned char ciphertext_192[16] =
- {
- 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
- 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
- };
-
- rijndael_setkey (&ctx, key_192, sizeof(key_192));
- rijndael_encrypt (&ctx, scratch, plaintext_192);
- if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
- return "AES-192 test encryption failed.";
- rijndael_decrypt (&ctx, scratch, scratch);
- if (memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
- return "AES-192 test decryption failed.";
-
- return NULL;
-}
-
-
-/* Run the self-tests for AES 256. Returns NULL on success. */
-static const char*
-selftest_basic_256 (void)
-{
- RIJNDAEL_context ctx;
- unsigned char scratch[16];
-
- static unsigned char plaintext_256[16] =
- {
- 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
- 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
- };
- static unsigned char key_256[32] =
- {
- 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
- 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
- 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
- 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
- };
- static const unsigned char ciphertext_256[16] =
- {
- 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
- 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
- };
-
- rijndael_setkey (&ctx, key_256, sizeof(key_256));
- rijndael_encrypt (&ctx, scratch, plaintext_256);
- if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
- return "AES-256 test encryption failed.";
- rijndael_decrypt (&ctx, scratch, scratch);
- if (memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
- return "AES-256 test decryption failed.";
-
- return NULL;
-}
-
-/* Run all the self-tests and return NULL on success. This function
- is used for the on-the-fly self-tests. */
-static const char *
-selftest (void)
-{
- const char *r;
-
- if ( (r = selftest_basic_128 ())
- || (r = selftest_basic_192 ())
- || (r = selftest_basic_256 ()) )
- return r;
-
- return r;
-}
-
-
-/* SP800-38a.pdf for AES-128. */
-static const char *
-selftest_fips_128_38a (int requested_mode)
-{
- struct tv
- {
- int mode;
- const unsigned char key[16];
- const unsigned char iv[16];
- struct
- {
- const unsigned char input[16];
- const unsigned char output[16];
- } data[4];
- } tv[2] =
- {
- {
- GCRY_CIPHER_MODE_CFB, /* F.3.13, CFB128-AES128 */
- { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
- 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
- {
- { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
- { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
- 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
-
- { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
- { 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f,
- 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } },
-
- { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
- { 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40,
- 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } },
-
- { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
- { 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e,
- 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } }
- }
- },
- {
- GCRY_CIPHER_MODE_OFB,
- { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
- 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
- {
- { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
- { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
- 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
-
- { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
- { 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
- 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } },
-
- { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
- { 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
- 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } },
-
- { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
- { 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
- 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } },
- }
- }
- };
- unsigned char scratch[16];
- gpg_error_t err;
- int tvi, idx;
- gcry_cipher_hd_t hdenc = NULL;
- gcry_cipher_hd_t hddec = NULL;
-
-#define Fail(a) do { \
- _gcry_cipher_close (hdenc); \
- _gcry_cipher_close (hddec); \
- return a; \
- } while (0)
-
- gcry_assert (sizeof tv[0].data[0].input == sizeof scratch);
- gcry_assert (sizeof tv[0].data[0].output == sizeof scratch);
-
- for (tvi=0; tvi < DIM (tv); tvi++)
- if (tv[tvi].mode == requested_mode)
- break;
- if (tvi == DIM (tv))
- Fail ("no test data for this mode");
-
- err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0);
- if (err)
- Fail ("open");
- err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0);
- if (err)
- Fail ("open");
- err = _gcry_cipher_setkey (hdenc, tv[tvi].key, sizeof tv[tvi].key);
- if (!err)
- err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key);
- if (err)
- Fail ("set key");
- err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv);
- if (!err)
- err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv);
- if (err)
- Fail ("set IV");
- for (idx=0; idx < DIM (tv[tvi].data); idx++)
- {
- err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch,
- tv[tvi].data[idx].input,
- sizeof tv[tvi].data[idx].input);
- if (err)
- Fail ("encrypt command");
- if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch))
- Fail ("encrypt mismatch");
- err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch,
- tv[tvi].data[idx].output,
- sizeof tv[tvi].data[idx].output);
- if (err)
- Fail ("decrypt command");
- if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch))
- Fail ("decrypt mismatch");
- }
-
-#undef Fail
- _gcry_cipher_close (hdenc);
- _gcry_cipher_close (hddec);
- return NULL;
-}
-
-
-/* Complete selftest for AES-128 with all modes and driver code. */
-static gpg_err_code_t
-selftest_fips_128 (int extended, selftest_report_func_t report)
-{
- const char *what;
- const char *errtxt;
-
- what = "low-level";
- errtxt = selftest_basic_128 ();
- if (errtxt)
- goto failed;
-
- if (extended)
- {
- what = "cfb";
- errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB);
- if (errtxt)
- goto failed;
-
- what = "ofb";
- errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB);
- if (errtxt)
- goto failed;
- }
-
- return 0; /* Succeeded. */
-
- failed:
- if (report)
- report ("cipher", GCRY_CIPHER_AES128, what, errtxt);
- return GPG_ERR_SELFTEST_FAILED;
-}
-
-/* Complete selftest for AES-192. */
-static gpg_err_code_t
-selftest_fips_192 (int extended, selftest_report_func_t report)
-{
- const char *what;
- const char *errtxt;
-
- (void)extended; /* No extended tests available. */
-
- what = "low-level";
- errtxt = selftest_basic_192 ();
- if (errtxt)
- goto failed;
-
-
- return 0; /* Succeeded. */
-
- failed:
- if (report)
- report ("cipher", GCRY_CIPHER_AES192, what, errtxt);
- return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-/* Complete selftest for AES-256. */
-static gpg_err_code_t
-selftest_fips_256 (int extended, selftest_report_func_t report)
-{
- const char *what;
- const char *errtxt;
-
- (void)extended; /* No extended tests available. */
-
- what = "low-level";
- errtxt = selftest_basic_256 ();
- if (errtxt)
- goto failed;
-
- return 0; /* Succeeded. */
-
- failed:
- if (report)
- report ("cipher", GCRY_CIPHER_AES256, what, errtxt);
- return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-
-/* Run a full self-test for ALGO and return 0 on success. */
-static gpg_err_code_t
-run_selftests (int algo, int extended, selftest_report_func_t report)
-{
- gpg_err_code_t ec;
-
- switch (algo)
- {
- case GCRY_CIPHER_AES128:
- ec = selftest_fips_128 (extended, report);
- break;
- case GCRY_CIPHER_AES192:
- ec = selftest_fips_192 (extended, report);
- break;
- case GCRY_CIPHER_AES256:
- ec = selftest_fips_256 (extended, report);
- break;
- default:
- ec = GPG_ERR_CIPHER_ALGO;
- break;
-
- }
- return ec;
-}
-
-
-
-
-static const char *rijndael_names[] =
- {
- "RIJNDAEL",
- "AES128",
- "AES-128",
- NULL
- };
-
-static gcry_cipher_oid_spec_t rijndael_oids[] =
- {
- { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB },
- { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC },
- { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB },
- { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB },
- { NULL }
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_aes =
- {
- "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context),
- rijndael_setkey, rijndael_encrypt, rijndael_decrypt
- };
-cipher_extra_spec_t _gcry_cipher_extraspec_aes =
- {
- run_selftests
- };
-
-static const char *rijndael192_names[] =
- {
- "RIJNDAEL192",
- "AES-192",
- NULL
- };
-
-static gcry_cipher_oid_spec_t rijndael192_oids[] =
- {
- { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB },
- { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC },
- { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB },
- { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB },
- { NULL }
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_aes192 =
- {
- "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context),
- rijndael_setkey, rijndael_encrypt, rijndael_decrypt
- };
-cipher_extra_spec_t _gcry_cipher_extraspec_aes192 =
- {
- run_selftests
- };
-
-static const char *rijndael256_names[] =
- {
- "RIJNDAEL256",
- "AES-256",
- NULL
- };
-
-static gcry_cipher_oid_spec_t rijndael256_oids[] =
- {
- { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB },
- { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC },
- { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB },
- { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB },
- { NULL }
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_aes256 =
- {
- "AES256", rijndael256_names, rijndael256_oids, 16, 256,
- sizeof (RIJNDAEL_context),
- rijndael_setkey, rijndael_encrypt, rijndael_decrypt
- };
-
-cipher_extra_spec_t _gcry_cipher_extraspec_aes256 =
- {
- run_selftests
- };
+/* Rijndael (AES) for GnuPG
+ * Copyright (C) 2000, 2001, 2002, 2003, 2007,
+ * 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************
+ * The code here is based on the optimized implementation taken from
+ * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000,
+ * which carries this notice:
+ *------------------------------------------
+ * rijndael-alg-fst.c v2.3 April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ * v2.0: Vincent Rijmen
+ * v2.3: Paulo Barreto
+ *
+ * This code is placed in the public domain.
+ *------------------------------------------
+ *
+ * The SP800-38a document is available at:
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for memcmp() */
+
+#include "types.h" /* for byte and u32 typedefs */
+#include "g10lib.h"
+#include "cipher.h"
+
+#define MAXKC (256/32)
+#define MAXROUNDS 14
+#define BLOCKSIZE (128/8)
+
+
+/* USE_PADLOCK indicates whether to compile the padlock specific
+ code. */
+#undef USE_PADLOCK
+#ifdef ENABLE_PADLOCK_SUPPORT
+# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
+# define USE_PADLOCK
+# endif
+#endif /*ENABLE_PADLOCK_SUPPORT*/
+
+static const char *selftest(void);
+
+typedef struct
+{
+ int ROUNDS; /* Key-length-dependent number of rounds. */
+ int decryption_prepared; /* The decryption key schedule is available. */
+#ifdef USE_PADLOCK
+ int use_padlock; /* Padlock shall be used. */
+ /* The key as passed to the padlock engine. */
+ unsigned char padlock_key[16] __attribute__ ((aligned (16)));
+#endif
+ union
+ {
+ PROPERLY_ALIGNED_TYPE dummy;
+ byte keyschedule[MAXROUNDS+1][4][4];
+ } u1;
+ union
+ {
+ PROPERLY_ALIGNED_TYPE dummy;
+ byte keyschedule[MAXROUNDS+1][4][4];
+ } u2;
+} RIJNDAEL_context;
+
+#define keySched u1.keyschedule
+#define keySched2 u2.keyschedule
+
+/* All the numbers. */
+#include "rijndael-tables.h"
+
+
+/* Perform the key setup. */
+static gcry_err_code_t
+do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+{
+ static int initialized = 0;
+ static const char *selftest_failed=0;
+ int ROUNDS;
+ int i,j, r, t, rconpointer = 0;
+ int KC;
+ union
+ {
+ PROPERLY_ALIGNED_TYPE dummy;
+ byte k[MAXKC][4];
+ } k;
+#define k k.k
+ union
+ {
+ PROPERLY_ALIGNED_TYPE dummy;
+ byte tk[MAXKC][4];
+ } tk;
+#define tk tk.tk
+
+ /* The on-the-fly self tests are only run in non-fips mode. In fips
+ mode explicit self-tests are required. Actually the on-the-fly
+ self-tests are not fully thread-safe and it might happen that a
+ failed self-test won't get noticed in another thread.
+
+ FIXME: We might want to have a central registry of succeeded
+ self-tests. */
+ if (!fips_mode () && !initialized)
+ {
+ initialized = 1;
+ selftest_failed = selftest ();
+ if (selftest_failed)
+ log_error ("%s\n", selftest_failed );
+ }
+ if (selftest_failed)
+ return GPG_ERR_SELFTEST_FAILED;
+
+ ctx->decryption_prepared = 0;
+#ifdef USE_PADLOCK
+ ctx->use_padlock = 0;
+#endif
+
+ if( keylen == 128/8 )
+ {
+ ROUNDS = 10;
+ KC = 4;
+#ifdef USE_PADLOCK
+ if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
+ {
+ ctx->use_padlock = 1;
+ memcpy (ctx->padlock_key, key, keylen);
+ }
+#endif
+ }
+ else if ( keylen == 192/8 )
+ {
+ ROUNDS = 12;
+ KC = 6;
+ }
+ else if ( keylen == 256/8 )
+ {
+ ROUNDS = 14;
+ KC = 8;
+ }
+ else
+ return GPG_ERR_INV_KEYLEN;
+
+ ctx->ROUNDS = ROUNDS;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ {
+ /* Nothing to do as we support only hardware key generation for
+ now. */
+ }
+ else
+#endif /*USE_PADLOCK*/
+ {
+#define W (ctx->keySched)
+ for (i = 0; i < keylen; i++)
+ {
+ k[i >> 2][i & 3] = key[i];
+ }
+
+ for (j = KC-1; j >= 0; j--)
+ {
+ *((u32*)tk[j]) = *((u32*)k[j]);
+ }
+ r = 0;
+ t = 0;
+ /* Copy values into round key array. */
+ for (j = 0; (j < KC) && (r < ROUNDS + 1); )
+ {
+ for (; (j < KC) && (t < 4); j++, t++)
+ {
+ *((u32*)W[r][t]) = *((u32*)tk[j]);
+ }
+ if (t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+
+ while (r < ROUNDS + 1)
+ {
+ /* While not enough round key material calculated calculate
+ new values. */
+ tk[0][0] ^= S[tk[KC-1][1]];
+ tk[0][1] ^= S[tk[KC-1][2]];
+ tk[0][2] ^= S[tk[KC-1][3]];
+ tk[0][3] ^= S[tk[KC-1][0]];
+ tk[0][0] ^= rcon[rconpointer++];
+
+ if (KC != 8)
+ {
+ for (j = 1; j < KC; j++)
+ {
+ *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
+ }
+ }
+ else
+ {
+ for (j = 1; j < KC/2; j++)
+ {
+ *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
+ }
+ tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
+ tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
+ tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
+ tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
+ for (j = KC/2 + 1; j < KC; j++)
+ {
+ *((u32*)tk[j]) ^= *((u32*)tk[j-1]);
+ }
+ }
+
+ /* Copy values into round key array. */
+ for (j = 0; (j < KC) && (r < ROUNDS + 1); )
+ {
+ for (; (j < KC) && (t < 4); j++, t++)
+ {
+ *((u32*)W[r][t]) = *((u32*)tk[j]);
+ }
+ if (t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+ }
+#undef W
+ }
+
+ return 0;
+#undef tk
+#undef k
+}
+
+
+static gcry_err_code_t
+rijndael_setkey (void *context, const byte *key, const unsigned keylen)
+{
+ RIJNDAEL_context *ctx = context;
+
+ int rc = do_setkey (ctx, key, keylen);
+ _gcry_burn_stack ( 100 + 16*sizeof(int));
+ return rc;
+}
+
+
+/* Make a decryption key from an encryption key. */
+static void
+prepare_decryption( RIJNDAEL_context *ctx )
+{
+ int r;
+ union
+ {
+ PROPERLY_ALIGNED_TYPE dummy;
+ byte *w;
+ } w;
+#define w w.w
+
+ for (r=0; r < MAXROUNDS+1; r++ )
+ {
+ *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]);
+ *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]);
+ *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]);
+ *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]);
+ }
+#define W (ctx->keySched2)
+ for (r = 1; r < ctx->ROUNDS; r++)
+ {
+ w = W[r][0];
+ *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+ ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+
+ w = W[r][1];
+ *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+ ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+
+ w = W[r][2];
+ *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+ ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+
+ w = W[r][3];
+ *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+ ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+ }
+#undef W
+#undef w
+}
+
+
+
+/* Encrypt one block. A and B need to be aligned on a 4 byte
+ boundary. A and B may be the same. */
+static void
+do_encrypt_aligned (const RIJNDAEL_context *ctx,
+ unsigned char *b, const unsigned char *a)
+{
+#define rk (ctx->keySched)
+ int ROUNDS = ctx->ROUNDS;
+ int r;
+ union
+ {
+ u32 tempu32[4]; /* Force correct alignment. */
+ byte temp[4][4];
+ } u;
+
+ *((u32*)u.temp[0]) = *((u32*)(a )) ^ *((u32*)rk[0][0]);
+ *((u32*)u.temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[0][1]);
+ *((u32*)u.temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[0][2]);
+ *((u32*)u.temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[0][3]);
+ *((u32*)(b )) = (*((u32*)T1[u.temp[0][0]])
+ ^ *((u32*)T2[u.temp[1][1]])
+ ^ *((u32*)T3[u.temp[2][2]])
+ ^ *((u32*)T4[u.temp[3][3]]));
+ *((u32*)(b + 4)) = (*((u32*)T1[u.temp[1][0]])
+ ^ *((u32*)T2[u.temp[2][1]])
+ ^ *((u32*)T3[u.temp[3][2]])
+ ^ *((u32*)T4[u.temp[0][3]]));
+ *((u32*)(b + 8)) = (*((u32*)T1[u.temp[2][0]])
+ ^ *((u32*)T2[u.temp[3][1]])
+ ^ *((u32*)T3[u.temp[0][2]])
+ ^ *((u32*)T4[u.temp[1][3]]));
+ *((u32*)(b +12)) = (*((u32*)T1[u.temp[3][0]])
+ ^ *((u32*)T2[u.temp[0][1]])
+ ^ *((u32*)T3[u.temp[1][2]])
+ ^ *((u32*)T4[u.temp[2][3]]));
+
+ for (r = 1; r < ROUNDS-1; r++)
+ {
+ *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]);
+ *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]);
+ *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]);
+ *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]);
+
+ *((u32*)(b )) = (*((u32*)T1[u.temp[0][0]])
+ ^ *((u32*)T2[u.temp[1][1]])
+ ^ *((u32*)T3[u.temp[2][2]])
+ ^ *((u32*)T4[u.temp[3][3]]));
+ *((u32*)(b + 4)) = (*((u32*)T1[u.temp[1][0]])
+ ^ *((u32*)T2[u.temp[2][1]])
+ ^ *((u32*)T3[u.temp[3][2]])
+ ^ *((u32*)T4[u.temp[0][3]]));
+ *((u32*)(b + 8)) = (*((u32*)T1[u.temp[2][0]])
+ ^ *((u32*)T2[u.temp[3][1]])
+ ^ *((u32*)T3[u.temp[0][2]])
+ ^ *((u32*)T4[u.temp[1][3]]));
+ *((u32*)(b +12)) = (*((u32*)T1[u.temp[3][0]])
+ ^ *((u32*)T2[u.temp[0][1]])
+ ^ *((u32*)T3[u.temp[1][2]])
+ ^ *((u32*)T4[u.temp[2][3]]));
+ }
+
+ /* Last round is special. */
+ *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[ROUNDS-1][0]);
+ *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[ROUNDS-1][1]);
+ *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[ROUNDS-1][2]);
+ *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[ROUNDS-1][3]);
+ b[ 0] = T1[u.temp[0][0]][1];
+ b[ 1] = T1[u.temp[1][1]][1];
+ b[ 2] = T1[u.temp[2][2]][1];
+ b[ 3] = T1[u.temp[3][3]][1];
+ b[ 4] = T1[u.temp[1][0]][1];
+ b[ 5] = T1[u.temp[2][1]][1];
+ b[ 6] = T1[u.temp[3][2]][1];
+ b[ 7] = T1[u.temp[0][3]][1];
+ b[ 8] = T1[u.temp[2][0]][1];
+ b[ 9] = T1[u.temp[3][1]][1];
+ b[10] = T1[u.temp[0][2]][1];
+ b[11] = T1[u.temp[1][3]][1];
+ b[12] = T1[u.temp[3][0]][1];
+ b[13] = T1[u.temp[0][1]][1];
+ b[14] = T1[u.temp[1][2]][1];
+ b[15] = T1[u.temp[2][3]][1];
+ *((u32*)(b )) ^= *((u32*)rk[ROUNDS][0]);
+ *((u32*)(b+ 4)) ^= *((u32*)rk[ROUNDS][1]);
+ *((u32*)(b+ 8)) ^= *((u32*)rk[ROUNDS][2]);
+ *((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]);
+#undef rk
+}
+
+
+static void
+do_encrypt (const RIJNDAEL_context *ctx,
+ unsigned char *bx, const unsigned char *ax)
+{
+ /* BX and AX are not necessary correctly aligned. Thus we need to
+ copy them here. */
+ union
+ {
+ u32 dummy[4];
+ byte a[16];
+ } a;
+ union
+ {
+ u32 dummy[4];
+ byte b[16];
+ } b;
+
+ memcpy (a.a, ax, 16);
+ do_encrypt_aligned (ctx, b.b, a.a);
+ memcpy (bx, b.b, 16);
+}
+
+
+/* Encrypt or decrypt one block using the padlock engine. A and B may
+ be the same. */
+#ifdef USE_PADLOCK
+static void
+do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag,
+ unsigned char *bx, const unsigned char *ax)
+{
+ /* BX and AX are not necessary correctly aligned. Thus we need to
+ copy them here. */
+ unsigned char a[16] __attribute__ ((aligned (16)));
+ unsigned char b[16] __attribute__ ((aligned (16)));
+ unsigned int cword[4] __attribute__ ((aligned (16)));
+
+ /* The control word fields are:
+ 127:12 11:10 9 8 7 6 5 4 3:0
+ RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */
+ cword[0] = (ctx->ROUNDS & 15); /* (The mask is just a safeguard.) */
+ cword[1] = 0;
+ cword[2] = 0;
+ cword[3] = 0;
+ if (decrypt_flag)
+ cword[0] |= 0x00000200;
+
+ memcpy (a, ax, 16);
+
+ asm volatile
+ ("pushfl\n\t" /* Force key reload. */
+ "popfl\n\t"
+ "xchg %3, %%ebx\n\t" /* Load key. */
+ "movl $1, %%ecx\n\t" /* Init counter for just one block. */
+ ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */
+ "xchg %3, %%ebx\n" /* Restore GOT register. */
+ : /* No output */
+ : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlock_key)
+ : "%ecx", "cc", "memory"
+ );
+
+ memcpy (bx, b, 16);
+
+}
+#endif /*USE_PADLOCK*/
+
+
+static void
+rijndael_encrypt (void *context, byte *b, const byte *a)
+{
+ RIJNDAEL_context *ctx = context;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ {
+ do_padlock (ctx, 0, b, a);
+ _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
+ }
+ else
+#endif /*USE_PADLOCK*/
+ {
+ do_encrypt (ctx, b, a);
+ _gcry_burn_stack (48 + 2*sizeof(int));
+ }
+}
+
+
+/* Bulk encryption of complete blocks in CFB mode. Caller needs to
+ make sure that IV is aligned on an unsigned long boundary. This
+ function is only intended for the bulk encryption feature of
+ cipher.c. */
+void
+_gcry_aes_cfb_enc (void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks)
+{
+ RIJNDAEL_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ unsigned char *ivp;
+ int i;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ {
+ /* Fixme: Let Padlock do the CFBing. */
+ for ( ;nblocks; nblocks-- )
+ {
+ /* Encrypt the IV. */
+ do_padlock (ctx, 0, iv, iv);
+ /* XOR the input with the IV and store input into IV. */
+ for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ }
+ }
+ else
+#endif /* USE_PADLOCK*/
+ {
+ for ( ;nblocks; nblocks-- )
+ {
+ /* Encrypt the IV. */
+ do_encrypt_aligned (ctx, iv, iv);
+ /* XOR the input with the IV and store input into IV. */
+ for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+ *outbuf++ = (*ivp++ ^= *inbuf++);
+ }
+ }
+
+ _gcry_burn_stack (48 + 2*sizeof(int));
+}
+
+
+/* Bulk encryption of complete blocks in CBC mode. Caller needs to
+ make sure that IV is aligned on an unsigned long boundary. This
+ function is only intended for the bulk encryption feature of
+ cipher.c. */
+void
+_gcry_aes_cbc_enc (void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks, int cbc_mac)
+{
+ RIJNDAEL_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ unsigned char *ivp;
+ int i;
+
+ for ( ;nblocks; nblocks-- )
+ {
+ for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
+ outbuf[i] = inbuf[i] ^ *ivp++;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ do_padlock (ctx, 0, outbuf, outbuf);
+ else
+#endif /*USE_PADLOCK*/
+ do_encrypt (ctx, outbuf, outbuf );
+
+ memcpy (iv, outbuf, BLOCKSIZE);
+ inbuf += BLOCKSIZE;
+ if (!cbc_mac)
+ outbuf += BLOCKSIZE;
+ }
+
+ _gcry_burn_stack (48 + 2*sizeof(int));
+}
+
+
+
+/* Decrypt one block. A and B need to be aligned on a 4 byte boundary
+ and the decryption must have been prepared. A and B may be the
+ same. */
+static void
+do_decrypt_aligned (RIJNDAEL_context *ctx,
+ unsigned char *b, const unsigned char *a)
+{
+#define rk (ctx->keySched2)
+ int ROUNDS = ctx->ROUNDS;
+ int r;
+ union
+ {
+ u32 tempu32[4]; /* Force correct alignment. */
+ byte temp[4][4];
+ } u;
+
+
+ *((u32*)u.temp[0]) = *((u32*)(a )) ^ *((u32*)rk[ROUNDS][0]);
+ *((u32*)u.temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[ROUNDS][1]);
+ *((u32*)u.temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[ROUNDS][2]);
+ *((u32*)u.temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[ROUNDS][3]);
+
+ *((u32*)(b )) = (*((u32*)T5[u.temp[0][0]])
+ ^ *((u32*)T6[u.temp[3][1]])
+ ^ *((u32*)T7[u.temp[2][2]])
+ ^ *((u32*)T8[u.temp[1][3]]));
+ *((u32*)(b+ 4)) = (*((u32*)T5[u.temp[1][0]])
+ ^ *((u32*)T6[u.temp[0][1]])
+ ^ *((u32*)T7[u.temp[3][2]])
+ ^ *((u32*)T8[u.temp[2][3]]));
+ *((u32*)(b+ 8)) = (*((u32*)T5[u.temp[2][0]])
+ ^ *((u32*)T6[u.temp[1][1]])
+ ^ *((u32*)T7[u.temp[0][2]])
+ ^ *((u32*)T8[u.temp[3][3]]));
+ *((u32*)(b+12)) = (*((u32*)T5[u.temp[3][0]])
+ ^ *((u32*)T6[u.temp[2][1]])
+ ^ *((u32*)T7[u.temp[1][2]])
+ ^ *((u32*)T8[u.temp[0][3]]));
+
+ for (r = ROUNDS-1; r > 1; r--)
+ {
+ *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]);
+ *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]);
+ *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]);
+ *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]);
+ *((u32*)(b )) = (*((u32*)T5[u.temp[0][0]])
+ ^ *((u32*)T6[u.temp[3][1]])
+ ^ *((u32*)T7[u.temp[2][2]])
+ ^ *((u32*)T8[u.temp[1][3]]));
+ *((u32*)(b+ 4)) = (*((u32*)T5[u.temp[1][0]])
+ ^ *((u32*)T6[u.temp[0][1]])
+ ^ *((u32*)T7[u.temp[3][2]])
+ ^ *((u32*)T8[u.temp[2][3]]));
+ *((u32*)(b+ 8)) = (*((u32*)T5[u.temp[2][0]])
+ ^ *((u32*)T6[u.temp[1][1]])
+ ^ *((u32*)T7[u.temp[0][2]])
+ ^ *((u32*)T8[u.temp[3][3]]));
+ *((u32*)(b+12)) = (*((u32*)T5[u.temp[3][0]])
+ ^ *((u32*)T6[u.temp[2][1]])
+ ^ *((u32*)T7[u.temp[1][2]])
+ ^ *((u32*)T8[u.temp[0][3]]));
+ }
+
+ /* Last round is special. */
+ *((u32*)u.temp[0]) = *((u32*)(b )) ^ *((u32*)rk[1][0]);
+ *((u32*)u.temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[1][1]);
+ *((u32*)u.temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[1][2]);
+ *((u32*)u.temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[1][3]);
+ b[ 0] = S5[u.temp[0][0]];
+ b[ 1] = S5[u.temp[3][1]];
+ b[ 2] = S5[u.temp[2][2]];
+ b[ 3] = S5[u.temp[1][3]];
+ b[ 4] = S5[u.temp[1][0]];
+ b[ 5] = S5[u.temp[0][1]];
+ b[ 6] = S5[u.temp[3][2]];
+ b[ 7] = S5[u.temp[2][3]];
+ b[ 8] = S5[u.temp[2][0]];
+ b[ 9] = S5[u.temp[1][1]];
+ b[10] = S5[u.temp[0][2]];
+ b[11] = S5[u.temp[3][3]];
+ b[12] = S5[u.temp[3][0]];
+ b[13] = S5[u.temp[2][1]];
+ b[14] = S5[u.temp[1][2]];
+ b[15] = S5[u.temp[0][3]];
+ *((u32*)(b )) ^= *((u32*)rk[0][0]);
+ *((u32*)(b+ 4)) ^= *((u32*)rk[0][1]);
+ *((u32*)(b+ 8)) ^= *((u32*)rk[0][2]);
+ *((u32*)(b+12)) ^= *((u32*)rk[0][3]);
+#undef rk
+}
+
+
+/* Decrypt one block. AX and BX may be the same. */
+static void
+do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax)
+{
+ /* BX and AX are not necessary correctly aligned. Thus we need to
+ copy them here. */
+ union
+ {
+ u32 dummy[4];
+ byte a[16];
+ } a;
+ union
+ {
+ u32 dummy[4];
+ byte b[16];
+ } b;
+
+ if ( !ctx->decryption_prepared )
+ {
+ prepare_decryption ( ctx );
+ _gcry_burn_stack (64);
+ ctx->decryption_prepared = 1;
+ }
+
+ memcpy (a.a, ax, 16);
+ do_decrypt_aligned (ctx, b.b, a.a);
+ memcpy (bx, b.b, 16);
+#undef rk
+}
+
+
+
+
+static void
+rijndael_decrypt (void *context, byte *b, const byte *a)
+{
+ RIJNDAEL_context *ctx = context;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ {
+ do_padlock (ctx, 1, b, a);
+ _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
+ }
+ else
+#endif /*USE_PADLOCK*/
+ {
+ do_decrypt (ctx, b, a);
+ _gcry_burn_stack (48+2*sizeof(int));
+ }
+}
+
+
+/* Bulk decryption of complete blocks in CFB mode. Caller needs to
+ make sure that IV is aligned on an unisgned lonhg boundary. This
+ function is only intended for the bulk encryption feature of
+ cipher.c. */
+void
+_gcry_aes_cfb_dec (void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks)
+{
+ RIJNDAEL_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ unsigned char *ivp;
+ unsigned char temp;
+ int i;
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ {
+ /* Fixme: Let Padlock do the CFBing. */
+ for ( ;nblocks; nblocks-- )
+ {
+ do_padlock (ctx, 0, iv, iv);
+ for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ }
+ }
+ else
+#endif /*USE_PADLOCK*/
+ {
+ for ( ;nblocks; nblocks-- )
+ {
+ do_encrypt_aligned (ctx, iv, iv);
+ for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+ {
+ temp = *inbuf++;
+ *outbuf++ = *ivp ^ temp;
+ *ivp++ = temp;
+ }
+ }
+ }
+
+ _gcry_burn_stack (48 + 2*sizeof(int));
+}
+
+
+/* Bulk decryption of complete blocks in CBC mode. Caller needs to
+ make sure that IV is aligned on an unsigned long boundary. This
+ function is only intended for the bulk encryption feature of
+ cipher.c. */
+void
+_gcry_aes_cbc_dec (void *context, unsigned char *iv,
+ void *outbuf_arg, const void *inbuf_arg,
+ unsigned int nblocks)
+{
+ RIJNDAEL_context *ctx = context;
+ unsigned char *outbuf = outbuf_arg;
+ const unsigned char *inbuf = inbuf_arg;
+ unsigned char *ivp;
+ int i;
+ unsigned char savebuf[BLOCKSIZE];
+
+ for ( ;nblocks; nblocks-- )
+ {
+ /* We need to save INBUF away because it may be identical to
+ OUTBUF. */
+ memcpy (savebuf, inbuf, BLOCKSIZE);
+
+#ifdef USE_PADLOCK
+ if (ctx->use_padlock)
+ do_padlock (ctx, 1, outbuf, inbuf);
+ else
+#endif /*USE_PADLOCK*/
+ do_decrypt (ctx, outbuf, inbuf);
+
+ for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
+ outbuf[i] ^= *ivp++;
+ memcpy (iv, savebuf, BLOCKSIZE);
+ inbuf += BLOCKSIZE;
+ outbuf += BLOCKSIZE;
+ }
+
+ _gcry_burn_stack (48 + 2*sizeof(int) + BLOCKSIZE + 4*sizeof (char*));
+}
+
+
+
+
+/* Run the self-tests for AES 128. Returns NULL on success. */
+static const char*
+selftest_basic_128 (void)
+{
+ RIJNDAEL_context ctx;
+ unsigned char scratch[16];
+
+ /* The test vectors are from the AES supplied ones; more or less
+ randomly taken from ecb_tbl.txt (I=42,81,14) */
+ static const unsigned char plaintext_128[16] =
+ {
+ 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
+ 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
+ };
+ static const unsigned char key_128[16] =
+ {
+ 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
+ 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
+ };
+ static const unsigned char ciphertext_128[16] =
+ {
+ 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
+ 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
+ };
+
+ rijndael_setkey (&ctx, key_128, sizeof (key_128));
+ rijndael_encrypt (&ctx, scratch, plaintext_128);
+ if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128)))
+ return "AES-128 test encryption failed.";
+ rijndael_decrypt (&ctx, scratch, scratch);
+ if (memcmp (scratch, plaintext_128, sizeof (plaintext_128)))
+ return "AES-128 test decryption failed.";
+
+ return NULL;
+}
+
+/* Run the self-tests for AES 192. Returns NULL on success. */
+static const char*
+selftest_basic_192 (void)
+{
+ RIJNDAEL_context ctx;
+ unsigned char scratch[16];
+
+ static unsigned char plaintext_192[16] =
+ {
+ 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
+ 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
+ };
+ static unsigned char key_192[24] =
+ {
+ 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
+ 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
+ 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
+ };
+ static const unsigned char ciphertext_192[16] =
+ {
+ 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
+ 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
+ };
+
+ rijndael_setkey (&ctx, key_192, sizeof(key_192));
+ rijndael_encrypt (&ctx, scratch, plaintext_192);
+ if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
+ return "AES-192 test encryption failed.";
+ rijndael_decrypt (&ctx, scratch, scratch);
+ if (memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
+ return "AES-192 test decryption failed.";
+
+ return NULL;
+}
+
+
+/* Run the self-tests for AES 256. Returns NULL on success. */
+static const char*
+selftest_basic_256 (void)
+{
+ RIJNDAEL_context ctx;
+ unsigned char scratch[16];
+
+ static unsigned char plaintext_256[16] =
+ {
+ 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
+ 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
+ };
+ static unsigned char key_256[32] =
+ {
+ 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
+ 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
+ 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
+ 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
+ };
+ static const unsigned char ciphertext_256[16] =
+ {
+ 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
+ 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
+ };
+
+ rijndael_setkey (&ctx, key_256, sizeof(key_256));
+ rijndael_encrypt (&ctx, scratch, plaintext_256);
+ if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
+ return "AES-256 test encryption failed.";
+ rijndael_decrypt (&ctx, scratch, scratch);
+ if (memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
+ return "AES-256 test decryption failed.";
+
+ return NULL;
+}
+
+/* Run all the self-tests and return NULL on success. This function
+ is used for the on-the-fly self-tests. */
+static const char *
+selftest (void)
+{
+ const char *r;
+
+ if ( (r = selftest_basic_128 ())
+ || (r = selftest_basic_192 ())
+ || (r = selftest_basic_256 ()) )
+ return r;
+
+ return r;
+}
+
+
+/* SP800-38a.pdf for AES-128. */
+static const char *
+selftest_fips_128_38a (int requested_mode)
+{
+ struct tv
+ {
+ int mode;
+ const unsigned char key[16];
+ const unsigned char iv[16];
+ struct
+ {
+ const unsigned char input[16];
+ const unsigned char output[16];
+ } data[4];
+ } tv[2] =
+ {
+ {
+ GCRY_CIPHER_MODE_CFB, /* F.3.13, CFB128-AES128 */
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ {
+ { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+ { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
+ 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
+
+ { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
+ { 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f,
+ 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } },
+
+ { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
+ { 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40,
+ 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } },
+
+ { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ { 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e,
+ 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } }
+ }
+ },
+ {
+ GCRY_CIPHER_MODE_OFB,
+ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ {
+ { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+ { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
+ 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
+
+ { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
+ { 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+ 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } },
+
+ { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
+ { 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+ 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } },
+
+ { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ { 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+ 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } },
+ }
+ }
+ };
+ unsigned char scratch[16];
+ gpg_error_t err;
+ int tvi, idx;
+ gcry_cipher_hd_t hdenc = NULL;
+ gcry_cipher_hd_t hddec = NULL;
+
+#define Fail(a) do { \
+ _gcry_cipher_close (hdenc); \
+ _gcry_cipher_close (hddec); \
+ return a; \
+ } while (0)
+
+ gcry_assert (sizeof tv[0].data[0].input == sizeof scratch);
+ gcry_assert (sizeof tv[0].data[0].output == sizeof scratch);
+
+ for (tvi=0; tvi < DIM (tv); tvi++)
+ if (tv[tvi].mode == requested_mode)
+ break;
+ if (tvi == DIM (tv))
+ Fail ("no test data for this mode");
+
+ err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+ if (err)
+ Fail ("open");
+ err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+ if (err)
+ Fail ("open");
+ err = _gcry_cipher_setkey (hdenc, tv[tvi].key, sizeof tv[tvi].key);
+ if (!err)
+ err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key);
+ if (err)
+ Fail ("set key");
+ err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv);
+ if (!err)
+ err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv);
+ if (err)
+ Fail ("set IV");
+ for (idx=0; idx < DIM (tv[tvi].data); idx++)
+ {
+ err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch,
+ tv[tvi].data[idx].input,
+ sizeof tv[tvi].data[idx].input);
+ if (err)
+ Fail ("encrypt command");
+ if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch))
+ Fail ("encrypt mismatch");
+ err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch,
+ tv[tvi].data[idx].output,
+ sizeof tv[tvi].data[idx].output);
+ if (err)
+ Fail ("decrypt command");
+ if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch))
+ Fail ("decrypt mismatch");
+ }
+
+#undef Fail
+ _gcry_cipher_close (hdenc);
+ _gcry_cipher_close (hddec);
+ return NULL;
+}
+
+
+/* Complete selftest for AES-128 with all modes and driver code. */
+static gpg_err_code_t
+selftest_fips_128 (int extended, selftest_report_func_t report)
+{
+ const char *what;
+ const char *errtxt;
+
+ what = "low-level";
+ errtxt = selftest_basic_128 ();
+ if (errtxt)
+ goto failed;
+
+ if (extended)
+ {
+ what = "cfb";
+ errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB);
+ if (errtxt)
+ goto failed;
+
+ what = "ofb";
+ errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB);
+ if (errtxt)
+ goto failed;
+ }
+
+ return 0; /* Succeeded. */
+
+ failed:
+ if (report)
+ report ("cipher", GCRY_CIPHER_AES128, what, errtxt);
+ return GPG_ERR_SELFTEST_FAILED;
+}
+
+/* Complete selftest for AES-192. */
+static gpg_err_code_t
+selftest_fips_192 (int extended, selftest_report_func_t report)
+{
+ const char *what;
+ const char *errtxt;
+
+ (void)extended; /* No extended tests available. */
+
+ what = "low-level";
+ errtxt = selftest_basic_192 ();
+ if (errtxt)
+ goto failed;
+
+
+ return 0; /* Succeeded. */
+
+ failed:
+ if (report)
+ report ("cipher", GCRY_CIPHER_AES192, what, errtxt);
+ return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Complete selftest for AES-256. */
+static gpg_err_code_t
+selftest_fips_256 (int extended, selftest_report_func_t report)
+{
+ const char *what;
+ const char *errtxt;
+
+ (void)extended; /* No extended tests available. */
+
+ what = "low-level";
+ errtxt = selftest_basic_256 ();
+ if (errtxt)
+ goto failed;
+
+ return 0; /* Succeeded. */
+
+ failed:
+ if (report)
+ report ("cipher", GCRY_CIPHER_AES256, what, errtxt);
+ return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+/* Run a full self-test for ALGO and return 0 on success. */
+static gpg_err_code_t
+run_selftests (int algo, int extended, selftest_report_func_t report)
+{
+ gpg_err_code_t ec;
+
+ switch (algo)
+ {
+ case GCRY_CIPHER_AES128:
+ ec = selftest_fips_128 (extended, report);
+ break;
+ case GCRY_CIPHER_AES192:
+ ec = selftest_fips_192 (extended, report);
+ break;
+ case GCRY_CIPHER_AES256:
+ ec = selftest_fips_256 (extended, report);
+ break;
+ default:
+ ec = GPG_ERR_CIPHER_ALGO;
+ break;
+
+ }
+ return ec;
+}
+
+
+
+
+static const char *rijndael_names[] =
+ {
+ "RIJNDAEL",
+ "AES128",
+ "AES-128",
+ NULL
+ };
+
+static gcry_cipher_oid_spec_t rijndael_oids[] =
+ {
+ { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB },
+ { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC },
+ { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB },
+ { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB },
+ { NULL }
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_aes =
+ {
+ "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context),
+ rijndael_setkey, rijndael_encrypt, rijndael_decrypt
+ };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes =
+ {
+ run_selftests
+ };
+
+static const char *rijndael192_names[] =
+ {
+ "RIJNDAEL192",
+ "AES-192",
+ NULL
+ };
+
+static gcry_cipher_oid_spec_t rijndael192_oids[] =
+ {
+ { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB },
+ { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC },
+ { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB },
+ { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB },
+ { NULL }
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_aes192 =
+ {
+ "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context),
+ rijndael_setkey, rijndael_encrypt, rijndael_decrypt
+ };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes192 =
+ {
+ run_selftests
+ };
+
+static const char *rijndael256_names[] =
+ {
+ "RIJNDAEL256",
+ "AES-256",
+ NULL
+ };
+
+static gcry_cipher_oid_spec_t rijndael256_oids[] =
+ {
+ { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB },
+ { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC },
+ { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB },
+ { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB },
+ { NULL }
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_aes256 =
+ {
+ "AES256", rijndael256_names, rijndael256_oids, 16, 256,
+ sizeof (RIJNDAEL_context),
+ rijndael_setkey, rijndael_encrypt, rijndael_decrypt
+ };
+
+cipher_extra_spec_t _gcry_cipher_extraspec_aes256 =
+ {
+ run_selftests
+ };
diff --git a/libgcrypt-1.4.6/cipher/serpent.c b/libgcrypt-1.4.6/cipher/serpent.c
index 6b7e655..0ac0b5b 100644
--- a/libgcrypt-1.4.6/cipher/serpent.c
+++ b/libgcrypt-1.4.6/cipher/serpent.c
@@ -1,978 +1,978 @@
-/* serpent.c - Implementation of the Serpent encryption algorithm.
- * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <stdio.h>
-
-#include "types.h"
-#include "g10lib.h"
-#include "cipher.h"
-#include "bithelp.h"
-
-/* Number of rounds per Serpent encrypt/decrypt operation. */
-#define ROUNDS 32
-
-/* Magic number, used during generating of the subkeys. */
-#define PHI 0x9E3779B9
-
-/* Serpent works on 128 bit blocks. */
-typedef u32 serpent_block_t[4];
-
-/* Serpent key, provided by the user. If the original key is shorter
- than 256 bits, it is padded. */
-typedef u32 serpent_key_t[8];
-
-/* The key schedule consists of 33 128 bit subkeys. */
-typedef u32 serpent_subkeys_t[ROUNDS + 1][4];
-
-/* A Serpent context. */
-typedef struct serpent_context
-{
- serpent_subkeys_t keys; /* Generated subkeys. */
-} serpent_context_t;
-
-
-/* A prototype. */
-static const char *serpent_test (void);
-
-
-#define byte_swap_32(x) \
- (0 \
- | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
- | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
-
-/* These are the S-Boxes of Serpent. They are copied from Serpents
- reference implementation (the optimized one, contained in
- `floppy2') and are therefore:
-
- Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
-
- To quote the Serpent homepage
- (http://www.cl.cam.ac.uk/~rja14/serpent.html):
-
- "Serpent is now completely in the public domain, and we impose no
- restrictions on its use. This was announced on the 21st August at
- the First AES Candidate Conference. The optimised implementations
- in the submission package are now under the GNU PUBLIC LICENSE
- (GPL), although some comments in the code still say otherwise. You
- are welcome to use Serpent for any application." */
-
-#define SBOX0(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t05, t06, t07, t08, t09; \
- u32 t11, t12, t13, t14, t15, t17, t01; \
- t01 = b ^ c ; \
- t02 = a | d ; \
- t03 = a ^ b ; \
- z = t02 ^ t01; \
- t05 = c | z ; \
- t06 = a ^ d ; \
- t07 = b | c ; \
- t08 = d & t05; \
- t09 = t03 & t07; \
- y = t09 ^ t08; \
- t11 = t09 & y ; \
- t12 = c ^ d ; \
- t13 = t07 ^ t11; \
- t14 = b & t06; \
- t15 = t06 ^ t13; \
- w = ~ t15; \
- t17 = w ^ t14; \
- x = t12 ^ t17; \
- }
-
-#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t08, t09, t10; \
- u32 t12, t13, t14, t15, t17, t18, t01; \
- t01 = c ^ d ; \
- t02 = a | b ; \
- t03 = b | c ; \
- t04 = c & t01; \
- t05 = t02 ^ t01; \
- t06 = a | t04; \
- y = ~ t05; \
- t08 = b ^ d ; \
- t09 = t03 & t08; \
- t10 = d | y ; \
- x = t09 ^ t06; \
- t12 = a | t05; \
- t13 = x ^ t12; \
- t14 = t03 ^ t10; \
- t15 = a ^ c ; \
- z = t14 ^ t13; \
- t17 = t05 & t13; \
- t18 = t14 | t17; \
- w = t15 ^ t18; \
- }
-
-#define SBOX1(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t08; \
- u32 t10, t11, t12, t13, t16, t17, t01; \
- t01 = a | d ; \
- t02 = c ^ d ; \
- t03 = ~ b ; \
- t04 = a ^ c ; \
- t05 = a | t03; \
- t06 = d & t04; \
- t07 = t01 & t02; \
- t08 = b | t06; \
- y = t02 ^ t05; \
- t10 = t07 ^ t08; \
- t11 = t01 ^ t10; \
- t12 = y ^ t11; \
- t13 = b & d ; \
- z = ~ t10; \
- x = t13 ^ t12; \
- t16 = t10 | x ; \
- t17 = t05 & t16; \
- w = c ^ t17; \
- }
-
-#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t08; \
- u32 t09, t10, t11, t14, t15, t17, t01; \
- t01 = a ^ b ; \
- t02 = b | d ; \
- t03 = a & c ; \
- t04 = c ^ t02; \
- t05 = a | t04; \
- t06 = t01 & t05; \
- t07 = d | t03; \
- t08 = b ^ t06; \
- t09 = t07 ^ t06; \
- t10 = t04 | t03; \
- t11 = d & t08; \
- y = ~ t09; \
- x = t10 ^ t11; \
- t14 = a | y ; \
- t15 = t06 ^ x ; \
- z = t01 ^ t04; \
- t17 = c ^ t15; \
- w = t14 ^ t17; \
- }
-
-#define SBOX2(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t05, t06, t07, t08; \
- u32 t09, t10, t12, t13, t14, t01; \
- t01 = a | c ; \
- t02 = a ^ b ; \
- t03 = d ^ t01; \
- w = t02 ^ t03; \
- t05 = c ^ w ; \
- t06 = b ^ t05; \
- t07 = b | t05; \
- t08 = t01 & t06; \
- t09 = t03 ^ t07; \
- t10 = t02 | t09; \
- x = t10 ^ t08; \
- t12 = a | d ; \
- t13 = t09 ^ x ; \
- t14 = b ^ t13; \
- z = ~ t09; \
- y = t12 ^ t14; \
- }
-
-#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t06, t07, t08, t09; \
- u32 t10, t11, t12, t15, t16, t17, t01; \
- t01 = a ^ d ; \
- t02 = c ^ d ; \
- t03 = a & c ; \
- t04 = b | t02; \
- w = t01 ^ t04; \
- t06 = a | c ; \
- t07 = d | w ; \
- t08 = ~ d ; \
- t09 = b & t06; \
- t10 = t08 | t03; \
- t11 = b & t07; \
- t12 = t06 & t02; \
- z = t09 ^ t10; \
- x = t12 ^ t11; \
- t15 = c & z ; \
- t16 = w ^ x ; \
- t17 = t10 ^ t15; \
- y = t16 ^ t17; \
- }
-
-#define SBOX3(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t08; \
- u32 t09, t10, t11, t13, t14, t15, t01; \
- t01 = a ^ c ; \
- t02 = a | d ; \
- t03 = a & d ; \
- t04 = t01 & t02; \
- t05 = b | t03; \
- t06 = a & b ; \
- t07 = d ^ t04; \
- t08 = c | t06; \
- t09 = b ^ t07; \
- t10 = d & t05; \
- t11 = t02 ^ t10; \
- z = t08 ^ t09; \
- t13 = d | z ; \
- t14 = a | t07; \
- t15 = b & t13; \
- y = t08 ^ t11; \
- w = t14 ^ t15; \
- x = t05 ^ t04; \
- }
-
-#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t09; \
- u32 t11, t12, t13, t14, t16, t01; \
- t01 = c | d ; \
- t02 = a | d ; \
- t03 = c ^ t02; \
- t04 = b ^ t02; \
- t05 = a ^ d ; \
- t06 = t04 & t03; \
- t07 = b & t01; \
- y = t05 ^ t06; \
- t09 = a ^ t03; \
- w = t07 ^ t03; \
- t11 = w | t05; \
- t12 = t09 & t11; \
- t13 = a & y ; \
- t14 = t01 ^ t05; \
- x = b ^ t12; \
- t16 = b | t13; \
- z = t14 ^ t16; \
- }
-
-#define SBOX4(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t08, t09; \
- u32 t10, t11, t12, t13, t14, t15, t16, t01; \
- t01 = a | b ; \
- t02 = b | c ; \
- t03 = a ^ t02; \
- t04 = b ^ d ; \
- t05 = d | t03; \
- t06 = d & t01; \
- z = t03 ^ t06; \
- t08 = z & t04; \
- t09 = t04 & t05; \
- t10 = c ^ t06; \
- t11 = b & c ; \
- t12 = t04 ^ t08; \
- t13 = t11 | t03; \
- t14 = t10 ^ t09; \
- t15 = a & t05; \
- t16 = t11 | t12; \
- y = t13 ^ t08; \
- x = t15 ^ t16; \
- w = ~ t14; \
- }
-
-#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t09; \
- u32 t10, t11, t12, t13, t15, t01; \
- t01 = b | d ; \
- t02 = c | d ; \
- t03 = a & t01; \
- t04 = b ^ t02; \
- t05 = c ^ d ; \
- t06 = ~ t03; \
- t07 = a & t04; \
- x = t05 ^ t07; \
- t09 = x | t06; \
- t10 = a ^ t07; \
- t11 = t01 ^ t09; \
- t12 = d ^ t04; \
- t13 = c | t10; \
- z = t03 ^ t12; \
- t15 = a ^ t04; \
- y = t11 ^ t13; \
- w = t15 ^ t09; \
- }
-
-#define SBOX5(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t07, t08, t09; \
- u32 t10, t11, t12, t13, t14, t01; \
- t01 = b ^ d ; \
- t02 = b | d ; \
- t03 = a & t01; \
- t04 = c ^ t02; \
- t05 = t03 ^ t04; \
- w = ~ t05; \
- t07 = a ^ t01; \
- t08 = d | w ; \
- t09 = b | t05; \
- t10 = d ^ t08; \
- t11 = b | t07; \
- t12 = t03 | w ; \
- t13 = t07 | t10; \
- t14 = t01 ^ t11; \
- y = t09 ^ t13; \
- x = t07 ^ t08; \
- z = t12 ^ t14; \
- }
-
-#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t07, t08, t09; \
- u32 t10, t12, t13, t15, t16, t01; \
- t01 = a & d ; \
- t02 = c ^ t01; \
- t03 = a ^ d ; \
- t04 = b & t02; \
- t05 = a & c ; \
- w = t03 ^ t04; \
- t07 = a & w ; \
- t08 = t01 ^ w ; \
- t09 = b | t05; \
- t10 = ~ b ; \
- x = t08 ^ t09; \
- t12 = t10 | t07; \
- t13 = w | x ; \
- z = t02 ^ t12; \
- t15 = t02 ^ t13; \
- t16 = b ^ d ; \
- y = t16 ^ t15; \
- }
-
-#define SBOX6(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t07, t08, t09, t10; \
- u32 t11, t12, t13, t15, t17, t18, t01; \
- t01 = a & d ; \
- t02 = b ^ c ; \
- t03 = a ^ d ; \
- t04 = t01 ^ t02; \
- t05 = b | c ; \
- x = ~ t04; \
- t07 = t03 & t05; \
- t08 = b & x ; \
- t09 = a | c ; \
- t10 = t07 ^ t08; \
- t11 = b | d ; \
- t12 = c ^ t11; \
- t13 = t09 ^ t10; \
- y = ~ t13; \
- t15 = x & t03; \
- z = t12 ^ t07; \
- t17 = a ^ b ; \
- t18 = y ^ t15; \
- w = t17 ^ t18; \
- }
-
-#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t07, t08, t09; \
- u32 t12, t13, t14, t15, t16, t17, t01; \
- t01 = a ^ c ; \
- t02 = ~ c ; \
- t03 = b & t01; \
- t04 = b | t02; \
- t05 = d | t03; \
- t06 = b ^ d ; \
- t07 = a & t04; \
- t08 = a | t02; \
- t09 = t07 ^ t05; \
- x = t06 ^ t08; \
- w = ~ t09; \
- t12 = b & w ; \
- t13 = t01 & t05; \
- t14 = t01 ^ t12; \
- t15 = t07 ^ t13; \
- t16 = d | t02; \
- t17 = a ^ x ; \
- z = t17 ^ t15; \
- y = t16 ^ t14; \
- }
-
-#define SBOX7(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t05, t06, t08, t09, t10; \
- u32 t11, t13, t14, t15, t16, t17, t01; \
- t01 = a & c ; \
- t02 = ~ d ; \
- t03 = a & t02; \
- t04 = b | t01; \
- t05 = a & b ; \
- t06 = c ^ t04; \
- z = t03 ^ t06; \
- t08 = c | z ; \
- t09 = d | t05; \
- t10 = a ^ t08; \
- t11 = t04 & z ; \
- x = t09 ^ t10; \
- t13 = b ^ x ; \
- t14 = t01 ^ x ; \
- t15 = c ^ t05; \
- t16 = t11 | t13; \
- t17 = t02 | t14; \
- w = t15 ^ t17; \
- y = a ^ t16; \
- }
-
-#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \
- { \
- u32 t02, t03, t04, t06, t07, t08, t09; \
- u32 t10, t11, t13, t14, t15, t16, t01; \
- t01 = a & b ; \
- t02 = a | b ; \
- t03 = c | t01; \
- t04 = d & t02; \
- z = t03 ^ t04; \
- t06 = b ^ t04; \
- t07 = d ^ z ; \
- t08 = ~ t07; \
- t09 = t06 | t08; \
- t10 = b ^ d ; \
- t11 = a | d ; \
- x = a ^ t09; \
- t13 = c ^ t06; \
- t14 = c & t11; \
- t15 = d | x ; \
- t16 = t01 | t10; \
- w = t13 ^ t15; \
- y = t14 ^ t16; \
- }
-
-/* XOR BLOCK1 into BLOCK0. */
-#define BLOCK_XOR(block0, block1) \
- { \
- block0[0] ^= block1[0]; \
- block0[1] ^= block1[1]; \
- block0[2] ^= block1[2]; \
- block0[3] ^= block1[3]; \
- }
-
-/* Copy BLOCK_SRC to BLOCK_DST. */
-#define BLOCK_COPY(block_dst, block_src) \
- { \
- block_dst[0] = block_src[0]; \
- block_dst[1] = block_src[1]; \
- block_dst[2] = block_src[2]; \
- block_dst[3] = block_src[3]; \
- }
-
-/* Apply SBOX number WHICH to to the block found in ARRAY0 at index
- INDEX, writing the output to the block found in ARRAY1 at index
- INDEX. */
-#define SBOX(which, array0, array1, index) \
- SBOX##which (array0[index + 0], array0[index + 1], \
- array0[index + 2], array0[index + 3], \
- array1[index + 0], array1[index + 1], \
- array1[index + 2], array1[index + 3]);
-
-/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at
- index INDEX, writing the output to the block found in ARRAY1 at
- index INDEX. */
-#define SBOX_INVERSE(which, array0, array1, index) \
- SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \
- array0[index + 2], array0[index + 3], \
- array1[index + 0], array1[index + 1], \
- array1[index + 2], array1[index + 3]);
-
-/* Apply the linear transformation to BLOCK. */
-#define LINEAR_TRANSFORMATION(block) \
- { \
- block[0] = rol (block[0], 13); \
- block[2] = rol (block[2], 3); \
- block[1] = block[1] ^ block[0] ^ block[2]; \
- block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
- block[1] = rol (block[1], 1); \
- block[3] = rol (block[3], 7); \
- block[0] = block[0] ^ block[1] ^ block[3]; \
- block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
- block[0] = rol (block[0], 5); \
- block[2] = rol (block[2], 22); \
- }
-
-/* Apply the inverse linear transformation to BLOCK. */
-#define LINEAR_TRANSFORMATION_INVERSE(block) \
- { \
- block[2] = ror (block[2], 22); \
- block[0] = ror (block[0] , 5); \
- block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
- block[0] = block[0] ^ block[1] ^ block[3]; \
- block[3] = ror (block[3], 7); \
- block[1] = ror (block[1], 1); \
- block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
- block[1] = block[1] ^ block[0] ^ block[2]; \
- block[2] = ror (block[2], 3); \
- block[0] = ror (block[0], 13); \
- }
-
-/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
- subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage.
- This macro increments `round'. */
-#define ROUND(which, subkeys, block, block_tmp) \
- { \
- BLOCK_XOR (block, subkeys[round]); \
- round++; \
- SBOX (which, block, block_tmp, 0); \
- LINEAR_TRANSFORMATION (block_tmp); \
- BLOCK_COPY (block, block_tmp); \
- }
-
-/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
- and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
- storage. The result will be stored in BLOCK_TMP. This macro
- increments `round'. */
-#define ROUND_LAST(which, subkeys, block, block_tmp) \
- { \
- BLOCK_XOR (block, subkeys[round]); \
- round++; \
- SBOX (which, block, block_tmp, 0); \
- BLOCK_XOR (block_tmp, subkeys[round]); \
- round++; \
- }
-
-/* Apply an inverse Serpent round to BLOCK, using the SBOX number
- WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as
- temporary storage. This macro increments `round'. */
-#define ROUND_INVERSE(which, subkey, block, block_tmp) \
- { \
- LINEAR_TRANSFORMATION_INVERSE (block); \
- SBOX_INVERSE (which, block, block_tmp, 0); \
- BLOCK_XOR (block_tmp, subkey[round]); \
- round--; \
- BLOCK_COPY (block, block_tmp); \
- }
-
-/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
- and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
- storage. The result will be stored in BLOCK_TMP. This macro
- increments `round'. */
-#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
- { \
- BLOCK_XOR (block, subkeys[round]); \
- round--; \
- SBOX_INVERSE (which, block, block_tmp, 0); \
- BLOCK_XOR (block_tmp, subkeys[round]); \
- round--; \
- }
-
-/* Convert the user provided key KEY of KEY_LENGTH bytes into the
- internally used format. */
-static void
-serpent_key_prepare (const byte *key, unsigned int key_length,
- serpent_key_t key_prepared)
-{
- int i;
-
- /* Copy key. */
- for (i = 0; i < key_length / 4; i++)
- {
-#ifdef WORDS_BIGENDIAN
- key_prepared[i] = byte_swap_32 (((u32 *) key)[i]);
-#else
- key_prepared[i] = ((u32 *) key)[i];
-#endif
- }
-
- if (i < 8)
- {
- /* Key must be padded according to the Serpent
- specification. */
- key_prepared[i] = 0x00000001;
-
- for (i++; i < 8; i++)
- key_prepared[i] = 0;
- }
-}
-
-/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */
-static void
-serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
-{
- u32 w_real[140]; /* The `prekey'. */
- u32 k[132];
- u32 *w = &w_real[8];
- int i, j;
-
- /* Initialize with key values. */
- for (i = 0; i < 8; i++)
- w[i - 8] = key[i];
-
- /* Expand to intermediate key using the affine recurrence. */
- for (i = 0; i < 132; i++)
- w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
-
- /* Calculate subkeys via S-Boxes, in bitslice mode. */
- SBOX (3, w, k, 0);
- SBOX (2, w, k, 4);
- SBOX (1, w, k, 8);
- SBOX (0, w, k, 12);
- SBOX (7, w, k, 16);
- SBOX (6, w, k, 20);
- SBOX (5, w, k, 24);
- SBOX (4, w, k, 28);
- SBOX (3, w, k, 32);
- SBOX (2, w, k, 36);
- SBOX (1, w, k, 40);
- SBOX (0, w, k, 44);
- SBOX (7, w, k, 48);
- SBOX (6, w, k, 52);
- SBOX (5, w, k, 56);
- SBOX (4, w, k, 60);
- SBOX (3, w, k, 64);
- SBOX (2, w, k, 68);
- SBOX (1, w, k, 72);
- SBOX (0, w, k, 76);
- SBOX (7, w, k, 80);
- SBOX (6, w, k, 84);
- SBOX (5, w, k, 88);
- SBOX (4, w, k, 92);
- SBOX (3, w, k, 96);
- SBOX (2, w, k, 100);
- SBOX (1, w, k, 104);
- SBOX (0, w, k, 108);
- SBOX (7, w, k, 112);
- SBOX (6, w, k, 116);
- SBOX (5, w, k, 120);
- SBOX (4, w, k, 124);
- SBOX (3, w, k, 128);
-
- /* Renumber subkeys. */
- for (i = 0; i < ROUNDS + 1; i++)
- for (j = 0; j < 4; j++)
- subkeys[i][j] = k[4 * i + j];
-}
-
-/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
-static void
-serpent_setkey_internal (serpent_context_t *context,
- const byte *key, unsigned int key_length)
-{
- serpent_key_t key_prepared;
-
- serpent_key_prepare (key, key_length, key_prepared);
- serpent_subkeys_generate (key_prepared, context->keys);
- _gcry_burn_stack (272 * sizeof (u32));
-}
-
-/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */
-static gcry_err_code_t
-serpent_setkey (void *ctx,
- const byte *key, unsigned int key_length)
-{
- serpent_context_t *context = ctx;
- static const char *serpent_test_ret;
- static int serpent_init_done;
- gcry_err_code_t ret = GPG_ERR_NO_ERROR;
-
- if (! serpent_init_done)
- {
- /* Execute a self-test the first time, Serpent is used. */
- serpent_test_ret = serpent_test ();
- if (serpent_test_ret)
- log_error ("Serpent test failure: %s\n", serpent_test_ret);
- serpent_init_done = 1;
- }
-
- if (serpent_test_ret)
- ret = GPG_ERR_SELFTEST_FAILED;
- else
- {
- serpent_setkey_internal (context, key, key_length);
- _gcry_burn_stack (sizeof (serpent_key_t));
- }
-
- return ret;
-}
-
-static void
-serpent_encrypt_internal (serpent_context_t *context,
- const serpent_block_t input, serpent_block_t output)
-{
- serpent_block_t b, b_next;
- int round = 0;
-
-#ifdef WORDS_BIGENDIAN
- b[0] = byte_swap_32 (input[0]);
- b[1] = byte_swap_32 (input[1]);
- b[2] = byte_swap_32 (input[2]);
- b[3] = byte_swap_32 (input[3]);
-#else
- b[0] = input[0];
- b[1] = input[1];
- b[2] = input[2];
- b[3] = input[3];
-#endif
-
- ROUND (0, context->keys, b, b_next);
- ROUND (1, context->keys, b, b_next);
- ROUND (2, context->keys, b, b_next);
- ROUND (3, context->keys, b, b_next);
- ROUND (4, context->keys, b, b_next);
- ROUND (5, context->keys, b, b_next);
- ROUND (6, context->keys, b, b_next);
- ROUND (7, context->keys, b, b_next);
- ROUND (0, context->keys, b, b_next);
- ROUND (1, context->keys, b, b_next);
- ROUND (2, context->keys, b, b_next);
- ROUND (3, context->keys, b, b_next);
- ROUND (4, context->keys, b, b_next);
- ROUND (5, context->keys, b, b_next);
- ROUND (6, context->keys, b, b_next);
- ROUND (7, context->keys, b, b_next);
- ROUND (0, context->keys, b, b_next);
- ROUND (1, context->keys, b, b_next);
- ROUND (2, context->keys, b, b_next);
- ROUND (3, context->keys, b, b_next);
- ROUND (4, context->keys, b, b_next);
- ROUND (5, context->keys, b, b_next);
- ROUND (6, context->keys, b, b_next);
- ROUND (7, context->keys, b, b_next);
- ROUND (0, context->keys, b, b_next);
- ROUND (1, context->keys, b, b_next);
- ROUND (2, context->keys, b, b_next);
- ROUND (3, context->keys, b, b_next);
- ROUND (4, context->keys, b, b_next);
- ROUND (5, context->keys, b, b_next);
- ROUND (6, context->keys, b, b_next);
-
- ROUND_LAST (7, context->keys, b, b_next);
-
-#ifdef WORDS_BIGENDIAN
- output[0] = byte_swap_32 (b_next[0]);
- output[1] = byte_swap_32 (b_next[1]);
- output[2] = byte_swap_32 (b_next[2]);
- output[3] = byte_swap_32 (b_next[3]);
-#else
- output[0] = b_next[0];
- output[1] = b_next[1];
- output[2] = b_next[2];
- output[3] = b_next[3];
-#endif
-}
-
-static void
-serpent_decrypt_internal (serpent_context_t *context,
- const serpent_block_t input, serpent_block_t output)
-{
- serpent_block_t b, b_next;
- int round = ROUNDS;
-
-#ifdef WORDS_BIGENDIAN
- b_next[0] = byte_swap_32 (input[0]);
- b_next[1] = byte_swap_32 (input[1]);
- b_next[2] = byte_swap_32 (input[2]);
- b_next[3] = byte_swap_32 (input[3]);
-#else
- b_next[0] = input[0];
- b_next[1] = input[1];
- b_next[2] = input[2];
- b_next[3] = input[3];
-#endif
-
- ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
-
- ROUND_INVERSE (6, context->keys, b, b_next);
- ROUND_INVERSE (5, context->keys, b, b_next);
- ROUND_INVERSE (4, context->keys, b, b_next);
- ROUND_INVERSE (3, context->keys, b, b_next);
- ROUND_INVERSE (2, context->keys, b, b_next);
- ROUND_INVERSE (1, context->keys, b, b_next);
- ROUND_INVERSE (0, context->keys, b, b_next);
- ROUND_INVERSE (7, context->keys, b, b_next);
- ROUND_INVERSE (6, context->keys, b, b_next);
- ROUND_INVERSE (5, context->keys, b, b_next);
- ROUND_INVERSE (4, context->keys, b, b_next);
- ROUND_INVERSE (3, context->keys, b, b_next);
- ROUND_INVERSE (2, context->keys, b, b_next);
- ROUND_INVERSE (1, context->keys, b, b_next);
- ROUND_INVERSE (0, context->keys, b, b_next);
- ROUND_INVERSE (7, context->keys, b, b_next);
- ROUND_INVERSE (6, context->keys, b, b_next);
- ROUND_INVERSE (5, context->keys, b, b_next);
- ROUND_INVERSE (4, context->keys, b, b_next);
- ROUND_INVERSE (3, context->keys, b, b_next);
- ROUND_INVERSE (2, context->keys, b, b_next);
- ROUND_INVERSE (1, context->keys, b, b_next);
- ROUND_INVERSE (0, context->keys, b, b_next);
- ROUND_INVERSE (7, context->keys, b, b_next);
- ROUND_INVERSE (6, context->keys, b, b_next);
- ROUND_INVERSE (5, context->keys, b, b_next);
- ROUND_INVERSE (4, context->keys, b, b_next);
- ROUND_INVERSE (3, context->keys, b, b_next);
- ROUND_INVERSE (2, context->keys, b, b_next);
- ROUND_INVERSE (1, context->keys, b, b_next);
- ROUND_INVERSE (0, context->keys, b, b_next);
-
-
-#ifdef WORDS_BIGENDIAN
- output[0] = byte_swap_32 (b_next[0]);
- output[1] = byte_swap_32 (b_next[1]);
- output[2] = byte_swap_32 (b_next[2]);
- output[3] = byte_swap_32 (b_next[3]);
-#else
- output[0] = b_next[0];
- output[1] = b_next[1];
- output[2] = b_next[2];
- output[3] = b_next[3];
-#endif
-}
-
-static void
-serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
-{
- serpent_context_t *context = ctx;
-
- serpent_encrypt_internal (context,
- (const u32 *) buffer_in, (u32 *) buffer_out);
- _gcry_burn_stack (2 * sizeof (serpent_block_t));
-}
-
-static void
-serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
-{
- serpent_context_t *context = ctx;
-
- serpent_decrypt_internal (context,
- (const u32 *) buffer_in,
- (u32 *) buffer_out);
- _gcry_burn_stack (2 * sizeof (serpent_block_t));
-}
-
-
-
-/* Serpent test. */
-
-static const char *
-serpent_test (void)
-{
- serpent_context_t context;
- unsigned char scratch[16];
- unsigned int i;
-
- static struct test
- {
- int key_length;
- unsigned char key[32];
- unsigned char text_plain[16];
- unsigned char text_cipher[16];
- } test_data[] =
- {
- {
- 16,
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
- "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E",
- "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D"
- },
- {
- 24,
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00",
- "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E",
- "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9"
- },
- {
- 32,
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
- "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E",
- "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B"
- },
- {
- 32,
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
- "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
- "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C"
- },
- {
- 0
- },
- };
-
- for (i = 0; test_data[i].key_length; i++)
- {
- serpent_setkey_internal (&context, test_data[i].key,
- test_data[i].key_length);
- serpent_encrypt_internal (&context,
- (const u32 *) test_data[i].text_plain,
- (u32 *) scratch);
-
- if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
- switch (test_data[i].key_length)
- {
- case 16:
- return "Serpent-128 test encryption failed.";
- case 24:
- return "Serpent-192 test encryption failed.";
- case 32:
- return "Serpent-256 test encryption failed.";
- }
-
- serpent_decrypt_internal (&context,
- (const u32 *) test_data[i].text_cipher,
- (u32 *) scratch);
- if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
- switch (test_data[i].key_length)
- {
- case 16:
- return "Serpent-128 test decryption failed.";
- case 24:
- return "Serpent-192 test decryption failed.";
- case 32:
- return "Serpent-256 test decryption failed.";
- }
- }
-
- return NULL;
-}
-
-
-
-/* "SERPENT" is an alias for "SERPENT128". */
-static const char *cipher_spec_serpent128_aliases[] =
- {
- "SERPENT",
- NULL
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
- {
- "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128,
- sizeof (serpent_context_t),
- serpent_setkey, serpent_encrypt, serpent_decrypt
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
- {
- "SERPENT192", NULL, NULL, 16, 192,
- sizeof (serpent_context_t),
- serpent_setkey, serpent_encrypt, serpent_decrypt
- };
-
-gcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
- {
- "SERPENT256", NULL, NULL, 16, 256,
- sizeof (serpent_context_t),
- serpent_setkey, serpent_encrypt, serpent_decrypt
- };
+/* serpent.c - Implementation of the Serpent encryption algorithm.
+ * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "cipher.h"
+#include "bithelp.h"
+
+/* Number of rounds per Serpent encrypt/decrypt operation. */
+#define ROUNDS 32
+
+/* Magic number, used during generating of the subkeys. */
+#define PHI 0x9E3779B9
+
+/* Serpent works on 128 bit blocks. */
+typedef u32 serpent_block_t[4];
+
+/* Serpent key, provided by the user. If the original key is shorter
+ than 256 bits, it is padded. */
+typedef u32 serpent_key_t[8];
+
+/* The key schedule consists of 33 128 bit subkeys. */
+typedef u32 serpent_subkeys_t[ROUNDS + 1][4];
+
+/* A Serpent context. */
+typedef struct serpent_context
+{
+ serpent_subkeys_t keys; /* Generated subkeys. */
+} serpent_context_t;
+
+
+/* A prototype. */
+static const char *serpent_test (void);
+
+
+#define byte_swap_32(x) \
+ (0 \
+ | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
+ | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+/* These are the S-Boxes of Serpent. They are copied from Serpents
+ reference implementation (the optimized one, contained in
+ `floppy2') and are therefore:
+
+ Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
+
+ To quote the Serpent homepage
+ (http://www.cl.cam.ac.uk/~rja14/serpent.html):
+
+ "Serpent is now completely in the public domain, and we impose no
+ restrictions on its use. This was announced on the 21st August at
+ the First AES Candidate Conference. The optimised implementations
+ in the submission package are now under the GNU PUBLIC LICENSE
+ (GPL), although some comments in the code still say otherwise. You
+ are welcome to use Serpent for any application." */
+
+#define SBOX0(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t05, t06, t07, t08, t09; \
+ u32 t11, t12, t13, t14, t15, t17, t01; \
+ t01 = b ^ c ; \
+ t02 = a | d ; \
+ t03 = a ^ b ; \
+ z = t02 ^ t01; \
+ t05 = c | z ; \
+ t06 = a ^ d ; \
+ t07 = b | c ; \
+ t08 = d & t05; \
+ t09 = t03 & t07; \
+ y = t09 ^ t08; \
+ t11 = t09 & y ; \
+ t12 = c ^ d ; \
+ t13 = t07 ^ t11; \
+ t14 = b & t06; \
+ t15 = t06 ^ t13; \
+ w = ~ t15; \
+ t17 = w ^ t14; \
+ x = t12 ^ t17; \
+ }
+
+#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t08, t09, t10; \
+ u32 t12, t13, t14, t15, t17, t18, t01; \
+ t01 = c ^ d ; \
+ t02 = a | b ; \
+ t03 = b | c ; \
+ t04 = c & t01; \
+ t05 = t02 ^ t01; \
+ t06 = a | t04; \
+ y = ~ t05; \
+ t08 = b ^ d ; \
+ t09 = t03 & t08; \
+ t10 = d | y ; \
+ x = t09 ^ t06; \
+ t12 = a | t05; \
+ t13 = x ^ t12; \
+ t14 = t03 ^ t10; \
+ t15 = a ^ c ; \
+ z = t14 ^ t13; \
+ t17 = t05 & t13; \
+ t18 = t14 | t17; \
+ w = t15 ^ t18; \
+ }
+
+#define SBOX1(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t08; \
+ u32 t10, t11, t12, t13, t16, t17, t01; \
+ t01 = a | d ; \
+ t02 = c ^ d ; \
+ t03 = ~ b ; \
+ t04 = a ^ c ; \
+ t05 = a | t03; \
+ t06 = d & t04; \
+ t07 = t01 & t02; \
+ t08 = b | t06; \
+ y = t02 ^ t05; \
+ t10 = t07 ^ t08; \
+ t11 = t01 ^ t10; \
+ t12 = y ^ t11; \
+ t13 = b & d ; \
+ z = ~ t10; \
+ x = t13 ^ t12; \
+ t16 = t10 | x ; \
+ t17 = t05 & t16; \
+ w = c ^ t17; \
+ }
+
+#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t08; \
+ u32 t09, t10, t11, t14, t15, t17, t01; \
+ t01 = a ^ b ; \
+ t02 = b | d ; \
+ t03 = a & c ; \
+ t04 = c ^ t02; \
+ t05 = a | t04; \
+ t06 = t01 & t05; \
+ t07 = d | t03; \
+ t08 = b ^ t06; \
+ t09 = t07 ^ t06; \
+ t10 = t04 | t03; \
+ t11 = d & t08; \
+ y = ~ t09; \
+ x = t10 ^ t11; \
+ t14 = a | y ; \
+ t15 = t06 ^ x ; \
+ z = t01 ^ t04; \
+ t17 = c ^ t15; \
+ w = t14 ^ t17; \
+ }
+
+#define SBOX2(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t05, t06, t07, t08; \
+ u32 t09, t10, t12, t13, t14, t01; \
+ t01 = a | c ; \
+ t02 = a ^ b ; \
+ t03 = d ^ t01; \
+ w = t02 ^ t03; \
+ t05 = c ^ w ; \
+ t06 = b ^ t05; \
+ t07 = b | t05; \
+ t08 = t01 & t06; \
+ t09 = t03 ^ t07; \
+ t10 = t02 | t09; \
+ x = t10 ^ t08; \
+ t12 = a | d ; \
+ t13 = t09 ^ x ; \
+ t14 = b ^ t13; \
+ z = ~ t09; \
+ y = t12 ^ t14; \
+ }
+
+#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t06, t07, t08, t09; \
+ u32 t10, t11, t12, t15, t16, t17, t01; \
+ t01 = a ^ d ; \
+ t02 = c ^ d ; \
+ t03 = a & c ; \
+ t04 = b | t02; \
+ w = t01 ^ t04; \
+ t06 = a | c ; \
+ t07 = d | w ; \
+ t08 = ~ d ; \
+ t09 = b & t06; \
+ t10 = t08 | t03; \
+ t11 = b & t07; \
+ t12 = t06 & t02; \
+ z = t09 ^ t10; \
+ x = t12 ^ t11; \
+ t15 = c & z ; \
+ t16 = w ^ x ; \
+ t17 = t10 ^ t15; \
+ y = t16 ^ t17; \
+ }
+
+#define SBOX3(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t08; \
+ u32 t09, t10, t11, t13, t14, t15, t01; \
+ t01 = a ^ c ; \
+ t02 = a | d ; \
+ t03 = a & d ; \
+ t04 = t01 & t02; \
+ t05 = b | t03; \
+ t06 = a & b ; \
+ t07 = d ^ t04; \
+ t08 = c | t06; \
+ t09 = b ^ t07; \
+ t10 = d & t05; \
+ t11 = t02 ^ t10; \
+ z = t08 ^ t09; \
+ t13 = d | z ; \
+ t14 = a | t07; \
+ t15 = b & t13; \
+ y = t08 ^ t11; \
+ w = t14 ^ t15; \
+ x = t05 ^ t04; \
+ }
+
+#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t09; \
+ u32 t11, t12, t13, t14, t16, t01; \
+ t01 = c | d ; \
+ t02 = a | d ; \
+ t03 = c ^ t02; \
+ t04 = b ^ t02; \
+ t05 = a ^ d ; \
+ t06 = t04 & t03; \
+ t07 = b & t01; \
+ y = t05 ^ t06; \
+ t09 = a ^ t03; \
+ w = t07 ^ t03; \
+ t11 = w | t05; \
+ t12 = t09 & t11; \
+ t13 = a & y ; \
+ t14 = t01 ^ t05; \
+ x = b ^ t12; \
+ t16 = b | t13; \
+ z = t14 ^ t16; \
+ }
+
+#define SBOX4(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t08, t09; \
+ u32 t10, t11, t12, t13, t14, t15, t16, t01; \
+ t01 = a | b ; \
+ t02 = b | c ; \
+ t03 = a ^ t02; \
+ t04 = b ^ d ; \
+ t05 = d | t03; \
+ t06 = d & t01; \
+ z = t03 ^ t06; \
+ t08 = z & t04; \
+ t09 = t04 & t05; \
+ t10 = c ^ t06; \
+ t11 = b & c ; \
+ t12 = t04 ^ t08; \
+ t13 = t11 | t03; \
+ t14 = t10 ^ t09; \
+ t15 = a & t05; \
+ t16 = t11 | t12; \
+ y = t13 ^ t08; \
+ x = t15 ^ t16; \
+ w = ~ t14; \
+ }
+
+#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t09; \
+ u32 t10, t11, t12, t13, t15, t01; \
+ t01 = b | d ; \
+ t02 = c | d ; \
+ t03 = a & t01; \
+ t04 = b ^ t02; \
+ t05 = c ^ d ; \
+ t06 = ~ t03; \
+ t07 = a & t04; \
+ x = t05 ^ t07; \
+ t09 = x | t06; \
+ t10 = a ^ t07; \
+ t11 = t01 ^ t09; \
+ t12 = d ^ t04; \
+ t13 = c | t10; \
+ z = t03 ^ t12; \
+ t15 = a ^ t04; \
+ y = t11 ^ t13; \
+ w = t15 ^ t09; \
+ }
+
+#define SBOX5(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t07, t08, t09; \
+ u32 t10, t11, t12, t13, t14, t01; \
+ t01 = b ^ d ; \
+ t02 = b | d ; \
+ t03 = a & t01; \
+ t04 = c ^ t02; \
+ t05 = t03 ^ t04; \
+ w = ~ t05; \
+ t07 = a ^ t01; \
+ t08 = d | w ; \
+ t09 = b | t05; \
+ t10 = d ^ t08; \
+ t11 = b | t07; \
+ t12 = t03 | w ; \
+ t13 = t07 | t10; \
+ t14 = t01 ^ t11; \
+ y = t09 ^ t13; \
+ x = t07 ^ t08; \
+ z = t12 ^ t14; \
+ }
+
+#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t07, t08, t09; \
+ u32 t10, t12, t13, t15, t16, t01; \
+ t01 = a & d ; \
+ t02 = c ^ t01; \
+ t03 = a ^ d ; \
+ t04 = b & t02; \
+ t05 = a & c ; \
+ w = t03 ^ t04; \
+ t07 = a & w ; \
+ t08 = t01 ^ w ; \
+ t09 = b | t05; \
+ t10 = ~ b ; \
+ x = t08 ^ t09; \
+ t12 = t10 | t07; \
+ t13 = w | x ; \
+ z = t02 ^ t12; \
+ t15 = t02 ^ t13; \
+ t16 = b ^ d ; \
+ y = t16 ^ t15; \
+ }
+
+#define SBOX6(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t07, t08, t09, t10; \
+ u32 t11, t12, t13, t15, t17, t18, t01; \
+ t01 = a & d ; \
+ t02 = b ^ c ; \
+ t03 = a ^ d ; \
+ t04 = t01 ^ t02; \
+ t05 = b | c ; \
+ x = ~ t04; \
+ t07 = t03 & t05; \
+ t08 = b & x ; \
+ t09 = a | c ; \
+ t10 = t07 ^ t08; \
+ t11 = b | d ; \
+ t12 = c ^ t11; \
+ t13 = t09 ^ t10; \
+ y = ~ t13; \
+ t15 = x & t03; \
+ z = t12 ^ t07; \
+ t17 = a ^ b ; \
+ t18 = y ^ t15; \
+ w = t17 ^ t18; \
+ }
+
+#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t07, t08, t09; \
+ u32 t12, t13, t14, t15, t16, t17, t01; \
+ t01 = a ^ c ; \
+ t02 = ~ c ; \
+ t03 = b & t01; \
+ t04 = b | t02; \
+ t05 = d | t03; \
+ t06 = b ^ d ; \
+ t07 = a & t04; \
+ t08 = a | t02; \
+ t09 = t07 ^ t05; \
+ x = t06 ^ t08; \
+ w = ~ t09; \
+ t12 = b & w ; \
+ t13 = t01 & t05; \
+ t14 = t01 ^ t12; \
+ t15 = t07 ^ t13; \
+ t16 = d | t02; \
+ t17 = a ^ x ; \
+ z = t17 ^ t15; \
+ y = t16 ^ t14; \
+ }
+
+#define SBOX7(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t05, t06, t08, t09, t10; \
+ u32 t11, t13, t14, t15, t16, t17, t01; \
+ t01 = a & c ; \
+ t02 = ~ d ; \
+ t03 = a & t02; \
+ t04 = b | t01; \
+ t05 = a & b ; \
+ t06 = c ^ t04; \
+ z = t03 ^ t06; \
+ t08 = c | z ; \
+ t09 = d | t05; \
+ t10 = a ^ t08; \
+ t11 = t04 & z ; \
+ x = t09 ^ t10; \
+ t13 = b ^ x ; \
+ t14 = t01 ^ x ; \
+ t15 = c ^ t05; \
+ t16 = t11 | t13; \
+ t17 = t02 | t14; \
+ w = t15 ^ t17; \
+ y = a ^ t16; \
+ }
+
+#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \
+ { \
+ u32 t02, t03, t04, t06, t07, t08, t09; \
+ u32 t10, t11, t13, t14, t15, t16, t01; \
+ t01 = a & b ; \
+ t02 = a | b ; \
+ t03 = c | t01; \
+ t04 = d & t02; \
+ z = t03 ^ t04; \
+ t06 = b ^ t04; \
+ t07 = d ^ z ; \
+ t08 = ~ t07; \
+ t09 = t06 | t08; \
+ t10 = b ^ d ; \
+ t11 = a | d ; \
+ x = a ^ t09; \
+ t13 = c ^ t06; \
+ t14 = c & t11; \
+ t15 = d | x ; \
+ t16 = t01 | t10; \
+ w = t13 ^ t15; \
+ y = t14 ^ t16; \
+ }
+
+/* XOR BLOCK1 into BLOCK0. */
+#define BLOCK_XOR(block0, block1) \
+ { \
+ block0[0] ^= block1[0]; \
+ block0[1] ^= block1[1]; \
+ block0[2] ^= block1[2]; \
+ block0[3] ^= block1[3]; \
+ }
+
+/* Copy BLOCK_SRC to BLOCK_DST. */
+#define BLOCK_COPY(block_dst, block_src) \
+ { \
+ block_dst[0] = block_src[0]; \
+ block_dst[1] = block_src[1]; \
+ block_dst[2] = block_src[2]; \
+ block_dst[3] = block_src[3]; \
+ }
+
+/* Apply SBOX number WHICH to to the block found in ARRAY0 at index
+ INDEX, writing the output to the block found in ARRAY1 at index
+ INDEX. */
+#define SBOX(which, array0, array1, index) \
+ SBOX##which (array0[index + 0], array0[index + 1], \
+ array0[index + 2], array0[index + 3], \
+ array1[index + 0], array1[index + 1], \
+ array1[index + 2], array1[index + 3]);
+
+/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at
+ index INDEX, writing the output to the block found in ARRAY1 at
+ index INDEX. */
+#define SBOX_INVERSE(which, array0, array1, index) \
+ SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \
+ array0[index + 2], array0[index + 3], \
+ array1[index + 0], array1[index + 1], \
+ array1[index + 2], array1[index + 3]);
+
+/* Apply the linear transformation to BLOCK. */
+#define LINEAR_TRANSFORMATION(block) \
+ { \
+ block[0] = rol (block[0], 13); \
+ block[2] = rol (block[2], 3); \
+ block[1] = block[1] ^ block[0] ^ block[2]; \
+ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
+ block[1] = rol (block[1], 1); \
+ block[3] = rol (block[3], 7); \
+ block[0] = block[0] ^ block[1] ^ block[3]; \
+ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
+ block[0] = rol (block[0], 5); \
+ block[2] = rol (block[2], 22); \
+ }
+
+/* Apply the inverse linear transformation to BLOCK. */
+#define LINEAR_TRANSFORMATION_INVERSE(block) \
+ { \
+ block[2] = ror (block[2], 22); \
+ block[0] = ror (block[0] , 5); \
+ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
+ block[0] = block[0] ^ block[1] ^ block[3]; \
+ block[3] = ror (block[3], 7); \
+ block[1] = ror (block[1], 1); \
+ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
+ block[1] = block[1] ^ block[0] ^ block[2]; \
+ block[2] = ror (block[2], 3); \
+ block[0] = ror (block[0], 13); \
+ }
+
+/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
+ subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage.
+ This macro increments `round'. */
+#define ROUND(which, subkeys, block, block_tmp) \
+ { \
+ BLOCK_XOR (block, subkeys[round]); \
+ round++; \
+ SBOX (which, block, block_tmp, 0); \
+ LINEAR_TRANSFORMATION (block_tmp); \
+ BLOCK_COPY (block, block_tmp); \
+ }
+
+/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
+ and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
+ storage. The result will be stored in BLOCK_TMP. This macro
+ increments `round'. */
+#define ROUND_LAST(which, subkeys, block, block_tmp) \
+ { \
+ BLOCK_XOR (block, subkeys[round]); \
+ round++; \
+ SBOX (which, block, block_tmp, 0); \
+ BLOCK_XOR (block_tmp, subkeys[round]); \
+ round++; \
+ }
+
+/* Apply an inverse Serpent round to BLOCK, using the SBOX number
+ WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as
+ temporary storage. This macro increments `round'. */
+#define ROUND_INVERSE(which, subkey, block, block_tmp) \
+ { \
+ LINEAR_TRANSFORMATION_INVERSE (block); \
+ SBOX_INVERSE (which, block, block_tmp, 0); \
+ BLOCK_XOR (block_tmp, subkey[round]); \
+ round--; \
+ BLOCK_COPY (block, block_tmp); \
+ }
+
+/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
+ and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
+ storage. The result will be stored in BLOCK_TMP. This macro
+ increments `round'. */
+#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
+ { \
+ BLOCK_XOR (block, subkeys[round]); \
+ round--; \
+ SBOX_INVERSE (which, block, block_tmp, 0); \
+ BLOCK_XOR (block_tmp, subkeys[round]); \
+ round--; \
+ }
+
+/* Convert the user provided key KEY of KEY_LENGTH bytes into the
+ internally used format. */
+static void
+serpent_key_prepare (const byte *key, unsigned int key_length,
+ serpent_key_t key_prepared)
+{
+ int i;
+
+ /* Copy key. */
+ for (i = 0; i < key_length / 4; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ key_prepared[i] = byte_swap_32 (((u32 *) key)[i]);
+#else
+ key_prepared[i] = ((u32 *) key)[i];
+#endif
+ }
+
+ if (i < 8)
+ {
+ /* Key must be padded according to the Serpent
+ specification. */
+ key_prepared[i] = 0x00000001;
+
+ for (i++; i < 8; i++)
+ key_prepared[i] = 0;
+ }
+}
+
+/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */
+static void
+serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
+{
+ u32 w_real[140]; /* The `prekey'. */
+ u32 k[132];
+ u32 *w = &w_real[8];
+ int i, j;
+
+ /* Initialize with key values. */
+ for (i = 0; i < 8; i++)
+ w[i - 8] = key[i];
+
+ /* Expand to intermediate key using the affine recurrence. */
+ for (i = 0; i < 132; i++)
+ w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
+
+ /* Calculate subkeys via S-Boxes, in bitslice mode. */
+ SBOX (3, w, k, 0);
+ SBOX (2, w, k, 4);
+ SBOX (1, w, k, 8);
+ SBOX (0, w, k, 12);
+ SBOX (7, w, k, 16);
+ SBOX (6, w, k, 20);
+ SBOX (5, w, k, 24);
+ SBOX (4, w, k, 28);
+ SBOX (3, w, k, 32);
+ SBOX (2, w, k, 36);
+ SBOX (1, w, k, 40);
+ SBOX (0, w, k, 44);
+ SBOX (7, w, k, 48);
+ SBOX (6, w, k, 52);
+ SBOX (5, w, k, 56);
+ SBOX (4, w, k, 60);
+ SBOX (3, w, k, 64);
+ SBOX (2, w, k, 68);
+ SBOX (1, w, k, 72);
+ SBOX (0, w, k, 76);
+ SBOX (7, w, k, 80);
+ SBOX (6, w, k, 84);
+ SBOX (5, w, k, 88);
+ SBOX (4, w, k, 92);
+ SBOX (3, w, k, 96);
+ SBOX (2, w, k, 100);
+ SBOX (1, w, k, 104);
+ SBOX (0, w, k, 108);
+ SBOX (7, w, k, 112);
+ SBOX (6, w, k, 116);
+ SBOX (5, w, k, 120);
+ SBOX (4, w, k, 124);
+ SBOX (3, w, k, 128);
+
+ /* Renumber subkeys. */
+ for (i = 0; i < ROUNDS + 1; i++)
+ for (j = 0; j < 4; j++)
+ subkeys[i][j] = k[4 * i + j];
+}
+
+/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
+static void
+serpent_setkey_internal (serpent_context_t *context,
+ const byte *key, unsigned int key_length)
+{
+ serpent_key_t key_prepared;
+
+ serpent_key_prepare (key, key_length, key_prepared);
+ serpent_subkeys_generate (key_prepared, context->keys);
+ _gcry_burn_stack (272 * sizeof (u32));
+}
+
+/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */
+static gcry_err_code_t
+serpent_setkey (void *ctx,
+ const byte *key, unsigned int key_length)
+{
+ serpent_context_t *context = ctx;
+ static const char *serpent_test_ret;
+ static int serpent_init_done;
+ gcry_err_code_t ret = GPG_ERR_NO_ERROR;
+
+ if (! serpent_init_done)
+ {
+ /* Execute a self-test the first time, Serpent is used. */
+ serpent_test_ret = serpent_test ();
+ if (serpent_test_ret)
+ log_error ("Serpent test failure: %s\n", serpent_test_ret);
+ serpent_init_done = 1;
+ }
+
+ if (serpent_test_ret)
+ ret = GPG_ERR_SELFTEST_FAILED;
+ else
+ {
+ serpent_setkey_internal (context, key, key_length);
+ _gcry_burn_stack (sizeof (serpent_key_t));
+ }
+
+ return ret;
+}
+
+static void
+serpent_encrypt_internal (serpent_context_t *context,
+ const serpent_block_t input, serpent_block_t output)
+{
+ serpent_block_t b, b_next;
+ int round = 0;
+
+#ifdef WORDS_BIGENDIAN
+ b[0] = byte_swap_32 (input[0]);
+ b[1] = byte_swap_32 (input[1]);
+ b[2] = byte_swap_32 (input[2]);
+ b[3] = byte_swap_32 (input[3]);
+#else
+ b[0] = input[0];
+ b[1] = input[1];
+ b[2] = input[2];
+ b[3] = input[3];
+#endif
+
+ ROUND (0, context->keys, b, b_next);
+ ROUND (1, context->keys, b, b_next);
+ ROUND (2, context->keys, b, b_next);
+ ROUND (3, context->keys, b, b_next);
+ ROUND (4, context->keys, b, b_next);
+ ROUND (5, context->keys, b, b_next);
+ ROUND (6, context->keys, b, b_next);
+ ROUND (7, context->keys, b, b_next);
+ ROUND (0, context->keys, b, b_next);
+ ROUND (1, context->keys, b, b_next);
+ ROUND (2, context->keys, b, b_next);
+ ROUND (3, context->keys, b, b_next);
+ ROUND (4, context->keys, b, b_next);
+ ROUND (5, context->keys, b, b_next);
+ ROUND (6, context->keys, b, b_next);
+ ROUND (7, context->keys, b, b_next);
+ ROUND (0, context->keys, b, b_next);
+ ROUND (1, context->keys, b, b_next);
+ ROUND (2, context->keys, b, b_next);
+ ROUND (3, context->keys, b, b_next);
+ ROUND (4, context->keys, b, b_next);
+ ROUND (5, context->keys, b, b_next);
+ ROUND (6, context->keys, b, b_next);
+ ROUND (7, context->keys, b, b_next);
+ ROUND (0, context->keys, b, b_next);
+ ROUND (1, context->keys, b, b_next);
+ ROUND (2, context->keys, b, b_next);
+ ROUND (3, context->keys, b, b_next);
+ ROUND (4, context->keys, b, b_next);
+ ROUND (5, context->keys, b, b_next);
+ ROUND (6, context->keys, b, b_next);
+
+ ROUND_LAST (7, context->keys, b, b_next);
+
+#ifdef WORDS_BIGENDIAN
+ output[0] = byte_swap_32 (b_next[0]);
+ output[1] = byte_swap_32 (b_next[1]);
+ output[2] = byte_swap_32 (b_next[2]);
+ output[3] = byte_swap_32 (b_next[3]);
+#else
+ output[0] = b_next[0];
+ output[1] = b_next[1];
+ output[2] = b_next[2];
+ output[3] = b_next[3];
+#endif
+}
+
+static void
+serpent_decrypt_internal (serpent_context_t *context,
+ const serpent_block_t input, serpent_block_t output)
+{
+ serpent_block_t b, b_next;
+ int round = ROUNDS;
+
+#ifdef WORDS_BIGENDIAN
+ b_next[0] = byte_swap_32 (input[0]);
+ b_next[1] = byte_swap_32 (input[1]);
+ b_next[2] = byte_swap_32 (input[2]);
+ b_next[3] = byte_swap_32 (input[3]);
+#else
+ b_next[0] = input[0];
+ b_next[1] = input[1];
+ b_next[2] = input[2];
+ b_next[3] = input[3];
+#endif
+
+ ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
+
+ ROUND_INVERSE (6, context->keys, b, b_next);
+ ROUND_INVERSE (5, context->keys, b, b_next);
+ ROUND_INVERSE (4, context->keys, b, b_next);
+ ROUND_INVERSE (3, context->keys, b, b_next);
+ ROUND_INVERSE (2, context->keys, b, b_next);
+ ROUND_INVERSE (1, context->keys, b, b_next);
+ ROUND_INVERSE (0, context->keys, b, b_next);
+ ROUND_INVERSE (7, context->keys, b, b_next);
+ ROUND_INVERSE (6, context->keys, b, b_next);
+ ROUND_INVERSE (5, context->keys, b, b_next);
+ ROUND_INVERSE (4, context->keys, b, b_next);
+ ROUND_INVERSE (3, context->keys, b, b_next);
+ ROUND_INVERSE (2, context->keys, b, b_next);
+ ROUND_INVERSE (1, context->keys, b, b_next);
+ ROUND_INVERSE (0, context->keys, b, b_next);
+ ROUND_INVERSE (7, context->keys, b, b_next);
+ ROUND_INVERSE (6, context->keys, b, b_next);
+ ROUND_INVERSE (5, context->keys, b, b_next);
+ ROUND_INVERSE (4, context->keys, b, b_next);
+ ROUND_INVERSE (3, context->keys, b, b_next);
+ ROUND_INVERSE (2, context->keys, b, b_next);
+ ROUND_INVERSE (1, context->keys, b, b_next);
+ ROUND_INVERSE (0, context->keys, b, b_next);
+ ROUND_INVERSE (7, context->keys, b, b_next);
+ ROUND_INVERSE (6, context->keys, b, b_next);
+ ROUND_INVERSE (5, context->keys, b, b_next);
+ ROUND_INVERSE (4, context->keys, b, b_next);
+ ROUND_INVERSE (3, context->keys, b, b_next);
+ ROUND_INVERSE (2, context->keys, b, b_next);
+ ROUND_INVERSE (1, context->keys, b, b_next);
+ ROUND_INVERSE (0, context->keys, b, b_next);
+
+
+#ifdef WORDS_BIGENDIAN
+ output[0] = byte_swap_32 (b_next[0]);
+ output[1] = byte_swap_32 (b_next[1]);
+ output[2] = byte_swap_32 (b_next[2]);
+ output[3] = byte_swap_32 (b_next[3]);
+#else
+ output[0] = b_next[0];
+ output[1] = b_next[1];
+ output[2] = b_next[2];
+ output[3] = b_next[3];
+#endif
+}
+
+static void
+serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
+{
+ serpent_context_t *context = ctx;
+
+ serpent_encrypt_internal (context,
+ (const u32 *) buffer_in, (u32 *) buffer_out);
+ _gcry_burn_stack (2 * sizeof (serpent_block_t));
+}
+
+static void
+serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
+{
+ serpent_context_t *context = ctx;
+
+ serpent_decrypt_internal (context,
+ (const u32 *) buffer_in,
+ (u32 *) buffer_out);
+ _gcry_burn_stack (2 * sizeof (serpent_block_t));
+}
+
+
+
+/* Serpent test. */
+
+static const char *
+serpent_test (void)
+{
+ serpent_context_t context;
+ unsigned char scratch[16];
+ unsigned int i;
+
+ static struct test
+ {
+ int key_length;
+ unsigned char key[32];
+ unsigned char text_plain[16];
+ unsigned char text_cipher[16];
+ } test_data[] =
+ {
+ {
+ 16,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E",
+ "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D"
+ },
+ {
+ 24,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E",
+ "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9"
+ },
+ {
+ 32,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E",
+ "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B"
+ },
+ {
+ 32,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
+ "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C"
+ },
+ {
+ 0
+ },
+ };
+
+ for (i = 0; test_data[i].key_length; i++)
+ {
+ serpent_setkey_internal (&context, test_data[i].key,
+ test_data[i].key_length);
+ serpent_encrypt_internal (&context,
+ (const u32 *) test_data[i].text_plain,
+ (u32 *) scratch);
+
+ if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
+ switch (test_data[i].key_length)
+ {
+ case 16:
+ return "Serpent-128 test encryption failed.";
+ case 24:
+ return "Serpent-192 test encryption failed.";
+ case 32:
+ return "Serpent-256 test encryption failed.";
+ }
+
+ serpent_decrypt_internal (&context,
+ (const u32 *) test_data[i].text_cipher,
+ (u32 *) scratch);
+ if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
+ switch (test_data[i].key_length)
+ {
+ case 16:
+ return "Serpent-128 test decryption failed.";
+ case 24:
+ return "Serpent-192 test decryption failed.";
+ case 32:
+ return "Serpent-256 test decryption failed.";
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/* "SERPENT" is an alias for "SERPENT128". */
+static const char *cipher_spec_serpent128_aliases[] =
+ {
+ "SERPENT",
+ NULL
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
+ {
+ "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128,
+ sizeof (serpent_context_t),
+ serpent_setkey, serpent_encrypt, serpent_decrypt
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
+ {
+ "SERPENT192", NULL, NULL, 16, 192,
+ sizeof (serpent_context_t),
+ serpent_setkey, serpent_encrypt, serpent_decrypt
+ };
+
+gcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
+ {
+ "SERPENT256", NULL, NULL, 16, 256,
+ sizeof (serpent_context_t),
+ serpent_setkey, serpent_encrypt, serpent_decrypt
+ };
diff --git a/libgcrypt-1.4.6/cipher/sha512.c b/libgcrypt-1.4.6/cipher/sha512.c
index 59c3e65..43878ef 100644
--- a/libgcrypt-1.4.6/cipher/sha512.c
+++ b/libgcrypt-1.4.6/cipher/sha512.c
@@ -1,629 +1,629 @@
-/* sha512.c - SHA384 and SHA512 hash functions
- * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-
-/* Test vectors from FIPS-180-2:
- *
- * "abc"
- * 384:
- * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163
- * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7
- * 512:
- * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A
- * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F
- *
- * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
- * 384:
- * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2
- * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039
- * 512:
- * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018
- * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909
- *
- * "a" x 1000000
- * 384:
- * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852
- * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985
- * 512:
- * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB
- * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B
- */
-
-
-#include <config.h>
-#include <string.h>
-#include "g10lib.h"
-#include "bithelp.h"
-#include "cipher.h"
-#include "hash-common.h"
-
-typedef struct
-{
- u64 h0, h1, h2, h3, h4, h5, h6, h7;
- u64 nblocks;
- byte buf[128];
- int count;
-} SHA512_CONTEXT;
-
-static void
-sha512_init (void *context)
-{
- SHA512_CONTEXT *hd = context;
-
- hd->h0 = U64_C(0x6a09e667f3bcc908);
- hd->h1 = U64_C(0xbb67ae8584caa73b);
- hd->h2 = U64_C(0x3c6ef372fe94f82b);
- hd->h3 = U64_C(0xa54ff53a5f1d36f1);
- hd->h4 = U64_C(0x510e527fade682d1);
- hd->h5 = U64_C(0x9b05688c2b3e6c1f);
- hd->h6 = U64_C(0x1f83d9abfb41bd6b);
- hd->h7 = U64_C(0x5be0cd19137e2179);
-
- hd->nblocks = 0;
- hd->count = 0;
-}
-
-static void
-sha384_init (void *context)
-{
- SHA512_CONTEXT *hd = context;
-
- hd->h0 = U64_C(0xcbbb9d5dc1059ed8);
- hd->h1 = U64_C(0x629a292a367cd507);
- hd->h2 = U64_C(0x9159015a3070dd17);
- hd->h3 = U64_C(0x152fecd8f70e5939);
- hd->h4 = U64_C(0x67332667ffc00b31);
- hd->h5 = U64_C(0x8eb44a8768581511);
- hd->h6 = U64_C(0xdb0c2e0d64f98fa7);
- hd->h7 = U64_C(0x47b5481dbefa4fa4);
-
- hd->nblocks = 0;
- hd->count = 0;
-}
-
-
-static inline u64
-ROTR (u64 x, u64 n)
-{
- return ((x >> n) | (x << (64 - n)));
-}
-
-static inline u64
-Ch (u64 x, u64 y, u64 z)
-{
- return ((x & y) ^ ( ~x & z));
-}
-
-static inline u64
-Maj (u64 x, u64 y, u64 z)
-{
- return ((x & y) ^ (x & z) ^ (y & z));
-}
-
-static inline u64
-Sum0 (u64 x)
-{
- return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39));
-}
-
-static inline u64
-Sum1 (u64 x)
-{
- return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41));
-}
-
-/****************
- * Transform the message W which consists of 16 64-bit-words
- */
-static void
-transform (SHA512_CONTEXT *hd, const unsigned char *data)
-{
- u64 a, b, c, d, e, f, g, h;
- u64 w[80];
- int t;
- static const u64 k[] =
- {
- U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
- U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
- U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
- U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
- U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
- U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
- U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
- U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
- U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
- U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
- U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
- U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
- U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
- U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
- U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
- U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
- U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
- U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
- U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
- U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
- U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
- U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
- U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
- U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
- U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
- U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
- U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
- U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
- U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
- U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
- U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
- U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
- U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
- U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
- U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
- U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
- U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
- U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
- U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
- U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
- };
-
- /* get values from the chaining vars */
- a = hd->h0;
- b = hd->h1;
- c = hd->h2;
- d = hd->h3;
- e = hd->h4;
- f = hd->h5;
- g = hd->h6;
- h = hd->h7;
-
-#ifdef WORDS_BIGENDIAN
- memcpy (w, data, 128);
-#else
- {
- int i;
- byte *p2;
-
- for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8)
- {
- p2[7] = *data++;
- p2[6] = *data++;
- p2[5] = *data++;
- p2[4] = *data++;
- p2[3] = *data++;
- p2[2] = *data++;
- p2[1] = *data++;
- p2[0] = *data++;
- }
- }
-#endif
-
-#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
-#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
-
- for (t = 16; t < 80; t++)
- w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16];
-
-
- for (t = 0; t < 80; )
- {
- u64 t1, t2;
-
- /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e
- with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes
- initialized to 0,1,2,3...255,0,... and 1000 iterations:
-
- Not unrolled with macros: 440ms
- Unrolled with macros: 350ms
- Unrolled with inline: 330ms
- */
-#if 0 /* Not unrolled. */
- t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
- t2 = Sum0 (a) + Maj (a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + t1;
- d = c;
- c = b;
- b = a;
- a = t1 + t2;
- t++;
-#else /* Unrolled to interweave the chain variables. */
- t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
- t2 = Sum0 (a) + Maj (a, b, c);
- d += t1;
- h = t1 + t2;
-
- t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1];
- t2 = Sum0 (h) + Maj (h, a, b);
- c += t1;
- g = t1 + t2;
-
- t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2];
- t2 = Sum0 (g) + Maj (g, h, a);
- b += t1;
- f = t1 + t2;
-
- t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3];
- t2 = Sum0 (f) + Maj (f, g, h);
- a += t1;
- e = t1 + t2;
-
- t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4];
- t2 = Sum0 (e) + Maj (e, f, g);
- h += t1;
- d = t1 + t2;
-
- t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5];
- t2 = Sum0 (d) + Maj (d, e, f);
- g += t1;
- c = t1 + t2;
-
- t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6];
- t2 = Sum0 (c) + Maj (c, d, e);
- f += t1;
- b = t1 + t2;
-
- t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7];
- t2 = Sum0 (b) + Maj (b, c, d);
- e += t1;
- a = t1 + t2;
-
- t += 8;
-#endif
- }
-
- /* Update chaining vars. */
- hd->h0 += a;
- hd->h1 += b;
- hd->h2 += c;
- hd->h3 += d;
- hd->h4 += e;
- hd->h5 += f;
- hd->h6 += g;
- hd->h7 += h;
-}
-
-
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-sha512_write (void *context, const void *inbuf_arg, size_t inlen)
-{
- const unsigned char *inbuf = inbuf_arg;
- SHA512_CONTEXT *hd = context;
-
- if (hd->count == 128)
- { /* flush the buffer */
- transform (hd, hd->buf);
- _gcry_burn_stack (768);
- hd->count = 0;
- hd->nblocks++;
- }
- if (!inbuf)
- return;
- if (hd->count)
- {
- for (; inlen && hd->count < 128; inlen--)
- hd->buf[hd->count++] = *inbuf++;
- sha512_write (context, NULL, 0);
- if (!inlen)
- return;
- }
-
- while (inlen >= 128)
- {
- transform (hd, inbuf);
- hd->count = 0;
- hd->nblocks++;
- inlen -= 128;
- inbuf += 128;
- }
- _gcry_burn_stack (768);
- for (; inlen && hd->count < 128; inlen--)
- hd->buf[hd->count++] = *inbuf++;
-}
-
-
-/* The routine final terminates the computation and
- * returns the digest.
- * The handle is prepared for a new cycle, but adding bytes to the
- * handle will the destroy the returned buffer.
- * Returns: 64 bytes representing the digest. When used for sha384,
- * we take the leftmost 48 of those bytes.
- */
-
-static void
-sha512_final (void *context)
-{
- SHA512_CONTEXT *hd = context;
- u64 t, msb, lsb;
- byte *p;
-
- sha512_write (context, NULL, 0); /* flush */ ;
-
- t = hd->nblocks;
- /* multiply by 128 to make a byte count */
- lsb = t << 7;
- msb = t >> 57;
- /* add the count */
- t = lsb;
- if ((lsb += hd->count) < t)
- msb++;
- /* multiply by 8 to make a bit count */
- t = lsb;
- lsb <<= 3;
- msb <<= 3;
- msb |= t >> 61;
-
- if (hd->count < 112)
- { /* enough room */
- hd->buf[hd->count++] = 0x80; /* pad */
- while (hd->count < 112)
- hd->buf[hd->count++] = 0; /* pad */
- }
- else
- { /* need one extra block */
- hd->buf[hd->count++] = 0x80; /* pad character */
- while (hd->count < 128)
- hd->buf[hd->count++] = 0;
- sha512_write (context, NULL, 0); /* flush */ ;
- memset (hd->buf, 0, 112); /* fill next block with zeroes */
- }
- /* append the 128 bit count */
- hd->buf[112] = msb >> 56;
- hd->buf[113] = msb >> 48;
- hd->buf[114] = msb >> 40;
- hd->buf[115] = msb >> 32;
- hd->buf[116] = msb >> 24;
- hd->buf[117] = msb >> 16;
- hd->buf[118] = msb >> 8;
- hd->buf[119] = msb;
-
- hd->buf[120] = lsb >> 56;
- hd->buf[121] = lsb >> 48;
- hd->buf[122] = lsb >> 40;
- hd->buf[123] = lsb >> 32;
- hd->buf[124] = lsb >> 24;
- hd->buf[125] = lsb >> 16;
- hd->buf[126] = lsb >> 8;
- hd->buf[127] = lsb;
- transform (hd, hd->buf);
- _gcry_burn_stack (768);
-
- p = hd->buf;
-#ifdef WORDS_BIGENDIAN
-#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0)
-#else /* little endian */
-#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \
- *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \
- *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
- *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
-#endif
- X (0);
- X (1);
- X (2);
- X (3);
- X (4);
- X (5);
- /* Note that these last two chunks are included even for SHA384.
- We just ignore them. */
- X (6);
- X (7);
-#undef X
-}
-
-static byte *
-sha512_read (void *context)
-{
- SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context;
- return hd->buf;
-}
-
-
-
-/*
- Self-test section.
- */
-
-
-static gpg_err_code_t
-selftests_sha384 (int extended, selftest_report_func_t report)
-{
- const char *what;
- const char *errtxt;
-
- what = "short string";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA384, 0,
- "abc", 3,
- "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
- "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
- "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48);
- if (errtxt)
- goto failed;
-
- if (extended)
- {
- what = "long string";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA384, 0,
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
- "\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47"
- "\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12"
- "\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39",
- 48);
- if (errtxt)
- goto failed;
-
- what = "one million \"a\"";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA384, 1,
- NULL, 0,
- "\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C"
- "\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B"
- "\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85",
- 48);
- if (errtxt)
- goto failed;
- }
-
- return 0; /* Succeeded. */
-
- failed:
- if (report)
- report ("digest", GCRY_MD_SHA384, what, errtxt);
- return GPG_ERR_SELFTEST_FAILED;
-}
-
-static gpg_err_code_t
-selftests_sha512 (int extended, selftest_report_func_t report)
-{
- const char *what;
- const char *errtxt;
-
- what = "short string";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA512, 0,
- "abc", 3,
- "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31"
- "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A"
- "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD"
- "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64);
- if (errtxt)
- goto failed;
-
- if (extended)
- {
- what = "long string";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA512, 0,
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
- "\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F"
- "\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18"
- "\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A"
- "\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09",
- 64);
- if (errtxt)
- goto failed;
-
- what = "one million \"a\"";
- errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA512, 1,
- NULL, 0,
- "\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63"
- "\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB"
- "\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B"
- "\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B",
- 64);
- if (errtxt)
- goto failed;
- }
-
- return 0; /* Succeeded. */
-
- failed:
- if (report)
- report ("digest", GCRY_MD_SHA512, what, errtxt);
- return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-/* Run a full self-test for ALGO and return 0 on success. */
-static gpg_err_code_t
-run_selftests (int algo, int extended, selftest_report_func_t report)
-{
- gpg_err_code_t ec;
-
- switch (algo)
- {
- case GCRY_MD_SHA384:
- ec = selftests_sha384 (extended, report);
- break;
- case GCRY_MD_SHA512:
- ec = selftests_sha512 (extended, report);
- break;
- default:
- ec = GPG_ERR_DIGEST_ALGO;
- break;
-
- }
- return ec;
-}
-
-
-
-
-static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */
- {
- 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
- 0x00, 0x04, 0x40
- };
-
-static gcry_md_oid_spec_t oid_spec_sha512[] =
- {
- { "2.16.840.1.101.3.4.2.3" },
-
- /* PKCS#1 sha512WithRSAEncryption */
- { "1.2.840.113549.1.1.13" },
-
- { NULL }
- };
-
-gcry_md_spec_t _gcry_digest_spec_sha512 =
- {
- "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
- sha512_init, sha512_write, sha512_final, sha512_read,
- sizeof (SHA512_CONTEXT),
- };
-md_extra_spec_t _gcry_digest_extraspec_sha512 =
- {
- run_selftests
- };
-
-static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */
- {
- 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
- 0x00, 0x04, 0x30
- };
-
-static gcry_md_oid_spec_t oid_spec_sha384[] =
- {
- { "2.16.840.1.101.3.4.2.2" },
-
- /* PKCS#1 sha384WithRSAEncryption */
- { "1.2.840.113549.1.1.12" },
-
- { NULL },
- };
-
-gcry_md_spec_t _gcry_digest_spec_sha384 =
- {
- "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
- sha384_init, sha512_write, sha512_final, sha512_read,
- sizeof (SHA512_CONTEXT),
- };
-md_extra_spec_t _gcry_digest_extraspec_sha384 =
- {
- run_selftests
- };
+/* sha512.c - SHA384 and SHA512 hash functions
+ * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/* Test vectors from FIPS-180-2:
+ *
+ * "abc"
+ * 384:
+ * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163
+ * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7
+ * 512:
+ * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A
+ * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F
+ *
+ * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ * 384:
+ * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2
+ * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039
+ * 512:
+ * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018
+ * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909
+ *
+ * "a" x 1000000
+ * 384:
+ * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852
+ * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985
+ * 512:
+ * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB
+ * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B
+ */
+
+
+#include <config.h>
+#include <string.h>
+#include "g10lib.h"
+#include "bithelp.h"
+#include "cipher.h"
+#include "hash-common.h"
+
+typedef struct
+{
+ u64 h0, h1, h2, h3, h4, h5, h6, h7;
+ u64 nblocks;
+ byte buf[128];
+ int count;
+} SHA512_CONTEXT;
+
+static void
+sha512_init (void *context)
+{
+ SHA512_CONTEXT *hd = context;
+
+ hd->h0 = U64_C(0x6a09e667f3bcc908);
+ hd->h1 = U64_C(0xbb67ae8584caa73b);
+ hd->h2 = U64_C(0x3c6ef372fe94f82b);
+ hd->h3 = U64_C(0xa54ff53a5f1d36f1);
+ hd->h4 = U64_C(0x510e527fade682d1);
+ hd->h5 = U64_C(0x9b05688c2b3e6c1f);
+ hd->h6 = U64_C(0x1f83d9abfb41bd6b);
+ hd->h7 = U64_C(0x5be0cd19137e2179);
+
+ hd->nblocks = 0;
+ hd->count = 0;
+}
+
+static void
+sha384_init (void *context)
+{
+ SHA512_CONTEXT *hd = context;
+
+ hd->h0 = U64_C(0xcbbb9d5dc1059ed8);
+ hd->h1 = U64_C(0x629a292a367cd507);
+ hd->h2 = U64_C(0x9159015a3070dd17);
+ hd->h3 = U64_C(0x152fecd8f70e5939);
+ hd->h4 = U64_C(0x67332667ffc00b31);
+ hd->h5 = U64_C(0x8eb44a8768581511);
+ hd->h6 = U64_C(0xdb0c2e0d64f98fa7);
+ hd->h7 = U64_C(0x47b5481dbefa4fa4);
+
+ hd->nblocks = 0;
+ hd->count = 0;
+}
+
+
+static inline u64
+ROTR (u64 x, u64 n)
+{
+ return ((x >> n) | (x << (64 - n)));
+}
+
+static inline u64
+Ch (u64 x, u64 y, u64 z)
+{
+ return ((x & y) ^ ( ~x & z));
+}
+
+static inline u64
+Maj (u64 x, u64 y, u64 z)
+{
+ return ((x & y) ^ (x & z) ^ (y & z));
+}
+
+static inline u64
+Sum0 (u64 x)
+{
+ return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39));
+}
+
+static inline u64
+Sum1 (u64 x)
+{
+ return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41));
+}
+
+/****************
+ * Transform the message W which consists of 16 64-bit-words
+ */
+static void
+transform (SHA512_CONTEXT *hd, const unsigned char *data)
+{
+ u64 a, b, c, d, e, f, g, h;
+ u64 w[80];
+ int t;
+ static const u64 k[] =
+ {
+ U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
+ U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
+ U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
+ U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
+ U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
+ U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
+ U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
+ U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
+ U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
+ U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
+ U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
+ U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
+ U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
+ U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
+ U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
+ U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
+ U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
+ U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
+ U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
+ U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
+ U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
+ U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
+ U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
+ U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
+ U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
+ U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
+ U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
+ U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
+ U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
+ U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
+ U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
+ U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
+ U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
+ U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
+ U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
+ U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
+ U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
+ U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
+ U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
+ U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
+ };
+
+ /* get values from the chaining vars */
+ a = hd->h0;
+ b = hd->h1;
+ c = hd->h2;
+ d = hd->h3;
+ e = hd->h4;
+ f = hd->h5;
+ g = hd->h6;
+ h = hd->h7;
+
+#ifdef WORDS_BIGENDIAN
+ memcpy (w, data, 128);
+#else
+ {
+ int i;
+ byte *p2;
+
+ for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8)
+ {
+ p2[7] = *data++;
+ p2[6] = *data++;
+ p2[5] = *data++;
+ p2[4] = *data++;
+ p2[3] = *data++;
+ p2[2] = *data++;
+ p2[1] = *data++;
+ p2[0] = *data++;
+ }
+ }
+#endif
+
+#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
+#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
+
+ for (t = 16; t < 80; t++)
+ w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16];
+
+
+ for (t = 0; t < 80; )
+ {
+ u64 t1, t2;
+
+ /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e
+ with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes
+ initialized to 0,1,2,3...255,0,... and 1000 iterations:
+
+ Not unrolled with macros: 440ms
+ Unrolled with macros: 350ms
+ Unrolled with inline: 330ms
+ */
+#if 0 /* Not unrolled. */
+ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
+ t2 = Sum0 (a) + Maj (a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2;
+ t++;
+#else /* Unrolled to interweave the chain variables. */
+ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
+ t2 = Sum0 (a) + Maj (a, b, c);
+ d += t1;
+ h = t1 + t2;
+
+ t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1];
+ t2 = Sum0 (h) + Maj (h, a, b);
+ c += t1;
+ g = t1 + t2;
+
+ t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2];
+ t2 = Sum0 (g) + Maj (g, h, a);
+ b += t1;
+ f = t1 + t2;
+
+ t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3];
+ t2 = Sum0 (f) + Maj (f, g, h);
+ a += t1;
+ e = t1 + t2;
+
+ t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4];
+ t2 = Sum0 (e) + Maj (e, f, g);
+ h += t1;
+ d = t1 + t2;
+
+ t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5];
+ t2 = Sum0 (d) + Maj (d, e, f);
+ g += t1;
+ c = t1 + t2;
+
+ t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6];
+ t2 = Sum0 (c) + Maj (c, d, e);
+ f += t1;
+ b = t1 + t2;
+
+ t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7];
+ t2 = Sum0 (b) + Maj (b, c, d);
+ e += t1;
+ a = t1 + t2;
+
+ t += 8;
+#endif
+ }
+
+ /* Update chaining vars. */
+ hd->h0 += a;
+ hd->h1 += b;
+ hd->h2 += c;
+ hd->h3 += d;
+ hd->h4 += e;
+ hd->h5 += f;
+ hd->h6 += g;
+ hd->h7 += h;
+}
+
+
+/* Update the message digest with the contents
+ * of INBUF with length INLEN.
+ */
+static void
+sha512_write (void *context, const void *inbuf_arg, size_t inlen)
+{
+ const unsigned char *inbuf = inbuf_arg;
+ SHA512_CONTEXT *hd = context;
+
+ if (hd->count == 128)
+ { /* flush the buffer */
+ transform (hd, hd->buf);
+ _gcry_burn_stack (768);
+ hd->count = 0;
+ hd->nblocks++;
+ }
+ if (!inbuf)
+ return;
+ if (hd->count)
+ {
+ for (; inlen && hd->count < 128; inlen--)
+ hd->buf[hd->count++] = *inbuf++;
+ sha512_write (context, NULL, 0);
+ if (!inlen)
+ return;
+ }
+
+ while (inlen >= 128)
+ {
+ transform (hd, inbuf);
+ hd->count = 0;
+ hd->nblocks++;
+ inlen -= 128;
+ inbuf += 128;
+ }
+ _gcry_burn_stack (768);
+ for (; inlen && hd->count < 128; inlen--)
+ hd->buf[hd->count++] = *inbuf++;
+}
+
+
+/* The routine final terminates the computation and
+ * returns the digest.
+ * The handle is prepared for a new cycle, but adding bytes to the
+ * handle will the destroy the returned buffer.
+ * Returns: 64 bytes representing the digest. When used for sha384,
+ * we take the leftmost 48 of those bytes.
+ */
+
+static void
+sha512_final (void *context)
+{
+ SHA512_CONTEXT *hd = context;
+ u64 t, msb, lsb;
+ byte *p;
+
+ sha512_write (context, NULL, 0); /* flush */ ;
+
+ t = hd->nblocks;
+ /* multiply by 128 to make a byte count */
+ lsb = t << 7;
+ msb = t >> 57;
+ /* add the count */
+ t = lsb;
+ if ((lsb += hd->count) < t)
+ msb++;
+ /* multiply by 8 to make a bit count */
+ t = lsb;
+ lsb <<= 3;
+ msb <<= 3;
+ msb |= t >> 61;
+
+ if (hd->count < 112)
+ { /* enough room */
+ hd->buf[hd->count++] = 0x80; /* pad */
+ while (hd->count < 112)
+ hd->buf[hd->count++] = 0; /* pad */
+ }
+ else
+ { /* need one extra block */
+ hd->buf[hd->count++] = 0x80; /* pad character */
+ while (hd->count < 128)
+ hd->buf[hd->count++] = 0;
+ sha512_write (context, NULL, 0); /* flush */ ;
+ memset (hd->buf, 0, 112); /* fill next block with zeroes */
+ }
+ /* append the 128 bit count */
+ hd->buf[112] = msb >> 56;
+ hd->buf[113] = msb >> 48;
+ hd->buf[114] = msb >> 40;
+ hd->buf[115] = msb >> 32;
+ hd->buf[116] = msb >> 24;
+ hd->buf[117] = msb >> 16;
+ hd->buf[118] = msb >> 8;
+ hd->buf[119] = msb;
+
+ hd->buf[120] = lsb >> 56;
+ hd->buf[121] = lsb >> 48;
+ hd->buf[122] = lsb >> 40;
+ hd->buf[123] = lsb >> 32;
+ hd->buf[124] = lsb >> 24;
+ hd->buf[125] = lsb >> 16;
+ hd->buf[126] = lsb >> 8;
+ hd->buf[127] = lsb;
+ transform (hd, hd->buf);
+ _gcry_burn_stack (768);
+
+ p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0)
+#else /* little endian */
+#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \
+ *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \
+ *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
+ *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
+#endif
+ X (0);
+ X (1);
+ X (2);
+ X (3);
+ X (4);
+ X (5);
+ /* Note that these last two chunks are included even for SHA384.
+ We just ignore them. */
+ X (6);
+ X (7);
+#undef X
+}
+
+static byte *
+sha512_read (void *context)
+{
+ SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context;
+ return hd->buf;
+}
+
+
+
+/*
+ Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sha384 (int extended, selftest_report_func_t report)
+{
+ const char *what;
+ const char *errtxt;
+
+ what = "short string";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA384, 0,
+ "abc", 3,
+ "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
+ "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
+ "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48);
+ if (errtxt)
+ goto failed;
+
+ if (extended)
+ {
+ what = "long string";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA384, 0,
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47"
+ "\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12"
+ "\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39",
+ 48);
+ if (errtxt)
+ goto failed;
+
+ what = "one million \"a\"";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA384, 1,
+ NULL, 0,
+ "\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C"
+ "\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B"
+ "\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85",
+ 48);
+ if (errtxt)
+ goto failed;
+ }
+
+ return 0; /* Succeeded. */
+
+ failed:
+ if (report)
+ report ("digest", GCRY_MD_SHA384, what, errtxt);
+ return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+selftests_sha512 (int extended, selftest_report_func_t report)
+{
+ const char *what;
+ const char *errtxt;
+
+ what = "short string";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA512, 0,
+ "abc", 3,
+ "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31"
+ "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A"
+ "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD"
+ "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64);
+ if (errtxt)
+ goto failed;
+
+ if (extended)
+ {
+ what = "long string";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA512, 0,
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F"
+ "\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18"
+ "\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A"
+ "\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09",
+ 64);
+ if (errtxt)
+ goto failed;
+
+ what = "one million \"a\"";
+ errtxt = _gcry_hash_selftest_check_one
+ (GCRY_MD_SHA512, 1,
+ NULL, 0,
+ "\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63"
+ "\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB"
+ "\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B"
+ "\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B",
+ 64);
+ if (errtxt)
+ goto failed;
+ }
+
+ return 0; /* Succeeded. */
+
+ failed:
+ if (report)
+ report ("digest", GCRY_MD_SHA512, what, errtxt);
+ return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success. */
+static gpg_err_code_t
+run_selftests (int algo, int extended, selftest_report_func_t report)
+{
+ gpg_err_code_t ec;
+
+ switch (algo)
+ {
+ case GCRY_MD_SHA384:
+ ec = selftests_sha384 (extended, report);
+ break;
+ case GCRY_MD_SHA512:
+ ec = selftests_sha512 (extended, report);
+ break;
+ default:
+ ec = GPG_ERR_DIGEST_ALGO;
+ break;
+
+ }
+ return ec;
+}
+
+
+
+
+static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */
+ {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+ 0x00, 0x04, 0x40
+ };
+
+static gcry_md_oid_spec_t oid_spec_sha512[] =
+ {
+ { "2.16.840.1.101.3.4.2.3" },
+
+ /* PKCS#1 sha512WithRSAEncryption */
+ { "1.2.840.113549.1.1.13" },
+
+ { NULL }
+ };
+
+gcry_md_spec_t _gcry_digest_spec_sha512 =
+ {
+ "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
+ sha512_init, sha512_write, sha512_final, sha512_read,
+ sizeof (SHA512_CONTEXT),
+ };
+md_extra_spec_t _gcry_digest_extraspec_sha512 =
+ {
+ run_selftests
+ };
+
+static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */
+ {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+ 0x00, 0x04, 0x30
+ };
+
+static gcry_md_oid_spec_t oid_spec_sha384[] =
+ {
+ { "2.16.840.1.101.3.4.2.2" },
+
+ /* PKCS#1 sha384WithRSAEncryption */
+ { "1.2.840.113549.1.1.12" },
+
+ { NULL },
+ };
+
+gcry_md_spec_t _gcry_digest_spec_sha384 =
+ {
+ "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
+ sha384_init, sha512_write, sha512_final, sha512_read,
+ sizeof (SHA512_CONTEXT),
+ };
+md_extra_spec_t _gcry_digest_extraspec_sha384 =
+ {
+ run_selftests
+ };
diff --git a/libgcrypt-1.4.6/mpi/longlong.h b/libgcrypt-1.4.6/mpi/longlong.h
index b736d49..586c4cc 100644
--- a/libgcrypt-1.4.6/mpi/longlong.h
+++ b/libgcrypt-1.4.6/mpi/longlong.h
@@ -1,1578 +1,1578 @@
-/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
- Note: I added some stuff for use with gnupg
-
-Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or (at your
-option) any later version.
-
-This file 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 Lesser General Public
-License for more details.
-
-You should have received a copy of the GNU Library General Public License
-along with this file; see the file COPYING.LIB. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-MA 02111-1307, USA. */
-
-/* You have to define the following before including this file:
-
- UWtype -- An unsigned type, default type for operations (typically a "word")
- UHWtype -- An unsigned type, at least half the size of UWtype.
- UDWtype -- An unsigned type, at least twice as large a UWtype
- W_TYPE_SIZE -- size in bits of UWtype
-
- SItype, USItype -- Signed and unsigned 32 bit types.
- DItype, UDItype -- Signed and unsigned 64 bit types.
-
- On a 32 bit machine UWtype should typically be USItype;
- on a 64 bit machine, UWtype should typically be UDItype.
-*/
-
-#define __BITS4 (W_TYPE_SIZE / 4)
-#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
-#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
-
-/* This is used to make sure no undesirable sharing between different libraries
- that use this file takes place. */
-#ifndef __MPN
-#define __MPN(x) __##x
-#endif
-
-/* Define auxiliary asm macros.
-
- 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
- UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
- word product in HIGH_PROD and LOW_PROD.
-
- 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
- UDWtype product. This is just a variant of umul_ppmm.
-
- 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
- denominator) divides a UDWtype, composed by the UWtype integers
- HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
- in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
- than DENOMINATOR for correct operation. If, in addition, the most
- significant bit of DENOMINATOR must be 1, then the pre-processor symbol
- UDIV_NEEDS_NORMALIZATION is defined to 1.
-
- 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
- denominator). Like udiv_qrnnd but the numbers are signed. The quotient
- is rounded towards 0.
-
- 5) count_leading_zeros(count, x) counts the number of zero-bits from the
- msb to the first non-zero bit in the UWtype X. This is the number of
- steps X needs to be shifted left to set the msb. Undefined for X == 0,
- unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
-
- 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
- from the least significant end.
-
- 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
- high_addend_2, low_addend_2) adds two UWtype integers, composed by
- HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
- respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
- (i.e. carry out) is not stored anywhere, and is lost.
-
- 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
- high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
- composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
- LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
- and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
- and is lost.
-
- If any of these macros are left undefined for a particular CPU,
- C macros are used. */
-
-/* The CPUs come in alphabetical order below.
-
- Please add support for more CPUs here, or improve the current support
- for the CPUs below! */
-
-#ifdef __riscos__
-#pragma continue_after_hash_error
-#else /* !__riscos__ */
-#if defined (__GNUC__) && !defined (NO_ASM)
-
-/* We sometimes need to clobber "cc" with gcc2, but that would not be
- understood by gcc1. Use cpp to avoid major code duplication. */
-#if __GNUC__ < 2
-#define __CLOBBER_CC
-#define __AND_CLOBBER_CC
-#else /* __GNUC__ >= 2 */
-#define __CLOBBER_CC : "cc"
-#define __AND_CLOBBER_CC , "cc"
-#endif /* __GNUC__ < 2 */
-
-
-/***************************************
- ************** A29K *****************
- ***************************************/
-#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add %1,%4,%5\n" \
- "addc %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("sub %1,%4,%5\n" \
- "subc %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("multiplu %0,%1,%2" \
- : "=r" ((USItype)(xl)) \
- : "r" (__m0), \
- "r" (__m1)); \
- __asm__ ("multmu %0,%1,%2" \
- : "=r" ((USItype)(xh)) \
- : "r" (__m0), \
- "r" (__m1)); \
- } while (0)
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("dividu %0,%3,%4" \
- : "=r" ((USItype)(q)), \
- "=q" ((USItype)(r)) \
- : "1" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "r" ((USItype)(d)))
-#define count_leading_zeros(count, x) \
- __asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x)))
-#define COUNT_LEADING_ZEROS_0 32
-#endif /* __a29k__ */
-
-
-#if defined (__alpha) && W_TYPE_SIZE == 64
-#define umul_ppmm(ph, pl, m0, m1) \
- do { \
- UDItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("umulh %r1,%2,%0" \
- : "=r" ((UDItype) ph) \
- : "%rJ" (__m0), \
- "rI" (__m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#define UMUL_TIME 46
-#ifndef LONGLONG_STANDALONE
-#define udiv_qrnnd(q, r, n1, n0, d) \
- do { UDItype __r; \
- (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
- (r) = __r; \
- } while (0)
-extern UDItype __udiv_qrnnd ();
-#define UDIV_TIME 220
-#endif /* LONGLONG_STANDALONE */
-#endif /* __alpha */
-
-/***************************************
- ************** ARM ******************
- ***************************************/
-#if defined (__arm__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("adds %1, %4, %5\n" \
- "adc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subs %1, %4, %5\n" \
- "sbc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
-#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__
-#define umul_ppmm(xh, xl, a, b) \
- __asm__ ("%@ Inlined umul_ppmm\n" \
- "mov %|r0, %2, lsr #16 @ AAAA\n" \
- "mov %|r2, %3, lsr #16 @ BBBB\n" \
- "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \
- "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \
- "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \
- "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \
- "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \
- "mul %0, %|r0, %0 @ AAAA * bbbb\n" \
- "adds %|r0, %1, %0 @ central sum\n" \
- "addcs %|r2, %|r2, #65536\n" \
- "adds %1, %|r1, %|r0, lsl #16\n" \
- "adc %0, %|r2, %|r0, lsr #16" \
- : "=&r" ((USItype)(xh)), \
- "=r" ((USItype)(xl)) \
- : "r" ((USItype)(a)), \
- "r" ((USItype)(b)) \
- : "r0", "r1", "r2")
-#else
-#define umul_ppmm(xh, xl, a, b) \
- __asm__ ("%@ Inlined umul_ppmm\n" \
- "umull %r1, %r0, %r2, %r3" \
- : "=&r" ((USItype)(xh)), \
- "=r" ((USItype)(xl)) \
- : "r" ((USItype)(a)), \
- "r" ((USItype)(b)) \
- : "r0", "r1")
-#endif
-#define UMUL_TIME 20
-#define UDIV_TIME 100
-#endif /* __arm__ */
-
-/***************************************
- ************** CLIPPER **************
- ***************************************/
-#if defined (__clipper__) && W_TYPE_SIZE == 32
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("mulwux %2,%0" \
- : "=r" (__xx.__ll) \
- : "%0" ((USItype)(u)), \
- "r" ((USItype)(v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define smul_ppmm(w1, w0, u, v) \
- ({union {DItype __ll; \
- struct {SItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("mulwx %2,%0" \
- : "=r" (__xx.__ll) \
- : "%0" ((SItype)(u)), \
- "r" ((SItype)(v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define __umulsidi3(u, v) \
- ({UDItype __w; \
- __asm__ ("mulwux %2,%0" \
- : "=r" (__w) \
- : "%0" ((USItype)(u)), \
- "r" ((USItype)(v))); \
- __w; })
-#endif /* __clipper__ */
-
-
-/***************************************
- ************** GMICRO ***************
- ***************************************/
-#if defined (__gmicro__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add.w %5,%1\n" \
- "addx %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("sub.w %5,%1\n" \
- "subx %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define umul_ppmm(ph, pl, m0, m1) \
- __asm__ ("mulx %3,%0,%1" \
- : "=g" ((USItype)(ph)), \
- "=r" ((USItype)(pl)) \
- : "%0" ((USItype)(m0)), \
- "g" ((USItype)(m1)))
-#define udiv_qrnnd(q, r, nh, nl, d) \
- __asm__ ("divx %4,%0,%1" \
- : "=g" ((USItype)(q)), \
- "=r" ((USItype)(r)) \
- : "1" ((USItype)(nh)), \
- "0" ((USItype)(nl)), \
- "g" ((USItype)(d)))
-#define count_leading_zeros(count, x) \
- __asm__ ("bsch/1 %1,%0" \
- : "=g" (count) \
- : "g" ((USItype)(x)), \
- "0" ((USItype)0))
-#endif
-
-
-/***************************************
- ************** HPPA *****************
- ***************************************/
-#if defined (__hppa) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ (" add %4,%5,%1\n" \
- " addc %2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rM" ((USItype)(ah)), \
- "rM" ((USItype)(bh)), \
- "%rM" ((USItype)(al)), \
- "rM" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ (" sub %4,%5,%1\n" \
- " subb %2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rM" ((USItype)(ah)), \
- "rM" ((USItype)(bh)), \
- "rM" ((USItype)(al)), \
- "rM" ((USItype)(bl)))
-#if defined (_PA_RISC1_1)
-#define umul_ppmm(wh, wl, u, v) \
- do { \
- union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- __asm__ (" xmpyu %1,%2,%0" \
- : "=*f" (__xx.__ll) \
- : "*f" ((USItype)(u)), \
- "*f" ((USItype)(v))); \
- (wh) = __xx.__i.__h; \
- (wl) = __xx.__i.__l; \
- } while (0)
-#define UMUL_TIME 8
-#define UDIV_TIME 60
-#else
-#define UMUL_TIME 40
-#define UDIV_TIME 80
-#endif
-#ifndef LONGLONG_STANDALONE
-#define udiv_qrnnd(q, r, n1, n0, d) \
- do { USItype __r; \
- (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
- (r) = __r; \
- } while (0)
-extern USItype __udiv_qrnnd ();
-#endif /* LONGLONG_STANDALONE */
-#define count_leading_zeros(count, x) \
- do { \
- USItype __tmp; \
- __asm__ ( \
- " ldi 1,%0 \n" \
- " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \
- " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \
- " ldo 16(%0),%0 ; Yes. Perform add. \n" \
- " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \
- " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \
- " ldo 8(%0),%0 ; Yes. Perform add. \n" \
- " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \
- " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \
- " ldo 4(%0),%0 ; Yes. Perform add. \n" \
- " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \
- " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \
- " ldo 2(%0),%0 ; Yes. Perform add. \n" \
- " extru %1,30,1,%1 ; Extract bit 1. \n" \
- " sub %0,%1,%0 ; Subtract it. " \
- : "=r" (count), "=r" (__tmp) : "1" (x)); \
- } while (0)
-#endif /* hppa */
-
-
-/***************************************
- ************** I370 *****************
- ***************************************/
-#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mr %0,%3" \
- : "=r" (__xx.__i.__h), \
- "=r" (__xx.__i.__l) \
- : "%1" (__m0), \
- "r" (__m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
- (xh) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
-#define smul_ppmm(xh, xl, m0, m1) \
- do { \
- union {DItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- __asm__ ("mr %0,%3" \
- : "=r" (__xx.__i.__h), \
- "=r" (__xx.__i.__l) \
- : "%1" (m0), \
- "r" (m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
- } while (0)
-#define sdiv_qrnnd(q, r, n1, n0, d) \
- do { \
- union {DItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- __xx.__i.__h = n1; __xx.__i.__l = n0; \
- __asm__ ("dr %0,%2" \
- : "=r" (__xx.__ll) \
- : "0" (__xx.__ll), "r" (d)); \
- (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
- } while (0)
-#endif
-
-
-/***************************************
- ************** I386 *****************
- ***************************************/
-#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addl %5,%1\n" \
- "adcl %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subl %5,%1\n" \
- "sbbl %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("mull %3" \
- : "=a" ((USItype)(w0)), \
- "=d" ((USItype)(w1)) \
- : "%0" ((USItype)(u)), \
- "rm" ((USItype)(v)))
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("divl %4" \
- : "=a" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "rm" ((USItype)(d)))
-#define count_leading_zeros(count, x) \
- do { \
- USItype __cbtmp; \
- __asm__ ("bsrl %1,%0" \
- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \
- (count) = __cbtmp ^ 31; \
- } while (0)
-#define count_trailing_zeros(count, x) \
- __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
-#ifndef UMUL_TIME
-#define UMUL_TIME 40
-#endif
-#ifndef UDIV_TIME
-#define UDIV_TIME 40
-#endif
-#endif /* 80x86 */
-
-
-/***************************************
- ************** I860 *****************
- ***************************************/
-#if defined (__i860__) && W_TYPE_SIZE == 32
-#define rshift_rhlc(r,h,l,c) \
- __asm__ ("shr %3,r0,r0\n" \
- "shrd %1,%2,%0" \
- "=r" (r) : "r" (h), "r" (l), "rn" (c))
-#endif /* i860 */
-
-/***************************************
- ************** I960 *****************
- ***************************************/
-#if defined (__i960__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("cmpo 1,0\n" \
- "addc %5,%4,%1\n" \
- "addc %3,%2,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%dI" ((USItype)(ah)), \
- "dI" ((USItype)(bh)), \
- "%dI" ((USItype)(al)), \
- "dI" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("cmpo 0,0\n" \
- "subc %5,%4,%1\n" \
- "subc %3,%2,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "dI" ((USItype)(ah)), \
- "dI" ((USItype)(bh)), \
- "dI" ((USItype)(al)), \
- "dI" ((USItype)(bl)))
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("emul %2,%1,%0" \
- : "=d" (__xx.__ll) \
- : "%dI" ((USItype)(u)), \
- "dI" ((USItype)(v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define __umulsidi3(u, v) \
- ({UDItype __w; \
- __asm__ ("emul %2,%1,%0" \
- : "=d" (__w) \
- : "%dI" ((USItype)(u)), \
- "dI" ((USItype)(v))); \
- __w; })
-#define udiv_qrnnd(q, r, nh, nl, d) \
- do { \
- union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __nn; \
- __nn.__i.__h = (nh); __nn.__i.__l = (nl); \
- __asm__ ("ediv %d,%n,%0" \
- : "=d" (__rq.__ll) \
- : "dI" (__nn.__ll), \
- "dI" ((USItype)(d))); \
- (r) = __rq.__i.__l; (q) = __rq.__i.__h; \
- } while (0)
-#define count_leading_zeros(count, x) \
- do { \
- USItype __cbtmp; \
- __asm__ ("scanbit %1,%0" \
- : "=r" (__cbtmp) \
- : "r" ((USItype)(x))); \
- (count) = __cbtmp ^ 31; \
- } while (0)
-#define COUNT_LEADING_ZEROS_0 (-32) /* sic */
-#if defined (__i960mx) /* what is the proper symbol to test??? */
-#define rshift_rhlc(r,h,l,c) \
- do { \
- union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __nn; \
- __nn.__i.__h = (h); __nn.__i.__l = (l); \
- __asm__ ("shre %2,%1,%0" \
- : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \
- }
-#endif /* i960mx */
-#endif /* i960 */
-
-
-/***************************************
- ************** 68000 ****************
- ***************************************/
-#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add%.l %5,%1\n" \
- "addx%.l %3,%0" \
- : "=d" ((USItype)(sh)), \
- "=&d" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "d" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("sub%.l %5,%1\n" \
- "subx%.l %3,%0" \
- : "=d" ((USItype)(sh)), \
- "=&d" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "d" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("mulu%.l %3,%1:%0" \
- : "=d" ((USItype)(w0)), \
- "=d" ((USItype)(w1)) \
- : "%0" ((USItype)(u)), \
- "dmi" ((USItype)(v)))
-#define UMUL_TIME 45
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("divu%.l %4,%1:%0" \
- : "=d" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "dmi" ((USItype)(d)))
-#define UDIV_TIME 90
-#define sdiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("divs%.l %4,%1:%0" \
- : "=d" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "dmi" ((USItype)(d)))
-#define count_leading_zeros(count, x) \
- __asm__ ("bfffo %1{%b2:%b2},%0" \
- : "=d" ((USItype)(count)) \
- : "od" ((USItype)(x)), "n" (0))
-#define COUNT_LEADING_ZEROS_0 32
-#else /* not mc68020 */
-#define umul_ppmm(xh, xl, a, b) \
- do { USItype __umul_tmp1, __umul_tmp2; \
- __asm__ ("| Inlined umul_ppmm \n" \
- " move%.l %5,%3 \n" \
- " move%.l %2,%0 \n" \
- " move%.w %3,%1 \n" \
- " swap %3 \n" \
- " swap %0 \n" \
- " mulu %2,%1 \n" \
- " mulu %3,%0 \n" \
- " mulu %2,%3 \n" \
- " swap %2 \n" \
- " mulu %5,%2 \n" \
- " add%.l %3,%2 \n" \
- " jcc 1f \n" \
- " add%.l %#0x10000,%0 \n" \
- "1: move%.l %2,%3 \n" \
- " clr%.w %2 \n" \
- " swap %2 \n" \
- " swap %3 \n" \
- " clr%.w %3 \n" \
- " add%.l %3,%1 \n" \
- " addx%.l %2,%0 \n" \
- " | End inlined umul_ppmm" \
- : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \
- "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \
- : "%2" ((USItype)(a)), "d" ((USItype)(b))); \
- } while (0)
-#define UMUL_TIME 100
-#define UDIV_TIME 400
-#endif /* not mc68020 */
-#endif /* mc68000 */
-
-
-/***************************************
- ************** 88000 ****************
- ***************************************/
-#if defined (__m88000__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addu.co %1,%r4,%r5\n" \
- "addu.ci %0,%r2,%r3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rJ" ((USItype)(ah)), \
- "rJ" ((USItype)(bh)), \
- "%rJ" ((USItype)(al)), \
- "rJ" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subu.co %1,%r4,%r5\n" \
- "subu.ci %0,%r2,%r3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rJ" ((USItype)(ah)), \
- "rJ" ((USItype)(bh)), \
- "rJ" ((USItype)(al)), \
- "rJ" ((USItype)(bl)))
-#define count_leading_zeros(count, x) \
- do { \
- USItype __cbtmp; \
- __asm__ ("ff1 %0,%1" \
- : "=r" (__cbtmp) \
- : "r" ((USItype)(x))); \
- (count) = __cbtmp ^ 31; \
- } while (0)
-#define COUNT_LEADING_ZEROS_0 63 /* sic */
-#if defined (__m88110__)
-#define umul_ppmm(wh, wl, u, v) \
- do { \
- union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __x; \
- __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \
- (wh) = __x.__i.__h; \
- (wl) = __x.__i.__l; \
- } while (0)
-#define udiv_qrnnd(q, r, n1, n0, d) \
- ({union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __x, __q; \
- __x.__i.__h = (n1); __x.__i.__l = (n0); \
- __asm__ ("divu.d %0,%1,%2" \
- : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \
- (r) = (n0) - __q.__l * (d); (q) = __q.__l; })
-#define UMUL_TIME 5
-#define UDIV_TIME 25
-#else
-#define UMUL_TIME 17
-#define UDIV_TIME 150
-#endif /* __m88110__ */
-#endif /* __m88000__ */
-
-/***************************************
- ************** MIPS *****************
- ***************************************/
-#if defined (__mips__) && W_TYPE_SIZE == 32
-#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-#define umul_ppmm(w1, w0, u, v) \
- do { \
- UDItype _r; \
- _r = (UDItype) u * v; \
- (w1) = _r >> 32; \
- (w0) = (USItype) _r; \
- } while (0)
-#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("multu %2,%3" \
- : "=l" ((USItype)(w0)), \
- "=h" ((USItype)(w1)) \
- : "d" ((USItype)(u)), \
- "d" ((USItype)(v)))
-#else
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("multu %2,%3 \n" \
- "mflo %0 \n" \
- "mfhi %1" \
- : "=d" ((USItype)(w0)), \
- "=d" ((USItype)(w1)) \
- : "d" ((USItype)(u)), \
- "d" ((USItype)(v)))
-#endif
-#define UMUL_TIME 10
-#define UDIV_TIME 100
-#endif /* __mips__ */
-
-/***************************************
- ************** MIPS/64 **************
- ***************************************/
-#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-typedef unsigned int UTItype __attribute__ ((mode (TI)));
-#define umul_ppmm(w1, w0, u, v) \
- do { \
- UTItype _r; \
- _r = (UTItype) u * v; \
- (w1) = _r >> 64; \
- (w0) = (UDItype) _r; \
- } while (0)
-#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("dmultu %2,%3" \
- : "=l" ((UDItype)(w0)), \
- "=h" ((UDItype)(w1)) \
- : "d" ((UDItype)(u)), \
- "d" ((UDItype)(v)))
-#else
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("dmultu %2,%3 \n" \
- "mflo %0 \n" \
- "mfhi %1" \
- : "=d" ((UDItype)(w0)), \
- "=d" ((UDItype)(w1)) \
- : "d" ((UDItype)(u)), \
- "d" ((UDItype)(v)))
-#endif
-#define UMUL_TIME 20
-#define UDIV_TIME 140
-#endif /* __mips__ */
-
-
-/***************************************
- ************** 32000 ****************
- ***************************************/
-#if defined (__ns32000__) && W_TYPE_SIZE == 32
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("meid %2,%0" \
- : "=g" (__xx.__ll) \
- : "%0" ((USItype)(u)), \
- "g" ((USItype)(v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define __umulsidi3(u, v) \
- ({UDItype __w; \
- __asm__ ("meid %2,%0" \
- : "=g" (__w) \
- : "%0" ((USItype)(u)), \
- "g" ((USItype)(v))); \
- __w; })
-#define udiv_qrnnd(q, r, n1, n0, d) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
- __asm__ ("deid %2,%0" \
- : "=g" (__xx.__ll) \
- : "0" (__xx.__ll), \
- "g" ((USItype)(d))); \
- (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
-#define count_trailing_zeros(count,x) \
- do {
- __asm__ ("ffsd %2,%0" \
- : "=r" ((USItype) (count)) \
- : "0" ((USItype) 0), \
- "r" ((USItype) (x))); \
- } while (0)
-#endif /* __ns32000__ */
-
-
-/***************************************
- ************** PPC ******************
- ***************************************/
-#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- do { \
- if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
- else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
- else \
- __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
- } while (0)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- do { \
- if (__builtin_constant_p (ah) && (ah) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
- else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
- else if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
- else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
- else \
- __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
- } while (0)
-#define count_leading_zeros(count, x) \
- __asm__ ("{cntlz|cntlzw} %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x)))
-#define COUNT_LEADING_ZEROS_0 32
-#if defined (_ARCH_PPC)
-#define umul_ppmm(ph, pl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhwu %0,%1,%2" \
- : "=r" ((USItype) ph) \
- : "%r" (__m0), \
- "r" (__m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#define UMUL_TIME 15
-#define smul_ppmm(ph, pl, m0, m1) \
- do { \
- SItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhw %0,%1,%2" \
- : "=r" ((SItype) ph) \
- : "%r" (__m0), \
- "r" (__m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#define SMUL_TIME 14
-#define UDIV_TIME 120
-#else
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mul %0,%2,%3" \
- : "=r" ((USItype)(xh)), \
- "=q" ((USItype)(xl)) \
- : "r" (__m0), \
- "r" (__m1)); \
- (xh) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
-#define UMUL_TIME 8
-#define smul_ppmm(xh, xl, m0, m1) \
- __asm__ ("mul %0,%2,%3" \
- : "=r" ((SItype)(xh)), \
- "=q" ((SItype)(xl)) \
- : "r" (m0), \
- "r" (m1))
-#define SMUL_TIME 4
-#define sdiv_qrnnd(q, r, nh, nl, d) \
- __asm__ ("div %0,%2,%4" \
- : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \
- : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
-#define UDIV_TIME 100
-#endif
-#endif /* Power architecture variants. */
-
-/* Powerpc 64 bit support taken from gmp-4.1.2. */
-/* We should test _IBMR2 here when we add assembly support for the system
- vendor compilers. */
-#if 0 /* Not yet enabled becuase we don't have hardware for a test. */
-#if (defined (_ARCH_PPC) || defined (__powerpc__)) && W_TYPE_SIZE == 64
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- do { \
- if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
- else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
- else \
- __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
- : "=r" (sh), "=&r" (sl) \
- : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
- } while (0)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- do { \
- if (__builtin_constant_p (ah) && (ah) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
- else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
- else if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
- else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
- : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
- else \
- __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
- : "=r" (sh), "=&r" (sl) \
- : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
- } while (0)
-#define count_leading_zeros(count, x) \
- __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
-#define COUNT_LEADING_ZEROS_0 64
-#define umul_ppmm(ph, pl, m0, m1) \
- do { \
- UDItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#define UMUL_TIME 15
-#define smul_ppmm(ph, pl, m0, m1) \
- do { \
- DItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#define SMUL_TIME 14 /* ??? */
-#define UDIV_TIME 120 /* ??? */
-#endif /* 64-bit PowerPC. */
-#endif /* if 0 */
-
-/***************************************
- ************** PYR ******************
- ***************************************/
-#if defined (__pyr__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addw %5,%1 \n" \
- "addwc %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subw %5,%1 \n" \
- "subwb %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- __asm__ ("movw %1,%R0 \n" \
- "uemul %2,%0" \
- : "=&r" (__xx.__ll) \
- : "g" ((USItype) (u)), \
- "g" ((USItype)(v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#endif /* __pyr__ */
-
-
-/***************************************
- ************** RT/ROMP **************
- ***************************************/
-#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("a %1,%5 \n" \
- "ae %0,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "r" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("s %1,%5\n" \
- "se %0,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "r" ((USItype)(bl)))
-#define umul_ppmm(ph, pl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ( \
- "s r2,r2 \n" \
- "mts r10,%2 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "m r2,%3 \n" \
- "cas %0,r2,r0 \n" \
- "mfs r10,%1" \
- : "=r" ((USItype)(ph)), \
- "=r" ((USItype)(pl)) \
- : "%r" (__m0), \
- "r" (__m1) \
- : "r2"); \
- (ph) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
-#define UMUL_TIME 20
-#define UDIV_TIME 200
-#define count_leading_zeros(count, x) \
- do { \
- if ((x) >= 0x10000) \
- __asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x) >> 16)); \
- else \
- { \
- __asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x))); \
- (count) += 16; \
- } \
- } while (0)
-#endif /* RT/ROMP */
-
-
-/***************************************
- ************** SH2 ******************
- ***************************************/
-#if (defined (__sh2__) || defined(__sh3__) || defined(__SH4__) ) \
- && W_TYPE_SIZE == 32
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ( \
- "dmulu.l %2,%3\n" \
- "sts macl,%1\n" \
- "sts mach,%0" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v)) \
- : "macl", "mach")
-#define UMUL_TIME 5
-#endif
-
-/***************************************
- ************** SPARC ****************
- ***************************************/
-#if defined (__sparc__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addcc %r4,%5,%1\n" \
- "addx %r2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rJ" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%rJ" ((USItype)(al)), \
- "rI" ((USItype)(bl)) \
- __CLOBBER_CC)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subcc %r4,%5,%1\n" \
- "subx %r2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rJ" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "rJ" ((USItype)(al)), \
- "rI" ((USItype)(bl)) \
- __CLOBBER_CC)
-#if defined (__sparc_v8__)
-/* Don't match immediate range because, 1) it is not often useful,
- 2) the 'I' flag thinks of the range as a 13 bit signed interval,
- while we want to match a 13 bit interval, sign extended to 32 bits,
- but INTERPRETED AS UNSIGNED. */
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("umul %2,%3,%1;rd %%y,%0" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v)))
-#define UMUL_TIME 5
-#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */
-#define udiv_qrnnd(q, r, n1, n0, d) \
- do { \
- USItype __q; \
- __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \
- : "=r" ((USItype)(__q)) \
- : "r" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "r" ((USItype)(d))); \
- (r) = (n0) - __q * (d); \
- (q) = __q; \
- } while (0)
-#define UDIV_TIME 25
-#endif /* SUPERSPARC */
-#else /* ! __sparc_v8__ */
-#if defined (__sparclite__)
-/* This has hardware multiply but not divide. It also has two additional
- instructions scan (ffs from high bit) and divscc. */
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("umul %2,%3,%1;rd %%y,%0" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v)))
-#define UMUL_TIME 5
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("! Inlined udiv_qrnnd \n" \
- " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \
- " tst %%g0 \n" \
- " divscc %3,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%%g1 \n" \
- " divscc %%g1,%4,%0 \n" \
- " rd %%y,%1 \n" \
- " bl,a 1f \n" \
- " add %1,%4,%1 \n" \
- "1: ! End of inline udiv_qrnnd" \
- : "=r" ((USItype)(q)), \
- "=r" ((USItype)(r)) \
- : "r" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "rI" ((USItype)(d)) \
- : "%g1" __AND_CLOBBER_CC)
-#define UDIV_TIME 37
-#define count_leading_zeros(count, x) \
- __asm__ ("scan %1,0,%0" \
- : "=r" ((USItype)(x)) \
- : "r" ((USItype)(count)))
-/* Early sparclites return 63 for an argument of 0, but they warn that future
- implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0
- undefined. */
-#endif /* __sparclite__ */
-#endif /* __sparc_v8__ */
-/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */
-#ifndef umul_ppmm
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("! Inlined umul_ppmm \n" \
- " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \
- " sra %3,31,%%g2 ! Don't move this insn \n" \
- " and %2,%%g2,%%g2 ! Don't move this insn \n" \
- " andcc %%g0,0,%%g1 ! Don't move this insn \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,%3,%%g1 \n" \
- " mulscc %%g1,0,%%g1 \n" \
- " add %%g1,%%g2,%0 \n" \
- " rd %%y,%1" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "%rI" ((USItype)(u)), \
- "r" ((USItype)(v)) \
- : "%g1", "%g2" __AND_CLOBBER_CC)
-#define UMUL_TIME 39 /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
-#define udiv_qrnnd(q, r, n1, n0, d) \
- do { USItype __r; \
- (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
- (r) = __r; \
- } while (0)
-extern USItype __udiv_qrnnd ();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
-#endif /* __sparc__ */
-
-
-/***************************************
- ************** VAX ******************
- ***************************************/
-#if defined (__vax__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addl2 %5,%1\n" \
- "adwc %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subl2 %5,%1\n" \
- "sbwc %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("emul %1,%2,$0,%0" \
- : "=g" (__xx.__ll) \
- : "g" (__m0), \
- "g" (__m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
- (xh) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
-#define sdiv_qrnnd(q, r, n1, n0, d) \
- do { \
- union {DItype __ll; \
- struct {SItype __l, __h;} __i; \
- } __xx; \
- __xx.__i.__h = n1; __xx.__i.__l = n0; \
- __asm__ ("ediv %3,%2,%0,%1" \
- : "=g" (q), "=g" (r) \
- : "g" (__xx.__ll), "g" (d)); \
- } while (0)
-#endif /* __vax__ */
-
-
-/***************************************
- ************** Z8000 ****************
- ***************************************/
-#if defined (__z8000__) && W_TYPE_SIZE == 16
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \
- : "=r" ((unsigned int)(sh)), \
- "=&r" ((unsigned int)(sl)) \
- : "%0" ((unsigned int)(ah)), \
- "r" ((unsigned int)(bh)), \
- "%1" ((unsigned int)(al)), \
- "rQR" ((unsigned int)(bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \
- : "=r" ((unsigned int)(sh)), \
- "=&r" ((unsigned int)(sl)) \
- : "0" ((unsigned int)(ah)), \
- "r" ((unsigned int)(bh)), \
- "1" ((unsigned int)(al)), \
- "rQR" ((unsigned int)(bl)))
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- union {long int __ll; \
- struct {unsigned int __h, __l;} __i; \
- } __xx; \
- unsigned int __m0 = (m0), __m1 = (m1); \
- __asm__ ("mult %S0,%H3" \
- : "=r" (__xx.__i.__h), \
- "=r" (__xx.__i.__l) \
- : "%1" (__m0), \
- "rQR" (__m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
- (xh) += ((((signed int) __m0 >> 15) & __m1) \
- + (((signed int) __m1 >> 15) & __m0)); \
- } while (0)
-#endif /* __z8000__ */
-
-#endif /* __GNUC__ */
-#endif /* !__riscos__ */
-
-
-/***************************************
- *********** Generic Versions ********
- ***************************************/
-#if !defined (umul_ppmm) && defined (__umulsidi3)
-#define umul_ppmm(ph, pl, m0, m1) \
- { \
- UDWtype __ll = __umulsidi3 (m0, m1); \
- ph = (UWtype) (__ll >> W_TYPE_SIZE); \
- pl = (UWtype) __ll; \
- }
-#endif
-
-#if !defined (__umulsidi3)
-#define __umulsidi3(u, v) \
- ({UWtype __hi, __lo; \
- umul_ppmm (__hi, __lo, u, v); \
- ((UDWtype) __hi << W_TYPE_SIZE) | __lo; })
-#endif
-
-/* If this machine has no inline assembler, use C macros. */
-
-#if !defined (add_ssaaaa)
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- do { \
- UWtype __x; \
- __x = (al) + (bl); \
- (sh) = (ah) + (bh) + (__x < (al)); \
- (sl) = __x; \
- } while (0)
-#endif
-
-#if !defined (sub_ddmmss)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- do { \
- UWtype __x; \
- __x = (al) - (bl); \
- (sh) = (ah) - (bh) - (__x > (al)); \
- (sl) = __x; \
- } while (0)
-#endif
-
-#if !defined (umul_ppmm)
-#define umul_ppmm(w1, w0, u, v) \
- do { \
- UWtype __x0, __x1, __x2, __x3; \
- UHWtype __ul, __vl, __uh, __vh; \
- UWtype __u = (u), __v = (v); \
- \
- __ul = __ll_lowpart (__u); \
- __uh = __ll_highpart (__u); \
- __vl = __ll_lowpart (__v); \
- __vh = __ll_highpart (__v); \
- \
- __x0 = (UWtype) __ul * __vl; \
- __x1 = (UWtype) __ul * __vh; \
- __x2 = (UWtype) __uh * __vl; \
- __x3 = (UWtype) __uh * __vh; \
- \
- __x1 += __ll_highpart (__x0);/* this can't give carry */ \
- __x1 += __x2; /* but this indeed can */ \
- if (__x1 < __x2) /* did we get it? */ \
- __x3 += __ll_B; /* yes, add it in the proper pos. */ \
- \
- (w1) = __x3 + __ll_highpart (__x1); \
- (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\
- } while (0)
-#endif
-
-#if !defined (umul_ppmm)
-#define smul_ppmm(w1, w0, u, v) \
- do { \
- UWtype __w1; \
- UWtype __m0 = (u), __m1 = (v); \
- umul_ppmm (__w1, w0, __m0, __m1); \
- (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \
- - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \
- } while (0)
-#endif
-
-/* Define this unconditionally, so it can be used for debugging. */
-#define __udiv_qrnnd_c(q, r, n1, n0, d) \
- do { \
- UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \
- __d1 = __ll_highpart (d); \
- __d0 = __ll_lowpart (d); \
- \
- __r1 = (n1) % __d1; \
- __q1 = (n1) / __d1; \
- __m = (UWtype) __q1 * __d0; \
- __r1 = __r1 * __ll_B | __ll_highpart (n0); \
- if (__r1 < __m) \
- { \
- __q1--, __r1 += (d); \
- if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
- if (__r1 < __m) \
- __q1--, __r1 += (d); \
- } \
- __r1 -= __m; \
- \
- __r0 = __r1 % __d1; \
- __q0 = __r1 / __d1; \
- __m = (UWtype) __q0 * __d0; \
- __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
- if (__r0 < __m) \
- { \
- __q0--, __r0 += (d); \
- if (__r0 >= (d)) \
- if (__r0 < __m) \
- __q0--, __r0 += (d); \
- } \
- __r0 -= __m; \
- \
- (q) = (UWtype) __q1 * __ll_B | __q0; \
- (r) = __r0; \
- } while (0)
-
-/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
- __udiv_w_sdiv (defined in libgcc or elsewhere). */
-#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
-#define udiv_qrnnd(q, r, nh, nl, d) \
- do { \
- UWtype __r; \
- (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \
- (r) = __r; \
- } while (0)
-#endif
-
-/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
-#if !defined (udiv_qrnnd)
-#define UDIV_NEEDS_NORMALIZATION 1
-#define udiv_qrnnd __udiv_qrnnd_c
-#endif
-
-#if !defined (count_leading_zeros)
-extern
-#ifdef __STDC__
-const
-#endif
-unsigned char _gcry_clz_tab[];
-#define MPI_INTERNAL_NEED_CLZ_TAB 1
-#define count_leading_zeros(count, x) \
- do { \
- UWtype __xr = (x); \
- UWtype __a; \
- \
- if (W_TYPE_SIZE <= 32) \
- { \
- __a = __xr < ((UWtype) 1 << 2*__BITS4) \
- ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \
- : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\
- } \
- else \
- { \
- for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
- if (((__xr >> __a) & 0xff) != 0) \
- break; \
- } \
- \
- (count) = W_TYPE_SIZE - (_gcry_clz_tab[__xr >> __a] + __a); \
- } while (0)
-/* This version gives a well-defined value for zero. */
-#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
-#endif
-
-#if !defined (count_trailing_zeros)
-/* Define count_trailing_zeros using count_leading_zeros. The latter might be
- defined in asm, but if it is not, the C version above is good enough. */
-#define count_trailing_zeros(count, x) \
- do { \
- UWtype __ctz_x = (x); \
- UWtype __ctz_c; \
- count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
- (count) = W_TYPE_SIZE - 1 - __ctz_c; \
- } while (0)
-#endif
-
-#ifndef UDIV_NEEDS_NORMALIZATION
-#define UDIV_NEEDS_NORMALIZATION 0
-#endif
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+ Note: I added some stuff for use with gnupg
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998,
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+This file 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 Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this file; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* You have to define the following before including this file:
+
+ UWtype -- An unsigned type, default type for operations (typically a "word")
+ UHWtype -- An unsigned type, at least half the size of UWtype.
+ UDWtype -- An unsigned type, at least twice as large a UWtype
+ W_TYPE_SIZE -- size in bits of UWtype
+
+ SItype, USItype -- Signed and unsigned 32 bit types.
+ DItype, UDItype -- Signed and unsigned 64 bit types.
+
+ On a 32 bit machine UWtype should typically be USItype;
+ on a 64 bit machine, UWtype should typically be UDItype.
+*/
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* This is used to make sure no undesirable sharing between different libraries
+ that use this file takes place. */
+#ifndef __MPN
+#define __MPN(x) __##x
+#endif
+
+/* Define auxiliary asm macros.
+
+ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+ UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+ word product in HIGH_PROD and LOW_PROD.
+
+ 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+ UDWtype product. This is just a variant of umul_ppmm.
+
+ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator) divides a UDWtype, composed by the UWtype integers
+ HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
+ than DENOMINATOR for correct operation. If, in addition, the most
+ significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator). Like udiv_qrnnd but the numbers are signed. The quotient
+ is rounded towards 0.
+
+ 5) count_leading_zeros(count, x) counts the number of zero-bits from the
+ msb to the first non-zero bit in the UWtype X. This is the number of
+ steps X needs to be shifted left to set the msb. Undefined for X == 0,
+ unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+ 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+ from the least significant end.
+
+ 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
+ (i.e. carry out) is not stored anywhere, and is lost.
+
+ 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
+ and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+ and is lost.
+
+ If any of these macros are left undefined for a particular CPU,
+ C macros are used. */
+
+/* The CPUs come in alphabetical order below.
+
+ Please add support for more CPUs here, or improve the current support
+ for the CPUs below! */
+
+#ifdef __riscos__
+#pragma continue_after_hash_error
+#else /* !__riscos__ */
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+ understood by gcc1. Use cpp to avoid major code duplication. */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+
+/***************************************
+ ************** A29K *****************
+ ***************************************/
+#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %1,%4,%5\n" \
+ "addc %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %1,%4,%5\n" \
+ "subc %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("multiplu %0,%1,%2" \
+ : "=r" ((USItype)(xl)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ __asm__ ("multmu %0,%1,%2" \
+ : "=r" ((USItype)(xh)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("dividu %0,%3,%4" \
+ : "=r" ((USItype)(q)), \
+ "=q" ((USItype)(r)) \
+ : "1" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "r" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#endif /* __a29k__ */
+
+
+#if defined (__alpha) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("umulh %r1,%2,%0" \
+ : "=r" ((UDItype) ph) \
+ : "%rJ" (__m0), \
+ "rI" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 46
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { UDItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern UDItype __udiv_qrnnd ();
+#define UDIV_TIME 220
+#endif /* LONGLONG_STANDALONE */
+#endif /* __alpha */
+
+/***************************************
+ ************** ARM ******************
+ ***************************************/
+#if defined (__arm__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("adds %1, %4, %5\n" \
+ "adc %0, %2, %3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subs %1, %4, %5\n" \
+ "sbc %0, %2, %3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__
+#define umul_ppmm(xh, xl, a, b) \
+ __asm__ ("%@ Inlined umul_ppmm\n" \
+ "mov %|r0, %2, lsr #16 @ AAAA\n" \
+ "mov %|r2, %3, lsr #16 @ BBBB\n" \
+ "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \
+ "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \
+ "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \
+ "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \
+ "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \
+ "mul %0, %|r0, %0 @ AAAA * bbbb\n" \
+ "adds %|r0, %1, %0 @ central sum\n" \
+ "addcs %|r2, %|r2, #65536\n" \
+ "adds %1, %|r1, %|r0, lsl #16\n" \
+ "adc %0, %|r2, %|r0, lsr #16" \
+ : "=&r" ((USItype)(xh)), \
+ "=r" ((USItype)(xl)) \
+ : "r" ((USItype)(a)), \
+ "r" ((USItype)(b)) \
+ : "r0", "r1", "r2")
+#else
+#define umul_ppmm(xh, xl, a, b) \
+ __asm__ ("%@ Inlined umul_ppmm\n" \
+ "umull %r1, %r0, %r2, %r3" \
+ : "=&r" ((USItype)(xh)), \
+ "=r" ((USItype)(xl)) \
+ : "r" ((USItype)(a)), \
+ "r" ((USItype)(b)) \
+ : "r0", "r1")
+#endif
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+/***************************************
+ ************** CLIPPER **************
+ ***************************************/
+#if defined (__clipper__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("mulwux %2,%0" \
+ : "=r" (__xx.__ll) \
+ : "%0" ((USItype)(u)), \
+ "r" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define smul_ppmm(w1, w0, u, v) \
+ ({union {DItype __ll; \
+ struct {SItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("mulwx %2,%0" \
+ : "=r" (__xx.__ll) \
+ : "%0" ((SItype)(u)), \
+ "r" ((SItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("mulwux %2,%0" \
+ : "=r" (__w) \
+ : "%0" ((USItype)(u)), \
+ "r" ((USItype)(v))); \
+ __w; })
+#endif /* __clipper__ */
+
+
+/***************************************
+ ************** GMICRO ***************
+ ***************************************/
+#if defined (__gmicro__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add.w %5,%1\n" \
+ "addx %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub.w %5,%1\n" \
+ "subx %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+ __asm__ ("mulx %3,%0,%1" \
+ : "=g" ((USItype)(ph)), \
+ "=r" ((USItype)(pl)) \
+ : "%0" ((USItype)(m0)), \
+ "g" ((USItype)(m1)))
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ __asm__ ("divx %4,%0,%1" \
+ : "=g" ((USItype)(q)), \
+ "=r" ((USItype)(r)) \
+ : "1" ((USItype)(nh)), \
+ "0" ((USItype)(nl)), \
+ "g" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("bsch/1 %1,%0" \
+ : "=g" (count) \
+ : "g" ((USItype)(x)), \
+ "0" ((USItype)0))
+#endif
+
+
+/***************************************
+ ************** HPPA *****************
+ ***************************************/
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ (" add %4,%5,%1\n" \
+ " addc %2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rM" ((USItype)(ah)), \
+ "rM" ((USItype)(bh)), \
+ "%rM" ((USItype)(al)), \
+ "rM" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ (" sub %4,%5,%1\n" \
+ " subb %2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rM" ((USItype)(ah)), \
+ "rM" ((USItype)(bh)), \
+ "rM" ((USItype)(al)), \
+ "rM" ((USItype)(bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ (" xmpyu %1,%2,%0" \
+ : "=*f" (__xx.__ll) \
+ : "*f" ((USItype)(u)), \
+ "*f" ((USItype)(v))); \
+ (wh) = __xx.__i.__h; \
+ (wl) = __xx.__i.__l; \
+ } while (0)
+#define UMUL_TIME 8
+#define UDIV_TIME 60
+#else
+#define UMUL_TIME 40
+#define UDIV_TIME 80
+#endif
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { USItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern USItype __udiv_qrnnd ();
+#endif /* LONGLONG_STANDALONE */
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __tmp; \
+ __asm__ ( \
+ " ldi 1,%0 \n" \
+ " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \
+ " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \
+ " ldo 16(%0),%0 ; Yes. Perform add. \n" \
+ " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \
+ " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \
+ " ldo 8(%0),%0 ; Yes. Perform add. \n" \
+ " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \
+ " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \
+ " ldo 4(%0),%0 ; Yes. Perform add. \n" \
+ " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \
+ " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \
+ " ldo 2(%0),%0 ; Yes. Perform add. \n" \
+ " extru %1,30,1,%1 ; Extract bit 1. \n" \
+ " sub %0,%1,%0 ; Subtract it. " \
+ : "=r" (count), "=r" (__tmp) : "1" (x)); \
+ } while (0)
+#endif /* hppa */
+
+
+/***************************************
+ ************** I370 *****************
+ ***************************************/
+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mr %0,%3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (__m0), \
+ "r" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define smul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("mr %0,%3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (m0), \
+ "r" (m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ __asm__ ("dr %0,%2" \
+ : "=r" (__xx.__ll) \
+ : "0" (__xx.__ll), "r" (d)); \
+ (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
+ } while (0)
+#endif
+
+
+/***************************************
+ ************** I386 *****************
+ ***************************************/
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addl %5,%1\n" \
+ "adcl %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl %5,%1\n" \
+ "sbbl %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mull %3" \
+ : "=a" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "rm" ((USItype)(v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divl %4" \
+ : "=a" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "rm" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("bsrl %1,%0" \
+ : "=r" (__cbtmp) : "rm" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define count_trailing_zeros(count, x) \
+ __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
+#ifndef UMUL_TIME
+#define UMUL_TIME 40
+#endif
+#ifndef UDIV_TIME
+#define UDIV_TIME 40
+#endif
+#endif /* 80x86 */
+
+
+/***************************************
+ ************** I860 *****************
+ ***************************************/
+#if defined (__i860__) && W_TYPE_SIZE == 32
+#define rshift_rhlc(r,h,l,c) \
+ __asm__ ("shr %3,r0,r0\n" \
+ "shrd %1,%2,%0" \
+ "=r" (r) : "r" (h), "r" (l), "rn" (c))
+#endif /* i860 */
+
+/***************************************
+ ************** I960 *****************
+ ***************************************/
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("cmpo 1,0\n" \
+ "addc %5,%4,%1\n" \
+ "addc %3,%2,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%dI" ((USItype)(ah)), \
+ "dI" ((USItype)(bh)), \
+ "%dI" ((USItype)(al)), \
+ "dI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("cmpo 0,0\n" \
+ "subc %5,%4,%1\n" \
+ "subc %3,%2,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "dI" ((USItype)(ah)), \
+ "dI" ((USItype)(bh)), \
+ "dI" ((USItype)(al)), \
+ "dI" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__xx.__ll) \
+ : "%dI" ((USItype)(u)), \
+ "dI" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__w) \
+ : "%dI" ((USItype)(u)), \
+ "dI" ((USItype)(v))); \
+ __w; })
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __nn; \
+ __nn.__i.__h = (nh); __nn.__i.__l = (nl); \
+ __asm__ ("ediv %d,%n,%0" \
+ : "=d" (__rq.__ll) \
+ : "dI" (__nn.__ll), \
+ "dI" ((USItype)(d))); \
+ (r) = __rq.__i.__l; (q) = __rq.__i.__h; \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("scanbit %1,%0" \
+ : "=r" (__cbtmp) \
+ : "r" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 (-32) /* sic */
+#if defined (__i960mx) /* what is the proper symbol to test??? */
+#define rshift_rhlc(r,h,l,c) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __nn; \
+ __nn.__i.__h = (h); __nn.__i.__l = (l); \
+ __asm__ ("shre %2,%1,%0" \
+ : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \
+ }
+#endif /* i960mx */
+#endif /* i960 */
+
+
+/***************************************
+ ************** 68000 ****************
+ ***************************************/
+#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add%.l %5,%1\n" \
+ "addx%.l %3,%0" \
+ : "=d" ((USItype)(sh)), \
+ "=&d" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "d" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub%.l %5,%1\n" \
+ "subx%.l %3,%0" \
+ : "=d" ((USItype)(sh)), \
+ "=&d" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "d" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mulu%.l %3,%1:%0" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "dmi" ((USItype)(v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divu%.l %4,%1:%0" \
+ : "=d" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "dmi" ((USItype)(d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divs%.l %4,%1:%0" \
+ : "=d" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "dmi" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("bfffo %1{%b2:%b2},%0" \
+ : "=d" ((USItype)(count)) \
+ : "od" ((USItype)(x)), "n" (0))
+#define COUNT_LEADING_ZEROS_0 32
+#else /* not mc68020 */
+#define umul_ppmm(xh, xl, a, b) \
+ do { USItype __umul_tmp1, __umul_tmp2; \
+ __asm__ ("| Inlined umul_ppmm \n" \
+ " move%.l %5,%3 \n" \
+ " move%.l %2,%0 \n" \
+ " move%.w %3,%1 \n" \
+ " swap %3 \n" \
+ " swap %0 \n" \
+ " mulu %2,%1 \n" \
+ " mulu %3,%0 \n" \
+ " mulu %2,%3 \n" \
+ " swap %2 \n" \
+ " mulu %5,%2 \n" \
+ " add%.l %3,%2 \n" \
+ " jcc 1f \n" \
+ " add%.l %#0x10000,%0 \n" \
+ "1: move%.l %2,%3 \n" \
+ " clr%.w %2 \n" \
+ " swap %2 \n" \
+ " swap %3 \n" \
+ " clr%.w %3 \n" \
+ " add%.l %3,%1 \n" \
+ " addx%.l %2,%0 \n" \
+ " | End inlined umul_ppmm" \
+ : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \
+ "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \
+ : "%2" ((USItype)(a)), "d" ((USItype)(b))); \
+ } while (0)
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#endif /* not mc68020 */
+#endif /* mc68000 */
+
+
+/***************************************
+ ************** 88000 ****************
+ ***************************************/
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addu.co %1,%r4,%r5\n" \
+ "addu.ci %0,%r2,%r3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rJ" ((USItype)(ah)), \
+ "rJ" ((USItype)(bh)), \
+ "%rJ" ((USItype)(al)), \
+ "rJ" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subu.co %1,%r4,%r5\n" \
+ "subu.ci %0,%r2,%r3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rJ" ((USItype)(ah)), \
+ "rJ" ((USItype)(bh)), \
+ "rJ" ((USItype)(al)), \
+ "rJ" ((USItype)(bl)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("ff1 %0,%1" \
+ : "=r" (__cbtmp) \
+ : "r" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
+#if defined (__m88110__)
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \
+ (wh) = __x.__i.__h; \
+ (wl) = __x.__i.__l; \
+ } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x, __q; \
+ __x.__i.__h = (n1); __x.__i.__l = (n0); \
+ __asm__ ("divu.d %0,%1,%2" \
+ : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \
+ (r) = (n0) - __q.__l * (d); (q) = __q.__l; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __m88110__ */
+#endif /* __m88000__ */
+
+/***************************************
+ ************** MIPS *****************
+ ***************************************/
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UDItype _r; \
+ _r = (UDItype) u * v; \
+ (w1) = _r >> 32; \
+ (w0) = (USItype) _r; \
+ } while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("multu %2,%3" \
+ : "=l" ((USItype)(w0)), \
+ "=h" ((USItype)(w1)) \
+ : "d" ((USItype)(u)), \
+ "d" ((USItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("multu %2,%3 \n" \
+ "mflo %0 \n" \
+ "mfhi %1" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "d" ((USItype)(u)), \
+ "d" ((USItype)(v)))
+#endif
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+/***************************************
+ ************** MIPS/64 **************
+ ***************************************/
+#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UTItype _r; \
+ _r = (UTItype) u * v; \
+ (w1) = _r >> 64; \
+ (w0) = (UDItype) _r; \
+ } while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("dmultu %2,%3" \
+ : "=l" ((UDItype)(w0)), \
+ "=h" ((UDItype)(w1)) \
+ : "d" ((UDItype)(u)), \
+ "d" ((UDItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("dmultu %2,%3 \n" \
+ "mflo %0 \n" \
+ "mfhi %1" \
+ : "=d" ((UDItype)(w0)), \
+ "=d" ((UDItype)(w1)) \
+ : "d" ((UDItype)(u)), \
+ "d" ((UDItype)(v)))
+#endif
+#define UMUL_TIME 20
+#define UDIV_TIME 140
+#endif /* __mips__ */
+
+
+/***************************************
+ ************** 32000 ****************
+ ***************************************/
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "%0" ((USItype)(u)), \
+ "g" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__w) \
+ : "%0" ((USItype)(u)), \
+ "g" ((USItype)(v))); \
+ __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
+ __asm__ ("deid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "0" (__xx.__ll), \
+ "g" ((USItype)(d))); \
+ (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+ do {
+ __asm__ ("ffsd %2,%0" \
+ : "=r" ((USItype) (count)) \
+ : "0" ((USItype) 0), \
+ "r" ((USItype) (x))); \
+ } while (0)
+#endif /* __ns32000__ */
+
+
+/***************************************
+ ************** PPC ******************
+ ***************************************/
+#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("{cntlz|cntlzw} %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#if defined (_ARCH_PPC)
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhwu %0,%1,%2" \
+ : "=r" ((USItype) ph) \
+ : "%r" (__m0), \
+ "r" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ SItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhw %0,%1,%2" \
+ : "=r" ((SItype) ph) \
+ : "%r" (__m0), \
+ "r" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#else
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mul %0,%2,%3" \
+ : "=r" ((USItype)(xh)), \
+ "=q" ((USItype)(xl)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+ __asm__ ("mul %0,%2,%3" \
+ : "=r" ((SItype)(xh)), \
+ "=q" ((SItype)(xl)) \
+ : "r" (m0), \
+ "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+ __asm__ ("div %0,%2,%4" \
+ : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \
+ : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
+#define UDIV_TIME 100
+#endif
+#endif /* Power architecture variants. */
+
+/* Powerpc 64 bit support taken from gmp-4.1.2. */
+/* We should test _IBMR2 here when we add assembly support for the system
+ vendor compilers. */
+#if 0 /* Not yet enabled because we don't have hardware for a test. */
+#if (defined (_ARCH_PPC) || defined (__powerpc__)) && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" (sh), "=&r" (sl) \
+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
+ } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" (sh), "=&r" (sl) \
+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ DItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14 /* ??? */
+#define UDIV_TIME 120 /* ??? */
+#endif /* 64-bit PowerPC. */
+#endif /* if 0 */
+
+/***************************************
+ ************** PYR ******************
+ ***************************************/
+#if defined (__pyr__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addw %5,%1 \n" \
+ "addwc %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subw %5,%1 \n" \
+ "subwb %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("movw %1,%R0 \n" \
+ "uemul %2,%0" \
+ : "=&r" (__xx.__ll) \
+ : "g" ((USItype) (u)), \
+ "g" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#endif /* __pyr__ */
+
+
+/***************************************
+ ************** RT/ROMP **************
+ ***************************************/
+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("a %1,%5 \n" \
+ "ae %0,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "r" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("s %1,%5\n" \
+ "se %0,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "r" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ( \
+ "s r2,r2 \n" \
+ "mts r10,%2 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "m r2,%3 \n" \
+ "cas %0,r2,r0 \n" \
+ "mfs r10,%1" \
+ : "=r" ((USItype)(ph)), \
+ "=r" ((USItype)(pl)) \
+ : "%r" (__m0), \
+ "r" (__m1) \
+ : "r2"); \
+ (ph) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+ do { \
+ if ((x) >= 0x10000) \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x) >> 16)); \
+ else \
+ { \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x))); \
+ (count) += 16; \
+ } \
+ } while (0)
+#endif /* RT/ROMP */
+
+
+/***************************************
+ ************** SH2 ******************
+ ***************************************/
+#if (defined (__sh2__) || defined(__sh3__) || defined(__SH4__) ) \
+ && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ( \
+ "dmulu.l %2,%3\n" \
+ "sts macl,%1\n" \
+ "sts mach,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)) \
+ : "macl", "mach")
+#define UMUL_TIME 5
+#endif
+
+/***************************************
+ ************** SPARC ****************
+ ***************************************/
+#if defined (__sparc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addcc %r4,%5,%1\n" \
+ "addx %r2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rJ" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%rJ" ((USItype)(al)), \
+ "rI" ((USItype)(bl)) \
+ __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subcc %r4,%5,%1\n" \
+ "subx %r2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rJ" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "rJ" ((USItype)(al)), \
+ "rI" ((USItype)(bl)) \
+ __CLOBBER_CC)
+#if defined (__sparc_v8__)
+/* Don't match immediate range because, 1) it is not often useful,
+ 2) the 'I' flag thinks of the range as a 13 bit signed interval,
+ while we want to match a 13 bit interval, sign extended to 32 bits,
+ but INTERPRETED AS UNSIGNED. */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ USItype __q; \
+ __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \
+ : "=r" ((USItype)(__q)) \
+ : "r" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "r" ((USItype)(d))); \
+ (r) = (n0) - __q * (d); \
+ (q) = __q; \
+ } while (0)
+#define UDIV_TIME 25
+#endif /* SUPERSPARC */
+#else /* ! __sparc_v8__ */
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide. It also has two additional
+ instructions scan (ffs from high bit) and divscc. */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("! Inlined udiv_qrnnd \n" \
+ " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \
+ " tst %%g0 \n" \
+ " divscc %3,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%%g1 \n" \
+ " divscc %%g1,%4,%0 \n" \
+ " rd %%y,%1 \n" \
+ " bl,a 1f \n" \
+ " add %1,%4,%1 \n" \
+ "1: ! End of inline udiv_qrnnd" \
+ : "=r" ((USItype)(q)), \
+ "=r" ((USItype)(r)) \
+ : "r" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "rI" ((USItype)(d)) \
+ : "%g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+ __asm__ ("scan %1,0,%0" \
+ : "=r" ((USItype)(x)) \
+ : "r" ((USItype)(count)))
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+ implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0
+ undefined. */
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */
+#ifndef umul_ppmm
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("! Inlined umul_ppmm \n" \
+ " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \
+ " sra %3,31,%%g2 ! Don't move this insn \n" \
+ " and %2,%%g2,%%g2 ! Don't move this insn \n" \
+ " andcc %%g0,0,%%g1 ! Don't move this insn \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,%3,%%g1 \n" \
+ " mulscc %%g1,0,%%g1 \n" \
+ " add %%g1,%%g2,%0 \n" \
+ " rd %%y,%1" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "%rI" ((USItype)(u)), \
+ "r" ((USItype)(v)) \
+ : "%g1", "%g2" __AND_CLOBBER_CC)
+#define UMUL_TIME 39 /* 39 instructions */
+#endif
+#ifndef udiv_qrnnd
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { USItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern USItype __udiv_qrnnd ();
+#define UDIV_TIME 140
+#endif /* LONGLONG_STANDALONE */
+#endif /* udiv_qrnnd */
+#endif /* __sparc__ */
+
+
+/***************************************
+ ************** VAX ******************
+ ***************************************/
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addl2 %5,%1\n" \
+ "adwc %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl2 %5,%1\n" \
+ "sbwc %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("emul %1,%2,$0,%0" \
+ : "=g" (__xx.__ll) \
+ : "g" (__m0), \
+ "g" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {SItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ __asm__ ("ediv %3,%2,%0,%1" \
+ : "=g" (q), "=g" (r) \
+ : "g" (__xx.__ll), "g" (d)); \
+ } while (0)
+#endif /* __vax__ */
+
+
+/***************************************
+ ************** Z8000 ****************
+ ***************************************/
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "%0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "%1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {long int __ll; \
+ struct {unsigned int __h, __l;} __i; \
+ } __xx; \
+ unsigned int __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mult %S0,%H3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (__m0), \
+ "rQR" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((signed int) __m0 >> 15) & __m1) \
+ + (((signed int) __m1 >> 15) & __m0)); \
+ } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+#endif /* !__riscos__ */
+
+
+/***************************************
+ *********** Generic Versions ********
+ ***************************************/
+#if !defined (umul_ppmm) && defined (__umulsidi3)
+#define umul_ppmm(ph, pl, m0, m1) \
+ { \
+ UDWtype __ll = __umulsidi3 (m0, m1); \
+ ph = (UWtype) (__ll >> W_TYPE_SIZE); \
+ pl = (UWtype) __ll; \
+ }
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+ ({UWtype __hi, __lo; \
+ umul_ppmm (__hi, __lo, u, v); \
+ ((UDWtype) __hi << W_TYPE_SIZE) | __lo; })
+#endif
+
+/* If this machine has no inline assembler, use C macros. */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __x0, __x1, __x2, __x3; \
+ UHWtype __ul, __vl, __uh, __vh; \
+ UWtype __u = (u), __v = (v); \
+ \
+ __ul = __ll_lowpart (__u); \
+ __uh = __ll_highpart (__u); \
+ __vl = __ll_lowpart (__v); \
+ __vh = __ll_highpart (__v); \
+ \
+ __x0 = (UWtype) __ul * __vl; \
+ __x1 = (UWtype) __ul * __vh; \
+ __x2 = (UWtype) __uh * __vl; \
+ __x3 = (UWtype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\
+ } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define smul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __w1; \
+ UWtype __m0 = (u), __m1 = (v); \
+ umul_ppmm (__w1, w0, __m0, __m1); \
+ (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \
+ - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \
+ } while (0)
+#endif
+
+/* Define this unconditionally, so it can be used for debugging. */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+ __udiv_w_sdiv (defined in libgcc or elsewhere). */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ UWtype __r; \
+ (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \
+ (r) = __r; \
+ } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#if !defined (count_leading_zeros)
+extern
+#ifdef __STDC__
+const
+#endif
+unsigned char _gcry_clz_tab[];
+#define MPI_INTERNAL_NEED_CLZ_TAB 1
+#define count_leading_zeros(count, x) \
+ do { \
+ UWtype __xr = (x); \
+ UWtype __a; \
+ \
+ if (W_TYPE_SIZE <= 32) \
+ { \
+ __a = __xr < ((UWtype) 1 << 2*__BITS4) \
+ ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \
+ : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\
+ } \
+ else \
+ { \
+ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
+ if (((__xr >> __a) & 0xff) != 0) \
+ break; \
+ } \
+ \
+ (count) = W_TYPE_SIZE - (_gcry_clz_tab[__xr >> __a] + __a); \
+ } while (0)
+/* This version gives a well-defined value for zero. */
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros. The latter might be
+ defined in asm, but if it is not, the C version above is good enough. */
+#define count_trailing_zeros(count, x) \
+ do { \
+ UWtype __ctz_x = (x); \
+ UWtype __ctz_c; \
+ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
+ (count) = W_TYPE_SIZE - 1 - __ctz_c; \
+ } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/libgcrypt-1.4.6/mpi/mpi-bit.c b/libgcrypt-1.4.6/mpi/mpi-bit.c
index 32c820c..6c59fc0 100644
--- a/libgcrypt-1.4.6/mpi/mpi-bit.c
+++ b/libgcrypt-1.4.6/mpi/mpi-bit.c
@@ -1,365 +1,365 @@
-/* mpi-bit.c - MPI bit level fucntions
- * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "mpi-internal.h"
-#include "longlong.h"
-
-
-#ifdef MPI_INTERNAL_NEED_CLZ_TAB
-#ifdef __STDC__
-const
-#endif
-unsigned char
-_gcry_clz_tab[] =
-{
- 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-};
-#endif
-
-
-#define A_LIMB_1 ((mpi_limb_t)1)
-
-
-/****************
- * Sometimes we have MSL (most significant limbs) which are 0;
- * this is for some reasons not good, so this function removes them.
- */
-void
-_gcry_mpi_normalize( gcry_mpi_t a )
-{
- if( mpi_is_opaque(a) )
- return;
-
- for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
- ;
-}
-
-
-
-/****************
- * Return the number of bits in A.
- */
-unsigned int
-gcry_mpi_get_nbits( gcry_mpi_t a )
-{
- unsigned n;
-
- if( mpi_is_opaque(a) ) {
- return a->sign; /* which holds the number of bits */
- }
-
- _gcry_mpi_normalize( a );
- if( a->nlimbs ) {
- mpi_limb_t alimb = a->d[a->nlimbs-1];
- if( alimb )
- count_leading_zeros( n, alimb );
- else
- n = BITS_PER_MPI_LIMB;
- n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
- }
- else
- n = 0;
- return n;
-}
-
-
-/****************
- * Test whether bit N is set.
- */
-int
-gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n )
-{
- unsigned int limbno, bitno;
- mpi_limb_t limb;
-
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
-
- if( limbno >= a->nlimbs )
- return 0; /* too far left: this is a 0 */
- limb = a->d[limbno];
- return (limb & (A_LIMB_1 << bitno))? 1: 0;
-}
-
-
-/****************
- * Set bit N of A.
- */
-void
-gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
-{
- unsigned int limbno, bitno;
-
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
-
- if ( limbno >= a->nlimbs )
- {
- mpi_resize (a, limbno+1 );
- a->nlimbs = limbno+1;
- }
- a->d[limbno] |= (A_LIMB_1<<bitno);
-}
-
-/****************
- * Set bit N of A. and clear all bits above
- */
-void
-gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
-{
- unsigned int limbno, bitno;
-
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
-
- if ( limbno >= a->nlimbs )
- {
- mpi_resize (a, limbno+1 );
- a->nlimbs = limbno+1;
- }
- a->d[limbno] |= (A_LIMB_1<<bitno);
- for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
- a->d[limbno] &= ~(A_LIMB_1 << bitno);
- a->nlimbs = limbno+1;
-}
-
-/****************
- * clear bit N of A and all bits above
- */
-void
-gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
-{
- unsigned int limbno, bitno;
-
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
-
- if( limbno >= a->nlimbs )
- return; /* not allocated, therefore no need to clear bits
- :-) */
-
- for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
- a->d[limbno] &= ~(A_LIMB_1 << bitno);
- a->nlimbs = limbno+1;
-}
-
-/****************
- * Clear bit N of A.
- */
-void
-gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
-{
- unsigned int limbno, bitno;
-
- limbno = n / BITS_PER_MPI_LIMB;
- bitno = n % BITS_PER_MPI_LIMB;
-
- if( limbno >= a->nlimbs )
- return; /* don't need to clear this bit, it's to far to left */
- a->d[limbno] &= ~(A_LIMB_1 << bitno);
-}
-
-
-/****************
- * Shift A by COUNT limbs to the right
- * This is used only within the MPI library
- */
-void
-_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count )
-{
- mpi_ptr_t ap = a->d;
- mpi_size_t n = a->nlimbs;
- unsigned int i;
-
- if( count >= n ) {
- a->nlimbs = 0;
- return;
- }
-
- for( i = 0; i < n - count; i++ )
- ap[i] = ap[i+count];
- ap[i] = 0;
- a->nlimbs -= count;
-}
-
-
-/*
- * Shift A by N bits to the right.
- */
-void
-gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
-{
- mpi_size_t xsize;
- unsigned int i;
- unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
- unsigned int nbits = (n%BITS_PER_MPI_LIMB);
-
- if ( x == a )
- {
- /* In-place operation. */
- if ( nlimbs >= x->nlimbs )
- {
- x->nlimbs = 0;
- return;
- }
-
- if (nlimbs)
- {
- for (i=0; i < x->nlimbs - nlimbs; i++ )
- x->d[i] = x->d[i+nlimbs];
- x->d[i] = 0;
- x->nlimbs -= nlimbs;
-
- }
- if ( x->nlimbs && nbits )
- _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
- }
- else if ( nlimbs )
- {
- /* Copy and shift by more or equal bits than in a limb. */
- xsize = a->nlimbs;
- x->sign = a->sign;
- RESIZE_IF_NEEDED (x, xsize);
- x->nlimbs = xsize;
- for (i=0; i < a->nlimbs; i++ )
- x->d[i] = a->d[i];
- x->nlimbs = i;
-
- if ( nlimbs >= x->nlimbs )
- {
- x->nlimbs = 0;
- return;
- }
-
- if (nlimbs)
- {
- for (i=0; i < x->nlimbs - nlimbs; i++ )
- x->d[i] = x->d[i+nlimbs];
- x->d[i] = 0;
- x->nlimbs -= nlimbs;
- }
-
- if ( x->nlimbs && nbits )
- _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
- }
- else
- {
- /* Copy and shift by less than bits in a limb. */
- xsize = a->nlimbs;
- x->sign = a->sign;
- RESIZE_IF_NEEDED (x, xsize);
- x->nlimbs = xsize;
-
- if ( xsize )
- {
- if (nbits )
- _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits );
- else
- {
- /* The rshift helper function is not specified for
- NBITS==0, thus we do a plain copy here. */
- for (i=0; i < x->nlimbs; i++ )
- x->d[i] = a->d[i];
- }
- }
- }
- MPN_NORMALIZE (x->d, x->nlimbs);
-}
-
-
-/****************
- * Shift A by COUNT limbs to the left
- * This is used only within the MPI library
- */
-void
-_gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count)
-{
- mpi_ptr_t ap;
- int n = a->nlimbs;
- int i;
-
- if (!count || !n)
- return;
-
- RESIZE_IF_NEEDED (a, n+count);
-
- ap = a->d;
- for (i = n-1; i >= 0; i--)
- ap[i+count] = ap[i];
- for (i=0; i < count; i++ )
- ap[i] = 0;
- a->nlimbs += count;
-}
-
-
-/*
- * Shift A by N bits to the left.
- */
-void
-gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
-{
- unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
- unsigned int nbits = (n%BITS_PER_MPI_LIMB);
-
- if (x == a && !n)
- return; /* In-place shift with an amount of zero. */
-
- if ( x != a )
- {
- /* Copy A to X. */
- unsigned int alimbs = a->nlimbs;
- int asign = a->sign;
- mpi_ptr_t xp, ap;
-
- RESIZE_IF_NEEDED (x, alimbs+nlimbs+1);
- xp = x->d;
- ap = a->d;
- MPN_COPY (xp, ap, alimbs);
- x->nlimbs = alimbs;
- x->flags = a->flags;
- x->sign = asign;
- }
-
- if (nlimbs && !nbits)
- {
- /* Shift a full number of limbs. */
- _gcry_mpi_lshift_limbs (x, nlimbs);
- }
- else if (n)
- {
- /* We use a very dump approach: Shift left by the number of
- limbs plus one and than fix it up by an rshift. */
- _gcry_mpi_lshift_limbs (x, nlimbs+1);
- gcry_mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits);
- }
-
- MPN_NORMALIZE (x->d, x->nlimbs);
-}
-
+/* mpi-bit.c - MPI bit level functions
+ * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+#ifdef MPI_INTERNAL_NEED_CLZ_TAB
+#ifdef __STDC__
+const
+#endif
+unsigned char
+_gcry_clz_tab[] =
+{
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+#endif
+
+
+#define A_LIMB_1 ((mpi_limb_t)1)
+
+
+/****************
+ * Sometimes we have MSL (most significant limbs) which are 0;
+ * this is for some reasons not good, so this function removes them.
+ */
+void
+_gcry_mpi_normalize( gcry_mpi_t a )
+{
+ if( mpi_is_opaque(a) )
+ return;
+
+ for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
+ ;
+}
+
+
+
+/****************
+ * Return the number of bits in A.
+ */
+unsigned int
+gcry_mpi_get_nbits( gcry_mpi_t a )
+{
+ unsigned n;
+
+ if( mpi_is_opaque(a) ) {
+ return a->sign; /* which holds the number of bits */
+ }
+
+ _gcry_mpi_normalize( a );
+ if( a->nlimbs ) {
+ mpi_limb_t alimb = a->d[a->nlimbs-1];
+ if( alimb )
+ count_leading_zeros( n, alimb );
+ else
+ n = BITS_PER_MPI_LIMB;
+ n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
+ }
+ else
+ n = 0;
+ return n;
+}
+
+
+/****************
+ * Test whether bit N is set.
+ */
+int
+gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n )
+{
+ unsigned int limbno, bitno;
+ mpi_limb_t limb;
+
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if( limbno >= a->nlimbs )
+ return 0; /* too far left: this is a 0 */
+ limb = a->d[limbno];
+ return (limb & (A_LIMB_1 << bitno))? 1: 0;
+}
+
+
+/****************
+ * Set bit N of A.
+ */
+void
+gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
+{
+ unsigned int limbno, bitno;
+
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if ( limbno >= a->nlimbs )
+ {
+ mpi_resize (a, limbno+1 );
+ a->nlimbs = limbno+1;
+ }
+ a->d[limbno] |= (A_LIMB_1<<bitno);
+}
+
+/****************
+ * Set bit N of A. and clear all bits above
+ */
+void
+gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
+{
+ unsigned int limbno, bitno;
+
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if ( limbno >= a->nlimbs )
+ {
+ mpi_resize (a, limbno+1 );
+ a->nlimbs = limbno+1;
+ }
+ a->d[limbno] |= (A_LIMB_1<<bitno);
+ for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
+ a->d[limbno] &= ~(A_LIMB_1 << bitno);
+ a->nlimbs = limbno+1;
+}
+
+/****************
+ * clear bit N of A and all bits above
+ */
+void
+gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
+{
+ unsigned int limbno, bitno;
+
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if( limbno >= a->nlimbs )
+ return; /* not allocated, therefore no need to clear bits
+ :-) */
+
+ for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+ a->d[limbno] &= ~(A_LIMB_1 << bitno);
+ a->nlimbs = limbno+1;
+}
+
+/****************
+ * Clear bit N of A.
+ */
+void
+gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
+{
+ unsigned int limbno, bitno;
+
+ limbno = n / BITS_PER_MPI_LIMB;
+ bitno = n % BITS_PER_MPI_LIMB;
+
+ if( limbno >= a->nlimbs )
+ return; /* don't need to clear this bit, it's to far to left */
+ a->d[limbno] &= ~(A_LIMB_1 << bitno);
+}
+
+
+/****************
+ * Shift A by COUNT limbs to the right
+ * This is used only within the MPI library
+ */
+void
+_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count )
+{
+ mpi_ptr_t ap = a->d;
+ mpi_size_t n = a->nlimbs;
+ unsigned int i;
+
+ if( count >= n ) {
+ a->nlimbs = 0;
+ return;
+ }
+
+ for( i = 0; i < n - count; i++ )
+ ap[i] = ap[i+count];
+ ap[i] = 0;
+ a->nlimbs -= count;
+}
+
+
+/*
+ * Shift A by N bits to the right.
+ */
+void
+gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
+{
+ mpi_size_t xsize;
+ unsigned int i;
+ unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
+ unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+
+ if ( x == a )
+ {
+ /* In-place operation. */
+ if ( nlimbs >= x->nlimbs )
+ {
+ x->nlimbs = 0;
+ return;
+ }
+
+ if (nlimbs)
+ {
+ for (i=0; i < x->nlimbs - nlimbs; i++ )
+ x->d[i] = x->d[i+nlimbs];
+ x->d[i] = 0;
+ x->nlimbs -= nlimbs;
+
+ }
+ if ( x->nlimbs && nbits )
+ _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
+ }
+ else if ( nlimbs )
+ {
+ /* Copy and shift by more or equal bits than in a limb. */
+ xsize = a->nlimbs;
+ x->sign = a->sign;
+ RESIZE_IF_NEEDED (x, xsize);
+ x->nlimbs = xsize;
+ for (i=0; i < a->nlimbs; i++ )
+ x->d[i] = a->d[i];
+ x->nlimbs = i;
+
+ if ( nlimbs >= x->nlimbs )
+ {
+ x->nlimbs = 0;
+ return;
+ }
+
+ if (nlimbs)
+ {
+ for (i=0; i < x->nlimbs - nlimbs; i++ )
+ x->d[i] = x->d[i+nlimbs];
+ x->d[i] = 0;
+ x->nlimbs -= nlimbs;
+ }
+
+ if ( x->nlimbs && nbits )
+ _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
+ }
+ else
+ {
+ /* Copy and shift by less than bits in a limb. */
+ xsize = a->nlimbs;
+ x->sign = a->sign;
+ RESIZE_IF_NEEDED (x, xsize);
+ x->nlimbs = xsize;
+
+ if ( xsize )
+ {
+ if (nbits )
+ _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits );
+ else
+ {
+ /* The rshift helper function is not specified for
+ NBITS==0, thus we do a plain copy here. */
+ for (i=0; i < x->nlimbs; i++ )
+ x->d[i] = a->d[i];
+ }
+ }
+ }
+ MPN_NORMALIZE (x->d, x->nlimbs);
+}
+
+
+/****************
+ * Shift A by COUNT limbs to the left
+ * This is used only within the MPI library
+ */
+void
+_gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count)
+{
+ mpi_ptr_t ap;
+ int n = a->nlimbs;
+ int i;
+
+ if (!count || !n)
+ return;
+
+ RESIZE_IF_NEEDED (a, n+count);
+
+ ap = a->d;
+ for (i = n-1; i >= 0; i--)
+ ap[i+count] = ap[i];
+ for (i=0; i < count; i++ )
+ ap[i] = 0;
+ a->nlimbs += count;
+}
+
+
+/*
+ * Shift A by N bits to the left.
+ */
+void
+gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
+{
+ unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
+ unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+
+ if (x == a && !n)
+ return; /* In-place shift with an amount of zero. */
+
+ if ( x != a )
+ {
+ /* Copy A to X. */
+ unsigned int alimbs = a->nlimbs;
+ int asign = a->sign;
+ mpi_ptr_t xp, ap;
+
+ RESIZE_IF_NEEDED (x, alimbs+nlimbs+1);
+ xp = x->d;
+ ap = a->d;
+ MPN_COPY (xp, ap, alimbs);
+ x->nlimbs = alimbs;
+ x->flags = a->flags;
+ x->sign = asign;
+ }
+
+ if (nlimbs && !nbits)
+ {
+ /* Shift a full number of limbs. */
+ _gcry_mpi_lshift_limbs (x, nlimbs);
+ }
+ else if (n)
+ {
+ /* We use a very dump approach: Shift left by the number of
+ limbs plus one and than fix it up by an rshift. */
+ _gcry_mpi_lshift_limbs (x, nlimbs+1);
+ gcry_mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits);
+ }
+
+ MPN_NORMALIZE (x->d, x->nlimbs);
+}
+
diff --git a/libgcrypt-1.4.6/mpi/mpi-div.c b/libgcrypt-1.4.6/mpi/mpi-div.c
index 0d8a2d1..e94e531 100644
--- a/libgcrypt-1.4.6/mpi/mpi-div.c
+++ b/libgcrypt-1.4.6/mpi/mpi-div.c
@@ -1,358 +1,358 @@
-/* mpi-div.c - MPI functions
- * Copyright (C) 1994, 1996, 1998, 2001, 2002,
- * 2003 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- * Actually it's the same code with only minor changes in the
- * way the data is stored; this is to support the abstraction
- * of an optional secure memory allocation which may be used
- * to avoid revealing of sensitive data due to paging etc.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "mpi-internal.h"
-#include "longlong.h"
-#include "g10lib.h"
-
-
-void
-_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
-{
- int divisor_sign = divisor->sign;
- gcry_mpi_t temp_divisor = NULL;
-
- /* We need the original value of the divisor after the remainder has been
- * preliminary calculated. We have to copy it to temporary space if it's
- * the same variable as REM. */
- if( rem == divisor ) {
- temp_divisor = mpi_copy( divisor );
- divisor = temp_divisor;
- }
-
- _gcry_mpi_tdiv_r( rem, dividend, divisor );
-
- if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
- gcry_mpi_add( rem, rem, divisor);
-
- if( temp_divisor )
- mpi_free(temp_divisor);
-}
-
-
-
-/****************
- * Division rounding the quotient towards -infinity.
- * The remainder gets the same sign as the denominator.
- * rem is optional
- */
-
-ulong
-_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
-{
- mpi_limb_t rlimb;
-
- rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
- if( rlimb && dividend->sign )
- rlimb = divisor - rlimb;
-
- if( rem ) {
- rem->d[0] = rlimb;
- rem->nlimbs = rlimb? 1:0;
- }
- return rlimb;
-}
-
-
-void
-_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor )
-{
- gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
- _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
- mpi_free(tmp);
-}
-
-void
-_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
-{
- int divisor_sign = divisor->sign;
- gcry_mpi_t temp_divisor = NULL;
-
- if( quot == divisor || rem == divisor ) {
- temp_divisor = mpi_copy( divisor );
- divisor = temp_divisor;
- }
-
- _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
-
- if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
- gcry_mpi_sub_ui( quot, quot, 1 );
- gcry_mpi_add( rem, rem, divisor);
- }
-
- if( temp_divisor )
- mpi_free(temp_divisor);
-}
-
-
-/* If den == quot, den needs temporary storage.
- * If den == rem, den needs temporary storage.
- * If num == quot, num needs temporary storage.
- * If den has temporary storage, it can be normalized while being copied,
- * i.e no extra storage should be allocated.
- */
-
-void
-_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
-{
- _gcry_mpi_tdiv_qr(NULL, rem, num, den );
-}
-
-void
-_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
-{
- mpi_ptr_t np, dp;
- mpi_ptr_t qp, rp;
- mpi_size_t nsize = num->nlimbs;
- mpi_size_t dsize = den->nlimbs;
- mpi_size_t qsize, rsize;
- mpi_size_t sign_remainder = num->sign;
- mpi_size_t sign_quotient = num->sign ^ den->sign;
- unsigned normalization_steps;
- mpi_limb_t q_limb;
- mpi_ptr_t marker[5];
- unsigned int marker_nlimbs[5];
- int markidx=0;
-
- /* Ensure space is enough for quotient and remainder.
- * We need space for an extra limb in the remainder, because it's
- * up-shifted (normalized) below. */
- rsize = nsize + 1;
- mpi_resize( rem, rsize);
-
- qsize = rsize - dsize; /* qsize cannot be bigger than this. */
- if( qsize <= 0 ) {
- if( num != rem ) {
- rem->nlimbs = num->nlimbs;
- rem->sign = num->sign;
- MPN_COPY(rem->d, num->d, nsize);
- }
- if( quot ) {
- /* This needs to follow the assignment to rem, in case the
- * numerator and quotient are the same. */
- quot->nlimbs = 0;
- quot->sign = 0;
- }
- return;
- }
-
- if( quot )
- mpi_resize( quot, qsize);
-
- /* Read pointers here, when reallocation is finished. */
- np = num->d;
- dp = den->d;
- rp = rem->d;
-
- /* Optimize division by a single-limb divisor. */
- if( dsize == 1 ) {
- mpi_limb_t rlimb;
- if( quot ) {
- qp = quot->d;
- rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] );
- qsize -= qp[qsize - 1] == 0;
- quot->nlimbs = qsize;
- quot->sign = sign_quotient;
- }
- else
- rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] );
- rp[0] = rlimb;
- rsize = rlimb != 0?1:0;
- rem->nlimbs = rsize;
- rem->sign = sign_remainder;
- return;
- }
-
-
- if( quot ) {
- qp = quot->d;
- /* Make sure QP and NP point to different objects. Otherwise the
- * numerator would be gradually overwritten by the quotient limbs. */
- if(qp == np) { /* Copy NP object to temporary space. */
- marker_nlimbs[markidx] = nsize;
- np = marker[markidx++] = mpi_alloc_limb_space(nsize,
- mpi_is_secure(quot));
- MPN_COPY(np, qp, nsize);
- }
- }
- else /* Put quotient at top of remainder. */
- qp = rp + dsize;
-
- count_leading_zeros( normalization_steps, dp[dsize - 1] );
-
- /* Normalize the denominator, i.e. make its most significant bit set by
- * shifting it NORMALIZATION_STEPS bits to the left. Also shift the
- * numerator the same number of steps (to keep the quotient the same!).
- */
- if( normalization_steps ) {
- mpi_ptr_t tp;
- mpi_limb_t nlimb;
-
- /* Shift up the denominator setting the most significant bit of
- * the most significant word. Use temporary storage not to clobber
- * the original contents of the denominator. */
- marker_nlimbs[markidx] = dsize;
- tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
- _gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
- dp = tp;
-
- /* Shift up the numerator, possibly introducing a new most
- * significant word. Move the shifted numerator in the remainder
- * meanwhile. */
- nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps);
- if( nlimb ) {
- rp[nsize] = nlimb;
- rsize = nsize + 1;
- }
- else
- rsize = nsize;
- }
- else {
- /* The denominator is already normalized, as required. Copy it to
- * temporary space if it overlaps with the quotient or remainder. */
- if( dp == rp || (quot && (dp == qp))) {
- mpi_ptr_t tp;
-
- marker_nlimbs[markidx] = dsize;
- tp = marker[markidx++] = mpi_alloc_limb_space(dsize,
- mpi_is_secure(den));
- MPN_COPY( tp, dp, dsize );
- dp = tp;
- }
-
- /* Move the numerator to the remainder. */
- if( rp != np )
- MPN_COPY(rp, np, nsize);
-
- rsize = nsize;
- }
-
- q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize );
-
- if( quot ) {
- qsize = rsize - dsize;
- if(q_limb) {
- qp[qsize] = q_limb;
- qsize += 1;
- }
-
- quot->nlimbs = qsize;
- quot->sign = sign_quotient;
- }
-
- rsize = dsize;
- MPN_NORMALIZE (rp, rsize);
-
- if( normalization_steps && rsize ) {
- _gcry_mpih_rshift(rp, rp, rsize, normalization_steps);
- rsize -= rp[rsize - 1] == 0?1:0;
- }
-
- rem->nlimbs = rsize;
- rem->sign = sign_remainder;
- while( markidx )
- {
- markidx--;
- _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]);
- }
-}
-
-void
-_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
-{
- mpi_size_t usize, wsize;
- mpi_size_t limb_cnt;
-
- usize = u->nlimbs;
- limb_cnt = count / BITS_PER_MPI_LIMB;
- wsize = usize - limb_cnt;
- if( limb_cnt >= usize )
- w->nlimbs = 0;
- else {
- mpi_ptr_t wp;
- mpi_ptr_t up;
-
- RESIZE_IF_NEEDED( w, wsize );
- wp = w->d;
- up = u->d;
-
- count %= BITS_PER_MPI_LIMB;
- if( count ) {
- _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count );
- wsize -= !wp[wsize - 1];
- }
- else {
- MPN_COPY_INCR( wp, up + limb_cnt, wsize);
- }
-
- w->nlimbs = wsize;
- }
-}
-
-/****************
- * Check whether dividend is divisible by divisor
- * (note: divisor must fit into a limb)
- */
-int
-_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
-{
- return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
-}
-
-
-void
-gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor, int round)
-{
- if (!round)
- {
- if (!rem)
- {
- gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot));
- _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor);
- mpi_free (tmp);
- }
- else
- _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor);
- }
- else if (round < 0)
- {
- if (!rem)
- _gcry_mpi_fdiv_q (quot, dividend, divisor);
- else if (!quot)
- _gcry_mpi_fdiv_r (rem, dividend, divisor);
- else
- _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor);
- }
- else
- log_bug ("mpi rounding to ceiling not yet implemented\n");
-}
-
-
-
+/* mpi-div.c - MPI functions
+ * Copyright (C) 1994, 1996, 1998, 2001, 2002,
+ * 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ * Actually it's the same code with only minor changes in the
+ * way the data is stored; this is to support the abstraction
+ * of an optional secure memory allocation which may be used
+ * to avoid revealing of sensitive data due to paging etc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+#include "g10lib.h"
+
+
+void
+_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
+{
+ int divisor_sign = divisor->sign;
+ gcry_mpi_t temp_divisor = NULL;
+
+ /* We need the original value of the divisor after the remainder has been
+ * preliminary calculated. We have to copy it to temporary space if it's
+ * the same variable as REM. */
+ if( rem == divisor ) {
+ temp_divisor = mpi_copy( divisor );
+ divisor = temp_divisor;
+ }
+
+ _gcry_mpi_tdiv_r( rem, dividend, divisor );
+
+ if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
+ gcry_mpi_add( rem, rem, divisor);
+
+ if( temp_divisor )
+ mpi_free(temp_divisor);
+}
+
+
+
+/****************
+ * Division rounding the quotient towards -infinity.
+ * The remainder gets the same sign as the denominator.
+ * rem is optional
+ */
+
+ulong
+_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
+{
+ mpi_limb_t rlimb;
+
+ rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
+ if( rlimb && dividend->sign )
+ rlimb = divisor - rlimb;
+
+ if( rem ) {
+ rem->d[0] = rlimb;
+ rem->nlimbs = rlimb? 1:0;
+ }
+ return rlimb;
+}
+
+
+void
+_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor )
+{
+ gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
+ _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
+ mpi_free(tmp);
+}
+
+void
+_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
+{
+ int divisor_sign = divisor->sign;
+ gcry_mpi_t temp_divisor = NULL;
+
+ if( quot == divisor || rem == divisor ) {
+ temp_divisor = mpi_copy( divisor );
+ divisor = temp_divisor;
+ }
+
+ _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
+
+ if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
+ gcry_mpi_sub_ui( quot, quot, 1 );
+ gcry_mpi_add( rem, rem, divisor);
+ }
+
+ if( temp_divisor )
+ mpi_free(temp_divisor);
+}
+
+
+/* If den == quot, den needs temporary storage.
+ * If den == rem, den needs temporary storage.
+ * If num == quot, num needs temporary storage.
+ * If den has temporary storage, it can be normalized while being copied,
+ * i.e no extra storage should be allocated.
+ */
+
+void
+_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
+{
+ _gcry_mpi_tdiv_qr(NULL, rem, num, den );
+}
+
+void
+_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
+{
+ mpi_ptr_t np, dp;
+ mpi_ptr_t qp, rp;
+ mpi_size_t nsize = num->nlimbs;
+ mpi_size_t dsize = den->nlimbs;
+ mpi_size_t qsize, rsize;
+ mpi_size_t sign_remainder = num->sign;
+ mpi_size_t sign_quotient = num->sign ^ den->sign;
+ unsigned normalization_steps;
+ mpi_limb_t q_limb;
+ mpi_ptr_t marker[5];
+ unsigned int marker_nlimbs[5];
+ int markidx=0;
+
+ /* Ensure space is enough for quotient and remainder.
+ * We need space for an extra limb in the remainder, because it's
+ * up-shifted (normalized) below. */
+ rsize = nsize + 1;
+ mpi_resize( rem, rsize);
+
+ qsize = rsize - dsize; /* qsize cannot be bigger than this. */
+ if( qsize <= 0 ) {
+ if( num != rem ) {
+ rem->nlimbs = num->nlimbs;
+ rem->sign = num->sign;
+ MPN_COPY(rem->d, num->d, nsize);
+ }
+ if( quot ) {
+ /* This needs to follow the assignment to rem, in case the
+ * numerator and quotient are the same. */
+ quot->nlimbs = 0;
+ quot->sign = 0;
+ }
+ return;
+ }
+
+ if( quot )
+ mpi_resize( quot, qsize);
+
+ /* Read pointers here, when reallocation is finished. */
+ np = num->d;
+ dp = den->d;
+ rp = rem->d;
+
+ /* Optimize division by a single-limb divisor. */
+ if( dsize == 1 ) {
+ mpi_limb_t rlimb;
+ if( quot ) {
+ qp = quot->d;
+ rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] );
+ qsize -= qp[qsize - 1] == 0;
+ quot->nlimbs = qsize;
+ quot->sign = sign_quotient;
+ }
+ else
+ rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] );
+ rp[0] = rlimb;
+ rsize = rlimb != 0?1:0;
+ rem->nlimbs = rsize;
+ rem->sign = sign_remainder;
+ return;
+ }
+
+
+ if( quot ) {
+ qp = quot->d;
+ /* Make sure QP and NP point to different objects. Otherwise the
+ * numerator would be gradually overwritten by the quotient limbs. */
+ if(qp == np) { /* Copy NP object to temporary space. */
+ marker_nlimbs[markidx] = nsize;
+ np = marker[markidx++] = mpi_alloc_limb_space(nsize,
+ mpi_is_secure(quot));
+ MPN_COPY(np, qp, nsize);
+ }
+ }
+ else /* Put quotient at top of remainder. */
+ qp = rp + dsize;
+
+ count_leading_zeros( normalization_steps, dp[dsize - 1] );
+
+ /* Normalize the denominator, i.e. make its most significant bit set by
+ * shifting it NORMALIZATION_STEPS bits to the left. Also shift the
+ * numerator the same number of steps (to keep the quotient the same!).
+ */
+ if( normalization_steps ) {
+ mpi_ptr_t tp;
+ mpi_limb_t nlimb;
+
+ /* Shift up the denominator setting the most significant bit of
+ * the most significant word. Use temporary storage not to clobber
+ * the original contents of the denominator. */
+ marker_nlimbs[markidx] = dsize;
+ tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
+ _gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
+ dp = tp;
+
+ /* Shift up the numerator, possibly introducing a new most
+ * significant word. Move the shifted numerator in the remainder
+ * meanwhile. */
+ nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps);
+ if( nlimb ) {
+ rp[nsize] = nlimb;
+ rsize = nsize + 1;
+ }
+ else
+ rsize = nsize;
+ }
+ else {
+ /* The denominator is already normalized, as required. Copy it to
+ * temporary space if it overlaps with the quotient or remainder. */
+ if( dp == rp || (quot && (dp == qp))) {
+ mpi_ptr_t tp;
+
+ marker_nlimbs[markidx] = dsize;
+ tp = marker[markidx++] = mpi_alloc_limb_space(dsize,
+ mpi_is_secure(den));
+ MPN_COPY( tp, dp, dsize );
+ dp = tp;
+ }
+
+ /* Move the numerator to the remainder. */
+ if( rp != np )
+ MPN_COPY(rp, np, nsize);
+
+ rsize = nsize;
+ }
+
+ q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize );
+
+ if( quot ) {
+ qsize = rsize - dsize;
+ if(q_limb) {
+ qp[qsize] = q_limb;
+ qsize += 1;
+ }
+
+ quot->nlimbs = qsize;
+ quot->sign = sign_quotient;
+ }
+
+ rsize = dsize;
+ MPN_NORMALIZE (rp, rsize);
+
+ if( normalization_steps && rsize ) {
+ _gcry_mpih_rshift(rp, rp, rsize, normalization_steps);
+ rsize -= rp[rsize - 1] == 0?1:0;
+ }
+
+ rem->nlimbs = rsize;
+ rem->sign = sign_remainder;
+ while( markidx )
+ {
+ markidx--;
+ _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]);
+ }
+}
+
+void
+_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
+{
+ mpi_size_t usize, wsize;
+ mpi_size_t limb_cnt;
+
+ usize = u->nlimbs;
+ limb_cnt = count / BITS_PER_MPI_LIMB;
+ wsize = usize - limb_cnt;
+ if( limb_cnt >= usize )
+ w->nlimbs = 0;
+ else {
+ mpi_ptr_t wp;
+ mpi_ptr_t up;
+
+ RESIZE_IF_NEEDED( w, wsize );
+ wp = w->d;
+ up = u->d;
+
+ count %= BITS_PER_MPI_LIMB;
+ if( count ) {
+ _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count );
+ wsize -= !wp[wsize - 1];
+ }
+ else {
+ MPN_COPY_INCR( wp, up + limb_cnt, wsize);
+ }
+
+ w->nlimbs = wsize;
+ }
+}
+
+/****************
+ * Check whether dividend is divisible by divisor
+ * (note: divisor must fit into a limb)
+ */
+int
+_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
+{
+ return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
+}
+
+
+void
+gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor, int round)
+{
+ if (!round)
+ {
+ if (!rem)
+ {
+ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot));
+ _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor);
+ mpi_free (tmp);
+ }
+ else
+ _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor);
+ }
+ else if (round < 0)
+ {
+ if (!rem)
+ _gcry_mpi_fdiv_q (quot, dividend, divisor);
+ else if (!quot)
+ _gcry_mpi_fdiv_r (rem, dividend, divisor);
+ else
+ _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor);
+ }
+ else
+ log_bug ("mpi rounding to ceiling not yet implemented\n");
+}
+
+
+
diff --git a/libgcrypt-1.4.6/mpi/mpi-scan.c b/libgcrypt-1.4.6/mpi/mpi-scan.c
index 90699cd..3ee09d2 100644
--- a/libgcrypt-1.4.6/mpi/mpi-scan.c
+++ b/libgcrypt-1.4.6/mpi/mpi-scan.c
@@ -1,132 +1,132 @@
-/* mpi-scan.c - MPI functions
- * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "mpi-internal.h"
-#include "longlong.h"
-
-/****************
- * Scan through an mpi and return byte for byte. a -1 is returned to indicate
- * the end of the mpi. Scanning is done from the lsb to the msb, returned
- * values are in the range of 0 .. 255.
- *
- * FIXME: This code is VERY ugly!
- */
-int
-_gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx )
-{
- int i, j;
- unsigned n;
- mpi_ptr_t ap;
- mpi_limb_t limb;
-
- ap = a->d;
- for(n=0,i=0; i < a->nlimbs; i++ ) {
- limb = ap[i];
- for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
- if( n == idx )
- return (limb >> j*8) & 0xff;
- }
- return -1;
-}
-
-
-/****************
- * Put a value at position IDX into A. idx counts from lsb to msb
- */
-void
-_gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int xc )
-{
- int i, j;
- unsigned n;
- mpi_ptr_t ap;
- mpi_limb_t limb, c;
-
- c = xc & 0xff;
- ap = a->d;
- for(n=0,i=0; i < a->alloced; i++ ) {
- limb = ap[i];
- for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
- if( n == idx ) {
- #if BYTES_PER_MPI_LIMB == 4
- if( j == 0 )
- limb = (limb & 0xffffff00) | c;
- else if( j == 1 )
- limb = (limb & 0xffff00ff) | (c<<8);
- else if( j == 2 )
- limb = (limb & 0xff00ffff) | (c<<16);
- else
- limb = (limb & 0x00ffffff) | (c<<24);
- #elif BYTES_PER_MPI_LIMB == 8
- if( j == 0 )
- limb = (limb & 0xffffffffffffff00) | c;
- else if( j == 1 )
- limb = (limb & 0xffffffffffff00ff) | (c<<8);
- else if( j == 2 )
- limb = (limb & 0xffffffffff00ffff) | (c<<16);
- else if( j == 3 )
- limb = (limb & 0xffffffff00ffffff) | (c<<24);
- else if( j == 4 )
- limb = (limb & 0xffffff00ffffffff) | (c<<32);
- else if( j == 5 )
- limb = (limb & 0xffff00ffffffffff) | (c<<40);
- else if( j == 6 )
- limb = (limb & 0xff00ffffffffffff) | (c<<48);
- else
- limb = (limb & 0x00ffffffffffffff) | (c<<56);
- #else
- #error please enhance this function, its ugly - i know.
- #endif
- if( a->nlimbs <= i )
- a->nlimbs = i+1;
- ap[i] = limb;
- return;
- }
- }
- abort(); /* index out of range */
-}
-
-
-/****************
- * Count the number of zerobits at the low end of A
- */
-unsigned
-_gcry_mpi_trailing_zeros( gcry_mpi_t a )
-{
- unsigned n, count = 0;
-
- for(n=0; n < a->nlimbs; n++ ) {
- if( a->d[n] ) {
- unsigned nn;
- mpi_limb_t alimb = a->d[n];
-
- count_trailing_zeros( nn, alimb );
- count += nn;
- break;
- }
- count += BITS_PER_MPI_LIMB;
- }
- return count;
-
-}
-
-
+/* mpi-scan.c - MPI functions
+ * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+/****************
+ * Scan through an mpi and return byte for byte. a -1 is returned to indicate
+ * the end of the mpi. Scanning is done from the lsb to the msb, returned
+ * values are in the range of 0 .. 255.
+ *
+ * FIXME: This code is VERY ugly!
+ */
+int
+_gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx )
+{
+ int i, j;
+ unsigned n;
+ mpi_ptr_t ap;
+ mpi_limb_t limb;
+
+ ap = a->d;
+ for(n=0,i=0; i < a->nlimbs; i++ ) {
+ limb = ap[i];
+ for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
+ if( n == idx )
+ return (limb >> j*8) & 0xff;
+ }
+ return -1;
+}
+
+
+/****************
+ * Put a value at position IDX into A. idx counts from lsb to msb
+ */
+void
+_gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int xc )
+{
+ int i, j;
+ unsigned n;
+ mpi_ptr_t ap;
+ mpi_limb_t limb, c;
+
+ c = xc & 0xff;
+ ap = a->d;
+ for(n=0,i=0; i < a->alloced; i++ ) {
+ limb = ap[i];
+ for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
+ if( n == idx ) {
+ #if BYTES_PER_MPI_LIMB == 4
+ if( j == 0 )
+ limb = (limb & 0xffffff00) | c;
+ else if( j == 1 )
+ limb = (limb & 0xffff00ff) | (c<<8);
+ else if( j == 2 )
+ limb = (limb & 0xff00ffff) | (c<<16);
+ else
+ limb = (limb & 0x00ffffff) | (c<<24);
+ #elif BYTES_PER_MPI_LIMB == 8
+ if( j == 0 )
+ limb = (limb & 0xffffffffffffff00) | c;
+ else if( j == 1 )
+ limb = (limb & 0xffffffffffff00ff) | (c<<8);
+ else if( j == 2 )
+ limb = (limb & 0xffffffffff00ffff) | (c<<16);
+ else if( j == 3 )
+ limb = (limb & 0xffffffff00ffffff) | (c<<24);
+ else if( j == 4 )
+ limb = (limb & 0xffffff00ffffffff) | (c<<32);
+ else if( j == 5 )
+ limb = (limb & 0xffff00ffffffffff) | (c<<40);
+ else if( j == 6 )
+ limb = (limb & 0xff00ffffffffffff) | (c<<48);
+ else
+ limb = (limb & 0x00ffffffffffffff) | (c<<56);
+ #else
+ #error please enhance this function, its ugly - i know.
+ #endif
+ if( a->nlimbs <= i )
+ a->nlimbs = i+1;
+ ap[i] = limb;
+ return;
+ }
+ }
+ abort(); /* index out of range */
+}
+
+
+/****************
+ * Count the number of zerobits at the low end of A
+ */
+unsigned
+_gcry_mpi_trailing_zeros( gcry_mpi_t a )
+{
+ unsigned n, count = 0;
+
+ for(n=0; n < a->nlimbs; n++ ) {
+ if( a->d[n] ) {
+ unsigned nn;
+ mpi_limb_t alimb = a->d[n];
+
+ count_trailing_zeros( nn, alimb );
+ count += nn;
+ break;
+ }
+ count += BITS_PER_MPI_LIMB;
+ }
+ return count;
+
+}
+
+
diff --git a/libgcrypt-1.4.6/mpi/mpicoder.c b/libgcrypt-1.4.6/mpi/mpicoder.c
index 8f0c76f..b2d542c 100644
--- a/libgcrypt-1.4.6/mpi/mpicoder.c
+++ b/libgcrypt-1.4.6/mpi/mpicoder.c
@@ -1,752 +1,751 @@
-/* mpicoder.c - Coder for the external representation of MPIs
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "mpi-internal.h"
-#include "g10lib.h"
-
-#define MAX_EXTERN_MPI_BITS 16384
-
-/* Helper used to scan PGP style MPIs. Returns NULL on failure. */
-static gcry_mpi_t
-mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
- int secure)
-{
- int i, j;
- unsigned int nbits, nbytes, nlimbs, nread=0;
- mpi_limb_t a;
- gcry_mpi_t val = MPI_NULL;
-
- if ( *ret_nread < 2 )
- goto leave;
- nbits = buffer[0] << 8 | buffer[1];
- if ( nbits > MAX_EXTERN_MPI_BITS )
- {
-/* log_debug ("mpi too large (%u bits)\n", nbits); */
- goto leave;
- }
- else if( !nbits )
- {
-/* log_debug ("an mpi of size 0 is not allowed\n"); */
- goto leave;
- }
- buffer += 2;
- nread = 2;
-
- nbytes = (nbits+7) / 8;
- nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
- val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs);
- i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
- i %= BYTES_PER_MPI_LIMB;
- j= val->nlimbs = nlimbs;
- val->sign = 0;
- for ( ; j > 0; j-- )
- {
- a = 0;
- for (; i < BYTES_PER_MPI_LIMB; i++ )
- {
- if ( ++nread > *ret_nread )
- {
-/* log_debug ("mpi larger than buffer"); */
- mpi_free (val);
- val = NULL;
- goto leave;
- }
- a <<= 8;
- a |= *buffer++;
- }
- i = 0;
- val->d[j-1] = a;
- }
-
- leave:
- *ret_nread = nread;
- return val;
-}
-
-
-/****************
- * Fill the mpi VAL from the hex string in STR.
- */
-static int
-mpi_fromstr (gcry_mpi_t val, const char *str)
-{
- int sign = 0;
- int prepend_zero = 0;
- int i, j, c, c1, c2;
- unsigned int nbits, nbytes, nlimbs;
- mpi_limb_t a;
-
- if ( *str == '-' )
- {
- sign = 1;
- str++;
- }
-
- /* Skip optional hex prefix. */
- if ( *str == '0' && str[1] == 'x' )
- str += 2;
-
- nbits = 4 * strlen (str);
- if ((nbits % 8))
- prepend_zero = 1;
-
- nbytes = (nbits+7) / 8;
- nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
-
- if ( val->alloced < nlimbs )
- mpi_resize (val, nlimbs);
-
- i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
- i %= BYTES_PER_MPI_LIMB;
- j = val->nlimbs = nlimbs;
- val->sign = sign;
- for (; j > 0; j--)
- {
- a = 0;
- for (; i < BYTES_PER_MPI_LIMB; i++)
- {
- if (prepend_zero)
- {
- c1 = '0';
- prepend_zero = 0;
- }
- else
- c1 = *str++;
-
- if (!c1)
- {
- mpi_clear (val);
- return 1; /* Error. */
- }
- c2 = *str++;
- if (!c2)
- {
- mpi_clear (val);
- return 1; /* Error. */
- }
- if ( c1 >= '0' && c1 <= '9' )
- c = c1 - '0';
- else if ( c1 >= 'a' && c1 <= 'f' )
- c = c1 - 'a' + 10;
- else if ( c1 >= 'A' && c1 <= 'F' )
- c = c1 - 'A' + 10;
- else
- {
- mpi_clear (val);
- return 1; /* Error. */
- }
- c <<= 4;
- if ( c2 >= '0' && c2 <= '9' )
- c |= c2 - '0';
- else if( c2 >= 'a' && c2 <= 'f' )
- c |= c2 - 'a' + 10;
- else if( c2 >= 'A' && c2 <= 'F' )
- c |= c2 - 'A' + 10;
- else
- {
- mpi_clear(val);
- return 1; /* Error. */
- }
- a <<= 8;
- a |= c;
- }
- i = 0;
- val->d[j-1] = a;
- }
-
- return 0; /* Okay. */
-}
-
-
-/* Dump the value of A in a format suitable for debugging to
- Libgcrypt's logging stream. Note that one leading space but no
- trailing space or linefeed will be printed. It is okay to pass
- NULL for A. */
-void
-gcry_mpi_dump (const gcry_mpi_t a)
-{
- int i;
-
- log_printf (" ");
- if (!a)
- log_printf ("[MPI_NULL]");
- else
- {
- if (a->sign)
- log_printf ( "-");
-#if BYTES_PER_MPI_LIMB == 2
-# define X "4"
-#elif BYTES_PER_MPI_LIMB == 4
-# define X "8"
-#elif BYTES_PER_MPI_LIMB == 8
-# define X "16"
-#elif BYTES_PER_MPI_LIMB == 16
-# define X "32"
-#else
-# error please define the format here
-#endif
- for (i=a->nlimbs; i > 0 ; i-- )
- {
- log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
- }
-#undef X
- if (!a->nlimbs)
- log_printf ("0");
- }
-}
-
-/* Convience function used internally. */
-void
-_gcry_log_mpidump (const char *text, gcry_mpi_t a)
-{
- log_printf ("%s:", text);
- gcry_mpi_dump (a);
- log_printf ("\n");
-}
-
-
-/* Return an allocated buffer with the MPI (msb first). NBYTES
- receives the length of this buffer. Caller must free the return
- string. This function returns an allocated buffer with NBYTES set
- to zero if the value of A is zero. If sign is not NULL, it will be
- set to the sign of the A. On error NULL is returned and ERRNO set
- appropriately. */
-static unsigned char *
-do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure)
-{
- unsigned char *p, *buffer;
- mpi_limb_t alimb;
- int i;
- size_t n;
-
- if (sign)
- *sign = a->sign;
-
- *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
- n = *nbytes? *nbytes:1; /* Allocate at least one byte. */
- p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n)
- : gcry_malloc (n);
- if (!buffer)
- return NULL;
-
- for (i=a->nlimbs-1; i >= 0; i--)
- {
- alimb = a->d[i];
-#if BYTES_PER_MPI_LIMB == 4
- *p++ = alimb >> 24;
- *p++ = alimb >> 16;
- *p++ = alimb >> 8;
- *p++ = alimb ;
-#elif BYTES_PER_MPI_LIMB == 8
- *p++ = alimb >> 56;
- *p++ = alimb >> 48;
- *p++ = alimb >> 40;
- *p++ = alimb >> 32;
- *p++ = alimb >> 24;
- *p++ = alimb >> 16;
- *p++ = alimb >> 8;
- *p++ = alimb ;
-#else
-# error please implement for this limb size.
-#endif
- }
-
- /* This is sub-optimal but we need to do the shift operation because
- the caller has to free the returned buffer. */
- for (p=buffer; !*p && *nbytes; p++, --*nbytes)
- ;
- if (p != buffer)
- memmove (buffer,p, *nbytes);
- return buffer;
-}
-
-
-byte *
-_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign)
-{
- return do_get_buffer (a, nbytes, sign, 0);
-}
-
-byte *
-_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned *nbytes, int *sign)
-{
- return do_get_buffer (a, nbytes, sign, 1);
-}
-
-
-/*
- * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to
- * SIGN.
- */
-void
-_gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
- unsigned int nbytes, int sign)
-{
- const unsigned char *buffer = (const unsigned char*)buffer_arg;
- const unsigned char *p;
- mpi_limb_t alimb;
- int nlimbs;
- int i;
-
- nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
- RESIZE_IF_NEEDED(a, nlimbs);
- a->sign = sign;
-
- for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
- {
-#if BYTES_PER_MPI_LIMB == 4
- alimb = *p-- ;
- alimb |= *p-- << 8 ;
- alimb |= *p-- << 16 ;
- alimb |= *p-- << 24 ;
-#elif BYTES_PER_MPI_LIMB == 8
- alimb = (mpi_limb_t)*p-- ;
- alimb |= (mpi_limb_t)*p-- << 8 ;
- alimb |= (mpi_limb_t)*p-- << 16 ;
- alimb |= (mpi_limb_t)*p-- << 24 ;
- alimb |= (mpi_limb_t)*p-- << 32 ;
- alimb |= (mpi_limb_t)*p-- << 40 ;
- alimb |= (mpi_limb_t)*p-- << 48 ;
- alimb |= (mpi_limb_t)*p-- << 56 ;
-#else
-# error please implement for this limb size.
-#endif
- a->d[i++] = alimb;
- }
- if ( p >= buffer )
- {
-#if BYTES_PER_MPI_LIMB == 4
- alimb = *p--;
- if (p >= buffer)
- alimb |= *p-- << 8;
- if (p >= buffer)
- alimb |= *p-- << 16;
- if (p >= buffer)
- alimb |= *p-- << 24;
-#elif BYTES_PER_MPI_LIMB == 8
- alimb = (mpi_limb_t)*p--;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 8;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 16;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 24;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 32;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 40;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 48;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 56;
-#else
-# error please implement for this limb size.
-#endif
- a->d[i++] = alimb;
- }
- a->nlimbs = i;
- gcry_assert (i == nlimbs);
-}
-
-
-/* Convert the external representation of an integer stored in BUFFER
- with a length of BUFLEN into a newly create MPI returned in
- RET_MPI. If NBYTES is not NULL, it will receive the number of
- bytes actually scanned after a successful operation. */
-gcry_error_t
-gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
- const void *buffer_arg, size_t buflen, size_t *nscanned)
-{
- const unsigned char *buffer = (const unsigned char*)buffer_arg;
- struct gcry_mpi *a = NULL;
- unsigned int len;
- int secure = (buffer && gcry_is_secure (buffer));
-
- if (format == GCRYMPI_FMT_SSH)
- len = 0;
- else
- len = buflen;
-
- if (format == GCRYMPI_FMT_STD)
- {
- const unsigned char *s = buffer;
-
- a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
- /BYTES_PER_MPI_LIMB)
- : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
- if (len)
- {
- a->sign = !!(*s & 0x80);
- if (a->sign)
- {
- /* FIXME: we have to convert from 2compl to magnitude format */
- mpi_free (a);
- return gcry_error (GPG_ERR_INTERNAL);
- }
- else
- _gcry_mpi_set_buffer (a, s, len, 0);
- }
- if (ret_mpi)
- {
- mpi_normalize ( a );
- *ret_mpi = a;
- }
- else
- mpi_free(a);
- return 0;
- }
- else if (format == GCRYMPI_FMT_USG)
- {
- a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
- /BYTES_PER_MPI_LIMB)
- : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
-
- if (len)
- _gcry_mpi_set_buffer (a, buffer, len, 0);
- if (ret_mpi)
- {
- mpi_normalize ( a );
- *ret_mpi = a;
- }
- else
- mpi_free(a);
- return 0;
- }
- else if (format == GCRYMPI_FMT_PGP)
- {
- a = mpi_read_from_buffer (buffer, &len, secure);
- if (nscanned)
- *nscanned = len;
- if (ret_mpi && a)
- {
- mpi_normalize (a);
- *ret_mpi = a;
- }
- else if (a)
- {
- mpi_free(a);
- a = NULL;
- }
- return a? 0 : gcry_error (GPG_ERR_INV_OBJ);
- }
- else if (format == GCRYMPI_FMT_SSH)
- {
- const unsigned char *s = buffer;
- size_t n;
-
- if (len && len < 4)
- return gcry_error (GPG_ERR_TOO_SHORT);
-
- n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
- s += 4;
- if (len)
- len -= 4;
- if (len && n > len)
- return gcry_error (GPG_ERR_TOO_LARGE);
-
- a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
- /BYTES_PER_MPI_LIMB)
- : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
- if (n)
- {
- a->sign = !!(*s & 0x80);
- if (a->sign)
- {
- /* FIXME: we have to convert from 2compl to magnitude format */
- mpi_free(a);
- return gcry_error (GPG_ERR_INTERNAL);
- }
- else
- _gcry_mpi_set_buffer( a, s, n, 0 );
- }
- if (nscanned)
- *nscanned = n+4;
- if (ret_mpi)
- {
- mpi_normalize ( a );
- *ret_mpi = a;
- }
- else
- mpi_free(a);
- return 0;
- }
- else if (format == GCRYMPI_FMT_HEX)
- {
- /* We can only handle C strings for now. */
- if (buflen)
- return gcry_error (GPG_ERR_INV_ARG);
-
- a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
- if (mpi_fromstr (a, (const char *)buffer))
- {
- mpi_free (a);
- return gcry_error (GPG_ERR_INV_OBJ);
- }
- if (ret_mpi)
- {
- mpi_normalize ( a );
- *ret_mpi = a;
- }
- else
- mpi_free(a);
- return 0;
- }
- else
- return gcry_error (GPG_ERR_INV_ARG);
-}
-
-
-/* Convert the big integer A into the external representation
- described by FORMAT and store it in the provided BUFFER which has
- been allocated by the user with a size of BUFLEN bytes. NWRITTEN
- receives the actual length of the external representation unless it
- has been passed as NULL. BUFFER may be NULL to query the required
- length. */
-gcry_error_t
-gcry_mpi_print (enum gcry_mpi_format format,
- unsigned char *buffer, size_t buflen,
- size_t *nwritten, struct gcry_mpi *a)
-{
- unsigned int nbits = mpi_get_nbits (a);
- size_t len;
- size_t dummy_nwritten;
-
- if (!nwritten)
- nwritten = &dummy_nwritten;
-
- len = buflen;
- *nwritten = 0;
- if (format == GCRYMPI_FMT_STD)
- {
- unsigned char *tmp;
- int extra = 0;
- unsigned int n;
-
- if (a->sign)
- return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
-
- tmp = _gcry_mpi_get_buffer (a, &n, NULL);
- if (!tmp)
- return gpg_error_from_syserror ();
- if (n && (*tmp & 0x80))
- {
- n++;
- extra=1;
- }
-
- if (buffer && n > len)
- {
- /* The provided buffer is too short. */
- gcry_free (tmp);
- return gcry_error (GPG_ERR_TOO_SHORT);
- }
- if (buffer)
- {
- unsigned char *s = buffer;
-
- if (extra)
- *s++ = 0;
- memcpy (s, tmp, n-extra);
- }
- gcry_free(tmp);
- *nwritten = n;
- return 0;
- }
- else if (format == GCRYMPI_FMT_USG)
- {
- unsigned int n = (nbits + 7)/8;
-
- /* Note: We ignore the sign for this format. */
- /* FIXME: for performance reasons we should put this into
- mpi_aprint because we can then use the buffer directly. */
- if (buffer && n > len)
- return gcry_error (GPG_ERR_TOO_SHORT);
- if (buffer)
- {
- unsigned char *tmp;
-
- tmp = _gcry_mpi_get_buffer (a, &n, NULL);
- if (!tmp)
- return gpg_error_from_syserror ();
- memcpy (buffer, tmp, n);
- gcry_free (tmp);
- }
- *nwritten = n;
- return 0;
- }
- else if (format == GCRYMPI_FMT_PGP)
- {
- unsigned int n = (nbits + 7)/8;
-
- /* The PGP format can only handle unsigned integers. */
- if( a->sign )
- return gcry_error (GPG_ERR_INV_ARG);
-
- if (buffer && n+2 > len)
- return gcry_error (GPG_ERR_TOO_SHORT);
-
- if (buffer)
- {
- unsigned char *tmp;
- unsigned char *s = buffer;
-
- s[0] = nbits >> 8;
- s[1] = nbits;
-
- tmp = _gcry_mpi_get_buffer (a, &n, NULL);
- if (!tmp)
- return gpg_error_from_syserror ();
- memcpy (s+2, tmp, n);
- gcry_free (tmp);
- }
- *nwritten = n+2;
- return 0;
- }
- else if (format == GCRYMPI_FMT_SSH)
- {
- unsigned char *tmp;
- int extra = 0;
- unsigned int n;
-
- if (a->sign)
- return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
-
- tmp = _gcry_mpi_get_buffer (a, &n, NULL);
- if (!tmp)
- return gpg_error_from_syserror ();
- if (n && (*tmp & 0x80))
- {
- n++;
- extra=1;
- }
-
- if (buffer && n+4 > len)
- {
- gcry_free(tmp);
- return gcry_error (GPG_ERR_TOO_SHORT);
- }
-
- if (buffer)
- {
- unsigned char *s = buffer;
-
- *s++ = n >> 24;
- *s++ = n >> 16;
- *s++ = n >> 8;
- *s++ = n;
- if (extra)
- *s++ = 0;
-
- memcpy (s, tmp, n-extra);
- }
- gcry_free (tmp);
- *nwritten = 4+n;
- return 0;
- }
- else if (format == GCRYMPI_FMT_HEX)
- {
- unsigned char *tmp;
- int i;
- int extra = 0;
- unsigned int n = 0;
-
- tmp = _gcry_mpi_get_buffer (a, &n, NULL);
- if (!tmp)
- return gpg_error_from_syserror ();
- if (!n || (*tmp & 0x80))
- extra = 2;
-
- if (buffer && 2*n + extra + !!a->sign + 1 > len)
- {
- gcry_free(tmp);
- return gcry_error (GPG_ERR_TOO_SHORT);
- }
- if (buffer)
- {
- unsigned char *s = buffer;
-
- if (a->sign)
- *s++ = '-';
- if (extra)
- {
- *s++ = '0';
- *s++ = '0';
- }
-
- for (i=0; i < n; i++)
- {
- unsigned int c = tmp[i];
-
- *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
- c &= 15;
- *s++ = c < 10? '0'+c : 'A'+c-10 ;
- }
- *s++ = 0;
- *nwritten = s - buffer;
- }
- else
- {
- *nwritten = 2*n + extra + !!a->sign + 1;
- }
- gcry_free (tmp);
- return 0;
- }
- else
- return gcry_error (GPG_ERR_INV_ARG);
-}
-
-
-/*
- * Like gcry_mpi_print but this function allocates the buffer itself.
- * The caller has to supply the address of a pointer. NWRITTEN may be
- * NULL.
- */
-gcry_error_t
-gcry_mpi_aprint (enum gcry_mpi_format format,
- unsigned char **buffer, size_t *nwritten,
- struct gcry_mpi *a)
-{
- size_t n;
- gcry_error_t rc;
-
- *buffer = NULL;
- rc = gcry_mpi_print (format, NULL, 0, &n, a);
- if (rc)
- return rc;
-
- *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n) : gcry_malloc (n);
- if (!*buffer)
- return gpg_error_from_syserror ();
- rc = gcry_mpi_print( format, *buffer, n, &n, a );
- if (rc)
- {
- gcry_free(*buffer);
- *buffer = NULL;
- }
- else if (nwritten)
- *nwritten = n;
- return rc;
-}
-
+/* mpicoder.c - Coder for the external representation of MPIs
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ * 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "mpi-internal.h"
+#include "g10lib.h"
+
+#define MAX_EXTERN_MPI_BITS 16384
+
+/* Helper used to scan PGP style MPIs. Returns NULL on failure. */
+static gcry_mpi_t
+mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
+ int secure)
+{
+ int i, j;
+ unsigned int nbits, nbytes, nlimbs, nread=0;
+ mpi_limb_t a;
+ gcry_mpi_t val = MPI_NULL;
+
+ if ( *ret_nread < 2 )
+ goto leave;
+ nbits = buffer[0] << 8 | buffer[1];
+ if ( nbits > MAX_EXTERN_MPI_BITS )
+ {
+/* log_debug ("mpi too large (%u bits)\n", nbits); */
+ goto leave;
+ }
+ buffer += 2;
+ nread = 2;
+
+ nbytes = (nbits+7) / 8;
+ nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
+ val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs);
+ i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
+ i %= BYTES_PER_MPI_LIMB;
+ j= val->nlimbs = nlimbs;
+ val->sign = 0;
+ for ( ; j > 0; j-- )
+ {
+ a = 0;
+ for (; i < BYTES_PER_MPI_LIMB; i++ )
+ {
+ if ( ++nread > *ret_nread )
+ {
+/* log_debug ("mpi larger than buffer"); */
+ mpi_free (val);
+ val = NULL;
+ goto leave;
+ }
+ a <<= 8;
+ a |= *buffer++;
+ }
+ i = 0;
+ val->d[j-1] = a;
+ }
+
+ leave:
+ *ret_nread = nread;
+ return val;
+}
+
+
+/****************
+ * Fill the mpi VAL from the hex string in STR.
+ */
+static int
+mpi_fromstr (gcry_mpi_t val, const char *str)
+{
+ int sign = 0;
+ int prepend_zero = 0;
+ int i, j, c, c1, c2;
+ unsigned int nbits, nbytes, nlimbs;
+ mpi_limb_t a;
+
+ if ( *str == '-' )
+ {
+ sign = 1;
+ str++;
+ }
+
+ /* Skip optional hex prefix. */
+ if ( *str == '0' && str[1] == 'x' )
+ str += 2;
+
+ nbits = 4 * strlen (str);
+ if ((nbits % 8))
+ prepend_zero = 1;
+
+ nbytes = (nbits+7) / 8;
+ nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
+
+ if ( val->alloced < nlimbs )
+ mpi_resize (val, nlimbs);
+
+ i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
+ i %= BYTES_PER_MPI_LIMB;
+ j = val->nlimbs = nlimbs;
+ val->sign = sign;
+ for (; j > 0; j--)
+ {
+ a = 0;
+ for (; i < BYTES_PER_MPI_LIMB; i++)
+ {
+ if (prepend_zero)
+ {
+ c1 = '0';
+ prepend_zero = 0;
+ }
+ else
+ c1 = *str++;
+
+ if (!c1)
+ {
+ mpi_clear (val);
+ return 1; /* Error. */
+ }
+ c2 = *str++;
+ if (!c2)
+ {
+ mpi_clear (val);
+ return 1; /* Error. */
+ }
+ if ( c1 >= '0' && c1 <= '9' )
+ c = c1 - '0';
+ else if ( c1 >= 'a' && c1 <= 'f' )
+ c = c1 - 'a' + 10;
+ else if ( c1 >= 'A' && c1 <= 'F' )
+ c = c1 - 'A' + 10;
+ else
+ {
+ mpi_clear (val);
+ return 1; /* Error. */
+ }
+ c <<= 4;
+ if ( c2 >= '0' && c2 <= '9' )
+ c |= c2 - '0';
+ else if( c2 >= 'a' && c2 <= 'f' )
+ c |= c2 - 'a' + 10;
+ else if( c2 >= 'A' && c2 <= 'F' )
+ c |= c2 - 'A' + 10;
+ else
+ {
+ mpi_clear(val);
+ return 1; /* Error. */
+ }
+ a <<= 8;
+ a |= c;
+ }
+ i = 0;
+ val->d[j-1] = a;
+ }
+
+ return 0; /* Okay. */
+}
+
+
+/* Dump the value of A in a format suitable for debugging to
+ Libgcrypt's logging stream. Note that one leading space but no
+ trailing space or linefeed will be printed. It is okay to pass
+ NULL for A. */
+void
+gcry_mpi_dump (const gcry_mpi_t a)
+{
+ int i;
+
+ log_printf (" ");
+ if (!a)
+ log_printf ("[MPI_NULL]");
+ else
+ {
+ if (a->sign)
+ log_printf ( "-");
+#if BYTES_PER_MPI_LIMB == 2
+# define X "4"
+#elif BYTES_PER_MPI_LIMB == 4
+# define X "8"
+#elif BYTES_PER_MPI_LIMB == 8
+# define X "16"
+#elif BYTES_PER_MPI_LIMB == 16
+# define X "32"
+#else
+# error please define the format here
+#endif
+ for (i=a->nlimbs; i > 0 ; i-- )
+ {
+ log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
+ }
+#undef X
+ if (!a->nlimbs)
+ log_printf ("0");
+ }
+}
+
+/* Convience function used internally. */
+void
+_gcry_log_mpidump (const char *text, gcry_mpi_t a)
+{
+ log_printf ("%s:", text);
+ gcry_mpi_dump (a);
+ log_printf ("\n");
+}
+
+
+/* Return an allocated buffer with the MPI (msb first). NBYTES
+ receives the length of this buffer. Caller must free the return
+ string. This function returns an allocated buffer with NBYTES set
+ to zero if the value of A is zero. If sign is not NULL, it will be
+ set to the sign of the A. On error NULL is returned and ERRNO set
+ appropriately. */
+static unsigned char *
+do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure)
+{
+ unsigned char *p, *buffer;
+ mpi_limb_t alimb;
+ int i;
+ size_t n;
+
+ if (sign)
+ *sign = a->sign;
+
+ *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
+ n = *nbytes? *nbytes:1; /* Allocate at least one byte. */
+ p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n)
+ : gcry_malloc (n);
+ if (!buffer)
+ return NULL;
+
+ for (i=a->nlimbs-1; i >= 0; i--)
+ {
+ alimb = a->d[i];
+#if BYTES_PER_MPI_LIMB == 4
+ *p++ = alimb >> 24;
+ *p++ = alimb >> 16;
+ *p++ = alimb >> 8;
+ *p++ = alimb ;
+#elif BYTES_PER_MPI_LIMB == 8
+ *p++ = alimb >> 56;
+ *p++ = alimb >> 48;
+ *p++ = alimb >> 40;
+ *p++ = alimb >> 32;
+ *p++ = alimb >> 24;
+ *p++ = alimb >> 16;
+ *p++ = alimb >> 8;
+ *p++ = alimb ;
+#else
+# error please implement for this limb size.
+#endif
+ }
+
+ /* This is sub-optimal but we need to do the shift operation because
+ the caller has to free the returned buffer. */
+ for (p=buffer; !*p && *nbytes; p++, --*nbytes)
+ ;
+ if (p != buffer)
+ memmove (buffer,p, *nbytes);
+ return buffer;
+}
+
+
+byte *
+_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign)
+{
+ return do_get_buffer (a, nbytes, sign, 0);
+}
+
+byte *
+_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned *nbytes, int *sign)
+{
+ return do_get_buffer (a, nbytes, sign, 1);
+}
+
+
+/*
+ * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to
+ * SIGN.
+ */
+void
+_gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
+ unsigned int nbytes, int sign)
+{
+ const unsigned char *buffer = (const unsigned char*)buffer_arg;
+ const unsigned char *p;
+ mpi_limb_t alimb;
+ int nlimbs;
+ int i;
+
+ nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
+ RESIZE_IF_NEEDED(a, nlimbs);
+ a->sign = sign;
+
+ for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
+ {
+#if BYTES_PER_MPI_LIMB == 4
+ alimb = *p-- ;
+ alimb |= *p-- << 8 ;
+ alimb |= *p-- << 16 ;
+ alimb |= *p-- << 24 ;
+#elif BYTES_PER_MPI_LIMB == 8
+ alimb = (mpi_limb_t)*p-- ;
+ alimb |= (mpi_limb_t)*p-- << 8 ;
+ alimb |= (mpi_limb_t)*p-- << 16 ;
+ alimb |= (mpi_limb_t)*p-- << 24 ;
+ alimb |= (mpi_limb_t)*p-- << 32 ;
+ alimb |= (mpi_limb_t)*p-- << 40 ;
+ alimb |= (mpi_limb_t)*p-- << 48 ;
+ alimb |= (mpi_limb_t)*p-- << 56 ;
+#else
+# error please implement for this limb size.
+#endif
+ a->d[i++] = alimb;
+ }
+ if ( p >= buffer )
+ {
+#if BYTES_PER_MPI_LIMB == 4
+ alimb = *p--;
+ if (p >= buffer)
+ alimb |= *p-- << 8;
+ if (p >= buffer)
+ alimb |= *p-- << 16;
+ if (p >= buffer)
+ alimb |= *p-- << 24;
+#elif BYTES_PER_MPI_LIMB == 8
+ alimb = (mpi_limb_t)*p--;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 8;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 16;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 24;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 32;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 40;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 48;
+ if (p >= buffer)
+ alimb |= (mpi_limb_t)*p-- << 56;
+#else
+# error please implement for this limb size.
+#endif
+ a->d[i++] = alimb;
+ }
+ a->nlimbs = i;
+ gcry_assert (i == nlimbs);
+}
+
+
+/* Convert the external representation of an integer stored in BUFFER
+ with a length of BUFLEN into a newly create MPI returned in
+ RET_MPI. If NBYTES is not NULL, it will receive the number of
+ bytes actually scanned after a successful operation. */
+gcry_error_t
+gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
+ const void *buffer_arg, size_t buflen, size_t *nscanned)
+{
+ const unsigned char *buffer = (const unsigned char*)buffer_arg;
+ struct gcry_mpi *a = NULL;
+ unsigned int len;
+ int secure = (buffer && gcry_is_secure (buffer));
+
+ if (format == GCRYMPI_FMT_SSH)
+ len = 0;
+ else
+ len = buflen;
+
+ if (format == GCRYMPI_FMT_STD)
+ {
+ const unsigned char *s = buffer;
+
+ a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
+ /BYTES_PER_MPI_LIMB)
+ : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
+ if (len)
+ {
+ a->sign = !!(*s & 0x80);
+ if (a->sign)
+ {
+ /* FIXME: we have to convert from 2compl to magnitude format */
+ mpi_free (a);
+ return gcry_error (GPG_ERR_INTERNAL);
+ }
+ else
+ _gcry_mpi_set_buffer (a, s, len, 0);
+ }
+ if (ret_mpi)
+ {
+ mpi_normalize ( a );
+ *ret_mpi = a;
+ }
+ else
+ mpi_free(a);
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_USG)
+ {
+ a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
+ /BYTES_PER_MPI_LIMB)
+ : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
+
+ if (len)
+ _gcry_mpi_set_buffer (a, buffer, len, 0);
+ if (ret_mpi)
+ {
+ mpi_normalize ( a );
+ *ret_mpi = a;
+ }
+ else
+ mpi_free(a);
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_PGP)
+ {
+ a = mpi_read_from_buffer (buffer, &len, secure);
+ if (nscanned)
+ *nscanned = len;
+ if (ret_mpi && a)
+ {
+ mpi_normalize (a);
+ *ret_mpi = a;
+ }
+ else if (a)
+ {
+ mpi_free(a);
+ a = NULL;
+ }
+ return a? 0 : gcry_error (GPG_ERR_INV_OBJ);
+ }
+ else if (format == GCRYMPI_FMT_SSH)
+ {
+ const unsigned char *s = buffer;
+ size_t n;
+
+ /* This test is not strictly necessary and an assert (!len)
+ would be sufficient. We keep this test in case we later
+ allow the BUFLEN argument to act as a sanitiy check. Same
+ below. */
+ if (len && len < 4)
+ return gcry_error (GPG_ERR_TOO_SHORT);
+
+ n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
+ s += 4;
+ if (len)
+ len -= 4;
+ if (len && n > len)
+ return gcry_error (GPG_ERR_TOO_LARGE);
+
+ a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
+ /BYTES_PER_MPI_LIMB)
+ : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
+ if (n)
+ {
+ a->sign = !!(*s & 0x80);
+ if (a->sign)
+ {
+ /* FIXME: we have to convert from 2compl to magnitude format */
+ mpi_free(a);
+ return gcry_error (GPG_ERR_INTERNAL);
+ }
+ else
+ _gcry_mpi_set_buffer( a, s, n, 0 );
+ }
+ if (nscanned)
+ *nscanned = n+4;
+ if (ret_mpi)
+ {
+ mpi_normalize ( a );
+ *ret_mpi = a;
+ }
+ else
+ mpi_free(a);
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_HEX)
+ {
+ /* We can only handle C strings for now. */
+ if (buflen)
+ return gcry_error (GPG_ERR_INV_ARG);
+
+ a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
+ if (mpi_fromstr (a, (const char *)buffer))
+ {
+ mpi_free (a);
+ return gcry_error (GPG_ERR_INV_OBJ);
+ }
+ if (ret_mpi)
+ {
+ mpi_normalize ( a );
+ *ret_mpi = a;
+ }
+ else
+ mpi_free(a);
+ return 0;
+ }
+ else
+ return gcry_error (GPG_ERR_INV_ARG);
+}
+
+
+/* Convert the big integer A into the external representation
+ described by FORMAT and store it in the provided BUFFER which has
+ been allocated by the user with a size of BUFLEN bytes. NWRITTEN
+ receives the actual length of the external representation unless it
+ has been passed as NULL. BUFFER may be NULL to query the required
+ length. */
+gcry_error_t
+gcry_mpi_print (enum gcry_mpi_format format,
+ unsigned char *buffer, size_t buflen,
+ size_t *nwritten, struct gcry_mpi *a)
+{
+ unsigned int nbits = mpi_get_nbits (a);
+ size_t len;
+ size_t dummy_nwritten;
+
+ if (!nwritten)
+ nwritten = &dummy_nwritten;
+
+ len = buflen;
+ *nwritten = 0;
+ if (format == GCRYMPI_FMT_STD)
+ {
+ unsigned char *tmp;
+ int extra = 0;
+ unsigned int n;
+
+ if (a->sign)
+ return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
+
+ tmp = _gcry_mpi_get_buffer (a, &n, NULL);
+ if (!tmp)
+ return gpg_error_from_syserror ();
+ if (n && (*tmp & 0x80))
+ {
+ n++;
+ extra=1;
+ }
+
+ if (buffer && n > len)
+ {
+ /* The provided buffer is too short. */
+ gcry_free (tmp);
+ return gcry_error (GPG_ERR_TOO_SHORT);
+ }
+ if (buffer)
+ {
+ unsigned char *s = buffer;
+
+ if (extra)
+ *s++ = 0;
+ memcpy (s, tmp, n-extra);
+ }
+ gcry_free(tmp);
+ *nwritten = n;
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_USG)
+ {
+ unsigned int n = (nbits + 7)/8;
+
+ /* Note: We ignore the sign for this format. */
+ /* FIXME: for performance reasons we should put this into
+ mpi_aprint because we can then use the buffer directly. */
+ if (buffer && n > len)
+ return gcry_error (GPG_ERR_TOO_SHORT);
+ if (buffer)
+ {
+ unsigned char *tmp;
+
+ tmp = _gcry_mpi_get_buffer (a, &n, NULL);
+ if (!tmp)
+ return gpg_error_from_syserror ();
+ memcpy (buffer, tmp, n);
+ gcry_free (tmp);
+ }
+ *nwritten = n;
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_PGP)
+ {
+ unsigned int n = (nbits + 7)/8;
+
+ /* The PGP format can only handle unsigned integers. */
+ if( a->sign )
+ return gcry_error (GPG_ERR_INV_ARG);
+
+ if (buffer && n+2 > len)
+ return gcry_error (GPG_ERR_TOO_SHORT);
+
+ if (buffer)
+ {
+ unsigned char *tmp;
+ unsigned char *s = buffer;
+
+ s[0] = nbits >> 8;
+ s[1] = nbits;
+
+ tmp = _gcry_mpi_get_buffer (a, &n, NULL);
+ if (!tmp)
+ return gpg_error_from_syserror ();
+ memcpy (s+2, tmp, n);
+ gcry_free (tmp);
+ }
+ *nwritten = n+2;
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_SSH)
+ {
+ unsigned char *tmp;
+ int extra = 0;
+ unsigned int n;
+
+ if (a->sign)
+ return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
+
+ tmp = _gcry_mpi_get_buffer (a, &n, NULL);
+ if (!tmp)
+ return gpg_error_from_syserror ();
+ if (n && (*tmp & 0x80))
+ {
+ n++;
+ extra=1;
+ }
+
+ if (buffer && n+4 > len)
+ {
+ gcry_free(tmp);
+ return gcry_error (GPG_ERR_TOO_SHORT);
+ }
+
+ if (buffer)
+ {
+ unsigned char *s = buffer;
+
+ *s++ = n >> 24;
+ *s++ = n >> 16;
+ *s++ = n >> 8;
+ *s++ = n;
+ if (extra)
+ *s++ = 0;
+
+ memcpy (s, tmp, n-extra);
+ }
+ gcry_free (tmp);
+ *nwritten = 4+n;
+ return 0;
+ }
+ else if (format == GCRYMPI_FMT_HEX)
+ {
+ unsigned char *tmp;
+ int i;
+ int extra = 0;
+ unsigned int n = 0;
+
+ tmp = _gcry_mpi_get_buffer (a, &n, NULL);
+ if (!tmp)
+ return gpg_error_from_syserror ();
+ if (!n || (*tmp & 0x80))
+ extra = 2;
+
+ if (buffer && 2*n + extra + !!a->sign + 1 > len)
+ {
+ gcry_free(tmp);
+ return gcry_error (GPG_ERR_TOO_SHORT);
+ }
+ if (buffer)
+ {
+ unsigned char *s = buffer;
+
+ if (a->sign)
+ *s++ = '-';
+ if (extra)
+ {
+ *s++ = '0';
+ *s++ = '0';
+ }
+
+ for (i=0; i < n; i++)
+ {
+ unsigned int c = tmp[i];
+
+ *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
+ c &= 15;
+ *s++ = c < 10? '0'+c : 'A'+c-10 ;
+ }
+ *s++ = 0;
+ *nwritten = s - buffer;
+ }
+ else
+ {
+ *nwritten = 2*n + extra + !!a->sign + 1;
+ }
+ gcry_free (tmp);
+ return 0;
+ }
+ else
+ return gcry_error (GPG_ERR_INV_ARG);
+}
+
+
+/*
+ * Like gcry_mpi_print but this function allocates the buffer itself.
+ * The caller has to supply the address of a pointer. NWRITTEN may be
+ * NULL.
+ */
+gcry_error_t
+gcry_mpi_aprint (enum gcry_mpi_format format,
+ unsigned char **buffer, size_t *nwritten,
+ struct gcry_mpi *a)
+{
+ size_t n;
+ gcry_error_t rc;
+
+ *buffer = NULL;
+ rc = gcry_mpi_print (format, NULL, 0, &n, a);
+ if (rc)
+ return rc;
+
+ *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n) : gcry_malloc (n);
+ if (!*buffer)
+ return gpg_error_from_syserror ();
+ rc = gcry_mpi_print( format, *buffer, n, &n, a );
+ if (rc)
+ {
+ gcry_free(*buffer);
+ *buffer = NULL;
+ }
+ else if (nwritten)
+ *nwritten = n;
+ return rc;
+}
+
diff --git a/libgcrypt-1.4.6/mpi/mpiutil.c b/libgcrypt-1.4.6/mpi/mpiutil.c
index 4dc5211..f406cbc 100644
--- a/libgcrypt-1.4.6/mpi/mpiutil.c
+++ b/libgcrypt-1.4.6/mpi/mpiutil.c
@@ -1,462 +1,461 @@
-/* mpiutil.ac - Utility functions for MPI
- * Copyright (C) 1998, 2000, 2001, 2002, 2003,
- * 2007 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "g10lib.h"
-#include "mpi-internal.h"
-#include "memory.h"
-#include "mod-source-info.h"
-
-
-const char *
-_gcry_mpi_get_hw_config (void)
-{
- return mod_source_info + 1;
-}
-
-
-/****************
- * Note: It was a bad idea to use the number of limbs to allocate
- * because on a alpha the limbs are large but we normally need
- * integers of n bits - So we should change this to bits (or bytes).
- *
- * But mpi_alloc is used in a lot of places :-(. New code
- * should use mpi_new.
- */
-gcry_mpi_t
-_gcry_mpi_alloc( unsigned nlimbs )
-{
- gcry_mpi_t a;
-
- a = gcry_xmalloc( sizeof *a );
- a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
- a->alloced = nlimbs;
- a->nlimbs = 0;
- a->sign = 0;
- a->flags = 0;
- return a;
-}
-
-void
-_gcry_mpi_m_check( gcry_mpi_t a )
-{
- _gcry_check_heap(a);
- _gcry_check_heap(a->d);
-}
-
-gcry_mpi_t
-_gcry_mpi_alloc_secure( unsigned nlimbs )
-{
- gcry_mpi_t a;
-
- a = gcry_xmalloc( sizeof *a );
- a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
- a->alloced = nlimbs;
- a->flags = 1;
- a->nlimbs = 0;
- a->sign = 0;
- return a;
-}
-
-
-
-mpi_ptr_t
-_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
-{
- mpi_ptr_t p;
- size_t len;
-
- len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
- p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
- if (! nlimbs)
- *p = 0;
-
- return p;
-}
-
-void
-_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
-{
- if (a)
- {
- size_t len = nlimbs * sizeof(mpi_limb_t);
-
- /* If we have information on the number of allocated limbs, we
- better wipe that space out. This is a failsafe feature if
- secure memory has been disabled or was not properly
- implemented in user provided allocation functions. */
- if (len)
- wipememory (a, len);
- gcry_free(a);
- }
-}
-
-
-void
-_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
-{
- _gcry_mpi_free_limb_space (a->d, a->alloced);
- a->d = ap;
- a->alloced = nlimbs;
-}
-
-
-
-/****************
- * Resize the array of A to NLIMBS. The additional space is cleared
- * (set to 0).
- */
-void
-_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
-{
- size_t i;
-
- if (nlimbs <= a->alloced)
- {
- /* We only need to clear the new space (this is a nop if the
- limb space is already of the correct size. */
- for (i=a->nlimbs; i < a->alloced; i++)
- a->d[i] = 0;
- return;
- }
-
- /* Actually resize the limb space. */
- if (a->d)
- {
- a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
- for (i=a->alloced; i < nlimbs; i++)
- a->d[i] = 0;
- }
- else
- {
- if (a->flags & 1)
- /* Secure memory is wanted. */
- a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
- else
- /* Standard memory. */
- a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
- }
- a->alloced = nlimbs;
-}
-
-void
-_gcry_mpi_clear( gcry_mpi_t a )
-{
- a->nlimbs = 0;
- a->flags = 0;
-}
-
-
-void
-_gcry_mpi_free( gcry_mpi_t a )
-{
- if (!a )
- return;
- if ((a->flags & 4))
- gcry_free( a->d );
- else
- {
- _gcry_mpi_free_limb_space(a->d, a->alloced);
- }
- if ((a->flags & ~7))
- log_bug("invalid flag value in mpi\n");
- gcry_free(a);
-}
-
-static void
-mpi_set_secure( gcry_mpi_t a )
-{
- mpi_ptr_t ap, bp;
-
- if ( (a->flags & 1) )
- return;
- a->flags |= 1;
- ap = a->d;
- if (!a->nlimbs)
- {
- gcry_assert (!ap);
- return;
- }
- bp = mpi_alloc_limb_space (a->nlimbs, 1);
- MPN_COPY( bp, ap, a->nlimbs );
- a->d = bp;
- _gcry_mpi_free_limb_space (ap, a->alloced);
-}
-
-
-gcry_mpi_t
-gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
-{
- if (!a)
- a = mpi_alloc(0);
-
- if( a->flags & 4 )
- gcry_free( a->d );
- else
- _gcry_mpi_free_limb_space (a->d, a->alloced);
-
- a->d = p;
- a->alloced = 0;
- a->nlimbs = 0;
- a->sign = nbits;
- a->flags = 4;
- return a;
-}
-
-
-void *
-gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
-{
- if( !(a->flags & 4) )
- log_bug("mpi_get_opaque on normal mpi\n");
- if( nbits )
- *nbits = a->sign;
- return a->d;
-}
-
-
-/****************
- * Note: This copy function should not interpret the MPI
- * but copy it transparently.
- */
-gcry_mpi_t
-gcry_mpi_copy( gcry_mpi_t a )
-{
- int i;
- gcry_mpi_t b;
-
- if( a && (a->flags & 4) ) {
- void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
- : gcry_xmalloc( (a->sign+7)/8 );
- memcpy( p, a->d, (a->sign+7)/8 );
- b = gcry_mpi_set_opaque( NULL, p, a->sign );
- }
- else if( a ) {
- b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
- : mpi_alloc( a->nlimbs );
- b->nlimbs = a->nlimbs;
- b->sign = a->sign;
- b->flags = a->flags;
- for(i=0; i < b->nlimbs; i++ )
- b->d[i] = a->d[i];
- }
- else
- b = NULL;
- return b;
-}
-
-
-/****************
- * This function allocates an MPI which is optimized to hold
- * a value as large as the one given in the argument and allocates it
- * with the same flags as A.
- */
-gcry_mpi_t
-_gcry_mpi_alloc_like( gcry_mpi_t a )
-{
- gcry_mpi_t b;
-
- if( a && (a->flags & 4) ) {
- int n = (a->sign+7)/8;
- void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
- : gcry_malloc( n );
- memcpy( p, a->d, n );
- b = gcry_mpi_set_opaque( NULL, p, a->sign );
- }
- else if( a ) {
- b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
- : mpi_alloc( a->nlimbs );
- b->nlimbs = 0;
- b->sign = 0;
- b->flags = a->flags;
- }
- else
- b = NULL;
- return b;
-}
-
-
-gcry_mpi_t
-gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
-{
- mpi_ptr_t wp, up;
- mpi_size_t usize = u->nlimbs;
- int usign = u->sign;
-
- if (!w)
- w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
- RESIZE_IF_NEEDED(w, usize);
- wp = w->d;
- up = u->d;
- MPN_COPY( wp, up, usize );
- w->nlimbs = usize;
- w->flags = u->flags;
- w->sign = usign;
- return w;
-}
-
-
-gcry_mpi_t
-gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
-{
- if (!w)
- w = _gcry_mpi_alloc (1);
- /* FIXME: If U is 0 we have no need to resize and thus possible
- allocating the the limbs. */
- RESIZE_IF_NEEDED(w, 1);
- w->d[0] = u;
- w->nlimbs = u? 1:0;
- w->sign = 0;
- w->flags = 0;
- return w;
-}
-
-gcry_err_code_t
-_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- unsigned long x = 0;
-
- if (w->nlimbs > 1)
- err = GPG_ERR_TOO_LARGE;
- else if (w->nlimbs == 1)
- x = w->d[0];
- else
- x = 0;
-
- if (! err)
- *u = x;
-
- return err;
-}
-
-gcry_error_t
-gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
-{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
-
- err = _gcry_mpi_get_ui (w, u);
-
- return gcry_error (err);
-}
-
-gcry_mpi_t
-_gcry_mpi_alloc_set_ui( unsigned long u)
-{
- gcry_mpi_t w = mpi_alloc(1);
- w->d[0] = u;
- w->nlimbs = u? 1:0;
- w->sign = 0;
- return w;
-}
-
-void
-gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
-{
- struct gcry_mpi tmp;
-
- tmp = *a; *a = *b; *b = tmp;
-}
-
-
-gcry_mpi_t
-gcry_mpi_new( unsigned int nbits )
-{
- return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
- / BITS_PER_MPI_LIMB );
-}
-
-
-gcry_mpi_t
-gcry_mpi_snew( unsigned int nbits )
-{
- return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
- / BITS_PER_MPI_LIMB );
-}
-
-void
-gcry_mpi_release( gcry_mpi_t a )
-{
- _gcry_mpi_free( a );
-}
-
-void
-gcry_mpi_randomize( gcry_mpi_t w,
- unsigned int nbits, enum gcry_random_level level )
-{
- unsigned char *p;
- size_t nbytes = (nbits+7)/8;
-
- if (level == GCRY_WEAK_RANDOM)
- {
- p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
- : gcry_xmalloc (nbytes);
- gcry_create_nonce (p, nbytes);
- }
- else
- {
- p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
- : gcry_random_bytes (nbytes, level);
- }
- _gcry_mpi_set_buffer( w, p, nbytes, 0 );
- gcry_free (p);
-}
-
-
-void
-gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
-{
- switch( flag ) {
- case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
- case GCRYMPI_FLAG_OPAQUE:
- default: log_bug("invalid flag value\n");
- }
-}
-
-void
-gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
-{
- (void)a; /* Not yet used. */
-
- switch (flag)
- {
- case GCRYMPI_FLAG_SECURE:
- case GCRYMPI_FLAG_OPAQUE:
- default: log_bug("invalid flag value\n");
- }
-}
-
-int
-gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
-{
- switch (flag)
- {
- case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
- case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
- default: log_bug("invalid flag value\n");
- }
- /*NOTREACHED*/
- return 0;
-}
-
+/* mpiutil.ac - Utility functions for MPI
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003,
+ * 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "g10lib.h"
+#include "mpi-internal.h"
+#include "mod-source-info.h"
+
+
+const char *
+_gcry_mpi_get_hw_config (void)
+{
+ return mod_source_info + 1;
+}
+
+
+/****************
+ * Note: It was a bad idea to use the number of limbs to allocate
+ * because on a alpha the limbs are large but we normally need
+ * integers of n bits - So we should change this to bits (or bytes).
+ *
+ * But mpi_alloc is used in a lot of places :-(. New code
+ * should use mpi_new.
+ */
+gcry_mpi_t
+_gcry_mpi_alloc( unsigned nlimbs )
+{
+ gcry_mpi_t a;
+
+ a = gcry_xmalloc( sizeof *a );
+ a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
+ a->alloced = nlimbs;
+ a->nlimbs = 0;
+ a->sign = 0;
+ a->flags = 0;
+ return a;
+}
+
+void
+_gcry_mpi_m_check( gcry_mpi_t a )
+{
+ _gcry_check_heap(a);
+ _gcry_check_heap(a->d);
+}
+
+gcry_mpi_t
+_gcry_mpi_alloc_secure( unsigned nlimbs )
+{
+ gcry_mpi_t a;
+
+ a = gcry_xmalloc( sizeof *a );
+ a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
+ a->alloced = nlimbs;
+ a->flags = 1;
+ a->nlimbs = 0;
+ a->sign = 0;
+ return a;
+}
+
+
+
+mpi_ptr_t
+_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
+{
+ mpi_ptr_t p;
+ size_t len;
+
+ len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
+ p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
+ if (! nlimbs)
+ *p = 0;
+
+ return p;
+}
+
+void
+_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
+{
+ if (a)
+ {
+ size_t len = nlimbs * sizeof(mpi_limb_t);
+
+ /* If we have information on the number of allocated limbs, we
+ better wipe that space out. This is a failsafe feature if
+ secure memory has been disabled or was not properly
+ implemented in user provided allocation functions. */
+ if (len)
+ wipememory (a, len);
+ gcry_free(a);
+ }
+}
+
+
+void
+_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
+{
+ _gcry_mpi_free_limb_space (a->d, a->alloced);
+ a->d = ap;
+ a->alloced = nlimbs;
+}
+
+
+
+/****************
+ * Resize the array of A to NLIMBS. The additional space is cleared
+ * (set to 0).
+ */
+void
+_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
+{
+ size_t i;
+
+ if (nlimbs <= a->alloced)
+ {
+ /* We only need to clear the new space (this is a nop if the
+ limb space is already of the correct size. */
+ for (i=a->nlimbs; i < a->alloced; i++)
+ a->d[i] = 0;
+ return;
+ }
+
+ /* Actually resize the limb space. */
+ if (a->d)
+ {
+ a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
+ for (i=a->alloced; i < nlimbs; i++)
+ a->d[i] = 0;
+ }
+ else
+ {
+ if (a->flags & 1)
+ /* Secure memory is wanted. */
+ a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
+ else
+ /* Standard memory. */
+ a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
+ }
+ a->alloced = nlimbs;
+}
+
+void
+_gcry_mpi_clear( gcry_mpi_t a )
+{
+ a->nlimbs = 0;
+ a->flags = 0;
+}
+
+
+void
+_gcry_mpi_free( gcry_mpi_t a )
+{
+ if (!a )
+ return;
+ if ((a->flags & 4))
+ gcry_free( a->d );
+ else
+ {
+ _gcry_mpi_free_limb_space(a->d, a->alloced);
+ }
+ if ((a->flags & ~7))
+ log_bug("invalid flag value in mpi\n");
+ gcry_free(a);
+}
+
+static void
+mpi_set_secure( gcry_mpi_t a )
+{
+ mpi_ptr_t ap, bp;
+
+ if ( (a->flags & 1) )
+ return;
+ a->flags |= 1;
+ ap = a->d;
+ if (!a->nlimbs)
+ {
+ gcry_assert (!ap);
+ return;
+ }
+ bp = mpi_alloc_limb_space (a->nlimbs, 1);
+ MPN_COPY( bp, ap, a->nlimbs );
+ a->d = bp;
+ _gcry_mpi_free_limb_space (ap, a->alloced);
+}
+
+
+gcry_mpi_t
+gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
+{
+ if (!a)
+ a = mpi_alloc(0);
+
+ if( a->flags & 4 )
+ gcry_free( a->d );
+ else
+ _gcry_mpi_free_limb_space (a->d, a->alloced);
+
+ a->d = p;
+ a->alloced = 0;
+ a->nlimbs = 0;
+ a->sign = nbits;
+ a->flags = 4;
+ return a;
+}
+
+
+void *
+gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
+{
+ if( !(a->flags & 4) )
+ log_bug("mpi_get_opaque on normal mpi\n");
+ if( nbits )
+ *nbits = a->sign;
+ return a->d;
+}
+
+
+/****************
+ * Note: This copy function should not interpret the MPI
+ * but copy it transparently.
+ */
+gcry_mpi_t
+gcry_mpi_copy( gcry_mpi_t a )
+{
+ int i;
+ gcry_mpi_t b;
+
+ if( a && (a->flags & 4) ) {
+ void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
+ : gcry_xmalloc( (a->sign+7)/8 );
+ memcpy( p, a->d, (a->sign+7)/8 );
+ b = gcry_mpi_set_opaque( NULL, p, a->sign );
+ }
+ else if( a ) {
+ b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
+ : mpi_alloc( a->nlimbs );
+ b->nlimbs = a->nlimbs;
+ b->sign = a->sign;
+ b->flags = a->flags;
+ for(i=0; i < b->nlimbs; i++ )
+ b->d[i] = a->d[i];
+ }
+ else
+ b = NULL;
+ return b;
+}
+
+
+/****************
+ * This function allocates an MPI which is optimized to hold
+ * a value as large as the one given in the argument and allocates it
+ * with the same flags as A.
+ */
+gcry_mpi_t
+_gcry_mpi_alloc_like( gcry_mpi_t a )
+{
+ gcry_mpi_t b;
+
+ if( a && (a->flags & 4) ) {
+ int n = (a->sign+7)/8;
+ void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
+ : gcry_malloc( n );
+ memcpy( p, a->d, n );
+ b = gcry_mpi_set_opaque( NULL, p, a->sign );
+ }
+ else if( a ) {
+ b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
+ : mpi_alloc( a->nlimbs );
+ b->nlimbs = 0;
+ b->sign = 0;
+ b->flags = a->flags;
+ }
+ else
+ b = NULL;
+ return b;
+}
+
+
+gcry_mpi_t
+gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
+{
+ mpi_ptr_t wp, up;
+ mpi_size_t usize = u->nlimbs;
+ int usign = u->sign;
+
+ if (!w)
+ w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
+ RESIZE_IF_NEEDED(w, usize);
+ wp = w->d;
+ up = u->d;
+ MPN_COPY( wp, up, usize );
+ w->nlimbs = usize;
+ w->flags = u->flags;
+ w->sign = usign;
+ return w;
+}
+
+
+gcry_mpi_t
+gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
+{
+ if (!w)
+ w = _gcry_mpi_alloc (1);
+ /* FIXME: If U is 0 we have no need to resize and thus possible
+ allocating the the limbs. */
+ RESIZE_IF_NEEDED(w, 1);
+ w->d[0] = u;
+ w->nlimbs = u? 1:0;
+ w->sign = 0;
+ w->flags = 0;
+ return w;
+}
+
+gcry_err_code_t
+_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ unsigned long x = 0;
+
+ if (w->nlimbs > 1)
+ err = GPG_ERR_TOO_LARGE;
+ else if (w->nlimbs == 1)
+ x = w->d[0];
+ else
+ x = 0;
+
+ if (! err)
+ *u = x;
+
+ return err;
+}
+
+gcry_error_t
+gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ err = _gcry_mpi_get_ui (w, u);
+
+ return gcry_error (err);
+}
+
+gcry_mpi_t
+_gcry_mpi_alloc_set_ui( unsigned long u)
+{
+ gcry_mpi_t w = mpi_alloc(1);
+ w->d[0] = u;
+ w->nlimbs = u? 1:0;
+ w->sign = 0;
+ return w;
+}
+
+void
+gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
+{
+ struct gcry_mpi tmp;
+
+ tmp = *a; *a = *b; *b = tmp;
+}
+
+
+gcry_mpi_t
+gcry_mpi_new( unsigned int nbits )
+{
+ return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
+ / BITS_PER_MPI_LIMB );
+}
+
+
+gcry_mpi_t
+gcry_mpi_snew( unsigned int nbits )
+{
+ return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
+ / BITS_PER_MPI_LIMB );
+}
+
+void
+gcry_mpi_release( gcry_mpi_t a )
+{
+ _gcry_mpi_free( a );
+}
+
+void
+gcry_mpi_randomize( gcry_mpi_t w,
+ unsigned int nbits, enum gcry_random_level level )
+{
+ unsigned char *p;
+ size_t nbytes = (nbits+7)/8;
+
+ if (level == GCRY_WEAK_RANDOM)
+ {
+ p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
+ : gcry_xmalloc (nbytes);
+ gcry_create_nonce (p, nbytes);
+ }
+ else
+ {
+ p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
+ : gcry_random_bytes (nbytes, level);
+ }
+ _gcry_mpi_set_buffer( w, p, nbytes, 0 );
+ gcry_free (p);
+}
+
+
+void
+gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
+{
+ switch( flag ) {
+ case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
+ case GCRYMPI_FLAG_OPAQUE:
+ default: log_bug("invalid flag value\n");
+ }
+}
+
+void
+gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
+{
+ (void)a; /* Not yet used. */
+
+ switch (flag)
+ {
+ case GCRYMPI_FLAG_SECURE:
+ case GCRYMPI_FLAG_OPAQUE:
+ default: log_bug("invalid flag value\n");
+ }
+}
+
+int
+gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
+{
+ switch (flag)
+ {
+ case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
+ case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
+ default: log_bug("invalid flag value\n");
+ }
+ /*NOTREACHED*/
+ return 0;
+}
+
diff --git a/libgcrypt-1.4.6/random/random-csprng.c b/libgcrypt-1.4.6/random/random-csprng.c
index aca977e..2e07dc3 100644
--- a/libgcrypt-1.4.6/random/random-csprng.c
+++ b/libgcrypt-1.4.6/random/random-csprng.c
@@ -1,1397 +1,1408 @@
-/* random-csprng.c - CSPRNG style random number generator (libgcrypt classic)
- * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- This random number generator is modelled after the one described in
- Peter Gutmann's 1998 Usenix Security Symposium paper: "Software
- Generation of Practically Strong Random Numbers". See also chapter
- 6 in his book "Cryptographic Security Architecture", New York,
- 2004, ISBN 0-387-95387-6.
-
- Note that the acronym CSPRNG stands for "Continuously Seeded
- PseudoRandom Number Generator" as used in Peter's implementation of
- the paper and not only for "Cryptographically Secure PseudoRandom
- Number Generator".
- */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_GETHRTIME
-#include <sys/times.h>
-#endif
-#ifdef HAVE_GETTIMEOFDAY
-#include <sys/time.h>
-#endif
-#ifdef HAVE_GETRUSAGE
-#include <sys/resource.h>
-#endif
-#ifdef __MINGW32__
-#include <process.h>
-#endif
-#include "g10lib.h"
-#include "../cipher/rmd.h"
-#include "random.h"
-#include "rand-internal.h"
-#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype. */
-#include "ath.h"
-
-#ifndef RAND_MAX /* For SunOS. */
-#define RAND_MAX 32767
-#endif
-
-/* Check whether we can lock the seed file read write. */
-#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
-#define LOCK_SEED_FILE 1
-#else
-#define LOCK_SEED_FILE 0
-#endif
-
-/* Define the constant we use for transforming the pool at read-out. */
-#if SIZEOF_UNSIGNED_LONG == 8
-#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
-#elif SIZEOF_UNSIGNED_LONG == 4
-#define ADD_VALUE 0xa5a5a5a5
-#else
-#error weird size for an unsigned long
-#endif
-
-/* Contstants pertaining to the hash pool. */
-#define BLOCKLEN 64 /* Hash this amount of bytes... */
-#define DIGESTLEN 20 /* ... into a digest of this length (rmd160). */
-/* POOLBLOCKS is the number of digests which make up the pool. */
-#define POOLBLOCKS 30
-/* POOLSIZE must be a multiple of the digest length to make the AND
- operations faster, the size should also be a multiple of unsigned
- long. */
-#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
-#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
-#error Please make sure that poolsize is a multiple of unsigned long
-#endif
-#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
-
-
-/* RNDPOOL is the pool we use to collect the entropy and to stir it
- up. Its allocated size is POOLSIZE+BLOCKLEN. Note that this is
- also an indication on whether the module has been fully
- initialized. */
-static unsigned char *rndpool;
-
-/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
- Its allocated size is also POOLSIZE+BLOCKLEN. */
-static unsigned char *keypool;
-
-/* This is the offset into RNDPOOL where the next random bytes are to
- be mixed in. */
-static size_t pool_writepos;
-
-/* When reading data out of KEYPOOL, we start the read at different
- positions. This variable keeps track on where to read next. */
-static size_t pool_readpos;
-
-/* This flag is set to true as soon as the pool has been completely
- filled the first time. This may happen either by rereading a seed
- file or by adding enough entropy. */
-static int pool_filled;
-
-/* This counter is used to track whether the initial seeding has been
- done with enough bytes from a reliable entropy source. */
-static size_t pool_filled_counter;
-
-/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
- have stricter requirements on what kind of entropy is in the pool.
- In particular POOL_FILLED is not sufficient. Thus we add some
- extra seeding and set this flag to true if the extra seeding has
- been done. */
-static int did_initial_extra_seeding;
-
-/* This variable is used to estimated the amount of fresh entropy
- available in RNDPOOL. */
-static int pool_balance;
-
-/* After a mixing operation this variable will be set to true and
- cleared if new entropy has been added or a remix is required for
- otehr reasons. */
-static int just_mixed;
-
-/* The name of the seed file or NULL if no seed file has been defined.
- The seed file needs to be regsitered at initialiation time. We
- keep a malloced copy here. */
-static char *seed_file_name;
-
-/* If a seed file has been registered and maybe updated on exit this
- flag set. */
-static int allow_seed_file_update;
-
-/* Option flag set at initialiation time to force allocation of the
- pool in secure memory. */
-static int secure_alloc;
-
-/* This function pointer is set to the actual entropy gathering
- function during initailization. After initialization it is
- guaranteed to point to function. (On systems without a random
- gatherer module a dummy function is used).*/
-static int (*slow_gather_fnc)(void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins, size_t, int);
-
-/* This function is set to the actual fast entropy gathering fucntion
- during initialization. If it is NULL, no such function is
- available. */
-static void (*fast_gather_fnc)(void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins);
-
-
-/* Option flag useful for debugging and the test suite. If set
- requests for very strong random are degraded to strong random. Not
- used by regular applications. */
-static int quick_test;
-
-/* On systems without entropy gathering modules, this flag is set to
- indicate that the random generator is not working properly. A
- warning message is issued as well. This is useful only for
- debugging and during development. */
-static int faked_rng;
-
-/* This is the lock we use to protect all pool operations. */
-static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER;
-
-/* This is a helper for assert calls. These calls are used to assert
- that functions are called in a locked state. It is not meant to be
- thread-safe but as a method to get aware of missing locks in the
- test suite. */
-static int pool_is_locked;
-
-/* This is the lock we use to protect the buffer used by the nonce
- generation. */
-static ath_mutex_t nonce_buffer_lock = ATH_MUTEX_INITIALIZER;
-
-
-/* We keep some counters in this structure for the sake of the
- _gcry_random_dump_stats () function. */
-static struct
-{
- unsigned long mixrnd;
- unsigned long mixkey;
- unsigned long slowpolls;
- unsigned long fastpolls;
- unsigned long getbytes1;
- unsigned long ngetbytes1;
- unsigned long getbytes2;
- unsigned long ngetbytes2;
- unsigned long addbytes;
- unsigned long naddbytes;
-} rndstats;
-
-
-
-/* --- Stuff pertaining to the random daemon support. --- */
-#ifdef USE_RANDOM_DAEMON
-
-/* If ALLOW_DAEMON is true, the module will try to use the random
- daemon first. If the daemon has failed, this variable is set to
- back to false and the code continues as normal. Note, we don't
- test this flag in a locked state because a wrong value does not
- harm and the trhead will find out itself that the daemon does not
- work and set it (again) to false. */
-static int allow_daemon;
-
-/* During initialization, the user may set a non-default socket name
- for accessing the random daemon. If this value is NULL, the
- default name will be used. */
-static char *daemon_socket_name;
-
-#endif /*USE_RANDOM_DAEMON*/
-
-
-
-/* --- Prototypes --- */
-static void read_pool (byte *buffer, size_t length, int level );
-static void add_randomness (const void *buffer, size_t length,
- enum random_origins origin);
-static void random_poll (void);
-static void do_fast_random_poll (void);
-static int (*getfnc_gather_random (void))(void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins, size_t, int);
-static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins);
-static void read_random_source (enum random_origins origin,
- size_t length, int level);
-static int gather_faked (void (*add)(const void*, size_t, enum random_origins),
- enum random_origins, size_t length, int level );
-
-
-
-/* --- Functions --- */
-
-
-/* Basic initialization which is required to initialize mutexes and
- such. It does not run a full initialization so that the filling of
- the random pool can be delayed until it is actually needed. We
- assume that this function is used before any concurrent access
- happens. */
-static void
-initialize_basics(void)
-{
- static int initialized;
- int err;
-
- if (!initialized)
- {
- initialized = 1;
- err = ath_mutex_init (&pool_lock);
- if (err)
- log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
-
- err = ath_mutex_init (&nonce_buffer_lock);
- if (err)
- log_fatal ("failed to create the nonce buffer lock: %s\n",
- strerror (err) );
-
-#ifdef USE_RANDOM_DAEMON
- _gcry_daemon_initialize_basics ();
-#endif /*USE_RANDOM_DAEMON*/
-
- /* Make sure that we are still using the values we have
- traditionally used for the random levels. */
- gcry_assert (GCRY_WEAK_RANDOM == 0
- && GCRY_STRONG_RANDOM == 1
- && GCRY_VERY_STRONG_RANDOM == 2);
- }
-}
-
-/* Take the pool lock. */
-static void
-lock_pool (void)
-{
- int err;
-
- err = ath_mutex_lock (&pool_lock);
- if (err)
- log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
- pool_is_locked = 1;
-}
-
-/* Release the pool lock. */
-static void
-unlock_pool (void)
-{
- int err;
-
- pool_is_locked = 0;
- err = ath_mutex_unlock (&pool_lock);
- if (err)
- log_fatal ("failed to release the pool lock: %s\n", strerror (err));
-}
-
-
-/* Full initialization of this module. */
-static void
-initialize(void)
-{
- /* Although the basic initialization should have happened already,
- we call it here to make sure that all prerequisites are met. */
- initialize_basics ();
-
- /* Now we can look the pool and complete the initialization if
- necessary. */
- lock_pool ();
- if (!rndpool)
- {
- /* The data buffer is allocated somewhat larger, so that we can
- use this extra space (which is allocated in secure memory) as
- a temporary hash buffer */
- rndpool = (secure_alloc
- ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
- : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
- keypool = (secure_alloc
- ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
- : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
-
- /* Setup the slow entropy gathering function. The code requires
- that this function exists. */
- slow_gather_fnc = getfnc_gather_random ();
- if (!slow_gather_fnc)
- {
- faked_rng = 1;
- slow_gather_fnc = gather_faked;
- }
-
- /* Setup the fast entropy gathering function. */
- fast_gather_fnc = getfnc_fast_random_poll ();
-
- }
- unlock_pool ();
-}
-
-
-
-
-/* Initialize this random subsystem. If FULL is false, this function
- merely calls the initialize and does not do anything more. Doing
- this is not really required but when running in a threaded
- environment we might get a race condition otherwise. */
-void
-_gcry_rngcsprng_initialize (int full)
-{
- if (!full)
- initialize_basics ();
- else
- initialize ();
-}
-
-
-void
-_gcry_rngcsprng_dump_stats (void)
-{
- /* In theory we would need to lock the stats here. However this
- function is usually called during cleanup and then we _might_ run
- into problems. */
-
- log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
- " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n",
- POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
- rndstats.naddbytes, rndstats.addbytes,
- rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
- rndstats.ngetbytes2, rndstats.getbytes2,
- _gcry_rndhw_failed_p()? " (hwrng failed)":"");
-}
-
-
-/* This function should be called during initialization and before
- intialization of this module to place the random pools into secure
- memory. */
-void
-_gcry_rngcsprng_secure_alloc (void)
-{
- secure_alloc = 1;
-}
-
-
-/* This may be called before full initialization to degrade the
- quality of the RNG for the sake of a faster running test suite. */
-void
-_gcry_rngcsprng_enable_quick_gen (void)
-{
- quick_test = 1;
-}
-
-
-void
-_gcry_rngcsprng_set_daemon_socket (const char *socketname)
-{
-#ifdef USE_RANDOM_DAEMON
- if (daemon_socket_name)
- BUG ();
-
- daemon_socket_name = gcry_xstrdup (socketname);
-#else /*!USE_RANDOM_DAEMON*/
- (void)socketname;
-#endif /*!USE_RANDOM_DAEMON*/
-}
-
-/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set
- to 0, disable the use of the daemon. With ONOF set to -1, return
- whether the daemon has been enabled. */
-int
-_gcry_rngcsprng_use_daemon (int onoff)
-{
-#ifdef USE_RANDOM_DAEMON
- int last;
-
- /* This is not really thread safe. However it is expected that this
- function is being called during initialization and at that point
- we are for other reasons not really thread safe. We do not want
- to lock it because we might eventually decide that this function
- may even be called prior to gcry_check_version. */
- last = allow_daemon;
- if (onoff != -1)
- allow_daemon = onoff;
-
- return last;
-#else /*!USE_RANDOM_DAEMON*/
- (void)onoff;
- return 0;
-#endif /*!USE_RANDOM_DAEMON*/
-}
-
-
-/* This function returns true if no real RNG is available or the
- quality of the RNG has been degraded for test purposes. */
-int
-_gcry_rngcsprng_is_faked (void)
-{
- /* We need to initialize due to the runtime determination of
- available entropy gather modules. */
- initialize();
- return (faked_rng || quick_test);
-}
-
-
-/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
- should be in the range of 0..100 to indicate the goodness of the
- entropy added, or -1 for goodness not known. */
-gcry_error_t
-_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
-{
- size_t nbytes;
- const char *bufptr;
-
- if (quality == -1)
- quality = 35;
- else if (quality > 100)
- quality = 100;
- else if (quality < 0)
- quality = 0;
-
- if (!buf)
- return gpg_error (GPG_ERR_INV_ARG);
-
- if (!buflen || quality < 10)
- return 0; /* Take a shortcut. */
-
- /* Because we don't increment the entropy estimation with FASTPOLL,
- we don't need to take lock that estimation while adding from an
- external source. This limited entropy estimation also means that
- we can't take QUALITY into account. */
- initialize_basics ();
- bufptr = buf;
- while (buflen)
- {
- nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
- lock_pool ();
- if (rndpool)
- add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
- unlock_pool ();
- bufptr += nbytes;
- buflen -= nbytes;
- }
- return 0;
-}
-
-
-/* Public function to fill the buffer with LENGTH bytes of
- cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
- not very strong, GCRY_STRONG_RANDOM is strong enough for most
- usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
- may be very slow. */
-void
-_gcry_rngcsprng_randomize (void *buffer, size_t length,
- enum gcry_random_level level)
-{
- unsigned char *p;
-
- /* Make sure we are initialized. */
- initialize ();
-
- /* Handle our hack used for regression tests of Libgcrypt. */
- if ( quick_test && level > GCRY_STRONG_RANDOM )
- level = GCRY_STRONG_RANDOM;
-
- /* Make sure the level is okay. */
- level &= 3;
-
-#ifdef USE_RANDOM_DAEMON
- if (allow_daemon
- && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
- return; /* The daemon succeeded. */
- allow_daemon = 0; /* Daemon failed - switch off. */
-#endif /*USE_RANDOM_DAEMON*/
-
- /* Acquire the pool lock. */
- lock_pool ();
-
- /* Update the statistics. */
- if (level >= GCRY_VERY_STRONG_RANDOM)
- {
- rndstats.getbytes2 += length;
- rndstats.ngetbytes2++;
- }
- else
- {
- rndstats.getbytes1 += length;
- rndstats.ngetbytes1++;
- }
-
- /* Read the random into the provided buffer. */
- for (p = buffer; length > 0;)
- {
- size_t n;
-
- n = length > POOLSIZE? POOLSIZE : length;
- read_pool (p, n, level);
- length -= n;
- p += n;
- }
-
- /* Release the pool lock. */
- unlock_pool ();
-}
-
-
-
-
-/*
- Mix the pool:
-
- |........blocks*20byte........|20byte|..44byte..|
- <..44byte..> <20byte>
- | |
- | +------+
- +---------------------------|----------+
- v v
- |........blocks*20byte........|20byte|..44byte..|
- <.....64bytes.....>
- |
- +----------------------------------+
- Hash
- v
- |.............................|20byte|..44byte..|
- <20byte><20byte><..44byte..>
- | |
- | +---------------------+
- +-----------------------------+ |
- v v
- |.............................|20byte|..44byte..|
- <.....64byte......>
- |
- +-------------------------+
- Hash
- v
- |.............................|20byte|..44byte..|
- <20byte><20byte><..44byte..>
-
- and so on until we did this for all blocks.
-
- To better protect against implementation errors in this code, we
- xor a digest of the entire pool into the pool before mixing.
-
- Note: this function must only be called with a locked pool.
- */
-static void
-mix_pool(unsigned char *pool)
-{
- static unsigned char failsafe_digest[DIGESTLEN];
- static int failsafe_digest_valid;
-
- unsigned char *hashbuf = pool + POOLSIZE;
- unsigned char *p, *pend;
- int i, n;
- RMD160_CONTEXT md;
-
-#if DIGESTLEN != 20
-#error must have a digest length of 20 for ripe-md-160
-#endif
-
- gcry_assert (pool_is_locked);
- _gcry_rmd160_init( &md );
-
- /* Loop over the pool. */
- pend = pool + POOLSIZE;
- memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
- memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
- _gcry_rmd160_mixblock( &md, hashbuf);
- memcpy(pool, hashbuf, 20 );
-
- if (failsafe_digest_valid && pool == rndpool)
- {
- for (i=0; i < 20; i++)
- pool[i] ^= failsafe_digest[i];
- }
-
- p = pool;
- for (n=1; n < POOLBLOCKS; n++)
- {
- memcpy (hashbuf, p, DIGESTLEN);
-
- p += DIGESTLEN;
- if (p+DIGESTLEN+BLOCKLEN < pend)
- memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
- else
- {
- unsigned char *pp = p + DIGESTLEN;
-
- for (i=DIGESTLEN; i < BLOCKLEN; i++ )
- {
- if ( pp >= pend )
- pp = pool;
- hashbuf[i] = *pp++;
- }
- }
-
- _gcry_rmd160_mixblock ( &md, hashbuf);
- memcpy(p, hashbuf, 20 );
- }
-
- /* Our hash implementation does only leave small parts (64 bytes)
- of the pool on the stack, so it is okay not to require secure
- memory here. Before we use this pool, it will be copied to the
- help buffer anyway. */
- if ( pool == rndpool)
- {
- _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
- failsafe_digest_valid = 1;
- }
-
- _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
-}
-
-
-void
-_gcry_rngcsprng_set_seed_file (const char *name)
-{
- if (seed_file_name)
- BUG ();
- seed_file_name = gcry_xstrdup (name);
-}
-
-
-/* Lock an open file identified by file descriptor FD and wait a
- reasonable time to succeed. With FOR_WRITE set to true a write
- lock will be taken. FNAME is used only for diagnostics. Returns 0
- on success or -1 on error. */
-static int
-lock_seed_file (int fd, const char *fname, int for_write)
-{
-#if LOCK_SEED_FILE
- struct flock lck;
- struct timeval tv;
- int backoff=0;
-
- /* We take a lock on the entire file. */
- memset (&lck, 0, sizeof lck);
- lck.l_type = for_write? F_WRLCK : F_RDLCK;
- lck.l_whence = SEEK_SET;
-
- while (fcntl (fd, F_SETLK, &lck) == -1)
- {
- if (errno != EAGAIN && errno != EACCES)
- {
- log_info (_("can't lock `%s': %s\n"), fname, strerror (errno));
- return -1;
- }
-
- if (backoff > 2) /* Show the first message after ~2.25 seconds. */
- log_info( _("waiting for lock on `%s'...\n"), fname);
-
- tv.tv_sec = backoff;
- tv.tv_usec = 250000;
- select (0, NULL, NULL, NULL, &tv);
- if (backoff < 10)
- backoff++ ;
- }
-#endif /*LOCK_SEED_FILE*/
- return 0;
-}
-
-
-/* Read in a seed from the random_seed file and return true if this
- was successful.
-
- Note: Multiple instances of applications sharing the same random
- seed file can be started in parallel, in which case they will read
- out the same pool and then race for updating it (the last update
- overwrites earlier updates). They will differentiate only by the
- weak entropy that is added in read_seed_file based on the PID and
- clock, and up to 16 bytes of weak random non-blockingly. The
- consequence is that the output of these different instances is
- correlated to some extent. In the perfect scenario, the attacker
- can control (or at least guess) the PID and clock of the
- application, and drain the system's entropy pool to reduce the "up
- to 16 bytes" above to 0. Then the dependencies of the inital
- states of the pools are completely known. */
-static int
-read_seed_file (void)
-{
- int fd;
- struct stat sb;
- unsigned char buffer[POOLSIZE];
- int n;
-
- gcry_assert (pool_is_locked);
-
- if (!seed_file_name)
- return 0;
-
-#ifdef HAVE_DOSISH_SYSTEM
- fd = open( seed_file_name, O_RDONLY | O_BINARY );
-#else
- fd = open( seed_file_name, O_RDONLY );
-#endif
- if( fd == -1 && errno == ENOENT)
- {
- allow_seed_file_update = 1;
- return 0;
- }
-
- if (fd == -1 )
- {
- log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
- return 0;
- }
- if (lock_seed_file (fd, seed_file_name, 0))
- {
- close (fd);
- return 0;
- }
- if (fstat( fd, &sb ) )
- {
- log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
- close(fd);
- return 0;
- }
- if (!S_ISREG(sb.st_mode) )
- {
- log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
- close(fd);
- return 0;
- }
- if (!sb.st_size )
- {
- log_info(_("note: random_seed file is empty\n") );
- close(fd);
- allow_seed_file_update = 1;
- return 0;
- }
- if (sb.st_size != POOLSIZE )
- {
- log_info(_("warning: invalid size of random_seed file - not used\n") );
- close(fd);
- return 0;
- }
-
- do
- {
- n = read( fd, buffer, POOLSIZE );
- }
- while (n == -1 && errno == EINTR );
-
- if (n != POOLSIZE)
- {
- log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
- close(fd);/*NOTREACHED*/
- return 0;
- }
-
- close(fd);
-
- add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
- /* add some minor entropy to the pool now (this will also force a mixing) */
- {
- pid_t x = getpid();
- add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
- }
- {
- time_t x = time(NULL);
- add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
- }
- {
- clock_t x = clock();
- add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
- }
-
- /* And read a few bytes from our entropy source. By using a level
- * of 0 this will not block and might not return anything with some
- * entropy drivers, however the rndlinux driver will use
- * /dev/urandom and return some stuff - Do not read too much as we
- * want to be friendly to the scare system entropy resource. */
- read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );
-
- allow_seed_file_update = 1;
- return 1;
-}
-
-
-void
-_gcry_rngcsprng_update_seed_file (void)
-{
- unsigned long *sp, *dp;
- int fd, i;
-
- /* We do only a basic initialization so that we can lock the pool.
- This is required to cope with the case that this function is
- called by some cleanup code at a point where the RNG has never
- been initialized. */
- initialize_basics ();
- lock_pool ();
-
- if ( !seed_file_name || !rndpool || !pool_filled )
- {
- unlock_pool ();
- return;
- }
- if ( !allow_seed_file_update )
- {
- unlock_pool ();
- log_info(_("note: random_seed file not updated\n"));
- return;
- }
-
- /* At this point we know that there is something in the pool and
- thus we can conclude that the pool has been fully initialized. */
-
-
- /* Copy the entropy pool to a scratch pool and mix both of them. */
- for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
- i < POOLWORDS; i++, dp++, sp++ )
- {
- *dp = *sp + ADD_VALUE;
- }
- mix_pool(rndpool); rndstats.mixrnd++;
- mix_pool(keypool); rndstats.mixkey++;
-
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
- fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
- S_IRUSR|S_IWUSR );
-#else
-# if LOCK_SEED_FILE
- fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
-# else
- fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
-# endif
-#endif
-
- if (fd == -1 )
- log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
- else if (lock_seed_file (fd, seed_file_name, 1))
- {
- close (fd);
- }
-#if LOCK_SEED_FILE
- else if (ftruncate (fd, 0))
- {
- log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
- close (fd);
- }
-#endif /*LOCK_SEED_FILE*/
- else
- {
- do
- {
- i = write (fd, keypool, POOLSIZE );
- }
- while (i == -1 && errno == EINTR);
- if (i != POOLSIZE)
- log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
- if (close(fd))
- log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
- }
-
- unlock_pool ();
-}
-
-
-/* Read random out of the pool. This function is the core of the
- public random functions. Note that Level GCRY_WEAK_RANDOM is not
- anymore handled special and in fact is an alias in the API for
- level GCRY_STRONG_RANDOM. Must be called with the pool already
- locked. */
-static void
-read_pool (byte *buffer, size_t length, int level)
-{
- int i;
- unsigned long *sp, *dp;
- /* The volatile is there to make sure the compiler does not optimize
- the code away in case the getpid function is badly attributed.
- Note that we keep a pid in a static variable as well as in a
- stack based one; the latter is to detect ill behaving thread
- libraries, ignoring the pool mutexes. */
- static volatile pid_t my_pid = (pid_t)(-1);
- volatile pid_t my_pid2;
-
- gcry_assert (pool_is_locked);
-
- retry:
- /* Get our own pid, so that we can detect a fork. */
- my_pid2 = getpid ();
- if (my_pid == (pid_t)(-1))
- my_pid = my_pid2;
- if ( my_pid != my_pid2 )
- {
- /* We detected a plain fork; i.e. we are now the child. Update
- the static pid and add some randomness. */
- pid_t x;
-
- my_pid = my_pid2;
- x = my_pid;
- add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
- just_mixed = 0; /* Make sure it will get mixed. */
- }
-
- gcry_assert (pool_is_locked);
-
- /* Our code does not allow to extract more than POOLSIZE. Better
- check it here. */
- if (length > POOLSIZE)
- {
- log_bug("too many random bits requested\n");
- }
-
- if (!pool_filled)
- {
- if (read_seed_file() )
- pool_filled = 1;
- }
-
- /* For level 2 quality (key generation) we always make sure that the
- pool has been seeded enough initially. */
- if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding)
- {
- size_t needed;
-
- pool_balance = 0;
- needed = length - pool_balance;
- if (needed < POOLSIZE/2)
- needed = POOLSIZE/2;
- else if( needed > POOLSIZE )
- BUG ();
- read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
- GCRY_VERY_STRONG_RANDOM);
- pool_balance += needed;
- did_initial_extra_seeding = 1;
- }
-
- /* For level 2 make sure that there is enough random in the pool. */
- if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length)
- {
- size_t needed;
-
- if (pool_balance < 0)
- pool_balance = 0;
- needed = length - pool_balance;
- if (needed > POOLSIZE)
- BUG ();
- read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
- GCRY_VERY_STRONG_RANDOM);
- pool_balance += needed;
- }
-
- /* Make sure the pool is filled. */
- while (!pool_filled)
- random_poll();
-
- /* Always do a fast random poll (we have to use the unlocked version). */
- do_fast_random_poll();
-
- /* Mix the pid in so that we for sure won't deliver the same random
- after a fork. */
- {
- pid_t apid = my_pid;
- add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT);
- }
-
- /* Mix the pool (if add_randomness() didn't it). */
- if (!just_mixed)
- {
- mix_pool(rndpool);
- rndstats.mixrnd++;
- }
-
- /* Create a new pool. */
- for(i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
- i < POOLWORDS; i++, dp++, sp++ )
- *dp = *sp + ADD_VALUE;
-
- /* Mix both pools. */
- mix_pool(rndpool); rndstats.mixrnd++;
- mix_pool(keypool); rndstats.mixkey++;
-
- /* Read the requested data. We use a read pointer to read from a
- different position each time. */
- while (length--)
- {
- *buffer++ = keypool[pool_readpos++];
- if (pool_readpos >= POOLSIZE)
- pool_readpos = 0;
- pool_balance--;
- }
-
- if (pool_balance < 0)
- pool_balance = 0;
-
- /* Clear the keypool. */
- memset (keypool, 0, POOLSIZE);
-
- /* We need to detect whether a fork has happened. A fork might have
- an identical pool and thus the child and the parent could emit
- the very same random number. This test here is to detect forks
- in a multi-threaded process. It does not work with all thread
- implementations in particular not with pthreads. However it is
- good enough for GNU Pth. */
- if ( getpid () != my_pid2 )
- {
- pid_t x = getpid();
- add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
- just_mixed = 0; /* Make sure it will get mixed. */
- my_pid = x; /* Also update the static pid. */
- goto retry;
- }
-}
-
-
-
-/* Add LENGTH bytes of randomness from buffer to the pool. ORIGIN is
- used to specify the randomness origin. This is one of the
- RANDOM_ORIGIN_* values. */
-static void
-add_randomness (const void *buffer, size_t length, enum random_origins origin)
-{
- const unsigned char *p = buffer;
- size_t count = 0;
-
- gcry_assert (pool_is_locked);
-
- rndstats.addbytes += length;
- rndstats.naddbytes++;
- while (length-- )
- {
- rndpool[pool_writepos++] ^= *p++;
- count++;
- if (pool_writepos >= POOLSIZE )
- {
- /* It is possible that we are invoked before the pool is
- filled using an unreliable origin of entropy, for example
- the fast random poll. To avoid flagging the pool as
- filled in this case, we track the initial filling state
- separately. See also the remarks about the seed file. */
- if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
- {
- pool_filled_counter += count;
- count = 0;
- if (pool_filled_counter >= POOLSIZE)
- pool_filled = 1;
- }
- pool_writepos = 0;
- mix_pool(rndpool); rndstats.mixrnd++;
- just_mixed = !length;
- }
- }
-}
-
-
-
-static void
-random_poll()
-{
- rndstats.slowpolls++;
- read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM);
-}
-
-
-/* Runtime determination of the slow entropy gathering module. */
-static int (*
-getfnc_gather_random (void))(void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins, size_t, int)
-{
- int (*fnc)(void (*)(const void*, size_t, enum random_origins),
- enum random_origins, size_t, int);
-
-#if USE_RNDLINUX
- if ( !access (NAME_OF_DEV_RANDOM, R_OK)
- && !access (NAME_OF_DEV_URANDOM, R_OK))
- {
- fnc = _gcry_rndlinux_gather_random;
- return fnc;
- }
-#endif
-
-#if USE_RNDEGD
- if ( _gcry_rndegd_connect_socket (1) != -1 )
- {
- fnc = _gcry_rndegd_gather_random;
- return fnc;
- }
-#endif
-
-#if USE_RNDUNIX
- fnc = _gcry_rndunix_gather_random;
- return fnc;
-#endif
-
-#if USE_RNDW32
- fnc = _gcry_rndw32_gather_random;
- return fnc;
-#endif
-
- log_fatal (_("no entropy gathering module detected\n"));
-
- return NULL; /*NOTREACHED*/
-}
-
-/* Runtime determination of the fast entropy gathering function.
- (Currently a compile time method is used.) */
-static void (*
-getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
- enum random_origins),
- enum random_origins)
-{
-#if USE_RNDW32
- return _gcry_rndw32_gather_random_fast;
-#endif
- return NULL;
-}
-
-
-
-static void
-do_fast_random_poll (void)
-{
- gcry_assert (pool_is_locked);
-
- rndstats.fastpolls++;
-
- if (fast_gather_fnc)
- fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL);
-
- /* Continue with the generic functions. */
-#if HAVE_GETHRTIME
- {
- hrtime_t tv;
- tv = gethrtime();
- add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL );
- }
-#elif HAVE_GETTIMEOFDAY
- {
- struct timeval tv;
- if( gettimeofday( &tv, NULL ) )
- BUG();
- add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
- add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL );
- }
-#elif HAVE_CLOCK_GETTIME
- { struct timespec tv;
- if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
- BUG();
- add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
- add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL );
- }
-#else /* use times */
-# ifndef HAVE_DOSISH_SYSTEM
- { struct tms buf;
- times( &buf );
- add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
- }
-# endif
-#endif
-
-#ifdef HAVE_GETRUSAGE
-# ifdef RUSAGE_SELF
- {
- struct rusage buf;
- /* QNX/Neutrino does return ENOSYS - so we just ignore it and add
- whatever is in buf. In a chroot environment it might not work
- at all (i.e. because /proc/ is not accessible), so we better
- ignore all error codes and hope for the best. */
- getrusage (RUSAGE_SELF, &buf );
- add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
- memset( &buf, 0, sizeof buf );
- }
-# else /*!RUSAGE_SELF*/
-# ifdef __GCC__
-# warning There is no RUSAGE_SELF on this system
-# endif
-# endif /*!RUSAGE_SELF*/
-#endif /*HAVE_GETRUSAGE*/
-
- /* Time and clock are availabe on all systems - so we better do it
- just in case one of the above functions didn't work. */
- {
- time_t x = time(NULL);
- add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
- }
- {
- clock_t x = clock();
- add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
- }
-
- /* If the system features a fast hardware RNG, read some bytes from
- there. */
- _gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL);
-}
-
-
-/* The fast random pool function as called at some places in
- libgcrypt. This is merely a wrapper to make sure that this module
- is initalized and to look the pool. Note, that this function is a
- NOP unless a random function has been used or _gcry_initialize (1)
- has been used. We use this hack so that the internal use of this
- function in cipher_open and md_open won't start filling up the
- random pool, even if no random will be required by the process. */
-void
-_gcry_rngcsprng_fast_poll (void)
-{
- initialize_basics ();
-
- lock_pool ();
- if (rndpool)
- {
- /* Yes, we are fully initialized. */
- do_fast_random_poll ();
- }
- unlock_pool ();
-}
-
-
-
-static void
-read_random_source (enum random_origins orgin, size_t length, int level )
-{
- if ( !slow_gather_fnc )
- log_fatal ("Slow entropy gathering module not yet initialized\n");
-
- if ( slow_gather_fnc (add_randomness, orgin, length, level) < 0)
- log_fatal ("No way to gather entropy for the RNG\n");
-}
-
-
-static int
-gather_faked (void (*add)(const void*, size_t, enum random_origins),
- enum random_origins origin, size_t length, int level )
-{
- static int initialized=0;
- size_t n;
- char *buffer, *p;
-
- (void)add;
- (void)level;
-
- if ( !initialized )
- {
- log_info(_("WARNING: using insecure random number generator!!\n"));
- initialized=1;
-#ifdef HAVE_RAND
- srand( time(NULL)*getpid());
-#else
- srandom( time(NULL)*getpid());
-#endif
- }
-
- p = buffer = gcry_xmalloc( length );
- n = length;
-#ifdef HAVE_RAND
- while ( n-- )
- *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
-#else
- while ( n-- )
- *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
-#endif
- add_randomness ( buffer, length, origin );
- gcry_free (buffer);
- return 0; /* okay */
-}
-
-
-/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
-void
-_gcry_rngcsprng_create_nonce (void *buffer, size_t length)
-{
- static unsigned char nonce_buffer[20+8];
- static int nonce_buffer_initialized = 0;
- static volatile pid_t my_pid; /* The volatile is there to make sure the
- compiler does not optimize the code away
- in case the getpid function is badly
- attributed. */
- volatile pid_t apid;
- unsigned char *p;
- size_t n;
- int err;
-
- /* Make sure we are initialized. */
- initialize ();
-
-#ifdef USE_RANDOM_DAEMON
- if (allow_daemon
- && !_gcry_daemon_create_nonce (daemon_socket_name, buffer, length))
- return; /* The daemon succeeded. */
- allow_daemon = 0; /* Daemon failed - switch off. */
-#endif /*USE_RANDOM_DAEMON*/
-
- /* Acquire the nonce buffer lock. */
- err = ath_mutex_lock (&nonce_buffer_lock);
- if (err)
- log_fatal ("failed to acquire the nonce buffer lock: %s\n",
- strerror (err));
-
- apid = getpid ();
- /* The first time intialize our buffer. */
- if (!nonce_buffer_initialized)
- {
- time_t atime = time (NULL);
- pid_t xpid = apid;
-
- my_pid = apid;
-
- if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
- BUG ();
-
- /* Initialize the first 20 bytes with a reasonable value so that
- a failure of gcry_randomize won't affect us too much. Don't
- care about the uninitialized remaining bytes. */
- p = nonce_buffer;
- memcpy (p, &xpid, sizeof xpid);
- p += sizeof xpid;
- memcpy (p, &atime, sizeof atime);
-
- /* Initialize the never changing private part of 64 bits. */
- gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
-
- nonce_buffer_initialized = 1;
- }
- else if ( my_pid != apid )
- {
- /* We forked. Need to reseed the buffer - doing this for the
- private part should be sufficient. */
- gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
- /* Update the pid so that we won't run into here again and
- again. */
- my_pid = apid;
- }
-
- /* Create the nonce by hashing the entire buffer, returning the hash
- and updating the first 20 bytes of the buffer with this hash. */
- for (p = buffer; length > 0; length -= n, p += n)
- {
- _gcry_sha1_hash_buffer (nonce_buffer,
- nonce_buffer, sizeof nonce_buffer);
- n = length > 20? 20 : length;
- memcpy (p, nonce_buffer, n);
- }
-
-
- /* Release the nonce buffer lock. */
- err = ath_mutex_unlock (&nonce_buffer_lock);
- if (err)
- log_fatal ("failed to release the nonce buffer lock: %s\n",
- strerror (err));
-
-}
+/* random-csprng.c - CSPRNG style random number generator (libgcrypt classic)
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ * 2007, 2008, 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This random number generator is modelled after the one described in
+ Peter Gutmann's 1998 Usenix Security Symposium paper: "Software
+ Generation of Practically Strong Random Numbers". See also chapter
+ 6 in his book "Cryptographic Security Architecture", New York,
+ 2004, ISBN 0-387-95387-6.
+
+ Note that the acronym CSPRNG stands for "Continuously Seeded
+ PseudoRandom Number Generator" as used in Peter's implementation of
+ the paper and not only for "Cryptographically Secure PseudoRandom
+ Number Generator".
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_GETHRTIME
+#include <sys/times.h>
+#endif
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+#endif
+#ifdef __MINGW32__
+#include <process.h>
+#endif
+#include "g10lib.h"
+#include "../cipher/rmd.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype. */
+#include "ath.h"
+
+#ifndef RAND_MAX /* For SunOS. */
+#define RAND_MAX 32767
+#endif
+
+/* Check whether we can lock the seed file read write. */
+#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
+#define LOCK_SEED_FILE 1
+#else
+#define LOCK_SEED_FILE 0
+#endif
+
+/* Define the constant we use for transforming the pool at read-out. */
+#if SIZEOF_UNSIGNED_LONG == 8
+#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
+#elif SIZEOF_UNSIGNED_LONG == 4
+#define ADD_VALUE 0xa5a5a5a5
+#else
+#error weird size for an unsigned long
+#endif
+
+/* Contstants pertaining to the hash pool. */
+#define BLOCKLEN 64 /* Hash this amount of bytes... */
+#define DIGESTLEN 20 /* ... into a digest of this length (rmd160). */
+/* POOLBLOCKS is the number of digests which make up the pool. */
+#define POOLBLOCKS 30
+/* POOLSIZE must be a multiple of the digest length to make the AND
+ operations faster, the size should also be a multiple of unsigned
+ long. */
+#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
+#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
+#error Please make sure that poolsize is a multiple of unsigned long
+#endif
+#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
+
+
+/* RNDPOOL is the pool we use to collect the entropy and to stir it
+ up. Its allocated size is POOLSIZE+BLOCKLEN. Note that this is
+ also an indication on whether the module has been fully
+ initialized. */
+static unsigned char *rndpool;
+
+/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
+ Its allocated size is also POOLSIZE+BLOCKLEN. */
+static unsigned char *keypool;
+
+/* This is the offset into RNDPOOL where the next random bytes are to
+ be mixed in. */
+static size_t pool_writepos;
+
+/* When reading data out of KEYPOOL, we start the read at different
+ positions. This variable keeps track on where to read next. */
+static size_t pool_readpos;
+
+/* This flag is set to true as soon as the pool has been completely
+ filled the first time. This may happen either by rereading a seed
+ file or by adding enough entropy. */
+static int pool_filled;
+
+/* This counter is used to track whether the initial seeding has been
+ done with enough bytes from a reliable entropy source. */
+static size_t pool_filled_counter;
+
+/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
+ have stricter requirements on what kind of entropy is in the pool.
+ In particular POOL_FILLED is not sufficient. Thus we add some
+ extra seeding and set this flag to true if the extra seeding has
+ been done. */
+static int did_initial_extra_seeding;
+
+/* This variable is used to estimated the amount of fresh entropy
+ available in RNDPOOL. */
+static int pool_balance;
+
+/* After a mixing operation this variable will be set to true and
+ cleared if new entropy has been added or a remix is required for
+ other reasons. */
+static int just_mixed;
+
+/* The name of the seed file or NULL if no seed file has been defined.
+ The seed file needs to be regsitered at initialiation time. We
+ keep a malloced copy here. */
+static char *seed_file_name;
+
+/* If a seed file has been registered and maybe updated on exit this
+ flag set. */
+static int allow_seed_file_update;
+
+/* Option flag set at initialiation time to force allocation of the
+ pool in secure memory. */
+static int secure_alloc;
+
+/* This function pointer is set to the actual entropy gathering
+ function during initailization. After initialization it is
+ guaranteed to point to function. (On systems without a random
+ gatherer module a dummy function is used).*/
+static int (*slow_gather_fnc)(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int);
+
+/* This function is set to the actual fast entropy gathering function
+ during initialization. If it is NULL, no such function is
+ available. */
+static void (*fast_gather_fnc)(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins);
+
+
+/* Option flag useful for debugging and the test suite. If set
+ requests for very strong random are degraded to strong random. Not
+ used by regular applications. */
+static int quick_test;
+
+/* On systems without entropy gathering modules, this flag is set to
+ indicate that the random generator is not working properly. A
+ warning message is issued as well. This is useful only for
+ debugging and during development. */
+static int faked_rng;
+
+/* This is the lock we use to protect all pool operations. */
+static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER;
+
+/* This is a helper for assert calls. These calls are used to assert
+ that functions are called in a locked state. It is not meant to be
+ thread-safe but as a method to get aware of missing locks in the
+ test suite. */
+static int pool_is_locked;
+
+/* This is the lock we use to protect the buffer used by the nonce
+ generation. */
+static ath_mutex_t nonce_buffer_lock = ATH_MUTEX_INITIALIZER;
+
+
+/* We keep some counters in this structure for the sake of the
+ _gcry_random_dump_stats () function. */
+static struct
+{
+ unsigned long mixrnd;
+ unsigned long mixkey;
+ unsigned long slowpolls;
+ unsigned long fastpolls;
+ unsigned long getbytes1;
+ unsigned long ngetbytes1;
+ unsigned long getbytes2;
+ unsigned long ngetbytes2;
+ unsigned long addbytes;
+ unsigned long naddbytes;
+} rndstats;
+
+
+
+/* --- Stuff pertaining to the random daemon support. --- */
+#ifdef USE_RANDOM_DAEMON
+
+/* If ALLOW_DAEMON is true, the module will try to use the random
+ daemon first. If the daemon has failed, this variable is set to
+ back to false and the code continues as normal. Note, we don't
+ test this flag in a locked state because a wrong value does not
+ harm and the trhead will find out itself that the daemon does not
+ work and set it (again) to false. */
+static int allow_daemon;
+
+/* During initialization, the user may set a non-default socket name
+ for accessing the random daemon. If this value is NULL, the
+ default name will be used. */
+static char *daemon_socket_name;
+
+#endif /*USE_RANDOM_DAEMON*/
+
+
+
+/* --- Prototypes --- */
+static void read_pool (byte *buffer, size_t length, int level );
+static void add_randomness (const void *buffer, size_t length,
+ enum random_origins origin);
+static void random_poll (void);
+static void do_fast_random_poll (void);
+static int (*getfnc_gather_random (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int);
+static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins);
+static void read_random_source (enum random_origins origin,
+ size_t length, int level);
+static int gather_faked (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins, size_t length, int level );
+
+
+
+/* --- Functions --- */
+
+
+/* Basic initialization which is required to initialize mutexes and
+ such. It does not run a full initialization so that the filling of
+ the random pool can be delayed until it is actually needed. We
+ assume that this function is used before any concurrent access
+ happens. */
+static void
+initialize_basics(void)
+{
+ static int initialized;
+ int err;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ err = ath_mutex_init (&pool_lock);
+ if (err)
+ log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
+
+ err = ath_mutex_init (&nonce_buffer_lock);
+ if (err)
+ log_fatal ("failed to create the nonce buffer lock: %s\n",
+ strerror (err) );
+
+#ifdef USE_RANDOM_DAEMON
+ _gcry_daemon_initialize_basics ();
+#endif /*USE_RANDOM_DAEMON*/
+
+ /* Make sure that we are still using the values we have
+ traditionally used for the random levels. */
+ gcry_assert (GCRY_WEAK_RANDOM == 0
+ && GCRY_STRONG_RANDOM == 1
+ && GCRY_VERY_STRONG_RANDOM == 2);
+ }
+}
+
+/* Take the pool lock. */
+static void
+lock_pool (void)
+{
+ int err;
+
+ err = ath_mutex_lock (&pool_lock);
+ if (err)
+ log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
+ pool_is_locked = 1;
+}
+
+/* Release the pool lock. */
+static void
+unlock_pool (void)
+{
+ int err;
+
+ pool_is_locked = 0;
+ err = ath_mutex_unlock (&pool_lock);
+ if (err)
+ log_fatal ("failed to release the pool lock: %s\n", strerror (err));
+}
+
+
+/* Full initialization of this module. */
+static void
+initialize(void)
+{
+ /* Although the basic initialization should have happened already,
+ we call it here to make sure that all prerequisites are met. */
+ initialize_basics ();
+
+ /* Now we can look the pool and complete the initialization if
+ necessary. */
+ lock_pool ();
+ if (!rndpool)
+ {
+ /* The data buffer is allocated somewhat larger, so that we can
+ use this extra space (which is allocated in secure memory) as
+ a temporary hash buffer */
+ rndpool = (secure_alloc
+ ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+ : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
+ keypool = (secure_alloc
+ ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+ : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
+
+ /* Setup the slow entropy gathering function. The code requires
+ that this function exists. */
+ slow_gather_fnc = getfnc_gather_random ();
+ if (!slow_gather_fnc)
+ {
+ faked_rng = 1;
+ slow_gather_fnc = gather_faked;
+ }
+
+ /* Setup the fast entropy gathering function. */
+ fast_gather_fnc = getfnc_fast_random_poll ();
+
+ }
+ unlock_pool ();
+}
+
+
+
+
+/* Initialize this random subsystem. If FULL is false, this function
+ merely calls the initialize and does not do anything more. Doing
+ this is not really required but when running in a threaded
+ environment we might get a race condition otherwise. */
+void
+_gcry_rngcsprng_initialize (int full)
+{
+ if (!full)
+ initialize_basics ();
+ else
+ initialize ();
+}
+
+
+void
+_gcry_rngcsprng_dump_stats (void)
+{
+ /* In theory we would need to lock the stats here. However this
+ function is usually called during cleanup and then we _might_ run
+ into problems. */
+
+ log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
+ " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n",
+ POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
+ rndstats.naddbytes, rndstats.addbytes,
+ rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
+ rndstats.ngetbytes2, rndstats.getbytes2,
+ _gcry_rndhw_failed_p()? " (hwrng failed)":"");
+}
+
+
+/* This function should be called during initialization and before
+ initialization of this module to place the random pools into secure
+ memory. */
+void
+_gcry_rngcsprng_secure_alloc (void)
+{
+ secure_alloc = 1;
+}
+
+
+/* This may be called before full initialization to degrade the
+ quality of the RNG for the sake of a faster running test suite. */
+void
+_gcry_rngcsprng_enable_quick_gen (void)
+{
+ quick_test = 1;
+}
+
+
+void
+_gcry_rngcsprng_set_daemon_socket (const char *socketname)
+{
+#ifdef USE_RANDOM_DAEMON
+ if (daemon_socket_name)
+ BUG ();
+
+ daemon_socket_name = gcry_xstrdup (socketname);
+#else /*!USE_RANDOM_DAEMON*/
+ (void)socketname;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set
+ to 0, disable the use of the daemon. With ONOF set to -1, return
+ whether the daemon has been enabled. */
+int
+_gcry_rngcsprng_use_daemon (int onoff)
+{
+#ifdef USE_RANDOM_DAEMON
+ int last;
+
+ /* This is not really thread safe. However it is expected that this
+ function is being called during initialization and at that point
+ we are for other reasons not really thread safe. We do not want
+ to lock it because we might eventually decide that this function
+ may even be called prior to gcry_check_version. */
+ last = allow_daemon;
+ if (onoff != -1)
+ allow_daemon = onoff;
+
+ return last;
+#else /*!USE_RANDOM_DAEMON*/
+ (void)onoff;
+ return 0;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+
+/* This function returns true if no real RNG is available or the
+ quality of the RNG has been degraded for test purposes. */
+int
+_gcry_rngcsprng_is_faked (void)
+{
+ /* We need to initialize due to the runtime determination of
+ available entropy gather modules. */
+ initialize();
+ return (faked_rng || quick_test);
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
+ should be in the range of 0..100 to indicate the goodness of the
+ entropy added, or -1 for goodness not known. */
+gcry_error_t
+_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
+{
+ size_t nbytes;
+ const char *bufptr;
+
+ if (quality == -1)
+ quality = 35;
+ else if (quality > 100)
+ quality = 100;
+ else if (quality < 0)
+ quality = 0;
+
+ if (!buf)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (!buflen || quality < 10)
+ return 0; /* Take a shortcut. */
+
+ /* Because we don't increment the entropy estimation with FASTPOLL,
+ we don't need to take lock that estimation while adding from an
+ external source. This limited entropy estimation also means that
+ we can't take QUALITY into account. */
+ initialize_basics ();
+ bufptr = buf;
+ while (buflen)
+ {
+ nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
+ lock_pool ();
+ if (rndpool)
+ add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
+ unlock_pool ();
+ bufptr += nbytes;
+ buflen -= nbytes;
+ }
+ return 0;
+}
+
+
+/* Public function to fill the buffer with LENGTH bytes of
+ cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
+ not very strong, GCRY_STRONG_RANDOM is strong enough for most
+ usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
+ may be very slow. */
+void
+_gcry_rngcsprng_randomize (void *buffer, size_t length,
+ enum gcry_random_level level)
+{
+ unsigned char *p;
+
+ /* Make sure we are initialized. */
+ initialize ();
+
+ /* Handle our hack used for regression tests of Libgcrypt. */
+ if ( quick_test && level > GCRY_STRONG_RANDOM )
+ level = GCRY_STRONG_RANDOM;
+
+ /* Make sure the level is okay. */
+ level &= 3;
+
+#ifdef USE_RANDOM_DAEMON
+ if (allow_daemon
+ && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
+ return; /* The daemon succeeded. */
+ allow_daemon = 0; /* Daemon failed - switch off. */
+#endif /*USE_RANDOM_DAEMON*/
+
+ /* Acquire the pool lock. */
+ lock_pool ();
+
+ /* Update the statistics. */
+ if (level >= GCRY_VERY_STRONG_RANDOM)
+ {
+ rndstats.getbytes2 += length;
+ rndstats.ngetbytes2++;
+ }
+ else
+ {
+ rndstats.getbytes1 += length;
+ rndstats.ngetbytes1++;
+ }
+
+ /* Read the random into the provided buffer. */
+ for (p = buffer; length > 0;)
+ {
+ size_t n;
+
+ n = length > POOLSIZE? POOLSIZE : length;
+ read_pool (p, n, level);
+ length -= n;
+ p += n;
+ }
+
+ /* Release the pool lock. */
+ unlock_pool ();
+}
+
+
+
+
+/*
+ Mix the pool:
+
+ |........blocks*20byte........|20byte|..44byte..|
+ <..44byte..> <20byte>
+ | |
+ | +------+
+ +---------------------------|----------+
+ v v
+ |........blocks*20byte........|20byte|..44byte..|
+ <.....64bytes.....>
+ |
+ +----------------------------------+
+ Hash
+ v
+ |.............................|20byte|..44byte..|
+ <20byte><20byte><..44byte..>
+ | |
+ | +---------------------+
+ +-----------------------------+ |
+ v v
+ |.............................|20byte|..44byte..|
+ <.....64byte......>
+ |
+ +-------------------------+
+ Hash
+ v
+ |.............................|20byte|..44byte..|
+ <20byte><20byte><..44byte..>
+
+ and so on until we did this for all blocks.
+
+ To better protect against implementation errors in this code, we
+ xor a digest of the entire pool into the pool before mixing.
+
+ Note: this function must only be called with a locked pool.
+ */
+static void
+mix_pool(unsigned char *pool)
+{
+ static unsigned char failsafe_digest[DIGESTLEN];
+ static int failsafe_digest_valid;
+
+ unsigned char *hashbuf = pool + POOLSIZE;
+ unsigned char *p, *pend;
+ int i, n;
+ RMD160_CONTEXT md;
+
+#if DIGESTLEN != 20
+#error must have a digest length of 20 for ripe-md-160
+#endif
+
+ gcry_assert (pool_is_locked);
+ _gcry_rmd160_init( &md );
+
+ /* Loop over the pool. */
+ pend = pool + POOLSIZE;
+ memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
+ memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
+ _gcry_rmd160_mixblock( &md, hashbuf);
+ memcpy(pool, hashbuf, 20 );
+
+ if (failsafe_digest_valid && pool == rndpool)
+ {
+ for (i=0; i < 20; i++)
+ pool[i] ^= failsafe_digest[i];
+ }
+
+ p = pool;
+ for (n=1; n < POOLBLOCKS; n++)
+ {
+ memcpy (hashbuf, p, DIGESTLEN);
+
+ p += DIGESTLEN;
+ if (p+DIGESTLEN+BLOCKLEN < pend)
+ memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
+ else
+ {
+ unsigned char *pp = p + DIGESTLEN;
+
+ for (i=DIGESTLEN; i < BLOCKLEN; i++ )
+ {
+ if ( pp >= pend )
+ pp = pool;
+ hashbuf[i] = *pp++;
+ }
+ }
+
+ _gcry_rmd160_mixblock ( &md, hashbuf);
+ memcpy(p, hashbuf, 20 );
+ }
+
+ /* Our hash implementation does only leave small parts (64 bytes)
+ of the pool on the stack, so it is okay not to require secure
+ memory here. Before we use this pool, it will be copied to the
+ help buffer anyway. */
+ if ( pool == rndpool)
+ {
+ _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
+ failsafe_digest_valid = 1;
+ }
+
+ _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
+}
+
+
+void
+_gcry_rngcsprng_set_seed_file (const char *name)
+{
+ if (seed_file_name)
+ BUG ();
+ seed_file_name = gcry_xstrdup (name);
+}
+
+
+/* Lock an open file identified by file descriptor FD and wait a
+ reasonable time to succeed. With FOR_WRITE set to true a write
+ lock will be taken. FNAME is used only for diagnostics. Returns 0
+ on success or -1 on error. */
+static int
+lock_seed_file (int fd, const char *fname, int for_write)
+{
+#ifdef __GCC__
+#warning Check whether we can lock on Windows.
+#endif
+#if LOCK_SEED_FILE
+ struct flock lck;
+ struct timeval tv;
+ int backoff=0;
+
+ /* We take a lock on the entire file. */
+ memset (&lck, 0, sizeof lck);
+ lck.l_type = for_write? F_WRLCK : F_RDLCK;
+ lck.l_whence = SEEK_SET;
+
+ while (fcntl (fd, F_SETLK, &lck) == -1)
+ {
+ if (errno != EAGAIN && errno != EACCES)
+ {
+ log_info (_("can't lock `%s': %s\n"), fname, strerror (errno));
+ return -1;
+ }
+
+ if (backoff > 2) /* Show the first message after ~2.25 seconds. */
+ log_info( _("waiting for lock on `%s'...\n"), fname);
+
+ tv.tv_sec = backoff;
+ tv.tv_usec = 250000;
+ select (0, NULL, NULL, NULL, &tv);
+ if (backoff < 10)
+ backoff++ ;
+ }
+#endif /*!LOCK_SEED_FILE*/
+ return 0;
+}
+
+
+/* Read in a seed from the random_seed file and return true if this
+ was successful.
+
+ Note: Multiple instances of applications sharing the same random
+ seed file can be started in parallel, in which case they will read
+ out the same pool and then race for updating it (the last update
+ overwrites earlier updates). They will differentiate only by the
+ weak entropy that is added in read_seed_file based on the PID and
+ clock, and up to 16 bytes of weak random non-blockingly. The
+ consequence is that the output of these different instances is
+ correlated to some extent. In the perfect scenario, the attacker
+ can control (or at least guess) the PID and clock of the
+ application, and drain the system's entropy pool to reduce the "up
+ to 16 bytes" above to 0. Then the dependencies of the initial
+ states of the pools are completely known. */
+static int
+read_seed_file (void)
+{
+ int fd;
+ struct stat sb;
+ unsigned char buffer[POOLSIZE];
+ int n;
+
+ gcry_assert (pool_is_locked);
+
+ if (!seed_file_name)
+ return 0;
+
+#ifdef HAVE_DOSISH_SYSTEM
+ fd = open( seed_file_name, O_RDONLY | O_BINARY );
+#else
+ fd = open( seed_file_name, O_RDONLY );
+#endif
+ if( fd == -1 && errno == ENOENT)
+ {
+ allow_seed_file_update = 1;
+ return 0;
+ }
+
+ if (fd == -1 )
+ {
+ log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
+ return 0;
+ }
+ if (lock_seed_file (fd, seed_file_name, 0))
+ {
+ close (fd);
+ return 0;
+ }
+ if (fstat( fd, &sb ) )
+ {
+ log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
+ close(fd);
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode) )
+ {
+ log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
+ close(fd);
+ return 0;
+ }
+ if (!sb.st_size )
+ {
+ log_info(_("note: random_seed file is empty\n") );
+ close(fd);
+ allow_seed_file_update = 1;
+ return 0;
+ }
+ if (sb.st_size != POOLSIZE )
+ {
+ log_info(_("warning: invalid size of random_seed file - not used\n") );
+ close(fd);
+ return 0;
+ }
+
+ do
+ {
+ n = read( fd, buffer, POOLSIZE );
+ }
+ while (n == -1 && errno == EINTR );
+
+ if (n != POOLSIZE)
+ {
+ log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
+ close(fd);/*NOTREACHED*/
+ return 0;
+ }
+
+ close(fd);
+
+ add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
+ /* add some minor entropy to the pool now (this will also force a mixing) */
+ {
+ pid_t x = getpid();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+ {
+ time_t x = time(NULL);
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+ {
+ clock_t x = clock();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+
+ /* And read a few bytes from our entropy source. By using a level
+ * of 0 this will not block and might not return anything with some
+ * entropy drivers, however the rndlinux driver will use
+ * /dev/urandom and return some stuff - Do not read too much as we
+ * want to be friendly to the scare system entropy resource. */
+ read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );
+
+ allow_seed_file_update = 1;
+ return 1;
+}
+
+
+void
+_gcry_rngcsprng_update_seed_file (void)
+{
+ unsigned long *sp, *dp;
+ int fd, i;
+
+ /* We do only a basic initialization so that we can lock the pool.
+ This is required to cope with the case that this function is
+ called by some cleanup code at a point where the RNG has never
+ been initialized. */
+ initialize_basics ();
+ lock_pool ();
+
+ if ( !seed_file_name || !rndpool || !pool_filled )
+ {
+ unlock_pool ();
+ return;
+ }
+ if ( !allow_seed_file_update )
+ {
+ unlock_pool ();
+ log_info(_("note: random_seed file not updated\n"));
+ return;
+ }
+
+ /* At this point we know that there is something in the pool and
+ thus we can conclude that the pool has been fully initialized. */
+
+
+ /* Copy the entropy pool to a scratch pool and mix both of them. */
+ for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
+ i < POOLWORDS; i++, dp++, sp++ )
+ {
+ *dp = *sp + ADD_VALUE;
+ }
+ mix_pool(rndpool); rndstats.mixrnd++;
+ mix_pool(keypool); rndstats.mixkey++;
+
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
+ fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
+ S_IRUSR|S_IWUSR );
+#else
+# if LOCK_SEED_FILE
+ fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
+# else
+ fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
+# endif
+#endif
+
+ if (fd == -1 )
+ log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
+ else if (lock_seed_file (fd, seed_file_name, 1))
+ {
+ close (fd);
+ }
+#if LOCK_SEED_FILE
+ else if (ftruncate (fd, 0))
+ {
+ log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
+ close (fd);
+ }
+#endif /*LOCK_SEED_FILE*/
+ else
+ {
+ do
+ {
+ i = write (fd, keypool, POOLSIZE );
+ }
+ while (i == -1 && errno == EINTR);
+ if (i != POOLSIZE)
+ log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
+ if (close(fd))
+ log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
+ }
+
+ unlock_pool ();
+}
+
+
+/* Read random out of the pool. This function is the core of the
+ public random functions. Note that Level GCRY_WEAK_RANDOM is not
+ anymore handled special and in fact is an alias in the API for
+ level GCRY_STRONG_RANDOM. Must be called with the pool already
+ locked. */
+static void
+read_pool (byte *buffer, size_t length, int level)
+{
+ int i;
+ unsigned long *sp, *dp;
+ /* The volatile is there to make sure the compiler does not optimize
+ the code away in case the getpid function is badly attributed.
+ Note that we keep a pid in a static variable as well as in a
+ stack based one; the latter is to detect ill behaving thread
+ libraries, ignoring the pool mutexes. */
+ static volatile pid_t my_pid = (pid_t)(-1);
+ volatile pid_t my_pid2;
+
+ gcry_assert (pool_is_locked);
+
+ retry:
+ /* Get our own pid, so that we can detect a fork. */
+ my_pid2 = getpid ();
+ if (my_pid == (pid_t)(-1))
+ my_pid = my_pid2;
+ if ( my_pid != my_pid2 )
+ {
+ /* We detected a plain fork; i.e. we are now the child. Update
+ the static pid and add some randomness. */
+ pid_t x;
+
+ my_pid = my_pid2;
+ x = my_pid;
+ add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+ just_mixed = 0; /* Make sure it will get mixed. */
+ }
+
+ gcry_assert (pool_is_locked);
+
+ /* Our code does not allow to extract more than POOLSIZE. Better
+ check it here. */
+ if (length > POOLSIZE)
+ {
+ log_bug("too many random bits requested\n");
+ }
+
+ if (!pool_filled)
+ {
+ if (read_seed_file() )
+ pool_filled = 1;
+ }
+
+ /* For level 2 quality (key generation) we always make sure that the
+ pool has been seeded enough initially. */
+ if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding)
+ {
+ size_t needed;
+
+ pool_balance = 0;
+ needed = length - pool_balance;
+ if (needed < POOLSIZE/2)
+ needed = POOLSIZE/2;
+ else if( needed > POOLSIZE )
+ BUG ();
+ read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+ GCRY_VERY_STRONG_RANDOM);
+ pool_balance += needed;
+ did_initial_extra_seeding = 1;
+ }
+
+ /* For level 2 make sure that there is enough random in the pool. */
+ if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length)
+ {
+ size_t needed;
+
+ if (pool_balance < 0)
+ pool_balance = 0;
+ needed = length - pool_balance;
+ if (needed > POOLSIZE)
+ BUG ();
+ read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+ GCRY_VERY_STRONG_RANDOM);
+ pool_balance += needed;
+ }
+
+ /* Make sure the pool is filled. */
+ while (!pool_filled)
+ random_poll();
+
+ /* Always do a fast random poll (we have to use the unlocked version). */
+ do_fast_random_poll();
+
+ /* Mix the pid in so that we for sure won't deliver the same random
+ after a fork. */
+ {
+ pid_t apid = my_pid;
+ add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT);
+ }
+
+ /* Mix the pool (if add_randomness() didn't it). */
+ if (!just_mixed)
+ {
+ mix_pool(rndpool);
+ rndstats.mixrnd++;
+ }
+
+ /* Create a new pool. */
+ for(i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
+ i < POOLWORDS; i++, dp++, sp++ )
+ *dp = *sp + ADD_VALUE;
+
+ /* Mix both pools. */
+ mix_pool(rndpool); rndstats.mixrnd++;
+ mix_pool(keypool); rndstats.mixkey++;
+
+ /* Read the requested data. We use a read pointer to read from a
+ different position each time. */
+ while (length--)
+ {
+ *buffer++ = keypool[pool_readpos++];
+ if (pool_readpos >= POOLSIZE)
+ pool_readpos = 0;
+ pool_balance--;
+ }
+
+ if (pool_balance < 0)
+ pool_balance = 0;
+
+ /* Clear the keypool. */
+ memset (keypool, 0, POOLSIZE);
+
+ /* We need to detect whether a fork has happened. A fork might have
+ an identical pool and thus the child and the parent could emit
+ the very same random number. This test here is to detect forks
+ in a multi-threaded process. It does not work with all thread
+ implementations in particular not with pthreads. However it is
+ good enough for GNU Pth. */
+ if ( getpid () != my_pid2 )
+ {
+ pid_t x = getpid();
+ add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+ just_mixed = 0; /* Make sure it will get mixed. */
+ my_pid = x; /* Also update the static pid. */
+ goto retry;
+ }
+}
+
+
+
+/* Add LENGTH bytes of randomness from buffer to the pool. ORIGIN is
+ used to specify the randomness origin. This is one of the
+ RANDOM_ORIGIN_* values. */
+static void
+add_randomness (const void *buffer, size_t length, enum random_origins origin)
+{
+ const unsigned char *p = buffer;
+ size_t count = 0;
+
+ gcry_assert (pool_is_locked);
+
+ rndstats.addbytes += length;
+ rndstats.naddbytes++;
+ while (length-- )
+ {
+ rndpool[pool_writepos++] ^= *p++;
+ count++;
+ if (pool_writepos >= POOLSIZE )
+ {
+ /* It is possible that we are invoked before the pool is
+ filled using an unreliable origin of entropy, for example
+ the fast random poll. To avoid flagging the pool as
+ filled in this case, we track the initial filling state
+ separately. See also the remarks about the seed file. */
+ if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
+ {
+ pool_filled_counter += count;
+ count = 0;
+ if (pool_filled_counter >= POOLSIZE)
+ pool_filled = 1;
+ }
+ pool_writepos = 0;
+ mix_pool(rndpool); rndstats.mixrnd++;
+ just_mixed = !length;
+ }
+ }
+}
+
+
+
+static void
+random_poll()
+{
+ rndstats.slowpolls++;
+ read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM);
+}
+
+
+/* Runtime determination of the slow entropy gathering module. */
+static int (*
+getfnc_gather_random (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int)
+{
+ int (*fnc)(void (*)(const void*, size_t, enum random_origins),
+ enum random_origins, size_t, int);
+
+#if USE_RNDLINUX
+ if ( !access (NAME_OF_DEV_RANDOM, R_OK)
+ && !access (NAME_OF_DEV_URANDOM, R_OK))
+ {
+ fnc = _gcry_rndlinux_gather_random;
+ return fnc;
+ }
+#endif
+
+#if USE_RNDEGD
+ if ( _gcry_rndegd_connect_socket (1) != -1 )
+ {
+ fnc = _gcry_rndegd_gather_random;
+ return fnc;
+ }
+#endif
+
+#if USE_RNDUNIX
+ fnc = _gcry_rndunix_gather_random;
+ return fnc;
+#endif
+
+#if USE_RNDW32
+ fnc = _gcry_rndw32_gather_random;
+ return fnc;
+#endif
+
+#if USE_RNDW32CE
+ fnc = _gcry_rndw32ce_gather_random;
+ return fnc;
+#endif
+
+ log_fatal (_("no entropy gathering module detected\n"));
+
+ return NULL; /*NOTREACHED*/
+}
+
+/* Runtime determination of the fast entropy gathering function.
+ (Currently a compile time method is used.) */
+static void (*
+getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins)
+{
+#if USE_RNDW32
+ return _gcry_rndw32_gather_random_fast;
+#endif
+#if USE_RNDW32CE
+ return _gcry_rndw32ce_gather_random_fast;
+#endif
+ return NULL;
+}
+
+
+
+static void
+do_fast_random_poll (void)
+{
+ gcry_assert (pool_is_locked);
+
+ rndstats.fastpolls++;
+
+ if (fast_gather_fnc)
+ fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+
+ /* Continue with the generic functions. */
+#if HAVE_GETHRTIME
+ {
+ hrtime_t tv;
+ tv = gethrtime();
+ add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL );
+ }
+#elif HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+ if( gettimeofday( &tv, NULL ) )
+ BUG();
+ add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+ add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL );
+ }
+#elif HAVE_CLOCK_GETTIME
+ { struct timespec tv;
+ if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
+ BUG();
+ add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+ add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL );
+ }
+#else /* use times */
+# ifndef HAVE_DOSISH_SYSTEM
+ { struct tms buf;
+ times( &buf );
+ add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+ }
+# endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
+# ifdef RUSAGE_SELF
+ {
+ struct rusage buf;
+ /* QNX/Neutrino does return ENOSYS - so we just ignore it and add
+ whatever is in buf. In a chroot environment it might not work
+ at all (i.e. because /proc/ is not accessible), so we better
+ ignore all error codes and hope for the best. */
+ getrusage (RUSAGE_SELF, &buf );
+ add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+ memset( &buf, 0, sizeof buf );
+ }
+# else /*!RUSAGE_SELF*/
+# ifdef __GCC__
+# warning There is no RUSAGE_SELF on this system
+# endif
+# endif /*!RUSAGE_SELF*/
+#endif /*HAVE_GETRUSAGE*/
+
+ /* Time and clock are availabe on all systems - so we better do it
+ just in case one of the above functions didn't work. */
+ {
+ time_t x = time(NULL);
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+ }
+ {
+ clock_t x = clock();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+ }
+
+ /* If the system features a fast hardware RNG, read some bytes from
+ there. */
+ _gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+}
+
+
+/* The fast random pool function as called at some places in
+ libgcrypt. This is merely a wrapper to make sure that this module
+ is initialized and to lock the pool. Note, that this function is a
+ NOP unless a random function has been used or _gcry_initialize (1)
+ has been used. We use this hack so that the internal use of this
+ function in cipher_open and md_open won't start filling up the
+ random pool, even if no random will be required by the process. */
+void
+_gcry_rngcsprng_fast_poll (void)
+{
+ initialize_basics ();
+
+ lock_pool ();
+ if (rndpool)
+ {
+ /* Yes, we are fully initialized. */
+ do_fast_random_poll ();
+ }
+ unlock_pool ();
+}
+
+
+
+static void
+read_random_source (enum random_origins orgin, size_t length, int level )
+{
+ if ( !slow_gather_fnc )
+ log_fatal ("Slow entropy gathering module not yet initialized\n");
+
+ if ( slow_gather_fnc (add_randomness, orgin, length, level) < 0)
+ log_fatal ("No way to gather entropy for the RNG\n");
+}
+
+
+static int
+gather_faked (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin, size_t length, int level )
+{
+ static int initialized=0;
+ size_t n;
+ char *buffer, *p;
+
+ (void)add;
+ (void)level;
+
+ if ( !initialized )
+ {
+ log_info(_("WARNING: using insecure random number generator!!\n"));
+ initialized=1;
+#ifdef HAVE_RAND
+ srand( time(NULL)*getpid());
+#else
+ srandom( time(NULL)*getpid());
+#endif
+ }
+
+ p = buffer = gcry_xmalloc( length );
+ n = length;
+#ifdef HAVE_RAND
+ while ( n-- )
+ *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
+#else
+ while ( n-- )
+ *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
+#endif
+ add_randomness ( buffer, length, origin );
+ gcry_free (buffer);
+ return 0; /* okay */
+}
+
+
+/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
+void
+_gcry_rngcsprng_create_nonce (void *buffer, size_t length)
+{
+ static unsigned char nonce_buffer[20+8];
+ static int nonce_buffer_initialized = 0;
+ static volatile pid_t my_pid; /* The volatile is there to make sure the
+ compiler does not optimize the code away
+ in case the getpid function is badly
+ attributed. */
+ volatile pid_t apid;
+ unsigned char *p;
+ size_t n;
+ int err;
+
+ /* Make sure we are initialized. */
+ initialize ();
+
+#ifdef USE_RANDOM_DAEMON
+ if (allow_daemon
+ && !_gcry_daemon_create_nonce (daemon_socket_name, buffer, length))
+ return; /* The daemon succeeded. */
+ allow_daemon = 0; /* Daemon failed - switch off. */
+#endif /*USE_RANDOM_DAEMON*/
+
+ /* Acquire the nonce buffer lock. */
+ err = ath_mutex_lock (&nonce_buffer_lock);
+ if (err)
+ log_fatal ("failed to acquire the nonce buffer lock: %s\n",
+ strerror (err));
+
+ apid = getpid ();
+ /* The first time initialize our buffer. */
+ if (!nonce_buffer_initialized)
+ {
+ time_t atime = time (NULL);
+ pid_t xpid = apid;
+
+ my_pid = apid;
+
+ if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
+ BUG ();
+
+ /* Initialize the first 20 bytes with a reasonable value so that
+ a failure of gcry_randomize won't affect us too much. Don't
+ care about the uninitialized remaining bytes. */
+ p = nonce_buffer;
+ memcpy (p, &xpid, sizeof xpid);
+ p += sizeof xpid;
+ memcpy (p, &atime, sizeof atime);
+
+ /* Initialize the never changing private part of 64 bits. */
+ gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+
+ nonce_buffer_initialized = 1;
+ }
+ else if ( my_pid != apid )
+ {
+ /* We forked. Need to reseed the buffer - doing this for the
+ private part should be sufficient. */
+ gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+ /* Update the pid so that we won't run into here again and
+ again. */
+ my_pid = apid;
+ }
+
+ /* Create the nonce by hashing the entire buffer, returning the hash
+ and updating the first 20 bytes of the buffer with this hash. */
+ for (p = buffer; length > 0; length -= n, p += n)
+ {
+ _gcry_sha1_hash_buffer (nonce_buffer,
+ nonce_buffer, sizeof nonce_buffer);
+ n = length > 20? 20 : length;
+ memcpy (p, nonce_buffer, n);
+ }
+
+
+ /* Release the nonce buffer lock. */
+ err = ath_mutex_unlock (&nonce_buffer_lock);
+ if (err)
+ log_fatal ("failed to release the nonce buffer lock: %s\n",
+ strerror (err));
+
+}
diff --git a/libgcrypt-1.4.6/random/random-fips.c b/libgcrypt-1.4.6/random/random-fips.c
index 2667e71..a960a3e 100644
--- a/libgcrypt-1.4.6/random/random-fips.c
+++ b/libgcrypt-1.4.6/random/random-fips.c
@@ -67,6 +67,7 @@
#include "random.h"
#include "rand-internal.h"
#include "ath.h"
+#include <process.h>
/* This is the lock we use to serialize access to this RNG. The extra
integer variable is only used to check the locking state; that is,
@@ -668,14 +669,14 @@ x931_reseed (rng_context_t rng_ctx)
standard random generator. */
get_random (rng_ctx->seed_V, 16, std_rng_context);
rng_ctx->is_seeded = 1;
- rng_ctx->seed_init_pid = getpid ();
+ rng_ctx->seed_init_pid = _getpid();
}
else
{
/* The other two generators are seeded from /dev/random. */
x931_generate_seed (rng_ctx->seed_V, 16);
rng_ctx->is_seeded = 1;
- rng_ctx->seed_init_pid = getpid ();
+ rng_ctx->seed_init_pid = _getpid();
}
}
@@ -701,15 +702,15 @@ get_random (void *buffer, size_t length, rng_context_t rng_ctx)
rng_ctx->cipher_hd = x931_generate_key (0);
if (!rng_ctx->cipher_hd)
goto bailout;
- rng_ctx->key_init_pid = getpid ();
+ rng_ctx->key_init_pid = _getpid();
}
/* Initialize the seed value if needed. */
if (!rng_ctx->is_seeded)
x931_reseed (rng_ctx);
- if (rng_ctx->key_init_pid != getpid ()
- || rng_ctx->seed_init_pid != getpid ())
+ if (rng_ctx->key_init_pid != _getpid()
+ || rng_ctx->seed_init_pid != _getpid())
{
/* We are in a child of us. Because we have no way yet to do
proper re-initialization (including self-checks etc), the
@@ -926,12 +927,12 @@ selftest_kat (selftest_report_func_t report)
errtxt = "error setting key for RNG";
goto leave;
}
- test_ctx->key_init_pid = getpid ();
+ test_ctx->key_init_pid = _getpid();
/* Setup the seed. */
memcpy (test_ctx->seed_V, tv[tvidx].v, 16);
test_ctx->is_seeded = 1;
- test_ctx->seed_init_pid = getpid ();
+ test_ctx->seed_init_pid = _getpid();
/* Setup a DT value. */
test_ctx->test_dt_ptr = tv[tvidx].dt;
@@ -962,8 +963,8 @@ selftest_kat (selftest_report_func_t report)
/* This test is actual pretty pointless because we use a local test
context. */
- if (test_ctx->key_init_pid != getpid ()
- || test_ctx->seed_init_pid != getpid ())
+ if (test_ctx->key_init_pid != _getpid()
+ || test_ctx->seed_init_pid != _getpid())
{
errtxt = "fork detection failed";
goto leave;
@@ -1049,12 +1050,12 @@ _gcry_rngfips_init_external_test (void **r_context, unsigned int flags,
if (err)
goto leave;
- test_ctx->key_init_pid = getpid ();
+ test_ctx->key_init_pid = _getpid();
/* Setup the seed. */
memcpy (test_ctx->seed_V, seed, seedlen);
test_ctx->is_seeded = 1;
- test_ctx->seed_init_pid = getpid ();
+ test_ctx->seed_init_pid = _getpid();
/* Setup a DT value. Because our context structure only stores a
pointer we copy the DT value to the extra space we allocated in
diff --git a/libgcrypt-1.4.6/random/rndw32.c b/libgcrypt-1.4.6/random/rndw32.c
index 55b7256..2a7f56e 100644
--- a/libgcrypt-1.4.6/random/rndw32.c
+++ b/libgcrypt-1.4.6/random/rndw32.c
@@ -499,7 +499,7 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
szValue, &dwSize);
- if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT"))
+ if (status == ERROR_SUCCESS && _stricmp (szValue, "WinNT"))
{
/* Note: There are (at least) three cases for ProductType:
WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
diff --git a/libgcrypt-1.4.6/src/ath.c b/libgcrypt-1.4.6/src/ath.c
index 0c274cd..fe7f289 100644
--- a/libgcrypt-1.4.6/src/ath.c
+++ b/libgcrypt-1.4.6/src/ath.c
@@ -38,7 +38,7 @@
#include "ath.h"
-
+
/* The interface table. */
static struct ath_ops ops;
@@ -58,7 +58,7 @@ static int ops_set;
#define GET_VERSION(a) (((a) >> 8)& 0xff)
-
+
/* The lock we take while checking for lazy lock initialization. */
static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER;
@@ -68,13 +68,13 @@ ath_init (void)
int err = 0;
if (ops_set)
- {
- if (ops.init)
+ {
+ if (ops.init)
err = (*ops.init) ();
- if (err)
+ if (err)
return err;
- err = (*ops.mutex_init) (&check_init_lock);
- }
+ err = (*ops.mutex_init) (&check_init_lock);
+ }
return err;
}
@@ -86,38 +86,38 @@ gpg_err_code_t
ath_install (struct ath_ops *ath_ops, int check_only)
{
if (check_only)
- {
- unsigned int option = 0;
-
- /* Check if the requested thread option is compatible to the
+ {
+ unsigned int option = 0;
+
+ /* Check if the requested thread option is compatible to the
thread option we are already committed to. */
- if (ath_ops)
+ if (ath_ops)
option = ath_ops->option;
- if (!ops_set && GET_OPTION (option))
+ if (!ops_set && GET_OPTION (option))
return GPG_ERR_NOT_SUPPORTED;
- if (GET_OPTION (ops.option) == ATH_THREAD_OPTION_USER
+ if (GET_OPTION (ops.option) == ATH_THREAD_OPTION_USER
|| GET_OPTION (option) == ATH_THREAD_OPTION_USER
|| GET_OPTION (ops.option) != GET_OPTION (option)
- || GET_VERSION (ops.option) != GET_VERSION (option))
+ || GET_VERSION (ops.option) != GET_VERSION (option))
return GPG_ERR_NOT_SUPPORTED;
- return 0;
- }
-
+ return 0;
+ }
+
if (ath_ops)
- {
- /* It is convenient to not require DESTROY. */
- if (!ath_ops->mutex_init || !ath_ops->mutex_lock
+ {
+ /* It is convenient to not require DESTROY. */
+ if (!ath_ops->mutex_init || !ath_ops->mutex_lock
|| !ath_ops->mutex_unlock)
return GPG_ERR_INV_ARG;
- ops = *ath_ops;
- ops_set = 1;
- }
+ ops = *ath_ops;
+ ops_set = 1;
+ }
else
- ops_set = 0;
+ ops_set = 0;
return 0;
}
@@ -129,11 +129,11 @@ mutex_init (ath_mutex_t *lock, int just_check)
int err = 0;
if (just_check)
- (*ops.mutex_lock) (&check_init_lock);
+ (*ops.mutex_lock) (&check_init_lock);
if (*lock == ATH_MUTEX_INITIALIZER || !just_check)
- err = (*ops.mutex_init) (lock);
+ err = (*ops.mutex_init) (lock);
if (just_check)
- (*ops.mutex_unlock) (&check_init_lock);
+ (*ops.mutex_unlock) (&check_init_lock);
return err;
}
@@ -142,7 +142,7 @@ int
ath_mutex_init (ath_mutex_t *lock)
{
if (ops_set)
- return mutex_init (lock, 0);
+ return mutex_init (lock, 0);
#ifndef NDEBUG
*lock = MUTEX_UNLOCKED;
@@ -155,19 +155,19 @@ int
ath_mutex_destroy (ath_mutex_t *lock)
{
if (ops_set)
- {
- if (!ops.mutex_destroy)
+ {
+ if (!ops.mutex_destroy)
return 0;
- (*ops.mutex_lock) (&check_init_lock);
- if (*lock == ATH_MUTEX_INITIALIZER)
+ (*ops.mutex_lock) (&check_init_lock);
+ if (*lock == ATH_MUTEX_INITIALIZER)
{
(*ops.mutex_unlock) (&check_init_lock);
return 0;
}
- (*ops.mutex_unlock) (&check_init_lock);
- return (*ops.mutex_destroy) (lock);
- }
+ (*ops.mutex_unlock) (&check_init_lock);
+ return (*ops.mutex_destroy) (lock);
+ }
#ifndef NDEBUG
assert (*lock == MUTEX_UNLOCKED);
@@ -182,12 +182,12 @@ int
ath_mutex_lock (ath_mutex_t *lock)
{
if (ops_set)
- {
- int ret = mutex_init (lock, 1);
- if (ret)
+ {
+ int ret = mutex_init (lock, 1);
+ if (ret)
return ret;
- return (*ops.mutex_lock) (lock);
- }
+ return (*ops.mutex_lock) (lock);
+ }
#ifndef NDEBUG
assert (*lock == MUTEX_UNLOCKED);
@@ -202,12 +202,12 @@ int
ath_mutex_unlock (ath_mutex_t *lock)
{
if (ops_set)
- {
- int ret = mutex_init (lock, 1);
- if (ret)
+ {
+ int ret = mutex_init (lock, 1);
+ if (ret)
return ret;
- return (*ops.mutex_unlock) (lock);
- }
+ return (*ops.mutex_unlock) (lock);
+ }
#ifndef NDEBUG
assert (*lock == MUTEX_LOCKED);
@@ -222,9 +222,9 @@ ssize_t
ath_read (int fd, void *buf, size_t nbytes)
{
if (ops_set && ops.read)
- return (*ops.read) (fd, buf, nbytes);
+ return (*ops.read) (fd, buf, nbytes);
else
- return read (fd, buf, nbytes);
+ return _read (fd, buf, nbytes);
}
@@ -232,28 +232,28 @@ ssize_t
ath_write (int fd, const void *buf, size_t nbytes)
{
if (ops_set && ops.write)
- return (*ops.write) (fd, buf, nbytes);
+ return (*ops.write) (fd, buf, nbytes);
else
- return write (fd, buf, nbytes);
+ return _write (fd, buf, nbytes);
}
ssize_t
#ifdef _WIN32
ath_select (int nfd, void *rset, void *wset, void *eset,
- struct timeval *timeout)
+ struct timeval *timeout)
#else
ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
- struct timeval *timeout)
+ struct timeval *timeout)
#endif
{
if (ops_set && ops.select)
- return (*ops.select) (nfd, rset, wset, eset, timeout);
+ return (*ops.select) (nfd, rset, wset, eset, timeout);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return select (nfd, rset, wset, eset, timeout);
+ return select (nfd, rset, wset, eset, timeout);
#endif
}
@@ -262,12 +262,12 @@ ssize_t
ath_waitpid (pid_t pid, int *status, int options)
{
if (ops_set && ops.waitpid)
- return (*ops.waitpid) (pid, status, options);
+ return (*ops.waitpid) (pid, status, options);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return waitpid (pid, status, options);
+ return waitpid (pid, status, options);
#endif
}
@@ -280,12 +280,12 @@ ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
#endif
{
if (ops_set && ops.accept)
- return (*ops.accept) (s, addr, length_ptr);
+ return (*ops.accept) (s, addr, length_ptr);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return accept (s, addr, length_ptr);
+ return accept (s, addr, length_ptr);
#endif
}
@@ -298,12 +298,12 @@ ath_connect (int s, struct sockaddr *addr, socklen_t length)
#endif
{
if (ops_set && ops.connect)
- return (*ops.connect) (s, addr, length);
+ return (*ops.connect) (s, addr, length);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return connect (s, addr, length);
+ return connect (s, addr, length);
#endif
}
@@ -316,12 +316,12 @@ ath_sendmsg (int s, const struct msghdr *msg, int flags)
#endif
{
if (ops_set && ops.sendmsg)
- return (*ops.sendmsg) (s, msg, flags);
+ return (*ops.sendmsg) (s, msg, flags);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return sendmsg (s, msg, flags);
+ return sendmsg (s, msg, flags);
#endif
}
@@ -334,12 +334,12 @@ ath_recvmsg (int s, struct msghdr *msg, int flags)
#endif
{
if (ops_set && ops.recvmsg)
- return (*ops.recvmsg) (s, msg, flags);
+ return (*ops.recvmsg) (s, msg, flags);
else
#ifdef _WIN32
- return -1;
+ return -1;
#else
- return recvmsg (s, msg, flags);
+ return recvmsg (s, msg, flags);
#endif
}
diff --git a/libgcrypt-1.4.6/src/fips.c b/libgcrypt-1.4.6/src/fips.c
index 91f3042..8709dae 100644
--- a/libgcrypt-1.4.6/src/fips.c
+++ b/libgcrypt-1.4.6/src/fips.c
@@ -128,7 +128,7 @@ _gcry_initialize_fips_mode (int force)
file. The filename is hardwired so that there won't be any
confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is
actually used. The file itself may be empty. */
- if ( !access (FIPS_FORCE_FILE, F_OK) )
+ if ( !_access (FIPS_FORCE_FILE, F_OK) )
{
gcry_assert (!no_fips_mode_required);
goto leave;
@@ -156,7 +156,7 @@ _gcry_initialize_fips_mode (int force)
}
else if ((saved_errno = errno) != ENOENT
&& saved_errno != EACCES
- && !access ("/proc/version", F_OK) )
+ && !_access ("/proc/version", F_OK) )
{
/* Problem reading the fips file despite that we have the proc
file system. We better stop right away. */
diff --git a/libgcrypt-1.4.6/src/gcrypt.h b/libgcrypt-1.4.6/src/gcrypt.h
index 08112a7..d583c52 100644
--- a/libgcrypt-1.4.6/src/gcrypt.h
+++ b/libgcrypt-1.4.6/src/gcrypt.h
@@ -1,6 +1,6 @@
/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*-
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of Libgcrypt.
@@ -38,8 +38,8 @@
# include <ws2tcpip.h>
# include <time.h>
# ifndef __GNUC__
- typedef long ssize_t;
- typedef int pid_t;
+ typedef long SSIZE_T;
+ typedef int pid_t;
# endif /*!__GNUC__*/
#else
# include <sys/socket.h>
@@ -80,8 +80,8 @@ extern "C" {
#ifdef __GNUC__
#define _GCRY_GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
#if _GCRY_GCC_VERSION >= 30100
#define _GCRY_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
@@ -177,12 +177,12 @@ gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err);
/* Return an error value with the system error ERR. */
gcry_err_code_t gcry_error_from_errno (int err);
-
+
/* This enum is deprecated; it is only declared for the sake of
complete API compatibility. */
enum gcry_thread_option
{
- _GCRY_THREAD_OPTION_DUMMY
+ _GCRY_THREAD_OPTION_DUMMY
} _GCRY_GCC_ATTR_DEPRECATED;
@@ -201,9 +201,9 @@ enum gcry_thread_option
struct gcry_thread_cbs
{
/* The OPTION field encodes the thread model and the version number
- of this structure.
- Bits 7 - 0 are used for the thread model
- Bits 15 - 8 are used for the version number.
+ of this structure.
+ Bits 7 - 0 are used for the thread model
+ Bits 15 - 8 are used for the version number.
*/
unsigned int option;
@@ -216,7 +216,7 @@ struct gcry_thread_cbs
ssize_t (*write) (int fd, const void *buf, size_t nbytes);
#ifdef _WIN32
ssize_t (*select) (int nfd, void *rset, void *wset, void *eset,
- struct timeval *timeout);
+ struct timeval *timeout);
ssize_t (*waitpid) (pid_t pid, int *status, int options);
int (*accept) (int s, void *addr, int *length_ptr);
int (*connect) (int s, void *addr, gcry_socklen_t length);
@@ -224,7 +224,7 @@ struct gcry_thread_cbs
int (*recvmsg) (int s, void *msg, int flags);
#else
ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
- struct timeval *timeout);
+ struct timeval *timeout);
ssize_t (*waitpid) (pid_t pid, int *status, int options);
int (*accept) (int s, struct sockaddr *addr, gcry_socklen_t *length_ptr);
int (*connect) (int s, struct sockaddr *addr, gcry_socklen_t length);
@@ -241,10 +241,10 @@ static ssize_t gcry_pth_select (int nfd, void *rset, void *wset, \
static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
{ return pth_waitpid (pid, status, options); } \
static int gcry_pth_accept (int s, void *addr, \
- gcry_socklen_t *length_ptr) \
+ gcry_socklen_t *length_ptr) \
{ return pth_accept (s, addr, length_ptr); } \
static int gcry_pth_connect (int s, void *addr, \
- gcry_socklen_t length) \
+ gcry_socklen_t length) \
{ return pth_connect (s, addr, length); }
#else /*!_WIN32*/
# define _GCRY_THREAD_OPTION_PTH_IMPL_NET \
@@ -254,10 +254,10 @@ static ssize_t gcry_pth_select (int nfd, fd_set *rset, fd_set *wset, \
static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
{ return pth_waitpid (pid, status, options); } \
static int gcry_pth_accept (int s, struct sockaddr *addr, \
- gcry_socklen_t *length_ptr) \
+ gcry_socklen_t *length_ptr) \
{ return pth_accept (s, addr, length_ptr); } \
static int gcry_pth_connect (int s, struct sockaddr *addr, \
- gcry_socklen_t length) \
+ gcry_socklen_t length) \
{ return pth_connect (s, addr, length); }
#endif /*!_WIN32*/
@@ -270,37 +270,37 @@ static int gcry_pth_mutex_init (void **priv) \
{ \
int err = 0; \
pth_mutex_t *lock = malloc (sizeof (pth_mutex_t)); \
- \
+ \
if (!lock) \
- err = ENOMEM; \
+ err = ENOMEM; \
if (!err) \
- { \
- err = pth_mutex_init (lock); \
- if (err == FALSE) \
+ { \
+ err = pth_mutex_init (lock); \
+ if (err == FALSE) \
err = errno; \
- else \
+ else \
err = 0; \
- if (err) \
+ if (err) \
free (lock); \
- else \
+ else \
*priv = lock; \
- } \
+ } \
return err; \
} \
static int gcry_pth_mutex_destroy (void **lock) \
{ /* GNU Pth has no destructor function. */ free (*lock); return 0; } \
static int gcry_pth_mutex_lock (void **lock) \
{ return ((pth_mutex_acquire (*lock, 0, NULL)) == FALSE) \
- ? errno : 0; } \
+ ? errno : 0; } \
static int gcry_pth_mutex_unlock (void **lock) \
{ return ((pth_mutex_release (*lock)) == FALSE) \
- ? errno : 0; } \
+ ? errno : 0; } \
static ssize_t gcry_pth_read (int fd, void *buf, size_t nbytes) \
{ return pth_read (fd, buf, nbytes); } \
static ssize_t gcry_pth_write (int fd, const void *buf, size_t nbytes) \
{ return pth_write (fd, buf, nbytes); } \
_GCRY_THREAD_OPTION_PTH_IMPL_NET \
- \
+ \
/* Note: GNU Pth is missing pth_sendmsg and pth_recvmsg. */ \
static struct gcry_thread_cbs gcry_threads_pth = { \
(GCRY_THREAD_OPTION_PTH | (GCRY_THREAD_OPTION_VERSION << 8)), \
@@ -315,34 +315,34 @@ static int gcry_pthread_mutex_init (void **priv) \
{ \
int err = 0; \
pthread_mutex_t *lock = (pthread_mutex_t*)malloc (sizeof (pthread_mutex_t));\
- \
+ \
if (!lock) \
- err = ENOMEM; \
+ err = ENOMEM; \
if (!err) \
- { \
- err = pthread_mutex_init (lock, NULL); \
- if (err) \
+ { \
+ err = pthread_mutex_init (lock, NULL); \
+ if (err) \
free (lock); \
- else \
+ else \
*priv = lock; \
- } \
+ } \
return err; \
} \
static int gcry_pthread_mutex_destroy (void **lock) \
{ int err = pthread_mutex_destroy ((pthread_mutex_t*)*lock); \
- free (*lock); return err; } \
+ free (*lock); return err; } \
static int gcry_pthread_mutex_lock (void **lock) \
{ return pthread_mutex_lock ((pthread_mutex_t*)*lock); } \
static int gcry_pthread_mutex_unlock (void **lock) \
{ return pthread_mutex_unlock ((pthread_mutex_t*)*lock); } \
- \
+ \
static struct gcry_thread_cbs gcry_threads_pthread = { \
(GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)), \
NULL, gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, \
gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock, \
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
-
+
/* The data object used to hold a multi precision integer. */
struct gcry_mpi;
typedef struct gcry_mpi *gcry_mpi_t;
@@ -352,7 +352,7 @@ typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED;
typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED;
#endif
-
+
/* Check that the library fulfills the version requirement. */
const char *gcry_check_version (const char *req_version);
@@ -362,69 +362,69 @@ const char *gcry_check_version (const char *req_version);
/* Codes used with the gcry_control function. */
enum gcry_ctl_cmds
{
- GCRYCTL_SET_KEY = 1,
- GCRYCTL_SET_IV = 2,
- GCRYCTL_CFB_SYNC = 3,
- GCRYCTL_RESET = 4, /* e.g. for MDs */
- GCRYCTL_FINALIZE = 5,
- GCRYCTL_GET_KEYLEN = 6,
- GCRYCTL_GET_BLKLEN = 7,
- GCRYCTL_TEST_ALGO = 8,
- GCRYCTL_IS_SECURE = 9,
- GCRYCTL_GET_ASNOID = 10,
- GCRYCTL_ENABLE_ALGO = 11,
- GCRYCTL_DISABLE_ALGO = 12,
- GCRYCTL_DUMP_RANDOM_STATS = 13,
- GCRYCTL_DUMP_SECMEM_STATS = 14,
- GCRYCTL_GET_ALGO_NPKEY = 15,
- GCRYCTL_GET_ALGO_NSKEY = 16,
- GCRYCTL_GET_ALGO_NSIGN = 17,
- GCRYCTL_GET_ALGO_NENCR = 18,
- GCRYCTL_SET_VERBOSITY = 19,
- GCRYCTL_SET_DEBUG_FLAGS = 20,
- GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
- GCRYCTL_USE_SECURE_RNDPOOL= 22,
- GCRYCTL_DUMP_MEMORY_STATS = 23,
- GCRYCTL_INIT_SECMEM = 24,
- GCRYCTL_TERM_SECMEM = 25,
- GCRYCTL_DISABLE_SECMEM_WARN = 27,
- GCRYCTL_SUSPEND_SECMEM_WARN = 28,
- GCRYCTL_RESUME_SECMEM_WARN = 29,
- GCRYCTL_DROP_PRIVS = 30,
- GCRYCTL_ENABLE_M_GUARD = 31,
- GCRYCTL_START_DUMP = 32,
- GCRYCTL_STOP_DUMP = 33,
- GCRYCTL_GET_ALGO_USAGE = 34,
- GCRYCTL_IS_ALGO_ENABLED = 35,
- GCRYCTL_DISABLE_INTERNAL_LOCKING = 36,
- GCRYCTL_DISABLE_SECMEM = 37,
- GCRYCTL_INITIALIZATION_FINISHED = 38,
- GCRYCTL_INITIALIZATION_FINISHED_P = 39,
- GCRYCTL_ANY_INITIALIZATION_P = 40,
- GCRYCTL_SET_CBC_CTS = 41,
- GCRYCTL_SET_CBC_MAC = 42,
- GCRYCTL_SET_CTR = 43,
- GCRYCTL_ENABLE_QUICK_RANDOM = 44,
- GCRYCTL_SET_RANDOM_SEED_FILE = 45,
- GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
- GCRYCTL_SET_THREAD_CBS = 47,
- GCRYCTL_FAST_POLL = 48,
- GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49,
- GCRYCTL_USE_RANDOM_DAEMON = 50,
- GCRYCTL_FAKED_RANDOM_P = 51,
- GCRYCTL_SET_RNDEGD_SOCKET = 52,
- GCRYCTL_PRINT_CONFIG = 53,
- GCRYCTL_OPERATIONAL_P = 54,
- GCRYCTL_FIPS_MODE_P = 55,
- GCRYCTL_FORCE_FIPS_MODE = 56,
- GCRYCTL_SELFTEST = 57
- /* Note: 58 .. 62 are used internally. */
+ GCRYCTL_SET_KEY = 1,
+ GCRYCTL_SET_IV = 2,
+ GCRYCTL_CFB_SYNC = 3,
+ GCRYCTL_RESET = 4, /* e.g. for MDs */
+ GCRYCTL_FINALIZE = 5,
+ GCRYCTL_GET_KEYLEN = 6,
+ GCRYCTL_GET_BLKLEN = 7,
+ GCRYCTL_TEST_ALGO = 8,
+ GCRYCTL_IS_SECURE = 9,
+ GCRYCTL_GET_ASNOID = 10,
+ GCRYCTL_ENABLE_ALGO = 11,
+ GCRYCTL_DISABLE_ALGO = 12,
+ GCRYCTL_DUMP_RANDOM_STATS = 13,
+ GCRYCTL_DUMP_SECMEM_STATS = 14,
+ GCRYCTL_GET_ALGO_NPKEY = 15,
+ GCRYCTL_GET_ALGO_NSKEY = 16,
+ GCRYCTL_GET_ALGO_NSIGN = 17,
+ GCRYCTL_GET_ALGO_NENCR = 18,
+ GCRYCTL_SET_VERBOSITY = 19,
+ GCRYCTL_SET_DEBUG_FLAGS = 20,
+ GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
+ GCRYCTL_USE_SECURE_RNDPOOL= 22,
+ GCRYCTL_DUMP_MEMORY_STATS = 23,
+ GCRYCTL_INIT_SECMEM = 24,
+ GCRYCTL_TERM_SECMEM = 25,
+ GCRYCTL_DISABLE_SECMEM_WARN = 27,
+ GCRYCTL_SUSPEND_SECMEM_WARN = 28,
+ GCRYCTL_RESUME_SECMEM_WARN = 29,
+ GCRYCTL_DROP_PRIVS = 30,
+ GCRYCTL_ENABLE_M_GUARD = 31,
+ GCRYCTL_START_DUMP = 32,
+ GCRYCTL_STOP_DUMP = 33,
+ GCRYCTL_GET_ALGO_USAGE = 34,
+ GCRYCTL_IS_ALGO_ENABLED = 35,
+ GCRYCTL_DISABLE_INTERNAL_LOCKING = 36,
+ GCRYCTL_DISABLE_SECMEM = 37,
+ GCRYCTL_INITIALIZATION_FINISHED = 38,
+ GCRYCTL_INITIALIZATION_FINISHED_P = 39,
+ GCRYCTL_ANY_INITIALIZATION_P = 40,
+ GCRYCTL_SET_CBC_CTS = 41,
+ GCRYCTL_SET_CBC_MAC = 42,
+ GCRYCTL_SET_CTR = 43,
+ GCRYCTL_ENABLE_QUICK_RANDOM = 44,
+ GCRYCTL_SET_RANDOM_SEED_FILE = 45,
+ GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
+ GCRYCTL_SET_THREAD_CBS = 47,
+ GCRYCTL_FAST_POLL = 48,
+ GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49,
+ GCRYCTL_USE_RANDOM_DAEMON = 50,
+ GCRYCTL_FAKED_RANDOM_P = 51,
+ GCRYCTL_SET_RNDEGD_SOCKET = 52,
+ GCRYCTL_PRINT_CONFIG = 53,
+ GCRYCTL_OPERATIONAL_P = 54,
+ GCRYCTL_FIPS_MODE_P = 55,
+ GCRYCTL_FORCE_FIPS_MODE = 56,
+ GCRYCTL_SELFTEST = 57
+ /* Note: 58 .. 62 are used internally. */
};
/* Perform various operations defined by CMD. */
gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...);
-
+
/* S-expression management. */
/* The object to represent an S-expression as used with the public key
@@ -440,39 +440,39 @@ typedef struct gcry_sexp *GcrySexp _GCRY_GCC_ATTR_DEPRECATED;
/* The possible values for the S-expression format. */
enum gcry_sexp_format
{
- GCRYSEXP_FMT_DEFAULT = 0,
- GCRYSEXP_FMT_CANON = 1,
- GCRYSEXP_FMT_BASE64 = 2,
- GCRYSEXP_FMT_ADVANCED = 3
+ GCRYSEXP_FMT_DEFAULT = 0,
+ GCRYSEXP_FMT_CANON = 1,
+ GCRYSEXP_FMT_BASE64 = 2,
+ GCRYSEXP_FMT_ADVANCED = 3
};
/* Create an new S-expression object from BUFFER of size LENGTH and
return it in RETSEXP. With AUTODETECT set to 0 the data in BUFFER
is expected to be in canonized format. */
gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp,
- const void *buffer, size_t length,
- int autodetect);
+ const void *buffer, size_t length,
+ int autodetect);
/* Same as gcry_sexp_new but allows to pass a FREEFNC which has the
- effect to transfer ownership of BUFFER to the created object. */
+ effect to transfer ownership of BUFFER to the created object. */
gcry_error_t gcry_sexp_create (gcry_sexp_t *retsexp,
- void *buffer, size_t length,
- int autodetect, void (*freefnc) (void *));
+ void *buffer, size_t length,
+ int autodetect, void (*freefnc) (void *));
/* Scan BUFFER and return a new S-expression object in RETSEXP. This
function expects a printf like string in BUFFER. */
gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
- const char *buffer, size_t length);
+ const char *buffer, size_t length);
/* Same as gcry_sexp_sscan but expects a string in FORMAT and can thus
only be used for certain encodings. */
gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, ...);
+ const char *format, ...);
/* Like gcry_sexp_build, but uses an array instead of variable
function arguments. */
gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, void **arg_list);
+ const char *format, void **arg_list);
/* Release the S-expression object SEXP */
void gcry_sexp_release (gcry_sexp_t sexp);
@@ -480,12 +480,12 @@ void gcry_sexp_release (gcry_sexp_t sexp);
/* Calculate the length of an canonized S-expresion in BUFFER and
check for a valid encoding. */
size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
- size_t *erroff, gcry_error_t *errcode);
+ size_t *erroff, gcry_error_t *errcode);
/* Copies the S-expression object SEXP into BUFFER using the format
specified in MODE. */
size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
- size_t maxlength);
+ size_t maxlength);
/* Dumps the S-expression object A in a format suitable for debugging
to Libgcrypt's logging stream. */
@@ -503,7 +503,7 @@ gcry_sexp_t gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n);
newly allocated S-expression consisting of the found sublist or
`NULL' when not found. */
gcry_sexp_t gcry_sexp_find_token (gcry_sexp_t list,
- const char *tok, size_t toklen);
+ const char *tok, size_t toklen);
/* Return the length of the LIST. For a valid S-expression this
should be at least 1. */
int gcry_sexp_length (const gcry_sexp_t list);
@@ -535,7 +535,7 @@ gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list);
*Note:* The returned pointer is valid as long as LIST is not
modified or released. */
const char *gcry_sexp_nth_data (const gcry_sexp_t list, int number,
- size_t *datalen);
+ size_t *datalen);
/* This function is used to get and convert data from a LIST. The
data is assumed to be a Nul terminated string. The caller must
@@ -553,7 +553,7 @@ char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
-
+
/*******************************************
* *
* Multi Precision Integer Functions *
@@ -563,21 +563,21 @@ gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
/* Different formats of external big integer representation. */
enum gcry_mpi_format
{
- GCRYMPI_FMT_NONE= 0,
- GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */
- GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */
- GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */
- GCRYMPI_FMT_HEX = 4, /* Hex format. */
- GCRYMPI_FMT_USG = 5 /* Like STD but unsigned. */
+ GCRYMPI_FMT_NONE= 0,
+ GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */
+ GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */
+ GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */
+ GCRYMPI_FMT_HEX = 4, /* Hex format. */
+ GCRYMPI_FMT_USG = 5 /* Like STD but unsigned. */
};
/* Flags used for creating big integers. */
enum gcry_mpi_flag
{
- GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
- GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just
- a way to store some bytes. This is
- useful for encrypted big integers. */
+ GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
+ GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just
+ a way to store some bytes. This is
+ useful for encrypted big integers. */
};
@@ -617,8 +617,8 @@ int gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v);
RET_MPI. If NSCANNED is not NULL, it will receive the number of
bytes actually scanned after a successful operation. */
gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
- const void *buffer, size_t buflen,
- size_t *nscanned);
+ const void *buffer, size_t buflen,
+ size_t *nscanned);
/* Convert the big integer A into the external representation
described by FORMAT and store it in the provided BUFFER which has
@@ -626,17 +626,17 @@ gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
receives the actual length of the external representation unless it
has been passed as NULL. */
gcry_error_t gcry_mpi_print (enum gcry_mpi_format format,
- unsigned char *buffer, size_t buflen,
- size_t *nwritten,
- const gcry_mpi_t a);
+ unsigned char *buffer, size_t buflen,
+ size_t *nwritten,
+ const gcry_mpi_t a);
/* Convert the big integer A int the external representation described
by FORMAT and store it in a newly allocated buffer which address
will be put into BUFFER. NWRITTEN receives the actual lengths of the
external representation. */
gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format format,
- unsigned char **buffer, size_t *nwritten,
- const gcry_mpi_t a);
+ unsigned char **buffer, size_t *nwritten,
+ const gcry_mpi_t a);
/* Dump the value of A in a format suitable for debugging to
Libgcrypt's logging stream. Note that one leading space but no
@@ -678,15 +678,15 @@ void gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt);
/* Q = DIVIDEND / DIVISOR, R = DIVIDEND % DIVISOR,
Q or R may be passed as NULL. ROUND should be negative or 0. */
void gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
- gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
+ gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
/* R = DIVIDEND % DIVISOR */
void gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor);
/* W = B ^ E mod M. */
void gcry_mpi_powm (gcry_mpi_t w,
- const gcry_mpi_t b, const gcry_mpi_t e,
- const gcry_mpi_t m);
+ const gcry_mpi_t b, const gcry_mpi_t e,
+ const gcry_mpi_t m);
/* Set G to the greatest common divisor of A and B.
Return true if the G is 1. */
@@ -750,10 +750,10 @@ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
#define mpi_secure_new( n ) gcry_mpi_snew( (n) )
#define mpi_release(a) \
do \
- { \
- gcry_mpi_release ((a)); \
- (a) = NULL; \
- } \
+ { \
+ gcry_mpi_release ((a)); \
+ (a) = NULL; \
+ } \
while (0)
#define mpi_copy( a ) gcry_mpi_copy( (a) )
@@ -761,7 +761,7 @@ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) )
#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) )
#define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) )
-
+
#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v))
#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m))
@@ -793,7 +793,7 @@ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
#endif /* GCRYPT_NO_MPI_MACROS */
-
+
/************************************
* *
* Symmetric Cipher Functions *
@@ -813,31 +813,31 @@ typedef struct gcry_cipher_handle *GcryCipherHd _GCRY_GCC_ATTR_DEPRECATED;
More IDs may be registered at runtime. */
enum gcry_cipher_algos
{
- GCRY_CIPHER_NONE = 0,
- GCRY_CIPHER_IDEA = 1,
- GCRY_CIPHER_3DES = 2,
- GCRY_CIPHER_CAST5 = 3,
- GCRY_CIPHER_BLOWFISH = 4,
- GCRY_CIPHER_SAFER_SK128 = 5,
- GCRY_CIPHER_DES_SK = 6,
- GCRY_CIPHER_AES = 7,
- GCRY_CIPHER_AES192 = 8,
- GCRY_CIPHER_AES256 = 9,
- GCRY_CIPHER_TWOFISH = 10,
-
- /* Other cipher numbers are above 300 for OpenPGP reasons. */
- GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */
- GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */
- GCRY_CIPHER_TWOFISH128 = 303,
- GCRY_CIPHER_SERPENT128 = 304,
- GCRY_CIPHER_SERPENT192 = 305,
- GCRY_CIPHER_SERPENT256 = 306,
- GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */
- GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */
- GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */
- GCRY_CIPHER_CAMELLIA128 = 310,
- GCRY_CIPHER_CAMELLIA192 = 311,
- GCRY_CIPHER_CAMELLIA256 = 312
+ GCRY_CIPHER_NONE = 0,
+ GCRY_CIPHER_IDEA = 1,
+ GCRY_CIPHER_3DES = 2,
+ GCRY_CIPHER_CAST5 = 3,
+ GCRY_CIPHER_BLOWFISH = 4,
+ GCRY_CIPHER_SAFER_SK128 = 5,
+ GCRY_CIPHER_DES_SK = 6,
+ GCRY_CIPHER_AES = 7,
+ GCRY_CIPHER_AES192 = 8,
+ GCRY_CIPHER_AES256 = 9,
+ GCRY_CIPHER_TWOFISH = 10,
+
+ /* Other cipher numbers are above 300 for OpenPGP reasons. */
+ GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */
+ GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */
+ GCRY_CIPHER_TWOFISH128 = 303,
+ GCRY_CIPHER_SERPENT128 = 304,
+ GCRY_CIPHER_SERPENT192 = 305,
+ GCRY_CIPHER_SERPENT256 = 306,
+ GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */
+ GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */
+ GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */
+ GCRY_CIPHER_CAMELLIA128 = 310,
+ GCRY_CIPHER_CAMELLIA192 = 311,
+ GCRY_CIPHER_CAMELLIA256 = 312
};
/* The Rijndael algorithm is basically AES, so provide some macros. */
@@ -851,45 +851,45 @@ enum gcry_cipher_algos
supported for each algorithm. */
enum gcry_cipher_modes
{
- GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
- GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
- GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
- GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
- GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
- GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
- GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
- GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */
+ GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
+ GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
+ GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
+ GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
+ GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
+ GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
+ GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
+ GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */
};
/* Flags used with the open function. */
enum gcry_cipher_flags
{
- GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */
- GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
- GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
- GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
+ GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */
+ GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
+ GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
+ GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
};
/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may
be given as an bitwise OR of the gcry_cipher_flags values. */
gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
- int algo, int mode, unsigned int flags);
+ int algo, int mode, unsigned int flags);
/* Close the cioher handle H and release all resource. */
void gcry_cipher_close (gcry_cipher_hd_t h);
/* Perform various operations on the cipher object H. */
gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
- size_t buflen);
+ size_t buflen);
/* Retrieve various information about the cipher object H. */
gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer,
- size_t *nbytes);
+ size_t *nbytes);
/* Retrieve various information about the cipher algorithm ALGO. */
gcry_error_t gcry_cipher_algo_info (int algo, int what, void *buffer,
- size_t *nbytes);
+ size_t *nbytes);
/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
string representation of the algorithm name. For unknown algorithm
@@ -910,22 +910,22 @@ int gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE;
most algorithms it is possible to pass NULL for in and 0 for INLEN
and do a in-place decryption of the data provided in OUT. */
gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h,
- void *out, size_t outsize,
- const void *in, size_t inlen);
+ void *out, size_t outsize,
+ const void *in, size_t inlen);
/* The counterpart to gcry_cipher_encrypt. */
gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h,
- void *out, size_t outsize,
- const void *in, size_t inlen);
+ void *out, size_t outsize,
+ const void *in, size_t inlen);
/* Set KEY of length KEYLEN bytes for the cipher handle HD. */
gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd,
- const void *key, size_t keylen);
+ const void *key, size_t keylen);
/* Set initialization vector IV of length IVLEN for the cipher handle HD. */
gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd,
- const void *iv, size_t ivlen);
+ const void *iv, size_t ivlen);
/* Reset the handle to the state after open. */
@@ -937,12 +937,12 @@ gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd,
/* Enable or disable CTS in future calls to gcry_encrypt(). CBC mode only. */
#define gcry_cipher_cts(h,on) gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \
- NULL, on )
+ NULL, on )
/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
block size length, or (NULL,0) to set the CTR to the all-zero block. */
gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd,
- const void *ctr, size_t ctrlen);
+ const void *ctr, size_t ctrlen);
/* Retrieved the key length in bytes used with algorithm A. */
size_t gcry_cipher_get_algo_keylen (int algo);
@@ -952,7 +952,7 @@ size_t gcry_cipher_get_algo_blklen (int algo);
/* Return 0 if the algorithm A is available for use. */
#define gcry_cipher_test_algo(a) \
- gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+ gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/* Get a list consisting of the IDs of the loaded cipher modules. If
LIST is zero, write the number of loaded cipher modules to
@@ -962,7 +962,7 @@ size_t gcry_cipher_get_algo_blklen (int algo);
*LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
gcry_error_t gcry_cipher_list (int *list, int *list_length);
-
+
/************************************
* *
* Asymmetric Cipher Functions *
@@ -972,13 +972,13 @@ gcry_error_t gcry_cipher_list (int *list, int *list_length);
/* The algorithms and their IDs we support. */
enum gcry_pk_algos
{
- GCRY_PK_RSA = 1,
- GCRY_PK_RSA_E = 2, /* (deprecated) */
- GCRY_PK_RSA_S = 3, /* (deprecated) */
- GCRY_PK_ELG_E = 16,
- GCRY_PK_DSA = 17,
- GCRY_PK_ELG = 20,
- GCRY_PK_ECDSA = 301
+ GCRY_PK_RSA = 1,
+ GCRY_PK_RSA_E = 2, /* (deprecated) */
+ GCRY_PK_RSA_S = 3, /* (deprecated) */
+ GCRY_PK_ELG_E = 16,
+ GCRY_PK_DSA = 17,
+ GCRY_PK_ELG = 20,
+ GCRY_PK_ECDSA = 301
};
/* Flags describing usage capabilities of a PK algorithm. */
@@ -991,21 +991,21 @@ enum gcry_pk_algos
/* Encrypt the DATA using the public key PKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t pkey);
+ gcry_sexp_t data, gcry_sexp_t pkey);
/* Decrypt the DATA using the private key SKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_decrypt (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t skey);
+ gcry_sexp_t data, gcry_sexp_t skey);
/* Sign the DATA using the private key SKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_sign (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t skey);
+ gcry_sexp_t data, gcry_sexp_t skey);
/* Check the signature SIGVAL on DATA using the public key PKEY. */
gcry_error_t gcry_pk_verify (gcry_sexp_t sigval,
- gcry_sexp_t data, gcry_sexp_t pkey);
+ gcry_sexp_t data, gcry_sexp_t pkey);
/* Check that private KEY is sane. */
gcry_error_t gcry_pk_testkey (gcry_sexp_t key);
@@ -1020,7 +1020,7 @@ gcry_error_t gcry_pk_ctl (int cmd, void *buffer, size_t buflen);
/* Retrieve information about the public key algorithm ALGO. */
gcry_error_t gcry_pk_algo_info (int algo, int what,
- void *buffer, size_t *nbytes);
+ void *buffer, size_t *nbytes);
/* Map the public key algorithm whose ID is contained in ALGORITHM to
a string representation of the algorithm name. For unknown
@@ -1041,7 +1041,7 @@ unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
/* Return 0 if the public key algorithm A is available for use. */
#define gcry_pk_test_algo(a) \
- gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+ gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/* Get a list consisting of the IDs of the loaded pubkey modules. If
LIST is zero, write the number of loaded pubkey modules to
@@ -1051,7 +1051,7 @@ unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
*LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
gcry_error_t gcry_pk_list (int *list, int *list_length);
-
+
/************************************
* *
@@ -1063,31 +1063,31 @@ gcry_error_t gcry_pk_list (int *list, int *list_length);
are implemnted. */
enum gcry_md_algos
{
- GCRY_MD_NONE = 0,
- GCRY_MD_MD5 = 1,
- GCRY_MD_SHA1 = 2,
- GCRY_MD_RMD160 = 3,
- GCRY_MD_MD2 = 5,
- GCRY_MD_TIGER = 6, /* TIGER/192 as used by GnuPG <= 1.3.2. */
- GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
- GCRY_MD_SHA256 = 8,
- GCRY_MD_SHA384 = 9,
- GCRY_MD_SHA512 = 10,
- GCRY_MD_SHA224 = 11,
- GCRY_MD_MD4 = 301,
- GCRY_MD_CRC32 = 302,
- GCRY_MD_CRC32_RFC1510 = 303,
- GCRY_MD_CRC24_RFC2440 = 304,
- GCRY_MD_WHIRLPOOL = 305,
- GCRY_MD_TIGER1 = 306, /* TIGER (fixed). */
- GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */
+ GCRY_MD_NONE = 0,
+ GCRY_MD_MD5 = 1,
+ GCRY_MD_SHA1 = 2,
+ GCRY_MD_RMD160 = 3,
+ GCRY_MD_MD2 = 5,
+ GCRY_MD_TIGER = 6, /* TIGER/192 as used by GnuPG <= 1.3.2. */
+ GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
+ GCRY_MD_SHA256 = 8,
+ GCRY_MD_SHA384 = 9,
+ GCRY_MD_SHA512 = 10,
+ GCRY_MD_SHA224 = 11,
+ GCRY_MD_MD4 = 301,
+ GCRY_MD_CRC32 = 302,
+ GCRY_MD_CRC32_RFC1510 = 303,
+ GCRY_MD_CRC24_RFC2440 = 304,
+ GCRY_MD_WHIRLPOOL = 305,
+ GCRY_MD_TIGER1 = 306, /* TIGER (fixed). */
+ GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */
};
/* Flags used with the open function. */
enum gcry_md_flags
{
- GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
- GCRY_MD_FLAG_HMAC = 2 /* Make an HMAC out of this algorithm. */
+ GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
+ GCRY_MD_FLAG_HMAC = 2 /* Make an HMAC out of this algorithm. */
};
/* (Forward declaration.) */
@@ -1133,7 +1133,7 @@ void gcry_md_reset (gcry_md_hd_t hd);
/* Perform various operations on the digest object HD. */
gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd,
- void *buffer, size_t buflen);
+ void *buffer, size_t buflen);
/* Pass LENGTH bytes of data in BUFFER to the digest object HD so that
it can update the digest values. This is the actual hash
@@ -1150,7 +1150,7 @@ unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo);
DIGEST which must be large enough to hold the digest of the given
algorithm. */
void gcry_md_hash_buffer (int algo, void *digest,
- const void *buffer, size_t length);
+ const void *buffer, size_t length);
/* Retrieve the algorithm used with HD. This does not work reliable
if more than one algorithm is enabled in HD. */
@@ -1169,11 +1169,11 @@ int gcry_md_is_secure (gcry_md_hd_t a);
/* Retrieve various information about the object H. */
gcry_error_t gcry_md_info (gcry_md_hd_t h, int what, void *buffer,
- size_t *nbytes);
+ size_t *nbytes);
/* Retrieve various information about the algorithm ALGO. */
gcry_error_t gcry_md_algo_info (int algo, int what, void *buffer,
- size_t *nbytes);
+ size_t *nbytes);
/* Map the digest algorithm id ALGO to a string representation of the
algorithm name. For unknown algorithms this function returns
@@ -1197,40 +1197,40 @@ void gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
/* Update the hash(s) of H with the character C. This is a buffered
version of the gcry_md_write function. */
#define gcry_md_putc(h,c) \
- do { \
- gcry_md_hd_t h__ = (h); \
- if( (h__)->bufpos == (h__)->bufsize ) \
- gcry_md_write( (h__), NULL, 0 ); \
- (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
- } while(0)
+ do { \
+ gcry_md_hd_t h__ = (h); \
+ if( (h__)->bufpos == (h__)->bufsize ) \
+ gcry_md_write( (h__), NULL, 0 ); \
+ (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
+ } while(0)
/* Finalize the digest calculation. This is not really needed because
gcry_md_read() does this implicitly. */
#define gcry_md_final(a) \
- gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
+ gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
/* Return 0 if the algorithm A is available for use. */
#define gcry_md_test_algo(a) \
- gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+ gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/* Return an DER encoded ASN.1 OID for the algorithm A in buffer B. N
must point to size_t variable with the available size of buffer B.
After return it will receive the actual size of the returned
OID. */
#define gcry_md_get_asnoid(a,b,n) \
- gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n))
+ gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n))
/* Enable debugging for digest object A; i.e. create files named
dbgmd-<n>.<string> while hashing. B is a string used as the suffix
for the filename. This macro is deprecated, use gcry_md_debug. */
#ifndef GCRYPT_NO_DEPRECATED
#define gcry_md_start_debug(a,b) \
- gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 )
+ gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 )
/* Disable the debugging of A. This macro is deprecated, use
gcry_md_debug. */
#define gcry_md_stop_debug(a,b) \
- gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 )
+ gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 )
#endif
/* Get a list consisting of the IDs of the loaded message digest
@@ -1242,7 +1242,7 @@ void gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
number. */
gcry_error_t gcry_md_list (int *list, int *list_length);
-
+
/* Alternative interface for asymmetric cryptography. This interface
is deprecated. */
@@ -1250,34 +1250,34 @@ gcry_error_t gcry_md_list (int *list, int *list_length);
/* The algorithm IDs. */
typedef enum gcry_ac_id
{
- GCRY_AC_RSA = 1,
- GCRY_AC_DSA = 17,
- GCRY_AC_ELG = 20,
- GCRY_AC_ELG_E = 16
+ GCRY_AC_RSA = 1,
+ GCRY_AC_DSA = 17,
+ GCRY_AC_ELG = 20,
+ GCRY_AC_ELG_E = 16
}
gcry_ac_id_t;
/* Key types. */
typedef enum gcry_ac_key_type
{
- GCRY_AC_KEY_SECRET,
- GCRY_AC_KEY_PUBLIC
+ GCRY_AC_KEY_SECRET,
+ GCRY_AC_KEY_PUBLIC
}
gcry_ac_key_type_t;
/* Encoding methods. */
typedef enum gcry_ac_em
{
- GCRY_AC_EME_PKCS_V1_5,
- GCRY_AC_EMSA_PKCS_V1_5
+ GCRY_AC_EME_PKCS_V1_5,
+ GCRY_AC_EMSA_PKCS_V1_5
}
gcry_ac_em_t;
/* Encryption and Signature schemes. */
typedef enum gcry_ac_scheme
{
- GCRY_AC_ES_PKCS_V1_5,
- GCRY_AC_SSA_PKCS_V1_5
+ GCRY_AC_ES_PKCS_V1_5,
+ GCRY_AC_SSA_PKCS_V1_5
}
gcry_ac_scheme_t;
@@ -1302,8 +1302,8 @@ typedef struct gcry_ac_key_pair *gcry_ac_key_pair_t;
typedef struct gcry_ac_handle *gcry_ac_handle_t;
typedef gpg_error_t (*gcry_ac_data_read_cb_t) (void *opaque,
- unsigned char *buffer,
- size_t *buffer_n);
+ unsigned char *buffer,
+ size_t *buffer_n);
typedef gpg_error_t (*gcry_ac_data_write_cb_t) (void *opaque,
unsigned char *buffer,
@@ -1311,15 +1311,15 @@ typedef gpg_error_t (*gcry_ac_data_write_cb_t) (void *opaque,
typedef enum
{
- GCRY_AC_IO_READABLE,
- GCRY_AC_IO_WRITABLE
+ GCRY_AC_IO_READABLE,
+ GCRY_AC_IO_WRITABLE
}
gcry_ac_io_mode_t;
typedef enum
{
- GCRY_AC_IO_STRING,
- GCRY_AC_IO_CALLBACK
+ GCRY_AC_IO_STRING,
+ GCRY_AC_IO_CALLBACK
}
gcry_ac_io_type_t;
@@ -1330,34 +1330,34 @@ typedef struct gcry_ac_io
gcry_ac_io_type_t type _GCRY_ATTR_INTERNAL;
union
{
- union
- {
- struct
- {
+ union
+ {
+ struct
+ {
gcry_ac_data_read_cb_t cb;
void *opaque;
- } callback;
- struct
- {
+ } callback;
+ struct
+ {
unsigned char *data;
size_t data_n;
- } string;
- void *opaque;
- } readable;
- union
- {
- struct
- {
+ } string;
+ void *opaque;
+ } readable;
+ union
+ {
+ struct
+ {
gcry_ac_data_write_cb_t cb;
void *opaque;
- } callback;
- struct
- {
+ } callback;
+ struct
+ {
unsigned char **data;
size_t *data_n;
- } string;
- void *opaque;
- } writable;
+ } string;
+ void *opaque;
+ } writable;
} io _GCRY_ATTR_INTERNAL;
}
gcry_ac_io_t;
@@ -1402,7 +1402,7 @@ void gcry_ac_data_destroy (gcry_ac_data_t data);
/* Create a copy of the data set DATA and store it in DATA_CP. */
gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *data_cp,
- gcry_ac_data_t data);
+ gcry_ac_data_t data);
/* Return the number of named MPI values inside of the data set
DATA. */
@@ -1417,21 +1417,21 @@ void gcry_ac_data_clear (gcry_ac_data_t data);
GCRY_AC_FLAG_DATA_COPY, the values contained in the data set will
be deallocated when they are to be removed from the data set. */
gcry_error_t gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags,
- const char *name, gcry_mpi_t mpi);
+ const char *name, gcry_mpi_t mpi);
/* Store the value labelled with NAME found in DATA in MPI. If FLAGS
contains GCRY_AC_FLAG_COPY, store a copy of the MPI value contained
in the data set. MPI may be NULL. */
gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags,
- const char *name, gcry_mpi_t *mpi);
+ const char *name, gcry_mpi_t *mpi);
/* Stores in NAME and MPI the named MPI value contained in the data
set DATA with the index IDX. If FLAGS contains GCRY_AC_FLAG_COPY,
store copies of the values contained in the data set. NAME or MPI
may be NULL. */
gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags,
- unsigned int idx,
- const char **name, gcry_mpi_t *mpi);
+ unsigned int idx,
+ const char **name, gcry_mpi_t *mpi);
/* Convert the data set DATA into a new S-Expression, which is to be
stored in SEXP, according to the identifiers contained in
@@ -1443,13 +1443,13 @@ gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
S-Expression SEXP, according to the identifiers contained in
IDENTIFIERS. */
gcry_error_t gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp,
- const char **identifiers);
+ const char **identifiers);
/* Initialize AC_IO according to MODE, TYPE and the variable list of
arguments. The list of variable arguments to specify depends on
the given TYPE. */
void gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
- gcry_ac_io_type_t type, ...);
+ gcry_ac_io_type_t type, ...);
/* Initialize AC_IO according to MODE, TYPE and the variable list of
arguments AP. The list of variable arguments to specify depends on
@@ -1459,14 +1459,14 @@ void gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
/* Create a new ac handle. */
gcry_error_t gcry_ac_open (gcry_ac_handle_t *handle,
- gcry_ac_id_t algorithm, unsigned int flags);
+ gcry_ac_id_t algorithm, unsigned int flags);
/* Destroy an ac handle. */
void gcry_ac_close (gcry_ac_handle_t handle);
/* Initialize a key from a given data set. */
gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
- gcry_ac_key_type_t type, gcry_ac_data_t data);
+ gcry_ac_key_type_t type, gcry_ac_data_t data);
/* Generates a new key pair via the handle HANDLE of NBITS bits and
stores it in KEY_PAIR. In case non-standard settings are wanted, a
@@ -1474,13 +1474,13 @@ gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
matching the selected algorithm, can be given as KEY_SPEC.
MISC_DATA is not used yet. */
gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
- unsigned int nbits, void *spec,
- gcry_ac_key_pair_t *key_pair,
- gcry_mpi_t **misc_data);
+ unsigned int nbits, void *spec,
+ gcry_ac_key_pair_t *key_pair,
+ gcry_mpi_t **misc_data);
/* Returns the key of type WHICH out of the key pair KEY_PAIR. */
gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
- gcry_ac_key_type_t which);
+ gcry_ac_key_type_t which);
/* Returns the data set contained in the key KEY. */
gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t key);
@@ -1490,12 +1490,12 @@ gcry_error_t gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key);
/* Stores the number of bits of the key KEY in NBITS via HANDLE. */
gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t handle,
- gcry_ac_key_t key, unsigned int *nbits);
+ gcry_ac_key_t key, unsigned int *nbits);
/* Writes the 20 byte long key grip of the key KEY to KEY_GRIP via
HANDLE. */
gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key,
- unsigned char *key_grip);
+ unsigned char *key_grip);
/* Destroy a key. */
void gcry_ac_key_destroy (gcry_ac_key_t key);
@@ -1523,34 +1523,34 @@ gcry_error_t gcry_ac_data_decode (gcry_ac_em_t method,
the control of the flags FLAGS and store the resulting data set
into DATA_ENCRYPTED. */
gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t handle,
- unsigned int flags,
- gcry_ac_key_t key,
- gcry_mpi_t data_plain,
- gcry_ac_data_t *data_encrypted);
+ unsigned int flags,
+ gcry_ac_key_t key,
+ gcry_mpi_t data_plain,
+ gcry_ac_data_t *data_encrypted);
/* Decrypt the decrypted data contained in the data set DATA_ENCRYPTED
with the key KEY under the control of the flags FLAGS and store the
resulting plain text MPI value in DATA_PLAIN. */
gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t handle,
- unsigned int flags,
- gcry_ac_key_t key,
- gcry_mpi_t *data_plain,
- gcry_ac_data_t data_encrypted);
+ unsigned int flags,
+ gcry_ac_key_t key,
+ gcry_mpi_t *data_plain,
+ gcry_ac_data_t data_encrypted);
/* Sign the data contained in DATA with the key KEY and store the
resulting signature in the data set DATA_SIGNATURE. */
gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t handle,
- gcry_ac_key_t key,
- gcry_mpi_t data,
- gcry_ac_data_t *data_signature);
+ gcry_ac_key_t key,
+ gcry_mpi_t data,
+ gcry_ac_data_t *data_signature);
/* Verify that the signature contained in the data set DATA_SIGNATURE
is indeed the result of signing the data contained in DATA with the
secret key belonging to the public key KEY. */
gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t handle,
- gcry_ac_key_t key,
- gcry_mpi_t data,
- gcry_ac_data_t data_signature);
+ gcry_ac_key_t key,
+ gcry_mpi_t data,
+ gcry_ac_data_t data_signature);
/* Encrypts the plain text readable from IO_MESSAGE through HANDLE
with the public key KEY according to SCHEME, FLAGS and OPTS. If
@@ -1582,11 +1582,11 @@ gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle,
scheme (gcry_ac_ssa_*_t). The signature is written to
IO_SIGNATURE. */
gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t handle,
- gcry_ac_scheme_t scheme,
- unsigned int flags, void *opts,
- gcry_ac_key_t key,
- gcry_ac_io_t *io_message,
- gcry_ac_io_t *io_signature);
+ gcry_ac_scheme_t scheme,
+ unsigned int flags, void *opts,
+ gcry_ac_key_t key,
+ gcry_ac_io_t *io_message,
+ gcry_ac_io_t *io_signature);
/* Verifies through HANDLE that the signature readable from
IO_SIGNATURE is indeed the result of signing the message readable
@@ -1606,17 +1606,17 @@ gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t handle,
gcry_pk_algo_name. */
#ifndef GCRYPT_NO_DEPRECATED
gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t algorithm,
- const char **name)
- /* */ _GCRY_GCC_ATTR_DEPRECATED;
+ const char **name)
+ /* */ _GCRY_GCC_ATTR_DEPRECATED;
/* Store the numeric ID of the algorithm whose textual representation
is contained in NAME in ALGORITHM. This function is deprecated;
use gcry_pk_map_name. */
gcry_error_t gcry_ac_name_to_id (const char *name,
- gcry_ac_id_t *algorithm)
- /* */ _GCRY_GCC_ATTR_DEPRECATED;
+ gcry_ac_id_t *algorithm)
+ /* */ _GCRY_GCC_ATTR_DEPRECATED;
#endif
-
+
/************************************
* *
* Random Generating Functions *
@@ -1629,22 +1629,22 @@ gcry_error_t gcry_ac_name_to_id (const char *name,
(except with gcry_mpi_randomize); use gcry_create_nonce instead. */
typedef enum gcry_random_level
{
- GCRY_WEAK_RANDOM = 0,
- GCRY_STRONG_RANDOM = 1,
- GCRY_VERY_STRONG_RANDOM = 2
+ GCRY_WEAK_RANDOM = 0,
+ GCRY_STRONG_RANDOM = 1,
+ GCRY_VERY_STRONG_RANDOM = 2
}
gcry_random_level_t;
/* Fill BUFFER with LENGTH bytes of random, using random numbers of
quality LEVEL. */
void gcry_randomize (void *buffer, size_t length,
- enum gcry_random_level level);
+ enum gcry_random_level level);
/* Add the external random from BUFFER with LENGTH bytes into the
pool. QUALITY should either be -1 for unknown or in the range of 0
to 100 */
gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length,
- int quality);
+ int quality);
/* If random numbers are used in an application, this macro should be
called from time to time so that new stuff gets added to the
@@ -1655,20 +1655,20 @@ gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length,
/* Return NBYTES of allocated random using a random numbers of quality
LEVEL. */
void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
- _GCRY_GCC_ATTR_MALLOC;
+ _GCRY_GCC_ATTR_MALLOC;
/* Return NBYTES of allocated random using a random numbers of quality
LEVEL. The random numbers are created returned in "secure"
memory. */
void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
- _GCRY_GCC_ATTR_MALLOC;
+ _GCRY_GCC_ATTR_MALLOC;
/* Set the big integer W to a random value of NBITS using a random
generator with quality LEVEL. Note that by using a level of
GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */
void gcry_mpi_randomize (gcry_mpi_t w,
- unsigned int nbits, enum gcry_random_level level);
+ unsigned int nbits, enum gcry_random_level level);
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
@@ -1677,7 +1677,7 @@ void gcry_create_nonce (void *buffer, size_t length);
-
+
/*******************************/
/* */
/* Prime Number Functions */
@@ -1692,7 +1692,7 @@ void gcry_create_nonce (void *buffer, size_t length);
/* The function should return 1 if the operation shall continue, 0 to
reject the prime candidate. */
typedef int (*gcry_prime_check_func_t) (void *arg, int mode,
- gcry_mpi_t candidate);
+ gcry_mpi_t candidate);
/* Flags for gcry_prime_generate(): */
@@ -1710,22 +1710,22 @@ typedef int (*gcry_prime_check_func_t) (void *arg, int mode,
factors and store it in FACTORS. FLAGS might be used to influence
the prime number generation process. */
gcry_error_t gcry_prime_generate (gcry_mpi_t *prime,
- unsigned int prime_bits,
- unsigned int factor_bits,
- gcry_mpi_t **factors,
- gcry_prime_check_func_t cb_func,
- void *cb_arg,
- gcry_random_level_t random_level,
- unsigned int flags);
+ unsigned int prime_bits,
+ unsigned int factor_bits,
+ gcry_mpi_t **factors,
+ gcry_prime_check_func_t cb_func,
+ void *cb_arg,
+ gcry_random_level_t random_level,
+ unsigned int flags);
/* Find a generator for PRIME where the factorization of (prime-1) is
in the NULL terminated array FACTORS. Return the generator as a
newly allocated MPI in R_G. If START_G is not NULL, use this as
teh start for the search. */
gcry_error_t gcry_prime_group_generator (gcry_mpi_t *r_g,
- gcry_mpi_t prime,
- gcry_mpi_t *factors,
- gcry_mpi_t start_g);
+ gcry_mpi_t prime,
+ gcry_mpi_t *factors,
+ gcry_mpi_t start_g);
/* Convenience function to release the FACTORS array. */
@@ -1736,7 +1736,7 @@ void gcry_prime_release_factors (gcry_mpi_t *factors);
gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
-
+
/************************************
* *
* Miscellaneous Stuff *
@@ -1746,13 +1746,13 @@ gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
/* Log levels used by the internal logging facility. */
enum gcry_log_levels
{
- GCRY_LOG_CONT = 0, /* (Continue the last log line.) */
- GCRY_LOG_INFO = 10,
- GCRY_LOG_WARN = 20,
- GCRY_LOG_ERROR = 30,
- GCRY_LOG_FATAL = 40,
- GCRY_LOG_BUG = 50,
- GCRY_LOG_DEBUG = 100
+ GCRY_LOG_CONT = 0, /* (Continue the last log line.) */
+ GCRY_LOG_INFO = 10,
+ GCRY_LOG_WARN = 20,
+ GCRY_LOG_ERROR = 30,
+ GCRY_LOG_FATAL = 40,
+ GCRY_LOG_BUG = 50,
+ GCRY_LOG_DEBUG = 100
};
/* Type for progress handlers. */
@@ -1786,11 +1786,11 @@ void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
/* Register a custom memory allocation functions. */
void gcry_set_allocation_handler (
- gcry_handler_alloc_t func_alloc,
- gcry_handler_alloc_t func_alloc_secure,
- gcry_handler_secure_check_t func_secure_check,
- gcry_handler_realloc_t func_realloc,
- gcry_handler_free_t func_free);
+ gcry_handler_alloc_t func_alloc,
+ gcry_handler_alloc_t func_alloc_secure,
+ gcry_handler_secure_check_t func_secure_check,
+ gcry_handler_realloc_t func_realloc,
+ gcry_handler_free_t func_free);
/* Register a function used instead of the internal out of memory
handler. */
diff --git a/libgcrypt-1.4.6/src/gcrypt.h.in b/libgcrypt-1.4.6/src/gcrypt.h.in
index 3d1cb4c..cf6eef6 100644
--- a/libgcrypt-1.4.6/src/gcrypt.h.in
+++ b/libgcrypt-1.4.6/src/gcrypt.h.in
@@ -1,1839 +1,1845 @@
-/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*-
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
- This file is part of Libgcrypt.
-
- Libgcrypt is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- Libgcrypt 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- File: @configure_input@ */
-
-#ifndef _GCRYPT_H
-#define _GCRYPT_H
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <gpg-error.h>
-
-#include <sys/types.h>
-
-#if defined _WIN32 || defined __WIN32__
-# include <winsock2.h>
-# include <ws2tcpip.h>
-# include <time.h>
-# ifndef __GNUC__
- typedef long ssize_t;
- typedef int pid_t;
-# endif /*!__GNUC__*/
-#else
-# include <sys/socket.h>
-# include <sys/time.h>
-#endif /*!_WIN32*/
-
-@FALLBACK_SOCKLEN_T@
-
-
-/* This is required for error code compatibility. */
-#define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
-
-#ifdef __cplusplus
-extern "C" {
-#if 0 /* (Keep Emacsens' auto-indent happy.) */
-}
-#endif
-#endif
-
-/* The version of this header should match the one of the library. It
- should not be used by a program because gcry_check_version() should
- return the same version. The purpose of this macro is to let
- autoconf (using the AM_PATH_GCRYPT macro) check that this header
- matches the installed library. */
-#define GCRYPT_VERSION "@VERSION@"
-
-/* Internal: We can't use the convenience macros for the multi
- precision integer functions when building this library. */
-#ifdef _GCRYPT_IN_LIBGCRYPT
-#ifndef GCRYPT_NO_MPI_MACROS
-#define GCRYPT_NO_MPI_MACROS 1
-#endif
-#endif
-
-/* We want to use gcc attributes when possible. Warning: Don't use
- these macros in your programs: As indicated by the leading
- underscore they are subject to change without notice. */
-#ifdef __GNUC__
-
-#define _GCRY_GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
-
-#if _GCRY_GCC_VERSION >= 30100
-#define _GCRY_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
-#endif
-
-#if _GCRY_GCC_VERSION >= 29600
-#define _GCRY_GCC_ATTR_PURE __attribute__ ((__pure__))
-#endif
-
-#if _GCRY_GCC_VERSION >= 30200
-#define _GCRY_GCC_ATTR_MALLOC __attribute__ ((__malloc__))
-#endif
-
-#endif /*__GNUC__*/
-
-#ifndef _GCRY_GCC_ATTR_DEPRECATED
-#define _GCRY_GCC_ATTR_DEPRECATED
-#endif
-#ifndef _GCRY_GCC_ATTR_PURE
-#define _GCRY_GCC_ATTR_PURE
-#endif
-#ifndef _GCRY_GCC_ATTR_MALLOC
-#define _GCRY_GCC_ATTR_MALLOC
-#endif
-
-/* Some members in a public type should only be used internally.
- There is no "internal" attribute, so we abuse the deprecated
- attribute to discourage external use. */
-#ifdef _GCRYPT_IN_LIBGCRYPT
-#define _GCRY_ATTR_INTERNAL
-#else
-#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED
-#endif
-
-/* Wrappers for the libgpg-error library. */
-
-typedef gpg_error_t gcry_error_t;
-typedef gpg_err_code_t gcry_err_code_t;
-typedef gpg_err_source_t gcry_err_source_t;
-
-static GPG_ERR_INLINE gcry_error_t
-gcry_err_make (gcry_err_source_t source, gcry_err_code_t code)
-{
- return gpg_err_make (source, code);
-}
-
-/* The user can define GPG_ERR_SOURCE_DEFAULT before including this
- file to specify a default source for gpg_error. */
-#ifndef GCRY_ERR_SOURCE_DEFAULT
-#define GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
-#endif
-
-static GPG_ERR_INLINE gcry_error_t
-gcry_error (gcry_err_code_t code)
-{
- return gcry_err_make (GCRY_ERR_SOURCE_DEFAULT, code);
-}
-
-static GPG_ERR_INLINE gcry_err_code_t
-gcry_err_code (gcry_error_t err)
-{
- return gpg_err_code (err);
-}
-
-
-static GPG_ERR_INLINE gcry_err_source_t
-gcry_err_source (gcry_error_t err)
-{
- return gpg_err_source (err);
-}
-
-/* Return a pointer to a string containing a description of the error
- code in the error value ERR. */
-const char *gcry_strerror (gcry_error_t err);
-
-/* Return a pointer to a string containing a description of the error
- source in the error value ERR. */
-const char *gcry_strsource (gcry_error_t err);
-
-/* Retrieve the error code for the system error ERR. This returns
- GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
- this). */
-gcry_err_code_t gcry_err_code_from_errno (int err);
-
-/* Retrieve the system error for the error code CODE. This returns 0
- if CODE is not a system error code. */
-int gcry_err_code_to_errno (gcry_err_code_t code);
-
-/* Return an error value with the error source SOURCE and the system
- error ERR. */
-gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err);
-
-/* Return an error value with the system error ERR. */
-gcry_err_code_t gcry_error_from_errno (int err);
-
-
-/* This enum is deprecated; it is only declared for the sake of
- complete API compatibility. */
-enum gcry_thread_option
- {
- _GCRY_THREAD_OPTION_DUMMY
- } _GCRY_GCC_ATTR_DEPRECATED;
-
-
-/* Constants defining the thread model to use. Used with the OPTION
- field of the struct gcry_thread_cbs. */
-#define GCRY_THREAD_OPTION_DEFAULT 0
-#define GCRY_THREAD_OPTION_USER 1
-#define GCRY_THREAD_OPTION_PTH 2
-#define GCRY_THREAD_OPTION_PTHREAD 3
-
-/* The version number encoded in the OPTION field of the struct
- gcry_thread_cbs. */
-#define GCRY_THREAD_OPTION_VERSION 0
-
-/* Wrapper for struct ath_ops. */
-struct gcry_thread_cbs
-{
- /* The OPTION field encodes the thread model and the version number
- of this structure.
- Bits 7 - 0 are used for the thread model
- Bits 15 - 8 are used for the version number.
- */
- unsigned int option;
-
- int (*init) (void);
- int (*mutex_init) (void **priv);
- int (*mutex_destroy) (void **priv);
- int (*mutex_lock) (void **priv);
- int (*mutex_unlock) (void **priv);
- ssize_t (*read) (int fd, void *buf, size_t nbytes);
- ssize_t (*write) (int fd, const void *buf, size_t nbytes);
-#ifdef _WIN32
- ssize_t (*select) (int nfd, void *rset, void *wset, void *eset,
- struct timeval *timeout);
- ssize_t (*waitpid) (pid_t pid, int *status, int options);
- int (*accept) (int s, void *addr, int *length_ptr);
- int (*connect) (int s, void *addr, gcry_socklen_t length);
- int (*sendmsg) (int s, const void *msg, int flags);
- int (*recvmsg) (int s, void *msg, int flags);
-#else
- ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
- struct timeval *timeout);
- ssize_t (*waitpid) (pid_t pid, int *status, int options);
- int (*accept) (int s, struct sockaddr *addr, gcry_socklen_t *length_ptr);
- int (*connect) (int s, struct sockaddr *addr, gcry_socklen_t length);
- int (*sendmsg) (int s, const struct msghdr *msg, int flags);
- int (*recvmsg) (int s, struct msghdr *msg, int flags);
-#endif
-};
-
-#ifdef _WIN32
-# define _GCRY_THREAD_OPTION_PTH_IMPL_NET \
-static ssize_t gcry_pth_select (int nfd, void *rset, void *wset, \
- void *eset, struct timeval *timeout) \
- { return pth_select (nfd, rset, wset, eset, timeout); } \
-static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
- { return pth_waitpid (pid, status, options); } \
-static int gcry_pth_accept (int s, void *addr, \
- gcry_socklen_t *length_ptr) \
- { return pth_accept (s, addr, length_ptr); } \
-static int gcry_pth_connect (int s, void *addr, \
- gcry_socklen_t length) \
- { return pth_connect (s, addr, length); }
-#else /*!_WIN32*/
-# define _GCRY_THREAD_OPTION_PTH_IMPL_NET \
-static ssize_t gcry_pth_select (int nfd, fd_set *rset, fd_set *wset, \
- fd_set *eset, struct timeval *timeout) \
- { return pth_select (nfd, rset, wset, eset, timeout); } \
-static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
- { return pth_waitpid (pid, status, options); } \
-static int gcry_pth_accept (int s, struct sockaddr *addr, \
- gcry_socklen_t *length_ptr) \
- { return pth_accept (s, addr, length_ptr); } \
-static int gcry_pth_connect (int s, struct sockaddr *addr, \
- gcry_socklen_t length) \
- { return pth_connect (s, addr, length); }
-#endif /*!_WIN32*/
-
-
-
-#define GCRY_THREAD_OPTION_PTH_IMPL \
-static int gcry_pth_init (void) \
-{ return (pth_init () == FALSE) ? errno : 0; } \
-static int gcry_pth_mutex_init (void **priv) \
-{ \
- int err = 0; \
- pth_mutex_t *lock = malloc (sizeof (pth_mutex_t)); \
- \
- if (!lock) \
- err = ENOMEM; \
- if (!err) \
- { \
- err = pth_mutex_init (lock); \
- if (err == FALSE) \
- err = errno; \
- else \
- err = 0; \
- if (err) \
- free (lock); \
- else \
- *priv = lock; \
- } \
- return err; \
-} \
-static int gcry_pth_mutex_destroy (void **lock) \
- { /* GNU Pth has no destructor function. */ free (*lock); return 0; } \
-static int gcry_pth_mutex_lock (void **lock) \
- { return ((pth_mutex_acquire (*lock, 0, NULL)) == FALSE) \
- ? errno : 0; } \
-static int gcry_pth_mutex_unlock (void **lock) \
- { return ((pth_mutex_release (*lock)) == FALSE) \
- ? errno : 0; } \
-static ssize_t gcry_pth_read (int fd, void *buf, size_t nbytes) \
- { return pth_read (fd, buf, nbytes); } \
-static ssize_t gcry_pth_write (int fd, const void *buf, size_t nbytes) \
- { return pth_write (fd, buf, nbytes); } \
-_GCRY_THREAD_OPTION_PTH_IMPL_NET \
- \
-/* Note: GNU Pth is missing pth_sendmsg and pth_recvmsg. */ \
-static struct gcry_thread_cbs gcry_threads_pth = { \
- (GCRY_THREAD_OPTION_PTH | (GCRY_THREAD_OPTION_VERSION << 8)), \
- gcry_pth_init, gcry_pth_mutex_init, gcry_pth_mutex_destroy, \
- gcry_pth_mutex_lock, gcry_pth_mutex_unlock, gcry_pth_read, gcry_pth_write, \
- gcry_pth_select, gcry_pth_waitpid, gcry_pth_accept, gcry_pth_connect, \
- NULL, NULL }
-
-
-#define GCRY_THREAD_OPTION_PTHREAD_IMPL \
-static int gcry_pthread_mutex_init (void **priv) \
-{ \
- int err = 0; \
- pthread_mutex_t *lock = (pthread_mutex_t*)malloc (sizeof (pthread_mutex_t));\
- \
- if (!lock) \
- err = ENOMEM; \
- if (!err) \
- { \
- err = pthread_mutex_init (lock, NULL); \
- if (err) \
- free (lock); \
- else \
- *priv = lock; \
- } \
- return err; \
-} \
-static int gcry_pthread_mutex_destroy (void **lock) \
- { int err = pthread_mutex_destroy ((pthread_mutex_t*)*lock); \
- free (*lock); return err; } \
-static int gcry_pthread_mutex_lock (void **lock) \
- { return pthread_mutex_lock ((pthread_mutex_t*)*lock); } \
-static int gcry_pthread_mutex_unlock (void **lock) \
- { return pthread_mutex_unlock ((pthread_mutex_t*)*lock); } \
- \
-static struct gcry_thread_cbs gcry_threads_pthread = { \
- (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)), \
- NULL, gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, \
- gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock, \
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
-
-
-/* The data object used to hold a multi precision integer. */
-struct gcry_mpi;
-typedef struct gcry_mpi *gcry_mpi_t;
-
-#ifndef GCRYPT_NO_DEPRECATED
-typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED;
-typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED;
-#endif
-
-
-
-/* Check that the library fulfills the version requirement. */
-const char *gcry_check_version (const char *req_version);
-
-/* Codes for function dispatchers. */
-
-/* Codes used with the gcry_control function. */
-enum gcry_ctl_cmds
- {
- GCRYCTL_SET_KEY = 1,
- GCRYCTL_SET_IV = 2,
- GCRYCTL_CFB_SYNC = 3,
- GCRYCTL_RESET = 4, /* e.g. for MDs */
- GCRYCTL_FINALIZE = 5,
- GCRYCTL_GET_KEYLEN = 6,
- GCRYCTL_GET_BLKLEN = 7,
- GCRYCTL_TEST_ALGO = 8,
- GCRYCTL_IS_SECURE = 9,
- GCRYCTL_GET_ASNOID = 10,
- GCRYCTL_ENABLE_ALGO = 11,
- GCRYCTL_DISABLE_ALGO = 12,
- GCRYCTL_DUMP_RANDOM_STATS = 13,
- GCRYCTL_DUMP_SECMEM_STATS = 14,
- GCRYCTL_GET_ALGO_NPKEY = 15,
- GCRYCTL_GET_ALGO_NSKEY = 16,
- GCRYCTL_GET_ALGO_NSIGN = 17,
- GCRYCTL_GET_ALGO_NENCR = 18,
- GCRYCTL_SET_VERBOSITY = 19,
- GCRYCTL_SET_DEBUG_FLAGS = 20,
- GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
- GCRYCTL_USE_SECURE_RNDPOOL= 22,
- GCRYCTL_DUMP_MEMORY_STATS = 23,
- GCRYCTL_INIT_SECMEM = 24,
- GCRYCTL_TERM_SECMEM = 25,
- GCRYCTL_DISABLE_SECMEM_WARN = 27,
- GCRYCTL_SUSPEND_SECMEM_WARN = 28,
- GCRYCTL_RESUME_SECMEM_WARN = 29,
- GCRYCTL_DROP_PRIVS = 30,
- GCRYCTL_ENABLE_M_GUARD = 31,
- GCRYCTL_START_DUMP = 32,
- GCRYCTL_STOP_DUMP = 33,
- GCRYCTL_GET_ALGO_USAGE = 34,
- GCRYCTL_IS_ALGO_ENABLED = 35,
- GCRYCTL_DISABLE_INTERNAL_LOCKING = 36,
- GCRYCTL_DISABLE_SECMEM = 37,
- GCRYCTL_INITIALIZATION_FINISHED = 38,
- GCRYCTL_INITIALIZATION_FINISHED_P = 39,
- GCRYCTL_ANY_INITIALIZATION_P = 40,
- GCRYCTL_SET_CBC_CTS = 41,
- GCRYCTL_SET_CBC_MAC = 42,
- GCRYCTL_SET_CTR = 43,
- GCRYCTL_ENABLE_QUICK_RANDOM = 44,
- GCRYCTL_SET_RANDOM_SEED_FILE = 45,
- GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
- GCRYCTL_SET_THREAD_CBS = 47,
- GCRYCTL_FAST_POLL = 48,
- GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49,
- GCRYCTL_USE_RANDOM_DAEMON = 50,
- GCRYCTL_FAKED_RANDOM_P = 51,
- GCRYCTL_SET_RNDEGD_SOCKET = 52,
- GCRYCTL_PRINT_CONFIG = 53,
- GCRYCTL_OPERATIONAL_P = 54,
- GCRYCTL_FIPS_MODE_P = 55,
- GCRYCTL_FORCE_FIPS_MODE = 56,
- GCRYCTL_SELFTEST = 57
- /* Note: 58 .. 62 are used internally. */
- };
-
-/* Perform various operations defined by CMD. */
-gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...);
-
-
-/* S-expression management. */
-
-/* The object to represent an S-expression as used with the public key
- functions. */
-struct gcry_sexp;
-typedef struct gcry_sexp *gcry_sexp_t;
-
-#ifndef GCRYPT_NO_DEPRECATED
-typedef struct gcry_sexp *GCRY_SEXP _GCRY_GCC_ATTR_DEPRECATED;
-typedef struct gcry_sexp *GcrySexp _GCRY_GCC_ATTR_DEPRECATED;
-#endif
-
-/* The possible values for the S-expression format. */
-enum gcry_sexp_format
- {
- GCRYSEXP_FMT_DEFAULT = 0,
- GCRYSEXP_FMT_CANON = 1,
- GCRYSEXP_FMT_BASE64 = 2,
- GCRYSEXP_FMT_ADVANCED = 3
- };
-
-/* Create an new S-expression object from BUFFER of size LENGTH and
- return it in RETSEXP. With AUTODETECT set to 0 the data in BUFFER
- is expected to be in canonized format. */
-gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp,
- const void *buffer, size_t length,
- int autodetect);
-
- /* Same as gcry_sexp_new but allows to pass a FREEFNC which has the
- effect to transfer ownership of BUFFER to the created object. */
-gcry_error_t gcry_sexp_create (gcry_sexp_t *retsexp,
- void *buffer, size_t length,
- int autodetect, void (*freefnc) (void *));
-
-/* Scan BUFFER and return a new S-expression object in RETSEXP. This
- function expects a printf like string in BUFFER. */
-gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
- const char *buffer, size_t length);
-
-/* Same as gcry_sexp_sscan but expects a string in FORMAT and can thus
- only be used for certain encodings. */
-gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, ...);
-
-/* Like gcry_sexp_build, but uses an array instead of variable
- function arguments. */
-gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, void **arg_list);
-
-/* Release the S-expression object SEXP */
-void gcry_sexp_release (gcry_sexp_t sexp);
-
-/* Calculate the length of an canonized S-expresion in BUFFER and
- check for a valid encoding. */
-size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
- size_t *erroff, gcry_error_t *errcode);
-
-/* Copies the S-expression object SEXP into BUFFER using the format
- specified in MODE. */
-size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
- size_t maxlength);
-
-/* Dumps the S-expression object A in a format suitable for debugging
- to Libgcrypt's logging stream. */
-void gcry_sexp_dump (const gcry_sexp_t a);
-
-gcry_sexp_t gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b);
-gcry_sexp_t gcry_sexp_alist (const gcry_sexp_t *array);
-gcry_sexp_t gcry_sexp_vlist (const gcry_sexp_t a, ...);
-gcry_sexp_t gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n);
-gcry_sexp_t gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n);
-
-/* Scan the S-expression for a sublist with a type (the car of the
- list) matching the string TOKEN. If TOKLEN is not 0, the token is
- assumed to be raw memory of this length. The function returns a
- newly allocated S-expression consisting of the found sublist or
- `NULL' when not found. */
-gcry_sexp_t gcry_sexp_find_token (gcry_sexp_t list,
- const char *tok, size_t toklen);
-/* Return the length of the LIST. For a valid S-expression this
- should be at least 1. */
-int gcry_sexp_length (const gcry_sexp_t list);
-
-/* Create and return a new S-expression from the element with index
- NUMBER in LIST. Note that the first element has the index 0. If
- there is no such element, `NULL' is returned. */
-gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t list, int number);
-
-/* Create and return a new S-expression from the first element in
- LIST; this called the "type" and should always exist and be a
- string. `NULL' is returned in case of a problem. */
-gcry_sexp_t gcry_sexp_car (const gcry_sexp_t list);
-
-/* Create and return a new list form all elements except for the first
- one. Note, that this function may return an invalid S-expression
- because it is not guaranteed, that the type exists and is a string.
- However, for parsing a complex S-expression it might be useful for
- intermediate lists. Returns `NULL' on error. */
-gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t list);
-
-gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list);
-
-
-/* This function is used to get data from a LIST. A pointer to the
- actual data with index NUMBER is returned and the length of this
- data will be stored to DATALEN. If there is no data at the given
- index or the index represents another list, `NULL' is returned.
- *Note:* The returned pointer is valid as long as LIST is not
- modified or released. */
-const char *gcry_sexp_nth_data (const gcry_sexp_t list, int number,
- size_t *datalen);
-
-/* This function is used to get and convert data from a LIST. The
- data is assumed to be a Nul terminated string. The caller must
- release the returned value using `gcry_free'. If there is no data
- at the given index, the index represents a list or the value can't
- be converted to a string, `NULL' is returned. */
-char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
-
-/* This function is used to get and convert data from a LIST. This
- data is assumed to be an MPI stored in the format described by
- MPIFMT and returned as a standard Libgcrypt MPI. The caller must
- release this returned value using `gcry_mpi_release'. If there is
- no data at the given index, the index represents a list or the
- value can't be converted to an MPI, `NULL' is returned. */
-gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
-
-
-
-/*******************************************
- * *
- * Multi Precision Integer Functions *
- * *
- *******************************************/
-
-/* Different formats of external big integer representation. */
-enum gcry_mpi_format
- {
- GCRYMPI_FMT_NONE= 0,
- GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */
- GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */
- GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */
- GCRYMPI_FMT_HEX = 4, /* Hex format. */
- GCRYMPI_FMT_USG = 5 /* Like STD but unsigned. */
- };
-
-/* Flags used for creating big integers. */
-enum gcry_mpi_flag
- {
- GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
- GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just
- a way to store some bytes. This is
- useful for encrypted big integers. */
- };
-
-
-/* Allocate a new big integer object, initialize it with 0 and
- initially allocate memory for a number of at least NBITS. */
-gcry_mpi_t gcry_mpi_new (unsigned int nbits);
-
-/* Same as gcry_mpi_new() but allocate in "secure" memory. */
-gcry_mpi_t gcry_mpi_snew (unsigned int nbits);
-
-/* Release the number A and free all associated resources. */
-void gcry_mpi_release (gcry_mpi_t a);
-
-/* Create a new number with the same value as A. */
-gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t a);
-
-/* Store the big integer value U in W. */
-gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
-
-/* Store the unsigned integer value U in W. */
-gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
-
-/* Swap the values of A and B. */
-void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
-
-/* Compare the big integer number U and V returning 0 for equality, a
- positive value for U > V and a negative for U < V. */
-int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v);
-
-/* Compare the big integer number U with the unsigned integer V
- returning 0 for equality, a positive value for U > V and a negative
- for U < V. */
-int gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v);
-
-/* Convert the external representation of an integer stored in BUFFER
- with a length of BUFLEN into a newly create MPI returned in
- RET_MPI. If NSCANNED is not NULL, it will receive the number of
- bytes actually scanned after a successful operation. */
-gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
- const void *buffer, size_t buflen,
- size_t *nscanned);
-
-/* Convert the big integer A into the external representation
- described by FORMAT and store it in the provided BUFFER which has
- been allocated by the user with a size of BUFLEN bytes. NWRITTEN
- receives the actual length of the external representation unless it
- has been passed as NULL. */
-gcry_error_t gcry_mpi_print (enum gcry_mpi_format format,
- unsigned char *buffer, size_t buflen,
- size_t *nwritten,
- const gcry_mpi_t a);
-
-/* Convert the big integer A int the external representation described
- by FORMAT and store it in a newly allocated buffer which address
- will be put into BUFFER. NWRITTEN receives the actual lengths of the
- external representation. */
-gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format format,
- unsigned char **buffer, size_t *nwritten,
- const gcry_mpi_t a);
-
-/* Dump the value of A in a format suitable for debugging to
- Libgcrypt's logging stream. Note that one leading space but no
- trailing space or linefeed will be printed. It is okay to pass
- NULL for A. */
-void gcry_mpi_dump (const gcry_mpi_t a);
-
-
-/* W = U + V. */
-void gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
-
-/* W = U + V. V is an unsigned integer. */
-void gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v);
-
-/* W = U + V mod M. */
-void gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
-
-/* W = U - V. */
-void gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
-
-/* W = U - V. V is an unsigned integer. */
-void gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
-
-/* W = U - V mod M */
-void gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
-
-/* W = U * V. */
-void gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
-
-/* W = U * V. V is an unsigned integer. */
-void gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
-
-/* W = U * V mod M. */
-void gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
-
-/* W = U * (2 ^ CNT). */
-void gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt);
-
-/* Q = DIVIDEND / DIVISOR, R = DIVIDEND % DIVISOR,
- Q or R may be passed as NULL. ROUND should be negative or 0. */
-void gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
- gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
-
-/* R = DIVIDEND % DIVISOR */
-void gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor);
-
-/* W = B ^ E mod M. */
-void gcry_mpi_powm (gcry_mpi_t w,
- const gcry_mpi_t b, const gcry_mpi_t e,
- const gcry_mpi_t m);
-
-/* Set G to the greatest common divisor of A and B.
- Return true if the G is 1. */
-int gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b);
-
-/* Set X to the multiplicative inverse of A mod M.
- Return true if the value exists. */
-int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m);
-
-
-/* Return the number of bits required to represent A. */
-unsigned int gcry_mpi_get_nbits (gcry_mpi_t a);
-
-/* Return true when bit number N (counting from 0) is set in A. */
-int gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n);
-
-/* Set bit number N in A. */
-void gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n);
-
-/* Clear bit number N in A. */
-void gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n);
-
-/* Set bit number N in A and clear all bits greater than N. */
-void gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n);
-
-/* Clear bit number N in A and all bits greater than N. */
-void gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n);
-
-/* Shift the value of A by N bits to the right and store the result in X. */
-void gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
-
-/* Shift the value of A by N bits to the left and store the result in X. */
-void gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
-
-/* Store NBITS of the value P points to in A and mark A as an opaque
- value. WARNING: Never use an opaque MPI for anything thing else then
- gcry_mpi_release, gcry_mpi_get_opaque. */
-gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits);
-
-/* Return a pointer to an opaque value stored in A and return its size
- in NBITS. Note that the returned pointer is still owned by A and
- that the function should never be used for an non-opaque MPI. */
-void *gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits);
-
-/* Set the FLAG for the big integer A. Currently only the flag
- GCRYMPI_FLAG_SECURE is allowed to convert A into an big intger
- stored in "secure" memory. */
-void gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
-
-/* Clear FLAG for the big integer A. Note that this function is
- currently useless as no flags are allowed. */
-void gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
-
-/* Return true when the FLAG is set for A. */
-int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
-
-/* Unless the GCRYPT_NO_MPI_MACROS is used, provide a couple of
- convenience macros for the big integer functions. */
-#ifndef GCRYPT_NO_MPI_MACROS
-#define mpi_new(n) gcry_mpi_new( (n) )
-#define mpi_secure_new( n ) gcry_mpi_snew( (n) )
-#define mpi_release(a) \
- do \
- { \
- gcry_mpi_release ((a)); \
- (a) = NULL; \
- } \
- while (0)
-
-#define mpi_copy( a ) gcry_mpi_copy( (a) )
-#define mpi_set( w, u) gcry_mpi_set( (w), (u) )
-#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) )
-#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) )
-#define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) )
-
-#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
-#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v))
-#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m))
-#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v))
-#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v))
-#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m))
-#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v))
-#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v))
-#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v))
-#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m))
-#define mpi_powm(w,b,e,m) gcry_mpi_powm ( (w), (b), (e), (m) )
-#define mpi_tdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), 0)
-#define mpi_fdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), -1)
-#define mpi_mod(r,a,m) gcry_mpi_mod ((r), (a), (m))
-#define mpi_gcd(g,a,b) gcry_mpi_gcd ( (g), (a), (b) )
-#define mpi_invm(g,a,b) gcry_mpi_invm ( (g), (a), (b) )
-
-#define mpi_get_nbits(a) gcry_mpi_get_nbits ((a))
-#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b))
-#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b))
-#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b))
-#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b))
-#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b))
-#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c))
-#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c))
-
-#define mpi_set_opaque(a,b,c) gcry_mpi_set_opaque( (a), (b), (c) )
-#define mpi_get_opaque(a,b) gcry_mpi_get_opaque( (a), (b) )
-#endif /* GCRYPT_NO_MPI_MACROS */
-
-
-
-/************************************
- * *
- * Symmetric Cipher Functions *
- * *
- ************************************/
-
-/* The data object used to hold a handle to an encryption object. */
-struct gcry_cipher_handle;
-typedef struct gcry_cipher_handle *gcry_cipher_hd_t;
-
-#ifndef GCRYPT_NO_DEPRECATED
-typedef struct gcry_cipher_handle *GCRY_CIPHER_HD _GCRY_GCC_ATTR_DEPRECATED;
-typedef struct gcry_cipher_handle *GcryCipherHd _GCRY_GCC_ATTR_DEPRECATED;
-#endif
-
-/* All symmetric encryption algorithms are identified by their IDs.
- More IDs may be registered at runtime. */
-enum gcry_cipher_algos
- {
- GCRY_CIPHER_NONE = 0,
- GCRY_CIPHER_IDEA = 1,
- GCRY_CIPHER_3DES = 2,
- GCRY_CIPHER_CAST5 = 3,
- GCRY_CIPHER_BLOWFISH = 4,
- GCRY_CIPHER_SAFER_SK128 = 5,
- GCRY_CIPHER_DES_SK = 6,
- GCRY_CIPHER_AES = 7,
- GCRY_CIPHER_AES192 = 8,
- GCRY_CIPHER_AES256 = 9,
- GCRY_CIPHER_TWOFISH = 10,
-
- /* Other cipher numbers are above 300 for OpenPGP reasons. */
- GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */
- GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */
- GCRY_CIPHER_TWOFISH128 = 303,
- GCRY_CIPHER_SERPENT128 = 304,
- GCRY_CIPHER_SERPENT192 = 305,
- GCRY_CIPHER_SERPENT256 = 306,
- GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */
- GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */
- GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */
- GCRY_CIPHER_CAMELLIA128 = 310,
- GCRY_CIPHER_CAMELLIA192 = 311,
- GCRY_CIPHER_CAMELLIA256 = 312
- };
-
-/* The Rijndael algorithm is basically AES, so provide some macros. */
-#define GCRY_CIPHER_AES128 GCRY_CIPHER_AES
-#define GCRY_CIPHER_RIJNDAEL GCRY_CIPHER_AES
-#define GCRY_CIPHER_RIJNDAEL128 GCRY_CIPHER_AES128
-#define GCRY_CIPHER_RIJNDAEL192 GCRY_CIPHER_AES192
-#define GCRY_CIPHER_RIJNDAEL256 GCRY_CIPHER_AES256
-
-/* The supported encryption modes. Note that not all of them are
- supported for each algorithm. */
-enum gcry_cipher_modes
- {
- GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
- GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
- GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
- GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
- GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
- GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
- GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
- GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */
- };
-
-/* Flags used with the open function. */
-enum gcry_cipher_flags
- {
- GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */
- GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
- GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
- GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
- };
-
-
-/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may
- be given as an bitwise OR of the gcry_cipher_flags values. */
-gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
- int algo, int mode, unsigned int flags);
-
-/* Close the cioher handle H and release all resource. */
-void gcry_cipher_close (gcry_cipher_hd_t h);
-
-/* Perform various operations on the cipher object H. */
-gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
- size_t buflen);
-
-/* Retrieve various information about the cipher object H. */
-gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer,
- size_t *nbytes);
-
-/* Retrieve various information about the cipher algorithm ALGO. */
-gcry_error_t gcry_cipher_algo_info (int algo, int what, void *buffer,
- size_t *nbytes);
-
-/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
- string representation of the algorithm name. For unknown algorithm
- IDs this function returns "?". */
-const char *gcry_cipher_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
-
-/* Map the algorithm name NAME to an cipher algorithm ID. Return 0 if
- the algorithm name is not known. */
-int gcry_cipher_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
-
-/* Given an ASN.1 object identifier in standard IETF dotted decimal
- format in STRING, return the encryption mode associated with that
- OID or 0 if not known or applicable. */
-int gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE;
-
-/* Encrypt the plaintext of size INLEN in IN using the cipher handle H
- into the buffer OUT which has an allocated length of OUTSIZE. For
- most algorithms it is possible to pass NULL for in and 0 for INLEN
- and do a in-place decryption of the data provided in OUT. */
-gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h,
- void *out, size_t outsize,
- const void *in, size_t inlen);
-
-/* The counterpart to gcry_cipher_encrypt. */
-gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h,
- void *out, size_t outsize,
- const void *in, size_t inlen);
-
-/* Set KEY of length KEYLEN bytes for the cipher handle HD. */
-gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd,
- const void *key, size_t keylen);
-
-
-/* Set initialization vector IV of length IVLEN for the cipher handle HD. */
-gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd,
- const void *iv, size_t ivlen);
-
-
-/* Reset the handle to the state after open. */
-#define gcry_cipher_reset(h) gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0)
-
-/* Perform the OpenPGP sync operation if this is enabled for the
- cipher handle H. */
-#define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, NULL, 0)
-
-/* Enable or disable CTS in future calls to gcry_encrypt(). CBC mode only. */
-#define gcry_cipher_cts(h,on) gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \
- NULL, on )
-
-/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
- block size length, or (NULL,0) to set the CTR to the all-zero block. */
-gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd,
- const void *ctr, size_t ctrlen);
-
-/* Retrieved the key length in bytes used with algorithm A. */
-size_t gcry_cipher_get_algo_keylen (int algo);
-
-/* Retrieve the block length in bytes used with algorithm A. */
-size_t gcry_cipher_get_algo_blklen (int algo);
-
-/* Return 0 if the algorithm A is available for use. */
-#define gcry_cipher_test_algo(a) \
- gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
-
-/* Get a list consisting of the IDs of the loaded cipher modules. If
- LIST is zero, write the number of loaded cipher modules to
- LIST_LENGTH and return. If LIST is non-zero, the first
- *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
- according size. In case there are less cipher modules than
- *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
-gcry_error_t gcry_cipher_list (int *list, int *list_length);
-
-
-/************************************
- * *
- * Asymmetric Cipher Functions *
- * *
- ************************************/
-
-/* The algorithms and their IDs we support. */
-enum gcry_pk_algos
- {
- GCRY_PK_RSA = 1,
- GCRY_PK_RSA_E = 2, /* (deprecated) */
- GCRY_PK_RSA_S = 3, /* (deprecated) */
- GCRY_PK_ELG_E = 16,
- GCRY_PK_DSA = 17,
- GCRY_PK_ELG = 20,
- GCRY_PK_ECDSA = 301
- };
-
-/* Flags describing usage capabilities of a PK algorithm. */
-#define GCRY_PK_USAGE_SIGN 1 /* Good for signatures. */
-#define GCRY_PK_USAGE_ENCR 2 /* Good for encryption. */
-#define GCRY_PK_USAGE_CERT 4 /* Good to certify other keys. */
-#define GCRY_PK_USAGE_AUTH 8 /* Good for authentication. */
-#define GCRY_PK_USAGE_UNKN 128 /* Unknown usage flag. */
-
-/* Encrypt the DATA using the public key PKEY and store the result as
- a newly created S-expression at RESULT. */
-gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t pkey);
-
-/* Decrypt the DATA using the private key SKEY and store the result as
- a newly created S-expression at RESULT. */
-gcry_error_t gcry_pk_decrypt (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t skey);
-
-/* Sign the DATA using the private key SKEY and store the result as
- a newly created S-expression at RESULT. */
-gcry_error_t gcry_pk_sign (gcry_sexp_t *result,
- gcry_sexp_t data, gcry_sexp_t skey);
-
-/* Check the signature SIGVAL on DATA using the public key PKEY. */
-gcry_error_t gcry_pk_verify (gcry_sexp_t sigval,
- gcry_sexp_t data, gcry_sexp_t pkey);
-
-/* Check that private KEY is sane. */
-gcry_error_t gcry_pk_testkey (gcry_sexp_t key);
-
-/* Generate a new key pair according to the parameters given in
- S_PARMS. The new key pair is returned in as an S-expression in
- R_KEY. */
-gcry_error_t gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms);
-
-/* Catch all function for miscellaneous operations. */
-gcry_error_t gcry_pk_ctl (int cmd, void *buffer, size_t buflen);
-
-/* Retrieve information about the public key algorithm ALGO. */
-gcry_error_t gcry_pk_algo_info (int algo, int what,
- void *buffer, size_t *nbytes);
-
-/* Map the public key algorithm whose ID is contained in ALGORITHM to
- a string representation of the algorithm name. For unknown
- algorithm IDs this functions returns "?". */
-const char *gcry_pk_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
-
-/* Map the algorithm NAME to a public key algorithm Id. Return 0 if
- the algorithm name is not known. */
-int gcry_pk_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
-
-/* Return what is commonly referred as the key length for the given
- public or private KEY. */
-unsigned int gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE;
-
-/* Please note that keygrip is still experimental and should not be
- used without contacting the author. */
-unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
-
-/* Return 0 if the public key algorithm A is available for use. */
-#define gcry_pk_test_algo(a) \
- gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
-
-/* Get a list consisting of the IDs of the loaded pubkey modules. If
- LIST is zero, write the number of loaded pubkey modules to
- LIST_LENGTH and return. If LIST is non-zero, the first
- *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
- according size. In case there are less pubkey modules than
- *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
-gcry_error_t gcry_pk_list (int *list, int *list_length);
-
-
-
-/************************************
- * *
- * Cryptograhic Hash Functions *
- * *
- ************************************/
-
-/* Algorithm IDs for the hash functions we know about. Not all of them
- are implemnted. */
-enum gcry_md_algos
- {
- GCRY_MD_NONE = 0,
- GCRY_MD_MD5 = 1,
- GCRY_MD_SHA1 = 2,
- GCRY_MD_RMD160 = 3,
- GCRY_MD_MD2 = 5,
- GCRY_MD_TIGER = 6, /* TIGER/192 as used by GnuPG <= 1.3.2. */
- GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
- GCRY_MD_SHA256 = 8,
- GCRY_MD_SHA384 = 9,
- GCRY_MD_SHA512 = 10,
- GCRY_MD_SHA224 = 11,
- GCRY_MD_MD4 = 301,
- GCRY_MD_CRC32 = 302,
- GCRY_MD_CRC32_RFC1510 = 303,
- GCRY_MD_CRC24_RFC2440 = 304,
- GCRY_MD_WHIRLPOOL = 305,
- GCRY_MD_TIGER1 = 306, /* TIGER (fixed). */
- GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */
- };
-
-/* Flags used with the open function. */
-enum gcry_md_flags
- {
- GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
- GCRY_MD_FLAG_HMAC = 2 /* Make an HMAC out of this algorithm. */
- };
-
-/* (Forward declaration.) */
-struct gcry_md_context;
-
-/* This object is used to hold a handle to a message digest object.
- This structure is private - only to be used by the public gcry_md_*
- macros. */
-typedef struct gcry_md_handle
-{
- /* Actual context. */
- struct gcry_md_context *ctx;
-
- /* Buffer management. */
- int bufpos;
- int bufsize;
- unsigned char buf[1];
-} *gcry_md_hd_t;
-
-/* Compatibility types, do not use them. */
-#ifndef GCRYPT_NO_DEPRECATED
-typedef struct gcry_md_handle *GCRY_MD_HD _GCRY_GCC_ATTR_DEPRECATED;
-typedef struct gcry_md_handle *GcryMDHd _GCRY_GCC_ATTR_DEPRECATED;
-#endif
-
-/* Create a message digest object for algorithm ALGO. FLAGS may be
- given as an bitwise OR of the gcry_md_flags values. ALGO may be
- given as 0 if the algorithms to be used are later set using
- gcry_md_enable. */
-gcry_error_t gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags);
-
-/* Release the message digest object HD. */
-void gcry_md_close (gcry_md_hd_t hd);
-
-/* Add the message digest algorithm ALGO to the digest object HD. */
-gcry_error_t gcry_md_enable (gcry_md_hd_t hd, int algo);
-
-/* Create a new digest object as an exact copy of the object HD. */
-gcry_error_t gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd);
-
-/* Reset the digest object HD to its initial state. */
-void gcry_md_reset (gcry_md_hd_t hd);
-
-/* Perform various operations on the digest object HD. */
-gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd,
- void *buffer, size_t buflen);
-
-/* Pass LENGTH bytes of data in BUFFER to the digest object HD so that
- it can update the digest values. This is the actual hash
- function. */
-void gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
-
-/* Read out the final digest from HD return the digest value for
- algorithm ALGO. */
-unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo);
-
-/* Convenience function to calculate the hash from the data in BUFFER
- of size LENGTH using the algorithm ALGO avoiding the creating of a
- hash object. The hash is returned in the caller provided buffer
- DIGEST which must be large enough to hold the digest of the given
- algorithm. */
-void gcry_md_hash_buffer (int algo, void *digest,
- const void *buffer, size_t length);
-
-/* Retrieve the algorithm used with HD. This does not work reliable
- if more than one algorithm is enabled in HD. */
-int gcry_md_get_algo (gcry_md_hd_t hd);
-
-/* Retrieve the length in bytes of the digest yielded by algorithm
- ALGO. */
-unsigned int gcry_md_get_algo_dlen (int algo);
-
-/* Return true if the the algorithm ALGO is enabled in the digest
- object A. */
-int gcry_md_is_enabled (gcry_md_hd_t a, int algo);
-
-/* Return true if the digest object A is allocated in "secure" memory. */
-int gcry_md_is_secure (gcry_md_hd_t a);
-
-/* Retrieve various information about the object H. */
-gcry_error_t gcry_md_info (gcry_md_hd_t h, int what, void *buffer,
- size_t *nbytes);
-
-/* Retrieve various information about the algorithm ALGO. */
-gcry_error_t gcry_md_algo_info (int algo, int what, void *buffer,
- size_t *nbytes);
-
-/* Map the digest algorithm id ALGO to a string representation of the
- algorithm name. For unknown algorithms this function returns
- "?". */
-const char *gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
-
-/* Map the algorithm NAME to a digest algorithm Id. Return 0 if
- the algorithm name is not known. */
-int gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
-
-/* For use with the HMAC feature, the set MAC key to the KEY of
- KEYLEN bytes. */
-gcry_error_t gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen);
-
-/* Start or stop debugging for digest handle HD; i.e. create a file
- named dbgmd-<n>.<suffix> while hashing. If SUFFIX is NULL,
- debugging stops and the file will be closed. */
-void gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
-
-
-/* Update the hash(s) of H with the character C. This is a buffered
- version of the gcry_md_write function. */
-#define gcry_md_putc(h,c) \
- do { \
- gcry_md_hd_t h__ = (h); \
- if( (h__)->bufpos == (h__)->bufsize ) \
- gcry_md_write( (h__), NULL, 0 ); \
- (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
- } while(0)
-
-/* Finalize the digest calculation. This is not really needed because
- gcry_md_read() does this implicitly. */
-#define gcry_md_final(a) \
- gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
-
-/* Return 0 if the algorithm A is available for use. */
-#define gcry_md_test_algo(a) \
- gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
-
-/* Return an DER encoded ASN.1 OID for the algorithm A in buffer B. N
- must point to size_t variable with the available size of buffer B.
- After return it will receive the actual size of the returned
- OID. */
-#define gcry_md_get_asnoid(a,b,n) \
- gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n))
-
-/* Enable debugging for digest object A; i.e. create files named
- dbgmd-<n>.<string> while hashing. B is a string used as the suffix
- for the filename. This macro is deprecated, use gcry_md_debug. */
-#ifndef GCRYPT_NO_DEPRECATED
-#define gcry_md_start_debug(a,b) \
- gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 )
-
-/* Disable the debugging of A. This macro is deprecated, use
- gcry_md_debug. */
-#define gcry_md_stop_debug(a,b) \
- gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 )
-#endif
-
-/* Get a list consisting of the IDs of the loaded message digest
- modules. If LIST is zero, write the number of loaded message
- digest modules to LIST_LENGTH and return. If LIST is non-zero, the
- first *LIST_LENGTH algorithm IDs are stored in LIST, which must be
- of according size. In case there are less message digest modules
- than *LIST_LENGTH, *LIST_LENGTH is updated to the correct
- number. */
-gcry_error_t gcry_md_list (int *list, int *list_length);
-
-
-
-/* Alternative interface for asymmetric cryptography. This interface
- is deprecated. */
-
-/* The algorithm IDs. */
-typedef enum gcry_ac_id
- {
- GCRY_AC_RSA = 1,
- GCRY_AC_DSA = 17,
- GCRY_AC_ELG = 20,
- GCRY_AC_ELG_E = 16
- }
-gcry_ac_id_t;
-
-/* Key types. */
-typedef enum gcry_ac_key_type
- {
- GCRY_AC_KEY_SECRET,
- GCRY_AC_KEY_PUBLIC
- }
-gcry_ac_key_type_t;
-
-/* Encoding methods. */
-typedef enum gcry_ac_em
- {
- GCRY_AC_EME_PKCS_V1_5,
- GCRY_AC_EMSA_PKCS_V1_5
- }
-gcry_ac_em_t;
-
-/* Encryption and Signature schemes. */
-typedef enum gcry_ac_scheme
- {
- GCRY_AC_ES_PKCS_V1_5,
- GCRY_AC_SSA_PKCS_V1_5
- }
-gcry_ac_scheme_t;
-
-/* AC data. */
-#define GCRY_AC_FLAG_DEALLOC (1 << 0)
-#define GCRY_AC_FLAG_COPY (1 << 1)
-#define GCRY_AC_FLAG_NO_BLINDING (1 << 2)
-
-/* This type represents a `data set'. */
-typedef struct gcry_ac_data *gcry_ac_data_t;
-
-/* This type represents a single `key', either a secret one or a
- public one. */
-typedef struct gcry_ac_key *gcry_ac_key_t;
-
-/* This type represents a `key pair' containing a secret and a public
- key. */
-typedef struct gcry_ac_key_pair *gcry_ac_key_pair_t;
-
-/* This type represents a `handle' that is needed by functions
- performing cryptographic operations. */
-typedef struct gcry_ac_handle *gcry_ac_handle_t;
-
-typedef gpg_error_t (*gcry_ac_data_read_cb_t) (void *opaque,
- unsigned char *buffer,
- size_t *buffer_n);
-
-typedef gpg_error_t (*gcry_ac_data_write_cb_t) (void *opaque,
- unsigned char *buffer,
- size_t buffer_n);
-
-typedef enum
- {
- GCRY_AC_IO_READABLE,
- GCRY_AC_IO_WRITABLE
- }
-gcry_ac_io_mode_t;
-
-typedef enum
- {
- GCRY_AC_IO_STRING,
- GCRY_AC_IO_CALLBACK
- }
-gcry_ac_io_type_t;
-
-typedef struct gcry_ac_io
-{
- /* This is an INTERNAL structure, do NOT use manually. */
- gcry_ac_io_mode_t mode _GCRY_ATTR_INTERNAL;
- gcry_ac_io_type_t type _GCRY_ATTR_INTERNAL;
- union
- {
- union
- {
- struct
- {
- gcry_ac_data_read_cb_t cb;
- void *opaque;
- } callback;
- struct
- {
- unsigned char *data;
- size_t data_n;
- } string;
- void *opaque;
- } readable;
- union
- {
- struct
- {
- gcry_ac_data_write_cb_t cb;
- void *opaque;
- } callback;
- struct
- {
- unsigned char **data;
- size_t *data_n;
- } string;
- void *opaque;
- } writable;
- } io _GCRY_ATTR_INTERNAL;
-}
-gcry_ac_io_t;
-
-/* The caller of gcry_ac_key_pair_generate can provide one of these
- structures in order to influence the key generation process in an
- algorithm-specific way. */
-typedef struct gcry_ac_key_spec_rsa
-{
- gcry_mpi_t e; /* E to use. */
-} gcry_ac_key_spec_rsa_t;
-
-/* Structure used for passing data to the implementation of the
- `EME-PKCS-V1_5' encoding method. */
-typedef struct gcry_ac_eme_pkcs_v1_5
-{
- size_t key_size;
-} gcry_ac_eme_pkcs_v1_5_t;
-
-typedef enum gcry_md_algos gcry_md_algo_t;
-
-/* Structure used for passing data to the implementation of the
- `EMSA-PKCS-V1_5' encoding method. */
-typedef struct gcry_ac_emsa_pkcs_v1_5
-{
- gcry_md_algo_t md;
- size_t em_n;
-} gcry_ac_emsa_pkcs_v1_5_t;
-
-/* Structure used for passing data to the implementation of the
- `SSA-PKCS-V1_5' signature scheme. */
-typedef struct gcry_ac_ssa_pkcs_v1_5
-{
- gcry_md_algo_t md;
-} gcry_ac_ssa_pkcs_v1_5_t;
-
-/* Returns a new, empty data set in DATA. */
-gcry_error_t gcry_ac_data_new (gcry_ac_data_t *data);
-
-/* Destroy the data set DATA. */
-void gcry_ac_data_destroy (gcry_ac_data_t data);
-
-/* Create a copy of the data set DATA and store it in DATA_CP. */
-gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *data_cp,
- gcry_ac_data_t data);
-
-/* Return the number of named MPI values inside of the data set
- DATA. */
-unsigned int gcry_ac_data_length (gcry_ac_data_t data);
-
-/* Destroy any values contained in the data set DATA. */
-void gcry_ac_data_clear (gcry_ac_data_t data);
-
-/* Add the value MPI to DATA with the label NAME. If FLAGS contains
- GCRY_AC_FLAG_DATA_COPY, the data set will contain copies of NAME
- and MPI. If FLAGS contains GCRY_AC_FLAG_DATA_DEALLOC or
- GCRY_AC_FLAG_DATA_COPY, the values contained in the data set will
- be deallocated when they are to be removed from the data set. */
-gcry_error_t gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags,
- const char *name, gcry_mpi_t mpi);
-
-/* Store the value labelled with NAME found in DATA in MPI. If FLAGS
- contains GCRY_AC_FLAG_COPY, store a copy of the MPI value contained
- in the data set. MPI may be NULL. */
-gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags,
- const char *name, gcry_mpi_t *mpi);
-
-/* Stores in NAME and MPI the named MPI value contained in the data
- set DATA with the index IDX. If FLAGS contains GCRY_AC_FLAG_COPY,
- store copies of the values contained in the data set. NAME or MPI
- may be NULL. */
-gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags,
- unsigned int idx,
- const char **name, gcry_mpi_t *mpi);
-
-/* Convert the data set DATA into a new S-Expression, which is to be
- stored in SEXP, according to the identifiers contained in
- IDENTIFIERS. */
-gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
- const char **identifiers);
-
-/* Create a new data set, which is to be stored in DATA_SET, from the
- S-Expression SEXP, according to the identifiers contained in
- IDENTIFIERS. */
-gcry_error_t gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp,
- const char **identifiers);
-
-/* Initialize AC_IO according to MODE, TYPE and the variable list of
- arguments. The list of variable arguments to specify depends on
- the given TYPE. */
-void gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
- gcry_ac_io_type_t type, ...);
-
-/* Initialize AC_IO according to MODE, TYPE and the variable list of
- arguments AP. The list of variable arguments to specify depends on
- the given TYPE. */
-void gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
- gcry_ac_io_type_t type, va_list ap);
-
-/* Create a new ac handle. */
-gcry_error_t gcry_ac_open (gcry_ac_handle_t *handle,
- gcry_ac_id_t algorithm, unsigned int flags);
-
-/* Destroy an ac handle. */
-void gcry_ac_close (gcry_ac_handle_t handle);
-
-/* Initialize a key from a given data set. */
-gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
- gcry_ac_key_type_t type, gcry_ac_data_t data);
-
-/* Generates a new key pair via the handle HANDLE of NBITS bits and
- stores it in KEY_PAIR. In case non-standard settings are wanted, a
- pointer to a structure of type gcry_ac_key_spec_<algorithm>_t,
- matching the selected algorithm, can be given as KEY_SPEC.
- MISC_DATA is not used yet. */
-gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
- unsigned int nbits, void *spec,
- gcry_ac_key_pair_t *key_pair,
- gcry_mpi_t **misc_data);
-
-/* Returns the key of type WHICH out of the key pair KEY_PAIR. */
-gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
- gcry_ac_key_type_t which);
-
-/* Returns the data set contained in the key KEY. */
-gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t key);
-
-/* Verifies that the key KEY is sane via HANDLE. */
-gcry_error_t gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key);
-
-/* Stores the number of bits of the key KEY in NBITS via HANDLE. */
-gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t handle,
- gcry_ac_key_t key, unsigned int *nbits);
-
-/* Writes the 20 byte long key grip of the key KEY to KEY_GRIP via
- HANDLE. */
-gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key,
- unsigned char *key_grip);
-
-/* Destroy a key. */
-void gcry_ac_key_destroy (gcry_ac_key_t key);
-
-/* Destroy a key pair. */
-void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair);
-
-/* Encodes a message according to the encoding method METHOD. OPTIONS
- must be a pointer to a method-specific structure
- (gcry_ac_em*_t). */
-gcry_error_t gcry_ac_data_encode (gcry_ac_em_t method,
- unsigned int flags, void *options,
- gcry_ac_io_t *io_read,
- gcry_ac_io_t *io_write);
-
-/* Decodes a message according to the encoding method METHOD. OPTIONS
- must be a pointer to a method-specific structure
- (gcry_ac_em*_t). */
-gcry_error_t gcry_ac_data_decode (gcry_ac_em_t method,
- unsigned int flags, void *options,
- gcry_ac_io_t *io_read,
- gcry_ac_io_t *io_write);
-
-/* Encrypt the plain text MPI value DATA_PLAIN with the key KEY under
- the control of the flags FLAGS and store the resulting data set
- into DATA_ENCRYPTED. */
-gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t handle,
- unsigned int flags,
- gcry_ac_key_t key,
- gcry_mpi_t data_plain,
- gcry_ac_data_t *data_encrypted);
-
-/* Decrypt the decrypted data contained in the data set DATA_ENCRYPTED
- with the key KEY under the control of the flags FLAGS and store the
- resulting plain text MPI value in DATA_PLAIN. */
-gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t handle,
- unsigned int flags,
- gcry_ac_key_t key,
- gcry_mpi_t *data_plain,
- gcry_ac_data_t data_encrypted);
-
-/* Sign the data contained in DATA with the key KEY and store the
- resulting signature in the data set DATA_SIGNATURE. */
-gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t handle,
- gcry_ac_key_t key,
- gcry_mpi_t data,
- gcry_ac_data_t *data_signature);
-
-/* Verify that the signature contained in the data set DATA_SIGNATURE
- is indeed the result of signing the data contained in DATA with the
- secret key belonging to the public key KEY. */
-gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t handle,
- gcry_ac_key_t key,
- gcry_mpi_t data,
- gcry_ac_data_t data_signature);
-
-/* Encrypts the plain text readable from IO_MESSAGE through HANDLE
- with the public key KEY according to SCHEME, FLAGS and OPTS. If
- OPTS is not NULL, it has to be a pointer to a structure specific to
- the chosen scheme (gcry_ac_es_*_t). The encrypted message is
- written to IO_CIPHER. */
-gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle,
- gcry_ac_scheme_t scheme,
- unsigned int flags, void *opts,
- gcry_ac_key_t key,
- gcry_ac_io_t *io_message,
- gcry_ac_io_t *io_cipher);
-
-/* Decrypts the cipher text readable from IO_CIPHER through HANDLE
- with the secret key KEY according to SCHEME, @var{flags} and OPTS.
- If OPTS is not NULL, it has to be a pointer to a structure specific
- to the chosen scheme (gcry_ac_es_*_t). The decrypted message is
- written to IO_MESSAGE. */
-gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle,
- gcry_ac_scheme_t scheme,
- unsigned int flags, void *opts,
- gcry_ac_key_t key,
- gcry_ac_io_t *io_cipher,
- gcry_ac_io_t *io_message);
-
-/* Signs the message readable from IO_MESSAGE through HANDLE with the
- secret key KEY according to SCHEME, FLAGS and OPTS. If OPTS is not
- NULL, it has to be a pointer to a structure specific to the chosen
- scheme (gcry_ac_ssa_*_t). The signature is written to
- IO_SIGNATURE. */
-gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t handle,
- gcry_ac_scheme_t scheme,
- unsigned int flags, void *opts,
- gcry_ac_key_t key,
- gcry_ac_io_t *io_message,
- gcry_ac_io_t *io_signature);
-
-/* Verifies through HANDLE that the signature readable from
- IO_SIGNATURE is indeed the result of signing the message readable
- from IO_MESSAGE with the secret key belonging to the public key KEY
- according to SCHEME and OPTS. If OPTS is not NULL, it has to be an
- anonymous structure (gcry_ac_ssa_*_t) specific to the chosen
- scheme. */
-gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t handle,
- gcry_ac_scheme_t scheme,
- unsigned int flags, void *opts,
- gcry_ac_key_t key,
- gcry_ac_io_t *io_message,
- gcry_ac_io_t *io_signature);
-
-/* Store the textual representation of the algorithm whose id is given
- in ALGORITHM in NAME. This function is deprecated; use
- gcry_pk_algo_name. */
-#ifndef GCRYPT_NO_DEPRECATED
-gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t algorithm,
- const char **name)
- /* */ _GCRY_GCC_ATTR_DEPRECATED;
-/* Store the numeric ID of the algorithm whose textual representation
- is contained in NAME in ALGORITHM. This function is deprecated;
- use gcry_pk_map_name. */
-gcry_error_t gcry_ac_name_to_id (const char *name,
- gcry_ac_id_t *algorithm)
- /* */ _GCRY_GCC_ATTR_DEPRECATED;
-#endif
-
-
-/************************************
- * *
- * Random Generating Functions *
- * *
- ************************************/
-
-/* The possible values for the random quality. The rule of thumb is
- to use STRONG for session keys and VERY_STRONG for key material.
- WEAK is usually an alias for STRONG and should not be used anymore
- (except with gcry_mpi_randomize); use gcry_create_nonce instead. */
-typedef enum gcry_random_level
- {
- GCRY_WEAK_RANDOM = 0,
- GCRY_STRONG_RANDOM = 1,
- GCRY_VERY_STRONG_RANDOM = 2
- }
-gcry_random_level_t;
-
-/* Fill BUFFER with LENGTH bytes of random, using random numbers of
- quality LEVEL. */
-void gcry_randomize (void *buffer, size_t length,
- enum gcry_random_level level);
-
-/* Add the external random from BUFFER with LENGTH bytes into the
- pool. QUALITY should either be -1 for unknown or in the range of 0
- to 100 */
-gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length,
- int quality);
-
-/* If random numbers are used in an application, this macro should be
- called from time to time so that new stuff gets added to the
- internal pool of the RNG. */
-#define gcry_fast_random_poll() gcry_control (GCRYCTL_FAST_POLL, NULL)
-
-
-/* Return NBYTES of allocated random using a random numbers of quality
- LEVEL. */
-void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
- _GCRY_GCC_ATTR_MALLOC;
-
-/* Return NBYTES of allocated random using a random numbers of quality
- LEVEL. The random numbers are created returned in "secure"
- memory. */
-void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
- _GCRY_GCC_ATTR_MALLOC;
-
-
-/* Set the big integer W to a random value of NBITS using a random
- generator with quality LEVEL. Note that by using a level of
- GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */
-void gcry_mpi_randomize (gcry_mpi_t w,
- unsigned int nbits, enum gcry_random_level level);
-
-
-/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
-void gcry_create_nonce (void *buffer, size_t length);
-
-
-
-
-
-/*******************************/
-/* */
-/* Prime Number Functions */
-/* */
-/*******************************/
-
-/* Mode values passed to a gcry_prime_check_func_t. */
-#define GCRY_PRIME_CHECK_AT_FINISH 0
-#define GCRY_PRIME_CHECK_AT_GOT_PRIME 1
-#define GCRY_PRIME_CHECK_AT_MAYBE_PRIME 2
-
-/* The function should return 1 if the operation shall continue, 0 to
- reject the prime candidate. */
-typedef int (*gcry_prime_check_func_t) (void *arg, int mode,
- gcry_mpi_t candidate);
-
-/* Flags for gcry_prime_generate(): */
-
-/* Allocate prime numbers and factors in secure memory. */
-#define GCRY_PRIME_FLAG_SECRET (1 << 0)
-
-/* Make sure that at least one prime factor is of size
- `FACTOR_BITS'. */
-#define GCRY_PRIME_FLAG_SPECIAL_FACTOR (1 << 1)
-
-/* Generate a new prime number of PRIME_BITS bits and store it in
- PRIME. If FACTOR_BITS is non-zero, one of the prime factors of
- (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is
- non-zero, allocate a new, NULL-terminated array holding the prime
- factors and store it in FACTORS. FLAGS might be used to influence
- the prime number generation process. */
-gcry_error_t gcry_prime_generate (gcry_mpi_t *prime,
- unsigned int prime_bits,
- unsigned int factor_bits,
- gcry_mpi_t **factors,
- gcry_prime_check_func_t cb_func,
- void *cb_arg,
- gcry_random_level_t random_level,
- unsigned int flags);
-
-/* Find a generator for PRIME where the factorization of (prime-1) is
- in the NULL terminated array FACTORS. Return the generator as a
- newly allocated MPI in R_G. If START_G is not NULL, use this as
- teh start for the search. */
-gcry_error_t gcry_prime_group_generator (gcry_mpi_t *r_g,
- gcry_mpi_t prime,
- gcry_mpi_t *factors,
- gcry_mpi_t start_g);
-
-
-/* Convenience function to release the FACTORS array. */
-void gcry_prime_release_factors (gcry_mpi_t *factors);
-
-
-/* Check wether the number X is prime. */
-gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
-
-
-
-/************************************
- * *
- * Miscellaneous Stuff *
- * *
- ************************************/
-
-/* Log levels used by the internal logging facility. */
-enum gcry_log_levels
- {
- GCRY_LOG_CONT = 0, /* (Continue the last log line.) */
- GCRY_LOG_INFO = 10,
- GCRY_LOG_WARN = 20,
- GCRY_LOG_ERROR = 30,
- GCRY_LOG_FATAL = 40,
- GCRY_LOG_BUG = 50,
- GCRY_LOG_DEBUG = 100
- };
-
-/* Type for progress handlers. */
-typedef void (*gcry_handler_progress_t) (void *, const char *, int, int, int);
-
-/* Type for memory allocation handlers. */
-typedef void *(*gcry_handler_alloc_t) (size_t n);
-
-/* Type for secure memory check handlers. */
-typedef int (*gcry_handler_secure_check_t) (const void *);
-
-/* Type for memory reallocation handlers. */
-typedef void *(*gcry_handler_realloc_t) (void *p, size_t n);
-
-/* Type for memory free handlers. */
-typedef void (*gcry_handler_free_t) (void *);
-
-/* Type for out-of-memory handlers. */
-typedef int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int);
-
-/* Type for fatal error handlers. */
-typedef void (*gcry_handler_error_t) (void *, int, const char *);
-
-/* Type for logging handlers. */
-typedef void (*gcry_handler_log_t) (void *, int, const char *, va_list);
-
-/* Certain operations can provide progress information. This function
- is used to register a handler for retrieving these information. */
-void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
-
-
-/* Register a custom memory allocation functions. */
-void gcry_set_allocation_handler (
- gcry_handler_alloc_t func_alloc,
- gcry_handler_alloc_t func_alloc_secure,
- gcry_handler_secure_check_t func_secure_check,
- gcry_handler_realloc_t func_realloc,
- gcry_handler_free_t func_free);
-
-/* Register a function used instead of the internal out of memory
- handler. */
-void gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque);
-
-/* Register a function used instead of the internal fatal error
- handler. */
-void gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque);
-
-/* Register a function used instead of the internal logging
- facility. */
-void gcry_set_log_handler (gcry_handler_log_t f, void *opaque);
-
-/* Reserved for future use. */
-void gcry_set_gettext_handler (const char *(*f)(const char*));
-
-/* Libgcrypt uses its own memory allocation. It is important to use
- gcry_free () to release memory allocated by libgcrypt. */
-void *gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_calloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_realloc (void *a, size_t n);
-char *gcry_strdup (const char *string) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_xmalloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_xcalloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_xmalloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_xcalloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
-void *gcry_xrealloc (void *a, size_t n);
-char *gcry_xstrdup (const char * a) _GCRY_GCC_ATTR_MALLOC;
-void gcry_free (void *a);
-
-/* Return true if A is allocated in "secure" memory. */
-int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
-
-/* Return true if Libgcrypt is in FIPS mode. */
-#define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0)
-
-
-/* Include support for Libgcrypt modules. */
-#include <gcrypt-module.h>
-
-#if 0 /* (Keep Emacsens' auto-indent happy.) */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif /* _GCRYPT_H */
+/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*-
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ This file is part of Libgcrypt.
+
+ Libgcrypt is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ Libgcrypt 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ File: @configure_input@ */
+
+#ifndef _GCRYPT_H
+#define _GCRYPT_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <gpg-error.h>
+
+#include <sys/types.h>
+
+#if defined _WIN32 || defined __WIN32__
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <time.h>
+# ifndef __GNUC__
+ typedef long ssize_t;
+ typedef int pid_t;
+# endif /*!__GNUC__*/
+#else
+# include <sys/socket.h>
+# include <sys/time.h>
+#@INSERT_SYS_SELECT_H@
+#endif /*!_WIN32*/
+
+@FALLBACK_SOCKLEN_T@
+
+/* This is required for error code compatibility. */
+#define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
+
+#ifdef __cplusplus
+extern "C" {
+#if 0 /* (Keep Emacsens' auto-indent happy.) */
+}
+#endif
+#endif
+
+/* The version of this header should match the one of the library. It
+ should not be used by a program because gcry_check_version() should
+ return the same version. The purpose of this macro is to let
+ autoconf (using the AM_PATH_GCRYPT macro) check that this header
+ matches the installed library. */
+#define GCRYPT_VERSION "@VERSION@"
+
+/* Internal: We can't use the convenience macros for the multi
+ precision integer functions when building this library. */
+#ifdef _GCRYPT_IN_LIBGCRYPT
+#ifndef GCRYPT_NO_MPI_MACROS
+#define GCRYPT_NO_MPI_MACROS 1
+#endif
+#endif
+
+/* We want to use gcc attributes when possible. Warning: Don't use
+ these macros in your programs: As indicated by the leading
+ underscore they are subject to change without notice. */
+#ifdef __GNUC__
+
+#define _GCRY_GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+#if _GCRY_GCC_VERSION >= 30100
+#define _GCRY_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+
+#if _GCRY_GCC_VERSION >= 29600
+#define _GCRY_GCC_ATTR_PURE __attribute__ ((__pure__))
+#endif
+
+#if _GCRY_GCC_VERSION >= 30200
+#define _GCRY_GCC_ATTR_MALLOC __attribute__ ((__malloc__))
+#endif
+
+#endif /*__GNUC__*/
+
+#ifndef _GCRY_GCC_ATTR_DEPRECATED
+#define _GCRY_GCC_ATTR_DEPRECATED
+#endif
+#ifndef _GCRY_GCC_ATTR_PURE
+#define _GCRY_GCC_ATTR_PURE
+#endif
+#ifndef _GCRY_GCC_ATTR_MALLOC
+#define _GCRY_GCC_ATTR_MALLOC
+#endif
+
+/* Some members in a public type should only be used internally.
+ There is no "internal" attribute, so we abuse the deprecated
+ attribute to discourage external use. */
+#ifdef _GCRYPT_IN_LIBGCRYPT
+#define _GCRY_ATTR_INTERNAL
+#else
+#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED
+#endif
+
+/* Wrappers for the libgpg-error library. */
+
+typedef gpg_error_t gcry_error_t;
+typedef gpg_err_code_t gcry_err_code_t;
+typedef gpg_err_source_t gcry_err_source_t;
+
+static GPG_ERR_INLINE gcry_error_t
+gcry_err_make (gcry_err_source_t source, gcry_err_code_t code)
+{
+ return gpg_err_make (source, code);
+}
+
+/* The user can define GPG_ERR_SOURCE_DEFAULT before including this
+ file to specify a default source for gpg_error. */
+#ifndef GCRY_ERR_SOURCE_DEFAULT
+#define GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
+#endif
+
+static GPG_ERR_INLINE gcry_error_t
+gcry_error (gcry_err_code_t code)
+{
+ return gcry_err_make (GCRY_ERR_SOURCE_DEFAULT, code);
+}
+
+static GPG_ERR_INLINE gcry_err_code_t
+gcry_err_code (gcry_error_t err)
+{
+ return gpg_err_code (err);
+}
+
+
+static GPG_ERR_INLINE gcry_err_source_t
+gcry_err_source (gcry_error_t err)
+{
+ return gpg_err_source (err);
+}
+
+/* Return a pointer to a string containing a description of the error
+ code in the error value ERR. */
+const char *gcry_strerror (gcry_error_t err);
+
+/* Return a pointer to a string containing a description of the error
+ source in the error value ERR. */
+const char *gcry_strsource (gcry_error_t err);
+
+/* Retrieve the error code for the system error ERR. This returns
+ GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
+ this). */
+gcry_err_code_t gcry_err_code_from_errno (int err);
+
+/* Retrieve the system error for the error code CODE. This returns 0
+ if CODE is not a system error code. */
+int gcry_err_code_to_errno (gcry_err_code_t code);
+
+/* Return an error value with the error source SOURCE and the system
+ error ERR. */
+gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err);
+
+/* Return an error value with the system error ERR. */
+gcry_err_code_t gcry_error_from_errno (int err);
+
+
+/* This enum is deprecated; it is only declared for the sake of
+ complete API compatibility. */
+enum gcry_thread_option
+ {
+ _GCRY_THREAD_OPTION_DUMMY
+ } _GCRY_GCC_ATTR_DEPRECATED;
+
+
+/* Constants defining the thread model to use. Used with the OPTION
+ field of the struct gcry_thread_cbs. */
+#define GCRY_THREAD_OPTION_DEFAULT 0
+#define GCRY_THREAD_OPTION_USER 1
+#define GCRY_THREAD_OPTION_PTH 2
+#define GCRY_THREAD_OPTION_PTHREAD 3
+
+/* The version number encoded in the OPTION field of the struct
+ gcry_thread_cbs. */
+#define GCRY_THREAD_OPTION_VERSION 0
+
+/* Wrapper for struct ath_ops. */
+struct gcry_thread_cbs
+{
+ /* The OPTION field encodes the thread model and the version number
+ of this structure.
+ Bits 7 - 0 are used for the thread model
+ Bits 15 - 8 are used for the version number.
+ */
+ unsigned int option;
+
+ int (*init) (void);
+ int (*mutex_init) (void **priv);
+ int (*mutex_destroy) (void **priv);
+ int (*mutex_lock) (void **priv);
+ int (*mutex_unlock) (void **priv);
+ ssize_t (*read) (int fd, void *buf, size_t nbytes);
+ ssize_t (*write) (int fd, const void *buf, size_t nbytes);
+#ifdef _WIN32
+ ssize_t (*select) (int nfd, void *rset, void *wset, void *eset,
+ struct timeval *timeout);
+ ssize_t (*waitpid) (pid_t pid, int *status, int options);
+ int (*accept) (int s, void *addr, int *length_ptr);
+ int (*connect) (int s, void *addr, gcry_socklen_t length);
+ int (*sendmsg) (int s, const void *msg, int flags);
+ int (*recvmsg) (int s, void *msg, int flags);
+#else
+ ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout);
+ ssize_t (*waitpid) (pid_t pid, int *status, int options);
+ int (*accept) (int s, struct sockaddr *addr, gcry_socklen_t *length_ptr);
+ int (*connect) (int s, struct sockaddr *addr, gcry_socklen_t length);
+ int (*sendmsg) (int s, const struct msghdr *msg, int flags);
+ int (*recvmsg) (int s, struct msghdr *msg, int flags);
+#endif
+};
+
+#ifdef _WIN32
+# define _GCRY_THREAD_OPTION_PTH_IMPL_NET \
+static ssize_t gcry_pth_select (int nfd, void *rset, void *wset, \
+ void *eset, struct timeval *timeout) \
+ { return pth_select (nfd, rset, wset, eset, timeout); } \
+static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
+ { return pth_waitpid (pid, status, options); } \
+static int gcry_pth_accept (int s, void *addr, \
+ gcry_socklen_t *length_ptr) \
+ { return pth_accept (s, addr, length_ptr); } \
+static int gcry_pth_connect (int s, void *addr, \
+ gcry_socklen_t length) \
+ { return pth_connect (s, addr, length); }
+#else /*!_WIN32*/
+# define _GCRY_THREAD_OPTION_PTH_IMPL_NET \
+static ssize_t gcry_pth_select (int nfd, fd_set *rset, fd_set *wset, \
+ fd_set *eset, struct timeval *timeout) \
+ { return pth_select (nfd, rset, wset, eset, timeout); } \
+static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \
+ { return pth_waitpid (pid, status, options); } \
+static int gcry_pth_accept (int s, struct sockaddr *addr, \
+ gcry_socklen_t *length_ptr) \
+ { return pth_accept (s, addr, length_ptr); } \
+static int gcry_pth_connect (int s, struct sockaddr *addr, \
+ gcry_socklen_t length) \
+ { return pth_connect (s, addr, length); }
+#endif /*!_WIN32*/
+
+
+
+#define GCRY_THREAD_OPTION_PTH_IMPL \
+static int gcry_pth_init (void) \
+{ return (pth_init () == FALSE) ? errno : 0; } \
+static int gcry_pth_mutex_init (void **priv) \
+{ \
+ int err = 0; \
+ pth_mutex_t *lock = malloc (sizeof (pth_mutex_t)); \
+ \
+ if (!lock) \
+ err = ENOMEM; \
+ if (!err) \
+ { \
+ err = pth_mutex_init (lock); \
+ if (err == FALSE) \
+ err = errno; \
+ else \
+ err = 0; \
+ if (err) \
+ free (lock); \
+ else \
+ *priv = lock; \
+ } \
+ return err; \
+} \
+static int gcry_pth_mutex_destroy (void **lock) \
+ { /* GNU Pth has no destructor function. */ free (*lock); return 0; } \
+static int gcry_pth_mutex_lock (void **lock) \
+ { return ((pth_mutex_acquire (*lock, 0, NULL)) == FALSE) \
+ ? errno : 0; } \
+static int gcry_pth_mutex_unlock (void **lock) \
+ { return ((pth_mutex_release (*lock)) == FALSE) \
+ ? errno : 0; } \
+static ssize_t gcry_pth_read (int fd, void *buf, size_t nbytes) \
+ { return pth_read (fd, buf, nbytes); } \
+static ssize_t gcry_pth_write (int fd, const void *buf, size_t nbytes) \
+ { return pth_write (fd, buf, nbytes); } \
+_GCRY_THREAD_OPTION_PTH_IMPL_NET \
+ \
+/* Note: GNU Pth is missing pth_sendmsg and pth_recvmsg. */ \
+static struct gcry_thread_cbs gcry_threads_pth = { \
+ (GCRY_THREAD_OPTION_PTH | (GCRY_THREAD_OPTION_VERSION << 8)), \
+ gcry_pth_init, gcry_pth_mutex_init, gcry_pth_mutex_destroy, \
+ gcry_pth_mutex_lock, gcry_pth_mutex_unlock, gcry_pth_read, gcry_pth_write, \
+ gcry_pth_select, gcry_pth_waitpid, gcry_pth_accept, gcry_pth_connect, \
+ NULL, NULL }
+
+
+#define GCRY_THREAD_OPTION_PTHREAD_IMPL \
+static int gcry_pthread_mutex_init (void **priv) \
+{ \
+ int err = 0; \
+ pthread_mutex_t *lock = (pthread_mutex_t*)malloc (sizeof (pthread_mutex_t));\
+ \
+ if (!lock) \
+ err = ENOMEM; \
+ if (!err) \
+ { \
+ err = pthread_mutex_init (lock, NULL); \
+ if (err) \
+ free (lock); \
+ else \
+ *priv = lock; \
+ } \
+ return err; \
+} \
+static int gcry_pthread_mutex_destroy (void **lock) \
+ { int err = pthread_mutex_destroy ((pthread_mutex_t*)*lock); \
+ free (*lock); return err; } \
+static int gcry_pthread_mutex_lock (void **lock) \
+ { return pthread_mutex_lock ((pthread_mutex_t*)*lock); } \
+static int gcry_pthread_mutex_unlock (void **lock) \
+ { return pthread_mutex_unlock ((pthread_mutex_t*)*lock); } \
+ \
+static struct gcry_thread_cbs gcry_threads_pthread = { \
+ (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)), \
+ NULL, gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, \
+ gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock, \
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+
+
+/* The data object used to hold a multi precision integer. */
+struct gcry_mpi;
+typedef struct gcry_mpi *gcry_mpi_t;
+
+#ifndef GCRYPT_NO_DEPRECATED
+typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED;
+typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED;
+#endif
+
+
+
+/* Check that the library fulfills the version requirement. */
+const char *gcry_check_version (const char *req_version);
+
+/* Codes for function dispatchers. */
+
+/* Codes used with the gcry_control function. */
+enum gcry_ctl_cmds
+ {
+ GCRYCTL_SET_KEY = 1,
+ GCRYCTL_SET_IV = 2,
+ GCRYCTL_CFB_SYNC = 3,
+ GCRYCTL_RESET = 4, /* e.g. for MDs */
+ GCRYCTL_FINALIZE = 5,
+ GCRYCTL_GET_KEYLEN = 6,
+ GCRYCTL_GET_BLKLEN = 7,
+ GCRYCTL_TEST_ALGO = 8,
+ GCRYCTL_IS_SECURE = 9,
+ GCRYCTL_GET_ASNOID = 10,
+ GCRYCTL_ENABLE_ALGO = 11,
+ GCRYCTL_DISABLE_ALGO = 12,
+ GCRYCTL_DUMP_RANDOM_STATS = 13,
+ GCRYCTL_DUMP_SECMEM_STATS = 14,
+ GCRYCTL_GET_ALGO_NPKEY = 15,
+ GCRYCTL_GET_ALGO_NSKEY = 16,
+ GCRYCTL_GET_ALGO_NSIGN = 17,
+ GCRYCTL_GET_ALGO_NENCR = 18,
+ GCRYCTL_SET_VERBOSITY = 19,
+ GCRYCTL_SET_DEBUG_FLAGS = 20,
+ GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
+ GCRYCTL_USE_SECURE_RNDPOOL= 22,
+ GCRYCTL_DUMP_MEMORY_STATS = 23,
+ GCRYCTL_INIT_SECMEM = 24,
+ GCRYCTL_TERM_SECMEM = 25,
+ GCRYCTL_DISABLE_SECMEM_WARN = 27,
+ GCRYCTL_SUSPEND_SECMEM_WARN = 28,
+ GCRYCTL_RESUME_SECMEM_WARN = 29,
+ GCRYCTL_DROP_PRIVS = 30,
+ GCRYCTL_ENABLE_M_GUARD = 31,
+ GCRYCTL_START_DUMP = 32,
+ GCRYCTL_STOP_DUMP = 33,
+ GCRYCTL_GET_ALGO_USAGE = 34,
+ GCRYCTL_IS_ALGO_ENABLED = 35,
+ GCRYCTL_DISABLE_INTERNAL_LOCKING = 36,
+ GCRYCTL_DISABLE_SECMEM = 37,
+ GCRYCTL_INITIALIZATION_FINISHED = 38,
+ GCRYCTL_INITIALIZATION_FINISHED_P = 39,
+ GCRYCTL_ANY_INITIALIZATION_P = 40,
+ GCRYCTL_SET_CBC_CTS = 41,
+ GCRYCTL_SET_CBC_MAC = 42,
+ GCRYCTL_SET_CTR = 43,
+ GCRYCTL_ENABLE_QUICK_RANDOM = 44,
+ GCRYCTL_SET_RANDOM_SEED_FILE = 45,
+ GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
+ GCRYCTL_SET_THREAD_CBS = 47,
+ GCRYCTL_FAST_POLL = 48,
+ GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49,
+ GCRYCTL_USE_RANDOM_DAEMON = 50,
+ GCRYCTL_FAKED_RANDOM_P = 51,
+ GCRYCTL_SET_RNDEGD_SOCKET = 52,
+ GCRYCTL_PRINT_CONFIG = 53,
+ GCRYCTL_OPERATIONAL_P = 54,
+ GCRYCTL_FIPS_MODE_P = 55,
+ GCRYCTL_FORCE_FIPS_MODE = 56,
+ GCRYCTL_SELFTEST = 57
+ /* Note: 58 .. 62 are used internally. */
+ };
+
+/* Perform various operations defined by CMD. */
+gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...);
+
+
+/* S-expression management. */
+
+/* The object to represent an S-expression as used with the public key
+ functions. */
+struct gcry_sexp;
+typedef struct gcry_sexp *gcry_sexp_t;
+
+#ifndef GCRYPT_NO_DEPRECATED
+typedef struct gcry_sexp *GCRY_SEXP _GCRY_GCC_ATTR_DEPRECATED;
+typedef struct gcry_sexp *GcrySexp _GCRY_GCC_ATTR_DEPRECATED;
+#endif
+
+/* The possible values for the S-expression format. */
+enum gcry_sexp_format
+ {
+ GCRYSEXP_FMT_DEFAULT = 0,
+ GCRYSEXP_FMT_CANON = 1,
+ GCRYSEXP_FMT_BASE64 = 2,
+ GCRYSEXP_FMT_ADVANCED = 3
+ };
+
+/* Create an new S-expression object from BUFFER of size LENGTH and
+ return it in RETSEXP. With AUTODETECT set to 0 the data in BUFFER
+ is expected to be in canonized format. */
+gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp,
+ const void *buffer, size_t length,
+ int autodetect);
+
+ /* Same as gcry_sexp_new but allows to pass a FREEFNC which has the
+ effect to transfer ownership of BUFFER to the created object. */
+gcry_error_t gcry_sexp_create (gcry_sexp_t *retsexp,
+ void *buffer, size_t length,
+ int autodetect, void (*freefnc) (void *));
+
+/* Scan BUFFER and return a new S-expression object in RETSEXP. This
+ function expects a printf like string in BUFFER. */
+gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length);
+
+/* Same as gcry_sexp_sscan but expects a string in FORMAT and can thus
+ only be used for certain encodings. */
+gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *format, ...);
+
+/* Like gcry_sexp_build, but uses an array instead of variable
+ function arguments. */
+gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *format, void **arg_list);
+
+/* Release the S-expression object SEXP */
+void gcry_sexp_release (gcry_sexp_t sexp);
+
+/* Calculate the length of an canonized S-expresion in BUFFER and
+ check for a valid encoding. */
+size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
+ size_t *erroff, gcry_error_t *errcode);
+
+/* Copies the S-expression object SEXP into BUFFER using the format
+ specified in MODE. */
+size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
+ size_t maxlength);
+
+/* Dumps the S-expression object A in a format suitable for debugging
+ to Libgcrypt's logging stream. */
+void gcry_sexp_dump (const gcry_sexp_t a);
+
+gcry_sexp_t gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b);
+gcry_sexp_t gcry_sexp_alist (const gcry_sexp_t *array);
+gcry_sexp_t gcry_sexp_vlist (const gcry_sexp_t a, ...);
+gcry_sexp_t gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n);
+gcry_sexp_t gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n);
+
+/* Scan the S-expression for a sublist with a type (the car of the
+ list) matching the string TOKEN. If TOKLEN is not 0, the token is
+ assumed to be raw memory of this length. The function returns a
+ newly allocated S-expression consisting of the found sublist or
+ `NULL' when not found. */
+gcry_sexp_t gcry_sexp_find_token (gcry_sexp_t list,
+ const char *tok, size_t toklen);
+/* Return the length of the LIST. For a valid S-expression this
+ should be at least 1. */
+int gcry_sexp_length (const gcry_sexp_t list);
+
+/* Create and return a new S-expression from the element with index
+ NUMBER in LIST. Note that the first element has the index 0. If
+ there is no such element, `NULL' is returned. */
+gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t list, int number);
+
+/* Create and return a new S-expression from the first element in
+ LIST; this called the "type" and should always exist and be a
+ string. `NULL' is returned in case of a problem. */
+gcry_sexp_t gcry_sexp_car (const gcry_sexp_t list);
+
+/* Create and return a new list form all elements except for the first
+ one. Note, that this function may return an invalid S-expression
+ because it is not guaranteed, that the type exists and is a string.
+ However, for parsing a complex S-expression it might be useful for
+ intermediate lists. Returns `NULL' on error. */
+gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t list);
+
+gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list);
+
+
+/* This function is used to get data from a LIST. A pointer to the
+ actual data with index NUMBER is returned and the length of this
+ data will be stored to DATALEN. If there is no data at the given
+ index or the index represents another list, `NULL' is returned.
+ *Note:* The returned pointer is valid as long as LIST is not
+ modified or released. */
+const char *gcry_sexp_nth_data (const gcry_sexp_t list, int number,
+ size_t *datalen);
+
+/* This function is used to get and convert data from a LIST. The
+ data is assumed to be a Nul terminated string. The caller must
+ release the returned value using `gcry_free'. If there is no data
+ at the given index, the index represents a list or the value can't
+ be converted to a string, `NULL' is returned. */
+char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
+
+/* This function is used to get and convert data from a LIST. This
+ data is assumed to be an MPI stored in the format described by
+ MPIFMT and returned as a standard Libgcrypt MPI. The caller must
+ release this returned value using `gcry_mpi_release'. If there is
+ no data at the given index, the index represents a list or the
+ value can't be converted to an MPI, `NULL' is returned. */
+gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
+
+
+
+/*******************************************
+ * *
+ * Multi Precision Integer Functions *
+ * *
+ *******************************************/
+
+/* Different formats of external big integer representation. */
+enum gcry_mpi_format
+ {
+ GCRYMPI_FMT_NONE= 0,
+ GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */
+ GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */
+ GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */
+ GCRYMPI_FMT_HEX = 4, /* Hex format. */
+ GCRYMPI_FMT_USG = 5 /* Like STD but unsigned. */
+ };
+
+/* Flags used for creating big integers. */
+enum gcry_mpi_flag
+ {
+ GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
+ GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just
+ a way to store some bytes. This is
+ useful for encrypted big integers. */
+ };
+
+
+/* Allocate a new big integer object, initialize it with 0 and
+ initially allocate memory for a number of at least NBITS. */
+gcry_mpi_t gcry_mpi_new (unsigned int nbits);
+
+/* Same as gcry_mpi_new() but allocate in "secure" memory. */
+gcry_mpi_t gcry_mpi_snew (unsigned int nbits);
+
+/* Release the number A and free all associated resources. */
+void gcry_mpi_release (gcry_mpi_t a);
+
+/* Create a new number with the same value as A. */
+gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t a);
+
+/* Store the big integer value U in W. */
+gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
+
+/* Store the unsigned integer value U in W. */
+gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
+
+/* Swap the values of A and B. */
+void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
+
+/* Compare the big integer number U and V returning 0 for equality, a
+ positive value for U > V and a negative for U < V. */
+int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v);
+
+/* Compare the big integer number U with the unsigned integer V
+ returning 0 for equality, a positive value for U > V and a negative
+ for U < V. */
+int gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v);
+
+/* Convert the external representation of an integer stored in BUFFER
+ with a length of BUFLEN into a newly create MPI returned in
+ RET_MPI. If NSCANNED is not NULL, it will receive the number of
+ bytes actually scanned after a successful operation. */
+gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
+ const void *buffer, size_t buflen,
+ size_t *nscanned);
+
+/* Convert the big integer A into the external representation
+ described by FORMAT and store it in the provided BUFFER which has
+ been allocated by the user with a size of BUFLEN bytes. NWRITTEN
+ receives the actual length of the external representation unless it
+ has been passed as NULL. */
+gcry_error_t gcry_mpi_print (enum gcry_mpi_format format,
+ unsigned char *buffer, size_t buflen,
+ size_t *nwritten,
+ const gcry_mpi_t a);
+
+/* Convert the big integer A int the external representation described
+ by FORMAT and store it in a newly allocated buffer which address
+ will be put into BUFFER. NWRITTEN receives the actual lengths of the
+ external representation. */
+gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format format,
+ unsigned char **buffer, size_t *nwritten,
+ const gcry_mpi_t a);
+
+/* Dump the value of A in a format suitable for debugging to
+ Libgcrypt's logging stream. Note that one leading space but no
+ trailing space or linefeed will be printed. It is okay to pass
+ NULL for A. */
+void gcry_mpi_dump (const gcry_mpi_t a);
+
+
+/* W = U + V. */
+void gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
+
+/* W = U + V. V is an unsigned integer. */
+void gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v);
+
+/* W = U + V mod M. */
+void gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
+
+/* W = U - V. */
+void gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
+
+/* W = U - V. V is an unsigned integer. */
+void gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
+
+/* W = U - V mod M */
+void gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
+
+/* W = U * V. */
+void gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
+
+/* W = U * V. V is an unsigned integer. */
+void gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
+
+/* W = U * V mod M. */
+void gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
+
+/* W = U * (2 ^ CNT). */
+void gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt);
+
+/* Q = DIVIDEND / DIVISOR, R = DIVIDEND % DIVISOR,
+ Q or R may be passed as NULL. ROUND should be negative or 0. */
+void gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
+ gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
+
+/* R = DIVIDEND % DIVISOR */
+void gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor);
+
+/* W = B ^ E mod M. */
+void gcry_mpi_powm (gcry_mpi_t w,
+ const gcry_mpi_t b, const gcry_mpi_t e,
+ const gcry_mpi_t m);
+
+/* Set G to the greatest common divisor of A and B.
+ Return true if the G is 1. */
+int gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b);
+
+/* Set X to the multiplicative inverse of A mod M.
+ Return true if the value exists. */
+int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m);
+
+
+/* Return the number of bits required to represent A. */
+unsigned int gcry_mpi_get_nbits (gcry_mpi_t a);
+
+/* Return true when bit number N (counting from 0) is set in A. */
+int gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n);
+
+/* Set bit number N in A. */
+void gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n);
+
+/* Clear bit number N in A. */
+void gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n);
+
+/* Set bit number N in A and clear all bits greater than N. */
+void gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n);
+
+/* Clear bit number N in A and all bits greater than N. */
+void gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n);
+
+/* Shift the value of A by N bits to the right and store the result in X. */
+void gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
+
+/* Shift the value of A by N bits to the left and store the result in X. */
+void gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
+
+/* Store NBITS of the value P points to in A and mark A as an opaque
+ value. WARNING: Never use an opaque MPI for anything thing else then
+ gcry_mpi_release, gcry_mpi_get_opaque. */
+gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits);
+
+/* Return a pointer to an opaque value stored in A and return its size
+ in NBITS. Note that the returned pointer is still owned by A and
+ that the function should never be used for an non-opaque MPI. */
+void *gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits);
+
+/* Set the FLAG for the big integer A. Currently only the flag
+ GCRYMPI_FLAG_SECURE is allowed to convert A into an big intger
+ stored in "secure" memory. */
+void gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
+
+/* Clear FLAG for the big integer A. Note that this function is
+ currently useless as no flags are allowed. */
+void gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
+
+/* Return true when the FLAG is set for A. */
+int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
+
+/* Unless the GCRYPT_NO_MPI_MACROS is used, provide a couple of
+ convenience macros for the big integer functions. */
+#ifndef GCRYPT_NO_MPI_MACROS
+#define mpi_new(n) gcry_mpi_new( (n) )
+#define mpi_secure_new( n ) gcry_mpi_snew( (n) )
+#define mpi_release(a) \
+ do \
+ { \
+ gcry_mpi_release ((a)); \
+ (a) = NULL; \
+ } \
+ while (0)
+
+#define mpi_copy( a ) gcry_mpi_copy( (a) )
+#define mpi_set( w, u) gcry_mpi_set( (w), (u) )
+#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) )
+#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) )
+#define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) )
+
+#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
+#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v))
+#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m))
+#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v))
+#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v))
+#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m))
+#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v))
+#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v))
+#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v))
+#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m))
+#define mpi_powm(w,b,e,m) gcry_mpi_powm ( (w), (b), (e), (m) )
+#define mpi_tdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), 0)
+#define mpi_fdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), -1)
+#define mpi_mod(r,a,m) gcry_mpi_mod ((r), (a), (m))
+#define mpi_gcd(g,a,b) gcry_mpi_gcd ( (g), (a), (b) )
+#define mpi_invm(g,a,b) gcry_mpi_invm ( (g), (a), (b) )
+
+#define mpi_get_nbits(a) gcry_mpi_get_nbits ((a))
+#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b))
+#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b))
+#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b))
+#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b))
+#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b))
+#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c))
+#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c))
+
+#define mpi_set_opaque(a,b,c) gcry_mpi_set_opaque( (a), (b), (c) )
+#define mpi_get_opaque(a,b) gcry_mpi_get_opaque( (a), (b) )
+#endif /* GCRYPT_NO_MPI_MACROS */
+
+
+
+/************************************
+ * *
+ * Symmetric Cipher Functions *
+ * *
+ ************************************/
+
+/* The data object used to hold a handle to an encryption object. */
+struct gcry_cipher_handle;
+typedef struct gcry_cipher_handle *gcry_cipher_hd_t;
+
+#ifndef GCRYPT_NO_DEPRECATED
+typedef struct gcry_cipher_handle *GCRY_CIPHER_HD _GCRY_GCC_ATTR_DEPRECATED;
+typedef struct gcry_cipher_handle *GcryCipherHd _GCRY_GCC_ATTR_DEPRECATED;
+#endif
+
+/* All symmetric encryption algorithms are identified by their IDs.
+ More IDs may be registered at runtime. */
+enum gcry_cipher_algos
+ {
+ GCRY_CIPHER_NONE = 0,
+ GCRY_CIPHER_IDEA = 1,
+ GCRY_CIPHER_3DES = 2,
+ GCRY_CIPHER_CAST5 = 3,
+ GCRY_CIPHER_BLOWFISH = 4,
+ GCRY_CIPHER_SAFER_SK128 = 5,
+ GCRY_CIPHER_DES_SK = 6,
+ GCRY_CIPHER_AES = 7,
+ GCRY_CIPHER_AES192 = 8,
+ GCRY_CIPHER_AES256 = 9,
+ GCRY_CIPHER_TWOFISH = 10,
+
+ /* Other cipher numbers are above 300 for OpenPGP reasons. */
+ GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */
+ GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */
+ GCRY_CIPHER_TWOFISH128 = 303,
+ GCRY_CIPHER_SERPENT128 = 304,
+ GCRY_CIPHER_SERPENT192 = 305,
+ GCRY_CIPHER_SERPENT256 = 306,
+ GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */
+ GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */
+ GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */
+ GCRY_CIPHER_CAMELLIA128 = 310,
+ GCRY_CIPHER_CAMELLIA192 = 311,
+ GCRY_CIPHER_CAMELLIA256 = 312
+ };
+
+/* The Rijndael algorithm is basically AES, so provide some macros. */
+#define GCRY_CIPHER_AES128 GCRY_CIPHER_AES
+#define GCRY_CIPHER_RIJNDAEL GCRY_CIPHER_AES
+#define GCRY_CIPHER_RIJNDAEL128 GCRY_CIPHER_AES128
+#define GCRY_CIPHER_RIJNDAEL192 GCRY_CIPHER_AES192
+#define GCRY_CIPHER_RIJNDAEL256 GCRY_CIPHER_AES256
+
+/* The supported encryption modes. Note that not all of them are
+ supported for each algorithm. */
+enum gcry_cipher_modes
+ {
+ GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
+ GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
+ GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
+ GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
+ GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
+ GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
+ GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
+ GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */
+ };
+
+/* Flags used with the open function. */
+enum gcry_cipher_flags
+ {
+ GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */
+ GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */
+ GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */
+ GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */
+ };
+
+
+/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may
+ be given as an bitwise OR of the gcry_cipher_flags values. */
+gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
+ int algo, int mode, unsigned int flags);
+
+/* Close the cioher handle H and release all resource. */
+void gcry_cipher_close (gcry_cipher_hd_t h);
+
+/* Perform various operations on the cipher object H. */
+gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
+ size_t buflen);
+
+/* Retrieve various information about the cipher object H. */
+gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer,
+ size_t *nbytes);
+
+/* Retrieve various information about the cipher algorithm ALGO. */
+gcry_error_t gcry_cipher_algo_info (int algo, int what, void *buffer,
+ size_t *nbytes);
+
+/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
+ string representation of the algorithm name. For unknown algorithm
+ IDs this function returns "?". */
+const char *gcry_cipher_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
+
+/* Map the algorithm name NAME to an cipher algorithm ID. Return 0 if
+ the algorithm name is not known. */
+int gcry_cipher_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
+
+/* Given an ASN.1 object identifier in standard IETF dotted decimal
+ format in STRING, return the encryption mode associated with that
+ OID or 0 if not known or applicable. */
+int gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE;
+
+/* Encrypt the plaintext of size INLEN in IN using the cipher handle H
+ into the buffer OUT which has an allocated length of OUTSIZE. For
+ most algorithms it is possible to pass NULL for in and 0 for INLEN
+ and do a in-place decryption of the data provided in OUT. */
+gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h,
+ void *out, size_t outsize,
+ const void *in, size_t inlen);
+
+/* The counterpart to gcry_cipher_encrypt. */
+gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h,
+ void *out, size_t outsize,
+ const void *in, size_t inlen);
+
+/* Set KEY of length KEYLEN bytes for the cipher handle HD. */
+gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd,
+ const void *key, size_t keylen);
+
+
+/* Set initialization vector IV of length IVLEN for the cipher handle HD. */
+gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd,
+ const void *iv, size_t ivlen);
+
+
+/* Reset the handle to the state after open. */
+#define gcry_cipher_reset(h) gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0)
+
+/* Perform the OpenPGP sync operation if this is enabled for the
+ cipher handle H. */
+#define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, NULL, 0)
+
+/* Enable or disable CTS in future calls to gcry_encrypt(). CBC mode only. */
+#define gcry_cipher_cts(h,on) gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \
+ NULL, on )
+
+/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of
+ block size length, or (NULL,0) to set the CTR to the all-zero block. */
+gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd,
+ const void *ctr, size_t ctrlen);
+
+/* Retrieved the key length in bytes used with algorithm A. */
+size_t gcry_cipher_get_algo_keylen (int algo);
+
+/* Retrieve the block length in bytes used with algorithm A. */
+size_t gcry_cipher_get_algo_blklen (int algo);
+
+/* Return 0 if the algorithm A is available for use. */
+#define gcry_cipher_test_algo(a) \
+ gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+
+/* Get a list consisting of the IDs of the loaded cipher modules. If
+ LIST is zero, write the number of loaded cipher modules to
+ LIST_LENGTH and return. If LIST is non-zero, the first
+ *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
+ according size. In case there are less cipher modules than
+ *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
+gcry_error_t gcry_cipher_list (int *list, int *list_length);
+
+
+/************************************
+ * *
+ * Asymmetric Cipher Functions *
+ * *
+ ************************************/
+
+/* The algorithms and their IDs we support. */
+enum gcry_pk_algos
+ {
+ GCRY_PK_RSA = 1,
+ GCRY_PK_RSA_E = 2, /* (deprecated) */
+ GCRY_PK_RSA_S = 3, /* (deprecated) */
+ GCRY_PK_ELG_E = 16,
+ GCRY_PK_DSA = 17,
+ GCRY_PK_ELG = 20,
+ GCRY_PK_ECDSA = 301,
+ GCRY_PK_ECDH = 302
+ };
+
+/* Flags describing usage capabilities of a PK algorithm. */
+#define GCRY_PK_USAGE_SIGN 1 /* Good for signatures. */
+#define GCRY_PK_USAGE_ENCR 2 /* Good for encryption. */
+#define GCRY_PK_USAGE_CERT 4 /* Good to certify other keys. */
+#define GCRY_PK_USAGE_AUTH 8 /* Good for authentication. */
+#define GCRY_PK_USAGE_UNKN 128 /* Unknown usage flag. */
+
+/* Encrypt the DATA using the public key PKEY and store the result as
+ a newly created S-expression at RESULT. */
+gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result,
+ gcry_sexp_t data, gcry_sexp_t pkey);
+
+/* Decrypt the DATA using the private key SKEY and store the result as
+ a newly created S-expression at RESULT. */
+gcry_error_t gcry_pk_decrypt (gcry_sexp_t *result,
+ gcry_sexp_t data, gcry_sexp_t skey);
+
+/* Sign the DATA using the private key SKEY and store the result as
+ a newly created S-expression at RESULT. */
+gcry_error_t gcry_pk_sign (gcry_sexp_t *result,
+ gcry_sexp_t data, gcry_sexp_t skey);
+
+/* Check the signature SIGVAL on DATA using the public key PKEY. */
+gcry_error_t gcry_pk_verify (gcry_sexp_t sigval,
+ gcry_sexp_t data, gcry_sexp_t pkey);
+
+/* Check that private KEY is sane. */
+gcry_error_t gcry_pk_testkey (gcry_sexp_t key);
+
+/* Generate a new key pair according to the parameters given in
+ S_PARMS. The new key pair is returned in as an S-expression in
+ R_KEY. */
+gcry_error_t gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms);
+
+/* Catch all function for miscellaneous operations. */
+gcry_error_t gcry_pk_ctl (int cmd, void *buffer, size_t buflen);
+
+/* Retrieve information about the public key algorithm ALGO. */
+gcry_error_t gcry_pk_algo_info (int algo, int what,
+ void *buffer, size_t *nbytes);
+
+/* Map the public key algorithm whose ID is contained in ALGORITHM to
+ a string representation of the algorithm name. For unknown
+ algorithm IDs this functions returns "?". */
+const char *gcry_pk_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
+
+/* Map the algorithm NAME to a public key algorithm Id. Return 0 if
+ the algorithm name is not known. */
+int gcry_pk_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
+
+/* Return what is commonly referred as the key length for the given
+ public or private KEY. */
+unsigned int gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE;
+
+/* Please note that keygrip is still experimental and should not be
+ used without contacting the author. */
+unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
+
+/* Return 0 if the public key algorithm A is available for use. */
+#define gcry_pk_test_algo(a) \
+ gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+
+/* Get a list consisting of the IDs of the loaded pubkey modules. If
+ LIST is zero, write the number of loaded pubkey modules to
+ LIST_LENGTH and return. If LIST is non-zero, the first
+ *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
+ according size. In case there are less pubkey modules than
+ *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
+gcry_error_t gcry_pk_list (int *list, int *list_length);
+
+
+
+/************************************
+ * *
+ * Cryptograhic Hash Functions *
+ * *
+ ************************************/
+
+/* Algorithm IDs for the hash functions we know about. Not all of them
+ are implemnted. */
+enum gcry_md_algos
+ {
+ GCRY_MD_NONE = 0,
+ GCRY_MD_MD5 = 1,
+ GCRY_MD_SHA1 = 2,
+ GCRY_MD_RMD160 = 3,
+ GCRY_MD_MD2 = 5,
+ GCRY_MD_TIGER = 6, /* TIGER/192 as used by gpg <= 1.3.2. */
+ GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
+ GCRY_MD_SHA256 = 8,
+ GCRY_MD_SHA384 = 9,
+ GCRY_MD_SHA512 = 10,
+ GCRY_MD_SHA224 = 11,
+ GCRY_MD_MD4 = 301,
+ GCRY_MD_CRC32 = 302,
+ GCRY_MD_CRC32_RFC1510 = 303,
+ GCRY_MD_CRC24_RFC2440 = 304,
+ GCRY_MD_WHIRLPOOL = 305,
+ GCRY_MD_TIGER1 = 306, /* TIGER fixed. */
+ GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */
+ };
+
+/* Flags used with the open function. */
+enum gcry_md_flags
+ {
+ GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
+ GCRY_MD_FLAG_HMAC = 2 /* Make an HMAC out of this algorithm. */
+ };
+
+/* (Forward declaration.) */
+struct gcry_md_context;
+
+/* This object is used to hold a handle to a message digest object.
+ This structure is private - only to be used by the public gcry_md_*
+ macros. */
+typedef struct gcry_md_handle
+{
+ /* Actual context. */
+ struct gcry_md_context *ctx;
+
+ /* Buffer management. */
+ int bufpos;
+ int bufsize;
+ unsigned char buf[1];
+} *gcry_md_hd_t;
+
+/* Compatibility types, do not use them. */
+#ifndef GCRYPT_NO_DEPRECATED
+typedef struct gcry_md_handle *GCRY_MD_HD _GCRY_GCC_ATTR_DEPRECATED;
+typedef struct gcry_md_handle *GcryMDHd _GCRY_GCC_ATTR_DEPRECATED;
+#endif
+
+/* Create a message digest object for algorithm ALGO. FLAGS may be
+ given as an bitwise OR of the gcry_md_flags values. ALGO may be
+ given as 0 if the algorithms to be used are later set using
+ gcry_md_enable. */
+gcry_error_t gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags);
+
+/* Release the message digest object HD. */
+void gcry_md_close (gcry_md_hd_t hd);
+
+/* Add the message digest algorithm ALGO to the digest object HD. */
+gcry_error_t gcry_md_enable (gcry_md_hd_t hd, int algo);
+
+/* Create a new digest object as an exact copy of the object HD. */
+gcry_error_t gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd);
+
+/* Reset the digest object HD to its initial state. */
+void gcry_md_reset (gcry_md_hd_t hd);
+
+/* Perform various operations on the digest object HD. */
+gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd,
+ void *buffer, size_t buflen);
+
+/* Pass LENGTH bytes of data in BUFFER to the digest object HD so that
+ it can update the digest values. This is the actual hash
+ function. */
+void gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
+
+/* Read out the final digest from HD return the digest value for
+ algorithm ALGO. */
+unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo);
+
+/* Convenience function to calculate the hash from the data in BUFFER
+ of size LENGTH using the algorithm ALGO avoiding the creating of a
+ hash object. The hash is returned in the caller provided buffer
+ DIGEST which must be large enough to hold the digest of the given
+ algorithm. */
+void gcry_md_hash_buffer (int algo, void *digest,
+ const void *buffer, size_t length);
+
+/* Retrieve the algorithm used with HD. This does not work reliable
+ if more than one algorithm is enabled in HD. */
+int gcry_md_get_algo (gcry_md_hd_t hd);
+
+/* Retrieve the length in bytes of the digest yielded by algorithm
+ ALGO. */
+unsigned int gcry_md_get_algo_dlen (int algo);
+
+/* Return true if the the algorithm ALGO is enabled in the digest
+ object A. */
+int gcry_md_is_enabled (gcry_md_hd_t a, int algo);
+
+/* Return true if the digest object A is allocated in "secure" memory. */
+int gcry_md_is_secure (gcry_md_hd_t a);
+
+/* Retrieve various information about the object H. */
+gcry_error_t gcry_md_info (gcry_md_hd_t h, int what, void *buffer,
+ size_t *nbytes);
+
+/* Retrieve various information about the algorithm ALGO. */
+gcry_error_t gcry_md_algo_info (int algo, int what, void *buffer,
+ size_t *nbytes);
+
+/* Map the digest algorithm id ALGO to a string representation of the
+ algorithm name. For unknown algorithms this function returns
+ "?". */
+const char *gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
+
+/* Map the algorithm NAME to a digest algorithm Id. Return 0 if
+ the algorithm name is not known. */
+int gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
+
+/* For use with the HMAC feature, the set MAC key to the KEY of
+ KEYLEN bytes. */
+gcry_error_t gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen);
+
+/* Start or stop debugging for digest handle HD; i.e. create a file
+ named dbgmd-<n>.<suffix> while hashing. If SUFFIX is NULL,
+ debugging stops and the file will be closed. */
+void gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
+
+
+/* Update the hash(s) of H with the character C. This is a buffered
+ version of the gcry_md_write function. */
+#define gcry_md_putc(h,c) \
+ do { \
+ gcry_md_hd_t h__ = (h); \
+ if( (h__)->bufpos == (h__)->bufsize ) \
+ gcry_md_write( (h__), NULL, 0 ); \
+ (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
+ } while(0)
+
+/* Finalize the digest calculation. This is not really needed because
+ gcry_md_read() does this implicitly. */
+#define gcry_md_final(a) \
+ gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
+
+/* Return 0 if the algorithm A is available for use. */
+#define gcry_md_test_algo(a) \
+ gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+
+/* Return an DER encoded ASN.1 OID for the algorithm A in buffer B. N
+ must point to size_t variable with the available size of buffer B.
+ After return it will receive the actual size of the returned
+ OID. */
+#define gcry_md_get_asnoid(a,b,n) \
+ gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n))
+
+/* Enable debugging for digest object A; i.e. create files named
+ dbgmd-<n>.<string> while hashing. B is a string used as the suffix
+ for the filename. This macro is deprecated, use gcry_md_debug. */
+#ifndef GCRYPT_NO_DEPRECATED
+#define gcry_md_start_debug(a,b) \
+ gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 )
+
+/* Disable the debugging of A. This macro is deprecated, use
+ gcry_md_debug. */
+#define gcry_md_stop_debug(a,b) \
+ gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 )
+#endif
+
+/* Get a list consisting of the IDs of the loaded message digest
+ modules. If LIST is zero, write the number of loaded message
+ digest modules to LIST_LENGTH and return. If LIST is non-zero, the
+ first *LIST_LENGTH algorithm IDs are stored in LIST, which must be
+ of according size. In case there are less message digest modules
+ than *LIST_LENGTH, *LIST_LENGTH is updated to the correct
+ number. */
+gcry_error_t gcry_md_list (int *list, int *list_length);
+
+
+
+/* Alternative interface for asymmetric cryptography. This interface
+ is deprecated. */
+
+/* The algorithm IDs. */
+typedef enum gcry_ac_id
+ {
+ GCRY_AC_RSA = 1,
+ GCRY_AC_DSA = 17,
+ GCRY_AC_ELG = 20,
+ GCRY_AC_ELG_E = 16
+ }
+gcry_ac_id_t;
+
+/* Key types. */
+typedef enum gcry_ac_key_type
+ {
+ GCRY_AC_KEY_SECRET,
+ GCRY_AC_KEY_PUBLIC
+ }
+gcry_ac_key_type_t;
+
+/* Encoding methods. */
+typedef enum gcry_ac_em
+ {
+ GCRY_AC_EME_PKCS_V1_5,
+ GCRY_AC_EMSA_PKCS_V1_5
+ }
+gcry_ac_em_t;
+
+/* Encryption and Signature schemes. */
+typedef enum gcry_ac_scheme
+ {
+ GCRY_AC_ES_PKCS_V1_5,
+ GCRY_AC_SSA_PKCS_V1_5
+ }
+gcry_ac_scheme_t;
+
+/* AC data. */
+#define GCRY_AC_FLAG_DEALLOC (1 << 0)
+#define GCRY_AC_FLAG_COPY (1 << 1)
+#define GCRY_AC_FLAG_NO_BLINDING (1 << 2)
+
+/* This type represents a `data set'. */
+typedef struct gcry_ac_data *gcry_ac_data_t;
+
+/* This type represents a single `key', either a secret one or a
+ public one. */
+typedef struct gcry_ac_key *gcry_ac_key_t;
+
+/* This type represents a `key pair' containing a secret and a public
+ key. */
+typedef struct gcry_ac_key_pair *gcry_ac_key_pair_t;
+
+/* This type represents a `handle' that is needed by functions
+ performing cryptographic operations. */
+typedef struct gcry_ac_handle *gcry_ac_handle_t;
+
+typedef gpg_error_t (*gcry_ac_data_read_cb_t) (void *opaque,
+ unsigned char *buffer,
+ size_t *buffer_n);
+
+typedef gpg_error_t (*gcry_ac_data_write_cb_t) (void *opaque,
+ unsigned char *buffer,
+ size_t buffer_n);
+
+typedef enum
+ {
+ GCRY_AC_IO_READABLE,
+ GCRY_AC_IO_WRITABLE
+ }
+gcry_ac_io_mode_t;
+
+typedef enum
+ {
+ GCRY_AC_IO_STRING,
+ GCRY_AC_IO_CALLBACK
+ }
+gcry_ac_io_type_t;
+
+typedef struct gcry_ac_io
+{
+ /* This is an INTERNAL structure, do NOT use manually. */
+ gcry_ac_io_mode_t mode _GCRY_ATTR_INTERNAL;
+ gcry_ac_io_type_t type _GCRY_ATTR_INTERNAL;
+ union
+ {
+ union
+ {
+ struct
+ {
+ gcry_ac_data_read_cb_t cb;
+ void *opaque;
+ } callback;
+ struct
+ {
+ unsigned char *data;
+ size_t data_n;
+ } string;
+ void *opaque;
+ } readable;
+ union
+ {
+ struct
+ {
+ gcry_ac_data_write_cb_t cb;
+ void *opaque;
+ } callback;
+ struct
+ {
+ unsigned char **data;
+ size_t *data_n;
+ } string;
+ void *opaque;
+ } writable;
+ } io _GCRY_ATTR_INTERNAL;
+}
+gcry_ac_io_t;
+
+/* The caller of gcry_ac_key_pair_generate can provide one of these
+ structures in order to influence the key generation process in an
+ algorithm-specific way. */
+typedef struct gcry_ac_key_spec_rsa
+{
+ gcry_mpi_t e; /* E to use. */
+} gcry_ac_key_spec_rsa_t;
+
+/* Structure used for passing data to the implementation of the
+ `EME-PKCS-V1_5' encoding method. */
+typedef struct gcry_ac_eme_pkcs_v1_5
+{
+ size_t key_size;
+} gcry_ac_eme_pkcs_v1_5_t;
+
+typedef enum gcry_md_algos gcry_md_algo_t;
+
+/* Structure used for passing data to the implementation of the
+ `EMSA-PKCS-V1_5' encoding method. */
+typedef struct gcry_ac_emsa_pkcs_v1_5
+{
+ gcry_md_algo_t md;
+ size_t em_n;
+} gcry_ac_emsa_pkcs_v1_5_t;
+
+/* Structure used for passing data to the implementation of the
+ `SSA-PKCS-V1_5' signature scheme. */
+typedef struct gcry_ac_ssa_pkcs_v1_5
+{
+ gcry_md_algo_t md;
+} gcry_ac_ssa_pkcs_v1_5_t;
+
+/* Returns a new, empty data set in DATA. */
+gcry_error_t gcry_ac_data_new (gcry_ac_data_t *data);
+
+/* Destroy the data set DATA. */
+void gcry_ac_data_destroy (gcry_ac_data_t data);
+
+/* Create a copy of the data set DATA and store it in DATA_CP. */
+gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *data_cp,
+ gcry_ac_data_t data);
+
+/* Return the number of named MPI values inside of the data set
+ DATA. */
+unsigned int gcry_ac_data_length (gcry_ac_data_t data);
+
+/* Destroy any values contained in the data set DATA. */
+void gcry_ac_data_clear (gcry_ac_data_t data);
+
+/* Add the value MPI to DATA with the label NAME. If FLAGS contains
+ GCRY_AC_FLAG_DATA_COPY, the data set will contain copies of NAME
+ and MPI. If FLAGS contains GCRY_AC_FLAG_DATA_DEALLOC or
+ GCRY_AC_FLAG_DATA_COPY, the values contained in the data set will
+ be deallocated when they are to be removed from the data set. */
+gcry_error_t gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags,
+ const char *name, gcry_mpi_t mpi);
+
+/* Store the value labelled with NAME found in DATA in MPI. If FLAGS
+ contains GCRY_AC_FLAG_COPY, store a copy of the MPI value contained
+ in the data set. MPI may be NULL. */
+gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags,
+ const char *name, gcry_mpi_t *mpi);
+
+/* Stores in NAME and MPI the named MPI value contained in the data
+ set DATA with the index IDX. If FLAGS contains GCRY_AC_FLAG_COPY,
+ store copies of the values contained in the data set. NAME or MPI
+ may be NULL. */
+gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags,
+ unsigned int idx,
+ const char **name, gcry_mpi_t *mpi);
+
+/* Convert the data set DATA into a new S-Expression, which is to be
+ stored in SEXP, according to the identifiers contained in
+ IDENTIFIERS. */
+gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
+ const char **identifiers);
+
+/* Create a new data set, which is to be stored in DATA_SET, from the
+ S-Expression SEXP, according to the identifiers contained in
+ IDENTIFIERS. */
+gcry_error_t gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp,
+ const char **identifiers);
+
+/* Initialize AC_IO according to MODE, TYPE and the variable list of
+ arguments. The list of variable arguments to specify depends on
+ the given TYPE. */
+void gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
+ gcry_ac_io_type_t type, ...);
+
+/* Initialize AC_IO according to MODE, TYPE and the variable list of
+ arguments AP. The list of variable arguments to specify depends on
+ the given TYPE. */
+void gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode,
+ gcry_ac_io_type_t type, va_list ap);
+
+/* Create a new ac handle. */
+gcry_error_t gcry_ac_open (gcry_ac_handle_t *handle,
+ gcry_ac_id_t algorithm, unsigned int flags);
+
+/* Destroy an ac handle. */
+void gcry_ac_close (gcry_ac_handle_t handle);
+
+/* Initialize a key from a given data set. */
+gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
+ gcry_ac_key_type_t type, gcry_ac_data_t data);
+
+/* Generates a new key pair via the handle HANDLE of NBITS bits and
+ stores it in KEY_PAIR. In case non-standard settings are wanted, a
+ pointer to a structure of type gcry_ac_key_spec_<algorithm>_t,
+ matching the selected algorithm, can be given as KEY_SPEC.
+ MISC_DATA is not used yet. */
+gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
+ unsigned int nbits, void *spec,
+ gcry_ac_key_pair_t *key_pair,
+ gcry_mpi_t **misc_data);
+
+/* Returns the key of type WHICH out of the key pair KEY_PAIR. */
+gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
+ gcry_ac_key_type_t which);
+
+/* Returns the data set contained in the key KEY. */
+gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t key);
+
+/* Verifies that the key KEY is sane via HANDLE. */
+gcry_error_t gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key);
+
+/* Stores the number of bits of the key KEY in NBITS via HANDLE. */
+gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t handle,
+ gcry_ac_key_t key, unsigned int *nbits);
+
+/* Writes the 20 byte long key grip of the key KEY to KEY_GRIP via
+ HANDLE. */
+gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key,
+ unsigned char *key_grip);
+
+/* Destroy a key. */
+void gcry_ac_key_destroy (gcry_ac_key_t key);
+
+/* Destroy a key pair. */
+void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair);
+
+/* Encodes a message according to the encoding method METHOD. OPTIONS
+ must be a pointer to a method-specific structure
+ (gcry_ac_em*_t). */
+gcry_error_t gcry_ac_data_encode (gcry_ac_em_t method,
+ unsigned int flags, void *options,
+ gcry_ac_io_t *io_read,
+ gcry_ac_io_t *io_write);
+
+/* Decodes a message according to the encoding method METHOD. OPTIONS
+ must be a pointer to a method-specific structure
+ (gcry_ac_em*_t). */
+gcry_error_t gcry_ac_data_decode (gcry_ac_em_t method,
+ unsigned int flags, void *options,
+ gcry_ac_io_t *io_read,
+ gcry_ac_io_t *io_write);
+
+/* Encrypt the plain text MPI value DATA_PLAIN with the key KEY under
+ the control of the flags FLAGS and store the resulting data set
+ into DATA_ENCRYPTED. */
+gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t handle,
+ unsigned int flags,
+ gcry_ac_key_t key,
+ gcry_mpi_t data_plain,
+ gcry_ac_data_t *data_encrypted);
+
+/* Decrypt the decrypted data contained in the data set DATA_ENCRYPTED
+ with the key KEY under the control of the flags FLAGS and store the
+ resulting plain text MPI value in DATA_PLAIN. */
+gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t handle,
+ unsigned int flags,
+ gcry_ac_key_t key,
+ gcry_mpi_t *data_plain,
+ gcry_ac_data_t data_encrypted);
+
+/* Sign the data contained in DATA with the key KEY and store the
+ resulting signature in the data set DATA_SIGNATURE. */
+gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t handle,
+ gcry_ac_key_t key,
+ gcry_mpi_t data,
+ gcry_ac_data_t *data_signature);
+
+/* Verify that the signature contained in the data set DATA_SIGNATURE
+ is indeed the result of signing the data contained in DATA with the
+ secret key belonging to the public key KEY. */
+gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t handle,
+ gcry_ac_key_t key,
+ gcry_mpi_t data,
+ gcry_ac_data_t data_signature);
+
+/* Encrypts the plain text readable from IO_MESSAGE through HANDLE
+ with the public key KEY according to SCHEME, FLAGS and OPTS. If
+ OPTS is not NULL, it has to be a pointer to a structure specific to
+ the chosen scheme (gcry_ac_es_*_t). The encrypted message is
+ written to IO_CIPHER. */
+gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle,
+ gcry_ac_scheme_t scheme,
+ unsigned int flags, void *opts,
+ gcry_ac_key_t key,
+ gcry_ac_io_t *io_message,
+ gcry_ac_io_t *io_cipher);
+
+/* Decrypts the cipher text readable from IO_CIPHER through HANDLE
+ with the secret key KEY according to SCHEME, @var{flags} and OPTS.
+ If OPTS is not NULL, it has to be a pointer to a structure specific
+ to the chosen scheme (gcry_ac_es_*_t). The decrypted message is
+ written to IO_MESSAGE. */
+gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle,
+ gcry_ac_scheme_t scheme,
+ unsigned int flags, void *opts,
+ gcry_ac_key_t key,
+ gcry_ac_io_t *io_cipher,
+ gcry_ac_io_t *io_message);
+
+/* Signs the message readable from IO_MESSAGE through HANDLE with the
+ secret key KEY according to SCHEME, FLAGS and OPTS. If OPTS is not
+ NULL, it has to be a pointer to a structure specific to the chosen
+ scheme (gcry_ac_ssa_*_t). The signature is written to
+ IO_SIGNATURE. */
+gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t handle,
+ gcry_ac_scheme_t scheme,
+ unsigned int flags, void *opts,
+ gcry_ac_key_t key,
+ gcry_ac_io_t *io_message,
+ gcry_ac_io_t *io_signature);
+
+/* Verifies through HANDLE that the signature readable from
+ IO_SIGNATURE is indeed the result of signing the message readable
+ from IO_MESSAGE with the secret key belonging to the public key KEY
+ according to SCHEME and OPTS. If OPTS is not NULL, it has to be an
+ anonymous structure (gcry_ac_ssa_*_t) specific to the chosen
+ scheme. */
+gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t handle,
+ gcry_ac_scheme_t scheme,
+ unsigned int flags, void *opts,
+ gcry_ac_key_t key,
+ gcry_ac_io_t *io_message,
+ gcry_ac_io_t *io_signature);
+
+/* Store the textual representation of the algorithm whose id is given
+ in ALGORITHM in NAME. This function is deprecated; use
+ gcry_pk_algo_name. */
+#ifndef GCRYPT_NO_DEPRECATED
+gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t algorithm,
+ const char **name)
+ /* */ _GCRY_GCC_ATTR_DEPRECATED;
+/* Store the numeric ID of the algorithm whose textual representation
+ is contained in NAME in ALGORITHM. This function is deprecated;
+ use gcry_pk_map_name. */
+gcry_error_t gcry_ac_name_to_id (const char *name,
+ gcry_ac_id_t *algorithm)
+ /* */ _GCRY_GCC_ATTR_DEPRECATED;
+#endif
+
+
+/************************************
+ * *
+ * Random Generating Functions *
+ * *
+ ************************************/
+
+/* The possible values for the random quality. The rule of thumb is
+ to use STRONG for session keys and VERY_STRONG for key material.
+ WEAK is usually an alias for STRONG and should not be used anymore
+ (except with gcry_mpi_randomize); use gcry_create_nonce instead. */
+typedef enum gcry_random_level
+ {
+ GCRY_WEAK_RANDOM = 0,
+ GCRY_STRONG_RANDOM = 1,
+ GCRY_VERY_STRONG_RANDOM = 2
+ }
+gcry_random_level_t;
+
+/* Fill BUFFER with LENGTH bytes of random, using random numbers of
+ quality LEVEL. */
+void gcry_randomize (void *buffer, size_t length,
+ enum gcry_random_level level);
+
+/* Add the external random from BUFFER with LENGTH bytes into the
+ pool. QUALITY should either be -1 for unknown or in the range of 0
+ to 100 */
+gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length,
+ int quality);
+
+/* If random numbers are used in an application, this macro should be
+ called from time to time so that new stuff gets added to the
+ internal pool of the RNG. */
+#define gcry_fast_random_poll() gcry_control (GCRYCTL_FAST_POLL, NULL)
+
+
+/* Return NBYTES of allocated random using a random numbers of quality
+ LEVEL. */
+void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
+ _GCRY_GCC_ATTR_MALLOC;
+
+/* Return NBYTES of allocated random using a random numbers of quality
+ LEVEL. The random numbers are created returned in "secure"
+ memory. */
+void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
+ _GCRY_GCC_ATTR_MALLOC;
+
+
+/* Set the big integer W to a random value of NBITS using a random
+ generator with quality LEVEL. Note that by using a level of
+ GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */
+void gcry_mpi_randomize (gcry_mpi_t w,
+ unsigned int nbits, enum gcry_random_level level);
+
+
+/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
+void gcry_create_nonce (void *buffer, size_t length);
+
+
+
+
+
+/*******************************/
+/* */
+/* Prime Number Functions */
+/* */
+/*******************************/
+
+/* Mode values passed to a gcry_prime_check_func_t. */
+#define GCRY_PRIME_CHECK_AT_FINISH 0
+#define GCRY_PRIME_CHECK_AT_GOT_PRIME 1
+#define GCRY_PRIME_CHECK_AT_MAYBE_PRIME 2
+
+/* The function should return 1 if the operation shall continue, 0 to
+ reject the prime candidate. */
+typedef int (*gcry_prime_check_func_t) (void *arg, int mode,
+ gcry_mpi_t candidate);
+
+/* Flags for gcry_prime_generate(): */
+
+/* Allocate prime numbers and factors in secure memory. */
+#define GCRY_PRIME_FLAG_SECRET (1 << 0)
+
+/* Make sure that at least one prime factor is of size
+ `FACTOR_BITS'. */
+#define GCRY_PRIME_FLAG_SPECIAL_FACTOR (1 << 1)
+
+/* Generate a new prime number of PRIME_BITS bits and store it in
+ PRIME. If FACTOR_BITS is non-zero, one of the prime factors of
+ (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is
+ non-zero, allocate a new, NULL-terminated array holding the prime
+ factors and store it in FACTORS. FLAGS might be used to influence
+ the prime number generation process. */
+gcry_error_t gcry_prime_generate (gcry_mpi_t *prime,
+ unsigned int prime_bits,
+ unsigned int factor_bits,
+ gcry_mpi_t **factors,
+ gcry_prime_check_func_t cb_func,
+ void *cb_arg,
+ gcry_random_level_t random_level,
+ unsigned int flags);
+
+/* Find a generator for PRIME where the factorization of (prime-1) is
+ in the NULL terminated array FACTORS. Return the generator as a
+ newly allocated MPI in R_G. If START_G is not NULL, use this as
+ teh start for the search. */
+gcry_error_t gcry_prime_group_generator (gcry_mpi_t *r_g,
+ gcry_mpi_t prime,
+ gcry_mpi_t *factors,
+ gcry_mpi_t start_g);
+
+
+/* Convenience function to release the FACTORS array. */
+void gcry_prime_release_factors (gcry_mpi_t *factors);
+
+
+/* Check wether the number X is prime. */
+gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
+
+
+
+/************************************
+ * *
+ * Miscellaneous Stuff *
+ * *
+ ************************************/
+
+/* Log levels used by the internal logging facility. */
+enum gcry_log_levels
+ {
+ GCRY_LOG_CONT = 0, /* (Continue the last log line.) */
+ GCRY_LOG_INFO = 10,
+ GCRY_LOG_WARN = 20,
+ GCRY_LOG_ERROR = 30,
+ GCRY_LOG_FATAL = 40,
+ GCRY_LOG_BUG = 50,
+ GCRY_LOG_DEBUG = 100
+ };
+
+/* Type for progress handlers. */
+typedef void (*gcry_handler_progress_t) (void *, const char *, int, int, int);
+
+/* Type for memory allocation handlers. */
+typedef void *(*gcry_handler_alloc_t) (size_t n);
+
+/* Type for secure memory check handlers. */
+typedef int (*gcry_handler_secure_check_t) (const void *);
+
+/* Type for memory reallocation handlers. */
+typedef void *(*gcry_handler_realloc_t) (void *p, size_t n);
+
+/* Type for memory free handlers. */
+typedef void (*gcry_handler_free_t) (void *);
+
+/* Type for out-of-memory handlers. */
+typedef int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int);
+
+/* Type for fatal error handlers. */
+typedef void (*gcry_handler_error_t) (void *, int, const char *);
+
+/* Type for logging handlers. */
+typedef void (*gcry_handler_log_t) (void *, int, const char *, va_list);
+
+/* Certain operations can provide progress information. This function
+ is used to register a handler for retrieving these information. */
+void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
+
+
+/* Register a custom memory allocation functions. */
+void gcry_set_allocation_handler (
+ gcry_handler_alloc_t func_alloc,
+ gcry_handler_alloc_t func_alloc_secure,
+ gcry_handler_secure_check_t func_secure_check,
+ gcry_handler_realloc_t func_realloc,
+ gcry_handler_free_t func_free);
+
+/* Register a function used instead of the internal out of memory
+ handler. */
+void gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque);
+
+/* Register a function used instead of the internal fatal error
+ handler. */
+void gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque);
+
+/* Register a function used instead of the internal logging
+ facility. */
+void gcry_set_log_handler (gcry_handler_log_t f, void *opaque);
+
+/* Reserved for future use. */
+void gcry_set_gettext_handler (const char *(*f)(const char*));
+
+/* Libgcrypt uses its own memory allocation. It is important to use
+ gcry_free () to release memory allocated by libgcrypt. */
+void *gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_calloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_realloc (void *a, size_t n);
+char *gcry_strdup (const char *string) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_xmalloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_xcalloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_xmalloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_xcalloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
+void *gcry_xrealloc (void *a, size_t n);
+char *gcry_xstrdup (const char * a) _GCRY_GCC_ATTR_MALLOC;
+void gcry_free (void *a);
+
+/* Return true if A is allocated in "secure" memory. */
+int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
+
+/* Return true if Libgcrypt is in FIPS mode. */
+#define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0)
+
+
+/* Include support for Libgcrypt modules. */
+#include <gcrypt-module.h>
+
+#if 0 /* (Keep Emacsens' auto-indent happy.) */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GCRYPT_H */
+/*
+@emacs_local_vars_begin@
+@emacs_local_vars_read_only@
+@emacs_local_vars_end@
+*/
diff --git a/libgcrypt-1.4.6/src/misc.c b/libgcrypt-1.4.6/src/misc.c
index fcad8d4..a20163c 100644
--- a/libgcrypt-1.4.6/src/misc.c
+++ b/libgcrypt-1.4.6/src/misc.c
@@ -64,7 +64,7 @@ gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value)
static void
write2stderr( const char *s )
{
- write( 2, s, strlen(s) );
+ _write( 2, s, strlen(s) );
}
/*
diff --git a/libgcrypt-1.4.6/src/sexp.c b/libgcrypt-1.4.6/src/sexp.c
index 99d0141..e11f86e 100644
--- a/libgcrypt-1.4.6/src/sexp.c
+++ b/libgcrypt-1.4.6/src/sexp.c
@@ -1,1974 +1,1976 @@
-/* sexp.c - S-Expression handling
- * Copyright (C) 1999, 2000, 2001, 2002, 2003,
- * 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
- *
- * This file is part of Libgcrypt.
- *
- * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Libgcrypt 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <errno.h>
-
-#define GCRYPT_NO_MPI_MACROS 1
-#include "g10lib.h"
-#include "memory.h"
-
-typedef struct gcry_sexp *NODE;
-typedef unsigned short DATALEN;
-
-struct gcry_sexp
-{
- byte d[1];
-};
-
-#define ST_STOP 0
-#define ST_DATA 1 /* datalen follows */
-#define ST_HINT 2 /* datalen follows */
-#define ST_OPEN 3
-#define ST_CLOSE 4
-
-/* the atoi macros assume that the buffer has only valid digits */
-#define atoi_1(p) (*(p) - '0' )
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-
-#define TOKEN_SPECIALS "-./_:*+="
-
-static gcry_error_t
-sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
- const char *buffer, size_t length, int argflag,
- va_list arg_ptr, void **arg_list);
-
-/* Return true if P points to a byte containing a whitespace according
- to the S-expressions definition. */
-#undef whitespacep
-static GPG_ERR_INLINE int
-whitespacep (const char *p)
-{
- switch (*p)
- {
- case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
- default: return 0;
- }
-}
-
-
-#if 0
-static void
-dump_mpi( gcry_mpi_t a )
-{
- char buffer[1000];
- size_t n = 1000;
-
- if( !a )
- fputs("[no MPI]", stderr );
- else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
- fputs("[MPI too large to print]", stderr );
- else
- fputs( buffer, stderr );
-}
-#endif
-
-static void
-dump_string (const byte *p, size_t n, int delim )
-{
- for (; n; n--, p++ )
- {
- if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
- {
- if( *p == '\n' )
- log_printf ("\\n");
- else if( *p == '\r' )
- log_printf ("\\r");
- else if( *p == '\f' )
- log_printf ("\\f");
- else if( *p == '\v' )
- log_printf ("\\v");
- else if( *p == '\b' )
- log_printf ("\\b");
- else if( !*p )
- log_printf ("\\0");
- else
- log_printf ("\\x%02x", *p );
- }
- else
- log_printf ("%c", *p);
- }
-}
-
-
-void
-gcry_sexp_dump (const gcry_sexp_t a)
-{
- const byte *p;
- int indent = 0;
- int type;
-
- if (!a)
- {
- log_printf ( "[nil]\n");
- return;
- }
-
- p = a->d;
- while ( (type = *p) != ST_STOP )
- {
- p++;
- switch ( type )
- {
- case ST_OPEN:
- log_printf ("%*s[open]\n", 2*indent, "");
- indent++;
- break;
- case ST_CLOSE:
- if( indent )
- indent--;
- log_printf ("%*s[close]\n", 2*indent, "");
- break;
- case ST_DATA: {
- DATALEN n;
- memcpy ( &n, p, sizeof n );
- p += sizeof n;
- log_printf ("%*s[data=\"", 2*indent, "" );
- dump_string (p, n, '\"' );
- log_printf ("\"]\n");
- p += n;
- }
- break;
- default:
- log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
- break;
- }
- }
-}
-
-/****************
- * Pass list through except when it is an empty list - in that case
- * return NULL and release the passed list.
- */
-static gcry_sexp_t
-normalize ( gcry_sexp_t list )
-{
- unsigned char *p;
-
- if ( !list )
- return NULL;
- p = list->d;
- if ( *p == ST_STOP )
- {
- /* this is "" */
- gcry_sexp_release ( list );
- return NULL;
- }
- if ( *p == ST_OPEN && p[1] == ST_CLOSE )
- {
- /* this is "()" */
- gcry_sexp_release ( list );
- return NULL;
- }
-
- return list;
-}
-#pragma runtime_checks("su", off)
-/* Create a new S-expression object by reading LENGTH bytes from
- BUFFER, assuming it is canonical encoded or autodetected encoding
- when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of
- the buffer is transferred to the newly created object. FREEFNC
- should be the freefnc used to release BUFFER; there is no guarantee
- at which point this function is called; most likey you want to use
- free() or gcry_free().
-
- Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
- BUFFER points to a valid canonical encoded S-expression. A LENGTH
- of 0 and AUTODETECT 1 indicates that buffer points to a
- null-terminated string.
-
- This function returns 0 and and the pointer to the new object in
- RETSEXP or an error code in which case RETSEXP is set to NULL. */
-gcry_error_t
-gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
- int autodetect, void (*freefnc)(void*) )
-{
- gcry_error_t errcode;
- gcry_sexp_t se;
- volatile va_list dummy_arg_ptr;
-
- if (!retsexp)
- return gcry_error (GPG_ERR_INV_ARG);
- *retsexp = NULL;
- if (autodetect < 0 || autodetect > 1 || !buffer)
- return gcry_error (GPG_ERR_INV_ARG);
-
- if (!length && !autodetect)
- { /* What a brave caller to assume that there is really a canonical
- encoded S-expression in buffer */
- length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
- if (!length)
- return errcode;
- }
- else if (!length && autodetect)
- { /* buffer is a string */
- length = strlen ((char *)buffer);
- }
-
- errcode = sexp_sscan (&se, NULL, buffer, length, 0, dummy_arg_ptr, NULL);
- if (errcode)
- return errcode;
-
- *retsexp = se;
- if (freefnc)
- {
- /* For now we release the buffer immediately. As soon as we
- have changed the internal represenation of S-expression to
- the canoncial format - which has the advantage of faster
- parsing - we will use this function as a closure in our
- GCRYSEXP object and use the BUFFER directly. */
- freefnc (buffer);
- }
- return gcry_error (GPG_ERR_NO_ERROR);
-}
-
-/* Same as gcry_sexp_create but don't transfer ownership */
-gcry_error_t
-gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
- int autodetect)
-{
- return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
-}
-
-
-/****************
- * Release resource of the given SEXP object.
- */
-void
-gcry_sexp_release( gcry_sexp_t sexp )
-{
- if (sexp)
- {
- if (gcry_is_secure (sexp))
- {
- /* Extra paranoid wiping. */
- const byte *p = sexp->d;
- int type;
-
- while ( (type = *p) != ST_STOP )
- {
- p++;
- switch ( type )
- {
- case ST_OPEN:
- break;
- case ST_CLOSE:
- break;
- case ST_DATA:
- {
- DATALEN n;
- memcpy ( &n, p, sizeof n );
- p += sizeof n;
- p += n;
- }
- break;
- default:
- break;
- }
- }
- wipememory (sexp->d, p - sexp->d);
- }
- gcry_free ( sexp );
- }
-}
-
-
-/****************
- * Make a pair from lists a and b, don't use a or b later on.
- * Special behaviour: If one is a single element list we put the
- * element straight into the new pair.
- */
-gcry_sexp_t
-gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
-{
- (void)a;
- (void)b;
-
- /* NYI: Implementation should be quite easy with our new data
- representation */
- BUG ();
- return NULL;
-}
-
-
-/****************
- * Make a list from all items in the array the end of the array is marked
- * with a NULL.
- */
-gcry_sexp_t
-gcry_sexp_alist( const gcry_sexp_t *array )
-{
- (void)array;
-
- /* NYI: Implementation should be quite easy with our new data
- representation. */
- BUG ();
- return NULL;
-}
-
-/****************
- * Make a list from all items, the end of list is indicated by a NULL
- */
-gcry_sexp_t
-gcry_sexp_vlist( const gcry_sexp_t a, ... )
-{
- (void)a;
- /* NYI: Implementation should be quite easy with our new data
- representation. */
- BUG ();
- return NULL;
-}
-
-
-/****************
- * Append n to the list a
- * Returns: a new ist (which maybe a)
- */
-gcry_sexp_t
-gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
-{
- (void)a;
- (void)n;
- /* NYI: Implementation should be quite easy with our new data
- representation. */
- BUG ();
- return NULL;
-}
-
-gcry_sexp_t
-gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
-{
- (void)a;
- (void)n;
- /* NYI: Implementation should be quite easy with our new data
- representation. */
- BUG ();
- return NULL;
-}
-
-
-
-/****************
- * Locate token in a list. The token must be the car of a sublist.
- * Returns: A new list with this sublist or NULL if not found.
- */
-gcry_sexp_t
-gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
-{
- const byte *p;
- DATALEN n;
-
- if ( !list )
- return NULL;
-
- if ( !toklen )
- toklen = strlen(tok);
-
- p = list->d;
- while ( *p != ST_STOP )
- {
- if ( *p == ST_OPEN && p[1] == ST_DATA )
- {
- const byte *head = p;
-
- p += 2;
- memcpy ( &n, p, sizeof n );
- p += sizeof n;
- if ( n == toklen && !memcmp( p, tok, toklen ) )
- { /* found it */
- gcry_sexp_t newlist;
- byte *d;
- int level = 1;
-
- /* Look for the end of the list. */
- for ( p += n; level; p++ )
- {
- if ( *p == ST_DATA )
- {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--; /* Compensate for later increment. */
- }
- else if ( *p == ST_OPEN )
- {
- level++;
- }
- else if ( *p == ST_CLOSE )
- {
- level--;
- }
- else if ( *p == ST_STOP )
- {
- BUG ();
- }
- }
- n = p - head;
-
- newlist = gcry_malloc ( sizeof *newlist + n );
- if (!newlist)
- {
- /* No way to return an error code, so we can only
- return Not Found. */
- return NULL;
- }
- d = newlist->d;
- memcpy ( d, head, n ); d += n;
- *d++ = ST_STOP;
- return normalize ( newlist );
- }
- p += n;
- }
- else if ( *p == ST_DATA )
- {
- memcpy ( &n, ++p, sizeof n ); p += sizeof n;
- p += n;
- }
- else
- p++;
- }
- return NULL;
-}
-
-/****************
- * Return the length of the given list
- */
-int
-gcry_sexp_length( const gcry_sexp_t list )
-{
- const byte *p;
- DATALEN n;
- int type;
- int length = 0;
- int level = 0;
-
- if ( !list )
- return 0;
-
- p = list->d;
- while ( (type=*p) != ST_STOP ) {
- p++;
- if ( type == ST_DATA ) {
- memcpy ( &n, p, sizeof n );
- p += sizeof n + n;
- if ( level == 1 )
- length++;
- }
- else if ( type == ST_OPEN ) {
- if ( level == 1 )
- length++;
- level++;
- }
- else if ( type == ST_CLOSE ) {
- level--;
- }
- }
- return length;
-}
-
-
-/* Return the internal lengths offset of LIST. That is the size of
- the buffer from the first ST_OPEN, which is retruned at R_OFF, to
- the corresponding ST_CLOSE inclusive. */
-static size_t
-get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
-{
- const unsigned char *p;
- DATALEN n;
- int type;
- int level = 0;
-
- *r_off = 0;
- if (list)
- {
- p = list->d;
- while ( (type=*p) != ST_STOP )
- {
- p++;
- if (type == ST_DATA)
- {
- memcpy (&n, p, sizeof n);
- p += sizeof n + n;
- }
- else if (type == ST_OPEN)
- {
- if (!level)
- *r_off = (p-1) - list->d;
- level++;
- }
- else if ( type == ST_CLOSE )
- {
- level--;
- if (!level)
- return p - list->d;
- }
- }
- }
- return 0; /* Not a proper list. */
-}
-
-
-
-/* Extract the CAR of the given list. May return NULL for bad lists
- or memory failure. */
-gcry_sexp_t
-gcry_sexp_nth( const gcry_sexp_t list, int number )
-{
- const byte *p;
- DATALEN n;
- gcry_sexp_t newlist;
- byte *d;
- int level = 0;
-
- if ( !list || list->d[0] != ST_OPEN )
- return NULL;
- p = list->d;
-
- while ( number > 0 ) {
- p++;
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_OPEN ) {
- level++;
- }
- else if ( *p == ST_CLOSE ) {
- level--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_STOP ) {
- return NULL;
- }
- }
- p++;
-
- if ( *p == ST_DATA ) {
- memcpy ( &n, p, sizeof n ); p += sizeof n;
- newlist = gcry_malloc ( sizeof *newlist + n + 1 );
- if (!newlist)
- return NULL;
- d = newlist->d;
- memcpy ( d, p, n ); d += n;
- *d++ = ST_STOP;
- }
- else if ( *p == ST_OPEN ) {
- const byte *head = p;
-
- level = 1;
- do {
- p++;
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- }
- else if ( *p == ST_OPEN ) {
- level++;
- }
- else if ( *p == ST_CLOSE ) {
- level--;
- }
- else if ( *p == ST_STOP ) {
- BUG ();
- }
- } while ( level );
- n = p + 1 - head;
-
- newlist = gcry_malloc ( sizeof *newlist + n );
- if (!newlist)
- return NULL;
- d = newlist->d;
- memcpy ( d, head, n ); d += n;
- *d++ = ST_STOP;
- }
- else
- newlist = NULL;
-
- return normalize (newlist);
-}
-
-gcry_sexp_t
-gcry_sexp_car( const gcry_sexp_t list )
-{
- return gcry_sexp_nth ( list, 0 );
-}
-
-
-/* Helper to get data from the car. The returned value is valid as
- long as the list is not modified. */
-static const char *
-sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
-{
- const byte *p;
- DATALEN n;
- int level = 0;
-
- *datalen = 0;
- if ( !list )
- return NULL;
-
- p = list->d;
- if ( *p == ST_OPEN )
- p++; /* Yep, a list. */
- else if (number)
- return NULL; /* Not a list but N > 0 requested. */
-
- /* Skip over N elements. */
- while ( number > 0 )
- {
- if ( *p == ST_DATA )
- {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_OPEN )
- {
- level++;
- }
- else if ( *p == ST_CLOSE )
- {
- level--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_STOP )
- {
- return NULL;
- }
- p++;
- }
-
- /* If this is data, return it. */
- if ( *p == ST_DATA )
- {
- memcpy ( &n, ++p, sizeof n );
- *datalen = n;
- return (const char*)p + sizeof n;
- }
-
- return NULL;
-}
-
-
-/* Get data from the car. The returned value is valid as long as the
- list is not modified. */
-const char *
-gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
-{
- return sexp_nth_data (list, number, datalen);
-}
-
-
-/* Get a string from the car. The returned value is a malloced string
- and needs to be freed by the caller. */
-char *
-gcry_sexp_nth_string (const gcry_sexp_t list, int number)
-{
- const char *s;
- size_t n;
- char *buf;
-
- s = sexp_nth_data (list, number, &n);
- if (!s || n < 1 || (n+1) < 1)
- return NULL;
- buf = gcry_malloc (n+1);
- if (!buf)
- return NULL;
- memcpy (buf, s, n);
- buf[n] = 0;
- return buf;
-}
-
-/*
- * Get a MPI from the car
- */
-gcry_mpi_t
-gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
-{
- const char *s;
- size_t n;
- gcry_mpi_t a;
-
- if ( !mpifmt )
- mpifmt = GCRYMPI_FMT_STD;
-
- s = sexp_nth_data (list, number, &n);
- if (!s)
- return NULL;
-
- if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) )
- return NULL;
-
- return a;
-}
-
-
-/****************
- * Get the CDR
- */
-gcry_sexp_t
-gcry_sexp_cdr( const gcry_sexp_t list )
-{
- const byte *p;
- const byte *head;
- DATALEN n;
- gcry_sexp_t newlist;
- byte *d;
- int level = 0;
- int skip = 1;
-
- if ( !list || list->d[0] != ST_OPEN )
- return NULL;
- p = list->d;
-
- while ( skip > 0 ) {
- p++;
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- if ( !level )
- skip--;
- }
- else if ( *p == ST_OPEN ) {
- level++;
- }
- else if ( *p == ST_CLOSE ) {
- level--;
- if ( !level )
- skip--;
- }
- else if ( *p == ST_STOP ) {
- return NULL;
- }
- }
- p++;
-
- head = p;
- level = 0;
- do {
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- }
- else if ( *p == ST_OPEN ) {
- level++;
- }
- else if ( *p == ST_CLOSE ) {
- level--;
- }
- else if ( *p == ST_STOP ) {
- return NULL;
- }
- p++;
- } while ( level );
- n = p - head;
-
- newlist = gcry_malloc ( sizeof *newlist + n + 2 );
- if (!newlist)
- return NULL;
- d = newlist->d;
- *d++ = ST_OPEN;
- memcpy ( d, head, n ); d += n;
- *d++ = ST_CLOSE;
- *d++ = ST_STOP;
-
- return normalize (newlist);
-}
-
-gcry_sexp_t
-gcry_sexp_cadr ( const gcry_sexp_t list )
-{
- gcry_sexp_t a, b;
-
- a = gcry_sexp_cdr ( list );
- b = gcry_sexp_car ( a );
- gcry_sexp_release ( a );
- return b;
-}
-
-
-
-static int
-hextobyte( const byte *s )
-{
- int c=0;
-
- if( *s >= '0' && *s <= '9' )
- c = 16 * (*s - '0');
- else if( *s >= 'A' && *s <= 'F' )
- c = 16 * (10 + *s - 'A');
- else if( *s >= 'a' && *s <= 'f' ) {
- c = 16 * (10 + *s - 'a');
- }
- s++;
- if( *s >= '0' && *s <= '9' )
- c += *s - '0';
- else if( *s >= 'A' && *s <= 'F' )
- c += 10 + *s - 'A';
- else if( *s >= 'a' && *s <= 'f' ) {
- c += 10 + *s - 'a';
- }
- return c;
-}
-
-struct make_space_ctx {
- gcry_sexp_t sexp;
- size_t allocated;
- byte *pos;
-};
-
-static gpg_err_code_t
-make_space ( struct make_space_ctx *c, size_t n )
-{
- size_t used = c->pos - c->sexp->d;
-
- if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
- {
- gcry_sexp_t newsexp;
- byte *newhead;
- size_t newsize;
-
- newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
- if (newsize <= c->allocated)
- return GPG_ERR_TOO_LARGE;
- newsexp = gcry_realloc ( c->sexp, sizeof *newsexp + newsize - 1);
- if (!newsexp)
- return gpg_err_code_from_errno (errno);
- c->allocated = newsize;
- newhead = newsexp->d;
- c->pos = newhead + used;
- c->sexp = newsexp;
- }
- return 0;
-}
-
-
-/* Unquote STRING of LENGTH and store it into BUF. The surrounding
- quotes are must already be removed from STRING. We assume that the
- quoted string is syntacillay correct. */
-static size_t
-unquote_string (const char *string, size_t length, unsigned char *buf)
-{
- int esc = 0;
- const unsigned char *s = (const unsigned char*)string;
- unsigned char *d = buf;
- size_t n = length;
-
- for (; n; n--, s++)
- {
- if (esc)
- {
- switch (*s)
- {
- case 'b': *d++ = '\b'; break;
- case 't': *d++ = '\t'; break;
- case 'v': *d++ = '\v'; break;
- case 'n': *d++ = '\n'; break;
- case 'f': *d++ = '\f'; break;
- case 'r': *d++ = '\r'; break;
- case '"': *d++ = '\"'; break;
- case '\'': *d++ = '\''; break;
- case '\\': *d++ = '\\'; break;
-
- case '\r': /* ignore CR[,LF] */
- if (n>1 && s[1] == '\n')
- {
- s++; n--;
- }
- esc = 0;
- break;
-
- case '\n': /* ignore LF[,CR] */
- if (n>1 && s[1] == '\r')
- {
- s++; n--;
- }
- break;
-
- case 'x': /* hex value */
- if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
- {
- s++; n--;
- *d++ = xtoi_2 (s);
- s++; n--;
- }
- break;
-
- default:
- if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
- {
- *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
- s += 2;
- n -= 2;
- }
- break;
- }
- esc = 0;
- }
- else if( *s == '\\' )
- esc = 1;
- else
- *d++ = *s;
- }
-
- return d - buf;
-}
-
-/****************
- * Scan the provided buffer and return the S expression in our internal
- * format. Returns a newly allocated expression. If erroff is not NULL and
- * a parsing error has occured, the offset into buffer will be returned.
- * If ARGFLAG is true, the function supports some printf like
- * expressions.
- * These are:
- * %m - MPI
- * %s - string (no autoswitch to secure allocation)
- * %d - integer stored as string (no autoswitch to secure allocation)
- * %b - memory buffer; this takes _two_ arguments: an integer with the
- * length of the buffer and a pointer to the buffer.
- * %S - Copy an gcry_sexp_t here. The S-expression needs to be a
- * regular one, starting with a parenthesis.
- * (no autoswitch to secure allocation)
- * all other format elements are currently not defined and return an error.
- * this includes the "%%" sequence becauce the percent sign is not an
- * allowed character.
- * FIXME: We should find a way to store the secure-MPIs not in the string
- * but as reference to somewhere - this can help us to save huge amounts
- * of secure memory. The problem is, that if only one element is secure, all
- * other elements are automagicaly copied to secure memory too, so the most
- * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
- * regardless whether it is needed or not.
- */
-static gcry_error_t
-sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
- const char *buffer, size_t length, int argflag,
- va_list arg_ptr, void **arg_list)
-{
- gcry_err_code_t err = 0;
- static const char tokenchars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789-./_:*+=";
- const char *p;
- size_t n;
- const char *digptr = NULL;
- const char *quoted = NULL;
- const char *tokenp = NULL;
- const char *hexfmt = NULL;
- const char *base64 = NULL;
- const char *disphint = NULL;
- const char *percent = NULL;
- int hexcount = 0;
- int quoted_esc = 0;
- int datalen = 0;
- size_t dummy_erroff;
- struct make_space_ctx c;
- int arg_counter = 0;
- int level = 0;
-
- if (!erroff)
- erroff = &dummy_erroff;
-
- /* Depending on wether ARG_LIST is non-zero or not, this macro gives
- us the next argument, either from the variable argument list as
- specified by ARG_PTR or from the argument array ARG_LIST. */
-#define ARG_NEXT(storage, type) \
- do \
- { \
- if (!arg_list) \
- storage = va_arg (arg_ptr, type); \
- else \
- storage = *((type *) (arg_list[arg_counter++])); \
- } \
- while (0)
-
- /* The MAKE_SPACE macro is used before each store operation to
- ensure that the buffer is large enough. It requires a global
- context named C and jumps out to the label LEAVE on error! It
- also sets ERROFF using the variables BUFFER and P. */
-#define MAKE_SPACE(n) do { \
- gpg_err_code_t _ms_err = make_space (&c, (n)); \
- if (_ms_err) \
- { \
- err = _ms_err; \
- *erroff = p - buffer; \
- goto leave; \
- } \
- } while (0)
-
- /* The STORE_LEN macro is used to store the length N at buffer P. */
-#define STORE_LEN(p,n) do { \
- DATALEN ashort = (n); \
- memcpy ( (p), &ashort, sizeof(ashort) ); \
- (p) += sizeof (ashort); \
- } while (0)
-
- /* We assume that the internal representation takes less memory than
- the provided one. However, we add space for one extra datalen so
- that the code which does the ST_CLOSE can use MAKE_SPACE */
- c.allocated = length + sizeof(DATALEN);
- if (buffer && length && gcry_is_secure (buffer))
- c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
- else
- c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
- if (!c.sexp)
- {
- err = gpg_err_code_from_errno (errno);
- *erroff = 0;
- goto leave;
- }
- c.pos = c.sexp->d;
-
- for (p = buffer, n = length; n; p++, n--)
- {
- if (tokenp && !hexfmt)
- {
- if (strchr (tokenchars, *p))
- continue;
- else
- {
- datalen = p - tokenp;
- MAKE_SPACE (datalen);
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, datalen);
- memcpy (c.pos, tokenp, datalen);
- c.pos += datalen;
- tokenp = NULL;
- }
- }
-
- if (quoted)
- {
- if (quoted_esc)
- {
- switch (*p)
- {
- case 'b': case 't': case 'v': case 'n': case 'f':
- case 'r': case '"': case '\'': case '\\':
- quoted_esc = 0;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- if (!((n > 2)
- && (p[1] >= '0') && (p[1] <= '7')
- && (p[2] >= '0') && (p[2] <= '7')))
- {
- *erroff = p - buffer;
- /* Invalid octal value. */
- err = GPG_ERR_SEXP_BAD_QUOTATION;
- goto leave;
- }
- p += 2;
- n -= 2;
- quoted_esc = 0;
- break;
-
- case 'x':
- if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
- {
- *erroff = p - buffer;
- /* Invalid hex value. */
- err = GPG_ERR_SEXP_BAD_QUOTATION;
- goto leave;
- }
- p += 2;
- n -= 2;
- quoted_esc = 0;
- break;
-
- case '\r':
- /* ignore CR[,LF] */
- if (n && (p[1] == '\n'))
- {
- p++;
- n--;
- }
- quoted_esc = 0;
- break;
-
- case '\n':
- /* ignore LF[,CR] */
- if (n && (p[1] == '\r'))
- {
- p++;
- n--;
- }
- quoted_esc = 0;
- break;
-
- default:
- *erroff = p - buffer;
- /* Invalid quoted string escape. */
- err = GPG_ERR_SEXP_BAD_QUOTATION;
- goto leave;
- }
- }
- else if (*p == '\\')
- quoted_esc = 1;
- else if (*p == '\"')
- {
- /* Keep it easy - we know that the unquoted string will
- never be larger. */
- unsigned char *save;
- size_t len;
-
- quoted++; /* Skip leading quote. */
- MAKE_SPACE (p - quoted);
- *c.pos++ = ST_DATA;
- save = c.pos;
- STORE_LEN (c.pos, 0); /* Will be fixed up later. */
- len = unquote_string (quoted, p - quoted, c.pos);
- c.pos += len;
- STORE_LEN (save, len);
- quoted = NULL;
- }
- }
- else if (hexfmt)
- {
- if (isxdigit (*p))
- hexcount++;
- else if (*p == '#')
- {
- if ((hexcount & 1))
- {
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
- goto leave;
- }
-
- datalen = hexcount / 2;
- MAKE_SPACE (datalen);
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, datalen);
- for (hexfmt++; hexfmt < p; hexfmt++)
- {
- if (whitespacep (hexfmt))
- continue;
- *c.pos++ = hextobyte ((const unsigned char*)hexfmt);
- hexfmt++;
- }
- hexfmt = NULL;
- }
- else if (!whitespacep (p))
- {
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_BAD_HEX_CHAR;
- goto leave;
- }
- }
- else if (base64)
- {
- if (*p == '|')
- base64 = NULL;
- }
- else if (digptr)
- {
- if (digitp (p))
- ;
- else if (*p == ':')
- {
- datalen = atoi (digptr); /* FIXME: check for overflow. */
- digptr = NULL;
- if (datalen > n - 1)
- {
- *erroff = p - buffer;
- /* Buffer too short. */
- err = GPG_ERR_SEXP_STRING_TOO_LONG;
- goto leave;
- }
- /* Make a new list entry. */
- MAKE_SPACE (datalen);
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, datalen);
- memcpy (c.pos, p + 1, datalen);
- c.pos += datalen;
- n -= datalen;
- p += datalen;
- }
- else if (*p == '\"')
- {
- digptr = NULL; /* We ignore the optional length. */
- quoted = p;
- quoted_esc = 0;
- }
- else if (*p == '#')
- {
- digptr = NULL; /* We ignore the optional length. */
- hexfmt = p;
- hexcount = 0;
- }
- else if (*p == '|')
- {
- digptr = NULL; /* We ignore the optional length. */
- base64 = p;
- }
- else
- {
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_INV_LEN_SPEC;
- goto leave;
- }
- }
- else if (percent)
- {
- if (*p == 'm')
- {
- /* Insert an MPI. */
- gcry_mpi_t m;
- size_t nm = 0;
-
- ARG_NEXT (m, gcry_mpi_t);
-
- if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m))
- BUG ();
-
- MAKE_SPACE (nm);
- if (!gcry_is_secure (c.sexp->d)
- && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
- {
- /* We have to switch to secure allocation. */
- gcry_sexp_t newsexp;
- byte *newhead;
-
- newsexp = gcry_malloc_secure (sizeof *newsexp
- + c.allocated - 1);
- if (!newsexp)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
- newhead = newsexp->d;
- memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
- c.pos = newhead + (c.pos - c.sexp->d);
- gcry_free (c.sexp);
- c.sexp = newsexp;
- }
-
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, nm);
- if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m))
- BUG ();
- c.pos += nm;
- }
- else if (*p == 's')
- {
- /* Insert an string. */
- const char *astr;
- size_t alen;
-
- ARG_NEXT (astr, const char *);
- alen = strlen (astr);
-
- MAKE_SPACE (alen);
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, alen);
- memcpy (c.pos, astr, alen);
- c.pos += alen;
- }
- else if (*p == 'b')
- {
- /* Insert a memory buffer. */
- const char *astr;
- int alen;
-
- ARG_NEXT (alen, int);
- ARG_NEXT (astr, const char *);
-
- MAKE_SPACE (alen);
- if (alen
- && !gcry_is_secure (c.sexp->d)
- && gcry_is_secure (astr))
- {
- /* We have to switch to secure allocation. */
- gcry_sexp_t newsexp;
- byte *newhead;
-
- newsexp = gcry_malloc_secure (sizeof *newsexp
- + c.allocated - 1);
- if (!newsexp)
- {
- err = gpg_err_code_from_errno (errno);
- goto leave;
- }
- newhead = newsexp->d;
- memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
- c.pos = newhead + (c.pos - c.sexp->d);
- gcry_free (c.sexp);
- c.sexp = newsexp;
- }
-
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, alen);
- memcpy (c.pos, astr, alen);
- c.pos += alen;
- }
- else if (*p == 'd')
- {
- /* Insert an integer as string. */
- int aint;
- size_t alen;
- char buf[20];
-
- ARG_NEXT (aint, int);
- sprintf (buf, "%d", aint);
- alen = strlen (buf);
- MAKE_SPACE (alen);
- *c.pos++ = ST_DATA;
- STORE_LEN (c.pos, alen);
- memcpy (c.pos, buf, alen);
- c.pos += alen;
- }
- else if (*p == 'S')
- {
- /* Insert a gcry_sexp_t. */
- gcry_sexp_t asexp;
- size_t alen, aoff;
-
- ARG_NEXT (asexp, gcry_sexp_t);
- alen = get_internal_buffer (asexp, &aoff);
- if (alen)
- {
- MAKE_SPACE (alen);
- memcpy (c.pos, asexp->d + aoff, alen);
- c.pos += alen;
- }
- }
- else
- {
- *erroff = p - buffer;
- /* Invalid format specifier. */
- err = GPG_ERR_SEXP_INV_LEN_SPEC;
- goto leave;
- }
- percent = NULL;
- }
- else if (*p == '(')
- {
- if (disphint)
- {
- *erroff = p - buffer;
- /* Open display hint. */
- err = GPG_ERR_SEXP_UNMATCHED_DH;
- goto leave;
- }
- MAKE_SPACE (0);
- *c.pos++ = ST_OPEN;
- level++;
- }
- else if (*p == ')')
- {
- /* Walk up. */
- if (disphint)
- {
- *erroff = p - buffer;
- /* Open display hint. */
- err = GPG_ERR_SEXP_UNMATCHED_DH;
- goto leave;
- }
- MAKE_SPACE (0);
- *c.pos++ = ST_CLOSE;
- level--;
- }
- else if (*p == '\"')
- {
- quoted = p;
- quoted_esc = 0;
- }
- else if (*p == '#')
- {
- hexfmt = p;
- hexcount = 0;
- }
- else if (*p == '|')
- base64 = p;
- else if (*p == '[')
- {
- if (disphint)
- {
- *erroff = p - buffer;
- /* Open display hint. */
- err = GPG_ERR_SEXP_NESTED_DH;
- goto leave;
- }
- disphint = p;
- }
- else if (*p == ']')
- {
- if (!disphint)
- {
- *erroff = p - buffer;
- /* Open display hint. */
- err = GPG_ERR_SEXP_UNMATCHED_DH;
- goto leave;
- }
- disphint = NULL;
- }
- else if (digitp (p))
- {
- if (*p == '0')
- {
- /* A length may not begin with zero. */
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_ZERO_PREFIX;
- goto leave;
- }
- digptr = p;
- }
- else if (strchr (tokenchars, *p))
- tokenp = p;
- else if (whitespacep (p))
- ;
- else if (*p == '{')
- {
- /* fixme: handle rescanning: we can do this by saving our
- current state and start over at p+1 -- Hmmm. At this
- point here we are in a well defined state, so we don't
- need to save it. Great. */
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
- goto leave;
- }
- else if (strchr ("&\\", *p))
- {
- /* Reserved punctuation. */
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
- goto leave;
- }
- else if (argflag && (*p == '%'))
- percent = p;
- else
- {
- /* Bad or unavailable. */
- *erroff = p - buffer;
- err = GPG_ERR_SEXP_BAD_CHARACTER;
- goto leave;
- }
- }
- MAKE_SPACE (0);
- *c.pos++ = ST_STOP;
-
- if (level && !err)
- err = GPG_ERR_SEXP_UNMATCHED_PAREN;
-
- leave:
- if (err)
- {
- /* Error -> deallocate. */
- if (c.sexp)
- {
- /* Extra paranoid wipe on error. */
- if (gcry_is_secure (c.sexp))
- wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
- gcry_free (c.sexp);
- }
- /* This might be expected by existing code... */
- *retsexp = NULL;
- }
- else
- *retsexp = normalize (c.sexp);
-
- return gcry_error (err);
-#undef MAKE_SPACE
-#undef STORE_LEN
-}
-
-gcry_error_t
-gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
-{
- gcry_error_t rc;
- va_list arg_ptr;
-
- va_start (arg_ptr, format);
- rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
- arg_ptr, NULL);
- va_end (arg_ptr);
-
- return rc;
-}
-
-
-gcry_error_t
-_gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, va_list arg_ptr)
-{
- return sexp_sscan (retsexp, erroff, format, strlen(format), 1,
- arg_ptr, NULL);
-}
-
-/* Like gcry_sexp_build, but uses an array instead of variable
- function arguments. */
-gcry_error_t
-gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
- const char *format, void **arg_list)
-{
- /* We don't need the va_list because it is controlled by the
- following flag, however we have to pass it but can't initialize
- it as there is no portable way to do so. volatile is needed to
- suppress the compiler warning */
- volatile va_list dummy_arg_ptr;
-
- gcry_error_t rc;
-
- rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
- dummy_arg_ptr, arg_list);
-
- return rc;
-}
-
-gcry_error_t
-gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
- const char *buffer, size_t length)
-{
- /* We don't need the va_list because it is controlled by the
- following flag, however we have to pass it but can't initialize
- it as there is no portable way to do so. volatile is needed to
- suppress the compiler warning */
- volatile va_list dummy_arg_ptr;
-
- return sexp_sscan (retsexp, erroff, buffer, length, 0,
- dummy_arg_ptr, NULL);
-}
-
-#pragma runtime_checks("su", restore)
-
-
-/* Figure out a suitable encoding for BUFFER of LENGTH.
- Returns: 0 = Binary
- 1 = String possible
- 2 = Token possible
-*/
-static int
-suitable_encoding (const unsigned char *buffer, size_t length)
-{
- const unsigned char *s;
- int maybe_token = 1;
-
- if (!length)
- return 1;
-
- for (s=buffer; length; s++, length--)
- {
- if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
- && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
- return 0; /*binary*/
- if ( maybe_token
- && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
- maybe_token = 0;
- }
- s = buffer;
- if ( maybe_token && !digitp (s) )
- return 2;
- return 1;
-}
-
-
-static int
-convert_to_hex (const unsigned char *src, size_t len, char *dest)
-{
- int i;
-
- if (dest)
- {
- *dest++ = '#';
- for (i=0; i < len; i++, dest += 2 )
- sprintf (dest, "%02X", src[i]);
- *dest++ = '#';
- }
- return len*2+2;
-}
-
-static int
-convert_to_string (const unsigned char *s, size_t len, char *dest)
-{
- if (dest)
- {
- char *p = dest;
- *p++ = '\"';
- for (; len; len--, s++ )
- {
- switch (*s)
- {
- case '\b': *p++ = '\\'; *p++ = 'b'; break;
- case '\t': *p++ = '\\'; *p++ = 't'; break;
- case '\v': *p++ = '\\'; *p++ = 'v'; break;
- case '\n': *p++ = '\\'; *p++ = 'n'; break;
- case '\f': *p++ = '\\'; *p++ = 'f'; break;
- case '\r': *p++ = '\\'; *p++ = 'r'; break;
- case '\"': *p++ = '\\'; *p++ = '\"'; break;
- case '\'': *p++ = '\\'; *p++ = '\''; break;
- case '\\': *p++ = '\\'; *p++ = '\\'; break;
- default:
- if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
- {
- sprintf (p, "\\x%02x", *s);
- p += 4;
- }
- else
- *p++ = *s;
- }
- }
- *p++ = '\"';
- return p - dest;
- }
- else
- {
- int count = 2;
- for (; len; len--, s++ )
- {
- switch (*s)
- {
- case '\b':
- case '\t':
- case '\v':
- case '\n':
- case '\f':
- case '\r':
- case '\"':
- case '\'':
- case '\\': count += 2; break;
- default:
- if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
- count += 4;
- else
- count++;
- }
- }
- return count;
- }
-}
-
-
-
-static int
-convert_to_token (const unsigned char *src, size_t len, char *dest)
-{
- if (dest)
- memcpy (dest, src, len);
- return len;
-}
-
-
-/****************
- * Print SEXP to buffer using the MODE. Returns the length of the
- * SEXP in buffer or 0 if the buffer is too short (We have at least an
- * empty list consisting of 2 bytes). If a buffer of NULL is provided,
- * the required length is returned.
- */
-size_t
-gcry_sexp_sprint (const gcry_sexp_t list, int mode,
- void *buffer, size_t maxlength )
-{
- static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
- const unsigned char *s;
- char *d;
- DATALEN n;
- char numbuf[20];
- size_t len = 0;
- int i, indent = 0;
-
- s = list? list->d : empty;
- d = buffer;
- while ( *s != ST_STOP )
- {
- switch ( *s )
- {
- case ST_OPEN:
- s++;
- if ( mode != GCRYSEXP_FMT_CANON )
- {
- if (indent)
- len++;
- len += indent;
- }
- len++;
- if ( buffer )
- {
- if ( len >= maxlength )
- return 0;
- if ( mode != GCRYSEXP_FMT_CANON )
- {
- if (indent)
- *d++ = '\n';
- for (i=0; i < indent; i++)
- *d++ = ' ';
- }
- *d++ = '(';
- }
- indent++;
- break;
- case ST_CLOSE:
- s++;
- len++;
- if ( buffer )
- {
- if ( len >= maxlength )
- return 0;
- *d++ = ')';
- }
- indent--;
- if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
- {
- len++;
- len += indent;
- if (buffer)
- {
- if (len >= maxlength)
- return 0;
- *d++ = '\n';
- for (i=0; i < indent; i++)
- *d++ = ' ';
- }
- }
- break;
- case ST_DATA:
- s++;
- memcpy ( &n, s, sizeof n ); s += sizeof n;
- if (mode == GCRYSEXP_FMT_ADVANCED)
- {
- int type;
- size_t nn;
-
- switch ( (type=suitable_encoding (s, n)))
- {
- case 1: nn = convert_to_string (s, n, NULL); break;
- case 2: nn = convert_to_token (s, n, NULL); break;
- default: nn = convert_to_hex (s, n, NULL); break;
- }
- len += nn;
- if (buffer)
- {
- if (len >= maxlength)
- return 0;
- switch (type)
- {
- case 1: convert_to_string (s, n, d); break;
- case 2: convert_to_token (s, n, d); break;
- default: convert_to_hex (s, n, d); break;
- }
- d += nn;
- }
- if (s[n] != ST_CLOSE)
- {
- len++;
- if (buffer)
- {
- if (len >= maxlength)
- return 0;
- *d++ = ' ';
- }
- }
- }
- else
- {
- sprintf (numbuf, "%u:", (unsigned int)n );
- len += strlen (numbuf) + n;
- if ( buffer )
- {
- if ( len >= maxlength )
- return 0;
- d = stpcpy ( d, numbuf );
- memcpy ( d, s, n ); d += n;
- }
- }
- s += n;
- break;
- default:
- BUG ();
- }
- }
- if ( mode != GCRYSEXP_FMT_CANON )
- {
- len++;
- if (buffer)
- {
- if ( len >= maxlength )
- return 0;
- *d++ = '\n';
- }
- }
- if (buffer)
- {
- if ( len >= maxlength )
- return 0;
- *d++ = 0; /* for convenience we make a C string */
- }
- else
- len++; /* we need one byte more for this */
-
- return len;
-}
-
-
-/* Scan a cannocial encoded buffer with implicit length values and
- return the actual length this S-expression uses. For a valid S-Exp
- it should never return 0. If LENGTH is not zero, the maximum
- length to scan is given - this can be used for syntax checks of
- data passed from outside. errorcode and erroff may both be passed as
- NULL. */
-size_t
-gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
- size_t *erroff, gcry_error_t *errcode)
-{
- const unsigned char *p;
- const unsigned char *disphint = NULL;
- unsigned int datalen = 0;
- size_t dummy_erroff;
- gcry_error_t dummy_errcode;
- size_t count = 0;
- int level = 0;
-
- if (!erroff)
- erroff = &dummy_erroff;
- if (!errcode)
- errcode = &dummy_errcode;
-
- *errcode = gcry_error (GPG_ERR_NO_ERROR);
- *erroff = 0;
- if (!buffer)
- return 0;
- if (*buffer != '(')
- {
- *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
- return 0;
- }
-
- for (p=buffer; ; p++, count++ )
- {
- if (length && count >= length)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
- return 0;
- }
-
- if (datalen)
- {
- if (*p == ':')
- {
- if (length && (count+datalen) >= length)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
- return 0;
- }
- count += datalen;
- p += datalen;
- datalen = 0;
- }
- else if (digitp(p))
- datalen = datalen*10 + atoi_1(p);
- else
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
- return 0;
- }
- }
- else if (*p == '(')
- {
- if (disphint)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
- return 0;
- }
- level++;
- }
- else if (*p == ')')
- { /* walk up */
- if (!level)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
- return 0;
- }
- if (disphint)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
- return 0;
- }
- if (!--level)
- return ++count; /* ready */
- }
- else if (*p == '[')
- {
- if (disphint)
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
- return 0;
- }
- disphint = p;
- }
- else if (*p == ']')
- {
- if ( !disphint )
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
- return 0;
- }
- disphint = NULL;
- }
- else if (digitp (p) )
- {
- if (*p == '0')
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
- return 0;
- }
- datalen = atoi_1 (p);
- }
- else if (*p == '&' || *p == '\\')
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
- return 0;
- }
- else
- {
- *erroff = count;
- *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
- return 0;
- }
- }
-}
+/* sexp.c - S-Expression handling
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003,
+ * 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define GCRYPT_NO_MPI_MACROS 1
+#include "g10lib.h"
+
+typedef struct gcry_sexp *NODE;
+typedef unsigned short DATALEN;
+
+struct gcry_sexp
+{
+ byte d[1];
+};
+
+#define ST_STOP 0
+#define ST_DATA 1 /* datalen follows */
+#define ST_HINT 2 /* datalen follows */
+#define ST_OPEN 3
+#define ST_CLOSE 4
+
+/* the atoi macros assume that the buffer has only valid digits */
+#define atoi_1(p) (*(p) - '0' )
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+#define TOKEN_SPECIALS "-./_:*+="
+
+static gcry_error_t
+vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length, int argflag,
+ void **arg_list, va_list arg_ptr);
+
+static gcry_error_t
+sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length, int argflag,
+ void **arg_list, ...);
+
+/* Return true if P points to a byte containing a whitespace according
+ to the S-expressions definition. */
+#undef whitespacep
+static GPG_ERR_INLINE int
+whitespacep (const char *p)
+{
+ switch (*p)
+ {
+ case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
+ default: return 0;
+ }
+}
+
+
+#if 0
+static void
+dump_mpi( gcry_mpi_t a )
+{
+ char buffer[1000];
+ size_t n = 1000;
+
+ if( !a )
+ fputs("[no MPI]", stderr );
+ else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
+ fputs("[MPI too large to print]", stderr );
+ else
+ fputs( buffer, stderr );
+}
+#endif
+
+static void
+dump_string (const byte *p, size_t n, int delim )
+{
+ for (; n; n--, p++ )
+ {
+ if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
+ {
+ if( *p == '\n' )
+ log_printf ("\\n");
+ else if( *p == '\r' )
+ log_printf ("\\r");
+ else if( *p == '\f' )
+ log_printf ("\\f");
+ else if( *p == '\v' )
+ log_printf ("\\v");
+ else if( *p == '\b' )
+ log_printf ("\\b");
+ else if( !*p )
+ log_printf ("\\0");
+ else
+ log_printf ("\\x%02x", *p );
+ }
+ else
+ log_printf ("%c", *p);
+ }
+}
+
+
+void
+gcry_sexp_dump (const gcry_sexp_t a)
+{
+ const byte *p;
+ int indent = 0;
+ int type;
+
+ if (!a)
+ {
+ log_printf ( "[nil]\n");
+ return;
+ }
+
+ p = a->d;
+ while ( (type = *p) != ST_STOP )
+ {
+ p++;
+ switch ( type )
+ {
+ case ST_OPEN:
+ log_printf ("%*s[open]\n", 2*indent, "");
+ indent++;
+ break;
+ case ST_CLOSE:
+ if( indent )
+ indent--;
+ log_printf ("%*s[close]\n", 2*indent, "");
+ break;
+ case ST_DATA: {
+ DATALEN n;
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n;
+ log_printf ("%*s[data=\"", 2*indent, "" );
+ dump_string (p, n, '\"' );
+ log_printf ("\"]\n");
+ p += n;
+ }
+ break;
+ default:
+ log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
+ break;
+ }
+ }
+}
+
+/****************
+ * Pass list through except when it is an empty list - in that case
+ * return NULL and release the passed list.
+ */
+static gcry_sexp_t
+normalize ( gcry_sexp_t list )
+{
+ unsigned char *p;
+
+ if ( !list )
+ return NULL;
+ p = list->d;
+ if ( *p == ST_STOP )
+ {
+ /* this is "" */
+ gcry_sexp_release ( list );
+ return NULL;
+ }
+ if ( *p == ST_OPEN && p[1] == ST_CLOSE )
+ {
+ /* this is "()" */
+ gcry_sexp_release ( list );
+ return NULL;
+ }
+
+ return list;
+}
+
+/* Create a new S-expression object by reading LENGTH bytes from
+ BUFFER, assuming it is canonical encoded or autodetected encoding
+ when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of
+ the buffer is transferred to the newly created object. FREEFNC
+ should be the freefnc used to release BUFFER; there is no guarantee
+ at which point this function is called; most likey you want to use
+ free() or gcry_free().
+
+ Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
+ BUFFER points to a valid canonical encoded S-expression. A LENGTH
+ of 0 and AUTODETECT 1 indicates that buffer points to a
+ null-terminated string.
+
+ This function returns 0 and and the pointer to the new object in
+ RETSEXP or an error code in which case RETSEXP is set to NULL. */
+gcry_error_t
+gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
+ int autodetect, void (*freefnc)(void*) )
+{
+ gcry_error_t errcode;
+ gcry_sexp_t se;
+
+ if (!retsexp)
+ return gcry_error (GPG_ERR_INV_ARG);
+ *retsexp = NULL;
+ if (autodetect < 0 || autodetect > 1 || !buffer)
+ return gcry_error (GPG_ERR_INV_ARG);
+
+ if (!length && !autodetect)
+ { /* What a brave caller to assume that there is really a canonical
+ encoded S-expression in buffer */
+ length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
+ if (!length)
+ return errcode;
+ }
+ else if (!length && autodetect)
+ { /* buffer is a string */
+ length = strlen ((char *)buffer);
+ }
+
+ errcode = sexp_sscan (&se, NULL, buffer, length, 0, NULL);
+ if (errcode)
+ return errcode;
+
+ *retsexp = se;
+ if (freefnc)
+ {
+ /* For now we release the buffer immediately. As soon as we
+ have changed the internal represenation of S-expression to
+ the canoncial format - which has the advantage of faster
+ parsing - we will use this function as a closure in our
+ GCRYSEXP object and use the BUFFER directly. */
+ freefnc (buffer);
+ }
+ return gcry_error (GPG_ERR_NO_ERROR);
+}
+
+/* Same as gcry_sexp_create but don't transfer ownership */
+gcry_error_t
+gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
+ int autodetect)
+{
+ return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
+}
+
+
+/****************
+ * Release resource of the given SEXP object.
+ */
+void
+gcry_sexp_release( gcry_sexp_t sexp )
+{
+ if (sexp)
+ {
+ if (gcry_is_secure (sexp))
+ {
+ /* Extra paranoid wiping. */
+ const byte *p = sexp->d;
+ int type;
+
+ while ( (type = *p) != ST_STOP )
+ {
+ p++;
+ switch ( type )
+ {
+ case ST_OPEN:
+ break;
+ case ST_CLOSE:
+ break;
+ case ST_DATA:
+ {
+ DATALEN n;
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n;
+ p += n;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ wipememory (sexp->d, p - sexp->d);
+ }
+ gcry_free ( sexp );
+ }
+}
+
+
+/****************
+ * Make a pair from lists a and b, don't use a or b later on.
+ * Special behaviour: If one is a single element list we put the
+ * element straight into the new pair.
+ */
+gcry_sexp_t
+gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
+{
+ (void)a;
+ (void)b;
+
+ /* NYI: Implementation should be quite easy with our new data
+ representation */
+ BUG ();
+ return NULL;
+}
+
+
+/****************
+ * Make a list from all items in the array the end of the array is marked
+ * with a NULL.
+ */
+gcry_sexp_t
+gcry_sexp_alist( const gcry_sexp_t *array )
+{
+ (void)array;
+
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
+}
+
+/****************
+ * Make a list from all items, the end of list is indicated by a NULL
+ */
+gcry_sexp_t
+gcry_sexp_vlist( const gcry_sexp_t a, ... )
+{
+ (void)a;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
+}
+
+
+/****************
+ * Append n to the list a
+ * Returns: a new ist (which maybe a)
+ */
+gcry_sexp_t
+gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
+{
+ (void)a;
+ (void)n;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
+}
+
+gcry_sexp_t
+gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
+{
+ (void)a;
+ (void)n;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
+}
+
+
+
+/****************
+ * Locate token in a list. The token must be the car of a sublist.
+ * Returns: A new list with this sublist or NULL if not found.
+ */
+gcry_sexp_t
+gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
+{
+ const byte *p;
+ DATALEN n;
+
+ if ( !list )
+ return NULL;
+
+ if ( !toklen )
+ toklen = strlen(tok);
+
+ p = list->d;
+ while ( *p != ST_STOP )
+ {
+ if ( *p == ST_OPEN && p[1] == ST_DATA )
+ {
+ const byte *head = p;
+
+ p += 2;
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n;
+ if ( n == toklen && !memcmp( p, tok, toklen ) )
+ { /* found it */
+ gcry_sexp_t newlist;
+ byte *d;
+ int level = 1;
+
+ /* Look for the end of the list. */
+ for ( p += n; level; p++ )
+ {
+ if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--; /* Compensate for later increment. */
+ }
+ else if ( *p == ST_OPEN )
+ {
+ level++;
+ }
+ else if ( *p == ST_CLOSE )
+ {
+ level--;
+ }
+ else if ( *p == ST_STOP )
+ {
+ BUG ();
+ }
+ }
+ n = p - head;
+
+ newlist = gcry_malloc ( sizeof *newlist + n );
+ if (!newlist)
+ {
+ /* No way to return an error code, so we can only
+ return Not Found. */
+ return NULL;
+ }
+ d = newlist->d;
+ memcpy ( d, head, n ); d += n;
+ *d++ = ST_STOP;
+ return normalize ( newlist );
+ }
+ p += n;
+ }
+ else if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n ); p += sizeof n;
+ p += n;
+ }
+ else
+ p++;
+ }
+ return NULL;
+}
+
+/****************
+ * Return the length of the given list
+ */
+int
+gcry_sexp_length( const gcry_sexp_t list )
+{
+ const byte *p;
+ DATALEN n;
+ int type;
+ int length = 0;
+ int level = 0;
+
+ if ( !list )
+ return 0;
+
+ p = list->d;
+ while ( (type=*p) != ST_STOP ) {
+ p++;
+ if ( type == ST_DATA ) {
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n + n;
+ if ( level == 1 )
+ length++;
+ }
+ else if ( type == ST_OPEN ) {
+ if ( level == 1 )
+ length++;
+ level++;
+ }
+ else if ( type == ST_CLOSE ) {
+ level--;
+ }
+ }
+ return length;
+}
+
+
+/* Return the internal lengths offset of LIST. That is the size of
+ the buffer from the first ST_OPEN, which is retruned at R_OFF, to
+ the corresponding ST_CLOSE inclusive. */
+static size_t
+get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
+{
+ const unsigned char *p;
+ DATALEN n;
+ int type;
+ int level = 0;
+
+ *r_off = 0;
+ if (list)
+ {
+ p = list->d;
+ while ( (type=*p) != ST_STOP )
+ {
+ p++;
+ if (type == ST_DATA)
+ {
+ memcpy (&n, p, sizeof n);
+ p += sizeof n + n;
+ }
+ else if (type == ST_OPEN)
+ {
+ if (!level)
+ *r_off = (p-1) - list->d;
+ level++;
+ }
+ else if ( type == ST_CLOSE )
+ {
+ level--;
+ if (!level)
+ return p - list->d;
+ }
+ }
+ }
+ return 0; /* Not a proper list. */
+}
+
+
+
+/* Extract the CAR of the given list. May return NULL for bad lists
+ or memory failure. */
+gcry_sexp_t
+gcry_sexp_nth( const gcry_sexp_t list, int number )
+{
+ const byte *p;
+ DATALEN n;
+ gcry_sexp_t newlist;
+ byte *d;
+ int level = 0;
+
+ if ( !list || list->d[0] != ST_OPEN )
+ return NULL;
+ p = list->d;
+
+ while ( number > 0 ) {
+ p++;
+ if ( *p == ST_DATA ) {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ if ( !level )
+ number--;
+ }
+ else if ( *p == ST_OPEN ) {
+ level++;
+ }
+ else if ( *p == ST_CLOSE ) {
+ level--;
+ if ( !level )
+ number--;
+ }
+ else if ( *p == ST_STOP ) {
+ return NULL;
+ }
+ }
+ p++;
+
+ if ( *p == ST_DATA ) {
+ memcpy ( &n, p, sizeof n ); p += sizeof n;
+ newlist = gcry_malloc ( sizeof *newlist + n + 1 );
+ if (!newlist)
+ return NULL;
+ d = newlist->d;
+ memcpy ( d, p, n ); d += n;
+ *d++ = ST_STOP;
+ }
+ else if ( *p == ST_OPEN ) {
+ const byte *head = p;
+
+ level = 1;
+ do {
+ p++;
+ if ( *p == ST_DATA ) {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ }
+ else if ( *p == ST_OPEN ) {
+ level++;
+ }
+ else if ( *p == ST_CLOSE ) {
+ level--;
+ }
+ else if ( *p == ST_STOP ) {
+ BUG ();
+ }
+ } while ( level );
+ n = p + 1 - head;
+
+ newlist = gcry_malloc ( sizeof *newlist + n );
+ if (!newlist)
+ return NULL;
+ d = newlist->d;
+ memcpy ( d, head, n ); d += n;
+ *d++ = ST_STOP;
+ }
+ else
+ newlist = NULL;
+
+ return normalize (newlist);
+}
+
+gcry_sexp_t
+gcry_sexp_car( const gcry_sexp_t list )
+{
+ return gcry_sexp_nth ( list, 0 );
+}
+
+
+/* Helper to get data from the car. The returned value is valid as
+ long as the list is not modified. */
+static const char *
+sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
+{
+ const byte *p;
+ DATALEN n;
+ int level = 0;
+
+ *datalen = 0;
+ if ( !list )
+ return NULL;
+
+ p = list->d;
+ if ( *p == ST_OPEN )
+ p++; /* Yep, a list. */
+ else if (number)
+ return NULL; /* Not a list but N > 0 requested. */
+
+ /* Skip over N elements. */
+ while ( number > 0 )
+ {
+ if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ if ( !level )
+ number--;
+ }
+ else if ( *p == ST_OPEN )
+ {
+ level++;
+ }
+ else if ( *p == ST_CLOSE )
+ {
+ level--;
+ if ( !level )
+ number--;
+ }
+ else if ( *p == ST_STOP )
+ {
+ return NULL;
+ }
+ p++;
+ }
+
+ /* If this is data, return it. */
+ if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n );
+ *datalen = n;
+ return (const char*)p + sizeof n;
+ }
+
+ return NULL;
+}
+
+
+/* Get data from the car. The returned value is valid as long as the
+ list is not modified. */
+const char *
+gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
+{
+ return sexp_nth_data (list, number, datalen);
+}
+
+
+/* Get a string from the car. The returned value is a malloced string
+ and needs to be freed by the caller. */
+char *
+gcry_sexp_nth_string (const gcry_sexp_t list, int number)
+{
+ const char *s;
+ size_t n;
+ char *buf;
+
+ s = sexp_nth_data (list, number, &n);
+ if (!s || n < 1 || (n+1) < 1)
+ return NULL;
+ buf = gcry_malloc (n+1);
+ if (!buf)
+ return NULL;
+ memcpy (buf, s, n);
+ buf[n] = 0;
+ return buf;
+}
+
+/*
+ * Get a MPI from the car
+ */
+gcry_mpi_t
+gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
+{
+ const char *s;
+ size_t n;
+ gcry_mpi_t a;
+
+ if ( !mpifmt )
+ mpifmt = GCRYMPI_FMT_STD;
+
+ s = sexp_nth_data (list, number, &n);
+ if (!s)
+ return NULL;
+
+ if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) )
+ return NULL;
+
+ return a;
+}
+
+
+/****************
+ * Get the CDR
+ */
+gcry_sexp_t
+gcry_sexp_cdr( const gcry_sexp_t list )
+{
+ const byte *p;
+ const byte *head;
+ DATALEN n;
+ gcry_sexp_t newlist;
+ byte *d;
+ int level = 0;
+ int skip = 1;
+
+ if ( !list || list->d[0] != ST_OPEN )
+ return NULL;
+ p = list->d;
+
+ while ( skip > 0 ) {
+ p++;
+ if ( *p == ST_DATA ) {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ if ( !level )
+ skip--;
+ }
+ else if ( *p == ST_OPEN ) {
+ level++;
+ }
+ else if ( *p == ST_CLOSE ) {
+ level--;
+ if ( !level )
+ skip--;
+ }
+ else if ( *p == ST_STOP ) {
+ return NULL;
+ }
+ }
+ p++;
+
+ head = p;
+ level = 0;
+ do {
+ if ( *p == ST_DATA ) {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ }
+ else if ( *p == ST_OPEN ) {
+ level++;
+ }
+ else if ( *p == ST_CLOSE ) {
+ level--;
+ }
+ else if ( *p == ST_STOP ) {
+ return NULL;
+ }
+ p++;
+ } while ( level );
+ n = p - head;
+
+ newlist = gcry_malloc ( sizeof *newlist + n + 2 );
+ if (!newlist)
+ return NULL;
+ d = newlist->d;
+ *d++ = ST_OPEN;
+ memcpy ( d, head, n ); d += n;
+ *d++ = ST_CLOSE;
+ *d++ = ST_STOP;
+
+ return normalize (newlist);
+}
+
+gcry_sexp_t
+gcry_sexp_cadr ( const gcry_sexp_t list )
+{
+ gcry_sexp_t a, b;
+
+ a = gcry_sexp_cdr ( list );
+ b = gcry_sexp_car ( a );
+ gcry_sexp_release ( a );
+ return b;
+}
+
+
+
+static int
+hextobyte( const byte *s )
+{
+ int c=0;
+
+ if( *s >= '0' && *s <= '9' )
+ c = 16 * (*s - '0');
+ else if( *s >= 'A' && *s <= 'F' )
+ c = 16 * (10 + *s - 'A');
+ else if( *s >= 'a' && *s <= 'f' ) {
+ c = 16 * (10 + *s - 'a');
+ }
+ s++;
+ if( *s >= '0' && *s <= '9' )
+ c += *s - '0';
+ else if( *s >= 'A' && *s <= 'F' )
+ c += 10 + *s - 'A';
+ else if( *s >= 'a' && *s <= 'f' ) {
+ c += 10 + *s - 'a';
+ }
+ return c;
+}
+
+struct make_space_ctx {
+ gcry_sexp_t sexp;
+ size_t allocated;
+ byte *pos;
+};
+
+static gpg_err_code_t
+make_space ( struct make_space_ctx *c, size_t n )
+{
+ size_t used = c->pos - c->sexp->d;
+
+ if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
+ {
+ gcry_sexp_t newsexp;
+ byte *newhead;
+ size_t newsize;
+
+ newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
+ if (newsize <= c->allocated)
+ return GPG_ERR_TOO_LARGE;
+ newsexp = gcry_realloc ( c->sexp, sizeof *newsexp + newsize - 1);
+ if (!newsexp)
+ return gpg_err_code_from_errno (errno);
+ c->allocated = newsize;
+ newhead = newsexp->d;
+ c->pos = newhead + used;
+ c->sexp = newsexp;
+ }
+ return 0;
+}
+
+
+/* Unquote STRING of LENGTH and store it into BUF. The surrounding
+ quotes are must already be removed from STRING. We assume that the
+ quoted string is syntacillay correct. */
+static size_t
+unquote_string (const char *string, size_t length, unsigned char *buf)
+{
+ int esc = 0;
+ const unsigned char *s = (const unsigned char*)string;
+ unsigned char *d = buf;
+ size_t n = length;
+
+ for (; n; n--, s++)
+ {
+ if (esc)
+ {
+ switch (*s)
+ {
+ case 'b': *d++ = '\b'; break;
+ case 't': *d++ = '\t'; break;
+ case 'v': *d++ = '\v'; break;
+ case 'n': *d++ = '\n'; break;
+ case 'f': *d++ = '\f'; break;
+ case 'r': *d++ = '\r'; break;
+ case '"': *d++ = '\"'; break;
+ case '\'': *d++ = '\''; break;
+ case '\\': *d++ = '\\'; break;
+
+ case '\r': /* ignore CR[,LF] */
+ if (n>1 && s[1] == '\n')
+ {
+ s++; n--;
+ }
+ break;
+
+ case '\n': /* ignore LF[,CR] */
+ if (n>1 && s[1] == '\r')
+ {
+ s++; n--;
+ }
+ break;
+
+ case 'x': /* hex value */
+ if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
+ {
+ s++; n--;
+ *d++ = xtoi_2 (s);
+ s++; n--;
+ }
+ break;
+
+ default:
+ if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
+ {
+ *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
+ s += 2;
+ n -= 2;
+ }
+ break;
+ }
+ esc = 0;
+ }
+ else if( *s == '\\' )
+ esc = 1;
+ else
+ *d++ = *s;
+ }
+
+ return d - buf;
+}
+
+/****************
+ * Scan the provided buffer and return the S expression in our internal
+ * format. Returns a newly allocated expression. If erroff is not NULL and
+ * a parsing error has occurred, the offset into buffer will be returned.
+ * If ARGFLAG is true, the function supports some printf like
+ * expressions.
+ * These are:
+ * %m - MPI
+ * %s - string (no autoswitch to secure allocation)
+ * %d - integer stored as string (no autoswitch to secure allocation)
+ * %b - memory buffer; this takes _two_ arguments: an integer with the
+ * length of the buffer and a pointer to the buffer.
+ * %S - Copy an gcry_sexp_t here. The S-expression needs to be a
+ * regular one, starting with a parenthesis.
+ * (no autoswitch to secure allocation)
+ * all other format elements are currently not defined and return an error.
+ * this includes the "%%" sequence becauce the percent sign is not an
+ * allowed character.
+ * FIXME: We should find a way to store the secure-MPIs not in the string
+ * but as reference to somewhere - this can help us to save huge amounts
+ * of secure memory. The problem is, that if only one element is secure, all
+ * other elements are automagicaly copied to secure memory too, so the most
+ * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
+ * regardless whether it is needed or not.
+ */
+static gcry_error_t
+vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length, int argflag,
+ void **arg_list, va_list arg_ptr)
+{
+ gcry_err_code_t err = 0;
+ static const char tokenchars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789-./_:*+=";
+ const char *p;
+ size_t n;
+ const char *digptr = NULL;
+ const char *quoted = NULL;
+ const char *tokenp = NULL;
+ const char *hexfmt = NULL;
+ const char *base64 = NULL;
+ const char *disphint = NULL;
+ const char *percent = NULL;
+ int hexcount = 0;
+ int quoted_esc = 0;
+ int datalen = 0;
+ size_t dummy_erroff;
+ struct make_space_ctx c;
+ int arg_counter = 0;
+ int level = 0;
+
+ if (!erroff)
+ erroff = &dummy_erroff;
+
+ /* Depending on whether ARG_LIST is non-zero or not, this macro gives
+ us the next argument, either from the variable argument list as
+ specified by ARG_PTR or from the argument array ARG_LIST. */
+#define ARG_NEXT(storage, type) \
+ do \
+ { \
+ if (!arg_list) \
+ storage = va_arg (arg_ptr, type); \
+ else \
+ storage = *((type *) (arg_list[arg_counter++])); \
+ } \
+ while (0)
+
+ /* The MAKE_SPACE macro is used before each store operation to
+ ensure that the buffer is large enough. It requires a global
+ context named C and jumps out to the label LEAVE on error! It
+ also sets ERROFF using the variables BUFFER and P. */
+#define MAKE_SPACE(n) do { \
+ gpg_err_code_t _ms_err = make_space (&c, (n)); \
+ if (_ms_err) \
+ { \
+ err = _ms_err; \
+ *erroff = p - buffer; \
+ goto leave; \
+ } \
+ } while (0)
+
+ /* The STORE_LEN macro is used to store the length N at buffer P. */
+#define STORE_LEN(p,n) do { \
+ DATALEN ashort = (n); \
+ memcpy ( (p), &ashort, sizeof(ashort) ); \
+ (p) += sizeof (ashort); \
+ } while (0)
+
+ /* We assume that the internal representation takes less memory than
+ the provided one. However, we add space for one extra datalen so
+ that the code which does the ST_CLOSE can use MAKE_SPACE */
+ c.allocated = length + sizeof(DATALEN);
+ if (buffer && length && gcry_is_secure (buffer))
+ c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
+ else
+ c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
+ if (!c.sexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ *erroff = 0;
+ goto leave;
+ }
+ c.pos = c.sexp->d;
+
+ for (p = buffer, n = length; n; p++, n--)
+ {
+ if (tokenp && !hexfmt)
+ {
+ if (strchr (tokenchars, *p))
+ continue;
+ else
+ {
+ datalen = p - tokenp;
+ MAKE_SPACE (datalen);
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, datalen);
+ memcpy (c.pos, tokenp, datalen);
+ c.pos += datalen;
+ tokenp = NULL;
+ }
+ }
+
+ if (quoted)
+ {
+ if (quoted_esc)
+ {
+ switch (*p)
+ {
+ case 'b': case 't': case 'v': case 'n': case 'f':
+ case 'r': case '"': case '\'': case '\\':
+ quoted_esc = 0;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7':
+ if (!((n > 2)
+ && (p[1] >= '0') && (p[1] <= '7')
+ && (p[2] >= '0') && (p[2] <= '7')))
+ {
+ *erroff = p - buffer;
+ /* Invalid octal value. */
+ err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
+ }
+ p += 2;
+ n -= 2;
+ quoted_esc = 0;
+ break;
+
+ case 'x':
+ if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
+ {
+ *erroff = p - buffer;
+ /* Invalid hex value. */
+ err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
+ }
+ p += 2;
+ n -= 2;
+ quoted_esc = 0;
+ break;
+
+ case '\r':
+ /* ignore CR[,LF] */
+ if (n && (p[1] == '\n'))
+ {
+ p++;
+ n--;
+ }
+ quoted_esc = 0;
+ break;
+
+ case '\n':
+ /* ignore LF[,CR] */
+ if (n && (p[1] == '\r'))
+ {
+ p++;
+ n--;
+ }
+ quoted_esc = 0;
+ break;
+
+ default:
+ *erroff = p - buffer;
+ /* Invalid quoted string escape. */
+ err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
+ }
+ }
+ else if (*p == '\\')
+ quoted_esc = 1;
+ else if (*p == '\"')
+ {
+ /* Keep it easy - we know that the unquoted string will
+ never be larger. */
+ unsigned char *save;
+ size_t len;
+
+ quoted++; /* Skip leading quote. */
+ MAKE_SPACE (p - quoted);
+ *c.pos++ = ST_DATA;
+ save = c.pos;
+ STORE_LEN (c.pos, 0); /* Will be fixed up later. */
+ len = unquote_string (quoted, p - quoted, c.pos);
+ c.pos += len;
+ STORE_LEN (save, len);
+ quoted = NULL;
+ }
+ }
+ else if (hexfmt)
+ {
+ if (isxdigit (*p))
+ hexcount++;
+ else if (*p == '#')
+ {
+ if ((hexcount & 1))
+ {
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
+ goto leave;
+ }
+
+ datalen = hexcount / 2;
+ MAKE_SPACE (datalen);
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, datalen);
+ for (hexfmt++; hexfmt < p; hexfmt++)
+ {
+ if (whitespacep (hexfmt))
+ continue;
+ *c.pos++ = hextobyte ((const unsigned char*)hexfmt);
+ hexfmt++;
+ }
+ hexfmt = NULL;
+ }
+ else if (!whitespacep (p))
+ {
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_BAD_HEX_CHAR;
+ goto leave;
+ }
+ }
+ else if (base64)
+ {
+ if (*p == '|')
+ base64 = NULL;
+ }
+ else if (digptr)
+ {
+ if (digitp (p))
+ ;
+ else if (*p == ':')
+ {
+ datalen = atoi (digptr); /* FIXME: check for overflow. */
+ digptr = NULL;
+ if (datalen > n - 1)
+ {
+ *erroff = p - buffer;
+ /* Buffer too short. */
+ err = GPG_ERR_SEXP_STRING_TOO_LONG;
+ goto leave;
+ }
+ /* Make a new list entry. */
+ MAKE_SPACE (datalen);
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, datalen);
+ memcpy (c.pos, p + 1, datalen);
+ c.pos += datalen;
+ n -= datalen;
+ p += datalen;
+ }
+ else if (*p == '\"')
+ {
+ digptr = NULL; /* We ignore the optional length. */
+ quoted = p;
+ quoted_esc = 0;
+ }
+ else if (*p == '#')
+ {
+ digptr = NULL; /* We ignore the optional length. */
+ hexfmt = p;
+ hexcount = 0;
+ }
+ else if (*p == '|')
+ {
+ digptr = NULL; /* We ignore the optional length. */
+ base64 = p;
+ }
+ else
+ {
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_INV_LEN_SPEC;
+ goto leave;
+ }
+ }
+ else if (percent)
+ {
+ if (*p == 'm')
+ {
+ /* Insert an MPI. */
+ gcry_mpi_t m;
+ size_t nm = 0;
+
+ ARG_NEXT (m, gcry_mpi_t);
+
+ if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m))
+ BUG ();
+
+ MAKE_SPACE (nm);
+ if (!gcry_is_secure (c.sexp->d)
+ && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
+ {
+ /* We have to switch to secure allocation. */
+ gcry_sexp_t newsexp;
+ byte *newhead;
+
+ newsexp = gcry_malloc_secure (sizeof *newsexp
+ + c.allocated - 1);
+ if (!newsexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ newhead = newsexp->d;
+ memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
+ c.pos = newhead + (c.pos - c.sexp->d);
+ gcry_free (c.sexp);
+ c.sexp = newsexp;
+ }
+
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, nm);
+ if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m))
+ BUG ();
+ c.pos += nm;
+ }
+ else if (*p == 's')
+ {
+ /* Insert an string. */
+ const char *astr;
+ size_t alen;
+
+ ARG_NEXT (astr, const char *);
+ alen = strlen (astr);
+
+ MAKE_SPACE (alen);
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, alen);
+ memcpy (c.pos, astr, alen);
+ c.pos += alen;
+ }
+ else if (*p == 'b')
+ {
+ /* Insert a memory buffer. */
+ const char *astr;
+ int alen;
+
+ ARG_NEXT (alen, int);
+ ARG_NEXT (astr, const char *);
+
+ MAKE_SPACE (alen);
+ if (alen
+ && !gcry_is_secure (c.sexp->d)
+ && gcry_is_secure (astr))
+ {
+ /* We have to switch to secure allocation. */
+ gcry_sexp_t newsexp;
+ byte *newhead;
+
+ newsexp = gcry_malloc_secure (sizeof *newsexp
+ + c.allocated - 1);
+ if (!newsexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
+ newhead = newsexp->d;
+ memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
+ c.pos = newhead + (c.pos - c.sexp->d);
+ gcry_free (c.sexp);
+ c.sexp = newsexp;
+ }
+
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, alen);
+ memcpy (c.pos, astr, alen);
+ c.pos += alen;
+ }
+ else if (*p == 'd')
+ {
+ /* Insert an integer as string. */
+ int aint;
+ size_t alen;
+ char buf[20];
+
+ ARG_NEXT (aint, int);
+ sprintf (buf, "%d", aint);
+ alen = strlen (buf);
+ MAKE_SPACE (alen);
+ *c.pos++ = ST_DATA;
+ STORE_LEN (c.pos, alen);
+ memcpy (c.pos, buf, alen);
+ c.pos += alen;
+ }
+ else if (*p == 'S')
+ {
+ /* Insert a gcry_sexp_t. */
+ gcry_sexp_t asexp;
+ size_t alen, aoff;
+
+ ARG_NEXT (asexp, gcry_sexp_t);
+ alen = get_internal_buffer (asexp, &aoff);
+ if (alen)
+ {
+ MAKE_SPACE (alen);
+ memcpy (c.pos, asexp->d + aoff, alen);
+ c.pos += alen;
+ }
+ }
+ else
+ {
+ *erroff = p - buffer;
+ /* Invalid format specifier. */
+ err = GPG_ERR_SEXP_INV_LEN_SPEC;
+ goto leave;
+ }
+ percent = NULL;
+ }
+ else if (*p == '(')
+ {
+ if (disphint)
+ {
+ *erroff = p - buffer;
+ /* Open display hint. */
+ err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
+ }
+ MAKE_SPACE (0);
+ *c.pos++ = ST_OPEN;
+ level++;
+ }
+ else if (*p == ')')
+ {
+ /* Walk up. */
+ if (disphint)
+ {
+ *erroff = p - buffer;
+ /* Open display hint. */
+ err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
+ }
+ MAKE_SPACE (0);
+ *c.pos++ = ST_CLOSE;
+ level--;
+ }
+ else if (*p == '\"')
+ {
+ quoted = p;
+ quoted_esc = 0;
+ }
+ else if (*p == '#')
+ {
+ hexfmt = p;
+ hexcount = 0;
+ }
+ else if (*p == '|')
+ base64 = p;
+ else if (*p == '[')
+ {
+ if (disphint)
+ {
+ *erroff = p - buffer;
+ /* Open display hint. */
+ err = GPG_ERR_SEXP_NESTED_DH;
+ goto leave;
+ }
+ disphint = p;
+ }
+ else if (*p == ']')
+ {
+ if (!disphint)
+ {
+ *erroff = p - buffer;
+ /* Open display hint. */
+ err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
+ }
+ disphint = NULL;
+ }
+ else if (digitp (p))
+ {
+ if (*p == '0')
+ {
+ /* A length may not begin with zero. */
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_ZERO_PREFIX;
+ goto leave;
+ }
+ digptr = p;
+ }
+ else if (strchr (tokenchars, *p))
+ tokenp = p;
+ else if (whitespacep (p))
+ ;
+ else if (*p == '{')
+ {
+ /* fixme: handle rescanning: we can do this by saving our
+ current state and start over at p+1 -- Hmmm. At this
+ point here we are in a well defined state, so we don't
+ need to save it. Great. */
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
+ goto leave;
+ }
+ else if (strchr ("&\\", *p))
+ {
+ /* Reserved punctuation. */
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
+ goto leave;
+ }
+ else if (argflag && (*p == '%'))
+ percent = p;
+ else
+ {
+ /* Bad or unavailable. */
+ *erroff = p - buffer;
+ err = GPG_ERR_SEXP_BAD_CHARACTER;
+ goto leave;
+ }
+ }
+ MAKE_SPACE (0);
+ *c.pos++ = ST_STOP;
+
+ if (level && !err)
+ err = GPG_ERR_SEXP_UNMATCHED_PAREN;
+
+ leave:
+ if (err)
+ {
+ /* Error -> deallocate. */
+ if (c.sexp)
+ {
+ /* Extra paranoid wipe on error. */
+ if (gcry_is_secure (c.sexp))
+ wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
+ gcry_free (c.sexp);
+ }
+ /* This might be expected by existing code... */
+ *retsexp = NULL;
+ }
+ else
+ *retsexp = normalize (c.sexp);
+
+ return gcry_error (err);
+#undef MAKE_SPACE
+#undef STORE_LEN
+}
+
+
+static gcry_error_t
+sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length, int argflag,
+ void **arg_list, ...)
+{
+ gcry_error_t rc;
+ va_list arg_ptr;
+
+ va_start (arg_ptr, arg_list);
+ rc = vsexp_sscan (retsexp, erroff, buffer, length, argflag,
+ arg_list, arg_ptr);
+ va_end (arg_ptr);
+
+ return rc;
+}
+
+
+gcry_error_t
+gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
+{
+ gcry_error_t rc;
+ va_list arg_ptr;
+
+ va_start (arg_ptr, format);
+ rc = vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
+ NULL, arg_ptr);
+ va_end (arg_ptr);
+
+ return rc;
+}
+
+
+gcry_error_t
+_gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *format, va_list arg_ptr)
+{
+ return vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
+ NULL, arg_ptr);
+}
+
+
+/* Like gcry_sexp_build, but uses an array instead of variable
+ function arguments. */
+gcry_error_t
+gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *format, void **arg_list)
+{
+ return sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
+}
+
+
+gcry_error_t
+gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+ const char *buffer, size_t length)
+{
+ return sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
+}
+
+
+/* Figure out a suitable encoding for BUFFER of LENGTH.
+ Returns: 0 = Binary
+ 1 = String possible
+ 2 = Token possible
+*/
+static int
+suitable_encoding (const unsigned char *buffer, size_t length)
+{
+ const unsigned char *s;
+ int maybe_token = 1;
+
+ if (!length)
+ return 1;
+
+ for (s=buffer; length; s++, length--)
+ {
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
+ && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
+ return 0; /*binary*/
+ if ( maybe_token
+ && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
+ maybe_token = 0;
+ }
+ s = buffer;
+ if ( maybe_token && !digitp (s) )
+ return 2;
+ return 1;
+}
+
+
+static int
+convert_to_hex (const unsigned char *src, size_t len, char *dest)
+{
+ int i;
+
+ if (dest)
+ {
+ *dest++ = '#';
+ for (i=0; i < len; i++, dest += 2 )
+ sprintf (dest, "%02X", src[i]);
+ *dest++ = '#';
+ }
+ return len*2+2;
+}
+
+static int
+convert_to_string (const unsigned char *s, size_t len, char *dest)
+{
+ if (dest)
+ {
+ char *p = dest;
+ *p++ = '\"';
+ for (; len; len--, s++ )
+ {
+ switch (*s)
+ {
+ case '\b': *p++ = '\\'; *p++ = 'b'; break;
+ case '\t': *p++ = '\\'; *p++ = 't'; break;
+ case '\v': *p++ = '\\'; *p++ = 'v'; break;
+ case '\n': *p++ = '\\'; *p++ = 'n'; break;
+ case '\f': *p++ = '\\'; *p++ = 'f'; break;
+ case '\r': *p++ = '\\'; *p++ = 'r'; break;
+ case '\"': *p++ = '\\'; *p++ = '\"'; break;
+ case '\'': *p++ = '\\'; *p++ = '\''; break;
+ case '\\': *p++ = '\\'; *p++ = '\\'; break;
+ default:
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
+ {
+ sprintf (p, "\\x%02x", *s);
+ p += 4;
+ }
+ else
+ *p++ = *s;
+ }
+ }
+ *p++ = '\"';
+ return p - dest;
+ }
+ else
+ {
+ int count = 2;
+ for (; len; len--, s++ )
+ {
+ switch (*s)
+ {
+ case '\b':
+ case '\t':
+ case '\v':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\"':
+ case '\'':
+ case '\\': count += 2; break;
+ default:
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
+ count += 4;
+ else
+ count++;
+ }
+ }
+ return count;
+ }
+}
+
+
+
+static int
+convert_to_token (const unsigned char *src, size_t len, char *dest)
+{
+ if (dest)
+ memcpy (dest, src, len);
+ return len;
+}
+
+
+/****************
+ * Print SEXP to buffer using the MODE. Returns the length of the
+ * SEXP in buffer or 0 if the buffer is too short (We have at least an
+ * empty list consisting of 2 bytes). If a buffer of NULL is provided,
+ * the required length is returned.
+ */
+size_t
+gcry_sexp_sprint (const gcry_sexp_t list, int mode,
+ void *buffer, size_t maxlength )
+{
+ static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
+ const unsigned char *s;
+ char *d;
+ DATALEN n;
+ char numbuf[20];
+ size_t len = 0;
+ int i, indent = 0;
+
+ s = list? list->d : empty;
+ d = buffer;
+ while ( *s != ST_STOP )
+ {
+ switch ( *s )
+ {
+ case ST_OPEN:
+ s++;
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ if (indent)
+ len++;
+ len += indent;
+ }
+ len++;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
+ return 0;
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ if (indent)
+ *d++ = '\n';
+ for (i=0; i < indent; i++)
+ *d++ = ' ';
+ }
+ *d++ = '(';
+ }
+ indent++;
+ break;
+ case ST_CLOSE:
+ s++;
+ len++;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = ')';
+ }
+ indent--;
+ if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
+ {
+ len++;
+ len += indent;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ *d++ = '\n';
+ for (i=0; i < indent; i++)
+ *d++ = ' ';
+ }
+ }
+ break;
+ case ST_DATA:
+ s++;
+ memcpy ( &n, s, sizeof n ); s += sizeof n;
+ if (mode == GCRYSEXP_FMT_ADVANCED)
+ {
+ int type;
+ size_t nn;
+
+ switch ( (type=suitable_encoding (s, n)))
+ {
+ case 1: nn = convert_to_string (s, n, NULL); break;
+ case 2: nn = convert_to_token (s, n, NULL); break;
+ default: nn = convert_to_hex (s, n, NULL); break;
+ }
+ len += nn;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ switch (type)
+ {
+ case 1: convert_to_string (s, n, d); break;
+ case 2: convert_to_token (s, n, d); break;
+ default: convert_to_hex (s, n, d); break;
+ }
+ d += nn;
+ }
+ if (s[n] != ST_CLOSE)
+ {
+ len++;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ *d++ = ' ';
+ }
+ }
+ }
+ else
+ {
+ sprintf (numbuf, "%u:", (unsigned int)n );
+ len += strlen (numbuf) + n;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
+ return 0;
+ d = stpcpy ( d, numbuf );
+ memcpy ( d, s, n ); d += n;
+ }
+ }
+ s += n;
+ break;
+ default:
+ BUG ();
+ }
+ }
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ len++;
+ if (buffer)
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = '\n';
+ }
+ }
+ if (buffer)
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = 0; /* for convenience we make a C string */
+ }
+ else
+ len++; /* we need one byte more for this */
+
+ return len;
+}
+
+
+/* Scan a canonical encoded buffer with implicit length values and
+ return the actual length this S-expression uses. For a valid S-Exp
+ it should never return 0. If LENGTH is not zero, the maximum
+ length to scan is given - this can be used for syntax checks of
+ data passed from outside. errorcode and erroff may both be passed as
+ NULL. */
+size_t
+gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
+ size_t *erroff, gcry_error_t *errcode)
+{
+ const unsigned char *p;
+ const unsigned char *disphint = NULL;
+ unsigned int datalen = 0;
+ size_t dummy_erroff;
+ gcry_error_t dummy_errcode;
+ size_t count = 0;
+ int level = 0;
+
+ if (!erroff)
+ erroff = &dummy_erroff;
+ if (!errcode)
+ errcode = &dummy_errcode;
+
+ *errcode = gcry_error (GPG_ERR_NO_ERROR);
+ *erroff = 0;
+ if (!buffer)
+ return 0;
+ if (*buffer != '(')
+ {
+ *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
+ return 0;
+ }
+
+ for (p=buffer; ; p++, count++ )
+ {
+ if (length && count >= length)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
+ return 0;
+ }
+
+ if (datalen)
+ {
+ if (*p == ':')
+ {
+ if (length && (count+datalen) >= length)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
+ return 0;
+ }
+ count += datalen;
+ p += datalen;
+ datalen = 0;
+ }
+ else if (digitp(p))
+ datalen = datalen*10 + atoi_1(p);
+ else
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
+ return 0;
+ }
+ }
+ else if (*p == '(')
+ {
+ if (disphint)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
+ return 0;
+ }
+ level++;
+ }
+ else if (*p == ')')
+ { /* walk up */
+ if (!level)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
+ return 0;
+ }
+ if (disphint)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
+ return 0;
+ }
+ if (!--level)
+ return ++count; /* ready */
+ }
+ else if (*p == '[')
+ {
+ if (disphint)
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
+ return 0;
+ }
+ disphint = p;
+ }
+ else if (*p == ']')
+ {
+ if ( !disphint )
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
+ return 0;
+ }
+ disphint = NULL;
+ }
+ else if (digitp (p) )
+ {
+ if (*p == '0')
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
+ return 0;
+ }
+ datalen = atoi_1 (p);
+ }
+ else if (*p == '&' || *p == '\\')
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
+ return 0;
+ }
+ else
+ {
+ *erroff = count;
+ *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
+ return 0;
+ }
+ }
+}
diff --git a/libotr-3.2.0/src/auth.c b/libotr-3.2.0/src/auth.c
index a6752c3..de69645 100644
--- a/libotr-3.2.0/src/auth.c
+++ b/libotr-3.2.0/src/auth.c
@@ -33,27 +33,27 @@
*/
void otrl_auth_new(OtrlAuthInfo *auth)
{
- auth->authstate = OTRL_AUTHSTATE_NONE;
- otrl_dh_keypair_init(&(auth->our_dh));
- auth->our_keyid = 0;
- auth->encgx = NULL;
- auth->encgx_len = 0;
- memset(auth->r, 0, 16);
- memset(auth->hashgx, 0, 32);
- auth->their_pub = NULL;
- auth->their_keyid = 0;
- auth->enc_c = NULL;
- auth->enc_cp = NULL;
- auth->mac_m1 = NULL;
- auth->mac_m1p = NULL;
- auth->mac_m2 = NULL;
- auth->mac_m2p = NULL;
- memset(auth->their_fingerprint, 0, 20);
- auth->initiated = 0;
- auth->protocol_version = 0;
- memset(auth->secure_session_id, 0, 20);
- auth->secure_session_id_len = 0;
- auth->lastauthmsg = NULL;
+ auth->authstate = OTRL_AUTHSTATE_NONE;
+ otrl_dh_keypair_init(&(auth->our_dh));
+ auth->our_keyid = 0;
+ auth->encgx = NULL;
+ auth->encgx_len = 0;
+ memset(auth->r, 0, 16);
+ memset(auth->hashgx, 0, 32);
+ auth->their_pub = NULL;
+ auth->their_keyid = 0;
+ auth->enc_c = NULL;
+ auth->enc_cp = NULL;
+ auth->mac_m1 = NULL;
+ auth->mac_m1p = NULL;
+ auth->mac_m2 = NULL;
+ auth->mac_m2p = NULL;
+ memset(auth->their_fingerprint, 0, 20);
+ auth->initiated = 0;
+ auth->protocol_version = 0;
+ memset(auth->secure_session_id, 0, 20);
+ auth->secure_session_id_len = 0;
+ auth->lastauthmsg = NULL;
}
/*
@@ -61,36 +61,36 @@ void otrl_auth_new(OtrlAuthInfo *auth)
*/
void otrl_auth_clear(OtrlAuthInfo *auth)
{
- auth->authstate = OTRL_AUTHSTATE_NONE;
- otrl_dh_keypair_free(&(auth->our_dh));
- auth->our_keyid = 0;
- free(auth->encgx);
- auth->encgx = NULL;
- auth->encgx_len = 0;
- memset(auth->r, 0, 16);
- memset(auth->hashgx, 0, 32);
- gcry_mpi_release(auth->their_pub);
- auth->their_pub = NULL;
- auth->their_keyid = 0;
- gcry_cipher_close(auth->enc_c);
- gcry_cipher_close(auth->enc_cp);
- gcry_md_close(auth->mac_m1);
- gcry_md_close(auth->mac_m1p);
- gcry_md_close(auth->mac_m2);
- gcry_md_close(auth->mac_m2p);
- auth->enc_c = NULL;
- auth->enc_cp = NULL;
- auth->mac_m1 = NULL;
- auth->mac_m1p = NULL;
- auth->mac_m2 = NULL;
- auth->mac_m2p = NULL;
- memset(auth->their_fingerprint, 0, 20);
- auth->initiated = 0;
- auth->protocol_version = 0;
- memset(auth->secure_session_id, 0, 20);
- auth->secure_session_id_len = 0;
- free(auth->lastauthmsg);
- auth->lastauthmsg = NULL;
+ auth->authstate = OTRL_AUTHSTATE_NONE;
+ otrl_dh_keypair_free(&(auth->our_dh));
+ auth->our_keyid = 0;
+ free(auth->encgx);
+ auth->encgx = NULL;
+ auth->encgx_len = 0;
+ memset(auth->r, 0, 16);
+ memset(auth->hashgx, 0, 32);
+ gcry_mpi_release(auth->their_pub);
+ auth->their_pub = NULL;
+ auth->their_keyid = 0;
+ gcry_cipher_close(auth->enc_c);
+ gcry_cipher_close(auth->enc_cp);
+ gcry_md_close(auth->mac_m1);
+ gcry_md_close(auth->mac_m1p);
+ gcry_md_close(auth->mac_m2);
+ gcry_md_close(auth->mac_m2p);
+ auth->enc_c = NULL;
+ auth->enc_cp = NULL;
+ auth->mac_m1 = NULL;
+ auth->mac_m1p = NULL;
+ auth->mac_m2 = NULL;
+ auth->mac_m2p = NULL;
+ memset(auth->their_fingerprint, 0, 20);
+ auth->initiated = 0;
+ auth->protocol_version = 0;
+ memset(auth->secure_session_id, 0, 20);
+ auth->secure_session_id_len = 0;
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = NULL;
}
/*
@@ -100,96 +100,96 @@ void otrl_auth_clear(OtrlAuthInfo *auth)
*/
gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- size_t npub;
- gcry_cipher_hd_t enc = NULL;
- unsigned char ctr[16];
- unsigned char *buf, *bufp;
- size_t buflen, lenp;
-
- /* Clear out this OtrlAuthInfo and start over */
- otrl_auth_clear(auth);
- auth->initiated = 1;
-
- otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
- auth->our_keyid = 1;
-
- /* Pick an encryption key */
- gcry_randomize(auth->r, 16, GCRY_STRONG_RANDOM);
-
- /* Allocate space for the encrypted g^x */
- gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
- auth->encgx = malloc(4+npub);
- if (auth->encgx == NULL) goto memerr;
- auth->encgx_len = 4+npub;
- bufp = auth->encgx;
- lenp = auth->encgx_len;
- write_mpi(auth->our_dh.pub, npub, "g^x");
- assert(lenp == 0);
-
- /* Hash g^x */
- gcry_md_hash_buffer(GCRY_MD_SHA256, auth->hashgx, auth->encgx,
- auth->encgx_len);
-
- /* Encrypt g^x using the key r */
- err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
- GCRY_CIPHER_SECURE);
- if (err) goto err;
-
- err = gcry_cipher_setkey(enc, auth->r, 16);
- if (err) goto err;
-
- memset(ctr, 0, 16);
- err = gcry_cipher_setctr(enc, ctr, 16);
- if (err) goto err;
-
- err = gcry_cipher_encrypt(enc, auth->encgx, auth->encgx_len, NULL, 0);
- if (err) goto err;
-
- gcry_cipher_close(enc);
- enc = NULL;
-
- /* Now serialize the message */
- lenp = 3 + 4 + auth->encgx_len + 4 + 32;
- bufp = malloc(lenp);
- if (bufp == NULL) goto memerr;
- buf = bufp;
- buflen = lenp;
-
- memmove(bufp, "\x00\x02\x02", 3); /* header */
- debug_data("Header", bufp, 3);
- bufp += 3; lenp -= 3;
-
- /* Encrypted g^x */
- write_int(auth->encgx_len);
- debug_int("Enc gx len", bufp-4);
- memmove(bufp, auth->encgx, auth->encgx_len);
- debug_data("Enc gx", bufp, auth->encgx_len);
- bufp += auth->encgx_len; lenp -= auth->encgx_len;
-
- /* Hashed g^x */
- write_int(32);
- debug_int("hashgx len", bufp-4);
- memmove(bufp, auth->hashgx, 32);
- debug_data("hashgx", bufp, 32);
- bufp += 32; lenp -= 32;
-
- assert(lenp == 0);
-
- auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
- free(buf);
- if (auth->lastauthmsg == NULL) goto memerr;
- auth->authstate = OTRL_AUTHSTATE_AWAITING_DHKEY;
-
- return err;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ size_t npub;
+ gcry_cipher_hd_t enc = NULL;
+ unsigned char ctr[16];
+ unsigned char *buf, *bufp;
+ size_t buflen, lenp;
+
+ /* Clear out this OtrlAuthInfo and start over */
+ otrl_auth_clear(auth);
+ auth->initiated = 1;
+
+ otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+ auth->our_keyid = 1;
+
+ /* Pick an encryption key */
+ gcry_randomize(auth->r, 16, GCRY_STRONG_RANDOM);
+
+ /* Allocate space for the encrypted g^x */
+ gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
+ auth->encgx = malloc(4+npub);
+ if (auth->encgx == NULL) goto memerr;
+ auth->encgx_len = 4+npub;
+ bufp = auth->encgx;
+ lenp = auth->encgx_len;
+ write_mpi(auth->our_dh.pub, npub, "g^x");
+ assert(lenp == 0);
+
+ /* Hash g^x */
+ gcry_md_hash_buffer(GCRY_MD_SHA256, auth->hashgx, auth->encgx,
+ auth->encgx_len);
+
+ /* Encrypt g^x using the key r */
+ err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
+ GCRY_CIPHER_SECURE);
+ if (err) goto err;
+
+ err = gcry_cipher_setkey(enc, auth->r, 16);
+ if (err) goto err;
+
+ memset(ctr, 0, 16);
+ err = gcry_cipher_setctr(enc, ctr, 16);
+ if (err) goto err;
+
+ err = gcry_cipher_encrypt(enc, auth->encgx, auth->encgx_len, NULL, 0);
+ if (err) goto err;
+
+ gcry_cipher_close(enc);
+ enc = NULL;
+
+ /* Now serialize the message */
+ lenp = 3 + 4 + auth->encgx_len + 4 + 32;
+ bufp = malloc(lenp);
+ if (bufp == NULL) goto memerr;
+ buf = bufp;
+ buflen = lenp;
+
+ memmove(bufp, "\x00\x02\x02", 3); /* header */
+ debug_data("Header", bufp, 3);
+ bufp += 3; lenp -= 3;
+
+ /* Encrypted g^x */
+ write_int(auth->encgx_len);
+ debug_int("Enc gx len", bufp-4);
+ memmove(bufp, auth->encgx, auth->encgx_len);
+ debug_data("Enc gx", bufp, auth->encgx_len);
+ bufp += auth->encgx_len; lenp -= auth->encgx_len;
+
+ /* Hashed g^x */
+ write_int(32);
+ debug_int("hashgx len", bufp-4);
+ memmove(bufp, auth->hashgx, 32);
+ debug_data("hashgx", bufp, 32);
+ bufp += 32; lenp -= 32;
+
+ assert(lenp == 0);
+
+ auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
+ free(buf);
+ if (auth->lastauthmsg == NULL) goto memerr;
+ auth->authstate = OTRL_AUTHSTATE_AWAITING_DHKEY;
+
+ return err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- otrl_auth_clear(auth);
- gcry_cipher_close(enc);
- return err;
+ otrl_auth_clear(auth);
+ gcry_cipher_close(enc);
+ return err;
}
/*
@@ -198,38 +198,38 @@ err:
*/
static gcry_error_t create_key_message(OtrlAuthInfo *auth)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- unsigned char *buf, *bufp;
- size_t buflen, lenp;
- size_t npub;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ unsigned char *buf, *bufp;
+ size_t buflen, lenp;
+ size_t npub;
- gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
- buflen = 3 + 4 + npub;
- buf = malloc(buflen);
- if (buf == NULL) goto memerr;
- bufp = buf;
- lenp = buflen;
+ gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
+ buflen = 3 + 4 + npub;
+ buf = malloc(buflen);
+ if (buf == NULL) goto memerr;
+ bufp = buf;
+ lenp = buflen;
- memmove(bufp, "\x00\x02\x0a", 3); /* header */
- debug_data("Header", bufp, 3);
- bufp += 3; lenp -= 3;
+ memmove(bufp, "\x00\x02\x0a", 3); /* header */
+ debug_data("Header", bufp, 3);
+ bufp += 3; lenp -= 3;
- /* g^y */
- write_mpi(auth->our_dh.pub, npub, "g^y");
+ /* g^y */
+ write_mpi(auth->our_dh.pub, npub, "g^y");
- assert(lenp == 0);
+ assert(lenp == 0);
- free(auth->lastauthmsg);
- auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
- free(buf);
- if (auth->lastauthmsg == NULL) goto memerr;
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
+ free(buf);
+ if (auth->lastauthmsg == NULL) goto memerr;
- return err;
+ return err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
- return err;
+ err = gcry_error(GPG_ERR_ENOMEM);
+ return err;
}
/*
@@ -240,73 +240,73 @@ memerr:
gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
const char *commitmsg)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp = NULL, *encbuf = NULL;
- unsigned char hashbuf[32];
- size_t buflen, lenp, enclen, hashlen;
- int res;
-
- res = otrl_base64_otr_decode(commitmsg, &buf, &buflen);
- if (res == -1) goto memerr;
- if (res == -2) goto invval;
-
- bufp = buf;
- lenp = buflen;
-
- /* Header */
- require_len(3);
- if (memcmp(bufp, "\x00\x02\x02", 3)) goto invval;
- bufp += 3; lenp -= 3;
-
- /* Encrypted g^x */
- read_int(enclen);
- require_len(enclen);
- encbuf = malloc(enclen);
- if (encbuf == NULL && enclen > 0) goto memerr;
- memmove(encbuf, bufp, enclen);
- bufp += enclen; lenp -= enclen;
-
- /* Hashed g^x */
- read_int(hashlen);
- if (hashlen != 32) goto invval;
- require_len(32);
- memmove(hashbuf, bufp, 32);
- bufp += 32; lenp -= 32;
-
- if (lenp != 0) goto invval;
- free(buf);
- buf = NULL;
-
- switch(auth->authstate) {
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp = NULL, *encbuf = NULL;
+ unsigned char hashbuf[32];
+ size_t buflen, lenp, enclen, hashlen;
+ int res;
+
+ res = otrl_base64_otr_decode(commitmsg, &buf, &buflen);
+ if (res == -1) goto memerr;
+ if (res == -2) goto invval;
+
+ bufp = buf;
+ lenp = buflen;
+
+ /* Header */
+ require_len(3);
+ if (memcmp(bufp, "\x00\x02\x02", 3)) goto invval;
+ bufp += 3; lenp -= 3;
+
+ /* Encrypted g^x */
+ read_int(enclen);
+ require_len(enclen);
+ encbuf = malloc(enclen);
+ if (encbuf == NULL && enclen > 0) goto memerr;
+ memmove(encbuf, bufp, enclen);
+ bufp += enclen; lenp -= enclen;
+
+ /* Hashed g^x */
+ read_int(hashlen);
+ if (hashlen != 32) goto invval;
+ require_len(32);
+ memmove(hashbuf, bufp, 32);
+ bufp += 32; lenp -= 32;
+
+ if (lenp != 0) goto invval;
+ free(buf);
+ buf = NULL;
+
+ switch(auth->authstate) {
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_SIG:
case OTRL_AUTHSTATE_V1_SETUP:
- /* Store the incoming information */
- otrl_auth_clear(auth);
- otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
- auth->our_keyid = 1;
- auth->encgx = encbuf;
- encbuf = NULL;
- auth->encgx_len = enclen;
- memmove(auth->hashgx, hashbuf, 32);
+ /* Store the incoming information */
+ otrl_auth_clear(auth);
+ otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+ auth->our_keyid = 1;
+ auth->encgx = encbuf;
+ encbuf = NULL;
+ auth->encgx_len = enclen;
+ memmove(auth->hashgx, hashbuf, 32);
- /* Create a D-H Key Message */
- err = create_key_message(auth);
- if (err) goto err;
- auth->authstate = OTRL_AUTHSTATE_AWAITING_REVEALSIG;
+ /* Create a D-H Key Message */
+ err = create_key_message(auth);
+ if (err) goto err;
+ auth->authstate = OTRL_AUTHSTATE_AWAITING_REVEALSIG;
- break;
+ break;
case OTRL_AUTHSTATE_AWAITING_DHKEY:
- /* We sent a D-H Commit Message, and we also received one
- * back. Compare the hashgx values to see which one wins. */
- if (memcmp(auth->hashgx, hashbuf, 32) > 0) {
+ /* We sent a D-H Commit Message, and we also received one
+ * back. Compare the hashgx values to see which one wins. */
+ if (memcmp(auth->hashgx, hashbuf, 32) > 0) {
/* Ours wins. Ignore the message we received, and just
* resend the same D-H Commit message again. */
free(encbuf);
encbuf = NULL;
- } else {
+ } else {
/* Ours loses. Use the incoming parameters instead. */
otrl_auth_clear(auth);
otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
@@ -320,30 +320,30 @@ gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
err = create_key_message(auth);
if (err) goto err;
auth->authstate = OTRL_AUTHSTATE_AWAITING_REVEALSIG;
- }
- break;
+ }
+ break;
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
- /* Use the incoming parameters, but just retransmit the old
- * D-H Key Message. */
- free(auth->encgx);
- auth->encgx = encbuf;
- encbuf = NULL;
- auth->encgx_len = enclen;
- memmove(auth->hashgx, hashbuf, 32);
- break;
- }
-
- return err;
+ /* Use the incoming parameters, but just retransmit the old
+ * D-H Key Message. */
+ free(auth->encgx);
+ auth->encgx = encbuf;
+ encbuf = NULL;
+ auth->encgx_len = enclen;
+ memmove(auth->hashgx, hashbuf, 32);
+ break;
+ }
+
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(encbuf);
- return err;
+ free(buf);
+ free(encbuf);
+ return err;
}
/*
@@ -358,92 +358,92 @@ static gcry_error_t calculate_pubkey_auth(unsigned char **authbufp,
gcry_mpi_t our_dh_pub, gcry_mpi_t their_dh_pub,
OtrlPrivKey *privkey, unsigned int keyid)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- size_t ourpublen, theirpublen, totallen, lenp;
- unsigned char *buf = NULL, *bufp = NULL;
- unsigned char macbuf[32];
- unsigned char *sigbuf = NULL;
- size_t siglen;
-
- /* How big are the DH public keys? */
- gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
- gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
-
- /* How big is the total structure to be MAC'd? */
- totallen = 4 + ourpublen + 4 + theirpublen + 2 + privkey->pubkey_datalen
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ size_t ourpublen, theirpublen, totallen, lenp;
+ unsigned char *buf = NULL, *bufp = NULL;
+ unsigned char macbuf[32];
+ unsigned char *sigbuf = NULL;
+ size_t siglen;
+
+ /* How big are the DH public keys? */
+ gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
+ gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
+
+ /* How big is the total structure to be MAC'd? */
+ totallen = 4 + ourpublen + 4 + theirpublen + 2 + privkey->pubkey_datalen
+ 4;
- buf = malloc(totallen);
- if (buf == NULL) goto memerr;
-
- bufp = buf;
- lenp = totallen;
-
- /* Write the data to be MAC'd */
- write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
- write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
- bufp[0] = ((privkey->pubkey_type) >> 16) & 0xff;
- bufp[1] = (privkey->pubkey_type) & 0xff;
- bufp += 2; lenp -= 2;
- memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
- debug_data("Pubkey", bufp, privkey->pubkey_datalen);
- bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
- write_int(keyid);
- debug_int("Keyid", bufp-4);
-
- assert(lenp == 0);
-
- /* Do the MAC */
- gcry_md_reset(mackey);
- gcry_md_write(mackey, buf, totallen);
- memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
-
- free(buf);
- buf = NULL;
-
- /* Sign the MAC */
- err = otrl_privkey_sign(&sigbuf, &siglen, privkey, macbuf, 32);
- if (err) goto err;
-
- /* Calculate the total size of the structure to be encrypted */
- totallen = 2 + privkey->pubkey_datalen + 4 + siglen;
- buf = malloc(totallen);
- if (buf == NULL) goto memerr;
- bufp = buf;
- lenp = totallen;
-
- /* Write the data to be encrypted */
- bufp[0] = ((privkey->pubkey_type) >> 16) & 0xff;
- bufp[1] = (privkey->pubkey_type) & 0xff;
- bufp += 2; lenp -= 2;
- memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
- debug_data("Pubkey", bufp, privkey->pubkey_datalen);
- bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
- write_int(keyid);
- debug_int("Keyid", bufp-4);
- memmove(bufp, sigbuf, siglen);
- debug_data("Signature", bufp, siglen);
- bufp += siglen; lenp -= siglen;
- free(sigbuf);
- sigbuf = NULL;
-
- assert(lenp == 0);
-
- /* Now do the encryption */
- err = gcry_cipher_encrypt(enckey, buf, totallen, NULL, 0);
- if (err) goto err;
-
- *authbufp = buf;
- buf = NULL;
- *authlenp = totallen;
-
- return err;
+ buf = malloc(totallen);
+ if (buf == NULL) goto memerr;
+
+ bufp = buf;
+ lenp = totallen;
+
+ /* Write the data to be MAC'd */
+ write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
+ write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
+ bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
+ bufp[1] = (privkey->pubkey_type) & 0xff;
+ bufp += 2; lenp -= 2;
+ memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
+ debug_data("Pubkey", bufp, privkey->pubkey_datalen);
+ bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
+ write_int(keyid);
+ debug_int("Keyid", bufp-4);
+
+ assert(lenp == 0);
+
+ /* Do the MAC */
+ gcry_md_reset(mackey);
+ gcry_md_write(mackey, buf, totallen);
+ memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
+
+ free(buf);
+ buf = NULL;
+
+ /* Sign the MAC */
+ err = otrl_privkey_sign(&sigbuf, &siglen, privkey, macbuf, 32);
+ if (err) goto err;
+
+ /* Calculate the total size of the structure to be encrypted */
+ totallen = 2 + privkey->pubkey_datalen + 4 + siglen;
+ buf = malloc(totallen);
+ if (buf == NULL) goto memerr;
+ bufp = buf;
+ lenp = totallen;
+
+ /* Write the data to be encrypted */
+ bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
+ bufp[1] = (privkey->pubkey_type) & 0xff;
+ bufp += 2; lenp -= 2;
+ memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
+ debug_data("Pubkey", bufp, privkey->pubkey_datalen);
+ bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
+ write_int(keyid);
+ debug_int("Keyid", bufp-4);
+ memmove(bufp, sigbuf, siglen);
+ debug_data("Signature", bufp, siglen);
+ bufp += siglen; lenp -= siglen;
+ free(sigbuf);
+ sigbuf = NULL;
+
+ assert(lenp == 0);
+
+ /* Now do the encryption */
+ err = gcry_cipher_encrypt(enckey, buf, totallen, NULL, 0);
+ if (err) goto err;
+
+ *authbufp = buf;
+ buf = NULL;
+ *authlenp = totallen;
+
+ return err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(sigbuf);
- return err;
+ free(buf);
+ free(sigbuf);
+ return err;
}
/*
@@ -458,107 +458,107 @@ static gcry_error_t check_pubkey_auth(unsigned char fingerprintbufp[20],
gcry_md_hd_t mackey, gcry_cipher_hd_t enckey,
gcry_mpi_t our_dh_pub, gcry_mpi_t their_dh_pub)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- size_t ourpublen, theirpublen, totallen, lenp;
- unsigned char *buf = NULL, *bufp = NULL;
- unsigned char macbuf[32];
- unsigned short pubkey_type;
- gcry_mpi_t p,q,g,y;
- gcry_sexp_t pubs = NULL;
- unsigned int received_keyid;
- unsigned char *fingerprintstart, *fingerprintend, *sigbuf;
- size_t siglen;
-
- /* Start by decrypting it */
- err = gcry_cipher_decrypt(enckey, authbuf, authlen, NULL, 0);
- if (err) goto err;
-
- bufp = authbuf;
- lenp = authlen;
-
- /* Get the public key and calculate its fingerprint */
- require_len(2);
- pubkey_type = (bufp[0] << 8) + bufp[1];
- bufp += 2; lenp -= 2;
- if (pubkey_type != OTRL_PUBKEY_TYPE_DSA) goto invval;
- fingerprintstart = bufp;
- read_mpi(p);
- read_mpi(q);
- read_mpi(g);
- read_mpi(y);
- fingerprintend = bufp;
- gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbufp,
- fingerprintstart, fingerprintend-fingerprintstart);
- gcry_sexp_build(&pubs, NULL,
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ size_t ourpublen, theirpublen, totallen, lenp;
+ unsigned char *buf = NULL, *bufp = NULL;
+ unsigned char macbuf[32];
+ unsigned short pubkey_type;
+ gcry_mpi_t p,q,g,y;
+ gcry_sexp_t pubs = NULL;
+ unsigned int received_keyid;
+ unsigned char *fingerprintstart, *fingerprintend, *sigbuf;
+ size_t siglen;
+
+ /* Start by decrypting it */
+ err = gcry_cipher_decrypt(enckey, authbuf, authlen, NULL, 0);
+ if (err) goto err;
+
+ bufp = authbuf;
+ lenp = authlen;
+
+ /* Get the public key and calculate its fingerprint */
+ require_len(2);
+ pubkey_type = (bufp[0] << 8) + bufp[1];
+ bufp += 2; lenp -= 2;
+ if (pubkey_type != OTRL_PUBKEY_TYPE_DSA) goto invval;
+ fingerprintstart = bufp;
+ read_mpi(p);
+ read_mpi(q);
+ read_mpi(g);
+ read_mpi(y);
+ fingerprintend = bufp;
+ gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbufp,
+ fingerprintstart, fingerprintend-fingerprintstart);
+ gcry_sexp_build(&pubs, NULL,
"(public-key (dsa (p %m)(q %m)(g %m)(y %m)))", p, q, g, y);
- gcry_mpi_release(p);
- gcry_mpi_release(q);
- gcry_mpi_release(g);
- gcry_mpi_release(y);
+ gcry_mpi_release(p);
+ gcry_mpi_release(q);
+ gcry_mpi_release(g);
+ gcry_mpi_release(y);
- /* Get the keyid */
- read_int(received_keyid);
- if (received_keyid == 0) goto invval;
+ /* Get the keyid */
+ read_int(received_keyid);
+ if (received_keyid == 0) goto invval;
- /* Get the signature */
- sigbuf = bufp;
- siglen = lenp;
+ /* Get the signature */
+ sigbuf = bufp;
+ siglen = lenp;
- /* How big are the DH public keys? */
- gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
- gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
+ /* How big are the DH public keys? */
+ gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
+ gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
- /* Now calculate the message to be MAC'd. */
- totallen = 4 + ourpublen + 4 + theirpublen + 2 +
+ /* Now calculate the message to be MAC'd. */
+ totallen = 4 + ourpublen + 4 + theirpublen + 2 +
(fingerprintend - fingerprintstart) + 4;
- buf = malloc(totallen);
- if (buf == NULL) goto memerr;
-
- bufp = buf;
- lenp = totallen;
-
- write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
- write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
- bufp[0] = (pubkey_type >> 16) & 0xff;
- bufp[1] = pubkey_type & 0xff;
- bufp += 2; lenp -= 2;
- memmove(bufp, fingerprintstart, fingerprintend - fingerprintstart);
- debug_data("Pubkey", bufp, fingerprintend - fingerprintstart);
- bufp += fingerprintend - fingerprintstart;
- lenp -= fingerprintend - fingerprintstart;
- write_int(received_keyid);
- debug_int("Keyid", bufp-4);
-
- assert(lenp == 0);
-
- /* Do the MAC */
- gcry_md_reset(mackey);
- gcry_md_write(mackey, buf, totallen);
- memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
-
- free(buf);
- buf = NULL;
-
- /* Verify the signature on the MAC */
- err = otrl_privkey_verify(sigbuf, siglen, pubkey_type, pubs, macbuf, 32);
- if (err) goto err;
- gcry_sexp_release(pubs);
- pubs = NULL;
-
- /* Everything checked out */
- *keyidp = received_keyid;
-
- return err;
+ buf = malloc(totallen);
+ if (buf == NULL) goto memerr;
+
+ bufp = buf;
+ lenp = totallen;
+
+ write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
+ write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
+ bufp[0] = (pubkey_type >> 8) & 0xff;
+ bufp[1] = pubkey_type & 0xff;
+ bufp += 2; lenp -= 2;
+ memmove(bufp, fingerprintstart, fingerprintend - fingerprintstart);
+ debug_data("Pubkey", bufp, fingerprintend - fingerprintstart);
+ bufp += fingerprintend - fingerprintstart;
+ lenp -= fingerprintend - fingerprintstart;
+ write_int(received_keyid);
+ debug_int("Keyid", bufp-4);
+
+ assert(lenp == 0);
+
+ /* Do the MAC */
+ gcry_md_reset(mackey);
+ gcry_md_write(mackey, buf, totallen);
+ memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
+
+ free(buf);
+ buf = NULL;
+
+ /* Verify the signature on the MAC */
+ err = otrl_privkey_verify(sigbuf, siglen, pubkey_type, pubs, macbuf, 32);
+ if (err) goto err;
+ gcry_sexp_release(pubs);
+ pubs = NULL;
+
+ /* Everything checked out */
+ *keyidp = received_keyid;
+
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- gcry_sexp_release(pubs);
- return err;
+ free(buf);
+ gcry_sexp_release(pubs);
+ return err;
}
/*
@@ -569,67 +569,67 @@ err:
static gcry_error_t create_revealsig_message(OtrlAuthInfo *auth,
OtrlPrivKey *privkey)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp, *startmac;
- size_t buflen, lenp;
-
- unsigned char *authbuf = NULL;
- size_t authlen;
-
- /* Get the encrypted authenticator */
- err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1, auth->enc_c,
- auth->our_dh.pub, auth->their_pub, privkey, auth->our_keyid);
- if (err) goto err;
-
- buflen = 3 + 4 + 16 + 4 + authlen + 20;
- buf = malloc(buflen);
- if (buf == NULL) goto memerr;
-
- bufp = buf;
- lenp = buflen;
-
- memmove(bufp, "\x00\x02\x11", 3); /* header */
- debug_data("Header", bufp, 3);
- bufp += 3; lenp -= 3;
-
- /* r */
- write_int(16);
- memmove(bufp, auth->r, 16);
- debug_data("r", bufp, 16);
- bufp += 16; lenp -= 16;
-
- /* Encrypted authenticator */
- startmac = bufp;
- write_int(authlen);
- memmove(bufp, authbuf, authlen);
- debug_data("auth", bufp, authlen);
- bufp += authlen; lenp -= authlen;
- free(authbuf);
- authbuf = NULL;
-
- /* MAC it, but only take the first 20 bytes */
- gcry_md_reset(auth->mac_m2);
- gcry_md_write(auth->mac_m2, startmac, bufp - startmac);
- memmove(bufp, gcry_md_read(auth->mac_m2, GCRY_MD_SHA256), 20);
- debug_data("MAC", bufp, 20);
- bufp += 20; lenp -= 20;
-
- assert(lenp == 0);
-
- free(auth->lastauthmsg);
- auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
- if (auth->lastauthmsg == NULL) goto memerr;
- free(buf);
- buf = NULL;
-
- return err;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp, *startmac;
+ size_t buflen, lenp;
+
+ unsigned char *authbuf = NULL;
+ size_t authlen;
+
+ /* Get the encrypted authenticator */
+ err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1, auth->enc_c,
+ auth->our_dh.pub, auth->their_pub, privkey, auth->our_keyid);
+ if (err) goto err;
+
+ buflen = 3 + 4 + 16 + 4 + authlen + 20;
+ buf = malloc(buflen);
+ if (buf == NULL) goto memerr;
+
+ bufp = buf;
+ lenp = buflen;
+
+ memmove(bufp, "\x00\x02\x11", 3); /* header */
+ debug_data("Header", bufp, 3);
+ bufp += 3; lenp -= 3;
+
+ /* r */
+ write_int(16);
+ memmove(bufp, auth->r, 16);
+ debug_data("r", bufp, 16);
+ bufp += 16; lenp -= 16;
+
+ /* Encrypted authenticator */
+ startmac = bufp;
+ write_int(authlen);
+ memmove(bufp, authbuf, authlen);
+ debug_data("auth", bufp, authlen);
+ bufp += authlen; lenp -= authlen;
+ free(authbuf);
+ authbuf = NULL;
+
+ /* MAC it, but only take the first 20 bytes */
+ gcry_md_reset(auth->mac_m2);
+ gcry_md_write(auth->mac_m2, startmac, bufp - startmac);
+ memmove(bufp, gcry_md_read(auth->mac_m2, GCRY_MD_SHA256), 20);
+ debug_data("MAC", bufp, 20);
+ bufp += 20; lenp -= 20;
+
+ assert(lenp == 0);
+
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
+ if (auth->lastauthmsg == NULL) goto memerr;
+ free(buf);
+ buf = NULL;
+
+ return err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(authbuf);
- return err;
+ free(buf);
+ free(authbuf);
+ return err;
}
/*
@@ -640,62 +640,62 @@ err:
static gcry_error_t create_signature_message(OtrlAuthInfo *auth,
OtrlPrivKey *privkey)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp, *startmac;
- size_t buflen, lenp;
-
- unsigned char *authbuf = NULL;
- size_t authlen;
-
- /* Get the encrypted authenticator */
- err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1p,
- auth->enc_cp, auth->our_dh.pub, auth->their_pub, privkey,
- auth->our_keyid);
- if (err) goto err;
-
- buflen = 3 + 4 + authlen + 20;
- buf = malloc(buflen);
- if (buf == NULL) goto memerr;
-
- bufp = buf;
- lenp = buflen;
-
- memmove(bufp, "\x00\x02\x12", 3); /* header */
- debug_data("Header", bufp, 3);
- bufp += 3; lenp -= 3;
-
- /* Encrypted authenticator */
- startmac = bufp;
- write_int(authlen);
- memmove(bufp, authbuf, authlen);
- debug_data("auth", bufp, authlen);
- bufp += authlen; lenp -= authlen;
- free(authbuf);
- authbuf = NULL;
-
- /* MAC it, but only take the first 20 bytes */
- gcry_md_reset(auth->mac_m2p);
- gcry_md_write(auth->mac_m2p, startmac, bufp - startmac);
- memmove(bufp, gcry_md_read(auth->mac_m2p, GCRY_MD_SHA256), 20);
- debug_data("MAC", bufp, 20);
- bufp += 20; lenp -= 20;
-
- assert(lenp == 0);
-
- free(auth->lastauthmsg);
- auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
- if (auth->lastauthmsg == NULL) goto memerr;
- free(buf);
- buf = NULL;
-
- return err;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp, *startmac;
+ size_t buflen, lenp;
+
+ unsigned char *authbuf = NULL;
+ size_t authlen;
+
+ /* Get the encrypted authenticator */
+ err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1p,
+ auth->enc_cp, auth->our_dh.pub, auth->their_pub, privkey,
+ auth->our_keyid);
+ if (err) goto err;
+
+ buflen = 3 + 4 + authlen + 20;
+ buf = malloc(buflen);
+ if (buf == NULL) goto memerr;
+
+ bufp = buf;
+ lenp = buflen;
+
+ memmove(bufp, "\x00\x02\x12", 3); /* header */
+ debug_data("Header", bufp, 3);
+ bufp += 3; lenp -= 3;
+
+ /* Encrypted authenticator */
+ startmac = bufp;
+ write_int(authlen);
+ memmove(bufp, authbuf, authlen);
+ debug_data("auth", bufp, authlen);
+ bufp += authlen; lenp -= authlen;
+ free(authbuf);
+ authbuf = NULL;
+
+ /* MAC it, but only take the first 20 bytes */
+ gcry_md_reset(auth->mac_m2p);
+ gcry_md_write(auth->mac_m2p, startmac, bufp - startmac);
+ memmove(bufp, gcry_md_read(auth->mac_m2p, GCRY_MD_SHA256), 20);
+ debug_data("MAC", bufp, 20);
+ bufp += 20; lenp -= 20;
+
+ assert(lenp == 0);
+
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
+ if (auth->lastauthmsg == NULL) goto memerr;
+ free(buf);
+ buf = NULL;
+
+ return err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(authbuf);
- return err;
+ free(buf);
+ free(authbuf);
+ return err;
}
/*
@@ -706,85 +706,85 @@ err:
gcry_error_t otrl_auth_handle_key(OtrlAuthInfo *auth, const char *keymsg,
int *havemsgp, OtrlPrivKey *privkey)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp = NULL;
- size_t buflen, lenp;
- gcry_mpi_t incoming_pub = NULL;
- int res;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp = NULL;
+ size_t buflen, lenp;
+ gcry_mpi_t incoming_pub = NULL;
+ int res;
- *havemsgp = 0;
+ *havemsgp = 0;
- res = otrl_base64_otr_decode(keymsg, &buf, &buflen);
- if (res == -1) goto memerr;
- if (res == -2) goto invval;
+ res = otrl_base64_otr_decode(keymsg, &buf, &buflen);
+ if (res == -1) goto memerr;
+ if (res == -2) goto invval;
- bufp = buf;
- lenp = buflen;
+ bufp = buf;
+ lenp = buflen;
- /* Header */
- if (memcmp(bufp, "\x00\x02\x0a", 3)) goto invval;
- bufp += 3; lenp -= 3;
+ /* Header */
+ if (memcmp(bufp, "\x00\x02\x0a", 3)) goto invval;
+ bufp += 3; lenp -= 3;
- /* g^y */
- read_mpi(incoming_pub);
+ /* g^y */
+ read_mpi(incoming_pub);
- if (lenp != 0) goto invval;
- free(buf);
- buf = NULL;
+ if (lenp != 0) goto invval;
+ free(buf);
+ buf = NULL;
- switch(auth->authstate) {
+ switch(auth->authstate) {
case OTRL_AUTHSTATE_AWAITING_DHKEY:
- /* Store the incoming public key */
- gcry_mpi_release(auth->their_pub);
- auth->their_pub = incoming_pub;
- incoming_pub = NULL;
-
- /* Compute the encryption and MAC keys */
- err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
- auth->their_pub, auth->secure_session_id,
- &(auth->secure_session_id_len),
- &(auth->enc_c), &(auth->enc_cp),
- &(auth->mac_m1), &(auth->mac_m1p),
- &(auth->mac_m2), &(auth->mac_m2p));
- if (err) goto err;
-
- /* Create the Reveal Signature Message */
- err = create_revealsig_message(auth, privkey);
- if (err) goto err;
- *havemsgp = 1;
- auth->authstate = OTRL_AUTHSTATE_AWAITING_SIG;
-
- break;
+ /* Store the incoming public key */
+ gcry_mpi_release(auth->their_pub);
+ auth->their_pub = incoming_pub;
+ incoming_pub = NULL;
+
+ /* Compute the encryption and MAC keys */
+ err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
+ auth->their_pub, auth->secure_session_id,
+ &(auth->secure_session_id_len),
+ &(auth->enc_c), &(auth->enc_cp),
+ &(auth->mac_m1), &(auth->mac_m1p),
+ &(auth->mac_m2), &(auth->mac_m2p));
+ if (err) goto err;
+
+ /* Create the Reveal Signature Message */
+ err = create_revealsig_message(auth, privkey);
+ if (err) goto err;
+ *havemsgp = 1;
+ auth->authstate = OTRL_AUTHSTATE_AWAITING_SIG;
+
+ break;
case OTRL_AUTHSTATE_AWAITING_SIG:
- if (gcry_mpi_cmp(incoming_pub, auth->their_pub) == 0) {
+ if (gcry_mpi_cmp(incoming_pub, auth->their_pub) == 0) {
/* Retransmit the Reveal Signature Message */
*havemsgp = 1;
- } else {
+ } else {
/* Ignore this message */
*havemsgp = 0;
- }
- break;
+ }
+ break;
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
case OTRL_AUTHSTATE_V1_SETUP:
- /* Ignore this message */
- *havemsgp = 0;
- break;
- }
+ /* Ignore this message */
+ *havemsgp = 0;
+ break;
+ }
- gcry_mpi_release(incoming_pub);
- return err;
+ gcry_mpi_release(incoming_pub);
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- gcry_mpi_release(incoming_pub);
- return err;
+ free(buf);
+ gcry_mpi_release(incoming_pub);
+ return err;
}
/*
@@ -799,162 +799,162 @@ gcry_error_t otrl_auth_handle_revealsig(OtrlAuthInfo *auth,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp = NULL, *gxbuf = NULL;
- unsigned char *authstart, *authend, *macstart;
- size_t buflen, lenp, rlen, authlen;
- gcry_cipher_hd_t enc = NULL;
- gcry_mpi_t incoming_pub = NULL;
- unsigned char ctr[16], hashbuf[32];
- int res;
-
- *havemsgp = 0;
-
- res = otrl_base64_otr_decode(revealmsg, &buf, &buflen);
- if (res == -1) goto memerr;
- if (res == -2) goto invval;
-
- bufp = buf;
- lenp = buflen;
-
- /* Header */
- if (memcmp(bufp, "\x00\x02\x11", 3)) goto invval;
- bufp += 3; lenp -= 3;
-
- /* r */
- read_int(rlen);
- if (rlen != 16) goto invval;
- require_len(rlen);
- memmove(auth->r, bufp, rlen);
- bufp += rlen; lenp -= rlen;
-
- /* auth */
- authstart = bufp;
- read_int(authlen);
- require_len(authlen);
- bufp += authlen; lenp -= authlen;
- authend = bufp;
-
- /* MAC */
- require_len(20);
- macstart = bufp;
- bufp += 20; lenp -= 20;
-
- if (lenp != 0) goto invval;
-
- switch(auth->authstate) {
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp = NULL, *gxbuf = NULL;
+ unsigned char *authstart, *authend, *macstart;
+ size_t buflen, lenp, rlen, authlen;
+ gcry_cipher_hd_t enc = NULL;
+ gcry_mpi_t incoming_pub = NULL;
+ unsigned char ctr[16], hashbuf[32];
+ int res;
+
+ *havemsgp = 0;
+
+ res = otrl_base64_otr_decode(revealmsg, &buf, &buflen);
+ if (res == -1) goto memerr;
+ if (res == -2) goto invval;
+
+ bufp = buf;
+ lenp = buflen;
+
+ /* Header */
+ if (memcmp(bufp, "\x00\x02\x11", 3)) goto invval;
+ bufp += 3; lenp -= 3;
+
+ /* r */
+ read_int(rlen);
+ if (rlen != 16) goto invval;
+ require_len(rlen);
+ memmove(auth->r, bufp, rlen);
+ bufp += rlen; lenp -= rlen;
+
+ /* auth */
+ authstart = bufp;
+ read_int(authlen);
+ require_len(authlen);
+ bufp += authlen; lenp -= authlen;
+ authend = bufp;
+
+ /* MAC */
+ require_len(20);
+ macstart = bufp;
+ bufp += 20; lenp -= 20;
+
+ if (lenp != 0) goto invval;
+
+ switch(auth->authstate) {
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
- gxbuf = malloc(auth->encgx_len);
- if (auth->encgx_len && gxbuf == NULL) goto memerr;
-
- /* Use r to decrypt the value of g^x we received earlier */
- err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
- GCRY_CIPHER_SECURE);
- if (err) goto err;
-
- err = gcry_cipher_setkey(enc, auth->r, 16);
- if (err) goto err;
-
- memset(ctr, 0, 16);
- err = gcry_cipher_setctr(enc, ctr, 16);
- if (err) goto err;
-
- err = gcry_cipher_decrypt(enc, gxbuf, auth->encgx_len,
- auth->encgx, auth->encgx_len);
- if (err) goto err;
-
- gcry_cipher_close(enc);
- enc = NULL;
-
- /* Check the hash */
- gcry_md_hash_buffer(GCRY_MD_SHA256, hashbuf, gxbuf,
- auth->encgx_len);
- if (memcmp(hashbuf, auth->hashgx, 32)) goto decfail;
-
- /* Extract g^x */
- bufp = gxbuf;
- lenp = auth->encgx_len;
-
- read_mpi(incoming_pub);
- free(gxbuf);
- gxbuf = NULL;
-
- if (lenp != 0) goto invval;
-
- gcry_mpi_release(auth->their_pub);
- auth->their_pub = incoming_pub;
- incoming_pub = NULL;
-
- /* Compute the encryption and MAC keys */
- err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
- auth->their_pub, auth->secure_session_id,
- &(auth->secure_session_id_len),
- &(auth->enc_c), &(auth->enc_cp),
- &(auth->mac_m1), &(auth->mac_m1p),
- &(auth->mac_m2), &(auth->mac_m2p));
- if (err) goto err;
-
- /* Check the MAC */
- gcry_md_reset(auth->mac_m2);
- gcry_md_write(auth->mac_m2, authstart, authend - authstart);
- if (memcmp(macstart,
+ gxbuf = malloc(auth->encgx_len);
+ if (auth->encgx_len && gxbuf == NULL) goto memerr;
+
+ /* Use r to decrypt the value of g^x we received earlier */
+ err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
+ GCRY_CIPHER_SECURE);
+ if (err) goto err;
+
+ err = gcry_cipher_setkey(enc, auth->r, 16);
+ if (err) goto err;
+
+ memset(ctr, 0, 16);
+ err = gcry_cipher_setctr(enc, ctr, 16);
+ if (err) goto err;
+
+ err = gcry_cipher_decrypt(enc, gxbuf, auth->encgx_len,
+ auth->encgx, auth->encgx_len);
+ if (err) goto err;
+
+ gcry_cipher_close(enc);
+ enc = NULL;
+
+ /* Check the hash */
+ gcry_md_hash_buffer(GCRY_MD_SHA256, hashbuf, gxbuf,
+ auth->encgx_len);
+ if (memcmp(hashbuf, auth->hashgx, 32)) goto decfail;
+
+ /* Extract g^x */
+ bufp = gxbuf;
+ lenp = auth->encgx_len;
+
+ read_mpi(incoming_pub);
+ free(gxbuf);
+ gxbuf = NULL;
+
+ if (lenp != 0) goto invval;
+
+ gcry_mpi_release(auth->their_pub);
+ auth->their_pub = incoming_pub;
+ incoming_pub = NULL;
+
+ /* Compute the encryption and MAC keys */
+ err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
+ auth->their_pub, auth->secure_session_id,
+ &(auth->secure_session_id_len),
+ &(auth->enc_c), &(auth->enc_cp),
+ &(auth->mac_m1), &(auth->mac_m1p),
+ &(auth->mac_m2), &(auth->mac_m2p));
+ if (err) goto err;
+
+ /* Check the MAC */
+ gcry_md_reset(auth->mac_m2);
+ gcry_md_write(auth->mac_m2, authstart, authend - authstart);
+ if (memcmp(macstart,
gcry_md_read(auth->mac_m2, GCRY_MD_SHA256),
20)) goto invval;
- /* Check the auth */
- err = check_pubkey_auth(auth->their_fingerprint,
- &(auth->their_keyid), authstart + 4,
- authend - authstart - 4, auth->mac_m1, auth->enc_c,
- auth->our_dh.pub, auth->their_pub);
- if (err) goto err;
-
- authstart = NULL;
- authend = NULL;
- macstart = NULL;
- free(buf);
- buf = NULL;
-
- /* Create the Signature Message */
- err = create_signature_message(auth, privkey);
- if (err) goto err;
-
- /* No error? Then we've completed our end of the
- * authentication. */
- auth->protocol_version = 2;
- auth->session_id_half = OTRL_SESSIONID_SECOND_HALF_BOLD;
- if (auth_succeeded) err = auth_succeeded(auth, asdata);
- *havemsgp = 1;
- auth->our_keyid = 0;
- auth->authstate = OTRL_AUTHSTATE_NONE;
-
- break;
+ /* Check the auth */
+ err = check_pubkey_auth(auth->their_fingerprint,
+ &(auth->their_keyid), authstart + 4,
+ authend - authstart - 4, auth->mac_m1, auth->enc_c,
+ auth->our_dh.pub, auth->their_pub);
+ if (err) goto err;
+
+ authstart = NULL;
+ authend = NULL;
+ macstart = NULL;
+ free(buf);
+ buf = NULL;
+
+ /* Create the Signature Message */
+ err = create_signature_message(auth, privkey);
+ if (err) goto err;
+
+ /* No error? Then we've completed our end of the
+ * authentication. */
+ auth->protocol_version = 2;
+ auth->session_id_half = OTRL_SESSIONID_SECOND_HALF_BOLD;
+ if (auth_succeeded) err = auth_succeeded(auth, asdata);
+ *havemsgp = 1;
+ auth->our_keyid = 0;
+ auth->authstate = OTRL_AUTHSTATE_NONE;
+
+ break;
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_DHKEY:
case OTRL_AUTHSTATE_AWAITING_SIG:
case OTRL_AUTHSTATE_V1_SETUP:
- /* Ignore this message */
- *havemsgp = 0;
- free(buf);
- buf = NULL;
- break;
- }
+ /* Ignore this message */
+ *havemsgp = 0;
+ free(buf);
+ buf = NULL;
+ break;
+ }
- return err;
+ return err;
decfail:
- err = gcry_error(GPG_ERR_NO_ERROR);
- goto err;
+ err = gcry_error(GPG_ERR_NO_ERROR);
+ goto err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(gxbuf);
- gcry_cipher_close(enc);
- gcry_mpi_release(incoming_pub);
- return err;
+ free(buf);
+ free(gxbuf);
+ gcry_cipher_close(enc);
+ gcry_mpi_release(incoming_pub);
+ return err;
}
/*
@@ -968,92 +968,92 @@ gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp = NULL;
- unsigned char *authstart, *authend, *macstart;
- size_t buflen, lenp, authlen;
- int res;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp = NULL;
+ unsigned char *authstart, *authend, *macstart;
+ size_t buflen, lenp, authlen;
+ int res;
- *havemsgp = 0;
+ *havemsgp = 0;
- res = otrl_base64_otr_decode(sigmsg, &buf, &buflen);
- if (res == -1) goto memerr;
- if (res == -2) goto invval;
+ res = otrl_base64_otr_decode(sigmsg, &buf, &buflen);
+ if (res == -1) goto memerr;
+ if (res == -2) goto invval;
- bufp = buf;
- lenp = buflen;
+ bufp = buf;
+ lenp = buflen;
- /* Header */
- if (memcmp(bufp, "\x00\x02\x12", 3)) goto invval;
- bufp += 3; lenp -= 3;
+ /* Header */
+ if (memcmp(bufp, "\x00\x02\x12", 3)) goto invval;
+ bufp += 3; lenp -= 3;
- /* auth */
- authstart = bufp;
- read_int(authlen);
- require_len(authlen);
- bufp += authlen; lenp -= authlen;
- authend = bufp;
+ /* auth */
+ authstart = bufp;
+ read_int(authlen);
+ require_len(authlen);
+ bufp += authlen; lenp -= authlen;
+ authend = bufp;
- /* MAC */
- require_len(20);
- macstart = bufp;
- bufp += 20; lenp -= 20;
+ /* MAC */
+ require_len(20);
+ macstart = bufp;
+ bufp += 20; lenp -= 20;
- if (lenp != 0) goto invval;
+ if (lenp != 0) goto invval;
- switch(auth->authstate) {
+ switch(auth->authstate) {
case OTRL_AUTHSTATE_AWAITING_SIG:
- /* Check the MAC */
- gcry_md_reset(auth->mac_m2p);
- gcry_md_write(auth->mac_m2p, authstart, authend - authstart);
- if (memcmp(macstart,
+ /* Check the MAC */
+ gcry_md_reset(auth->mac_m2p);
+ gcry_md_write(auth->mac_m2p, authstart, authend - authstart);
+ if (memcmp(macstart,
gcry_md_read(auth->mac_m2p, GCRY_MD_SHA256),
20)) goto invval;
- /* Check the auth */
- err = check_pubkey_auth(auth->their_fingerprint,
- &(auth->their_keyid), authstart + 4,
- authend - authstart - 4, auth->mac_m1p, auth->enc_cp,
- auth->our_dh.pub, auth->their_pub);
- if (err) goto err;
-
- authstart = NULL;
- authend = NULL;
- macstart = NULL;
- free(buf);
- buf = NULL;
-
- /* No error? Then we've completed our end of the
- * authentication. */
- auth->protocol_version = 2;
- auth->session_id_half = OTRL_SESSIONID_FIRST_HALF_BOLD;
- if (auth_succeeded) err = auth_succeeded(auth, asdata);
- free(auth->lastauthmsg);
- auth->lastauthmsg = NULL;
- *havemsgp = 1;
- auth->our_keyid = 0;
- auth->authstate = OTRL_AUTHSTATE_NONE;
-
- break;
+ /* Check the auth */
+ err = check_pubkey_auth(auth->their_fingerprint,
+ &(auth->their_keyid), authstart + 4,
+ authend - authstart - 4, auth->mac_m1p, auth->enc_cp,
+ auth->our_dh.pub, auth->their_pub);
+ if (err) goto err;
+
+ authstart = NULL;
+ authend = NULL;
+ macstart = NULL;
+ free(buf);
+ buf = NULL;
+
+ /* No error? Then we've completed our end of the
+ * authentication. */
+ auth->protocol_version = 2;
+ auth->session_id_half = OTRL_SESSIONID_FIRST_HALF_BOLD;
+ if (auth_succeeded) err = auth_succeeded(auth, asdata);
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = NULL;
+ *havemsgp = 1;
+ auth->our_keyid = 0;
+ auth->authstate = OTRL_AUTHSTATE_NONE;
+
+ break;
case OTRL_AUTHSTATE_NONE:
case OTRL_AUTHSTATE_AWAITING_DHKEY:
case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
case OTRL_AUTHSTATE_V1_SETUP:
- /* Ignore this message */
- *havemsgp = 0;
- break;
- }
+ /* Ignore this message */
+ *havemsgp = 0;
+ break;
+ }
- return err;
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- return err;
+ free(buf);
+ return err;
}
/* Version 1 routines, for compatibility */
@@ -1066,75 +1066,75 @@ err:
static gcry_error_t create_v1_key_exchange_message(OtrlAuthInfo *auth,
unsigned char reply, OtrlPrivKey *privkey)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- unsigned char *buf = NULL, *bufp = NULL, *sigbuf = NULL;
- size_t lenp, ourpublen, totallen, siglen;
- unsigned char hashbuf[20];
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ unsigned char *buf = NULL, *bufp = NULL, *sigbuf = NULL;
+ size_t lenp, ourpublen, totallen, siglen;
+ unsigned char hashbuf[20];
- if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA) {
+ if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA) {
return gpg_error(GPG_ERR_INV_VALUE);
- }
+ }
- /* How big is the DH public key? */
- gcry_mpi_print(format, NULL, 0, &ourpublen, auth->our_dh.pub);
+ /* How big is the DH public key? */
+ gcry_mpi_print(format, NULL, 0, &ourpublen, auth->our_dh.pub);
- totallen = 3 + 1 + privkey->pubkey_datalen + 4 + 4 + ourpublen + 40;
- buf = malloc(totallen);
- if (buf == NULL) goto memerr;
+ totallen = 3 + 1 + privkey->pubkey_datalen + 4 + 4 + ourpublen + 40;
+ buf = malloc(totallen);
+ if (buf == NULL) goto memerr;
- bufp = buf;
- lenp = totallen;
+ bufp = buf;
+ lenp = totallen;
- memmove(bufp, "\x00\x01\x0a", 3); /* header */
- debug_data("Header", bufp, 3);
- bufp += 3; lenp -= 3;
+ memmove(bufp, "\x00\x01\x0a", 3); /* header */
+ debug_data("Header", bufp, 3);
+ bufp += 3; lenp -= 3;
- bufp[0] = reply;
- debug_data("Reply", bufp, 1);
- bufp += 1; lenp -= 1;
+ bufp[0] = reply;
+ debug_data("Reply", bufp, 1);
+ bufp += 1; lenp -= 1;
- memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
- debug_data("Pubkey", bufp, privkey->pubkey_datalen);
- bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
+ memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
+ debug_data("Pubkey", bufp, privkey->pubkey_datalen);
+ bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
- write_int(auth->our_keyid);
- debug_int("Keyid", bufp-4);
+ write_int(auth->our_keyid);
+ debug_int("Keyid", bufp-4);
- write_mpi(auth->our_dh.pub, ourpublen, "D-H y");
+ write_mpi(auth->our_dh.pub, ourpublen, "D-H y");
- /* Hash all the data written so far, and sign the hash */
- gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
+ /* Hash all the data written so far, and sign the hash */
+ gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
- err = otrl_privkey_sign(&sigbuf, &siglen, privkey, hashbuf, 20);
- if (err) goto err;
+ err = otrl_privkey_sign(&sigbuf, &siglen, privkey, hashbuf, 20);
+ if (err) goto err;
- if (siglen != 40) goto invval;
- memmove(bufp, sigbuf, 40);
- debug_data("Signature", bufp, 40);
- bufp += 40; lenp -= 40;
- free(sigbuf);
- sigbuf = NULL;
+ if (siglen != 40) goto invval;
+ memmove(bufp, sigbuf, 40);
+ debug_data("Signature", bufp, 40);
+ bufp += 40; lenp -= 40;
+ free(sigbuf);
+ sigbuf = NULL;
- assert(lenp == 0);
+ assert(lenp == 0);
- free(auth->lastauthmsg);
- auth->lastauthmsg = otrl_base64_otr_encode(buf, totallen);
- if (auth->lastauthmsg == NULL) goto memerr;
- free(buf);
- buf = NULL;
+ free(auth->lastauthmsg);
+ auth->lastauthmsg = otrl_base64_otr_encode(buf, totallen);
+ if (auth->lastauthmsg == NULL) goto memerr;
+ free(buf);
+ buf = NULL;
- return err;
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- free(sigbuf);
- return err;
+ free(buf);
+ free(sigbuf);
+ return err;
}
/*
@@ -1147,27 +1147,27 @@ err:
gcry_error_t otrl_auth_start_v1(OtrlAuthInfo *auth, DH_keypair *our_dh,
unsigned int our_keyid, OtrlPrivKey *privkey)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- /* Clear out this OtrlAuthInfo and start over */
- otrl_auth_clear(auth);
- auth->initiated = 1;
+ /* Clear out this OtrlAuthInfo and start over */
+ otrl_auth_clear(auth);
+ auth->initiated = 1;
- /* Import the given DH keypair, or else create a fresh one */
- if (our_dh) {
+ /* Import the given DH keypair, or else create a fresh one */
+ if (our_dh) {
otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
auth->our_keyid = our_keyid;
- } else {
+ } else {
otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
auth->our_keyid = 1;
- }
+ }
- err = create_v1_key_exchange_message(auth, 0, privkey);
- if (!err) {
+ err = create_v1_key_exchange_message(auth, 0, privkey);
+ if (!err) {
auth->authstate = OTRL_AUTHSTATE_V1_SETUP;
- }
+ }
- return err;
+ return err;
}
/*
@@ -1184,133 +1184,133 @@ gcry_error_t otrl_auth_handle_v1_key_exchange(OtrlAuthInfo *auth,
gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
void *asdata)
{
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- unsigned char *buf = NULL, *bufp = NULL;
- unsigned char *fingerprintstart, *fingerprintend;
- unsigned char fingerprintbuf[20], hashbuf[20];
- gcry_mpi_t p, q, g, y, received_pub = NULL;
- gcry_sexp_t pubs = NULL;
- size_t buflen, lenp;
- unsigned char received_reply;
- unsigned int received_keyid;
- int res;
-
- *havemsgp = 0;
-
- res = otrl_base64_otr_decode(keyexchmsg, &buf, &buflen);
- if (res == -1) goto memerr;
- if (res == -2) goto invval;
-
- bufp = buf;
- lenp = buflen;
-
- /* Header */
- require_len(3);
- if (memcmp(bufp, "\x00\x01\x0a", 3)) goto invval;
- bufp += 3; lenp -= 3;
-
- /* Reply */
- require_len(1);
- received_reply = bufp[0];
- bufp += 1; lenp -= 1;
-
- /* Public Key */
- fingerprintstart = bufp;
- read_mpi(p);
- read_mpi(q);
- read_mpi(g);
- read_mpi(y);
- fingerprintend = bufp;
- gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbuf,
- fingerprintstart, fingerprintend-fingerprintstart);
- gcry_sexp_build(&pubs, NULL,
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ unsigned char *buf = NULL, *bufp = NULL;
+ unsigned char *fingerprintstart, *fingerprintend;
+ unsigned char fingerprintbuf[20], hashbuf[20];
+ gcry_mpi_t p, q, g, y, received_pub = NULL;
+ gcry_sexp_t pubs = NULL;
+ size_t buflen, lenp;
+ unsigned char received_reply;
+ unsigned int received_keyid;
+ int res;
+
+ *havemsgp = 0;
+
+ res = otrl_base64_otr_decode(keyexchmsg, &buf, &buflen);
+ if (res == -1) goto memerr;
+ if (res == -2) goto invval;
+
+ bufp = buf;
+ lenp = buflen;
+
+ /* Header */
+ require_len(3);
+ if (memcmp(bufp, "\x00\x01\x0a", 3)) goto invval;
+ bufp += 3; lenp -= 3;
+
+ /* Reply */
+ require_len(1);
+ received_reply = bufp[0];
+ bufp += 1; lenp -= 1;
+
+ /* Public Key */
+ fingerprintstart = bufp;
+ read_mpi(p);
+ read_mpi(q);
+ read_mpi(g);
+ read_mpi(y);
+ fingerprintend = bufp;
+ gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbuf,
+ fingerprintstart, fingerprintend-fingerprintstart);
+ gcry_sexp_build(&pubs, NULL,
"(public-key (dsa (p %m)(q %m)(g %m)(y %m)))", p, q, g, y);
- gcry_mpi_release(p);
- gcry_mpi_release(q);
- gcry_mpi_release(g);
- gcry_mpi_release(y);
-
- /* keyid */
- read_int(received_keyid);
- if (received_keyid == 0) goto invval;
-
- /* D-H pubkey */
- read_mpi(received_pub);
-
- /* Verify the signature */
- if (lenp != 40) goto invval;
- gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
- err = otrl_privkey_verify(bufp, lenp, OTRL_PUBKEY_TYPE_DSA,
- pubs, hashbuf, 20);
- if (err) goto err;
- gcry_sexp_release(pubs);
- pubs = NULL;
- free(buf);
- buf = NULL;
-
- if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP && received_reply == 0x01) {
+ gcry_mpi_release(p);
+ gcry_mpi_release(q);
+ gcry_mpi_release(g);
+ gcry_mpi_release(y);
+
+ /* keyid */
+ read_int(received_keyid);
+ if (received_keyid == 0) goto invval;
+
+ /* D-H pubkey */
+ read_mpi(received_pub);
+
+ /* Verify the signature */
+ if (lenp != 40) goto invval;
+ gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
+ err = otrl_privkey_verify(bufp, lenp, OTRL_PUBKEY_TYPE_DSA,
+ pubs, hashbuf, 20);
+ if (err) goto err;
+ gcry_sexp_release(pubs);
+ pubs = NULL;
+ free(buf);
+ buf = NULL;
+
+ if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP && received_reply == 0x01) {
/* They're replying to something we never sent. We must be
* logged in more than once; ignore the message. */
err = gpg_error(GPG_ERR_NO_ERROR);
goto err;
- }
+ }
- if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP) {
+ if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP) {
/* Clear the auth and start over */
otrl_auth_clear(auth);
- }
+ }
- /* Everything checked out */
- auth->their_keyid = received_keyid;
- gcry_mpi_release(auth->their_pub);
- auth->their_pub = received_pub;
- received_pub = NULL;
- memmove(auth->their_fingerprint, fingerprintbuf, 20);
+ /* Everything checked out */
+ auth->their_keyid = received_keyid;
+ gcry_mpi_release(auth->their_pub);
+ auth->their_pub = received_pub;
+ received_pub = NULL;
+ memmove(auth->their_fingerprint, fingerprintbuf, 20);
- if (received_reply == 0x01) {
+ if (received_reply == 0x01) {
/* Don't send a reply to this. */
*havemsgp = 0;
- } else {
+ } else {
/* Import the given DH keypair, or else create a fresh one */
if (our_dh) {
- otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
- auth->our_keyid = our_keyid;
+ otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
+ auth->our_keyid = our_keyid;
} else if (auth->our_keyid == 0) {
- otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
- auth->our_keyid = 1;
+ otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+ auth->our_keyid = 1;
}
/* Reply with our own Key Exchange Message */
err = create_v1_key_exchange_message(auth, 1, privkey);
if (err) goto err;
*havemsgp = 1;
- }
+ }
- /* Compute the session id */
- err = otrl_dh_compute_v1_session_id(&(auth->our_dh),
- auth->their_pub, auth->secure_session_id,
- &(auth->secure_session_id_len),
- &(auth->session_id_half));
- if (err) goto err;
+ /* Compute the session id */
+ err = otrl_dh_compute_v1_session_id(&(auth->our_dh),
+ auth->their_pub, auth->secure_session_id,
+ &(auth->secure_session_id_len),
+ &(auth->session_id_half));
+ if (err) goto err;
- /* We've completed our end of the authentication */
- auth->protocol_version = 1;
- if (auth_succeeded) err = auth_succeeded(auth, asdata);
- auth->our_keyid = 0;
- auth->authstate = OTRL_AUTHSTATE_NONE;
+ /* We've completed our end of the authentication */
+ auth->protocol_version = 1;
+ if (auth_succeeded) err = auth_succeeded(auth, asdata);
+ auth->our_keyid = 0;
+ auth->authstate = OTRL_AUTHSTATE_NONE;
- return err;
+ return err;
invval:
- err = gcry_error(GPG_ERR_INV_VALUE);
- goto err;
+ err = gcry_error(GPG_ERR_INV_VALUE);
+ goto err;
memerr:
- err = gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
err:
- free(buf);
- gcry_sexp_release(pubs);
- gcry_mpi_release(received_pub);
- return err;
+ free(buf);
+ gcry_sexp_release(pubs);
+ gcry_mpi_release(received_pub);
+ return err;
}
#ifdef OTRL_TESTING_AUTH
@@ -1321,93 +1321,93 @@ err:
static gcry_error_t starting(const OtrlAuthInfo *auth, void *asdata)
{
- char *name = asdata;
+ char *name = asdata;
- fprintf(stderr, "\nStarting ENCRYPTED mode for %s (v%d).\n", name, auth->protocol_version);
+ fprintf(stderr, "\nStarting ENCRYPTED mode for %s (v%d).\n", name, auth->protocol_version);
- fprintf(stderr, "\nour_dh (%d):", auth->our_keyid);
- gcry_mpi_dump(auth->our_dh.pub);
- fprintf(stderr, "\ntheir_pub (%d):", auth->their_keyid);
- gcry_mpi_dump(auth->their_pub);
+ fprintf(stderr, "\nour_dh (%d):", auth->our_keyid);
+ gcry_mpi_dump(auth->our_dh.pub);
+ fprintf(stderr, "\ntheir_pub (%d):", auth->their_keyid);
+ gcry_mpi_dump(auth->their_pub);
- debug_data("\nTheir fingerprint", auth->their_fingerprint, 20);
- debug_data("\nSecure session id", auth->secure_session_id,
- auth->secure_session_id_len);
- fprintf(stderr, "Sessionid half: %d\n\n", auth->session_id_half);
+ debug_data("\nTheir fingerprint", auth->their_fingerprint, 20);
+ debug_data("\nSecure session id", auth->secure_session_id,
+ auth->secure_session_id_len);
+ fprintf(stderr, "Sessionid half: %d\n\n", auth->session_id_half);
- return gpg_error(GPG_ERR_NO_ERROR);
+ return gpg_error(GPG_ERR_NO_ERROR);
}
int main(int argc, char **argv)
{
- OtrlAuthInfo alice, bob;
- gcry_error_t err;
- int havemsg;
- OtrlUserState us;
- OtrlPrivKey *alicepriv, *bobpriv;
-
- otrl_mem_init();
- otrl_dh_init();
- otrl_auth_new(&alice);
- otrl_auth_new(&bob);
-
- us = otrl_userstate_create();
- otrl_privkey_read(us, "/home/iang/.gaim/otr.private_key");
- alicepriv = otrl_privkey_find(us, "oneeyedian", "prpl-oscar");
- bobpriv = otrl_privkey_find(us, "otr4ian", "prpl-oscar");
-
- printf("\n\n ***** V2 *****\n\n");
-
- err = otrl_auth_start_v2(&bob, NULL, 0);
- CHECK_ERR
- printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
- err = otrl_auth_handle_commit(&alice, bob.lastauthmsg, NULL, 0);
- CHECK_ERR
- printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
- err = otrl_auth_handle_key(&bob, alice.lastauthmsg, &havemsg, bobpriv);
- CHECK_ERR
- if (havemsg) {
+ OtrlAuthInfo alice, bob;
+ gcry_error_t err;
+ int havemsg;
+ OtrlUserState us;
+ OtrlPrivKey *alicepriv, *bobpriv;
+
+ otrl_mem_init();
+ otrl_dh_init();
+ otrl_auth_new(&alice);
+ otrl_auth_new(&bob);
+
+ us = otrl_userstate_create();
+ otrl_privkey_read(us, "/home/iang/.gaim/otr.private_key");
+ alicepriv = otrl_privkey_find(us, "oneeyedian", "prpl-oscar");
+ bobpriv = otrl_privkey_find(us, "otr4ian", "prpl-oscar");
+
+ printf("\n\n ***** V2 *****\n\n");
+
+ err = otrl_auth_start_v2(&bob, NULL, 0);
+ CHECK_ERR
printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
- } else {
+ err = otrl_auth_handle_commit(&alice, bob.lastauthmsg, NULL, 0);
+ CHECK_ERR
+ printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
+ err = otrl_auth_handle_key(&bob, alice.lastauthmsg, &havemsg, bobpriv);
+ CHECK_ERR
+ if (havemsg) {
+ printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
+ } else {
printf("\nIGNORE\n\n");
- }
- err = otrl_auth_handle_revealsig(&alice, bob.lastauthmsg, &havemsg,
- alicepriv, starting, "Alice");
- CHECK_ERR
- if (havemsg) {
+ }
+ err = otrl_auth_handle_revealsig(&alice, bob.lastauthmsg, &havemsg,
+ alicepriv, starting, "Alice");
+ CHECK_ERR
+ if (havemsg) {
printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
- } else {
+ } else {
printf("\nIGNORE\n\n");
- }
- err = otrl_auth_handle_signature(&bob, alice.lastauthmsg, &havemsg,
- starting, "Bob");
- CHECK_ERR
-
- printf("\n\n ***** V1 *****\n\n");
-
- err = otrl_auth_start_v1(&bob, NULL, 0, bobpriv);
- CHECK_ERR
- printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
- err = otrl_auth_handle_v1_key_exchange(&alice, bob.lastauthmsg,
- &havemsg, alicepriv, NULL, 0, starting, "Alice");
- CHECK_ERR
- if (havemsg) {
+ }
+ err = otrl_auth_handle_signature(&bob, alice.lastauthmsg, &havemsg,
+ starting, "Bob");
+ CHECK_ERR
+
+ printf("\n\n ***** V1 *****\n\n");
+
+ err = otrl_auth_start_v1(&bob, NULL, 0, bobpriv);
+ CHECK_ERR
+ printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
+ err = otrl_auth_handle_v1_key_exchange(&alice, bob.lastauthmsg,
+ &havemsg, alicepriv, NULL, 0, starting, "Alice");
+ CHECK_ERR
+ if (havemsg) {
printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
- } else {
+ } else {
printf("\nIGNORE\n\n");
- }
- err = otrl_auth_handle_v1_key_exchange(&bob, alice.lastauthmsg,
- &havemsg, bobpriv, NULL, 0, starting, "Bob");
- CHECK_ERR
- if (havemsg) {
+ }
+ err = otrl_auth_handle_v1_key_exchange(&bob, alice.lastauthmsg,
+ &havemsg, bobpriv, NULL, 0, starting, "Bob");
+ CHECK_ERR
+ if (havemsg) {
printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
- } else {
+ } else {
printf("\nIGNORE\n\n");
- }
+ }
- otrl_userstate_free(us);
- otrl_auth_clear(&alice);
- otrl_auth_clear(&bob);
- return 0;
+ otrl_userstate_free(us);
+ otrl_auth_clear(&alice);
+ otrl_auth_clear(&bob);
+ return 0;
}
#endif
diff --git a/libotr-3.2.0/src/auth.h b/libotr-3.2.0/src/auth.h
index 6de75dd..ac9c668 100644
--- a/libotr-3.2.0/src/auth.h
+++ b/libotr-3.2.0/src/auth.h
@@ -24,52 +24,52 @@
#include "dh.h"
typedef enum {
- OTRL_AUTHSTATE_NONE,
- OTRL_AUTHSTATE_AWAITING_DHKEY,
- OTRL_AUTHSTATE_AWAITING_REVEALSIG,
- OTRL_AUTHSTATE_AWAITING_SIG,
- OTRL_AUTHSTATE_V1_SETUP
+ OTRL_AUTHSTATE_NONE,
+ OTRL_AUTHSTATE_AWAITING_DHKEY,
+ OTRL_AUTHSTATE_AWAITING_REVEALSIG,
+ OTRL_AUTHSTATE_AWAITING_SIG,
+ OTRL_AUTHSTATE_V1_SETUP
} OtrlAuthState;
typedef struct {
- OtrlAuthState authstate; /* Our state */
+ OtrlAuthState authstate; /* Our state */
- DH_keypair our_dh; /* Our D-H key */
- unsigned int our_keyid; /* ...and its keyid */
+ DH_keypair our_dh; /* Our D-H key */
+ unsigned int our_keyid; /* ...and its keyid */
- unsigned char *encgx; /* The encrypted value of g^x */
- size_t encgx_len; /* ...and its length */
- unsigned char r[16]; /* The encryption key */
+ unsigned char *encgx; /* The encrypted value of g^x */
+ size_t encgx_len; /* ...and its length */
+ unsigned char r[16]; /* The encryption key */
- unsigned char hashgx[32]; /* SHA256(g^x) */
+ unsigned char hashgx[32]; /* SHA256(g^x) */
- gcry_mpi_t their_pub; /* Their D-H public key */
- unsigned int their_keyid; /* ...and its keyid */
+ gcry_mpi_t their_pub; /* Their D-H public key */
+ unsigned int their_keyid; /* ...and its keyid */
- gcry_cipher_hd_t enc_c, enc_cp; /* c and c' encryption keys */
- gcry_md_hd_t mac_m1, mac_m1p; /* m1 and m1' MAC keys */
- gcry_md_hd_t mac_m2, mac_m2p; /* m2 and m2' MAC keys */
+ gcry_cipher_hd_t enc_c, enc_cp; /* c and c' encryption keys */
+ gcry_md_hd_t mac_m1, mac_m1p; /* m1 and m1' MAC keys */
+ gcry_md_hd_t mac_m2, mac_m2p; /* m2 and m2' MAC keys */
- unsigned char their_fingerprint[20]; /* The fingerprint of their
- long-term signing key */
+ unsigned char their_fingerprint[20]; /* The fingerprint of their
+ long-term signing key */
- int initiated; /* Did we initiate this
- authentication? */
+ int initiated; /* Did we initiate this
+ authentication? */
- unsigned int protocol_version; /* The protocol version number
- used to authenticate. */
+ unsigned int protocol_version; /* The protocol version number
+ used to authenticate. */
- unsigned char secure_session_id[20]; /* The secure session id */
- size_t secure_session_id_len; /* And its actual length,
- which may be either 20 (for
- v1) or 8 (for v2) */
- OtrlSessionIdHalf session_id_half; /* Which half of the session
- id gets shown in bold */
+ unsigned char secure_session_id[20]; /* The secure session id */
+ size_t secure_session_id_len; /* And its actual length,
+ which may be either 20 (for
+ v1) or 8 (for v2) */
+ OtrlSessionIdHalf session_id_half; /* Which half of the session
+ id gets shown in bold */
- char *lastauthmsg; /* The last auth message
- (base-64 encoded) we sent,
- in case we need to
- retransmit it. */
+ char *lastauthmsg; /* The last auth message
+ (base-64 encoded) we sent,
+ in case we need to
+ retransmit it. */
} OtrlAuthInfo;
#include "privkey-t.h"
diff --git a/libotr-3.2.0/src/context.c b/libotr-3.2.0/src/context.c
index e1601ec..8807b89 100644
--- a/libotr-3.2.0/src/context.c
+++ b/libotr-3.2.0/src/context.c
@@ -31,60 +31,60 @@
static ConnContext * new_context(const char * user, const char * accountname,
const char * protocol)
{
- ConnContext * context;
- OtrlSMState *smstate;
- context = malloc(sizeof(*context));
- assert(context != NULL);
- context->username = strdup(user);
- context->accountname = strdup(accountname);
- context->protocol = strdup(protocol);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
- context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
- otrl_auth_new(&(context->auth));
+ ConnContext * context;
+ OtrlSMState *smstate;
+ context = malloc(sizeof(*context));
+ assert(context != NULL);
+ context->username = _strdup(user);
+ context->accountname = _strdup(accountname);
+ context->protocol = _strdup(protocol);
+ context->fragment = NULL;
+ context->fragment_len = 0;
+ context->fragment_n = 0;
+ context->fragment_k = 0;
+ context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
+ otrl_auth_new(&(context->auth));
- smstate = malloc(sizeof(OtrlSMState));
- assert(smstate != NULL);
- otrl_sm_state_new(smstate);
- context->smstate = smstate;
+ smstate = malloc(sizeof(OtrlSMState));
+ assert(smstate != NULL);
+ otrl_sm_state_new(smstate);
+ context->smstate = smstate;
- context->fingerprint_root.fingerprint = NULL;
- context->fingerprint_root.context = context;
- context->fingerprint_root.next = NULL;
- context->fingerprint_root.tous = NULL;
- context->active_fingerprint = NULL;
- context->their_keyid = 0;
- context->their_y = NULL;
- context->their_old_y = NULL;
- context->our_keyid = 0;
- context->our_dh_key.groupid = 0;
- context->our_dh_key.priv = NULL;
- context->our_dh_key.pub = NULL;
- context->our_old_dh_key.groupid = 0;
- context->our_old_dh_key.priv = NULL;
- context->our_old_dh_key.pub = NULL;
- otrl_dh_session_blank(&(context->sesskeys[0][0]));
- otrl_dh_session_blank(&(context->sesskeys[0][1]));
- otrl_dh_session_blank(&(context->sesskeys[1][0]));
- otrl_dh_session_blank(&(context->sesskeys[1][1]));
- memset(context->sessionid, 0, 20);
- context->sessionid_len = 0;
- context->protocol_version = 0;
- context->numsavedkeys = 0;
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
- context->saved_mac_keys = NULL;
- context->generation = 0;
- context->lastsent = 0;
- context->lastmessage = NULL;
- context->may_retransmit = 0;
- context->otr_offer = OFFER_NOT;
- context->app_data = NULL;
- context->app_data_free = NULL;
- context->next = NULL;
- return context;
+ context->fingerprint_root.fingerprint = NULL;
+ context->fingerprint_root.context = context;
+ context->fingerprint_root.next = NULL;
+ context->fingerprint_root.tous = NULL;
+ context->active_fingerprint = NULL;
+ context->their_keyid = 0;
+ context->their_y = NULL;
+ context->their_old_y = NULL;
+ context->our_keyid = 0;
+ context->our_dh_key.groupid = 0;
+ context->our_dh_key.priv = NULL;
+ context->our_dh_key.pub = NULL;
+ context->our_old_dh_key.groupid = 0;
+ context->our_old_dh_key.priv = NULL;
+ context->our_old_dh_key.pub = NULL;
+ otrl_dh_session_blank(&(context->sesskeys[0][0]));
+ otrl_dh_session_blank(&(context->sesskeys[0][1]));
+ otrl_dh_session_blank(&(context->sesskeys[1][0]));
+ otrl_dh_session_blank(&(context->sesskeys[1][1]));
+ memset(context->sessionid, 0, 20);
+ context->sessionid_len = 0;
+ context->protocol_version = 0;
+ context->numsavedkeys = 0;
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
+ context->saved_mac_keys = NULL;
+ context->generation = 0;
+ context->lastsent = 0;
+ context->lastmessage = NULL;
+ context->may_retransmit = 0;
+ context->otr_offer = OFFER_NOT;
+ context->app_data = NULL;
+ context->app_data_free = NULL;
+ context->next = NULL;
+ return context;
}
ConnContext * otrl_context_new(const char * user, const char * accountname,
@@ -103,40 +103,40 @@ ConnContext * otrl_context_find(OtrlUserState us, const char *user,
int *addedp,
void (*add_app_data)(void *data, ConnContext *context), void *data)
{
- ConnContext ** curp;
- int usercmp = 1, acctcmp = 1, protocmp = 1;
- if (addedp) *addedp = 0;
- if (!user || !accountname || !protocol) return NULL;
- for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
- if ((usercmp = strcmp((*curp)->username, user)) > 0 ||
+ ConnContext ** curp;
+ int usercmp = 1, acctcmp = 1, protocmp = 1;
+ if (addedp) *addedp = 0;
+ if (!user || !accountname || !protocol) return NULL;
+ for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
+ if ((usercmp = strcmp((*curp)->username, user)) > 0 ||
(usercmp == 0 &&
(acctcmp = strcmp((*curp)->accountname, accountname)) > 0) ||
(usercmp == 0 && acctcmp == 0 &&
(protocmp = strcmp((*curp)->protocol, protocol)) >= 0))
- /* We're at the right place in the list. We've either found
- * it, or gone too far. */
- break;
- }
- if (usercmp == 0 && acctcmp == 0 && protocmp == 0) {
+ /* We're at the right place in the list. We've either found
+ * it, or gone too far. */
+ break;
+ }
+ if (usercmp == 0 && acctcmp == 0 && protocmp == 0) {
/* Found it! */
return *curp;
- }
- if (add_if_missing) {
+ }
+ if (add_if_missing) {
ConnContext *newctx;
if (addedp) *addedp = 1;
newctx = new_context(user, accountname, protocol);
newctx->next = *curp;
if (*curp) {
- (*curp)->tous = &(newctx->next);
+ (*curp)->tous = &(newctx->next);
}
*curp = newctx;
newctx->tous = curp;
if (add_app_data) {
- add_app_data(data, *curp);
+ add_app_data(data, *curp);
}
return *curp;
- }
- return NULL;
+ }
+ return NULL;
}
/* Find a fingerprint in a given context, perhaps adding it if not
@@ -144,14 +144,14 @@ ConnContext * otrl_context_find(OtrlUserState us, const char *user,
Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
unsigned char fingerprint[20], int add_if_missing, int *addedp)
{
- Fingerprint *f = context->fingerprint_root.next;
- if (addedp) *addedp = 0;
- while(f) {
+ Fingerprint *f = context->fingerprint_root.next;
+ if (addedp) *addedp = 0;
+ while(f) {
if (!memcmp(f->fingerprint, fingerprint, 20)) return f;
f = f->next;
- }
- /* Didn't find it. */
- if (add_if_missing) {
+ }
+ /* Didn't find it. */
+ if (add_if_missing) {
if (addedp) *addedp = 1;
f = malloc(sizeof(*f));
assert(f != NULL);
@@ -162,22 +162,22 @@ Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
f->trust = NULL;
f->next = context->fingerprint_root.next;
if (f->next) {
- f->next->tous = &(f->next);
+ f->next->tous = &(f->next);
}
context->fingerprint_root.next = f;
f->tous = &(context->fingerprint_root.next);
return f;
- }
- return NULL;
+ }
+ return NULL;
}
/* Set the trust level for a given fingerprint */
void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
{
- if (fprint == NULL) return;
+ if (fprint == NULL) return;
- free(fprint->trust);
- fprint->trust = trust ? strdup(trust) : NULL;
+ free(fprint->trust);
+ fprint->trust = trust ? _strdup(trust) : NULL;
}
/* Set the preshared secret for a given fingerprint. Note that this
@@ -186,65 +186,65 @@ void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
void otrl_context_set_preshared_secret(ConnContext *context,
const unsigned char *secret, size_t secret_len)
{
- free(context->preshared_secret);
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
+ free(context->preshared_secret);
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
- if (secret_len) {
+ if (secret_len) {
context->preshared_secret = malloc(secret_len);
if (context->preshared_secret) {
- memmove(context->preshared_secret, secret, secret_len);
- context->preshared_secret_len = secret_len;
+ memmove(context->preshared_secret, secret, secret_len);
+ context->preshared_secret_len = secret_len;
+ }
}
- }
}
/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
void otrl_context_force_finished(ConnContext *context)
{
- context->msgstate = OTRL_MSGSTATE_FINISHED;
- otrl_auth_clear(&(context->auth));
- free(context->fragment);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
- context->active_fingerprint = NULL;
- context->their_keyid = 0;
- gcry_mpi_release(context->their_y);
- context->their_y = NULL;
- gcry_mpi_release(context->their_old_y);
- context->their_old_y = NULL;
- context->our_keyid = 0;
- otrl_dh_keypair_free(&(context->our_dh_key));
- otrl_dh_keypair_free(&(context->our_old_dh_key));
- otrl_dh_session_free(&(context->sesskeys[0][0]));
- otrl_dh_session_free(&(context->sesskeys[0][1]));
- otrl_dh_session_free(&(context->sesskeys[1][0]));
- otrl_dh_session_free(&(context->sesskeys[1][1]));
- memset(context->sessionid, 0, 20);
- context->sessionid_len = 0;
- free(context->preshared_secret);
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
- context->protocol_version = 0;
- context->numsavedkeys = 0;
- free(context->saved_mac_keys);
- context->saved_mac_keys = NULL;
- gcry_free(context->lastmessage);
- context->lastmessage = NULL;
- context->may_retransmit = 0;
- otrl_sm_state_free(context->smstate);
+ context->msgstate = OTRL_MSGSTATE_FINISHED;
+ otrl_auth_clear(&(context->auth));
+ free(context->fragment);
+ context->fragment = NULL;
+ context->fragment_len = 0;
+ context->fragment_n = 0;
+ context->fragment_k = 0;
+ context->active_fingerprint = NULL;
+ context->their_keyid = 0;
+ gcry_mpi_release(context->their_y);
+ context->their_y = NULL;
+ gcry_mpi_release(context->their_old_y);
+ context->their_old_y = NULL;
+ context->our_keyid = 0;
+ otrl_dh_keypair_free(&(context->our_dh_key));
+ otrl_dh_keypair_free(&(context->our_old_dh_key));
+ otrl_dh_session_free(&(context->sesskeys[0][0]));
+ otrl_dh_session_free(&(context->sesskeys[0][1]));
+ otrl_dh_session_free(&(context->sesskeys[1][0]));
+ otrl_dh_session_free(&(context->sesskeys[1][1]));
+ memset(context->sessionid, 0, 20);
+ context->sessionid_len = 0;
+ free(context->preshared_secret);
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
+ context->protocol_version = 0;
+ context->numsavedkeys = 0;
+ free(context->saved_mac_keys);
+ context->saved_mac_keys = NULL;
+ gcry_free(context->lastmessage);
+ context->lastmessage = NULL;
+ context->may_retransmit = 0;
+ otrl_sm_state_free(context->smstate);
}
/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
void otrl_context_force_plaintext(ConnContext *context)
{
- /* First clean up everything we'd need to do for the FINISHED state */
- otrl_context_force_finished(context);
+ /* First clean up everything we'd need to do for the FINISHED state */
+ otrl_context_force_finished(context);
- /* And just set the state properly */
- context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
+ /* And just set the state properly */
+ context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
}
/* Forget a fingerprint (so long as it's not the active one. If it's a
@@ -255,76 +255,76 @@ void otrl_context_force_plaintext(ConnContext *context)
void otrl_context_forget_fingerprint(Fingerprint *fprint,
int and_maybe_context)
{
- ConnContext *context = fprint->context;
- if (fprint == &(context->fingerprint_root)) {
+ ConnContext *context = fprint->context;
+ if (fprint == &(context->fingerprint_root)) {
if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
and_maybe_context) {
- otrl_context_forget(context);
+ otrl_context_forget(context);
}
- } else {
+ } else {
if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
context->active_fingerprint != fprint) {
- free(fprint->fingerprint);
- free(fprint->trust);
- *(fprint->tous) = fprint->next;
- if (fprint->next) {
+ free(fprint->fingerprint);
+ free(fprint->trust);
+ *(fprint->tous) = fprint->next;
+ if (fprint->next) {
fprint->next->tous = fprint->tous;
- }
- free(fprint);
- if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
- context->fingerprint_root.next == NULL &&
- and_maybe_context) {
+ }
+ free(fprint);
+ if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
+ context->fingerprint_root.next == NULL &&
+ and_maybe_context) {
/* We just deleted the only fingerprint. Forget the
* whole thing. */
otrl_context_forget(context);
- }
+ }
+ }
}
- }
}
/* Forget a whole context, so long as it's PLAINTEXT. */
void otrl_context_forget(ConnContext *context)
{
- if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT) return;
+ if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT) return;
- /* Just to be safe, force to plaintext. This also frees any
- * extraneous data lying around. */
- otrl_context_force_plaintext(context);
+ /* Just to be safe, force to plaintext. This also frees any
+ * extraneous data lying around. */
+ otrl_context_force_plaintext(context);
- /* First free all the Fingerprints */
- while(context->fingerprint_root.next) {
+ /* First free all the Fingerprints */
+ while(context->fingerprint_root.next) {
otrl_context_forget_fingerprint(context->fingerprint_root.next, 0);
- }
- /* Now free all the dynamic info here */
- free(context->username);
- free(context->accountname);
- free(context->protocol);
- free(context->smstate);
- context->username = NULL;
- context->accountname = NULL;
- context->protocol = NULL;
- context->smstate = NULL;
+ }
+ /* Now free all the dynamic info here */
+ free(context->username);
+ free(context->accountname);
+ free(context->protocol);
+ free(context->smstate);
+ context->username = NULL;
+ context->accountname = NULL;
+ context->protocol = NULL;
+ context->smstate = NULL;
- /* Free the application data, if it exists */
- if (context->app_data && context->app_data_free) {
+ /* Free the application data, if it exists */
+ if (context->app_data && context->app_data_free) {
(context->app_data_free)(context->app_data);
context->app_data = NULL;
- }
+ }
- /* Fix the list linkages */
- *(context->tous) = context->next;
- if (context->next) {
+ /* Fix the list linkages */
+ *(context->tous) = context->next;
+ if (context->next) {
context->next->tous = context->tous;
- }
+ }
- free(context);
+ free(context);
}
/* Forget all the contexts in a given OtrlUserState. */
void otrl_context_forget_all(OtrlUserState us)
{
- while (us->context_root) {
+ while (us->context_root) {
otrl_context_force_plaintext(us->context_root);
otrl_context_forget(us->context_root);
- }
+ }
}
diff --git a/libotr-3.2.0/src/message.c b/libotr-3.2.0/src/message.c
index 704bb5c..06c3347 100644
--- a/libotr-3.2.0/src/message.c
+++ b/libotr-3.2.0/src/message.c
@@ -45,7 +45,7 @@ extern unsigned int otrl_api_version;
/* Deallocate a message allocated by other otrl_message_* routines. */
void otrl_message_free(char *message)
{
- free(message);
+ free(message);
}
/* Handle a message about to be sent to the network. It is safe to pass
@@ -76,62 +76,62 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
void (*add_appdata)(void *data, ConnContext *context),
void *data)
{
- struct context * context;
- char * msgtosend;
- gcry_error_t err;
- OtrlPolicy policy = OTRL_POLICY_DEFAULT;
- int context_added = 0;
+ struct context * context;
+ char * msgtosend;
+ gcry_error_t err;
+ OtrlPolicy policy = OTRL_POLICY_DEFAULT;
+ int context_added = 0;
- *messagep = NULL;
+ *messagep = NULL;
- if (!accountname || !protocol || !recipient || !message || !messagep)
- return gcry_error(GPG_ERR_NO_ERROR);
+ if (!accountname || !protocol || !recipient || !message || !messagep)
+ return gcry_error(GPG_ERR_NO_ERROR);
- /* See if we have a fingerprint for this user */
- context = otrl_context_find(us, recipient, accountname, protocol,
- 1, &context_added, add_appdata, data);
+ /* See if we have a fingerprint for this user */
+ context = otrl_context_find(us, recipient, accountname, protocol,
+ 1, &context_added, add_appdata, data);
- /* Update the context list if we added one */
- if (context_added && ops->update_context_list) {
+ /* Update the context list if we added one */
+ if (context_added && ops->update_context_list) {
ops->update_context_list(opdata);
- }
+ }
- /* Check the policy */
- if (ops->policy) {
+ /* Check the policy */
+ if (ops->policy) {
policy = ops->policy(opdata, context);
- }
+ }
- /* Should we go on at all? */
- if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
- return gcry_error(GPG_ERR_NO_ERROR);
- }
+ /* Should we go on at all? */
+ if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
+ return gcry_error(GPG_ERR_NO_ERROR);
+ }
- /* If this is an OTR Query message, don't encrypt it. */
- if (otrl_proto_message_type(message) == OTRL_MSGTYPE_QUERY) {
+ /* If this is an OTR Query message, don't encrypt it. */
+ if (otrl_proto_message_type(message) == OTRL_MSGTYPE_QUERY) {
/* Replace the "?OTR?" with a custom message */
char *bettermsg = otrl_proto_default_query_msg(accountname, policy);
if (bettermsg) {
- *messagep = bettermsg;
+ *messagep = bettermsg;
}
return gcry_error(GPG_ERR_NO_ERROR);
- }
+ }
- /* What is the current message disposition? */
- switch(context->msgstate) {
+ /* What is the current message disposition? */
+ switch(context->msgstate) {
case OTRL_MSGSTATE_PLAINTEXT:
- if ((policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
+ if ((policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
/* We're trying to send an unencrypted message with a policy
* that disallows that. Don't do that, but try to start
* up OTR instead. */
if ((!(ops->display_otr_message) ||
ops->display_otr_message(opdata, accountname,
- protocol, recipient, "Attempting to start a "
- "private conversation...")) && ops->notify) {
- const char *format = "You attempted to send an "
+ protocol, recipient, "Attempting to start a "
+ "private conversation...")) && ops->notify) {
+ const char *format = "You attempted to send an "
"unencrypted message to %s";
- char *primary = malloc(strlen(format) +
- strlen(recipient) - 1);
- if (primary) {
+ char *primary = malloc(strlen(format) +
+ strlen(recipient) - 1);
+ if (primary) {
sprintf(primary, format, recipient);
ops->notify(opdata, OTRL_NOTIFY_WARNING, accountname,
protocol, recipient, "OTR Policy Violation",
@@ -142,108 +142,108 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
"retransmitted when the private conversation "
"starts.");
free(primary);
- }
+ }
}
context->lastmessage = gcry_malloc_secure(strlen(message) + 1);
if (context->lastmessage) {
- char *bettermsg = otrl_proto_default_query_msg(accountname,
- policy);
- strcpy(context->lastmessage, message);
- context->lastsent = time(NULL);
- context->may_retransmit = 2;
- if (bettermsg) {
+ char *bettermsg = otrl_proto_default_query_msg(accountname,
+ policy);
+ strcpy(context->lastmessage, message);
+ context->lastsent = time(NULL);
+ context->may_retransmit = 2;
+ if (bettermsg) {
*messagep = bettermsg;
- } else {
+ } else {
return gcry_error(GPG_ERR_ENOMEM);
- }
+ }
}
- } else {
+ } else {
if ((policy & OTRL_POLICY_SEND_WHITESPACE_TAG) &&
context->otr_offer != OFFER_REJECTED) {
- /* See if this user can speak OTR. Append the
- * OTR_MESSAGE_TAG to the plaintext message, and see
- * if he responds. */
- size_t msglen = strlen(message);
- size_t basetaglen = strlen(OTRL_MESSAGE_TAG_BASE);
- size_t v1taglen = (policy & OTRL_POLICY_ALLOW_V1) ?
+ /* See if this user can speak OTR. Append the
+ * OTR_MESSAGE_TAG to the plaintext message, and see
+ * if he responds. */
+ size_t msglen = strlen(message);
+ size_t basetaglen = strlen(OTRL_MESSAGE_TAG_BASE);
+ size_t v1taglen = (policy & OTRL_POLICY_ALLOW_V1) ?
strlen(OTRL_MESSAGE_TAG_V1) : 0;
- size_t v2taglen = (policy & OTRL_POLICY_ALLOW_V2) ?
+ size_t v2taglen = (policy & OTRL_POLICY_ALLOW_V2) ?
strlen(OTRL_MESSAGE_TAG_V2) : 0;
- char *taggedmsg = malloc(msglen + basetaglen + v1taglen
- +v2taglen + 1);
- if (taggedmsg) {
+ char *taggedmsg = malloc(msglen + basetaglen + v1taglen
+ +v2taglen + 1);
+ if (taggedmsg) {
strcpy(taggedmsg, message);
strcpy(taggedmsg + msglen, OTRL_MESSAGE_TAG_BASE);
if (v1taglen) {
- strcpy(taggedmsg + msglen + basetaglen,
- OTRL_MESSAGE_TAG_V1);
+ strcpy(taggedmsg + msglen + basetaglen,
+ OTRL_MESSAGE_TAG_V1);
}
if (v2taglen) {
- strcpy(taggedmsg + msglen + basetaglen + v1taglen,
- OTRL_MESSAGE_TAG_V2);
+ strcpy(taggedmsg + msglen + basetaglen + v1taglen,
+ OTRL_MESSAGE_TAG_V2);
}
*messagep = taggedmsg;
if (context) {
- context->otr_offer = OFFER_SENT;
+ context->otr_offer = OFFER_SENT;
}
- }
+ }
+ }
}
- }
- break;
+ break;
case OTRL_MSGSTATE_ENCRYPTED:
- /* Create the new, encrypted message */
- err = otrl_proto_create_data(&msgtosend, context, message, tlvs,
- 0);
- if (!err) {
+ /* Create the new, encrypted message */
+ err = otrl_proto_create_data(&msgtosend, context, message, tlvs,
+ 0);
+ if (!err) {
context->lastsent = time(NULL);
*messagep = msgtosend;
- } else {
+ } else {
/* Uh, oh. Whatever we do, *don't* send the message in the
* clear. */
- *messagep = strdup("?OTR Error: Error occurred encrypting "
+ *messagep = _strdup("?OTR Error: Error occurred encrypting "
"message");
if ((!(ops->display_otr_message) ||
ops->display_otr_message(opdata, accountname,
- protocol, recipient, "An error occurred when "
- "encrypting your message. The message was not "
- "sent.")) && ops->notify) {
- ops->notify(opdata, OTRL_NOTIFY_ERROR,
- accountname, protocol, recipient,
- "Error encrypting message",
- "An error occurred when encrypting your message",
- "The message was not sent.");
+ protocol, recipient, "An error occurred when "
+ "encrypting your message. The message was not "
+ "sent.")) && ops->notify) {
+ ops->notify(opdata, OTRL_NOTIFY_ERROR,
+ accountname, protocol, recipient,
+ "Error encrypting message",
+ "An error occurred when encrypting your message",
+ "The message was not sent.");
}
if (!(*messagep)) {
- return gcry_error(GPG_ERR_ENOMEM);
+ return gcry_error(GPG_ERR_ENOMEM);
+ }
}
- }
- break;
+ break;
case OTRL_MSGSTATE_FINISHED:
- *messagep = strdup("");
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata, accountname,
+ *messagep = _strdup("");
+ if ((!(ops->display_otr_message) ||
+ ops->display_otr_message(opdata, accountname,
protocol, recipient, "Your message was not sent. "
"Either end your private conversation, or restart "
"it.")) && ops->notify) {
const char *fmt = "%s has already closed his/her private "
- "connection to you";
+ "connection to you";
char *primary = malloc(strlen(fmt) + strlen(recipient) - 1);
if (primary) {
- sprintf(primary, fmt, recipient);
- ops->notify(opdata, OTRL_NOTIFY_ERROR,
- accountname, protocol, recipient,
- "Private connection closed", primary,
- "Your message was not sent. Either close your "
- "private connection to him, or refresh it.");
+ sprintf(primary, fmt, recipient);
+ ops->notify(opdata, OTRL_NOTIFY_ERROR,
+ accountname, protocol, recipient,
+ "Private connection closed", primary,
+ "Your message was not sent. Either close your "
+ "private connection to him, or refresh it.");
}
- }
- if (!(*messagep)) {
+ }
+ if (!(*messagep)) {
return gcry_error(GPG_ERR_ENOMEM);
- }
- break;
- }
+ }
+ break;
+ }
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* If err == 0, send the last auth message for the given context to the
@@ -252,76 +252,76 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
static gcry_error_t send_or_error_auth(const OtrlMessageAppOps *ops,
void *opdata, gcry_error_t err, ConnContext *context)
{
- if (!err) {
+ if (!err) {
const char *msg = context->auth.lastauthmsg;
if (msg && *msg) {
- otrl_message_fragment_and_send(ops, opdata, context, msg, OTRL_FRAGMENT_SEND_ALL, NULL);
- /*if (ops->inject_message) {
+ otrl_message_fragment_and_send(ops, opdata, context, msg, OTRL_FRAGMENT_SEND_ALL, NULL);
+ /*if (ops->inject_message) {
ops->inject_message(opdata, context->accountname,
context->protocol, context->username, msg);
- }*/
+ }*/
}
- } else {
+ } else {
const char *buf_format = "Error setting up private conversation: %s";
const char *strerr;
char *buf;
switch(gcry_err_code(err)) {
- case GPG_ERR_INV_VALUE:
+ case GPG_ERR_INV_VALUE:
strerr = "Malformed message received";
break;
- default:
+ default:
strerr = gcry_strerror(err);
break;
}
buf = malloc(strlen(buf_format) + strlen(strerr) - 1);
if (buf) {
- sprintf(buf, buf_format, strerr);
+ sprintf(buf, buf_format, strerr);
}
if ((!(ops->display_otr_message) ||
ops->display_otr_message(opdata, context->accountname,
- context->protocol, context->username, buf))
+ context->protocol, context->username, buf))
&& ops->notify) {
- ops->notify(opdata, OTRL_NOTIFY_ERROR, context->accountname,
- context->protocol, context->username, "OTR error",
- buf, NULL);
+ ops->notify(opdata, OTRL_NOTIFY_ERROR, context->accountname,
+ context->protocol, context->username, "OTR error",
+ buf, NULL);
}
free(buf);
- }
- return err;
+ }
+ return err;
}
typedef struct {
- int gone_encrypted;
- OtrlUserState us;
- const OtrlMessageAppOps *ops;
- void *opdata;
- ConnContext *context;
- int ignore_message;
- char **messagep;
+ int gone_encrypted;
+ OtrlUserState us;
+ const OtrlMessageAppOps *ops;
+ void *opdata;
+ ConnContext *context;
+ int ignore_message;
+ char **messagep;
} EncrData;
static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
{
- EncrData *edata = asdata;
- gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
- Fingerprint *found_print = NULL;
- int fprint_added = 0;
- OtrlMessageState oldstate = edata->context->msgstate;
- Fingerprint *oldprint = edata->context->active_fingerprint;
-
- /* See if we're talking to ourselves */
- if (!gcry_mpi_cmp(auth->their_pub, auth->our_dh.pub)) {
+ EncrData *edata = asdata;
+ gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
+ Fingerprint *found_print = NULL;
+ int fprint_added = 0;
+ OtrlMessageState oldstate = edata->context->msgstate;
+ Fingerprint *oldprint = edata->context->active_fingerprint;
+
+ /* See if we're talking to ourselves */
+ if (!gcry_mpi_cmp(auth->their_pub, auth->our_dh.pub)) {
/* Yes, we are. */
if ((!(edata->ops->display_otr_message) ||
edata->ops->display_otr_message(edata->opdata,
- edata->context->accountname, edata->context->protocol,
- edata->context->username,
- "We are receiving our own OTR messages. "
- "You are either trying to talk to yourself, "
- "or someone is reflecting your messages back "
- "at you.")) && edata->ops->notify) {
- edata->ops->notify(edata->opdata, OTRL_NOTIFY_ERROR,
+ edata->context->accountname, edata->context->protocol,
+ edata->context->username,
+ "We are receiving our own OTR messages. "
+ "You are either trying to talk to yourself, "
+ "or someone is reflecting your messages back "
+ "at you.")) && edata->ops->notify) {
+ edata->ops->notify(edata->opdata, OTRL_NOTIFY_ERROR,
edata->context->accountname, edata->context->protocol,
edata->context->username, "OTR Error",
"We are receiving our own OTR messages.",
@@ -331,70 +331,70 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
}
edata->ignore_message = 1;
return gcry_error(GPG_ERR_NO_ERROR);
- }
+ }
- found_print = otrl_context_find_fingerprint(edata->context,
- edata->context->auth.their_fingerprint, 1, &fprint_added);
+ found_print = otrl_context_find_fingerprint(edata->context,
+ edata->context->auth.their_fingerprint, 1, &fprint_added);
- if (fprint_added) {
+ if (fprint_added) {
/* Inform the user of the new fingerprint */
if (edata->ops->new_fingerprint) {
- edata->ops->new_fingerprint(edata->opdata, edata->us,
- edata->context->accountname, edata->context->protocol,
- edata->context->username,
- edata->context->auth.their_fingerprint);
+ edata->ops->new_fingerprint(edata->opdata, edata->us,
+ edata->context->accountname, edata->context->protocol,
+ edata->context->username,
+ edata->context->auth.their_fingerprint);
}
/* Arrange that the new fingerprint be written to disk */
if (edata->ops->write_fingerprints) {
- edata->ops->write_fingerprints(edata->opdata);
+ edata->ops->write_fingerprints(edata->opdata);
+ }
}
- }
- /* Is this a new session or just a refresh of an existing one? */
- if (edata->context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
- oldprint == found_print &&
- edata->context->our_keyid - 1 == edata->context->auth.our_keyid &&
- !gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
+ /* Is this a new session or just a refresh of an existing one? */
+ if (edata->context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
+ oldprint == found_print &&
+ edata->context->our_keyid - 1 == edata->context->auth.our_keyid &&
+ !gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
edata->context->auth.our_dh.pub) &&
- ((edata->context->their_keyid > 0 &&
- edata->context->their_keyid ==
- edata->context->auth.their_keyid &&
- !gcry_mpi_cmp(edata->context->their_y,
+ ((edata->context->their_keyid > 0 &&
+ edata->context->their_keyid ==
+ edata->context->auth.their_keyid &&
+ !gcry_mpi_cmp(edata->context->their_y,
edata->context->auth.their_pub)) ||
- (edata->context->their_keyid > 1 &&
- edata->context->their_keyid - 1 ==
- edata->context->auth.their_keyid &&
- edata->context->their_old_y != NULL &&
- !gcry_mpi_cmp(edata->context->their_old_y,
+ (edata->context->their_keyid > 1 &&
+ edata->context->their_keyid - 1 ==
+ edata->context->auth.their_keyid &&
+ edata->context->their_old_y != NULL &&
+ !gcry_mpi_cmp(edata->context->their_old_y,
edata->context->auth.their_pub)))) {
/* This is just a refresh of the existing session. */
if (edata->ops->still_secure) {
- edata->ops->still_secure(edata->opdata, edata->context,
- edata->context->auth.initiated);
+ edata->ops->still_secure(edata->opdata, edata->context,
+ edata->context->auth.initiated);
}
edata->ignore_message = 1;
return gcry_error(GPG_ERR_NO_ERROR);
- }
+ }
- /* Copy the information from the auth into the context */
- memmove(edata->context->sessionid,
- edata->context->auth.secure_session_id, 20);
- edata->context->sessionid_len =
+ /* Copy the information from the auth into the context */
+ memmove(edata->context->sessionid,
+ edata->context->auth.secure_session_id, 20);
+ edata->context->sessionid_len =
edata->context->auth.secure_session_id_len;
- edata->context->sessionid_half =
+ edata->context->sessionid_half =
edata->context->auth.session_id_half;
- edata->context->protocol_version =
+ edata->context->protocol_version =
edata->context->auth.protocol_version;
- edata->context->their_keyid = edata->context->auth.their_keyid;
- gcry_mpi_release(edata->context->their_y);
- gcry_mpi_release(edata->context->their_old_y);
- edata->context->their_y = gcry_mpi_copy(edata->context->auth.their_pub);
- edata->context->their_old_y = NULL;
+ edata->context->their_keyid = edata->context->auth.their_keyid;
+ gcry_mpi_release(edata->context->their_y);
+ gcry_mpi_release(edata->context->their_old_y);
+ edata->context->their_y = gcry_mpi_copy(edata->context->auth.their_pub);
+ edata->context->their_old_y = NULL;
- if (edata->context->our_keyid - 1 != edata->context->auth.our_keyid ||
+ if (edata->context->our_keyid - 1 != edata->context->auth.our_keyid ||
gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
- edata->context->auth.our_dh.pub)) {
+ edata->context->auth.our_dh.pub)) {
otrl_dh_keypair_free(&(edata->context->our_dh_key));
otrl_dh_keypair_free(&(edata->context->our_old_dh_key));
otrl_dh_keypair_copy(&(edata->context->our_old_dh_key),
@@ -402,53 +402,53 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
otrl_dh_gen_keypair(edata->context->our_old_dh_key.groupid,
&(edata->context->our_dh_key));
edata->context->our_keyid = edata->context->auth.our_keyid + 1;
- }
+ }
- /* Create the session keys from the DH keys */
- otrl_dh_session_free(&(edata->context->sesskeys[0][0]));
- err = otrl_dh_session(&(edata->context->sesskeys[0][0]),
+ /* Create the session keys from the DH keys */
+ otrl_dh_session_free(&(edata->context->sesskeys[0][0]));
+ err = otrl_dh_session(&(edata->context->sesskeys[0][0]),
&(edata->context->our_dh_key), edata->context->their_y);
- if (err) return err;
- otrl_dh_session_free(&(edata->context->sesskeys[1][0]));
- err = otrl_dh_session(&(edata->context->sesskeys[1][0]),
+ if (err) return err;
+ otrl_dh_session_free(&(edata->context->sesskeys[1][0]));
+ err = otrl_dh_session(&(edata->context->sesskeys[1][0]),
&(edata->context->our_old_dh_key), edata->context->their_y);
- if (err) return err;
+ if (err) return err;
- edata->context->generation++;
- edata->context->active_fingerprint = found_print;
- edata->context->msgstate = OTRL_MSGSTATE_ENCRYPTED;
+ edata->context->generation++;
+ edata->context->active_fingerprint = found_print;
+ edata->context->msgstate = OTRL_MSGSTATE_ENCRYPTED;
- if (edata->ops->update_context_list) {
+ if (edata->ops->update_context_list) {
edata->ops->update_context_list(edata->opdata);
- }
- if (oldstate == OTRL_MSGSTATE_ENCRYPTED && oldprint == found_print) {
+ }
+ if (oldstate == OTRL_MSGSTATE_ENCRYPTED && oldprint == found_print) {
if (edata->ops->still_secure) {
- edata->ops->still_secure(edata->opdata, edata->context,
- edata->context->auth.initiated);
+ edata->ops->still_secure(edata->opdata, edata->context,
+ edata->context->auth.initiated);
}
- } else {
+ } else {
if (edata->ops->gone_secure) {
- edata->ops->gone_secure(edata->opdata, edata->context);
+ edata->ops->gone_secure(edata->opdata, edata->context);
+ }
}
- }
- edata->gone_encrypted = 1;
+ edata->gone_encrypted = 1;
- return gpg_error(GPG_ERR_NO_ERROR);
+ return gpg_error(GPG_ERR_NO_ERROR);
}
static void maybe_resend(EncrData *edata)
{
- gcry_error_t err;
- time_t now;
+ gcry_error_t err;
+ time_t now;
- if (!edata->gone_encrypted) return;
+ if (!edata->gone_encrypted) return;
- /* See if there's a message we sent recently that should be resent. */
- now = time(NULL);
- if (edata->context->lastmessage != NULL &&
- edata->context->may_retransmit &&
- edata->context->lastsent >= (now - RESEND_INTERVAL)) {
+ /* See if there's a message we sent recently that should be resent. */
+ now = time(NULL);
+ if (edata->context->lastmessage != NULL &&
+ edata->context->may_retransmit &&
+ edata->context->lastsent >= (now - RESEND_INTERVAL)) {
char *resendmsg;
int resending = (edata->context->may_retransmit == 1);
@@ -456,143 +456,143 @@ static void maybe_resend(EncrData *edata)
err = otrl_proto_create_data(&resendmsg,
edata->context, edata->context->lastmessage, NULL, 0);
if (!err) {
- const char *format = "<b>The last message "
+ const char *format = "<b>The last message "
"to %s was resent.</b>";
- char *buf;
+ char *buf;
- /* Resend the message */
- otrl_message_fragment_and_send(edata->ops, edata->opdata, edata->context, resendmsg, OTRL_FRAGMENT_SEND_ALL, NULL);
- free(resendmsg);
- edata->context->lastsent = now;
+ /* Resend the message */
+ otrl_message_fragment_and_send(edata->ops, edata->opdata, edata->context, resendmsg, OTRL_FRAGMENT_SEND_ALL, NULL);
+ free(resendmsg);
+ edata->context->lastsent = now;
- if (!resending) {
+ if (!resending) {
/* We're actually just sending it
* for the first time. */
edata->ignore_message = 1;
- } else {
+ } else {
/* Let the user know we resent it */
buf = malloc(strlen(format) +
strlen(edata->context->username) - 1);
if (buf) {
- sprintf(buf, format, edata->context->username);
- if (edata->ops->display_otr_message) {
+ sprintf(buf, format, edata->context->username);
+ if (edata->ops->display_otr_message) {
if (!edata->ops->display_otr_message(
- edata->opdata, edata->context->accountname,
- edata->context->protocol,
- edata->context->username, buf)) {
- edata->ignore_message = 1;
+ edata->opdata, edata->context->accountname,
+ edata->context->protocol,
+ edata->context->username, buf)) {
+ edata->ignore_message = 1;
}
- }
- if (edata->ignore_message != 1) {
+ }
+ if (edata->ignore_message != 1) {
*(edata->messagep) = buf;
edata->ignore_message = 0;
- } else {
+ } else {
free(buf);
- }
+ }
}
- }
+ }
+ }
}
- }
}
/* Set the trust level based on the result of the SMP */
static void set_smp_trust(const OtrlMessageAppOps *ops, void *opdata,
ConnContext *context, int trusted)
{
- otrl_context_set_trust(context->active_fingerprint, trusted ? "smp" : "");
+ otrl_context_set_trust(context->active_fingerprint, trusted ? "smp" : "");
- /* Write the new info to disk, redraw the ui, and redraw the
- * OTR buttons. */
- if (ops->write_fingerprints) {
+ /* Write the new info to disk, redraw the ui, and redraw the
+ * OTR buttons. */
+ if (ops->write_fingerprints) {
ops->write_fingerprints(opdata);
- }
+ }
}
static void init_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, ConnContext *context, const char *question,
const unsigned char *secret, size_t secretlen, int initiating)
{
- unsigned char *smpmsg = NULL;
- int smpmsglen;
- unsigned char combined_secret[SM_DIGEST_SIZE];
- gcry_error_t err;
- unsigned char our_fp[20];
- unsigned char *combined_buf;
- size_t combined_buf_len;
- OtrlTLV *sendtlv;
- char *sendsmp = NULL;
-
- if (!context || context->msgstate != OTRL_MSGSTATE_ENCRYPTED) return;
-
- /*
- * Construct the combined secret as a SHA256 hash of:
- * Version byte (0x01), Initiator fingerprint (20 bytes),
- * responder fingerprint (20 bytes), secure session id, input secret
- */
- otrl_privkey_fingerprint_raw(us, our_fp, context->accountname,
- context->protocol);
-
- combined_buf_len = 41 + context->sessionid_len + secretlen;
- combined_buf = malloc(combined_buf_len);
- combined_buf[0] = 0x01;
- if (initiating) {
+ unsigned char *smpmsg = NULL;
+ int smpmsglen;
+ unsigned char combined_secret[SM_DIGEST_SIZE];
+ gcry_error_t err;
+ unsigned char our_fp[20];
+ unsigned char *combined_buf;
+ size_t combined_buf_len;
+ OtrlTLV *sendtlv;
+ char *sendsmp = NULL;
+
+ if (!context || context->msgstate != OTRL_MSGSTATE_ENCRYPTED) return;
+
+ /*
+ * Construct the combined secret as a SHA256 hash of:
+ * Version byte (0x01), Initiator fingerprint (20 bytes),
+ * responder fingerprint (20 bytes), secure session id, input secret
+ */
+ otrl_privkey_fingerprint_raw(us, our_fp, context->accountname,
+ context->protocol);
+
+ combined_buf_len = 41 + context->sessionid_len + secretlen;
+ combined_buf = malloc(combined_buf_len);
+ combined_buf[0] = 0x01;
+ if (initiating) {
memmove(combined_buf + 1, our_fp, 20);
memmove(combined_buf + 21,
context->active_fingerprint->fingerprint, 20);
- } else {
+ } else {
memmove(combined_buf + 1,
context->active_fingerprint->fingerprint, 20);
memmove(combined_buf + 21, our_fp, 20);
- }
- memmove(combined_buf + 41, context->sessionid,
- context->sessionid_len);
- memmove(combined_buf + 41 + context->sessionid_len,
- secret, secretlen);
- gcry_md_hash_buffer(SM_HASH_ALGORITHM, combined_secret, combined_buf,
- combined_buf_len);
- free(combined_buf);
-
- if (initiating) {
+ }
+ memmove(combined_buf + 41, context->sessionid,
+ context->sessionid_len);
+ memmove(combined_buf + 41 + context->sessionid_len,
+ secret, secretlen);
+ gcry_md_hash_buffer(SM_HASH_ALGORITHM, combined_secret, combined_buf,
+ combined_buf_len);
+ free(combined_buf);
+
+ if (initiating) {
otrl_sm_step1(context->smstate, combined_secret, SM_DIGEST_SIZE,
&smpmsg, &smpmsglen);
- } else {
+ } else {
otrl_sm_step2b(context->smstate, combined_secret, SM_DIGEST_SIZE,
&smpmsg, &smpmsglen);
- }
+ }
- /* If we've got a question, attach it to the smpmsg */
- if (question != NULL) {
+ /* If we've got a question, attach it to the smpmsg */
+ if (question != NULL) {
size_t qlen = strlen(question);
unsigned char *qsmpmsg = malloc(qlen + 1 + smpmsglen);
if (!qsmpmsg) {
- free(smpmsg);
- return;
+ free(smpmsg);
+ return;
}
strcpy((char *)qsmpmsg, question);
memmove(qsmpmsg + qlen + 1, smpmsg, smpmsglen);
free(smpmsg);
smpmsg = qsmpmsg;
smpmsglen += qlen + 1;
- }
-
- /* Send msg with next smp msg content */
- sendtlv = otrl_tlv_new(initiating ?
- (question != NULL ? OTRL_TLV_SMP1Q : OTRL_TLV_SMP1)
- : OTRL_TLV_SMP2,
- smpmsglen, smpmsg);
- err = otrl_proto_create_data(&sendsmp, context, "", sendtlv,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
- /* Send it, and set the next expected message to the
+ }
+
+ /* Send msg with next smp msg content */
+ sendtlv = otrl_tlv_new(initiating ?
+ (question != NULL ? OTRL_TLV_SMP1Q : OTRL_TLV_SMP1)
+ : OTRL_TLV_SMP2,
+ smpmsglen, smpmsg);
+ err = otrl_proto_create_data(&sendsmp, context, "", sendtlv,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
+ /* Send it, and set the next expected message to the
* logical response */
- err = otrl_message_fragment_and_send(ops, opdata, context,
+ err = otrl_message_fragment_and_send(ops, opdata, context,
sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
- context->smstate->nextExpected =
- initiating ? OTRL_SMP_EXPECT2 : OTRL_SMP_EXPECT3;
- }
- free(sendsmp);
- otrl_tlv_free(sendtlv);
- free(smpmsg);
+ context->smstate->nextExpected =
+ initiating ? OTRL_SMP_EXPECT2 : OTRL_SMP_EXPECT3;
+ }
+ free(sendsmp);
+ otrl_tlv_free(sendtlv);
+ free(smpmsg);
}
/* Initiate the Socialist Millionaires' Protocol */
@@ -600,7 +600,7 @@ void otrl_message_initiate_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, ConnContext *context, const unsigned char *secret,
size_t secretlen)
{
- init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 1);
+ init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 1);
}
/* Initiate the Socialist Millionaires' Protocol and send a prompt
@@ -609,7 +609,7 @@ void otrl_message_initiate_smp_q(OtrlUserState us,
const OtrlMessageAppOps *ops, void *opdata, ConnContext *context,
const char *question, const unsigned char *secret, size_t secretlen)
{
- init_respond_smp(us, ops, opdata, context, question, secret, secretlen, 1);
+ init_respond_smp(us, ops, opdata, context, question, secret, secretlen, 1);
}
/* Respond to a buddy initiating the Socialist Millionaires' Protocol */
@@ -617,7 +617,7 @@ void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, ConnContext *context, const unsigned char *secret,
size_t secretlen)
{
- init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 0);
+ init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 0);
}
/* Abort the SMP. Called when an unexpected SMP message breaks the
@@ -625,23 +625,23 @@ void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, ConnContext *context)
{
- OtrlTLV *sendtlv = otrl_tlv_new(OTRL_TLV_SMP_ABORT, 0,
- (const unsigned char *)"");
- char *sendsmp = NULL;
- gcry_error_t err;
-
- context->smstate->nextExpected = OTRL_SMP_EXPECT1;
-
- err = otrl_proto_create_data(&sendsmp,
- context, "", sendtlv,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
+ OtrlTLV *sendtlv = otrl_tlv_new(OTRL_TLV_SMP_ABORT, 0,
+ (const unsigned char *)"");
+ char *sendsmp = NULL;
+ gcry_error_t err;
+
+ context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+
+ err = otrl_proto_create_data(&sendsmp,
+ context, "", sendtlv,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
/* Send the abort signal so our buddy knows we've stopped */
err = otrl_message_fragment_and_send(ops, opdata, context,
sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
- }
- free(sendsmp);
- otrl_tlv_free(sendtlv);
+ }
+ free(sendsmp);
+ otrl_tlv_free(sendtlv);
}
/* Handle a message just received from the network. It is safe to pass
@@ -675,79 +675,79 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
void (*add_appdata)(void *data, ConnContext *context),
void *data)
{
- ConnContext *context;
- OtrlMessageType msgtype;
- int context_added = 0;
- OtrlMessageState msgstate;
- OtrlPolicy policy = OTRL_POLICY_DEFAULT;
- int fragment_assembled = 0;
- char *unfragmessage = NULL;
- EncrData edata;
-
- if (!accountname || !protocol || !sender || !message || !newmessagep)
- return 0;
-
- *newmessagep = NULL;
- if (tlvsp) *tlvsp = NULL;
-
- /* Find our context and state with this correspondent */
- context = otrl_context_find(us, sender, accountname,
- protocol, 1, &context_added, add_appdata, data);
-
- /* Update the context list if we added one */
- if (context_added && ops->update_context_list) {
+ ConnContext *context;
+ OtrlMessageType msgtype;
+ int context_added = 0;
+ OtrlMessageState msgstate;
+ OtrlPolicy policy = OTRL_POLICY_DEFAULT;
+ int fragment_assembled = 0;
+ char *unfragmessage = NULL;
+ EncrData edata;
+
+ if (!accountname || !protocol || !sender || !message || !newmessagep)
+ return 0;
+
+ *newmessagep = NULL;
+ if (tlvsp) *tlvsp = NULL;
+
+ /* Find our context and state with this correspondent */
+ context = otrl_context_find(us, sender, accountname,
+ protocol, 1, &context_added, add_appdata, data);
+
+ /* Update the context list if we added one */
+ if (context_added && ops->update_context_list) {
ops->update_context_list(opdata);
- }
+ }
- /* Check the policy */
- if (ops->policy) {
+ /* Check the policy */
+ if (ops->policy) {
policy = ops->policy(opdata, context);
- }
+ }
- /* Should we go on at all? */
- if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
- return 0;
- }
+ /* Should we go on at all? */
+ if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
+ return 0;
+ }
- /* See if we have a fragment */
- switch(otrl_proto_fragment_accumulate(&unfragmessage, context, message)) {
+ /* See if we have a fragment */
+ switch(otrl_proto_fragment_accumulate(&unfragmessage, context, message)) {
case OTRL_FRAGMENT_UNFRAGMENTED:
- /* Do nothing */
- break;
+ /* Do nothing */
+ break;
case OTRL_FRAGMENT_INCOMPLETE:
- /* We've accumulated this fragment, but we don't have a
- * complete message yet */
- return 1;
+ /* We've accumulated this fragment, but we don't have a
+ * complete message yet */
+ return 1;
case OTRL_FRAGMENT_COMPLETE:
- /* We've got a new complete message, in unfragmessage. */
- fragment_assembled = 1;
- message = unfragmessage;
- break;
- }
-
- /* What type of message is it? Note that this just checks the
- * header; it's not necessarily a _valid_ message of this type. */
- msgtype = otrl_proto_message_type(message);
- msgstate = context->msgstate;
-
- /* See if they responded to our OTR offer */
- if ((policy & OTRL_POLICY_SEND_WHITESPACE_TAG)) {
+ /* We've got a new complete message, in unfragmessage. */
+ fragment_assembled = 1;
+ message = unfragmessage;
+ break;
+ }
+
+ /* What type of message is it? Note that this just checks the
+ * header; it's not necessarily a _valid_ message of this type. */
+ msgtype = otrl_proto_message_type(message);
+ msgstate = context->msgstate;
+
+ /* See if they responded to our OTR offer */
+ if ((policy & OTRL_POLICY_SEND_WHITESPACE_TAG)) {
if (msgtype != OTRL_MSGTYPE_NOTOTR) {
- context->otr_offer = OFFER_ACCEPTED;
+ context->otr_offer = OFFER_ACCEPTED;
} else if (context->otr_offer == OFFER_SENT) {
- context->otr_offer = OFFER_REJECTED;
+ context->otr_offer = OFFER_REJECTED;
+ }
}
- }
- edata.gone_encrypted = 0;
- edata.us = us;
- edata.context = context;
- edata.ops = ops;
- edata.opdata = opdata;
- edata.ignore_message = -1;
- edata.messagep = newmessagep;
+ edata.gone_encrypted = 0;
+ edata.us = us;
+ edata.context = context;
+ edata.ops = ops;
+ edata.opdata = opdata;
+ edata.ignore_message = -1;
+ edata.messagep = newmessagep;
- switch(msgtype) {
+ switch(msgtype) {
unsigned int bestversion;
const char *startwhite, *endwhite;
DH_keypair *our_dh;
@@ -756,165 +756,165 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
gcry_error_t err;
int haveauthmsg;
case OTRL_MSGTYPE_QUERY:
- /* See if we should use an existing DH keypair, or generate
- * a fresh one. */
- if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
+ /* See if we should use an existing DH keypair, or generate
+ * a fresh one. */
+ if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
our_dh = &(context->our_old_dh_key);
our_keyid = context->our_keyid - 1;
- } else {
+ } else {
our_dh = NULL;
our_keyid = 0;
- }
+ }
- /* Find the best version of OTR that we both speak */
- switch(otrl_proto_query_bestversion(message, policy)) {
+ /* Find the best version of OTR that we both speak */
+ switch(otrl_proto_query_bestversion(message, policy)) {
case 2:
- err = otrl_auth_start_v2(&(context->auth));
- send_or_error_auth(ops, opdata, err, context);
- break;
+ err = otrl_auth_start_v2(&(context->auth));
+ send_or_error_auth(ops, opdata, err, context);
+ break;
case 1:
- /* Get our private key */
- privkey = otrl_privkey_find(us, context->accountname,
- context->protocol);
- if (privkey == NULL) {
+ /* Get our private key */
+ privkey = otrl_privkey_find(us, context->accountname,
+ context->protocol);
+ if (privkey == NULL) {
/* We've got no private key! */
if (ops->create_privkey) {
- ops->create_privkey(opdata, context->accountname,
- context->protocol);
- privkey = otrl_privkey_find(us,
- context->accountname, context->protocol);
+ ops->create_privkey(opdata, context->accountname,
+ context->protocol);
+ privkey = otrl_privkey_find(us,
+ context->accountname, context->protocol);
+ }
}
- }
- if (privkey) {
+ if (privkey) {
err = otrl_auth_start_v1(&(context->auth), our_dh,
our_keyid, privkey);
send_or_error_auth(ops, opdata, err, context);
- }
- break;
+ }
+ break;
default:
- /* Just ignore this message */
- break;
- }
- /* Don't display the Query message to the user. */
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+ /* Just ignore this message */
+ break;
+ }
+ /* Don't display the Query message to the user. */
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_DH_COMMIT:
- if ((policy & OTRL_POLICY_ALLOW_V2)) {
+ if ((policy & OTRL_POLICY_ALLOW_V2)) {
err = otrl_auth_handle_commit(&(context->auth), message);
send_or_error_auth(ops, opdata, err, context);
- }
+ }
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_DH_KEY:
- if ((policy & OTRL_POLICY_ALLOW_V2)) {
+ if ((policy & OTRL_POLICY_ALLOW_V2)) {
/* Get our private key */
privkey = otrl_privkey_find(us, context->accountname,
context->protocol);
if (privkey == NULL) {
- /* We've got no private key! */
- if (ops->create_privkey) {
+ /* We've got no private key! */
+ if (ops->create_privkey) {
ops->create_privkey(opdata, context->accountname,
context->protocol);
privkey = otrl_privkey_find(us,
context->accountname, context->protocol);
- }
+ }
}
if (privkey) {
- err = otrl_auth_handle_key(&(context->auth), message,
- &haveauthmsg, privkey);
- if (err || haveauthmsg) {
+ err = otrl_auth_handle_key(&(context->auth), message,
+ &haveauthmsg, privkey);
+ if (err || haveauthmsg) {
send_or_error_auth(ops, opdata, err, context);
- }
+ }
+ }
}
- }
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_REVEALSIG:
- if ((policy & OTRL_POLICY_ALLOW_V2)) {
+ if ((policy & OTRL_POLICY_ALLOW_V2)) {
/* Get our private key */
privkey = otrl_privkey_find(us, context->accountname,
context->protocol);
if (privkey == NULL) {
- /* We've got no private key! */
- if (ops->create_privkey) {
+ /* We've got no private key! */
+ if (ops->create_privkey) {
ops->create_privkey(opdata, context->accountname,
context->protocol);
privkey = otrl_privkey_find(us,
context->accountname, context->protocol);
- }
+ }
}
if (privkey) {
- err = otrl_auth_handle_revealsig(&(context->auth),
- message, &haveauthmsg, privkey, go_encrypted,
- &edata);
- if (err || haveauthmsg) {
+ err = otrl_auth_handle_revealsig(&(context->auth),
+ message, &haveauthmsg, privkey, go_encrypted,
+ &edata);
+ if (err || haveauthmsg) {
send_or_error_auth(ops, opdata, err, context);
maybe_resend(&edata);
- }
+ }
+ }
}
- }
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_SIGNATURE:
- if ((policy & OTRL_POLICY_ALLOW_V2)) {
+ if ((policy & OTRL_POLICY_ALLOW_V2)) {
err = otrl_auth_handle_signature(&(context->auth),
message, &haveauthmsg, go_encrypted, &edata);
if (err || haveauthmsg) {
- send_or_error_auth(ops, opdata, err, context);
- maybe_resend(&edata);
+ send_or_error_auth(ops, opdata, err, context);
+ maybe_resend(&edata);
+ }
}
- }
-
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_V1_KEYEXCH:
- if ((policy & OTRL_POLICY_ALLOW_V1)) {
+ if ((policy & OTRL_POLICY_ALLOW_V1)) {
/* See if we should use an existing DH keypair, or generate
* a fresh one. */
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
- our_dh = &(context->our_old_dh_key);
- our_keyid = context->our_keyid - 1;
+ our_dh = &(context->our_old_dh_key);
+ our_keyid = context->our_keyid - 1;
} else {
- our_dh = NULL;
- our_keyid = 0;
+ our_dh = NULL;
+ our_keyid = 0;
}
/* Get our private key */
privkey = otrl_privkey_find(us, context->accountname,
context->protocol);
if (privkey == NULL) {
- /* We've got no private key! */
- if (ops->create_privkey) {
+ /* We've got no private key! */
+ if (ops->create_privkey) {
ops->create_privkey(opdata, context->accountname,
context->protocol);
privkey = otrl_privkey_find(us,
context->accountname, context->protocol);
- }
+ }
}
if (privkey) {
- err = otrl_auth_handle_v1_key_exchange(&(context->auth),
- message, &haveauthmsg, privkey, our_dh, our_keyid,
- go_encrypted, &edata);
- if (err || haveauthmsg) {
+ err = otrl_auth_handle_v1_key_exchange(&(context->auth),
+ message, &haveauthmsg, privkey, our_dh, our_keyid,
+ go_encrypted, &edata);
+ if (err || haveauthmsg) {
send_or_error_auth(ops, opdata, err, context);
maybe_resend(&edata);
- }
+ }
+ }
}
- }
-
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
+
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
case OTRL_MSGTYPE_DATA:
- switch(context->msgstate) {
+ switch(context->msgstate) {
gcry_error_t err;
OtrlTLV *tlvs, *tlv;
char *plaintext;
@@ -926,114 +926,114 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
case OTRL_MSGSTATE_PLAINTEXT:
case OTRL_MSGSTATE_FINISHED:
- /* See if we're supposed to ignore this message in
- * the event it's unreadable. */
- err = otrl_proto_data_read_flags(message, &flags);
- if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
+ /* See if we're supposed to ignore this message in
+ * the event it's unreadable. */
+ err = otrl_proto_data_read_flags(message, &flags);
+ if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
edata.ignore_message = 1;
break;
- }
+ }
- /* Don't use g_strdup_printf here, because someone
- * (not us) is going to free() the *newmessagep pointer,
- * not g_free() it. */
- format = "<b>The encrypted message received from %s is "
+ /* Don't use g_strdup_printf here, because someone
+ * (not us) is going to free() the *newmessagep pointer,
+ * not g_free() it. */
+ format = "<b>The encrypted message received from %s is "
"unreadable, as you are not currently communicating "
"privately.</b>";
- buf = malloc(strlen(format) + strlen(context->username)
- - 1); /* Remove "%s", add username + '\0' */
- if (buf) {
+ buf = malloc(strlen(format) + strlen(context->username)
+ - 1); /* Remove "%s", add username + '\0' */
+ if (buf) {
sprintf(buf, format, context->username);
if (ops->display_otr_message) {
- if (!ops->display_otr_message(opdata, accountname,
+ if (!ops->display_otr_message(opdata, accountname,
protocol, sender, buf)) {
edata.ignore_message = 1;
- }
+ }
}
if (edata.ignore_message != 1) {
- *newmessagep = buf;
- edata.ignore_message = 0;
+ *newmessagep = buf;
+ edata.ignore_message = 0;
} else {
- free(buf);
+ free(buf);
+ }
}
- }
- format = "?OTR Error: You sent encrypted "
- "data to %s, who wasn't expecting it.";
- if (otrl_api_version >= 0x00030100 &&
- ops->account_name) {
+ format = "?OTR Error: You sent encrypted "
+ "data to %s, who wasn't expecting it.";
+ if (otrl_api_version >= 0x00030100 &&
+ ops->account_name) {
displayaccountname = ops->account_name(opdata,
context->accountname, protocol);
- } else {
+ } else {
displayaccountname = NULL;
- }
- buf = malloc(strlen(format) + strlen(displayaccountname ?
+ }
+ buf = malloc(strlen(format) + strlen(displayaccountname ?
displayaccountname : context->accountname)
- - 1);
- if (buf) {
+ - 1);
+ if (buf) {
sprintf(buf, format, displayaccountname ?
displayaccountname : context->accountname);
if (ops->inject_message) {
- ops->inject_message(opdata, accountname, protocol,
- sender, buf);
+ ops->inject_message(opdata, accountname, protocol,
+ sender, buf);
}
free(buf);
- }
- if (displayaccountname && otrl_api_version >= 0x00030100 &&
- ops->account_name_free) {
+ }
+ if (displayaccountname && otrl_api_version >= 0x00030100 &&
+ ops->account_name_free) {
ops->account_name_free(opdata, displayaccountname);
- }
+ }
- break;
+ break;
case OTRL_MSGSTATE_ENCRYPTED:
- err = otrl_proto_accept_data(&plaintext, &tlvs, context,
- message, &flags);
- if (err) {
+ err = otrl_proto_accept_data(&plaintext, &tlvs, context,
+ message, &flags);
+ if (err) {
int is_conflict =
- (gpg_err_code(err) == GPG_ERR_CONFLICT);
+ (gpg_err_code(err) == GPG_ERR_CONFLICT);
if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
- edata.ignore_message = 1;
- break;
+ edata.ignore_message = 1;
+ break;
}
format = is_conflict ? "We received an unreadable "
- "encrypted message from %s." :
- "We received a malformed data message from %s.";
+ "encrypted message from %s." :
+ "We received a malformed data message from %s.";
buf = malloc(strlen(format) + strlen(sender) - 1);
if (buf) {
- sprintf(buf, format, sender);
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata,
+ sprintf(buf, format, sender);
+ if ((!(ops->display_otr_message) ||
+ ops->display_otr_message(opdata,
accountname, protocol, sender,
buf)) && ops->notify) {
ops->notify(opdata, OTRL_NOTIFY_ERROR,
accountname, protocol, sender,
"OTR Error", buf, NULL);
- }
- free(buf);
+ }
+ free(buf);
}
if (ops->inject_message) {
- ops->inject_message(opdata, accountname, protocol,
- sender, is_conflict ? "?OTR Error: "
- "You transmitted an unreadable "
- "encrypted message." :
- "?OTR Error: You transmitted "
- "a malformed data message");
+ ops->inject_message(opdata, accountname, protocol,
+ sender, is_conflict ? "?OTR Error: "
+ "You transmitted an unreadable "
+ "encrypted message." :
+ "?OTR Error: You transmitted "
+ "a malformed data message");
}
edata.ignore_message = 1;
break;
- }
+ }
- /* If the other side told us he's disconnected his
- * private connection, make a note of that so we
- * don't try sending anything else to him. */
- if (otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED)) {
+ /* If the other side told us he's disconnected his
+ * private connection, make a note of that so we
+ * don't try sending anything else to him. */
+ if (otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED)) {
otrl_context_force_finished(context);
- }
+ }
- /* If TLVs contain SMP data, process it */
- nextMsg = context->smstate->nextExpected;
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
- if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
+ /* If TLVs contain SMP data, process it */
+ nextMsg = context->smstate->nextExpected;
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
+ if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
/* We can only do the verification half now.
* We must wait for the secret to be entered
* to continue. */
@@ -1042,17 +1042,17 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
size_t qlen = qend ? (qend - question + 1) : tlv->len;
otrl_sm_step2a(context->smstate, tlv->data + qlen,
tlv->len - qlen, 1);
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
- if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+ if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
/* We can only do the verification half now.
* We must wait for the secret to be entered
* to continue. */
otrl_sm_step2a(context->smstate, tlv->data, tlv->len,
0);
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
- if (tlv && nextMsg == OTRL_SMP_EXPECT2) {
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+ if (tlv && nextMsg == OTRL_SMP_EXPECT2) {
unsigned char* nextmsg;
int nextmsglen;
OtrlTLV *sendtlv;
@@ -1062,24 +1062,24 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
if (context->smstate->sm_prog_state !=
OTRL_SMP_PROG_CHEATED) {
- /* Send msg with next smp msg content */
- sendtlv = otrl_tlv_new(OTRL_TLV_SMP3, nextmsglen,
- nextmsg);
- err = otrl_proto_create_data(&sendsmp,
- context, "", sendtlv,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
+ /* Send msg with next smp msg content */
+ sendtlv = otrl_tlv_new(OTRL_TLV_SMP3, nextmsglen,
+ nextmsg);
+ err = otrl_proto_create_data(&sendsmp,
+ context, "", sendtlv,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
err = otrl_message_fragment_and_send(ops,
opdata, context, sendsmp,
OTRL_FRAGMENT_SEND_ALL, NULL);
- }
- free(sendsmp);
- otrl_tlv_free(sendtlv);
+ }
+ free(sendsmp);
+ otrl_tlv_free(sendtlv);
}
free(nextmsg);
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
- if (tlv && nextMsg == OTRL_SMP_EXPECT3) {
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+ if (tlv && nextMsg == OTRL_SMP_EXPECT3) {
unsigned char* nextmsg;
int nextmsglen;
OtrlTLV *sendtlv;
@@ -1088,71 +1088,71 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
tlv->len, &nextmsg, &nextmsglen);
/* Set trust level based on result */
if (context->smstate->received_question == 0) {
- set_smp_trust(ops, opdata, context,
- (err == gcry_error(GPG_ERR_NO_ERROR)));
+ set_smp_trust(ops, opdata, context,
+ (err == gcry_error(GPG_ERR_NO_ERROR)));
}
if (context->smstate->sm_prog_state !=
OTRL_SMP_PROG_CHEATED) {
- /* Send msg with next smp msg content */
- sendtlv = otrl_tlv_new(OTRL_TLV_SMP4, nextmsglen,
- nextmsg);
- err = otrl_proto_create_data(&sendsmp,
- context, "", sendtlv,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
+ /* Send msg with next smp msg content */
+ sendtlv = otrl_tlv_new(OTRL_TLV_SMP4, nextmsglen,
+ nextmsg);
+ err = otrl_proto_create_data(&sendsmp,
+ context, "", sendtlv,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
err = otrl_message_fragment_and_send(ops,
opdata, context, sendsmp,
OTRL_FRAGMENT_SEND_ALL, NULL);
- }
- free(sendsmp);
- otrl_tlv_free(sendtlv);
+ }
+ free(sendsmp);
+ otrl_tlv_free(sendtlv);
}
free(nextmsg);
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
- if (tlv && nextMsg == OTRL_SMP_EXPECT4) {
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+ if (tlv && nextMsg == OTRL_SMP_EXPECT4) {
err = otrl_sm_step5(context->smstate, tlv->data,
tlv->len);
/* Set trust level based on result */
set_smp_trust(ops, opdata, context,
(err == gcry_error(GPG_ERR_NO_ERROR)));
- }
- tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
- if (tlv) {
+ }
+ tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+ if (tlv) {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
- }
- if (plaintext[0] == '\0') {
+ }
+ if (plaintext[0] == '\0') {
/* If it's a heartbeat (an empty message), don't
* display it to the user, but log a debug message. */
format = "Heartbeat received from %s.\n";
buf = malloc(strlen(format) + strlen(sender) - 1);
if (buf) {
- sprintf(buf, format, sender);
- if (ops->log_message) {
+ sprintf(buf, format, sender);
+ if (ops->log_message) {
ops->log_message(opdata, buf);
- }
- free(buf);
+ }
+ free(buf);
}
edata.ignore_message = 1;
- } else if (edata.ignore_message == 0 &&
- context->their_keyid > 0) {
+ } else if (edata.ignore_message == 0 &&
+ context->their_keyid > 0) {
/* If it's *not* a heartbeat, and we haven't
* sent anything in a while, also send a
* heartbeat. */
time_t now = time(NULL);
if (context->lastsent < (now - HEARTBEAT_INTERVAL)) {
- char *heartbeat;
+ char *heartbeat;
- /* Create the heartbeat message */
- err = otrl_proto_create_data(&heartbeat,
- context, "", NULL,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
+ /* Create the heartbeat message */
+ err = otrl_proto_create_data(&heartbeat,
+ context, "", NULL,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
/* Send it, and log a debug message */
if (ops->inject_message) {
- ops->inject_message(opdata, accountname,
- protocol, sender, heartbeat);
+ ops->inject_message(opdata, accountname,
+ protocol, sender, heartbeat);
}
free(heartbeat);
@@ -1163,122 +1163,122 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
buf = malloc(strlen(format) + strlen(sender)
- 1);
if (buf) {
- sprintf(buf, format, sender);
- if (ops->log_message) {
+ sprintf(buf, format, sender);
+ if (ops->log_message) {
ops->log_message(opdata, buf);
- }
- free(buf);
+ }
+ free(buf);
+ }
}
- }
}
- }
+ }
- /* Return the TLVs even if ignore_message == 1 so
- * that we can attach TLVs to heartbeats. */
- if (tlvsp) {
+ /* Return the TLVs even if ignore_message == 1 so
+ * that we can attach TLVs to heartbeats. */
+ if (tlvsp) {
*tlvsp = tlvs;
- } else {
+ } else {
otrl_tlv_free(tlvs);
- }
+ }
- if (edata.ignore_message != 1) {
+ if (edata.ignore_message != 1) {
*newmessagep = plaintext;
edata.ignore_message = 0;
- } else {
+ } else {
free(plaintext);
- }
- break;
- }
- break;
+ }
+ break;
+ }
+ break;
case OTRL_MSGTYPE_ERROR:
- if ((policy & OTRL_POLICY_ERROR_START_AKE)) {
+ if ((policy & OTRL_POLICY_ERROR_START_AKE)) {
char *msgtosend = otrl_proto_default_query_msg(
context->accountname, policy);
if (msgtosend && ops->inject_message) {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username,
- msgtosend);
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username,
+ msgtosend);
}
free(msgtosend);
- }
+ }
- if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
+ if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
/* Mark the last message we sent as eligible for
* retransmission */
context->may_retransmit = 1;
- }
+ }
- /* In any event, display the error message, with the
- * display_otr_message callback, if possible */
- if (ops->display_otr_message) {
+ /* In any event, display the error message, with the
+ * display_otr_message callback, if possible */
+ if (ops->display_otr_message) {
const char *otrerror = strstr(message, "?OTR Error:");
if (otrerror) {
- /* Skip the leading '?' */
- ++otrerror;
+ /* Skip the leading '?' */
+ ++otrerror;
} else {
- otrerror = message;
+ otrerror = message;
}
if (!ops->display_otr_message(opdata, accountname, protocol,
- sender, otrerror)) {
- edata.ignore_message = 1;
+ sender, otrerror)) {
+ edata.ignore_message = 1;
+ }
}
- }
- break;
+ break;
case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
- /* Strip the tag from the message */
- bestversion = otrl_proto_whitespace_bestversion(message,
- &startwhite, &endwhite, policy);
- if (startwhite && endwhite) {
+ /* Strip the tag from the message */
+ bestversion = otrl_proto_whitespace_bestversion(message,
+ &startwhite, &endwhite, policy);
+ if (startwhite && endwhite) {
size_t restlen = strlen(endwhite);
- char *strippedmsg = strdup(message);
+ char *strippedmsg = _strdup(message);
if (strippedmsg) {
- memmove(strippedmsg + (startwhite - message),
- strippedmsg + (endwhite - message), restlen+1);
- *newmessagep = strippedmsg;
- edata.ignore_message = 0;
+ memmove(strippedmsg + (startwhite - message),
+ strippedmsg + (endwhite - message), restlen+1);
+ *newmessagep = strippedmsg;
+ edata.ignore_message = 0;
+ }
}
- }
- if (bestversion && context->msgstate != OTRL_MSGSTATE_ENCRYPTED
- && (policy & OTRL_POLICY_WHITESPACE_START_AKE)) {
+ if (bestversion && context->msgstate != OTRL_MSGSTATE_ENCRYPTED
+ && (policy & OTRL_POLICY_WHITESPACE_START_AKE)) {
switch(bestversion) {
- case 2:
+ case 2:
err = otrl_auth_start_v2(&(context->auth));
send_or_error_auth(ops, opdata, err, context);
break;
- case 1:
+ case 1:
/* Get our private key */
privkey = otrl_privkey_find(us, context->accountname,
context->protocol);
if (privkey == NULL) {
- /* We've got no private key! */
- if (ops->create_privkey) {
+ /* We've got no private key! */
+ if (ops->create_privkey) {
ops->create_privkey(opdata,
context->accountname,
context->protocol);
privkey = otrl_privkey_find(us,
context->accountname,
context->protocol);
- }
+ }
}
if (privkey) {
- err = otrl_auth_start_v1(&(context->auth), NULL, 0,
- privkey);
- send_or_error_auth(ops, opdata, err, context);
+ err = otrl_auth_start_v1(&(context->auth), NULL, 0,
+ privkey);
+ send_or_error_auth(ops, opdata, err, context);
}
break;
- default:
+ default:
/* Don't start the AKE */
break;
}
- }
+ }
- /* FALLTHROUGH */
+ /* FALLTHROUGH */
case OTRL_MSGTYPE_NOTOTR:
- if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
- (policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
+ if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
+ (policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
/* Not fine. Let the user know. */
/* Don't use g_strdup_printf here, because someone
@@ -1286,56 +1286,56 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
* not g_free() it. */
const char *plainmsg = (*newmessagep) ? *newmessagep : message;
const char *format = "<b>The following message received "
- "from %s was <i>not</i> encrypted: [</b>%s<b>]</b>";
+ "from %s was <i>not</i> encrypted: [</b>%s<b>]</b>";
char *buf = malloc(strlen(format) + strlen(context->username)
+ strlen(plainmsg) - 3);
/* Remove "%s%s", add username + message + '\0' */
if (buf) {
- sprintf(buf, format, context->username, plainmsg);
- if (ops->display_otr_message) {
+ sprintf(buf, format, context->username, plainmsg);
+ if (ops->display_otr_message) {
if (!ops->display_otr_message(opdata, accountname,
- protocol, sender, buf)) {
- free(*newmessagep);
- *newmessagep = NULL;
- edata.ignore_message = 1;
+ protocol, sender, buf)) {
+ free(*newmessagep);
+ *newmessagep = NULL;
+ edata.ignore_message = 1;
+ }
}
- }
- if (edata.ignore_message != 1) {
+ if (edata.ignore_message != 1) {
free(*newmessagep);
*newmessagep = buf;
edata.ignore_message = 0;
- } else {
+ } else {
free(buf);
- }
+ }
}
- }
- break;
+ }
+ break;
case OTRL_MSGTYPE_UNKNOWN:
- /* We received an OTR message we didn't recognize. Ignore
- * it, but make a log entry. */
- if (ops->log_message) {
+ /* We received an OTR message we didn't recognize. Ignore
+ * it, but make a log entry. */
+ if (ops->log_message) {
const char *format = "Unrecognized OTR message received "
- "from %s.\n";
+ "from %s.\n";
char *buf = malloc(strlen(format) + strlen(sender) - 1);
if (buf) {
- sprintf(buf, format, sender);
- ops->log_message(opdata, buf);
- free(buf);
+ sprintf(buf, format, sender);
+ ops->log_message(opdata, buf);
+ free(buf);
+ }
}
- }
- if (edata.ignore_message == -1) edata.ignore_message = 1;
- break;
- }
-
- /* If we reassembled a fragmented message, we need to free the
- * allocated memory now. */
- if (fragment_assembled) {
+ if (edata.ignore_message == -1) edata.ignore_message = 1;
+ break;
+ }
+
+ /* If we reassembled a fragmented message, we need to free the
+ * allocated memory now. */
+ if (fragment_assembled) {
free(unfragmessage);
- }
+ }
- if (edata.ignore_message == -1) edata.ignore_message = 0;
- return edata.ignore_message;
+ if (edata.ignore_message == -1) edata.ignore_message = 0;
+ return edata.ignore_message;
}
/* Send a message to the network, fragmenting first if necessary.
@@ -1345,67 +1345,67 @@ gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
void *opdata, ConnContext *context, const char *message,
OtrlFragmentPolicy fragPolicy, char **returnFragment)
{
- int mms = 0;
- if (message && ops->inject_message) {
- int msglen;
+ int mms = 0;
+ if (message && ops->inject_message) {
+ int msglen;
- if (otrl_api_version >= 0x030100 && ops->max_message_size) {
- mms = ops->max_message_size(opdata, context);
- }
- msglen = strlen(message);
+ if (otrl_api_version >= 0x030100 && ops->max_message_size) {
+ mms = ops->max_message_size(opdata, context);
+ }
+ msglen = strlen(message);
/* Don't incur overhead of fragmentation unless necessary */
- if(mms != 0 && msglen > mms) {
- char **fragments;
- gcry_error_t err;
- int i;
- int fragment_count = ((msglen - 1) / (mms -19)) + 1;
+ if(mms != 0 && msglen > mms) {
+ char **fragments;
+ gcry_error_t err;
+ int i;
+ int fragment_count = ((msglen - 1) / (mms -19)) + 1;
/* like ceil(msglen/(mms - 19)) */
- err = otrl_proto_fragment_create(mms, fragment_count, &fragments,
- message);
- if (err) {
+ err = otrl_proto_fragment_create(mms, fragment_count, &fragments,
+ message);
+ if (err) {
return err;
- }
-
- /* Determine which fragments to send and which to return
- * based on given Fragment Policy. If the first fragment
- * should be returned instead of sent, store it. */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_FIRST) {
- *returnFragment = strdup(fragments[0]);
- } else {
+ }
+
+ /* Determine which fragments to send and which to return
+ * based on given Fragment Policy. If the first fragment
+ * should be returned instead of sent, store it. */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_FIRST) {
+ *returnFragment = _strdup(fragments[0]);
+ } else {
ops->inject_message(opdata, context->accountname,
context->protocol, context->username, fragments[0]);
- }
- for (i=1; i<fragment_count-1; i++) {
+ }
+ for (i=1; i<fragment_count-1; i++) {
ops->inject_message(opdata, context->accountname,
context->protocol, context->username, fragments[i]);
- }
- /* If the last fragment should be stored instead of sent,
- * store it */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_LAST) {
- *returnFragment = strdup(fragments[fragment_count-1]);
- } else {
+ }
+ /* If the last fragment should be stored instead of sent,
+ * store it */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_LAST) {
+ *returnFragment = _strdup(fragments[fragment_count-1]);
+ } else {
ops->inject_message(opdata, context->accountname,
context->protocol, context->username, fragments[fragment_count-1]);
- }
- /* Now free all fragment memory */
- otrl_proto_fragment_free(&fragments, fragment_count);
+ }
+ /* Now free all fragment memory */
+ otrl_proto_fragment_free(&fragments, fragment_count);
} else {
- /* No fragmentation necessary */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL) {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, message);
- } else {
+ /* No fragmentation necessary */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL) {
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username, message);
+ } else {
/* Copy and return the entire given message. */
int l = strlen(message) + 1;
*returnFragment = malloc(sizeof(char)*l);
strcpy(*returnFragment, message);
- }
+ }
+ }
}
- }
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* Put a connection into the PLAINTEXT state, first sending the
@@ -1415,32 +1415,32 @@ void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, const char *accountname, const char *protocol,
const char *username)
{
- ConnContext *context = otrl_context_find(us, username, accountname,
- protocol, 0, NULL, NULL, NULL);
+ ConnContext *context = otrl_context_find(us, username, accountname,
+ protocol, 0, NULL, NULL, NULL);
- if (!context) return;
+ if (!context) return;
- if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
- context->their_keyid > 0 &&
- ops->is_logged_in &&
- ops->is_logged_in(opdata, accountname, protocol, username) == 1) {
+ if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
+ context->their_keyid > 0 &&
+ ops->is_logged_in &&
+ ops->is_logged_in(opdata, accountname, protocol, username) == 1) {
if (ops->inject_message) {
- char *encmsg = NULL;
- gcry_error_t err;
- OtrlTLV *tlv = otrl_tlv_new(OTRL_TLV_DISCONNECTED, 0, NULL);
+ char *encmsg = NULL;
+ gcry_error_t err;
+ OtrlTLV *tlv = otrl_tlv_new(OTRL_TLV_DISCONNECTED, 0, NULL);
- err = otrl_proto_create_data(&encmsg, context, "", tlv,
- OTRL_MSGFLAGS_IGNORE_UNREADABLE);
- if (!err) {
+ err = otrl_proto_create_data(&encmsg, context, "", tlv,
+ OTRL_MSGFLAGS_IGNORE_UNREADABLE);
+ if (!err) {
ops->inject_message(opdata, accountname, protocol,
username, encmsg);
- }
- free(encmsg);
+ }
+ free(encmsg);
+ }
}
- }
- otrl_context_force_plaintext(context);
- if (ops->update_context_list) {
+ otrl_context_force_plaintext(context);
+ if (ops->update_context_list) {
ops->update_context_list(opdata);
- }
+ }
}
diff --git a/libotr-3.2.0/src/privkey.c b/libotr-3.2.0/src/privkey.c
index 78a4a18..498bfae 100644
--- a/libotr-3.2.0/src/privkey.c
+++ b/libotr-3.2.0/src/privkey.c
@@ -33,19 +33,19 @@
/* Convert a 20-byte hash value to a 45-byte human-readable value */
void otrl_privkey_hash_to_human(char human[45], const unsigned char hash[20])
{
- int word, byte;
- char *p = human;
+ int word, byte;
+ char *p = human;
- for(word=0; word<5; ++word) {
+ for(word=0; word<5; ++word) {
for(byte=0; byte<4; ++byte) {
- sprintf(p, "%02X", hash[word*4+byte]);
- p += 2;
+ sprintf(p, "%02X", hash[word*4+byte]);
+ p += 2;
}
*(p++) = ' ';
- }
- /* Change that last ' ' to a '\0' */
- --p;
- *p = '\0';
+ }
+ /* Change that last ' ' to a '\0' */
+ --p;
+ *p = '\0';
}
/* Calculate a human-readable hash of our DSA public key. Return it in
@@ -54,21 +54,21 @@ void otrl_privkey_hash_to_human(char human[45], const unsigned char hash[20])
char *otrl_privkey_fingerprint(OtrlUserState us, char fingerprint[45],
const char *accountname, const char *protocol)
{
- unsigned char hash[20];
- OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
+ unsigned char hash[20];
+ OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
- if (p) {
+ if (p) {
/* Calculate the hash */
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, p->pubkey_data,
p->pubkey_datalen);
/* Now convert it to a human-readable format */
otrl_privkey_hash_to_human(fingerprint, hash);
- } else {
+ } else {
return NULL;
- }
+ }
- return fingerprint;
+ return fingerprint;
}
/* Calculate a raw hash of our DSA public key. Return it in the passed
@@ -77,170 +77,170 @@ char *otrl_privkey_fingerprint(OtrlUserState us, char fingerprint[45],
unsigned char *otrl_privkey_fingerprint_raw(OtrlUserState us,
unsigned char hash[20], const char *accountname, const char *protocol)
{
- OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
+ OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
- if (p) {
+ if (p) {
/* Calculate the hash */
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, p->pubkey_data,
p->pubkey_datalen);
- } else {
+ } else {
return NULL;
- }
+ }
- return hash;
+ return hash;
}
/* Create a public key block from a private key */
static gcry_error_t make_pubkey(unsigned char **pubbufp, size_t *publenp,
gcry_sexp_t privkey)
{
- gcry_mpi_t p,q,g,y;
- gcry_sexp_t dsas,ps,qs,gs,ys;
- size_t np,nq,ng,ny;
- enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- unsigned char *bufp;
- size_t lenp;
-
- *pubbufp = NULL;
- *publenp = 0;
-
- /* Extract the public parameters */
- dsas = gcry_sexp_find_token(privkey, "dsa", 0);
- if (dsas == NULL) {
+ gcry_mpi_t p,q,g,y;
+ gcry_sexp_t dsas,ps,qs,gs,ys;
+ size_t np,nq,ng,ny;
+ enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ unsigned char *bufp;
+ size_t lenp;
+
+ *pubbufp = NULL;
+ *publenp = 0;
+
+ /* Extract the public parameters */
+ dsas = gcry_sexp_find_token(privkey, "dsa", 0);
+ if (dsas == NULL) {
return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
- }
- ps = gcry_sexp_find_token(dsas, "p", 0);
- qs = gcry_sexp_find_token(dsas, "q", 0);
- gs = gcry_sexp_find_token(dsas, "g", 0);
- ys = gcry_sexp_find_token(dsas, "y", 0);
- gcry_sexp_release(dsas);
- if (!ps || !qs || !gs || !ys) {
+ }
+ ps = gcry_sexp_find_token(dsas, "p", 0);
+ qs = gcry_sexp_find_token(dsas, "q", 0);
+ gs = gcry_sexp_find_token(dsas, "g", 0);
+ ys = gcry_sexp_find_token(dsas, "y", 0);
+ gcry_sexp_release(dsas);
+ if (!ps || !qs || !gs || !ys) {
gcry_sexp_release(ps);
gcry_sexp_release(qs);
gcry_sexp_release(gs);
gcry_sexp_release(ys);
return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
- }
- p = gcry_sexp_nth_mpi(ps, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(ps);
- q = gcry_sexp_nth_mpi(qs, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(qs);
- g = gcry_sexp_nth_mpi(gs, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(gs);
- y = gcry_sexp_nth_mpi(ys, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(ys);
- if (!p || !q || !g || !y) {
+ }
+ p = gcry_sexp_nth_mpi(ps, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(ps);
+ q = gcry_sexp_nth_mpi(qs, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(qs);
+ g = gcry_sexp_nth_mpi(gs, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(gs);
+ y = gcry_sexp_nth_mpi(ys, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(ys);
+ if (!p || !q || !g || !y) {
gcry_mpi_release(p);
gcry_mpi_release(q);
gcry_mpi_release(g);
gcry_mpi_release(y);
return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
- }
-
- *publenp = 0;
- gcry_mpi_print(format, NULL, 0, &np, p);
- *publenp += np + 4;
- gcry_mpi_print(format, NULL, 0, &nq, q);
- *publenp += nq + 4;
- gcry_mpi_print(format, NULL, 0, &ng, g);
- *publenp += ng + 4;
- gcry_mpi_print(format, NULL, 0, &ny, y);
- *publenp += ny + 4;
-
- *pubbufp = malloc(*publenp);
- if (*pubbufp == NULL) {
+ }
+
+ *publenp = 0;
+ gcry_mpi_print(format, NULL, 0, &np, p);
+ *publenp += np + 4;
+ gcry_mpi_print(format, NULL, 0, &nq, q);
+ *publenp += nq + 4;
+ gcry_mpi_print(format, NULL, 0, &ng, g);
+ *publenp += ng + 4;
+ gcry_mpi_print(format, NULL, 0, &ny, y);
+ *publenp += ny + 4;
+
+ *pubbufp = malloc(*publenp);
+ if (*pubbufp == NULL) {
gcry_mpi_release(p);
gcry_mpi_release(q);
gcry_mpi_release(g);
gcry_mpi_release(y);
return gcry_error(GPG_ERR_ENOMEM);
- }
- bufp = *pubbufp;
- lenp = *publenp;
+ }
+ bufp = *pubbufp;
+ lenp = *publenp;
- write_mpi(p,np,"P");
- write_mpi(q,nq,"Q");
- write_mpi(g,ng,"G");
- write_mpi(y,ny,"Y");
+ write_mpi(p,np,"P");
+ write_mpi(q,nq,"Q");
+ write_mpi(g,ng,"G");
+ write_mpi(y,ny,"Y");
- gcry_mpi_release(p);
- gcry_mpi_release(q);
- gcry_mpi_release(g);
- gcry_mpi_release(y);
+ gcry_mpi_release(p);
+ gcry_mpi_release(q);
+ gcry_mpi_release(g);
+ gcry_mpi_release(y);
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* Read a sets of private DSA keys from a file on disk into the given
* OtrlUserState. */
gcry_error_t otrl_privkey_read(OtrlUserState us, const char *filename)
{
- FILE *privf;
- gcry_error_t err;
-
- /* Open the privkey file. We use rb mode so that on WIN32, fread()
- * reads the same number of bytes that fstat() indicates are in the
- * file. */
- privf = fopen(filename, "rb");
- if (!privf) {
+ FILE *privf;
+ gcry_error_t err;
+
+ /* Open the privkey file. We use rb mode so that on WIN32, fread()
+ * reads the same number of bytes that fstat() indicates are in the
+ * file. */
+ privf = fopen(filename, "rb");
+ if (!privf) {
err = gcry_error_from_errno(errno);
return err;
- }
+ }
- err = otrl_privkey_read_FILEp(us, privf);
+ err = otrl_privkey_read_FILEp(us, privf);
- fclose(privf);
- return err;
+ fclose(privf);
+ return err;
}
/* Read a sets of private DSA keys from a FILE* into the given
* OtrlUserState. The FILE* must be open for reading. */
gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
{
- int privfd;
- struct stat st;
- char *buf;
- const char *token;
- size_t tokenlen;
- gcry_error_t err;
- gcry_sexp_t allkeys;
- size_t i;
-
- if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
-
- /* Release any old ideas we had about our keys */
- otrl_privkey_forget_all(us);
-
- /* Load the data into a buffer */
- privfd = fileno(privf);
- if (fstat(privfd, &st)) {
+ int privfd;
+ struct stat st;
+ char *buf;
+ const char *token;
+ size_t tokenlen;
+ gcry_error_t err;
+ gcry_sexp_t allkeys;
+ size_t i;
+
+ if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
+
+ /* Release any old ideas we had about our keys */
+ otrl_privkey_forget_all(us);
+
+ /* Load the data into a buffer */
+ privfd = _fileno(privf);
+ if (fstat(privfd, &st)) {
err = gcry_error_from_errno(errno);
return err;
- }
- buf = malloc(st.st_size);
- if (!buf && st.st_size > 0) {
+ }
+ buf = malloc(st.st_size);
+ if (!buf && st.st_size > 0) {
return gcry_error(GPG_ERR_ENOMEM);
- }
- if (fread(buf, st.st_size, 1, privf) != 1) {
+ }
+ if (fread(buf, st.st_size, 1, privf) != 1) {
err = gcry_error_from_errno(errno);
free(buf);
return err;
- }
+ }
- err = gcry_sexp_new(&allkeys, buf, st.st_size, 0);
- free(buf);
- if (err) {
+ err = gcry_sexp_new(&allkeys, buf, st.st_size, 0);
+ free(buf);
+ if (err) {
return err;
- }
+ }
- token = gcry_sexp_nth_data(allkeys, 0, &tokenlen);
- if (tokenlen != 8 || strncmp(token, "privkeys", 8)) {
+ token = gcry_sexp_nth_data(allkeys, 0, &tokenlen);
+ if (tokenlen != 8 || strncmp(token, "privkeys", 8)) {
gcry_sexp_release(allkeys);
return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
- }
+ }
- /* Get each account */
- for(i=1; i<gcry_sexp_length(allkeys); ++i) {
+ /* Get each account */
+ for(i=1; i<gcry_sexp_length(allkeys); ++i) {
gcry_sexp_t names, protos, privs;
char *name, *proto;
gcry_sexp_t accounts;
@@ -252,9 +252,9 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
/* It's really an "account" S-exp? */
token = gcry_sexp_nth_data(accounts, 0, &tokenlen);
if (tokenlen != 7 || strncmp(token, "account", 7)) {
- gcry_sexp_release(accounts);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ gcry_sexp_release(accounts);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
}
/* Extract the name, protocol, and privkey S-exps */
names = gcry_sexp_find_token(accounts, "name", 0);
@@ -262,28 +262,28 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
privs = gcry_sexp_find_token(accounts, "private-key", 0);
gcry_sexp_release(accounts);
if (!names || !protos || !privs) {
- gcry_sexp_release(names);
- gcry_sexp_release(protos);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ gcry_sexp_release(names);
+ gcry_sexp_release(protos);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
}
/* Extract the actual name and protocol */
token = gcry_sexp_nth_data(names, 1, &tokenlen);
if (!token) {
- gcry_sexp_release(names);
- gcry_sexp_release(protos);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ gcry_sexp_release(names);
+ gcry_sexp_release(protos);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
}
name = malloc(tokenlen + 1);
if (!name) {
- gcry_sexp_release(names);
- gcry_sexp_release(protos);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_ENOMEM);
+ gcry_sexp_release(names);
+ gcry_sexp_release(protos);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_ENOMEM);
}
memmove(name, token, tokenlen);
name[tokenlen] = '\0';
@@ -291,19 +291,19 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
token = gcry_sexp_nth_data(protos, 1, &tokenlen);
if (!token) {
- free(name);
- gcry_sexp_release(protos);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ free(name);
+ gcry_sexp_release(protos);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
}
proto = malloc(tokenlen + 1);
if (!proto) {
- free(name);
- gcry_sexp_release(protos);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_ENOMEM);
+ free(name);
+ gcry_sexp_release(protos);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_ENOMEM);
}
memmove(proto, token, tokenlen);
proto[tokenlen] = '\0';
@@ -312,11 +312,11 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
/* Make a new OtrlPrivKey entry */
p = malloc(sizeof(*p));
if (!p) {
- free(name);
- free(proto);
- gcry_sexp_release(privs);
- gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_ENOMEM);
+ free(name);
+ free(proto);
+ gcry_sexp_release(privs);
+ gcry_sexp_release(allkeys);
+ return gcry_error(GPG_ERR_ENOMEM);
}
/* Fill it in and link it up */
@@ -326,63 +326,63 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
p->privkey = privs;
p->next = us->privkey_root;
if (p->next) {
- p->next->tous = &(p->next);
+ p->next->tous = &(p->next);
}
p->tous = &(us->privkey_root);
us->privkey_root = p;
err = make_pubkey(&(p->pubkey_data), &(p->pubkey_datalen), p->privkey);
if (err) {
- gcry_sexp_release(allkeys);
- otrl_privkey_forget(p);
- return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ gcry_sexp_release(allkeys);
+ otrl_privkey_forget(p);
+ return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
+ }
}
- }
- gcry_sexp_release(allkeys);
+ gcry_sexp_release(allkeys);
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
static gcry_error_t sexp_write(FILE *privf, gcry_sexp_t sexp)
{
- size_t buflen;
- char *buf;
+ size_t buflen;
+ char *buf;
- buflen = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
- buf = malloc(buflen);
- if (buf == NULL && buflen > 0) {
+ buflen = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+ buf = malloc(buflen);
+ if (buf == NULL && buflen > 0) {
return gcry_error(GPG_ERR_ENOMEM);
- }
- gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, buflen);
-
- fprintf(privf, "%s", buf);
- free(buf);
+ }
+ gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, buflen);
+
+ fprintf(privf, "%s", buf);
+ free(buf);
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
static gcry_error_t account_write(FILE *privf, const char *accountname,
const char *protocol, gcry_sexp_t privkey)
{
- gcry_error_t err;
- gcry_sexp_t names, protos;
+ gcry_error_t err;
+ gcry_sexp_t names, protos;
- fprintf(privf, " (account\n");
+ fprintf(privf, " (account\n");
- err = gcry_sexp_build(&names, NULL, "(name %s)", accountname);
- if (!err) {
+ err = gcry_sexp_build(&names, NULL, "(name %s)", accountname);
+ if (!err) {
err = sexp_write(privf, names);
gcry_sexp_release(names);
- }
- if (!err) err = gcry_sexp_build(&protos, NULL, "(protocol %s)", protocol);
- if (!err) {
+ }
+ if (!err) err = gcry_sexp_build(&protos, NULL, "(protocol %s)", protocol);
+ if (!err) {
err = sexp_write(privf, protos);
gcry_sexp_release(protos);
- }
- if (!err) err = sexp_write(privf, privkey);
+ }
+ if (!err) err = sexp_write(privf, privkey);
- fprintf(privf, " )\n");
+ fprintf(privf, " )\n");
- return err;
+ return err;
}
/* Generate a private DSA key for a given account, storing it into a
@@ -391,31 +391,31 @@ static gcry_error_t account_write(FILE *privf, const char *accountname,
gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
const char *accountname, const char *protocol)
{
- gcry_error_t err;
- FILE *privf;
+ gcry_error_t err;
+ FILE *privf;
#ifndef WIN32
- mode_t oldmask;
+ mode_t oldmask;
#endif
#ifndef WIN32
- oldmask = umask(077);
+ oldmask = umask(077);
#endif
- privf = fopen(filename, "w+b");
- if (!privf) {
+ privf = fopen(filename, "w+b");
+ if (!privf) {
#ifndef WIN32
umask(oldmask);
#endif
err = gcry_error_from_errno(errno);
return err;
- }
+ }
- err = otrl_privkey_generate_FILEp(us, privf, accountname, protocol);
+ err = otrl_privkey_generate_FILEp(us, privf, accountname, protocol);
- fclose(privf);
+ fclose(privf);
#ifndef WIN32
- umask(oldmask);
+ umask(oldmask);
#endif
- return err;
+ return err;
}
/* Generate a private DSA key for a given account, storing it into a
@@ -425,56 +425,56 @@ gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
const char *accountname, const char *protocol)
{
- gcry_error_t err;
- gcry_sexp_t key, parms, privkey;
- static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
- OtrlPrivKey *p;
+ gcry_error_t err;
+ gcry_sexp_t key, parms, privkey;
+ static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
+ OtrlPrivKey *p;
- if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
+ if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
- /* Create a DSA key */
- err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
- if (err) {
+ /* Create a DSA key */
+ err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
+ if (err) {
return err;
- }
- err = gcry_pk_genkey(&key, parms);
- gcry_sexp_release(parms);
- if (err) {
+ }
+ err = gcry_pk_genkey(&key, parms);
+ gcry_sexp_release(parms);
+ if (err) {
return err;
- }
+ }
- /* Extract the privkey */
- privkey = gcry_sexp_find_token(key, "private-key", 0);
- gcry_sexp_release(key);
+ /* Extract the privkey */
+ privkey = gcry_sexp_find_token(key, "private-key", 0);
+ gcry_sexp_release(key);
- /* Output the other keys we know */
- fprintf(privf, "(privkeys\n");
+ /* Output the other keys we know */
+ fprintf(privf, "(privkeys\n");
- for (p=us->privkey_root; p; p=p->next) {
+ for (p=us->privkey_root; p; p=p->next) {
/* Skip this one if our new key replaces it */
if (!strcmp(p->accountname, accountname) &&
!strcmp(p->protocol, protocol)) {
- continue;
+ continue;
}
account_write(privf, p->accountname, p->protocol, p->privkey);
- }
- account_write(privf, accountname, protocol, privkey);
- gcry_sexp_release(privkey);
- fprintf(privf, ")\n");
+ }
+ account_write(privf, accountname, protocol, privkey);
+ gcry_sexp_release(privkey);
+ fprintf(privf, ")\n");
- fseek(privf, 0, SEEK_SET);
+ fseek(privf, 0, SEEK_SET);
- return otrl_privkey_read_FILEp(us, privf);
+ return otrl_privkey_read_FILEp(us, privf);
}
/* Convert a hex character to a value */
static unsigned int ctoh(char c)
{
- if (c >= '0' && c <= '9') return c-'0';
- if (c >= 'a' && c <= 'f') return c-'a'+10;
- if (c >= 'A' && c <= 'F') return c-'A'+10;
- return 0; /* Unknown hex char */
+ if (c >= '0' && c <= '9') return c-'0';
+ if (c >= 'a' && c <= 'f') return c-'a'+10;
+ if (c >= 'A' && c <= 'F') return c-'A'+10;
+ return 0; /* Unknown hex char */
}
/* Read the fingerprint store from a file on disk into the given
@@ -485,19 +485,19 @@ gcry_error_t otrl_privkey_read_fingerprints(OtrlUserState us,
void (*add_app_data)(void *data, ConnContext *context),
void *data)
{
- gcry_error_t err;
- FILE *storef;
+ gcry_error_t err;
+ FILE *storef;
- storef = fopen(filename, "rb");
- if (!storef) {
+ storef = fopen(filename, "rb");
+ if (!storef) {
err = gcry_error_from_errno(errno);
return err;
- }
+ }
- err = otrl_privkey_read_fingerprints_FILEp(us, storef, add_app_data, data);
+ err = otrl_privkey_read_fingerprints_FILEp(us, storef, add_app_data, data);
- fclose(storef);
- return err;
+ fclose(storef);
+ return err;
}
/* Read the fingerprint store from a FILE* into the given
@@ -508,14 +508,14 @@ gcry_error_t otrl_privkey_read_fingerprints_FILEp(OtrlUserState us,
void (*add_app_data)(void *data, ConnContext *context),
void *data)
{
- ConnContext *context;
- char storeline[1000];
- unsigned char fingerprint[20];
- size_t maxsize = sizeof(storeline);
+ ConnContext *context;
+ char storeline[1000];
+ unsigned char fingerprint[20];
+ size_t maxsize = sizeof(storeline);
- if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
+ if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
- while(fgets(storeline, maxsize, storef)) {
+ while(fgets(storeline, maxsize, storef)) {
char *username;
char *accountname;
char *protocol;
@@ -545,23 +545,23 @@ gcry_error_t otrl_privkey_read_fingerprints_FILEp(OtrlUserState us,
hex = tab + 1;
tab = strchr(hex, '\t');
if (!tab) {
- eol = strchr(hex, '\r');
- if (!eol) eol = strchr(hex, '\n');
- if (!eol) continue;
- *eol = '\0';
- trust = NULL;
+ eol = strchr(hex, '\r');
+ if (!eol) eol = strchr(hex, '\n');
+ if (!eol) continue;
+ *eol = '\0';
+ trust = NULL;
} else {
- *tab = '\0';
- trust = tab + 1;
- eol = strchr(trust, '\r');
- if (!eol) eol = strchr(trust, '\n');
- if (!eol) continue;
- *eol = '\0';
+ *tab = '\0';
+ trust = tab + 1;
+ eol = strchr(trust, '\r');
+ if (!eol) eol = strchr(trust, '\n');
+ if (!eol) continue;
+ *eol = '\0';
}
if (strlen(hex) != 40) continue;
for(j=0, i=0; i<40; i+=2) {
- fingerprint[j++] = (ctoh(hex[i]) << 4) + (ctoh(hex[i+1]));
+ fingerprint[j++] = (ctoh(hex[i]) << 4) + (ctoh(hex[i+1]));
}
/* Get the context for this user, adding if not yet present */
context = otrl_context_find(us, username, accountname, protocol,
@@ -569,28 +569,28 @@ gcry_error_t otrl_privkey_read_fingerprints_FILEp(OtrlUserState us,
/* Add the fingerprint if not already there */
fng = otrl_context_find_fingerprint(context, fingerprint, 1, NULL);
otrl_context_set_trust(fng, trust);
- }
+ }
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* Write the fingerprint store from a given OtrlUserState to a file on disk. */
gcry_error_t otrl_privkey_write_fingerprints(OtrlUserState us,
const char *filename)
{
- gcry_error_t err;
- FILE *storef;
+ gcry_error_t err;
+ FILE *storef;
- storef = fopen(filename, "wb");
- if (!storef) {
+ storef = fopen(filename, "wb");
+ if (!storef) {
err = gcry_error_from_errno(errno);
return err;
- }
+ }
- err = otrl_privkey_write_fingerprints_FILEp(us, storef);
+ err = otrl_privkey_write_fingerprints_FILEp(us, storef);
- fclose(storef);
- return err;
+ fclose(storef);
+ return err;
}
/* Write the fingerprint store from a given OtrlUserState to a FILE*.
@@ -598,26 +598,26 @@ gcry_error_t otrl_privkey_write_fingerprints(OtrlUserState us,
gcry_error_t otrl_privkey_write_fingerprints_FILEp(OtrlUserState us,
FILE *storef)
{
- ConnContext *context;
- Fingerprint *fprint;
+ ConnContext *context;
+ Fingerprint *fprint;
- if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
+ if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
- for(context = us->context_root; context; context = context->next) {
+ for(context = us->context_root; context; context = context->next) {
/* Don't both with the first (fingerprintless) entry. */
for (fprint = context->fingerprint_root.next; fprint;
fprint = fprint->next) {
- int i;
- fprintf(storef, "%s\t%s\t%s\t", context->username,
- context->accountname, context->protocol);
- for(i=0;i<20;++i) {
+ int i;
+ fprintf(storef, "%s\t%s\t%s\t", context->username,
+ context->accountname, context->protocol);
+ for(i=0;i<20;++i) {
fprintf(storef, "%02x", fprint->fingerprint[i]);
- }
- fprintf(storef, "\t%s\n", fprint->trust ? fprint->trust : "");
+ }
+ fprintf(storef, "\t%s\n", fprint->trust ? fprint->trust : "");
+ }
}
- }
- return gcry_error(GPG_ERR_NO_ERROR);
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* Fetch the private key from the given OtrlUserState associated with
@@ -625,42 +625,42 @@ gcry_error_t otrl_privkey_write_fingerprints_FILEp(OtrlUserState us,
OtrlPrivKey *otrl_privkey_find(OtrlUserState us, const char *accountname,
const char *protocol)
{
- OtrlPrivKey *p;
- if (!accountname || !protocol) return NULL;
+ OtrlPrivKey *p;
+ if (!accountname || !protocol) return NULL;
- for(p=us->privkey_root; p; p=p->next) {
+ for(p=us->privkey_root; p; p=p->next) {
if (!strcmp(p->accountname, accountname) &&
!strcmp(p->protocol, protocol)) {
- return p;
+ return p;
+ }
}
- }
- return NULL;
+ return NULL;
}
/* Forget a private key */
void otrl_privkey_forget(OtrlPrivKey *privkey)
{
- free(privkey->accountname);
- free(privkey->protocol);
- gcry_sexp_release(privkey->privkey);
- free(privkey->pubkey_data);
-
- /* Re-link the list */
- *(privkey->tous) = privkey->next;
- if (privkey->next) {
+ free(privkey->accountname);
+ free(privkey->protocol);
+ gcry_sexp_release(privkey->privkey);
+ free(privkey->pubkey_data);
+
+ /* Re-link the list */
+ *(privkey->tous) = privkey->next;
+ if (privkey->next) {
privkey->next->tous = privkey->tous;
- }
+ }
- /* Free the privkey struct */
- free(privkey);
+ /* Free the privkey struct */
+ free(privkey);
}
/* Forget all private keys in a given OtrlUserState. */
void otrl_privkey_forget_all(OtrlUserState us)
{
- while (us->privkey_root) {
+ while (us->privkey_root) {
otrl_privkey_forget(us->privkey_root);
- }
+ }
}
/* Sign data using a private key. The data must be small enough to be
@@ -670,45 +670,45 @@ void otrl_privkey_forget_all(OtrlUserState us)
gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
OtrlPrivKey *privkey, const unsigned char *data, size_t len)
{
- gcry_mpi_t r,s, datampi;
- gcry_sexp_t dsas, rs, ss, sigs, datas;
- size_t nr, ns;
- const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
+ gcry_mpi_t r,s, datampi;
+ gcry_sexp_t dsas, rs, ss, sigs, datas;
+ size_t nr, ns;
+ const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
- if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
+ if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
return gcry_error(GPG_ERR_INV_VALUE);
- *sigp = malloc(40);
- if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
- *siglenp = 40;
+ *sigp = malloc(40);
+ if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
+ *siglenp = 40;
- if (len) {
+ if (len) {
gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
- } else {
+ } else {
datampi = gcry_mpi_set_ui(NULL, 0);
- }
- gcry_sexp_build(&datas, NULL, "(%m)", datampi);
- gcry_mpi_release(datampi);
- gcry_pk_sign(&sigs, datas, privkey->privkey);
- gcry_sexp_release(datas);
- dsas = gcry_sexp_find_token(sigs, "dsa", 0);
- gcry_sexp_release(sigs);
- rs = gcry_sexp_find_token(dsas, "r", 0);
- ss = gcry_sexp_find_token(dsas, "s", 0);
- gcry_sexp_release(dsas);
- r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(rs);
- s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release(ss);
- gcry_mpi_print(format, NULL, 0, &nr, r);
- gcry_mpi_print(format, NULL, 0, &ns, s);
- memset(*sigp, 0, 40);
- gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r);
- gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s);
- gcry_mpi_release(r);
- gcry_mpi_release(s);
-
- return gcry_error(GPG_ERR_NO_ERROR);
+ }
+ gcry_sexp_build(&datas, NULL, "(%m)", datampi);
+ gcry_mpi_release(datampi);
+ gcry_pk_sign(&sigs, datas, privkey->privkey);
+ gcry_sexp_release(datas);
+ dsas = gcry_sexp_find_token(sigs, "dsa", 0);
+ gcry_sexp_release(sigs);
+ rs = gcry_sexp_find_token(dsas, "r", 0);
+ ss = gcry_sexp_find_token(dsas, "s", 0);
+ gcry_sexp_release(dsas);
+ r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(rs);
+ s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release(ss);
+ gcry_mpi_print(format, NULL, 0, &nr, r);
+ gcry_mpi_print(format, NULL, 0, &ns, s);
+ memset(*sigp, 0, 40);
+ gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r);
+ gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s);
+ gcry_mpi_release(r);
+ gcry_mpi_release(s);
+
+ return gcry_error(GPG_ERR_NO_ERROR);
}
/* Verify a signature on data using a public key. The data must be
@@ -717,31 +717,31 @@ gcry_error_t otrl_privkey_verify(const unsigned char *sigbuf, size_t siglen,
unsigned short pubkey_type, gcry_sexp_t pubs,
const unsigned char *data, size_t len)
{
- gcry_error_t err;
- gcry_mpi_t datampi,r,s;
- gcry_sexp_t datas, sigs;
+ gcry_error_t err;
+ gcry_mpi_t datampi,r,s;
+ gcry_sexp_t datas, sigs;
- if (pubkey_type != OTRL_PUBKEY_TYPE_DSA || siglen != 40)
+ if (pubkey_type != OTRL_PUBKEY_TYPE_DSA || siglen != 40)
return gcry_error(GPG_ERR_INV_VALUE);
- if (len) {
+ if (len) {
gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
- } else {
+ } else {
datampi = gcry_mpi_set_ui(NULL, 0);
- }
- gcry_sexp_build(&datas, NULL, "(%m)", datampi);
- gcry_mpi_release(datampi);
- gcry_mpi_scan(&r, GCRYMPI_FMT_USG, sigbuf, 20, NULL);
- gcry_mpi_scan(&s, GCRYMPI_FMT_USG, sigbuf+20, 20, NULL);
- gcry_sexp_build(&sigs, NULL, "(sig-val (dsa (r %m)(s %m)))", r, s);
- gcry_mpi_release(r);
- gcry_mpi_release(s);
-
- err = gcry_pk_verify(sigs, datas, pubs);
- gcry_sexp_release(datas);
- gcry_sexp_release(sigs);
-
- return err;
+ }
+ gcry_sexp_build(&datas, NULL, "(%m)", datampi);
+ gcry_mpi_release(datampi);
+ gcry_mpi_scan(&r, GCRYMPI_FMT_USG, sigbuf, 20, NULL);
+ gcry_mpi_scan(&s, GCRYMPI_FMT_USG, sigbuf+20, 20, NULL);
+ gcry_sexp_build(&sigs, NULL, "(sig-val (dsa (r %m)(s %m)))", r, s);
+ gcry_mpi_release(r);
+ gcry_mpi_release(s);
+
+ err = gcry_pk_verify(sigs, datas, pubs);
+ gcry_sexp_release(datas);
+ gcry_sexp_release(sigs);
+
+ return err;
}
gcry_error_t otrl_account_write(FILE *privf, const char *accountname,
const char *protocol, gcry_sexp_t privkey) {
diff --git a/otr.vs/libotr-3.2.0.vs/libotr320.vcxproj b/otr.vs/libotr-3.2.0.vs/libotr320.vcxproj
index e47c2f8..7e52fec 100644
--- a/otr.vs/libotr-3.2.0.vs/libotr320.vcxproj
+++ b/otr.vs/libotr-3.2.0.vs/libotr320.vcxproj
@@ -99,7 +99,7 @@
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ResourceCompile>