From 636321568d2ed755d53906b98667846f1d5c37a3 Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Thu, 16 Mar 2023 15:14:55 +0100 Subject: [PATCH] copied crypto project from SW03 --- ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln | 10 + ASYD_Cryptograhpy/SW04-DSA/DSA.c | 134 +++ ASYD_Cryptograhpy/SW04-DSA/DSA.h | 31 + ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj | 141 +++ .../SW04-DSA/SW04-DSA.vcxproj.filters | 36 + .../SW04-DSA/encryptionArithmetic.c | 937 ++++++++++++++++++ .../SW04-DSA/encryptionArithmetic.h | 70 ++ ASYD_Cryptograhpy/SW04-DSA/main.c | 168 ++++ .../examples/MicroBit/jumper/README.md | 40 - .../examples/MicroBit/jumper/jumper.gpr | 26 - .../examples/MicroBit/jumper/src/main.adb | 75 -- 11 files changed, 1527 insertions(+), 141 deletions(-) create mode 100644 ASYD_Cryptograhpy/SW04-DSA/DSA.c create mode 100644 ASYD_Cryptograhpy/SW04-DSA/DSA.h create mode 100644 ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj create mode 100644 ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj.filters create mode 100644 ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.c create mode 100644 ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.h create mode 100644 ASYD_Cryptograhpy/SW04-DSA/main.c delete mode 100644 ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/README.md delete mode 100644 ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/jumper.gpr delete mode 100644 ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/src/main.adb diff --git a/ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln b/ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln index 2032f13..a878b11 100644 --- a/ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln +++ b/ASYD_Cryptograhpy/ASYD_Cryptograhpy.sln @@ -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 diff --git a/ASYD_Cryptograhpy/SW04-DSA/DSA.c b/ASYD_Cryptograhpy/SW04-DSA/DSA.c new file mode 100644 index 0000000..b53e125 --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/DSA.c @@ -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 +#include +#include +#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 */ + } + } +} \ No newline at end of file diff --git a/ASYD_Cryptograhpy/SW04-DSA/DSA.h b/ASYD_Cryptograhpy/SW04-DSA/DSA.h new file mode 100644 index 0000000..149179c --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/DSA.h @@ -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 +#include +#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_ \ No newline at end of file diff --git a/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj b/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj new file mode 100644 index 0000000..8f35182 --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + 16.0 + Win32Proj + {737511b3-89a4-41cd-a680-ee8cc74c60fa} + SW04DSA + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj.filters b/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj.filters new file mode 100644 index 0000000..e4d8e24 --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/SW04-DSA.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.c b/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.c new file mode 100644 index 0000000..0e4fe8e --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.c @@ -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 +#include +#include /* calloc, malloc, free, etc. */ +#include +#include +#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 +} \ No newline at end of file diff --git a/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.h b/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.h new file mode 100644 index 0000000..97d2c6f --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/encryptionArithmetic.h @@ -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 +#include +#include +#include +#include + +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_ */ diff --git a/ASYD_Cryptograhpy/SW04-DSA/main.c b/ASYD_Cryptograhpy/SW04-DSA/main.c new file mode 100644 index 0000000..7e9bc55 --- /dev/null +++ b/ASYD_Cryptograhpy/SW04-DSA/main.c @@ -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 +#include +#include +#include +#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; +} \ No newline at end of file diff --git a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/README.md b/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/README.md deleted file mode 100644 index 583d851..0000000 --- a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/README.md +++ /dev/null @@ -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; -``` diff --git a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/jumper.gpr b/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/jumper.gpr deleted file mode 100644 index 29ac460..0000000 --- a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/jumper.gpr +++ /dev/null @@ -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; - diff --git a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/src/main.adb b/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/src/main.adb deleted file mode 100644 index 21a2c1c..0000000 --- a/ASYD_Safety/Ada_Microbit/examples/MicroBit/jumper/src/main.adb +++ /dev/null @@ -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;