trivium.c
Go to the documentation of this file.
1 /**
2  * @file trivium.c
3  * @brief Trivium stream cipher
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "cipher/trivium.h"
37 
38 //Check crypto library configuration
39 #if (TRIVIUM_SUPPORT == ENABLED)
40 
41 //Get a given bit of the internal state
42 #define TRIVIUM_GET_BIT(s, n) ((s[(n - 1) / 8] >> ((n - 1) % 8)) & 1)
43 
44 //Set a given bit of the internal state
45 #define TRIVIUM_SET_BIT(s, n, v) s[(n - 1) / 8] = \
46  (s[(n - 1) / 8] & ~(1 << ((n - 1) % 8))) | (v) << ((n - 1) % 8)
47 
48 
49 /**
50  * @brief Initialize Trivium context using the supplied key and IV
51  * @param[in] context Pointer to the Trivium context to initialize
52  * @param[in] key Pointer to the key
53  * @param[in] keyLen Length of the key (10 bytes)
54  * @param[in] iv Pointer to the initialization vector
55  * @param[in] ivLen Length of the initialization vector (10 bytes)
56  * @return Error code
57  **/
58 
59 error_t triviumInit(TriviumContext *context, const uint8_t *key,
60  size_t keyLen, const uint8_t *iv, size_t ivLen)
61 {
62  uint_t i;
63 
64  //Check parameters
65  if(context == NULL || key == NULL || iv == NULL)
67 
68  //Check the length of the key and IV
69  if(keyLen != 10 && ivLen != 10)
71 
72  //Clear the 288-bit internal state
73  osMemset(context->s, 0, 36);
74 
75  //Let (s1, s2, ..., s93) = (K1, ..., K80, 0, ..., 0)
76  for(i = 0; i < 10; i++)
77  {
78  context->s[i] = reverseInt8(key[9 - i]);
79  }
80 
81  //Load the 80-bit initialization vector
82  for(i = 0; i < 10; i++)
83  {
84  context->s[12 + i] = reverseInt8(iv[9 - i]);
85  }
86 
87  //Let (s94, s95, ..., s177) = (IV1, ..., IV80, 0, ..., 0)
88  for(i = 11; i < 22; i++)
89  {
90  context->s[i] = (context->s[i + 1] << 5) | (context->s[i] >> 3);
91  }
92 
93  //Let (s178, s279, ..., s288) = (0, ..., 0, 1, 1, 1)
94  TRIVIUM_SET_BIT(context->s, 286, 1);
95  TRIVIUM_SET_BIT(context->s, 287, 1);
96  TRIVIUM_SET_BIT(context->s, 288, 1);
97 
98  //The state is rotated over 4 full cycles, without generating key stream bit
99  for(i = 0; i < (4 * 288); i++)
100  {
101  triviumGenerateBit(context);
102  }
103 
104  //No error to report
105  return NO_ERROR;
106 }
107 
108 
109 /**
110  * @brief Encrypt/decrypt data with the Trivium algorithm
111  * @param[in] context Pointer to the Trivium context
112  * @param[in] input Pointer to the data to encrypt/decrypt (optional)
113  * @param[in] output Pointer to the resulting data (optional)
114  * @param[in] length Number of bytes to be processed
115  **/
116 
117 void triviumCipher(TriviumContext *context, const uint8_t *input,
118  uint8_t *output, size_t length)
119 {
120  size_t i;
121  uint8_t ks;
122 
123  //Encryption loop
124  for(i = 0; i < length; i++)
125  {
126  //Generate one byte of key stream
127  ks = triviumGenerateByte(context);
128 
129  //Valid output pointer?
130  if(output != NULL)
131  {
132  //Valid input pointer?
133  if(input != NULL)
134  {
135  //XOR the input data with the keystream
136  output[i] = input[i] ^ ks;
137  }
138  else
139  {
140  //Output the keystream
141  output[i] = ks;
142  }
143  }
144  }
145 }
146 
147 
148 /**
149  * @brief Generate one bit of key stream
150  * @param[in] context Pointer to the Trivium context
151  * @return Key stream bit
152  **/
153 
155 {
156  uint_t i;
157  uint8_t t1;
158  uint8_t t2;
159  uint8_t t3;
160  uint8_t z;
161 
162  //Let t1 = s66 + s93
163  t1 = TRIVIUM_GET_BIT(context->s, 66);
164  t1 ^= TRIVIUM_GET_BIT(context->s, 93);
165 
166  //Let t2 = s162 + s177
167  t2 = TRIVIUM_GET_BIT(context->s, 162);
168  t2 ^= TRIVIUM_GET_BIT(context->s, 177);
169 
170  //Let t3 = s243 + s288
171  t3 = TRIVIUM_GET_BIT(context->s, 243);
172  t3 ^= TRIVIUM_GET_BIT(context->s, 288);
173 
174  //Generate a key stream bit z
175  z = t1 ^ t2 ^ t3;
176 
177  //Let t1 = t1 + s91.s92 + s171
178  t1 ^= TRIVIUM_GET_BIT(context->s, 91) & TRIVIUM_GET_BIT(context->s, 92);
179  t1 ^= TRIVIUM_GET_BIT(context->s, 171);
180 
181  //Let t2 = t2 + s175.s176 + s264
182  t2 ^= TRIVIUM_GET_BIT(context->s, 175) & TRIVIUM_GET_BIT(context->s, 176);
183  t2 ^= TRIVIUM_GET_BIT(context->s, 264);
184 
185  //Let t3 = t3 + s286.s287 + s69
186  t3 ^= TRIVIUM_GET_BIT(context->s, 286) & TRIVIUM_GET_BIT(context->s, 287);
187  t3 ^= TRIVIUM_GET_BIT(context->s, 69);
188 
189  //Rotate the internal state
190  for(i = 35; i > 0; i--)
191  {
192  context->s[i] = (context->s[i] << 1) | (context->s[i - 1] >> 7);
193  }
194 
195  context->s[0] = context->s[0] << 1;
196 
197  //Let s1 = t3
198  TRIVIUM_SET_BIT(context->s, 1, t3);
199  //Let s94 = t1
200  TRIVIUM_SET_BIT(context->s, 94, t1);
201  //Let s178 = t2
202  TRIVIUM_SET_BIT(context->s, 178, t2);
203 
204  //Return one bit of key stream
205  return z;
206 }
207 
208 
209 /**
210  * @brief Generate one byte of key stream
211  * @param[in] context Pointer to the Trivium context
212  * @return Key stream byte
213  **/
214 
216 {
217  uint_t i;
218  uint8_t ks;
219 
220  //Initialize value
221  ks = 0;
222 
223  //Generate 8 bits of key stream
224  for(i = 0; i < 8; i++)
225  {
226  ks |= triviumGenerateBit(context) << i;
227  }
228 
229  //Return one byte of key stream
230  return ks;
231 }
232 
233 
234 /**
235  * @brief Release Trivium context
236  * @param[in] context Pointer to the Trivium context
237  **/
238 
240 {
241  //Clear Trivium context
242  osMemset(context, 0, sizeof(TriviumContext));
243 }
244 
245 #endif
unsigned int uint_t
Definition: compiler_port.h:50
uint8_t reverseInt8(uint8_t value)
Reverse bit order in a byte.
Definition: cpu_endian.c:90
General definitions for cryptographic algorithms.
uint32_t t1
uint32_t t2
uint8_t z
Definition: dns_common.h:191
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t iv[]
Definition: ike.h:1502
#define osMemset(p, value, length)
Definition: os_port.h:135
Trivium algorithm context.
Definition: trivium.h:48
uint8_t s[36]
Definition: trivium.h:49
uint8_t length
Definition: tcp.h:368
#define TRIVIUM_SET_BIT(s, n, v)
Definition: trivium.c:45
uint8_t triviumGenerateBit(TriviumContext *context)
Generate one bit of key stream.
Definition: trivium.c:154
uint8_t triviumGenerateByte(TriviumContext *context)
Generate one byte of key stream.
Definition: trivium.c:215
void triviumCipher(TriviumContext *context, const uint8_t *input, uint8_t *output, size_t length)
Encrypt/decrypt data with the Trivium algorithm.
Definition: trivium.c:117
#define TRIVIUM_GET_BIT(s, n)
Definition: trivium.c:42
void triviumDeinit(TriviumContext *context)
Release Trivium context.
Definition: trivium.c:239
error_t triviumInit(TriviumContext *context, const uint8_t *key, size_t keyLen, const uint8_t *iv, size_t ivLen)
Initialize Trivium context using the supplied key and IV.
Definition: trivium.c:59
Trivium stream cipher.