summaryrefslogtreecommitdiff
path: root/simeck.cpp
blob: a1a5316e11fdff96c06c1da1b63b9269a7c1b459 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// simeck.cpp - written and placed in the public domain by Gangqiang Yang and Jeffrey Walton.
//              Based on "The Simeck Family of Lightweight Block Ciphers" by Gangqiang Yang,
//              Bo Zhu, Valentin Suder, Mark D. Aagaard, and Guang Gong

#include "pch.h"
#include "config.h"

#include "simeck.h"
#include "misc.h"
#include "cpu.h"

ANONYMOUS_NAMESPACE_BEGIN

using CryptoPP::rotlConstant;
using CryptoPP::rotrConstant;

/// \brief SIMECK encryption round
/// \tparam T word type
/// \param key the key for the round or iteration
/// \param left the first value
/// \param right the second value
/// \details SIMECK_Encryption serves as the key schedule, encryption and
///   decryption functions.
template <class T>
inline void SIMECK_Encryption(const T key, T& left, T& right)
{
    const T temp = left;
    left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
    right = temp;
}

ANONYMOUS_NAMESPACE_END

NAMESPACE_BEGIN(CryptoPP)

std::string SIMECK32::Base::AlgorithmProvider() const
{
    return "C++";
}

void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
    CRYPTOPP_UNUSED(params);
    CRYPTOPP_UNUSED(keyLength);

    GetBlock<word16, BigEndian> kblock(userKey);
    kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);

    word16 constant = 0xFFFC;
    word32 sequence = 0x9A42BB1F;
    for (unsigned int i = 0; i < ROUNDS; ++i)
    {
        m_rk[i] = m_t[0];

        constant &= 0xFFFC;
        constant |= sequence & 1;
        sequence >>= 1;

        SIMECK_Encryption(static_cast<word16>(constant), m_t[1], m_t[0]);

        // rotate the LFSR of m_t
        m_t[4] = m_t[1];
        m_t[1] = m_t[2];
        m_t[2] = m_t[3];
        m_t[3] = m_t[4];
    }
}

void SIMECK32::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
    // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
    GetBlock<word16, BigEndian> iblock(inBlock);
    iblock(m_t[1])(m_t[0]);

    for (int idx = 0; idx < ROUNDS; ++idx)
        SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);

    PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
    oblock(m_t[1])(m_t[0]);
}

void SIMECK32::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
    // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
    GetBlock<word16, BigEndian> iblock(inBlock);
    iblock(m_t[0])(m_t[1]);

    for (int idx = ROUNDS - 1; idx >= 0; --idx)
        SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);

    PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
    oblock(m_t[0])(m_t[1]);
}

std::string SIMECK64::Base::AlgorithmProvider() const
{
    return "C++";
}

void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
    CRYPTOPP_UNUSED(params);
    CRYPTOPP_UNUSED(keyLength);

    GetBlock<word32, BigEndian> kblock(userKey);
    kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);

    word64 constant = W64LIT(0xFFFFFFFC);
    word64 sequence = W64LIT(0x938BCA3083F);
    for (unsigned int i = 0; i < ROUNDS; ++i)
    {
        m_rk[i] = m_t[0];

        constant &= W64LIT(0xFFFFFFFC);
        constant |= sequence & 1;
        sequence >>= 1;

        SIMECK_Encryption(static_cast<word32>(constant), m_t[1], m_t[0]);

        // rotate the LFSR of m_t
        m_t[4] = m_t[1];
        m_t[1] = m_t[2];
        m_t[2] = m_t[3];
        m_t[3] = m_t[4];
    }
}

void SIMECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
    // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
    GetBlock<word32, BigEndian> iblock(inBlock);
    iblock(m_t[1])(m_t[0]);

    for (int idx = 0; idx < ROUNDS; ++idx)
        SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);

    PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
    oblock(m_t[1])(m_t[0]);
}

void SIMECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
    // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
    GetBlock<word32, BigEndian> iblock(inBlock);
    iblock(m_t[0])(m_t[1]);

    for (int idx = ROUNDS - 1; idx >= 0; --idx)
        SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);

    PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
    oblock(m_t[0])(m_t[1]);
}

NAMESPACE_END