Initial import of libdpf.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
e4e666f459
4563 changed files with 1690372 additions and 0 deletions
406
thirdparty/lowmc/LowMC.cpp
vendored
Normal file
406
thirdparty/lowmc/LowMC.cpp
vendored
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
// Vendored from https://github.com/LowMC/lowmc
|
||||
// commit e847fb160ad8ca1f373efd91a55b6d67f7deb425
|
||||
// Local changes: namespace lowmc; definitions are inline so a header-only
|
||||
// user can include this file; Grain state restarts in instantiate_LowMC.
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
#include "LowMC.h"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
namespace lowmc {
|
||||
|
||||
// Shared by every LowMC instance. instantiate_LowMC restarts it.
|
||||
inline std::bitset<80> & grain_state() {
|
||||
static std::bitset<80> state;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// LowMC functions //
|
||||
/////////////////////////////
|
||||
|
||||
inline block LowMC::encrypt (const block message) {
|
||||
block c = message ^ roundkeys[0];
|
||||
for (unsigned r = 1; r <= rounds; ++r) {
|
||||
c = Substitution(c);
|
||||
c = MultiplyWithGF2Matrix(LinMatrices[r-1], c);
|
||||
c ^= roundconstants[r-1];
|
||||
c ^= roundkeys[r];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
inline block LowMC::decrypt (const block message) {
|
||||
block c = message;
|
||||
for (unsigned r = rounds; r > 0; --r) {
|
||||
c ^= roundkeys[r];
|
||||
c ^= roundconstants[r-1];
|
||||
c = MultiplyWithGF2Matrix(invLinMatrices[r-1], c);
|
||||
c = invSubstitution(c);
|
||||
}
|
||||
c ^= roundkeys[0];
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
inline void LowMC::set_key (keyblock k) {
|
||||
key = k;
|
||||
keyschedule();
|
||||
}
|
||||
|
||||
|
||||
inline void LowMC::print_matrices() {
|
||||
std::cout << "LowMC matrices and constants" << std::endl;
|
||||
std::cout << "============================" << std::endl;
|
||||
std::cout << "Block size: " << blocksize << std::endl;
|
||||
std::cout << "Key size: " << keysize << std::endl;
|
||||
std::cout << "Rounds: " << rounds << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Linear layer matrices" << std::endl;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
for (unsigned r = 1; r <= rounds; ++r) {
|
||||
std::cout << "Linear layer " << r << ":" << std::endl;
|
||||
for (auto row: LinMatrices[r-1]) {
|
||||
std::cout << "[";
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
std::cout << row[i];
|
||||
if (i != blocksize - 1) {
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Round constants" << std::endl;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
for (unsigned r = 1; r <= rounds; ++r) {
|
||||
std::cout << "Round constant " << r << ":" << std::endl;
|
||||
std::cout << "[";
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
std::cout << roundconstants[r-1][i];
|
||||
if (i != blocksize - 1) {
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Round key matrices" << std::endl;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
for (unsigned r = 0; r <= rounds; ++r) {
|
||||
std::cout << "Round key matrix " << r << ":" << std::endl;
|
||||
for (auto row: KeyMatrices[r]) {
|
||||
std::cout << "[";
|
||||
for (unsigned i = 0; i < keysize; ++i) {
|
||||
std::cout << row[i];
|
||||
if (i != keysize - 1) {
|
||||
std::cout << ", ";
|
||||
}
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
if (r != rounds) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// LowMC private functions //
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
inline block LowMC::Substitution (const block message) {
|
||||
block temp = 0;
|
||||
//Get the identity part of the message
|
||||
temp ^= (message >> 3*numofboxes);
|
||||
//Get the rest through the Sboxes
|
||||
for (unsigned i = 1; i <= numofboxes; ++i) {
|
||||
temp <<= 3;
|
||||
temp ^= Sbox[ ((message >> 3*(numofboxes-i))
|
||||
& block(0x7)).to_ulong()];
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
inline block LowMC::invSubstitution (const block message) {
|
||||
block temp = 0;
|
||||
//Get the identity part of the message
|
||||
temp ^= (message >> 3*numofboxes);
|
||||
//Get the rest through the invSboxes
|
||||
for (unsigned i = 1; i <= numofboxes; ++i) {
|
||||
temp <<= 3;
|
||||
temp ^= invSbox[ ((message >> 3*(numofboxes-i))
|
||||
& block(0x7)).to_ulong()];
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
inline block LowMC::MultiplyWithGF2Matrix
|
||||
(const std::vector<block> matrix, const block message) {
|
||||
block temp = 0;
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
temp[i] = (message & matrix[i]).count() % 2;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
inline block LowMC::MultiplyWithGF2Matrix_Key
|
||||
(const std::vector<keyblock> matrix, const keyblock k) {
|
||||
block temp = 0;
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
temp[i] = (k & matrix[i]).count() % 2;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline void LowMC::keyschedule () {
|
||||
roundkeys.clear();
|
||||
for (unsigned r = 0; r <= rounds; ++r) {
|
||||
roundkeys.push_back( MultiplyWithGF2Matrix_Key (KeyMatrices[r], key) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
inline void LowMC::instantiate_LowMC () {
|
||||
// Grain is specified to start from the all-ones state. Restart so a
|
||||
// later instance does not continue the previous instance's stream.
|
||||
grain_state().reset();
|
||||
// Create LinMatrices and invLinMatrices
|
||||
LinMatrices.clear();
|
||||
invLinMatrices.clear();
|
||||
for (unsigned r = 0; r < rounds; ++r) {
|
||||
// Create matrix
|
||||
std::vector<block> mat;
|
||||
// Fill matrix with random bits
|
||||
do {
|
||||
mat.clear();
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
mat.push_back( getrandblock () );
|
||||
}
|
||||
// Repeat if matrix is not invertible
|
||||
} while ( rank_of_Matrix(mat) != blocksize );
|
||||
LinMatrices.push_back(mat);
|
||||
invLinMatrices.push_back(invert_Matrix (LinMatrices.back()));
|
||||
}
|
||||
|
||||
// Create roundconstants
|
||||
roundconstants.clear();
|
||||
for (unsigned r = 0; r < rounds; ++r) {
|
||||
roundconstants.push_back( getrandblock () );
|
||||
}
|
||||
|
||||
// Create KeyMatrices
|
||||
KeyMatrices.clear();
|
||||
for (unsigned r = 0; r <= rounds; ++r) {
|
||||
// Create matrix
|
||||
std::vector<keyblock> mat;
|
||||
// Fill matrix with random bits
|
||||
do {
|
||||
mat.clear();
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
mat.push_back( getrandkeyblock () );
|
||||
}
|
||||
// Repeat if matrix is not of maximal rank
|
||||
} while ( rank_of_Matrix_Key(mat) < std::min(blocksize, keysize) );
|
||||
KeyMatrices.push_back(mat);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// Binary matrix functions //
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
inline unsigned LowMC::rank_of_Matrix (const std::vector<block> matrix) {
|
||||
std::vector<block> mat; //Copy of the matrix
|
||||
for (auto u : matrix) {
|
||||
mat.push_back(u);
|
||||
}
|
||||
unsigned size = mat[0].size();
|
||||
//Transform to upper triangular matrix
|
||||
unsigned row = 0;
|
||||
for (unsigned col = 1; col <= size; ++col) {
|
||||
if ( !mat[row][size-col] ) {
|
||||
unsigned r = row;
|
||||
while (r < mat.size() && !mat[r][size-col]) {
|
||||
++r;
|
||||
}
|
||||
if (r >= mat.size()) {
|
||||
continue;
|
||||
} else {
|
||||
auto temp = mat[row];
|
||||
mat[row] = mat[r];
|
||||
mat[r] = temp;
|
||||
}
|
||||
}
|
||||
for (unsigned i = row+1; i < mat.size(); ++i) {
|
||||
if ( mat[i][size-col] ) mat[i] ^= mat[row];
|
||||
}
|
||||
++row;
|
||||
if (row == size) break;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned LowMC::rank_of_Matrix_Key (const std::vector<keyblock> matrix) {
|
||||
std::vector<keyblock> mat; //Copy of the matrix
|
||||
for (auto u : matrix) {
|
||||
mat.push_back(u);
|
||||
}
|
||||
unsigned size = mat[0].size();
|
||||
//Transform to upper triangular matrix
|
||||
unsigned row = 0;
|
||||
for (unsigned col = 1; col <= size; ++col) {
|
||||
if ( !mat[row][size-col] ) {
|
||||
unsigned r = row;
|
||||
while (r < mat.size() && !mat[r][size-col]) {
|
||||
++r;
|
||||
}
|
||||
if (r >= mat.size()) {
|
||||
continue;
|
||||
} else {
|
||||
auto temp = mat[row];
|
||||
mat[row] = mat[r];
|
||||
mat[r] = temp;
|
||||
}
|
||||
}
|
||||
for (unsigned i = row+1; i < mat.size(); ++i) {
|
||||
if ( mat[i][size-col] ) mat[i] ^= mat[row];
|
||||
}
|
||||
++row;
|
||||
if (row == size) break;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
inline std::vector<block> LowMC::invert_Matrix (const std::vector<block> matrix) {
|
||||
std::vector<block> mat; //Copy of the matrix
|
||||
for (auto u : matrix) {
|
||||
mat.push_back(u);
|
||||
}
|
||||
std::vector<block> invmat(blocksize, 0); //To hold the inverted matrix
|
||||
for (unsigned i = 0; i < blocksize; ++i) {
|
||||
invmat[i][i] = 1;
|
||||
}
|
||||
|
||||
unsigned size = mat[0].size();
|
||||
//Transform to upper triangular matrix
|
||||
unsigned row = 0;
|
||||
for (unsigned col = 0; col < size; ++col) {
|
||||
if ( !mat[row][col] ) {
|
||||
unsigned r = row+1;
|
||||
while (r < mat.size() && !mat[r][col]) {
|
||||
++r;
|
||||
}
|
||||
if (r >= mat.size()) {
|
||||
continue;
|
||||
} else {
|
||||
auto temp = mat[row];
|
||||
mat[row] = mat[r];
|
||||
mat[r] = temp;
|
||||
temp = invmat[row];
|
||||
invmat[row] = invmat[r];
|
||||
invmat[r] = temp;
|
||||
}
|
||||
}
|
||||
for (unsigned i = row+1; i < mat.size(); ++i) {
|
||||
if ( mat[i][col] ) {
|
||||
mat[i] ^= mat[row];
|
||||
invmat[i] ^= invmat[row];
|
||||
}
|
||||
}
|
||||
++row;
|
||||
}
|
||||
|
||||
//Transform to identity matrix
|
||||
for (unsigned col = size; col > 0; --col) {
|
||||
for (unsigned r = 0; r < col-1; ++r) {
|
||||
if (mat[r][col-1]) {
|
||||
mat[r] ^= mat[col-1];
|
||||
invmat[r] ^= invmat[col-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invmat;
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// Pseudorandom bits //
|
||||
///////////////////////
|
||||
|
||||
|
||||
inline block LowMC::getrandblock () {
|
||||
block tmp = 0;
|
||||
for (unsigned i = 0; i < blocksize; ++i) tmp[i] = getrandbit ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline keyblock LowMC::getrandkeyblock () {
|
||||
keyblock tmp = 0;
|
||||
for (unsigned i = 0; i < keysize; ++i) tmp[i] = getrandbit ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
// Uses the Grain LSFR as self-shrinking generator to create pseudorandom bits
|
||||
// Is initialized with the all 1s state
|
||||
// The first 160 bits are thrown away
|
||||
inline bool LowMC::getrandbit () {
|
||||
std::bitset<80> & state = grain_state(); // 80 bit LFSR state
|
||||
bool tmp = 0;
|
||||
//If state has not been initialized yet
|
||||
if (state.none ()) {
|
||||
state.set (); //Initialize with all bits set
|
||||
//Throw the first 160 bits away
|
||||
for (unsigned i = 0; i < 160; ++i) {
|
||||
//Update the state
|
||||
tmp = state[0] ^ state[13] ^ state[23]
|
||||
^ state[38] ^ state[51] ^ state[62];
|
||||
state >>= 1;
|
||||
state[79] = tmp;
|
||||
}
|
||||
}
|
||||
//choice records whether the first bit is 1 or 0.
|
||||
//The second bit is produced if the first bit is 1.
|
||||
bool choice = false;
|
||||
do {
|
||||
//Update the state
|
||||
tmp = state[0] ^ state[13] ^ state[23]
|
||||
^ state[38] ^ state[51] ^ state[62];
|
||||
state >>= 1;
|
||||
state[79] = tmp;
|
||||
choice = tmp;
|
||||
tmp = state[0] ^ state[13] ^ state[23]
|
||||
^ state[38] ^ state[51] ^ state[62];
|
||||
state >>= 1;
|
||||
state[79] = tmp;
|
||||
} while (! choice);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
} // namespace lowmc
|
||||
Loading…
Add table
Add a link
Reference in a new issue