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
21
thirdparty/lowmc/LICENSE.md
vendored
Normal file
21
thirdparty/lowmc/LICENSE.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 tyti
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
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
|
||||
94
thirdparty/lowmc/LowMC.h
vendored
Normal file
94
thirdparty/lowmc/LowMC.h
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#ifndef __LowMC_h__
|
||||
#define __LowMC_h__
|
||||
|
||||
// Vendored from https://github.com/LowMC/lowmc
|
||||
// commit e847fb160ad8ca1f373efd91a55b6d67f7deb425
|
||||
// Local changes: namespace lowmc, and the parameters below.
|
||||
// LowMCv3 instance for a 128-bit block and key with 10 S-boxes, at data
|
||||
// complexity 2^128: `determine_rounds.py 128 10 128 128` reports 32 rounds.
|
||||
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace lowmc {
|
||||
|
||||
const unsigned numofboxes = 10; // Number of Sboxes
|
||||
const unsigned blocksize = 128; // Block size in bits
|
||||
const unsigned keysize = 128; // Key size in bits
|
||||
const unsigned rounds = 32; // Number of rounds
|
||||
|
||||
const unsigned identitysize = blocksize - 3*numofboxes;
|
||||
// Size of the identity part in the Sbox layer
|
||||
|
||||
typedef std::bitset<blocksize> block; // Store messages and states
|
||||
typedef std::bitset<keysize> keyblock;
|
||||
|
||||
class LowMC {
|
||||
public:
|
||||
LowMC (keyblock k = 0) {
|
||||
key = k;
|
||||
instantiate_LowMC();
|
||||
keyschedule();
|
||||
};
|
||||
|
||||
block encrypt (const block message);
|
||||
block decrypt (const block message);
|
||||
void set_key (keyblock k);
|
||||
|
||||
void print_matrices();
|
||||
|
||||
private:
|
||||
// LowMC private data members //
|
||||
// The Sbox and its inverse
|
||||
const std::vector<unsigned> Sbox =
|
||||
{0x00, 0x01, 0x03, 0x06, 0x07, 0x04, 0x05, 0x02};
|
||||
const std::vector<unsigned> invSbox =
|
||||
{0x00, 0x01, 0x07, 0x02, 0x05, 0x06, 0x03, 0x04};
|
||||
std::vector<std::vector<block>> LinMatrices;
|
||||
// Stores the binary matrices for each round
|
||||
std::vector<std::vector<block>> invLinMatrices;
|
||||
// Stores the inverses of LinMatrices
|
||||
std::vector<block> roundconstants;
|
||||
// Stores the round constants
|
||||
keyblock key = 0;
|
||||
//Stores the master key
|
||||
std::vector<std::vector<keyblock>> KeyMatrices;
|
||||
// Stores the matrices that generate the round keys
|
||||
std::vector<block> roundkeys;
|
||||
// Stores the round keys
|
||||
|
||||
// LowMC private functions //
|
||||
block Substitution (const block message);
|
||||
// The substitution layer
|
||||
block invSubstitution (const block message);
|
||||
// The inverse substitution layer
|
||||
|
||||
block MultiplyWithGF2Matrix
|
||||
(const std::vector<block> matrix, const block message);
|
||||
// For the linear layer
|
||||
block MultiplyWithGF2Matrix_Key
|
||||
(const std::vector<keyblock> matrix, const keyblock k);
|
||||
// For generating the round keys
|
||||
|
||||
void keyschedule ();
|
||||
//Creates the round keys from the master key
|
||||
|
||||
void instantiate_LowMC ();
|
||||
//Fills the matrices and roundconstants with pseudorandom bits
|
||||
|
||||
// Binary matrix functions //
|
||||
unsigned rank_of_Matrix (const std::vector<block> matrix);
|
||||
unsigned rank_of_Matrix_Key (const std::vector<keyblock> matrix);
|
||||
std::vector<block> invert_Matrix (const std::vector<block> matrix);
|
||||
|
||||
// Random bits functions //
|
||||
block getrandblock ();
|
||||
keyblock getrandkeyblock ();
|
||||
bool getrandbit ();
|
||||
|
||||
};
|
||||
|
||||
} // namespace lowmc
|
||||
|
||||
#endif
|
||||
23
thirdparty/lowmc/README.md
vendored
Normal file
23
thirdparty/lowmc/README.md
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# LowMC implementation
|
||||
This is a C++ implementation of the LowMC block cipher family. The
|
||||
parameters (block size, number of S-boxes in the substitution layer, number
|
||||
of rounds, key size) are defined in `LowMC.h`. Compilation requires support
|
||||
of C++11 features.
|
||||
|
||||
The files `LowMC.h` and `LowMC.cpp` contain the relevant code. `test.cpp`
|
||||
contains a short example usage.
|
||||
|
||||
The file `determine_rounds.py` contains a Python script that determines
|
||||
the number of rounds needed for LowMC to be secure in dependence on
|
||||
the other parameters: the block size *n*, the number of S-boxes per layer *m*,
|
||||
the log2 of the allowed data complexity *d*, and the key size *k*.
|
||||
|
||||
Example usage: `python3 determine_rounds.py 256 63 128 128`
|
||||
|
||||
## Script for generating the matrices and and constants
|
||||
|
||||
The python script `generate_matrices.py` can be used to generate the matrices
|
||||
for the linear layer and the key schedule as well as the round constants.
|
||||
They are written to a file named `matrices_and_constants.dat`. This is script
|
||||
can provide the matrices for use in cryptanalysis. It is _not_ needed for the
|
||||
reference implementation which creates the matrices and constants internally.
|
||||
Loading…
Add table
Add a link
Reference in a new issue