This commit is contained in:
Patrick Longa 2021-03-18 19:31:22 -07:00
Родитель 8482714790
Коммит ff61f68050
16 изменённых файлов: 798 добавлений и 205 удалений

Просмотреть файл

@ -188,6 +188,7 @@ typedef enum {
ECCRYPTO_ERROR_INVALID_PARAMETER, // 0x06
ECCRYPTO_ERROR_SHARED_KEY, // 0x07
ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, // 0x08
ECCRYPTO_ERROR_HASH_TO_CURVE, // 0x09
ECCRYPTO_ERROR_END_OF_LIST
} ECCRYPTO_STATUS;
@ -204,7 +205,8 @@ typedef enum {
#define ECCRYPTO_MSG_ERROR_NO_MEMORY "ECCRYPTO_ERROR_NO_MEMORY"
#define ECCRYPTO_MSG_ERROR_INVALID_PARAMETER "ECCRYPTO_ERROR_INVALID_PARAMETER"
#define ECCRYPTO_MSG_ERROR_SHARED_KEY "ECCRYPTO_ERROR_SHARED_KEY"
#define ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION "ECCRYPTO_ERROR_SIGNATURE_VERIFICATION"
#define ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION "ECCRYPTO_ERROR_SIGNATURE_VERIFICATION"
#define ECCRYPTO_MSG_ERROR_HASH_TO_CURVE "ECCRYPTO_ERROR_HASH_TO_CURVE"
#ifdef __cplusplus

Просмотреть файл

@ -131,6 +131,14 @@ ECCRYPTO_STATUS KeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey
ECCRYPTO_STATUS SecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret);
/**************** Public API for hashing to curve, 64-byte public keys ****************/
// Hash GF(p^2) element to a curve point
// Input: GF(p^2) element
// Output: point in affine coordinates with co-factor cleared
ECCRYPTO_STATUS HashToCurve(f2elm_t r, point_t P);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -11,6 +11,7 @@
* Preprint available at http://eprint.iacr.org/2015/565.
************************************************************************************/
#pragma once
#ifndef __FOURQ_PARAMS_H__
#define __FOURQ_PARAMS_H__
@ -30,4 +31,22 @@ static const uint64_t Montgomery_Rprime[4] = { 0xC81DB8795FF3D621, 0x173EA5AAEA6
static const uint64_t Montgomery_rprime[4] = { 0xE12FE5F079BC3929, 0xD75E78B8D1FCDCF3, 0xBCE409ED76B5DB21, 0xF32702FDAFC1C074 };
// Constants for hash to FourQ function
#if (RADIX == 32)
static felm_t con1 = { 6651107, 0, 4290264256, 2147483647 };
static felm_t con2 = { 1725590130, 1719979744, 2225079900, 707200452 };
static felm_t b0 = { 3738038324, 2664081113, 587564626, 1252475115 };
static felm_t b1 = { 17, 0, 4294967284, 2147483647 };
static felm_t A0 = { 1289, 0, 4294966384, 2147483647 };
static felm_t A1 = { 1007904792, 2866591091, 4136083791, 1668973403 };
#elif (RADIX == 64)
static felm_t con1 = { 6651107ULL, 9223372036850072768ULL };
static felm_t con2 = { 7387256751988042354ULL, 3037402815281497692ULL };
static felm_t b0 = { 11442141257964318772ULL, 5379339658566403666ULL };
static felm_t b1 = { 17ULL, 9223372036854775796ULL };
static felm_t A0 = { 1289ULL, 9223372036854774896ULL };
static felm_t A1 = { 12311914987857864728ULL, 7168186187914912079ULL };
#endif
#endif

Просмотреть файл

@ -21,7 +21,8 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Debug|Win32.ActiveCfg = Release|Win32
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Debug|Win32.ActiveCfg = Debug|Win32
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Debug|Win32.Build.0 = Debug|Win32
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Debug|x64.ActiveCfg = Debug|x64
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Debug|x64.Build.0 = Debug|x64
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Generic|Win32.ActiveCfg = Generic|Win32
@ -31,7 +32,8 @@ Global
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Release|Win32.ActiveCfg = Release|Win32
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Release|x64.ActiveCfg = Release|x64
{719F1A49-62B2-41E2-B500-40FAD83AB12A}.Release|x64.Build.0 = Release|x64
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Debug|Win32.ActiveCfg = Release|Win32
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Debug|Win32.ActiveCfg = Debug|Win32
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Debug|Win32.Build.0 = Debug|Win32
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Debug|x64.ActiveCfg = Debug|x64
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Debug|x64.Build.0 = Debug|x64
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Generic|Win32.ActiveCfg = Generic|Win32
@ -42,6 +44,7 @@ Global
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Release|x64.ActiveCfg = Release|x64
{A6DB2ADB-C570-47D5-BAAA-06904D60C091}.Release|x64.Build.0 = Release|x64
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Debug|Win32.ActiveCfg = Debug|Win32
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Debug|Win32.Build.0 = Debug|Win32
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Debug|x64.ActiveCfg = Debug|x64
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Debug|x64.Build.0 = Debug|x64
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Generic|Win32.ActiveCfg = Generic|Win32
@ -52,6 +55,7 @@ Global
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Release|x64.ActiveCfg = Release|x64
{47A9BC7F-1C7F-4BB3-B5D1-7AC7DDAC0E04}.Release|x64.Build.0 = Release|x64
{D36D493E-EFD2-4FF1-8CAE-2D16EEA76CAC}.Debug|Win32.ActiveCfg = Debug|Win32
{D36D493E-EFD2-4FF1-8CAE-2D16EEA76CAC}.Debug|Win32.Build.0 = Debug|Win32
{D36D493E-EFD2-4FF1-8CAE-2D16EEA76CAC}.Debug|x64.ActiveCfg = Debug|x64
{D36D493E-EFD2-4FF1-8CAE-2D16EEA76CAC}.Debug|x64.Build.0 = Debug|x64
{D36D493E-EFD2-4FF1-8CAE-2D16EEA76CAC}.Generic|Win32.ActiveCfg = Generic|Win32

Просмотреть файл

@ -86,7 +86,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__WINDOWS__; _X86_; _GENERIC_; USE_ENDO=true;</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -213,8 +213,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\AMD64\fp_x64.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Generic|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Generic|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\FourQ.h" />
<ClInclude Include="..\..\FourQ_api.h" />
@ -234,6 +234,7 @@
<ClCompile Include="..\..\eccp2_core.c" />
<ClCompile Include="..\..\eccp2_no_endo.c" />
<ClCompile Include="..\..\FourQ_params.h" />
<ClCompile Include="..\..\hash_to_curve.c" />
<ClCompile Include="..\..\kex.c" />
<ClCompile Include="..\..\schnorrq.c" />
</ItemGroup>

Просмотреть файл

@ -24,9 +24,6 @@
<ClInclude Include="..\..\generic\fp.h">
<Filter>Header Files\generic</Filter>
</ClInclude>
<ClInclude Include="..\..\AMD64\fp_x64.h">
<Filter>Header Files\x64</Filter>
</ClInclude>
<ClInclude Include="..\..\FourQ.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -42,6 +39,9 @@
<ClInclude Include="..\..\FourQ_api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\AMD64\fp_x64.h">
<Filter>Header Files\x64</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\eccp2.c">
@ -71,5 +71,8 @@
<ClCompile Include="..\..\..\sha512\sha512.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\hash_to_curve.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

Просмотреть файл

@ -94,7 +94,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__WINDOWS__; _X86_; _GENERIC_; USE_ENDO=true;</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

Просмотреть файл

@ -94,7 +94,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__WINDOWS__; _X86_; _GENERIC_; USE_ENDO=true;</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

Просмотреть файл

@ -95,7 +95,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__WINDOWS__; _X86_; _GENERIC_; USE_ENDO=true;</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

Просмотреть файл

@ -228,6 +228,7 @@ const char* FourQ_get_error_message(ECCRYPTO_STATUS Status)
{ECCRYPTO_ERROR_INVALID_PARAMETER, ECCRYPTO_MSG_ERROR_INVALID_PARAMETER},
{ECCRYPTO_ERROR_SHARED_KEY, ECCRYPTO_MSG_ERROR_SHARED_KEY},
{ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION},
{ECCRYPTO_ERROR_HASH_TO_CURVE, ECCRYPTO_MSG_ERROR_HASH_TO_CURVE},
};
if (Status >= ECCRYPTO_STATUS_TYPE_SIZE || mapping[Status].string == NULL) {

Просмотреть файл

@ -0,0 +1,237 @@
/**********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: hash to FourQ
***********************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
static digit_t fpeq1271(digit_t* a, digit_t* b)
{ // Constant-time comparison of two field elements, ai=bi? : (0) equal, (-1) unequal
digit_t c = 0;
for (unsigned int i = 0; i < NWORDS_FIELD; i++)
c |= a[i] ^ b[i];
return (digit_t)((-(sdigit_t)(c >> 1) | -(sdigit_t)(c & 1)) >> (8*sizeof(digit_t) - 1));
}
static void fpselect(digit_t* a, digit_t* b, digit_t* c, digit_t selector)
{ // Constant-time selection of field elements
// If selector = 0 do c <- a, else if selector =-1 do c <- b
for (unsigned int i = 0; i < NWORDS_FIELD; i++)
c[i] = (selector & (a[i] ^ b[i])) ^ a[i];
}
ECCRYPTO_STATUS HashToCurve(f2elm_t r, point_t out)
{
digit_t *r0 = (digit_t*)r[0], *r1 = (digit_t*)r[1];
felm_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16;
felm_t one = {0};
one[0] = 1;
digit_t* x0 = (digit_t*)out->x[0];
digit_t* x1 = (digit_t*)out->x[1];
digit_t* y0 = (digit_t*)out->y[0];
digit_t* y1 = (digit_t*)out->y[1];
digit_t selector;
fpadd1271(r0, r1, t0);
fpsub1271(r0, r1, t1);
fpmul1271(t0, t1, t0);
fpmul1271(r0, r1, t1);
fpadd1271(t1, t1, t1);
fpadd1271(t1, t1, t2);
fpadd1271(t0, t2, t2);
fpadd1271(t0, t0, t0);
fpsub1271(t0, t1, t3);
fpadd1271(t3, one, t0);
fpmul1271(A0, t0, t4);
fpmul1271(A1, t2, t1);
fpsub1271(t1, t4, t4);
fpmul1271(A1, t0, t5);
fpmul1271(A0, t2, t1);
fpadd1271(t1, t5, t1);
fpadd1271(t0, t2, t5);
fpsub1271(t0, t2, t6);
fpmul1271(t5, t6, t6);
fpmul1271(t2, t0, t5);
fpadd1271(t5, t5, t5);
fpmul1271(con1, t3, t7);
fpsub1271(t6, t7, t8);
fpmul1271(con2, t2, t7);
fpadd1271(t7, t8, t8);
fpmul1271(con1, t2, t7);
fpsub1271(t5, t7, t9);
fpmul1271(con2, t3, t7);
fpsub1271(t9, t7, t9);
fpmul1271(t4, t8, t5);
fpmul1271(t1, t9, t7);
fpadd1271(t5, t7, t7);
fpmul1271(t4, t9, t5);
fpmul1271(t1, t8, t10);
fpsub1271(t5, t10, t10);
fpsqr1271(t7, t5);
fpsqr1271(t10, t7);
fpadd1271(t5, t7, t5);
fpexp1251(t5, t7);
fpsqr1271(t7, t7);
fpmul1271(t5, t7, t7);
fpcopy1271(A0, t8);
fpcopy1271(A1, t9);
fpneg1271(t8);
fpneg1271(t9);
fpadd1271(A0, t4, t5);
fpsub1271(A1, t1, t11);
selector = fpeq1271(t7, one);
fpselect(t8, t5, t3, selector);
fpselect(t9, t11, t10, selector);
fpmul1271(t0, t3, t5);
fpmul1271(t2, t10, t8);
fpsub1271(t5, t8, t8);
fpmul1271(t2, t3, t5);
fpmul1271(t0, t10, t9);
fpadd1271(t5, t9, t9);
fpadd1271(t3, t10, t5);
fpsub1271(t3, t10, t11);
fpmul1271(t5, t11, t5);
fpmul1271(t3, t10, t11);
fpadd1271(t11, t11, t11);
fpmul1271(t3, t4, t12);
fpmul1271(t1, t10, t13);
fpadd1271(t12, t13, t13);
fpmul1271(t4, t10, t14);
fpmul1271(t1, t3, t12);
fpsub1271(t14, t12, t12);
fpsub1271(t5, t13, t5);
fpsub1271(t11, t12, t11);
fpadd1271(t5, t6, t5);
fpmul1271(t0, t2, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t11, t6, t11);
fpmul1271(t5, t8, t6);
fpmul1271(t9, t11, t12);
fpsub1271(t6, t12, t6);
fpmul1271(t5, t9, t12);
fpmul1271(t8, t11, t8);
fpadd1271(t12, t8, t12);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t0, t3, t14);
fpadd1271(t14, t14, t14);
fpadd1271(t2, t10, t8);
fpadd1271(t8, t8, t8);
fpmul1271(t6, t14, t4);
fpmul1271(t8, t12, t1);
fpsub1271(t4, t1, t4);
fpmul1271(t12, t14, t9);
fpmul1271(t6, t8, t1);
fpadd1271(t1, t9, t1);
fpsqr1271(t12, t5);
fpsqr1271(t6, t9);
fpadd1271(t5, t9, t9);
fpsqr1271(t1, t5);
fpsqr1271(t4, t11);
fpadd1271(t11, t5, t11);
fpsqr1271(t11, t5);
fpmul1271(t5, t9, t5);
fpexp1251(t5, t7);
fpsqr1271(t7, t13);
fpsqr1271(t13, t13);
fpmul1271(t11, t13, t13);
fpmul1271(t9, t13, t13);
fpmul1271(t5, t13, t13);
fpmul1271(t13, t7, t7);
fpmul1271(t5, t7, t7);
fpadd1271(t6, t7, t5);
fpdiv1271(t5);
fpexp1251(t5, t9);
fpsqr1271(t9, t11);
fpsqr1271(t11, t11);
fpmul1271(t5, t11, t11);
fpmul1271(t5, t9, t9);
fpmul1271(t11, t12, t11);
fpsqr1271(t9, t7);
fpadd1271(one, one, t15);
fpcopy1271(t11, t16);
fpcopy1271(t15, x0);
fpneg1271(x0);
selector = fpeq1271(t5, t7);
fpselect(t15, t16, t7, selector);
fpselect(t16, x0, t11, selector);
fpadd1271(t13, t13, t13);
fpsub1271(t3, t0, y0);
fpsub1271(t10, t2, y1);
fpmul1271(y0, t6, t16);
fpmul1271(y1, t12, t15);
fpsub1271(t16, t15, t15);
fpmul1271(y0, t12, y0);
fpmul1271(t6, y1, t16);
fpadd1271(t16, y0, t16);
fpmul1271(t15, t4, x0);
fpmul1271(t1, t16, y0);
fpadd1271(x0, y0, y0);
fpmul1271(t4, t16, y1);
fpmul1271(t1, t15, x0);
fpsub1271(y1, x0, y1);
fpmul1271(y0, t13, y0);
fpmul1271(y1, t13, y1);
fpmul1271(b0, t3, t15);
fpmul1271(b1, t10, x0);
fpsub1271(t15, x0, t15);
fpmul1271(b0, t10, t16);
fpmul1271(b1, t3, x0);
fpadd1271(t16, x0, t16);
fpmul1271(t15, t4, t5);
fpmul1271(t1, t16, x0);
fpadd1271(x0, t5, x0);
fpmul1271(t4, t16, x1);
fpmul1271(t1, t15, t5);
fpsub1271(x1, t5, x1);
fpmul1271(x0, t0, t5);
fpmul1271(x1, t2, t15);
fpsub1271(t5, t15, t15);
fpmul1271(x1, t0, t5);
fpmul1271(x0, t2, t16);
fpadd1271(t5, t16, t16);
fpmul1271(t15, t14, t5);
fpmul1271(t16, t8, x0);
fpsub1271(t5, x0, x0);
fpmul1271(t15, t8, t5);
fpmul1271(t16, t14, x1);
fpadd1271(x1, t5, x1);
fpmul1271(x0, t7, t5);
fpmul1271(x1, t11, t15);
fpsub1271(t5, t15, t15);
fpmul1271(t7, x1, t5);
fpmul1271(t11, x0, t16);
fpadd1271(t16, t5, t16);
fpmul1271(t13, t9, t13);
fpmul1271(t15, t13, x0);
fpmul1271(t16, t13, x1);
// Clear cofactor
point_extproj_t P;
point_setup(out, P);
cofactor_clearing(P);
eccnorm(P, out);
return ECCRYPTO_SUCCESS;
}

Просмотреть файл

@ -107,7 +107,7 @@ else
ASM_OBJECTS=fp2_1271.o
endif
endif
OBJECTS=eccp2.o eccp2_no_endo.o eccp2_core.o $(ASM_OBJECTS) crypto_util.o schnorrq.o kex.o sha512.o random.o
OBJECTS=eccp2.o eccp2_no_endo.o eccp2_core.o $(ASM_OBJECTS) crypto_util.o schnorrq.o hash_to_curve.o kex.o sha512.o random.o
OBJECTS_FP_TEST=fp_tests.o $(OBJECTS) test_extras.o
OBJECTS_ECC_TEST=ecc_tests.o $(OBJECTS) test_extras.o
OBJECTS_CRYPTO_TEST=crypto_tests.o $(OBJECTS) test_extras.o
@ -154,6 +154,9 @@ endif
schnorrq.o: schnorrq.c
$(CC) $(CFLAGS) schnorrq.c
hash_to_curve.o: hash_to_curve.c
$(CC) $(CFLAGS) hash_to_curve.c
kex.o: kex.c
$(CC) $(CFLAGS) kex.c
@ -181,5 +184,5 @@ fp_tests.o: tests/fp_tests.c
.PHONY: clean
clean:
rm -f $(SHARED_LIB_TARGET) crypto_test ecc_test fp_test fp2_1271.o fp2_1271_AVX2.o AMD64/consts.s consts.o $(OBJECTS_ALL)
rm -rf $(SHARED_LIB_TARGET) crypto_test ecc_test fp_test *.o AMD64/consts.s

Просмотреть файл

@ -8,6 +8,8 @@
#include "../FourQ_api.h"
#include "../FourQ_params.h"
#include "../../random/random.h"
#include "../../sha512/sha512.h"
#include "test_extras.h"
#include <stdio.h>
@ -139,198 +141,273 @@ ECCRYPTO_STATUS SchnorrQ_run()
ECCRYPTO_STATUS compressedkex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[32], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[32], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using compressed, 32-byte public keys: \n\n");
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using compressed, 32-byte public keys: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = CompressedKeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = CompressedKeyGeneration(SecretKeyB, PublicKeyB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = CompressedKeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = CompressedKeyGeneration(SecretKeyB, PublicKeyB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = CompressedSecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = CompressedSecretAgreement(SecretKeyB, PublicKeyA, SecretAgreementB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = CompressedSecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = CompressedSecretAgreement(SecretKeyB, PublicKeyA, SecretAgreementB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
return Status;
return Status;
}
ECCRYPTO_STATUS compressedkex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned long long cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[32], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
int n;
unsigned long long cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[32], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using compressed, 32-byte public keys: \n\n");
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using compressed, 32-byte public keys: \n\n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedKeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Keypair generation runs in ...................................................... %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
Status = CompressedKeyGeneration(SecretKeyB, PublicKeyB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedSecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Secret agreement runs in ........................................................ %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedKeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Keypair generation runs in ...................................................... %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
Status = CompressedKeyGeneration(SecretKeyB, PublicKeyB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedSecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Secret agreement runs in ........................................................ %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
return Status;
return Status;
}
ECCRYPTO_STATUS kex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using uncompressed, 64-byte public keys: \n\n");
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using uncompressed, 64-byte public keys: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = KeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = KeyGeneration(SecretKeyB, PublicKeyB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = KeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = KeyGeneration(SecretKeyB, PublicKeyB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = SecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = SecretAgreement(SecretKeyB, PublicKeyA, SecretAgreementB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = SecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = SecretAgreement(SecretKeyB, PublicKeyA, SecretAgreementB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
return Status;
return Status;
}
ECCRYPTO_STATUS kex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned long long cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
int n;
unsigned long long cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using uncompressed, 64-byte public keys: \n\n");
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using uncompressed, 64-byte public keys: \n\n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = KeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Keypair generation runs in ...................................................... %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = KeyGeneration(SecretKeyA, PublicKeyA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Keypair generation runs in ...................................................... %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
Status = KeyGeneration(SecretKeyB, PublicKeyB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Secret agreement runs in ........................................................ %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
Status = KeyGeneration(SecretKeyB, PublicKeyB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SecretAgreement(SecretKeyA, PublicKeyB, SecretAgreementA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Secret agreement runs in ........................................................ %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
return Status;
return Status;
}
ECCRYPTO_STATUS hash2curve_test()
{ // Test hashing to FourQ
int n, passed;
point_t P, Q;
point_extproj_t R;
unsigned char Value[32], HashedValue[64];
f2elm_t* f2elmt = (f2elm_t*)&HashedValue[0];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing hashing to FourQ: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
RandomBytesFunction(Value, 32);
CryptoHashFunction(Value, 32, HashedValue);
mod1271(((felm_t*)f2elmt)[0]);
mod1271(((felm_t*)f2elmt)[1]);
// Hash GF(p^2) element to curve
Status = HashToCurve((felm_t*)f2elmt, P);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
hash2curve_unsafe((felm_t*)f2elmt, Q); // Non-constant-time version for testing
if (fp2compare64((uint64_t*)P->x,(uint64_t*)Q->x)!=0 || fp2compare64((uint64_t*)P->y,(uint64_t*)Q->y)!=0) { passed=0; break; }
// Check if point is on the curve
point_setup(P, R);
if (!ecc_point_validate(R)) { passed=0; break; }
}
if (passed==1) printf(" Hash to FourQ tests.............................................................. PASSED");
else { printf(" Hash to FourQ tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_HASH_TO_CURVE; }
printf("\n");
return Status;
}
ECCRYPTO_STATUS hash2curve_run()
{ // Benchmark hashing to FourQ
int n;
unsigned long long cycles, cycles1, cycles2;
point_t P;
unsigned char Value[32], HashedValue[64];
f2elm_t* f2elmt = (f2elm_t*)&HashedValue[0];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking hashing to FourQ: \n\n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
RandomBytesFunction(Value, 32);
CryptoHashFunction(Value, 32, HashedValue);
mod1271(((felm_t*)f2elmt)[0]);
mod1271(((felm_t*)f2elmt)[1]);
cycles1 = cpucycles();
Status = HashToCurve((felm_t*)f2elmt, P);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
printf(" Hashing to FourQ runs in ....................................................... %8lld ", cycles/BENCH_LOOPS); print_unit;
printf("\n");
return Status;
}
int main()
{
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
Status = SchnorrQ_test(); // Test SchnorrQ signature scheme
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
@ -342,27 +419,38 @@ int main()
return false;
}
Status = compressedkex_test(); // Test Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = compressedkex_run(); // Benchmark Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = compressedkex_test(); // Test Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = compressedkex_run(); // Benchmark Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_test(); // Test Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_run(); // Benchmark Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_test(); // Test Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_run(); // Benchmark Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = hash2curve_test(); // Test hash to FourQ function
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = hash2curve_run(); // Benchmark hash to FourQ function
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
return true;
}

Просмотреть файл

@ -70,28 +70,28 @@ void random_scalar_test(uint64_t* a)
void fp2random1271_test(f2elm_t a)
{ // Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
digit_t mask_7fff = (digit_t)-1 >> 1;
digit_t mask_7fff = (digit_t)-1 >> 1;
random_scalar_test((uint64_t*)&a[0]);
a[0][NWORDS_FIELD - 1] &= mask_7fff;
a[1][NWORDS_FIELD - 1] &= mask_7fff;
random_scalar_test((uint64_t*)&a[0]);
a[0][NWORDS_FIELD - 1] &= mask_7fff;
a[1][NWORDS_FIELD - 1] &= mask_7fff;
}
void random_order_test(digit_t* a)
{ // Generating a pseudo-random element in [0, order-1]
// SECURITY NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
int i;
unsigned char* string = (unsigned char*)a;
int i;
unsigned char* string = (unsigned char*)a;
for (i = 0; i < 31; i++) {
string[i] = (unsigned char)rand(); // Obtain 246-bit number
}
string[30] &= 0x3F;
string[31] = 0;
subtract_mod_order(a, (digit_t*)&curve_order, a);
for (i = 0; i < 31; i++) {
string[i] = (unsigned char)rand(); // Obtain 246-bit number
}
string[30] &= 0x3F;
string[31] = 0;
subtract_mod_order(a, (digit_t*)&curve_order, a);
return;
return;
}
@ -169,3 +169,221 @@ bool verify_mLSB_recoding(uint64_t* scalar, int* digits)
return true;
}
static inline bool fpeq1271_unsafe(felm_t in1, felm_t in2)
{
return memcmp(in1, in2, sizeof(felm_t)) == 0;
}
void hash2curve_unsafe(f2elm_t r, point_t out)
{ // (Unsafe, non-constant-time version of) hash to curve function for testing
digit_t *r0 = (digit_t*)r[0], *r1 = (digit_t*)r[1];
felm_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18;
felm_t one = {0};
one[0] = 1;
digit_t* x0 = (digit_t*)out->x[0];
digit_t* x1 = (digit_t*)out->x[1];
digit_t* y0 = (digit_t*)out->y[0];
digit_t* y1 = (digit_t*)out->y[1];
fpadd1271(r0, r1, t0);
fpsub1271(r0, r1, t1);
fpmul1271(t0, t1, t0);
fpmul1271(r0, r1, t1);
fpadd1271(t1, t1, t1);
fpadd1271(t1, t1, t2);
fpadd1271(t0, t2, t2);
fpadd1271(t0, t0, t0);
fpsub1271(t0, t1, t3);
fpadd1271(t3, one, t0);
fpmul1271(A0, t0, t4);
fpmul1271(A1, t2, t1);
fpsub1271(t1, t4, t4);
fpmul1271(A1, t0, t5);
fpmul1271(A0, t2, t1);
fpadd1271(t1, t5, t1);
fpadd1271(t0, t2, t5);
fpsub1271(t0, t2, t6);
fpmul1271(t5, t6, t6);
fpmul1271(t2, t0, t5);
fpadd1271(t5, t5, t5);
fpmul1271(con1, t3, t7);
fpsub1271(t6, t7, t8);
fpmul1271(con2, t2, t7);
fpadd1271(t7, t8, t8);
fpmul1271(con1, t2, t7);
fpsub1271(t5, t7, t9);
fpmul1271(con2, t3, t7);
fpsub1271(t9, t7, t9);
fpmul1271(t4, t8, t5);
fpmul1271(t1, t9, t7);
fpadd1271(t5, t7, t7);
fpmul1271(t4, t9, t5);
fpmul1271(t1, t8, t10);
fpsub1271(t5, t10, t10);
fpsqr1271(t7, t5);
fpsqr1271(t10, t7);
fpadd1271(t5, t7, t5);
fpexp1251(t5, t7);
fpsqr1271(t7, t7);
fpmul1271(t5, t7, t7);
fpcopy1271(A0, t8);
fpcopy1271(A1, t9);
fpneg1271(t8);
fpneg1271(t9);
fpadd1271(A0, t4, t5);
fpsub1271(A1, t1, t11);
if (fpeq1271_unsafe(t7, one)) {
fpcopy1271(t8, t3);
fpcopy1271(t9, t10);
} else {
fpcopy1271(t5, t3);
fpcopy1271(t11, t10);
}
fpmul1271(t0, t3, t5);
fpmul1271(t2, t10, t8);
fpsub1271(t5, t8, t8);
fpmul1271(t2, t3, t5);
fpmul1271(t0, t10, t9);
fpadd1271(t5, t9, t9);
fpadd1271(t3, t10, t5);
fpsub1271(t3, t10, t11);
fpmul1271(t5, t11, t5);
fpmul1271(t3, t10, t11);
fpadd1271(t11, t11, t11);
fpmul1271(t3, t4, t12);
fpmul1271(t1, t10, t13);
fpadd1271(t12, t13, t13);
fpmul1271(t4, t10, t14);
fpmul1271(t1, t3, t12);
fpsub1271(t14, t12, t12);
fpsub1271(t5, t13, t5);
fpsub1271(t11, t12, t11);
fpadd1271(t5, t6, t5);
fpmul1271(t0, t2, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t11, t6, t11);
fpmul1271(t5, t8, t6);
fpmul1271(t9, t11, t12);
fpsub1271(t6, t12, t6);
fpmul1271(t5, t9, t12);
fpmul1271(t8, t11, t8);
fpadd1271(t12, t8, t12);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t6, t6, t6);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t12, t12, t12);
fpadd1271(t0, t3, t14);
fpadd1271(t14, t14, t14);
fpadd1271(t2, t10, t8);
fpadd1271(t8, t8, t8);
fpmul1271(t6, t14, t4);
fpmul1271(t8, t12, t1);
fpsub1271(t4, t1, t4);
fpmul1271(t12, t14, t9);
fpmul1271(t6, t8, t1);
fpadd1271(t1, t9, t1);
fpsqr1271(t12, t5);
fpsqr1271(t6, t9);
fpadd1271(t5, t9, t9);
fpsqr1271(t1, t5);
fpsqr1271(t4, t11);
fpadd1271(t11, t5, t11);
fpsqr1271(t11, t5);
fpmul1271(t5, t9, t5);
fpexp1251(t5, t7);
fpsqr1271(t7, t13);
fpsqr1271(t13, t13);
fpmul1271(t11, t13, t13);
fpmul1271(t9, t13, t13);
fpmul1271(t5, t13, t13);
fpmul1271(t13, t7, t7);
fpmul1271(t5, t7, t7);
fpadd1271(t6, t7, t5);
fpdiv1271(t5);
fpexp1251(t5, t9);
fpsqr1271(t9, t11);
fpsqr1271(t11, t11);
fpmul1271(t5, t11, t11);
fpmul1271(t5, t9, t9);
fpmul1271(t11, t12, t11);
fpsqr1271(t9, t7);
fpadd1271(one, one, t15);
fpcopy1271(t11, t16);
fpcopy1271(t15, x0);
fpneg1271(x0);
if (fpeq1271_unsafe(t5, t7)) {
fpcopy1271(t15, t17);
fpcopy1271(t16, t18);
} else {
fpcopy1271(t16, t17);
fpcopy1271(x0, t18);
}
fpadd1271(t13, t13, t13);
fpsub1271(t3, t0, y0);
fpsub1271(t10, t2, y1);
fpmul1271(y0, t6, t16);
fpmul1271(y1, t12, t15);
fpsub1271(t16, t15, t15);
fpmul1271(y0, t12, y0);
fpmul1271(t6, y1, t16);
fpadd1271(t16, y0, t16);
fpmul1271(t15, t4, x0);
fpmul1271(t1, t16, y0);
fpadd1271(x0, y0, y0);
fpmul1271(t4, t16, y1);
fpmul1271(t1, t15, x0);
fpsub1271(y1, x0, y1);
fpmul1271(y0, t13, y0);
fpmul1271(y1, t13, y1);
fpmul1271(b0, t3, t15);
fpmul1271(b1, t10, x0);
fpsub1271(t15, x0, t15);
fpmul1271(b0, t10, t16);
fpmul1271(b1, t3, x0);
fpadd1271(t16, x0, t16);
fpmul1271(t15, t4, t5);
fpmul1271(t1, t16, x0);
fpadd1271(x0, t5, x0);
fpmul1271(t4, t16, x1);
fpmul1271(t1, t15, t5);
fpsub1271(x1, t5, x1);
fpmul1271(x0, t0, t5);
fpmul1271(x1, t2, t15);
fpsub1271(t5, t15, t15);
fpmul1271(x1, t0, t5);
fpmul1271(x0, t2, t16);
fpadd1271(t5, t16, t16);
fpmul1271(t15, t14, t5);
fpmul1271(t16, t8, x0);
fpsub1271(t5, x0, x0);
fpmul1271(t15, t8, t5);
fpmul1271(t16, t14, x1);
fpadd1271(x1, t5, x1);
fpmul1271(x0, t17, t5);
fpmul1271(x1, t18, t15);
fpsub1271(t5, t15, t15);
fpmul1271(t17, x1, t5);
fpmul1271(t18, x0, t16);
fpadd1271(t16, t5, t16);
fpmul1271(t13, t9, t13);
fpmul1271(t15, t13, x0);
fpmul1271(t16, t13, x1);
// Clear cofactor
point_extproj_t P;
point_setup(out, P);
cofactor_clearing(P);
eccnorm(P, out);
}

Просмотреть файл

@ -41,6 +41,9 @@ void random_order_test(digit_t* a);
// Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
bool verify_mLSB_recoding(uint64_t* scalar, int* digits);
// (Unsafe, non-constant-time version of) hash to curve function for testing
void hash2curve_unsafe(f2elm_t r, point_t out);
#ifdef __cplusplus
}

Просмотреть файл

@ -1,4 +1,4 @@
## FourQlib v3.0 (C Edition)
## FourQlib v3.1 (C Edition)
**FourQlib** implements essential elliptic curve and cryptographic functions based on FourQ,
a high-security, high-performance elliptic curve that targets the 128-bit security level [1]. At the
@ -10,7 +10,7 @@ The library was developed by [Microsoft Research](http://research.microsoft.com/
## Contents
Version 3.0 includes the following implementations:
Version 3.1 includes the following implementations:
* [`FourQ_32bit`](FourQ_32bit/): a portable implementation especially tailored for 32-bit platforms.
* [`FourQ_64bit_and_portable`](FourQ_64bit_and_portable/): a portable implementation for 32-bit and 64-bit platforms with optional
@ -34,17 +34,23 @@ The library includes an implementation of SHA-512 which is used by default by Sc
Users can provide their own PRNG and hash implementations by replacing the functions in the [`random`](random/) and [`sha512`](sha512/)folders, and applying the corresponding changes to the settings in `FourQ.h` (in a given implementation).
Refer to [2] for the security requirements for the cryptographic hash function.
## What's new in version 3.0
## What's new
### In version 3.0
* New support for co-factor ECDH and SchnorrQ signatures.
* New implementations for 32-bit processors, 32-bit ARMv6 and ARMv7 processors, and 32-bit ARM Cortex-M4 microcontroller.
* New implementation for ARMv6/ARMv7/ARMv7-M with strong countermeasures against several side-channel attacks.
* New support for 64-bit ARMv8 processors.
### In version 3.1
* New hash to curve functionality (only supported in the portable implementation FourQ_64bit_and_portable).
## Main features
* Support for co-factor Elliptic Curve Diffie-Hellman (ECDH) key exchange [3].
* Support for the SchnorrQ digital signature scheme [2].
* Support for co-factor Elliptic Curve Diffie-Hellman (ECDH) key exchange [3], the SchnorrQ digital signature scheme [2], and
hash to curve conversion.
* Support for 3 core elliptic curve operations: variable-base, fixed-base and double-scalar multiplications.
* Support for Windows using Microsoft Visual Studio and Linux using GNU GCC or clang.
* Includes a basic implementation using portable C to enable support on a wide range of platforms including x64, x86