109 lines
2.3 KiB
C++
109 lines
2.3 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include "speck.hpp"
|
|
|
|
#include <cruft/util/bitwise.hpp>
|
|
|
|
using cruft::crypto::block::speck;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/// The round function for the encryption direction.
|
|
///
|
|
/// Mutates the x and y values.
|
|
///
|
|
/// \param x first data word
|
|
/// \param y second data word
|
|
/// \param k key word
|
|
static void
|
|
round_enc (u64 &x, u64 &y, u64 const &k)
|
|
{
|
|
x = cruft::rotater (x, 8);
|
|
x += y;
|
|
|
|
x ^= k;
|
|
|
|
y = cruft::rotatel (y, 3);
|
|
y ^= x;
|
|
}
|
|
|
|
|
|
///----------------------------------------------------------------------------
|
|
/// The round function for the decryption direction
|
|
///
|
|
/// Mutates the x and y values.
|
|
///
|
|
/// \param x
|
|
/// \param y
|
|
/// \param k
|
|
static void
|
|
round_dec (u64 &x, u64 &y, u64 const &k)
|
|
{
|
|
y ^= x;
|
|
y = cruft::rotater (y, 3);
|
|
|
|
x ^= k;
|
|
|
|
x -= y;
|
|
x = cruft::rotatel (x, 8);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/// Initialise the key schedule
|
|
speck::speck (std::array<u64,2> _key)
|
|
{
|
|
auto &x = _key[0];
|
|
auto &y = _key[1];
|
|
|
|
// Allocate a space to store the schedule as it's computed
|
|
std::array<u64,32> schedule;
|
|
schedule[0] = y;
|
|
|
|
// Initialise the key to be indices 0..31
|
|
std::iota (std::begin (m_key), std::end (m_key), 0);
|
|
|
|
// 'encrypt' the key using the index schedule
|
|
for (int i = 0; i < 31; ++i) {
|
|
round_enc (x, y, m_key[i]);
|
|
schedule[i + 1] = y;
|
|
}
|
|
|
|
// Copy the computed schedule back out
|
|
m_key = schedule;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
std::array<u64,2>
|
|
speck::encrypt (std::array<u64,2> plaintext) const
|
|
{
|
|
u64 &x = plaintext[0];
|
|
u64 &y = plaintext[1];
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
round_enc (x, y, m_key[i]);
|
|
|
|
return { x, y };
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
std::array<u64,2>
|
|
speck::decrypt (std::array<u64,2> plaintext) const
|
|
{
|
|
u64 &x = plaintext[0];
|
|
u64 &y = plaintext[1];
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
round_dec (x, y, m_key[31 - i]);
|
|
|
|
return { x, y };
|
|
}
|