Crypto++  8.8
Free C++ class library of cryptographic schemes
simeck.cpp
1 // simeck.cpp - written and placed in the public domain by Gangqiang Yang and Jeffrey Walton.
2 // Based on "The Simeck Family of Lightweight Block Ciphers" by Gangqiang Yang,
3 // Bo Zhu, Valentin Suder, Mark D. Aagaard, and Guang Gong
4 
5 #include "pch.h"
6 #include "config.h"
7 
8 #include "simeck.h"
9 #include "misc.h"
10 #include "cpu.h"
11 
12 ANONYMOUS_NAMESPACE_BEGIN
13 
16 
17 /// \brief SIMECK encryption round
18 /// \tparam T word type
19 /// \param key the key for the round or iteration
20 /// \param left the first value
21 /// \param right the second value
22 /// \details SIMECK_Encryption serves as the key schedule, encryption and
23 /// decryption functions.
24 template <class T>
25 inline void SIMECK_Encryption(const T key, T& left, T& right)
26 {
27  const T temp = left;
28  left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
29  right = temp;
30 }
31 
32 ANONYMOUS_NAMESPACE_END
33 
34 NAMESPACE_BEGIN(CryptoPP)
35 
36 std::string SIMECK32::Base::AlgorithmProvider() const
37 {
38  return "C++";
39 }
40 
41 void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
42 {
43  CRYPTOPP_UNUSED(params);
44  CRYPTOPP_UNUSED(keyLength);
45 
46  GetBlock<word16, BigEndian> kblock(userKey);
47  kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);
48 
49  word16 constant = 0xFFFC;
50  word32 sequence = 0x9A42BB1F;
51  for (unsigned int i = 0; i < ROUNDS; ++i)
52  {
53  m_rk[i] = m_t[0];
54 
55  constant &= 0xFFFC;
56  constant |= sequence & 1;
57  sequence >>= 1;
58 
59  SIMECK_Encryption(static_cast<word16>(constant), m_t[1], m_t[0]);
60 
61  // rotate the LFSR of m_t
62  m_t[4] = m_t[1];
63  m_t[1] = m_t[2];
64  m_t[2] = m_t[3];
65  m_t[3] = m_t[4];
66  }
67 }
68 
69 void SIMECK32::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
70 {
71  // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
72  GetBlock<word16, BigEndian> iblock(inBlock);
73  iblock(m_t[1])(m_t[0]);
74 
75  for (int idx = 0; idx < ROUNDS; ++idx)
76  SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
77 
78  PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
79  oblock(m_t[1])(m_t[0]);
80 }
81 
82 void SIMECK32::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
83 {
84  // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
85  GetBlock<word16, BigEndian> iblock(inBlock);
86  iblock(m_t[0])(m_t[1]);
87 
88  for (int idx = ROUNDS - 1; idx >= 0; --idx)
89  SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
90 
91  PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
92  oblock(m_t[0])(m_t[1]);
93 }
94 
95 std::string SIMECK64::Base::AlgorithmProvider() const
96 {
97  return "C++";
98 }
99 
100 void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
101 {
102  CRYPTOPP_UNUSED(params);
103  CRYPTOPP_UNUSED(keyLength);
104 
105  GetBlock<word32, BigEndian> kblock(userKey);
106  kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);
107 
108  word64 constant = W64LIT(0xFFFFFFFC);
109  word64 sequence = W64LIT(0x938BCA3083F);
110  for (unsigned int i = 0; i < ROUNDS; ++i)
111  {
112  m_rk[i] = m_t[0];
113 
114  constant &= W64LIT(0xFFFFFFFC);
115  constant |= sequence & 1;
116  sequence >>= 1;
117 
118  SIMECK_Encryption(static_cast<word32>(constant), m_t[1], m_t[0]);
119 
120  // rotate the LFSR of m_t
121  m_t[4] = m_t[1];
122  m_t[1] = m_t[2];
123  m_t[2] = m_t[3];
124  m_t[3] = m_t[4];
125  }
126 }
127 
128 void SIMECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
129 {
130  // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
131  GetBlock<word32, BigEndian> iblock(inBlock);
132  iblock(m_t[1])(m_t[0]);
133 
134  for (int idx = 0; idx < ROUNDS; ++idx)
135  SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
136 
137  PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
138  oblock(m_t[1])(m_t[0]);
139 }
140 
141 void SIMECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
142 {
143  // Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
144  GetBlock<word32, BigEndian> iblock(inBlock);
145  iblock(m_t[0])(m_t[1]);
146 
147  for (int idx = ROUNDS - 1; idx >= 0; --idx)
148  SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
149 
150  PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
151  oblock(m_t[0])(m_t[1]);
152 }
153 
154 NAMESPACE_END
static const int ROUNDS
The number of rounds for the algorithm provided as a constant.
Definition: seckey.h:56
Access a block of memory.
Definition: misc.h:2975
Interface for retrieving values given their names.
Definition: cryptlib.h:327
Access a block of memory.
Definition: misc.h:3016
Library configuration file.
#define W64LIT(x)
Declare an unsigned word64.
Definition: config_int.h:129
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
unsigned short word16
16-bit unsigned datatype
Definition: config_int.h:69
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:101
Functions for CPU features and intrinsics.
Utility functions for the Crypto++ library.
T rotlConstant(T x)
Performs a left rotate.
Definition: misc.h:1757
T rotrConstant(T x)
Performs a right rotate.
Definition: misc.h:1783
Crypto++ library namespace.
Precompiled header file.
Classes for the SIMECK block cipher.