copied crypto project from SW03

devel_freefall
Jonas Arnold 3 years ago
parent 79b2eb6121
commit 636321568d
  1. 10
      ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln
  2. 134
      ASYD_Cryptograhpy/SW04-DSA/DSA.c
  3. 31
      ASYD_Cryptograhpy/SW04-DSA/DSA.h
  4. 141
      ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj
  5. 36
      ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj.filters
  6. 937
      ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.c
  7. 70
      ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.h
  8. 168
      ASYD_Cryptograhpy/SW04-DSA/main.c
  9. 40
      ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/README.md
  10. 26
      ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/jumper.gpr
  11. 75
      ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/src/main.adb

@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SW02-XTEA-CBC", "SW02-XTEA-
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SW03-DHKE", "SW03-DHKE\SW03-DHKE.vcxproj", "{AF52BEB7-E554-45CF-BA24-0822CF851BEE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SW04-DSA", "SW04-DSA\SW04-DSA.vcxproj", "{737511B3-89A4-41CD-A680-EE8CC74C60FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -41,6 +43,14 @@ Global
{AF52BEB7-E554-45CF-BA24-0822CF851BEE}.Release|x64.Build.0 = Release|x64
{AF52BEB7-E554-45CF-BA24-0822CF851BEE}.Release|x86.ActiveCfg = Release|Win32
{AF52BEB7-E554-45CF-BA24-0822CF851BEE}.Release|x86.Build.0 = Release|Win32
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Debug|x64.ActiveCfg = Debug|x64
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Debug|x64.Build.0 = Debug|x64
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Debug|x86.ActiveCfg = Debug|Win32
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Debug|x86.Build.0 = Debug|Win32
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Release|x64.ActiveCfg = Release|x64
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Release|x64.Build.0 = Release|x64
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Release|x86.ActiveCfg = Release|Win32
{737511B3-89A4-41CD-A680-EE8CC74C60FA}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -0,0 +1,134 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief model solution for ASYD assignment crypto 04
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 03.02.23
*
*--------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "DSA.h"
#include "encryptionArithmetic.h"
/* https://de.wikipedia.org/wiki/Digital_Signature_Algorithm#Parameter_erzeugen */
/* based on the square and multiply algorithm */
/* https://www.biancahoegel.de/mathe/zahl/primitivwurzel.html */
/* https://www.practicalnetworking.net/stand-alone/square-and-multiply/ */
/* https://math.stackexchange.com/questions/1472480/learning-square-and-multiply-algorithm */
void moduloOperation(t_encryptionArithmetic* result, t_encryptionArithmetic* modulo, uint32_t keyLength);
void squareAndMultiply(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* modulo, t_encryptionArithmetic* result, uint32_t keyLength) {
/* assign base to result as the first step defined in the square & multply algorithm */
for (uint8_t i = 0; i < (keyLength / 32); i++) {
*(result->number + i) = *(base->number + i);
}
/* get amount of bits representing the exponent */
uint16_t numberOfBits = encryptionArithmetic_numberSize(exponent->number, keyLength);
/* execute square and multiply algorithm */
for (int i = 0; i < numberOfBits - 1; i++) {
/* -2 as we already did store the base inside our number and therefore skip the MSB */
if (*(exponent->number) >> (numberOfBits - i - 2) & 1) /* if bit is 1 => multiply number with itself as well as with base */
{
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
encryptionArithmetic(result->number, base->number, result, keyLength, MUL); /* multiply */
}
else /* if bit is 0 => multiply number with itself */
{
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
}
moduloOperation(result, modulo, keyLength);
}
printf("Square and Multiply result: %u\n", *result->number);
}
void moduloOperation(t_encryptionArithmetic* number, t_encryptionArithmetic* moduloValue, uint32_t keyLength) {
/* number % moduloValue */
/* https://www.geeksforgeeks.org/program-to-find-remainder-without-using-modulo-or-operator/ */
/* allocate memory */
t_encryptionArithmetic mulRes, divRes;
encryptionArithmetic_Init(&mulRes, keyLength);
encryptionArithmetic_Init(&divRes, keyLength);
/* perform modulo operation */
encryptionArithmetic(number->number, moduloValue->number, &divRes, keyLength, DIV);
encryptionArithmetic(moduloValue->number, divRes.number, &mulRes, keyLength, MUL);
encryptionArithmetic(number->number, mulRes.number, number, keyLength, SUB);
/* free memory */
encryptionArithmetic_DeInit(&mulRes);
encryptionArithmetic_DeInit(&divRes);
}
void modInverse(t_encryptionArithmetic* number, t_encryptionArithmetic* modValue, t_encryptionArithmetic* result, uint32_t keyLength) {
/* https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/ */
/* allocate memory */
t_encryptionArithmetic modRes1, modRes2, mulRes, counter, one;
encryptionArithmetic_Init(&modRes1, keyLength);
encryptionArithmetic_Init(&modRes2, keyLength);
encryptionArithmetic_Init(&mulRes, keyLength);
encryptionArithmetic_Init(&counter, keyLength);
encryptionArithmetic_Init(&one, keyLength);
*counter.number = 1;
*one.number = 1;
for (*counter.number; !encryptionArithmetic_isLarger(counter.number, modValue->number, keyLength); encryptionArithmetic(counter.number, one.number, &counter, keyLength, ADD)) {
/* number % modValue */
encryptionArithmetic_copyNumber(number->number, modRes1.number, keyLength);
moduloOperation(&modRes1, modValue, keyLength);
/* counter % modValue */
encryptionArithmetic_copyNumber(counter.number, modRes2.number, keyLength);
moduloOperation(&modRes2, modValue, keyLength);
/* modRes1 * modRes2 */
encryptionArithmetic(modRes1.number, modRes2.number, &mulRes, keyLength, MUL);
/* mulRes % modValue */
moduloOperation(&mulRes, modValue, keyLength);
if (*(mulRes.number) == 1) {
encryptionArithmetic_copyNumber(counter.number, result->number, keyLength);
}
}
encryptionArithmetic_DeInit(&modRes1);
encryptionArithmetic_DeInit(&modRes2);
encryptionArithmetic_DeInit(&mulRes);
encryptionArithmetic_DeInit(&counter);
}
void square(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* result, uint32_t keyLength) {
/* assign base to result as the first step defined in the square & multply algorithm */
for (uint8_t i = 0; i < (keyLength / 32); i++) {
*(result->number + i) = *(base->number + i);
}
/* get amount of bits representing the exponent */
uint16_t numberOfBits = encryptionArithmetic_numberSize(exponent->number, keyLength);
/* execute square and multiply algorithm */
for (int i = 0; i < numberOfBits - 1; i++) {
/* -2 as we already did store the base inside our number and therefore skip the MSB */
if (*(exponent->number) >> (numberOfBits - i - 2) & 1) /* if bit is 1 => multiply number with itself as well as with base */
{
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
encryptionArithmetic(result->number, base->number, result, keyLength, MUL); /* multiply */
}
else /* if bit is 0 => multiply number with itself */
{
encryptionArithmetic(result->number, result->number, result, keyLength, MUL); /* square */
}
}
}

@ -0,0 +1,31 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief model solution for ASYD assignment crypto 04
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 03.02.23
*
*--------------------------------------------------------------------
*/
#ifndef DSA_H_
#define DSA_H_
#define _CRT_SECURE_NO_WARININGS
#include <stdint.h>
#include <stdio.h>
#include "DSA.h"
#include "encryptionArithmetic.h"
void squareAndMultiply(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* modulo, t_encryptionArithmetic* result, uint32_t keyLength);
void square(t_encryptionArithmetic* base, t_encryptionArithmetic* exponent, t_encryptionArithmetic* result, uint32_t keyLength);
void moduloOperation(t_encryptionArithmetic* number, t_encryptionArithmetic* moduloValue, uint32_t keyLength);
void modInverse(t_encryptionArithmetic* number, t_encryptionArithmetic* modValue, t_encryptionArithmetic* result, uint32_t keyLength);
#endif // !RSA_H_

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="DSA.h" />
<ClInclude Include="encryptionArithmetic.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="DSA.c" />
<ClCompile Include="encryptionArithmetic.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{737511b3-89a4-41cd-a680-ee8cc74c60fa}</ProjectGuid>
<RootNamespace>SW04DSA</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

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

@ -0,0 +1,937 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief n size number computation - ASYD
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 17.05.2022
*
*--------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> /* calloc, malloc, free, etc. */
#include <stdbool.h>
#include <string.h>
#include "encryptionArithmetic.h"
/* link two numbers via a mathematical addition */
t_encryptionArithmetic* encryptionArithmetic_ADD(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical subtraction */
t_encryptionArithmetic* encryptionArithmetic_SUB(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical division */
t_encryptionArithmetic* encryptionArithmetic_DIV(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via a mathematical multiplication */
t_encryptionArithmetic* encryptionArithmetic_MUL(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical AND */
t_encryptionArithmetic* encryptionArithmetic_AND(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical OR */
t_encryptionArithmetic* encryptionArithmetic_OR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* link two numbers via logical XOR */
t_encryptionArithmetic* encryptionArithmetic_XOR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size);
/* shift number by amount to the left */
void encryptionArithmetic_LSL(uint32_t* number, uint8_t amount, uint16_t size);
/* empty an existing number of its content */
void encryptionArithmetic_clearNumber(uint32_t* number, uint16_t size);
/**
* Computes the computed result of two numbers while specifying the operation with an OPCODE
*
* Usage:
* Arrays with uint32_t sized entries (number1 and number2) hold the wanted values which get computed bitwise
* from LSB to MSB starting at index 0. Data gets stored as "little Endian".
* array[0] = [X X X X X X X X X]
* MSB LSB
*
* Example:
* uint32_t Number1[10] = { Number };
* uint32_t Number2[10] = { Number };
* t_encryptionArithmetic *result, number;
* result = &number;
* encryptionArithmetic_Init(result, size);
* encryptionArithmetic(Number1, Number2, result, size, ADD);
* encryptionArithmetic_DeInit(result->number);
*
* @param [in] number1
* pointer to the memory location of the first number (stored in 32bit-chunks)
* @param [in] number2
* pointer to the memory location of the second number (stored in 32bit-chunks)
* @param [in] result
* pointer to the memory location of the address which holds the computed number afterwards
* @param [in] size
* Size is in bits
* @param [in] OPCODE
* defines the desired operation that gets computed
* Available operand: ADD, SUB, DIV, MUL, AND, OR, XOR
* @return
* pointer to the memory address of the struct
*/
/* Important: The library takes massively advantage of pointers and memory allocation
* Even though there has been done a lot of testing in regard to memory & buffer overflows
* they might still happen if you aren't careful. You should rather allocate too much memory than
* too little and risk the corruption of data outside your desired working area.
*/
//03.02: deinit-counter added
uint16_t deinitCounter = 0;
t_encryptionArithmetic* encryptionArithmetic(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size, t_operation OPCODE)
{
switch (OPCODE)
{
case ADD: return encryptionArithmetic_ADD(&(*number1), &(*number2), &(*result), size); break;
case SUB: return encryptionArithmetic_SUB(&(*number1), &(*number2), &(*result), size); break;
case DIV: return encryptionArithmetic_DIV(&(*number1), &(*number2), &(*result), size); break;
case MUL: return encryptionArithmetic_MUL(&(*number1), &(*number2), &(*result), size); break;
case AND: return encryptionArithmetic_AND(&(*number1), &(*number2), &(*result), size); break;
case OR: return encryptionArithmetic_OR(&(*number1), &(*number2), &(*result), size); break;
case XOR: return encryptionArithmetic_XOR(&(*number1), &(*number2), &(*result), size); break;
default: printf("OPCODE not recognized. Please select an available one\n"); return 0; break;
}
}
t_encryptionArithmetic* encryptionArithmetic_AND(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 & lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_XOR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 ^ lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_OR(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
uint32_t lsl1;
uint32_t lsl2;
uint32_t lsr1;
uint32_t lsr2;
for (uint16_t j = 0; j < size / 32; j++)
{
for (uint8_t i = 0; i < 32; i++)
{
lsl1 = (*(number1 + imm)) << (31 - i);
lsl2 = (*(number2 + imm)) << (31 - i);
lsr1 = lsl1 >> (31);
lsr2 = lsl2 >> (31);
if (lsr1 | lsr2)
{
*(result->number + imm) |= 1 << i;
}
}
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_ADD(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size)
{
uint8_t imm = 0;
/* allocate memory */
result->remainder = 0;
if (result->memAllocSuccess == false) {
result->number = (uint32_t*)calloc(size / 32 + 1, sizeof(uint32_t));
}
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
/* Add the first 32 bits together while omitting the carry bit */
*(result->number + imm) = *(number1 + imm) + *(number2 + imm);
imm++;
for (uint16_t j = 1; j < size / 32 + 1; j++)
{
if (*(result->number + imm - 1) < *(number1 + imm - 1)) /* check for omitted carry bit */
{
result->hasOverflown = true;
}
else
{
result->hasOverflown = false;
}
*(result->number + imm) = *(number1 + imm) + *(number2 + imm); //Adds the next 32 bit chunk of numbers together
*(result->number + imm) = *(result->number + imm) + result->hasOverflown; //checks for the presence of a carry bit and adds it to the number
imm++;
}
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_SUB(uint32_t* minuend, uint32_t* subtrahend, t_encryptionArithmetic* result, uint16_t size)
{
/* based on the 1's complement subtraction */
/* https://electricalbaba.com/1s-complement-subtraction-explained-with-examples/ */
/* https://atozmath.com/NumberSubComp.aspx */
/* allocate memory */
if (result->memAllocSuccess == false) {
result->number = (uint32_t*)calloc(size / 32 + 1, sizeof(uint32_t));
}
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
/* get actual size of the subtrahend */
uint16_t subtrahendSize = encryptionArithmetic_numberSize(subtrahend, size);
/* get actual size of the minuend */
uint16_t minuendSize = encryptionArithmetic_numberSize(minuend, size);
/* allocate memory */
/* in order to facilitate the iterative usage of the function we need to make sure
* that the result is always empty when doing the calculations. Therefore both temp-pointers are needed */
uint32_t* tempMinuend = (uint32_t*)calloc((minuendSize) / 32 + 3, sizeof(uint32_t)); /* + 2 to handle the possible overflow */ //02.02: size -> minuendSize //03.02: 32 + 2 -> 32 + 3
uint32_t* tempSubtrahend = (uint32_t*)calloc((subtrahendSize) / 32 + 3, sizeof(uint32_t)); /* + 2 to handle the possible overflow */ //02.02: size -> subtrahendSize
if (tempMinuend == NULL || tempSubtrahend == NULL)
{
if (tempMinuend != NULL) {
free(tempMinuend);
}
if (tempSubtrahend != NULL) {
free(tempSubtrahend);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMinuend, minuend, (minuendSize <= 4) ? (1) : (minuendSize / 8) + 1); /* size / 8 + 1 = number of bytes including error for int calulation */
memmove(tempSubtrahend, subtrahend, (subtrahendSize <= 4) ? (1) : (subtrahendSize / 8) + 1);/* size / 8 + 1 = number of bytes including error for int calulation */
result->memAllocSuccess = true;
/* there is no sense in generating the 1's complement if we substract 0 from another number */
if (!subtrahendSize || !minuendSize) {
if (!subtrahendSize) {
/* copy number from minuend into result */
for (uint8_t imm = 0; imm < (minuendSize / 32 + 1); imm++) { //02.02: (size / 32) -> (minuendSize / 32 + 1)
*(result->number + imm) = *(tempMinuend + imm);
}
}
else {
/* copy number from subtrahend into result */
for (uint8_t imm = 0; imm < (subtrahendSize / 32 + 1); imm++) { //02.02: (size / 32) -> (subtrahendSize / 32 + 1)
*(result->number + imm) = *(tempSubtrahend + imm);
}
}
free(tempMinuend);
free(tempSubtrahend);
result->compSuccess = true;
return result;
}
/* generate the 1's complement out of the subtrahend */
uint8_t cnt = 0;
for (uint8_t i = 0; i < (subtrahendSize / 32) + 1; i++) { /* +1 to circumvent division by 0 */
*(tempSubtrahend + i) = ~(*(subtrahend + i));
cnt++;
}
/* clear any false set bit that occurs during 1's complement generation */
if (subtrahendSize == 32 * (cnt - 1)) {
*(tempSubtrahend + cnt - 1) = 0;
}
else if (subtrahendSize >= 32) {
*(tempSubtrahend + cnt - 1) = *(tempSubtrahend + cnt - 1) & (0xFFFFFFFF >> ((32 * cnt) - subtrahendSize));
}
else {
*(tempSubtrahend + cnt - 1) = *(tempSubtrahend + cnt - 1) & (0xFFFFFFFF >> (32 - subtrahendSize));
}
/* Add the first 32 bits together while omitting the carry bit */
encryptionArithmetic_clearNumber(result->number, size);
*(result->number) = *(tempMinuend) + *(tempSubtrahend);
uint8_t imm = 1;
for (uint16_t j = 1; j < minuendSize / 32 + 1; j++) // 02.02: +1 -> +2 | size -> minuendSize
{
if (*(result->number + imm - 1) < *(tempMinuend + imm - 1)) /* check for omitted carry bit */
{
result->hasOverflown = true;
}
else
{
result->hasOverflown = false;
}
*(result->number + imm) = *(tempMinuend + imm) + *(tempSubtrahend + imm); /* Adds the next 32 bit chunk of numbers together */
*(result->number + imm) = *(result->number + imm) + result->hasOverflown; /* checks for the presence of a carry bit and adds it to the number */
imm++;
}
/* get actual size of the number to catch overflows */
uint16_t numberSize = encryptionArithmetic_numberSize(result->number, size);
if (numberSize > minuendSize || numberSize > subtrahendSize) {
result->hasOverflown = true;
}
else {
result->hasOverflown = false;
}
/* if an overflow has occured (= result is positive), we need to add that bit to the LSB while omitting it as the MSB */
if (result->hasOverflown)
{
/* can't simply be a single uint32_t variable, as there would be out of boundary memory access through the ADD function */
uint32_t* carry = (uint32_t*)calloc((numberSize) / 32 + 2, sizeof(uint32_t)); //02.02: size -> numberSize
uint32_t* cache = (uint32_t*)calloc((numberSize) / 32 + 2, sizeof(uint32_t)); //02.02: size -> numberSize
if (cache == NULL || carry == NULL)
{
if (cache != NULL) {
free(cache);
}
if (carry != NULL) {
free(carry);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
*carry = 1;
result->memAllocSuccess = true;
for (int i = 0; i < (numberSize / 32) + 1; i++)
{
*(cache + i) = *(result->number + i);
}
/* remove overflow-MSB */
if (numberSize <= 32)
{
*(cache) ^= 1 << (numberSize - 1);
}
else
{
if (!(numberSize % 32)) /* numberSize is a multiple of 32 */
{
*(cache + (numberSize / 32) - 1) ^= 1 << 31;
}
else
{
*(cache + (numberSize / 32)) ^= 1 << (numberSize - 1 - ((numberSize / 32) * 32));
}
}
encryptionArithmetic_clearNumber(result->number, size);
encryptionArithmetic_ADD(&(*cache), &(*carry), &(*result), size);
free(cache);
free(carry);
}
else {
/* generate the 1's complement out of the result as it is negative */
cnt = 0;
for (uint8_t i = 0; i < (numberSize / 32) + 1; i++)
{ /* +1 to circumvent division by 0 */
*(result->number + i) = ~(*(result->number + i));
cnt++;
}
if (numberSize == 32 * (cnt - 1))
{
*(result->number + cnt - 1) = 0;
}
else if (numberSize >= 32)
{
*(result->number + cnt - 1) = *(result->number + cnt - 1) & (0xFFFFFFFF >> ((32 * cnt) - numberSize));
}
else
{
*(result->number + cnt - 1) = *(result->number + cnt - 1) & (0xFFFFFFFF >> (32 - numberSize));
}
}
free(tempMinuend);
free(tempSubtrahend);
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_DIV(uint32_t* dividend, uint32_t* divisor, t_encryptionArithmetic* result, uint16_t size)
{
/* based on long division */
/* https://www.cuemath.com/numbers/long-division/ */
/* allocate memory */
t_encryptionArithmetic* remainder, remainder2;
remainder = &remainder2;
encryptionArithmetic_Init(remainder, size);
result->remainder = 0;
bool stateFloat = false, state1 = false, isLarger = false, isEqual = false;
/* get actual size of dividend */
uint16_t dividendSize = encryptionArithmetic_numberSize(dividend, size);
/* get actual size of divisor */
uint16_t divisorSize = encryptionArithmetic_numberSize(divisor, size);
/* basic tests to catch unwanted states */
if (divisorSize == 0)
{
printf("Divisor is 0!\n");
result->compSuccess = false;
return result;
}
//for (uint16_t i = 0; i < (dividendSize > divisorSize ? dividendSize / 32 + 1 : divisorSize / 32 + 1); i++)
for (int16_t i = (dividendSize > divisorSize ? dividendSize / 32 : divisorSize / 32); i >= 0 ; i--)
{
/* division result = 1 */
if (*(divisor + i) == *(dividend + i))
{
state1 = true;
stateFloat = false;
}
/* would result in floating point operation */
else if (*(dividend + i) < *(divisor + i))
{
state1 = false;
stateFloat = true;
break;
}
else
{
state1 = false;
stateFloat = false;
break;
}
}
if (state1)
{ /* division result = 1 */
*(result->number) = 1;
result->remainder = 0;
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
else if (stateFloat)
{ /* would result in floating point operation */
printf("Divisor is larger than dividend. Floating point operations aren't supported. Result = 0\n");
*(result->number) = 0;
result->remainder = 0;
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
/* get the bit we are currently focused on (move from MSB to LSB) */
/* get the offset and focused bit inside the right data chunk */
uint16_t focusPos = 0; /* holds the current "active" bit position we add to our remainder */
uint8_t imm = 0; /* holds the offset relative to the size of our data */
uint8_t focusPosInsideDataChunk = 0; /* holds the read position relative to the address (imm) offset */
uint8_t cnt = 0; /* holds the number of '0' that have to be added to the result starting from the LSB */
uint16_t loopDivisorSize = 0; /* holds the the loop value to catch the wrong state if divisorSize % 32 == 0 */
if (divisorSize % 32 == 0)
{
loopDivisorSize = (divisorSize / 32) - 1;
}
else
{
loopDivisorSize = divisorSize / 32;
}
for (uint16_t k = 0; k < dividendSize; k++)
{
focusPos = dividendSize - 1 - k; /* -1 is needed, as the nth bit sits at position n-1 */
imm = focusPos / 32;
focusPosInsideDataChunk = focusPos - imm * 32;
/* if the remainder is larger than the divisor, we can safely conduct the subtraction w/o the need to check for an over/underflow */
//if (*(remainder->number + (divisorSize / 32)) >= *(divisor + (divisorSize / 32)))
//if (*(remainder->number + (divisorSize / 32)) > *(divisor + (divisorSize / 32)))
if (*(remainder->number + loopDivisorSize) > *(divisor + loopDivisorSize) || *(remainder->number + loopDivisorSize + 1) > *(divisor + loopDivisorSize + 1))
/* TODO: work here -> check why it fails here */
{
encryptionArithmetic_SUB(remainder->number, divisor, remainder, size); /* store subtraction of remainder and divisor inside remainder */
encryptionArithmetic_LSL(result->number, cnt, size); /* shift data to the left to add the next bit */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
k--; /* keep the read position on the same level, as it would skip one otherwise */
cnt = 0;
}
else if (*(remainder->number + loopDivisorSize) == *(divisor + loopDivisorSize) && *(remainder->number + loopDivisorSize + 1) == *(divisor + loopDivisorSize + 1))
{ /* check if both numbers are actually equal and not only the MSB-chunks of data */
isEqual = false;
for (uint16_t i = 0; i <= loopDivisorSize; i++)
{
if (*(remainder->number + i) == *(divisor + i))
{ /* add a logical "1" as LSB to the result */
isEqual = true;
}
else
{
/* remainder isn't == divisor and we need to execute the "else" part of the first if-statement */
encryptionArithmetic_LSL(remainder->number, 1, size); /* shift data one step to the left to add the next bit */
*remainder->number |= ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
cnt++;
isEqual = false;
break;
}
}
if (isEqual)
{ /* remainder == divisor and therefore the result is 1 */
encryptionArithmetic_clearNumber(remainder->number, size);
*(remainder->number) = 1;
}
}
/* as the remainder is smaller than the divisor, we would get an overflow when subtracting.
* Put next bit from the dividend at the end of remainder (new LSB) and try again */
else
{
encryptionArithmetic_LSL(remainder->number, 1, size); /* shift data one step to the left to add the next bit */
*remainder->number |= ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
cnt++;
}
}
/* legacy code */
//for (uint16_t k = 0; k < dividendSize; k++)
//{
// focusPos = dividendSize - 1 - k; /* -1 is needed, as the nth bit sits at position n-1 */
// imm = focusPos / 32;
// focusPosInsideDataChunk = focusPos - imm * 32;
// /* if the remainder is larger than the divisor, we can safely conduct the subtraction w/o the need to check for an over/underflow */
// if (result->remainder >= *divisor)
// {
// result->remainder = result->remainder - *divisor; /* store subtraction of remainder and divisor inside remainder */
// *(result->number + imm) = *(result->number + imm) << cnt | 1; /* add a logical "1" as LSB to the result */
// k--; /* keep the read position on the same level, as it would skip one otherwise */
// cnt = 0;
// }
// /* as the remainder is smaller than the divisor, we would get an overflow when subtracting.
// * Put next bit from the dividend at the end of remainder (new LSB) and try again */
// else
// {
// result->remainder = (result->remainder << 1) /* shift data each cycle one step to the left to add the next bit */
// | ((*(dividend + imm) >> (focusPosInsideDataChunk) & 1) ? 1 : 0); /* add next bit (0 or 1) to existing remainder */
// cnt++;
// }
//}
/* legacy code end */
/* get actual size of the temporary remainder */
uint16_t remainderSize = encryptionArithmetic_numberSize(remainder->number, size);
/* defines the amounts of loops necessary */
uint16_t loopLength = 0;
if (remainderSize > divisorSize)
{
if (!(remainderSize % 32)) /* remainder is a multiple of 32 */
{
loopLength = remainderSize / 32 - 1;
}
else
{
loopLength = remainderSize / 32;
}
}
else
{
if (!(divisorSize % 32)) /* remainder is a multiple of 32 */
{
loopLength = divisorSize / 32 - 1;
}
else
{
loopLength = divisorSize / 32;
}
}
isLarger = false;
isEqual = false;
for (uint16_t i = 0; i <= loopLength; i++)
{
if (*(remainder->number + i) > *(divisor + i))
{ /* store subtraction of remainder and divisor inside remainder */
isLarger = true;
isEqual = false;
}
else if (*(remainder->number + i) == *(divisor + i))
{ /* add a logical "1" as LSB to the result */
isLarger = false;
isEqual = true;
}
}
encryptionArithmetic_LSL(result->number, cnt, size); /* shift data cnt-amount to the left */
if (isLarger && !isEqual) /* store subtraction of remainder and divisor inside remainder */
{
encryptionArithmetic_SUB(remainder->number, divisor, remainder, size);
result->remainder = *remainder->number; /* store subtraction of remainder and divisor inside remainder */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
}
else if (!isLarger && isEqual) /* add a logical "1" as LSB to the result */
{
result->remainder = 0; /* no remainder left */
*(result->number) |= 1; /* add a logical "1" as LSB to the result */
}
else
{
result->remainder = *remainder->number; /* store local remainder inside outbound remainder */
}
encryptionArithmetic_DeInit(remainder);
result->compSuccess = true;
return result;
}
t_encryptionArithmetic* encryptionArithmetic_MUL(uint32_t* multiplicand, uint32_t* multiplier, t_encryptionArithmetic* result, uint16_t size)
{
/* based on the shift and add algorithm https://users.utcluj.ro/~baruch/book_ssce/SSCE-Shift-Mult.pdf */
uint8_t imm = 0; /* holds the immediate value to keep track of how many chunks of data we traversed */
uint8_t readPos = 0; /* current readable bit position */
/* get actual size of the multiplicand */
uint16_t multiplicandSize = encryptionArithmetic_numberSize(multiplicand, size);
/* get actual size of the multiplier */
uint16_t multiplierSize = encryptionArithmetic_numberSize(multiplier, size);
/* allocate memory */
/* in order to facilitate the iterative usage of the function we need to make sure
* that the result is always empty when doing the calculations. Therefore both temp-pointers are needed */
uint32_t* cache = (uint32_t*)calloc((size) / 32 * 3 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */
uint32_t* tempMultiplicand; /* allocation is done below */
uint32_t* tempMultiplier; /* allocation is done below */
/* for some reason (has to be investigated in the future) multiplying a number with a smaller number results in a limited amount of flipped bits
* current workaround: swap multiplier and multiplicand if multiplicand > multiplier */
if (multiplicandSize + 4 > multiplierSize) {
tempMultiplicand = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplicandSize
tempMultiplier = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplierSize
if (cache == NULL || tempMultiplicand == NULL || tempMultiplier == NULL)
{
if (cache != NULL) {
free(cache);
}
if (tempMultiplicand != NULL) {
free(tempMultiplicand);
}
if (tempMultiplier != NULL) {
free(tempMultiplier);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMultiplier, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
memmove(tempMultiplicand, multiplier, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
/* as the numbers have swapped places, a size recalculation is needed */
multiplicandSize = encryptionArithmetic_numberSize(multiplier, size);
multiplierSize = encryptionArithmetic_numberSize(multiplicand, size);
}
else { /* used to be the default way */
tempMultiplicand = (uint32_t*)calloc((multiplicandSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplicandSize
tempMultiplier = (uint32_t*)calloc((multiplierSize) / 32 * 4 + 2, sizeof(uint32_t)); /* Has to be double the size to be able to store all bits + 2 to handle the possible overflow */ //02.02: size -> multiplierSize
if (cache == NULL || tempMultiplicand == NULL || tempMultiplier == NULL)
{
if (cache != NULL) {
free(cache);
}
if (tempMultiplicand != NULL) {
free(tempMultiplicand);
}
if (tempMultiplier != NULL) {
free(tempMultiplier);
}
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
memmove(tempMultiplicand, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
memmove(tempMultiplier, multiplier, (multiplierSize <= 4) ? (1) : (multiplierSize / 8) + 1); /* size / 8 = number of bytes */
}
//memmove(tempMultiplicand, multiplicand, (multiplicandSize <= 4) ? (1) : (multiplicandSize / 8) + 1); /* size / 8 = number of bytes */
//memmove(tempMultiplier, multiplier, (multiplierSize <= 4) ? (1) : (multiplierSize / 8) + 1); /* size / 8 = number of bytes */
result->memAllocSuccess = true;
/* clear result for next operation */
encryptionArithmetic_clearNumber(result->number, size);
/* traverse the saved number in 32bit chunks */
for (uint16_t j = 0; j <= multiplierSize; j++) //02.02: size -> multiplierSize
{
if ((j / (imm + 1)) == 32) { /* +1 to prevent division by 0 */
readPos = 0;
imm++;
}
/* check if the current LSB is '1', skip if not */
if ((*(tempMultiplier + imm) >> readPos) & 1)
{
//for (uint8_t m = 0; m <= ((multiplicandSize > multiplierSize) ? (multiplicandSize / 32 + 1) : (multiplierSize / 32 + 1)); m++) //02.02: /32 -> /32 + 1 & size -> ?:
//for (uint8_t m = 0; m <= 7; m++)
for (uint8_t m = 0; m <= ((multiplicandSize + multiplierSize) / 32); m++)
{
/* shift the 32bit number "chunk" according the the layer of addition we are currently on and store in cache */
if (readPos == 0) {
*(cache + (m + (j / 32))) += *(tempMultiplicand + m); /* assign bits depending on current readPos */
}
else {
*(cache + (m + j / 32)) += *(tempMultiplicand + m) << readPos; /* assign bits depending on current readPos */
*(cache + (m + j / 32) + 1) += *(tempMultiplicand + m) >> (32 - readPos); /* assign bits that would be lost in shift operation to the next "chunk" */
}
/* add the previous result to the new layer including any overflowing that might occur */
*(result->number + m) += *(cache + m) + result->hasOverflown;
//*(result->number + m + (j / 32)) += *(cache + m + (j / 32)) + result->hasOverflown; //03.02
/* if the addition generated an overflow, the stored result will be smaller than the number we added to it */
if ((*(result->number + m) < *(cache + m))) {
//if ((*(result->number + m) < *(cache + m)) || (*(result->number + m) == 0xFFFFFFFF) && (*(cache + m) == 0xFFFFFFFF)) { //03.02
//if ((*(result->number + m + (j / 32)) < *(cache + m + (j / 32))) || (*(result->number + m + (j / 32)) == 0xFFFFFFFF) && (*(cache + m + (j / 32)) == 0xFFFFFFFF)) { //03.02
//if ((*(result->number + m + (j / 32)) < *(cache + m)) || (*(result->number + m + (j / 32)) == 0xFFFFFFFF) && (*(cache + m) == 0xFFFFFFFF)) { //04.02
//if ((*(result->number + m) < *(cache + m)) || (*(result->number + m + 1) == 0xFFFFFFFF) && (*(cache + m + 1) == 0xFFFFFFFF)) { //05.02 +m -> m + 1
result->hasOverflown = true;
}
else {
result->hasOverflown = false;
}
}
/* clearing the cache for the next addition operation */
encryptionArithmetic_clearNumber(cache, size);
}
readPos++;
}
free(cache);
free(tempMultiplicand);
free(tempMultiplier);
result->compSuccess = true;
return result;
}
void encryptionArithmetic_LSL(uint32_t* number, uint8_t amount, uint16_t size)
{
uint32_t overflowBit1 = 0, overflowBit2 = 0;
/* get actual size of number */
uint16_t numberSize = encryptionArithmetic_numberSize(number, size);
overflowBit1 = *number >> (32 - amount); /* store MSB from first block */
*number = *number << amount; /* perform lsl-operation of first block */
if (numberSize + amount >= 32)
{
for (uint8_t i = 1; i <= (numberSize + amount) / 32; i++)
{
overflowBit2 = *(number + i) >> (32 - amount); /* store MSB from current block */
*(number + i) = *(number + i) << amount; /* perform lsl-operation of current block */
*(number + i) |= overflowBit1; /* add MSB of last block to current block */
overflowBit1 = overflowBit2; /* store current MSB for next iteration */
}
}
}
t_encryptionArithmetic* encryptionArithmetic_Init(t_encryptionArithmetic* result, uint16_t size)
{
result->number = (uint32_t*)calloc((size) / 32 * 4 + 1, sizeof(uint32_t)); /* has to be this size to accommodate all types of computations, including multiplication */
if (result->number == NULL)
{
printf("Cannot allocate memory");
result->memAllocSuccess = false;
result->compSuccess = false;
return result;
}
result->memAllocSuccess = true;
result->compSuccess = false;
*(result->number) = 0;
result->remainder = 0;
result->hasOverflown = false;
return result;
}
void encryptionArithmetic_DeInit(t_encryptionArithmetic* ptr)
{
deinitCounter++;
free(ptr->number);
}
uint16_t encryptionArithmetic_numberSize(uint32_t *number, uint16_t size) {
uint8_t cnt = 0;
uint16_t sizeCache = size * 3, actualLength = size * 3; //02.02: *2 -> *3
while ((*(number + (sizeCache / 32) - 1)) >> (31 - cnt) != 1)
{
cnt++;
actualLength--;
if (cnt == 32)
{
cnt = 0;
sizeCache -= 32;
}
if (!actualLength) {
break;
}
}
return actualLength;
}
void encryptionArithmetic_clearNumber(uint32_t* number, uint16_t size) {
uint16_t numberSize = encryptionArithmetic_numberSize(number, size);
uint16_t loopNumberSize = 0;
if (numberSize % 32)
{
loopNumberSize = numberSize - 1;
}
else
{
loopNumberSize = numberSize;
}
for (uint16_t i = 0; i <= loopNumberSize / 32; i++) {
*(number + i) = 0;
}
}
/* returns true if first number is larger than the second one */
bool encryptionArithmetic_isLarger(uint32_t* number1, uint32_t* number2, uint16_t size) {
uint16_t divisorSize = encryptionArithmetic_numberSize(number2, size);
bool isLarger = false;
for (int16_t i = (divisorSize / 32); i >= 0; i--)
{ /* i has to be signed to access 0 */
if (*(number1 + i) > *(number2 + i))
{
isLarger = true;
}
else
{
isLarger = false;
}
}
return isLarger;
}
bool encryptionArithmetic_stringToHex(char* src, uint32_t* dest, uint16_t length) {
/* holds the amount of characters that are stored in src */
uint16_t stringLength = 0;
/* clear destination in order to facilitate iterative use or generally the same pointer */
encryptionArithmetic_clearNumber(dest, length);
/* get actual string length without the '\0' character and convert any lowercase characters */
for (stringLength = 0; src[stringLength] != '\0'; ++stringLength)
{
switch (src[stringLength]) {
case 'a': src[stringLength] = 'A'; break;
case 'b': src[stringLength] = 'B'; break;
case 'c': src[stringLength] = 'C'; break;
case 'd': src[stringLength] = 'D'; break;
case 'e': src[stringLength] = 'E'; break;
case 'f': src[stringLength] = 'F'; break;
default: break;
}
if (src[stringLength] < 48 || (src[stringLength] > 57 && src[stringLength] < 65) || src[stringLength] > 70)
{ /* 0...9, A...F */
printf("Abort, as input string contains values other than 0-9, A-F\n");
return false;
}
}
if (!stringLength)
{ /* string is empty */
return false;
}
if (stringLength * 4 > length)
{
printf("Abort, as stringLength > maxAllocatedSpace and would result in faulty memory access\n");
return false;
}
/* store conversion of string in destination while reversing the sequence */
uint16_t imm = stringLength / 8; /* 8*char == 32 bit */
uint8_t cnt;
if (!(stringLength % 8))
{
imm = stringLength / 8 - 1;
}
else
{
imm = stringLength / 8;
}
cnt = stringLength - (imm * 8) - 1;
for (uint16_t cntUp = 0; cntUp < stringLength; cntUp++)
{
if (src[cntUp] >= 48 && src[cntUp] <= 57)
{ /* 0...9 */
*(dest + imm) |= (src[cntUp] - 0x30) << (cnt * 4);
}
else
{ /* A...F */
*(dest + imm) |= (src[cntUp] - 0x37) << (cnt * 4);
}
if (cnt == 0)
{
cnt = 8;
imm--;
}
cnt--;
}
return true;
}
void encryptionArithmetic_copyNumber(uint32_t* src, uint32_t* dest, uint16_t length) {
encryptionArithmetic_clearNumber(dest, length);
uint32_t srcSize = encryptionArithmetic_numberSize(src, length);
memmove(dest, src, (srcSize <= 4) ? (1) : (srcSize / 8) + 1); /* size / 8 + 1 = number of bytes including error for int calulation */ //06.02: +1 -> + 0
}

@ -0,0 +1,70 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief n size number computation - ASYD
* \file
* \author Stefano Nicora, stefano.nicora@hslu.ch
* \date 07.03.2022
*
*--------------------------------------------------------------------
*/
#ifndef _ENCRYPTIONARITHMETIC_H_
#define _ENCRYPTIONARITHMETIC_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct encryptArithmetic {
bool hasOverflown; /* whether or not the computation has generated a overflow */
bool memAllocSuccess; /* whether or not the calloc call has been successful */
bool compSuccess; /* whether or not the desired computation has been successful */
uint32_t remainder; /* holds the remainder(if available) of the division */
uint32_t* number; /* holds the address of the computed number */
}t_encryptionArithmetic;
typedef enum {
ADD,
SUB,
DIV,
MUL,
AND,
OR,
XOR
}t_operation;
/* Computes the result of two numbers while specifying the operation with an OPCODE
*
* Usage:
* Arrays with uint32_t sized entries (number1 and number2) hold the wanted values which get computed bitwise
* from LSB to MSB starting at index 0. Data gets stored as "little Endian".
* array[0] = [X X X X X X X X X]
* MSB LSB
* */
t_encryptionArithmetic* encryptionArithmetic(uint32_t* number1, uint32_t* number2, t_encryptionArithmetic* result, uint16_t size, t_operation OPCODE);
/* initialize the module */
t_encryptionArithmetic* encryptionArithmetic_Init(t_encryptionArithmetic* result, uint16_t size);
/* deinitialize the module and free the allocated no longer needed memory */
void encryptionArithmetic_DeInit(t_encryptionArithmetic* ptr);
/* returns the number of bits representing the number */
uint16_t encryptionArithmetic_numberSize(uint32_t* number, uint16_t size);
/* returns true if first number is larger than the second one */
bool encryptionArithmetic_isLarger(uint32_t* number1, uint32_t* number2, uint16_t size);
/*
turns a number in a string-format in hex into a regular number inside the library
returns true if successful
*/
bool encryptionArithmetic_stringToHex(char* src, uint32_t* dest, uint16_t length);
void encryptionArithmetic_copyNumber(uint32_t* src, uint32_t* dest, uint16_t length);
#endif /* _ENCRYPTIONARITHMETIC_H_ */

@ -0,0 +1,168 @@
/**
*--------------------------------------------------------------------\n
* HSLU T&A Hochschule Luzern Technik+Architektur \n
*--------------------------------------------------------------------\n
*
* \brief ASYD assignment crypto 04
* \file
* \author Basil Estermann, basil.estermann@stud.hslu.ch
* Simon Frei, simon.frei@stud.hslu.ch
* Jonas Arnold, jonas.arnold@stud.hslu.ch
* \date 16.03.2023
*
*--------------------------------------------------------------------
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "encryptionArithmetic.h"
#include "DSA.h"
#define KEY_LENGTH 160
int createKeypair(void);
int calculateSessionKey(void);
void main(void) {
int result = 0;
printf("------ Calculate Keypair ------\n\n");
result = createKeypair();
if (result != 0) {
return result;
}
printf("------ Calculate Sessionkey ------\n\n");
result = calculateSessionKey();
if (result != 0) {
return result;
}
return 0;
}
int createKeypair(void) {
/*** CREATE KEYPAIR ***/
const char* P_string = "3203431780337000";
const char* alpha_string = "AFFE12345678AFFE";
const char* Priv_a_string = "9778729279583412";
const char* Priv_b_string = "4825234752983495";
// P has to be a prime number! Large prime number (64bit): 3203431780337000
t_encryptionArithmetic P;
encryptionArithmetic_Init(&P, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(P_string, P.number, KEY_LENGTH) == false) {
printf("ERROR: Creating P.");
return 1000000;
}
t_encryptionArithmetic alpha;
encryptionArithmetic_Init(&alpha, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(alpha_string, alpha.number, KEY_LENGTH) == false) {
printf("ERROR: Creating alpha.");
return 1000001;
}
t_encryptionArithmetic priv_a;
encryptionArithmetic_Init(&priv_a, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Priv_a_string, priv_a.number, KEY_LENGTH) == false) {
printf("ERROR: Creating priv a.");
return 1000003;
}
t_encryptionArithmetic priv_b;
encryptionArithmetic_Init(&priv_b, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Priv_b_string, priv_b.number, KEY_LENGTH) == false) {
printf("ERROR: Creating priv b.");
return 1000004;
}
/* initialize and calculate public key a */
t_encryptionArithmetic pub_a;
encryptionArithmetic_Init(&pub_a, KEY_LENGTH);
squareAndMultiply(&alpha, &priv_a, &P, &pub_a, KEY_LENGTH);
printf("Calculated public key for person A: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(pub_a.number + num_bytes)));
}
printf("\n");
/* initialize and calculate public key b */
t_encryptionArithmetic pub_b;
encryptionArithmetic_Init(&pub_b, KEY_LENGTH);
squareAndMultiply(&alpha, &priv_b, &P, &pub_b, KEY_LENGTH);
printf("Calculated public key for person B: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(pub_b.number + num_bytes)));
}
printf("\n");
/* initialize and calculate session key for person a */
t_encryptionArithmetic session_key_a;
encryptionArithmetic_Init(&session_key_a, KEY_LENGTH);
squareAndMultiply(&pub_b, &priv_a, &P, &session_key_a, KEY_LENGTH);
printf("Calculated session key for person A: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(session_key_a.number + num_bytes)));
}
printf("\n");
/* initialize and calculate session key for person b */
t_encryptionArithmetic session_key_b;
encryptionArithmetic_Init(&session_key_b, KEY_LENGTH);
squareAndMultiply(&pub_a, &priv_b, &P, &session_key_b, KEY_LENGTH);
printf("Calculated session key for person B: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(session_key_b.number + num_bytes)));
}
printf("\n");
return 0;
}
int calculateSessionKey(void) {
/*** Calculate Session Key ***/
const char* P_string = "3203431780337000";
const char* Priv_a_string = "9778729279583412";
const char* Pub_b_string = "13BED5BE5045000";
// P has to be a prime number! Large prime number (64bit): 3203431780337000
t_encryptionArithmetic P;
encryptionArithmetic_Init(&P, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(P_string, P.number, KEY_LENGTH) == false) {
printf("ERROR: Creating P.");
return 1100000;
}
t_encryptionArithmetic priv_a;
encryptionArithmetic_Init(&priv_a, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Priv_a_string, priv_a.number, KEY_LENGTH) == false) {
printf("ERROR: Creating priv a.");
return 1100003;
}
t_encryptionArithmetic pub_b;
encryptionArithmetic_Init(&pub_b, KEY_LENGTH);
if (encryptionArithmetic_stringToHex(Pub_b_string, pub_b.number, KEY_LENGTH) == false) {
printf("ERROR: Creating pub b.");
return 1100004;
}
/* initialize and calculate session key for person a */
t_encryptionArithmetic session_key_a;
encryptionArithmetic_Init(&session_key_a, KEY_LENGTH);
squareAndMultiply(&pub_b, &priv_a, &P, &session_key_a, KEY_LENGTH);
printf("Calculated session key for person A: 0x");
for (int num_bytes = KEY_LENGTH / 64; num_bytes >= 0; num_bytes--) {
printf("%X", *((uint32_t*)(session_key_a.number + num_bytes)));
}
printf("\n");
return 0;
}

@ -1,40 +0,0 @@
Accelerometer Example
=====================
In this example we will see how to use the accelerometer of the micro:bit. The
accelerometer can, for instance, be used to know which way the micro:bit is
oriented.
Code
====
To get the acceleration value for all axes, we will just call the function
`MicroBit.Accelerometer.Data`. This function returns a record with `X`, `Y`
and `Z` field giving the value for each axis.
```ada
declare
Data : MMA8653.All_Axes_Data;
-- A variable to store the accelerometer data
begin
-- Read Accelerometer data
Data := Accelerometer.Data;
end;
```
We can then use the value in the record to get some information about the
orientation of the micro:bit. For example, if the Y value is below `-200`
the micro:bit is vertical.
Note that the type used to store the values of the accelerometer is declared in
the package `MMA8653` (the driver), so we have to `with` and `use` this package
to be have acces to the operations for this type.
```ada
if Data.Y < -200 then
-- The micro:bit is vertical
end if;
```

@ -1,26 +0,0 @@
with "../../../boards/MicroBit/microbit_zfp.gpr";
project Jumper is
for Runtime ("ada") use Microbit_Zfp'Runtime ("Ada");
for Target use "arm-eabi";
for Main use ("main.adb");
for Languages use ("Ada");
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Create_Missing_Dirs use "True";
package Compiler renames Microbit_Zfp.Compiler;
package Linker is
for Default_Switches ("ada") use Microbit_Zfp.Linker_Switches & ("-Wl,--print-memory-usage", "-Wl,--gc-sections");
end Linker;
package Ide is
for Program_Host use ":1234";
for Communication_Protocol use "remote";
for Connection_Tool use "pyocd";
end Ide;
end Jumper;

@ -1,75 +0,0 @@
------------------------------------------------------------------------------
-- JUMPER TEAM BJS --
------------------------------------------------------------------------------
with LSM303; use LSM303;
with MicroBit.Display;
with MicroBit.Accelerometer;
with MicroBit.Console;
with MicroBit.Time;
use MicroBit;
procedure Main is
Data : LSM303.All_Axes_Data;
FreeFallCounter : Integer;
FreeFallDetectionCycles : Integer;
FreeFallCondition : Boolean;
Threshold : Axis_Data;
begin
Console.Put_Line ("Jumper - starting up ..");
-- Initialization
FreeFallCondition := False;
FreeFallCounter := 0;
FreeFallDetectionCycles := 100; -- 100 * 5ms = 500ms
Threshold := 20;
loop
-- READ DATA
-- Read the accelerometer data
Data := Accelerometer.Data;
-- Print the data on the serial port
Console.Put_Line ("X:" & Data.X'Img & ASCII.HT &
"Y:" & Data.Y'Img & ASCII.HT &
"Z:" & Data.Z'Img);
--------------------------------------------------------------------
-- FREEFALL DETECTION
-- check wether all axis are sub-threshold => increment counter
if abs(Data.X) < Threshold and
abs(Data.Y) < Threshold and
abs(Data.Z) < Threshold then
FreeFallCounter := FreeFallCounter + 1;
-- otherwise reset counter
else
FreeFallCounter := 0;
end if;
-- Set free fall condition when counter reaches threshold
if FreeFallCounter >= FreeFallDetectionCycles then
FreeFallCondition := True;
end if;
--------------------------------------------------------------------
-- DISPLAY
-- Clear the LED matrix
Display.Clear;
-- Check, wether FreeFallCondition was triggered
if FreeFallCondition then
Display.Display ('X');
else
Display.Display ('0');
end if;
Time.Sleep (5); -- 200 samples / s
end loop;
end Main;
Loading…
Cancel
Save