summaryrefslogtreecommitdiff
path: root/benchmarks/CUDA/AES/aesCudaUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks/CUDA/AES/aesCudaUtils.cpp')
-rw-r--r--benchmarks/CUDA/AES/aesCudaUtils.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/benchmarks/CUDA/AES/aesCudaUtils.cpp b/benchmarks/CUDA/AES/aesCudaUtils.cpp
new file mode 100644
index 0000000..3367186
--- /dev/null
+++ b/benchmarks/CUDA/AES/aesCudaUtils.cpp
@@ -0,0 +1,352 @@
+
+/***************************************************************************
+ * Copyright (C) 2006 *
+ * *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+
+/**
+ @author Svetlin Manavski <[email protected]>
+ */
+
+#include "aesCudaUtils.h"
+#include <string.h>
+
+extern unsigned Rcon[];
+extern unsigned SBox[];
+extern unsigned LogTable[];
+extern unsigned ExpoTable[];
+
+extern unsigned MODE;
+
+//------------------------------------------help-functions-------------------------------------------------------
+unsigned mySbox(unsigned num) {
+ return SBox[num];
+}
+
+unsigned myXor(unsigned num1, unsigned num2) {
+ return num1 ^ num2;
+}
+
+//------------------------------------------help-functions-------------------------------------------------------
+
+
+//------------------------------------------AESCudaUtils-----------------------------------------------------------
+//------------------------------------------AESCudaUtils-----------------------------------------------------------
+//------------------------------------------AESCudaUtils-----------------------------------------------------------
+
+// gestisce la riga di commando
+unsigned commandLineManager(int argc, char *argv[]) {
+
+ if ( argc<5 )
+ usage();
+
+ if ( argc%2 != 1)
+ usage();
+
+ if ( (*argv[1] != 'e') && (*argv[1] != 'd') )
+ usage();
+
+ if ( ( strcmp(argv[2], "256") ) && ( strcmp(argv[2], "128") ) )
+ usage();
+
+ if (*argv[1] != 'e')
+ MODE = 0;
+
+ //controllo esistenza file in futuro
+
+ return ( (argc-3) / 2 );
+}
+
+void usage() {
+ std::cout << "\nAES - CUDA by Svetlin Manavski" << std::endl;
+ std::cout << "Version 0.90" << std::endl << std::endl;
+ std::cout << "Usage:" << std::endl << std::endl;
+ std::cout << "aescuda <e|d> <128|256> input1 key1 input2 key2 .... inputN keyN" << std::endl;
+ std::cout << "e\t- means to encrypt the input file" << std::endl;
+ std::cout << "d\t- means to decrypt the input file" << std::endl;
+ std::cout << "128/256\t- selects the aes type" << std::endl << std::endl;
+ std::cout << "input file maximum size: 34.603.007 bytes" << std::endl;
+ std::cout << "key file must contain 32 or 16 elements in hex format separated by blanks\n\n";
+ exit(0);
+}
+
+//funzione principale
+unsigned initAesCuda(std::string myKeyFile, unsigned char myKeyBuffer[], const unsigned int myKeyBitsSize, std::string myInputFile, char inputArray[], const unsigned inputArraySize){
+
+ path inputPath(myInputFile.c_str());
+ path keyPath(myKeyFile.c_str());
+
+ if ( !exists(keyPath) )
+ throw std::string("file "+keyPath.string()+" doesn't exist");
+
+ if ( !exists(inputPath) )
+ throw std::string("file "+inputPath.string()+" doesn't exist");
+
+ if ( myKeyBitsSize!=256 && myKeyBitsSize!=128)
+ throw std::string("cannot use a key dimension different from 256 or 128");
+
+ if ( !myKeyBuffer )
+ throw std::string("key array not allocated");
+
+ if ( !inputArray )
+ throw std::string("input array not allocated");
+
+ boost::intmax_t inputFileSize = getFileSize(inputPath);
+ boost::intmax_t keyFileSize = getFileSize(keyPath);
+
+ if ( keyFileSize==0 )
+ throw std::string("cannot use an empty input file");
+
+ if ( inputFileSize==0 )
+ throw std::string("cannot use an empty key file");
+
+ if ( inputFileSize > inputArraySize - 1 && MODE)
+ throw std::string("cannot encrypt a file bigger than 34.603.007 bytes");
+
+ if ( inputFileSize > inputArraySize && !MODE)
+ throw std::string("cannot decrypt a file bigger than 33MB");
+
+ //legge l'input
+ readFromFileNotForm(inputPath, inputArray, inputFileSize);
+
+ std::vector<unsigned> keyArray(myKeyBitsSize/8);
+
+ unsigned ekSize = (myKeyBitsSize != 256) ? 176 : 240;
+
+ std::vector<unsigned> expKeyArray(ekSize);
+ std::vector<unsigned> invExpKeyArray(ekSize);
+
+ //legge la chiave
+ readFromFileForm(keyPath, keyArray);
+
+ std::cout << "\n###############################################################\n\n";
+ std::cout << "AES - CUDA by Svetlin Manavski)\n\n";
+ std::cout << "AES " << myKeyBitsSize << " is running...." << std::endl << std::endl;
+ std::cout << "Input file size: " << inputFileSize << " Bytes" << std::endl << std::endl;
+ std::cout << "Key: ";
+ for (unsigned cnt=0; cnt<keyArray.size(); ++cnt)
+ std::cout << std::hex << keyArray[cnt];
+
+ if (MODE){
+ //ENCRYPTION MODE
+
+ //PADDING MANAGEMENT FOLLOWING THE PKCS STANDARD
+ unsigned mod16 = inputFileSize % 16;
+ unsigned div16 = inputFileSize / 16;
+
+ unsigned padElem;
+ if ( mod16 != 0 )
+ padElem = 16 - mod16;
+ else
+ padElem = 16;
+
+ for (unsigned cnt = 0; cnt < padElem; ++cnt)
+ inputArray[div16*16 + mod16 + cnt] = padElem;
+
+ inputFileSize = inputFileSize + padElem;
+
+ //IN THE ENCRYPTION MODE I NEED THE EXPANDED KEY
+ expFunc(keyArray, expKeyArray);
+ for (unsigned cnt=0; cnt<expKeyArray.size(); ++cnt){
+ unsigned val = expKeyArray[cnt];
+ unsigned char *pc = reinterpret_cast<unsigned char *>(&val);
+ myKeyBuffer[cnt] = *(pc);
+ }
+ } else {
+ //DECRYPTION MODE
+
+ //IN THE ENCRYPTION MODE I NEED THE INVERSE EXPANDED KEY
+ expFunc(keyArray, expKeyArray);
+ invExpFunc(expKeyArray, invExpKeyArray);
+ for (unsigned cnt=0; cnt<invExpKeyArray.size(); ++cnt){
+ unsigned val = invExpKeyArray[cnt];
+ unsigned char *pc = reinterpret_cast<unsigned char *>(&val);
+ myKeyBuffer[cnt] = *(pc);
+ }
+ }
+ std::cout << std::endl;
+
+ return inputFileSize;
+}
+
+
+boost::intmax_t getFileSize(path &myPath){
+ if ( !exists(myPath) )
+ throw std::string("file "+myPath.string()+" doesn't exist");
+
+ return file_size(myPath);
+}
+
+//legge file non formattati come l'input
+void readFromFileNotForm(path &myPath, char *storingArray, unsigned dataSize){
+ if ( !exists(myPath) )
+ throw std::string("file "+myPath.string()+" doesn't exist");
+ if ( !storingArray )
+ throw std::string("readFromFileNotForm: array not allocated");
+
+ std::ifstream inStream;
+ inStream.open( myPath.string().c_str(), std::ifstream::binary );
+ inStream.read(storingArray, dataSize);
+ inStream.close();
+}
+
+//legge file formattati come la chiave (esadecimali separati da spazi)
+void readFromFileForm(path &myPath, std::vector<unsigned> &storingArray){
+ if ( !exists(myPath) )
+ throw std::string("file "+myPath.string()+" doesn't exist");
+ if ( storingArray.size()!=32 && storingArray.size()!=16)
+ throw std::string("readFromFileForm: storing array of wrong dimension");
+
+ std::ifstream inStream;
+ inStream>>std::hex;
+ inStream.open( myPath.string().c_str() );
+
+ for (unsigned cnt=0; cnt<storingArray.size(); ++cnt){
+ inStream >> storingArray[cnt];
+ if ( ( inStream.eof() ) && ( cnt != storingArray.size()-1 ) )
+ throw std::string("cannot use a key with less than 32 or 16 elements ");
+ if ( ( !inStream.eof() ) && ( cnt == storingArray.size()-1 ) )
+ std::cout << "WARNING: your key file has more than 32 or 16 elements. It will be cut down to this threshold\n";
+ if ( inStream.fail() )
+ throw std::string("Check that your key file elements are in hexadecimal format separeted by blanks");
+ }
+
+ inStream.close();
+}
+
+//espande la chiave
+void expFunc(std::vector<unsigned> &keyArray, std::vector<unsigned> &expKeyArray){
+ if ( keyArray.size()!=32 && keyArray.size()!=16 )
+ throw std::string("expFunc: key array of wrong dimension");
+ if ( expKeyArray.size()!=240 && expKeyArray.size()!=176 )
+ throw std::string("expFunc: expanded key array of wrong dimension");
+
+ copy(keyArray.begin(), keyArray.end(), expKeyArray.begin());
+
+ unsigned cycles = (expKeyArray.size()!=240) ? 11 : 8;
+
+ for (unsigned i=1; i<cycles; ++i){
+ singleStep(expKeyArray, i);
+ }
+}
+
+void singleStep(std::vector<unsigned> &expKey, unsigned stepIdx){
+ if ( expKey.size()!=240 && expKey.size()!=176 )
+ throw std::string("singleStep: expanded key array of wrong dimension");
+ if ( stepIdx<1 && stepIdx>11 )
+ throw std::string("singleStep: index out of range");
+
+ unsigned num = (expKey.size()!=240) ? 16 : 32;
+ unsigned idx = (expKey.size()!=240) ? 16*stepIdx : 32*stepIdx;
+
+ copy(expKey.begin()+(idx)-4, expKey.begin()+(idx),expKey.begin()+(idx));
+ rotate(expKey.begin()+(idx), expKey.begin()+(idx)+1, expKey.begin()+(idx)+4);
+
+ transform(expKey.begin()+(idx), expKey.begin()+(idx)+4, expKey.begin()+(idx), mySbox);
+
+ expKey[idx] = expKey[idx] ^ Rcon[stepIdx-1];
+
+ transform(expKey.begin()+(idx), expKey.begin()+(idx)+4, expKey.begin()+(idx)-num, expKey.begin()+(idx), myXor);
+
+ for (unsigned cnt=0; cnt<3; ++cnt){
+ copy(expKey.begin()+(idx)+4*cnt, expKey.begin()+(idx)+4*(cnt+1),expKey.begin()+(idx)+(4*(cnt+1)));
+ transform(expKey.begin()+(idx)+4*(cnt+1), expKey.begin()+(idx)+4*(cnt+2), expKey.begin()+(idx)-(num-4*(cnt+1)), expKey.begin()+(idx)+4*(cnt+1), myXor);
+ }
+
+ if(stepIdx!=7 && expKey.size()!=176){
+ copy(expKey.begin()+(idx)+12, expKey.begin()+(idx)+16,expKey.begin()+(idx)+16);
+ transform(expKey.begin()+(idx)+16, expKey.begin()+(idx)+20, expKey.begin()+(idx)+16, mySbox);
+ transform(expKey.begin()+(idx)+16, expKey.begin()+(idx)+20, expKey.begin()+(idx)-(32-16), expKey.begin()+(idx)+16, myXor);
+
+ for (unsigned cnt=4; cnt<7; ++cnt){
+ copy(expKey.begin()+(idx)+4*cnt, expKey.begin()+(idx)+4*(cnt+1),expKey.begin()+(idx)+(4*(cnt+1)));
+ transform(expKey.begin()+(idx)+4*(cnt+1), expKey.begin()+(idx)+4*(cnt+2), expKey.begin()+(idx)-(32-4*(cnt+1)), expKey.begin()+(idx)+4*(cnt+1), myXor);
+ }
+ }
+}
+
+//espande la chiave inversa per la decriptazione
+void invExpFunc(std::vector<unsigned> &expKey, std::vector<unsigned> &invExpKey){
+ if ( expKey.size()!=240 && expKey.size()!=176 )
+ throw std::string("invExpFunc: expanded key array of wrong dimension");
+ if ( invExpKey.size()!=240 && invExpKey.size()!=176 )
+ throw std::string("invExpFunc: inverse expanded key array of wrong dimension");
+
+ std::vector<unsigned> temp(16);
+
+ copy(expKey.begin(), expKey.begin()+16,invExpKey.end()-16);
+ copy(expKey.end()-16, expKey.end(),invExpKey.begin());
+
+ unsigned cycles = (expKey.size()!=240) ? 10 : 14;
+
+ for (unsigned cnt=1; cnt<cycles; ++cnt){
+ copy(expKey.end()-(16*cnt+16), expKey.end()-(16*cnt), temp.begin());
+ invMixColumn(temp);
+ copy(temp.begin(), temp.end(), invExpKey.begin()+(16*cnt));
+ }
+}
+
+void invMixColumn(std::vector<unsigned> &temp){
+ if ( temp.size()!=16 )
+ throw std::string("invMixColumn: array of wrong dimension");
+
+ std::vector<unsigned> result(4);
+
+ for(unsigned cnt=0; cnt<4; ++cnt){
+ result[0] = galoisProd(0x0e, temp[cnt*4]) ^ galoisProd(0x0b, temp[cnt*4+1]) ^ galoisProd(0x0d, temp[cnt*4+2]) ^ galoisProd(0x09, temp[cnt*4+3]);
+ result[1] = galoisProd(0x09, temp[cnt*4]) ^ galoisProd(0x0e, temp[cnt*4+1]) ^ galoisProd(0x0b, temp[cnt*4+2]) ^ galoisProd(0x0d, temp[cnt*4+3]);
+ result[2] = galoisProd(0x0d, temp[cnt*4]) ^ galoisProd(0x09, temp[cnt*4+1]) ^ galoisProd(0x0e, temp[cnt*4+2]) ^ galoisProd(0x0b, temp[cnt*4+3]);
+ result[3] = galoisProd(0x0b, temp[cnt*4]) ^ galoisProd(0x0d, temp[cnt*4+1]) ^ galoisProd(0x09, temp[cnt*4+2]) ^ galoisProd(0x0e, temp[cnt*4+3]);
+
+ copy(result.begin(), result.end(), temp.begin()+(4*cnt));
+ }
+}
+
+//prodotto di Galois di due numeri
+unsigned galoisProd(unsigned a, unsigned b){
+
+ if(a==0 || b==0) return 0;
+ else {
+ a = LogTable[a];
+ b = LogTable[b];
+ a = a+b;
+ a = a % 255;
+ a = ExpoTable[a];
+ return a;
+ }
+}
+
+//scrive su file il risultato
+void writeToFile(const std::string &outPath, char *storingArray, boost::intmax_t dataSize, unsigned maxInputSize){
+ if ( !storingArray )
+ throw std::string("writeToFile: array not allocated");
+
+ if ( dataSize > maxInputSize)
+ dataSize = maxInputSize;
+
+ std::ofstream outStream;
+ outStream.open( outPath.c_str() , std::ifstream::binary);
+
+ if (!MODE)
+ dataSize = dataSize - storingArray[dataSize-1];
+
+ outStream.write(storingArray, dataSize);
+ outStream.close();
+}
+