ASCON Suite
ascon-trng-none.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2022 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "ascon-trng.h"
24 #include <ascon/utility.h>
25 #include <string.h>
26 
27 #if defined(ASCON_TRNG_NONE)
28 
29 #if defined(HAVE_CONFIG_H)
30 #include <config.h>
31 #endif
32 #if defined(ARDUINO)
33 #include <Arduino.h>
34 #endif
35 #if defined(HAVE_TIME_H)
36 #include <time.h>
37 #endif
38 #if defined(HAVE_SYS_TIME_H)
39 #include <sys/time.h>
40 #endif
41 
42 #warning "No system random number source found"
43 #if !defined(ASCON_TRNG_MIXER)
44 #error "Mixer is required if there is no known TRNG on the system"
45 #endif
46 
47 int ascon_trng_get_bytes(unsigned char *out, size_t outlen) __attribute__((weak));
48 
60 int ascon_trng_get_bytes(unsigned char *out, size_t outlen)
61 {
62  (void)out;
63  (void)outlen;
64  return 0;
65 }
66 
67 /* Try to make the global_prng state thread-safe */
68 #if defined(HAVE_THREAD_KEYWORD)
69 #define THREAD_LOCAL __thread
70 #elif defined(HAVE_THREAD_LOCAL_KEYWORD)
71 #define THREAD_LOCAL _Thread_local
72 #else
73 #define THREAD_LOCAL
74 #endif
75 
76 /*
77  * Global PRNG that collects what little entropy we can get from timers.
78  */
79 static THREAD_LOCAL ascon_state_t global_prng;
80 static THREAD_LOCAL int volatile global_prng_initialized = 0;
81 
82 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY) || \
83  defined(HAVE_TIME)
84 
85 static void ascon_trng_add_timespec
86  (ascon_state_t *state, unsigned offset, uint32_t sec, uint32_t partial_sec)
87 {
88  uint32_t x[2];
89  x[0] = sec;
90  x[1] = partial_sec;
91  ascon_add_bytes(state, (unsigned char *)x, offset, sizeof(x));
92  ascon_clean(x, sizeof(x));
93 }
94 
95 #endif
96 
97 /* Add the current time to the PRNG state and then re-key the state */
98 static void ascon_trng_add_time(ascon_state_t *state)
99 {
100 #if defined(ARDUINO)
101  /* Add the current Arduino time as a seed to provide some extra jitter */
102  {
103  uint32_t x[2];
104  x[0] = (uint32_t)millis();
105  x[1] = (uint32_t)micros();
106  ascon_add_bytes(state, (const unsigned char *)x, 0, sizeof(x));
107  }
108 #elif defined(USE_HAL_DRIVER)
109  /* Mix in the STM32 millisecond tick counter for some extra jitter */
110  {
111  uint32_t x = HAL_GetTick();
112  ascon_add_bytes(state, (const unsigned char *)&x, 0, sizeof(x));
113  }
114 #elif defined(HAVE_CLOCK_GETTIME)
115  /* Mix in the monotonic and real times in nanoseconds */
116  {
117  struct timespec ts;
118 #if defined(CLOCK_MONOTONIC)
119  clock_gettime(CLOCK_MONOTONIC, &ts);
120  ascon_trng_add_timespec
121  (state, 0, (uint32_t)(ts.tv_sec), (uint32_t)(ts.tv_nsec));
122 #endif
123  clock_gettime(CLOCK_REALTIME, &ts);
124  ascon_trng_add_timespec
125  (state, 8, (uint32_t)(ts.tv_sec), (uint32_t)(ts.tv_nsec));
126  ascon_clean(&ts, sizeof(ts));
127  }
128 #elif defined(HAVE_GETTIMEOFDAY)
129  /* Mix in the current time of day in microseconds */
130  {
131  struct timeval tv;
132  gettimeofday(&tv, 0);
133  ascon_trng_add_timespec
134  (state, 0, (uint32_t)(tv.tv_sec), (uint32_t)(tv.tv_usec));
135  ascon_clean(&tv, sizeof(tv));
136  }
137 #elif defined(HAVE_TIME)
138  /* Mix in the current time of day in seconds (very little jitter) */
139  ascon_trng_add_timespec(state, 0, (uint32_t)time(0), 0);
140 #endif
141 
142  /* Permute the state for 6 rounds */
144 
145  /* Zero out part of the state to provide forward security */
147 
148  /* Permute the state for another 6 rounds */
150 }
151 
152 /* Squeeze data out of a PRNG */
153 static void ascon_trng_squeeze
154  (ascon_state_t *state, unsigned char *out, size_t outlen)
155 {
156  while (outlen >= 8U) {
157  ascon_extract_bytes(state, out, 0, 8);
159  out += 8;
160  outlen -= 8;
161  }
162  if (outlen > 0U) {
163  ascon_extract_bytes(state, out, 0, outlen);
165  }
166 }
167 
168 /* Make sure that the global PRNG is initialized and seeded */
169 static int ascon_trng_global_init(unsigned char seed[ASCON_SYSTEM_SEED_SIZE])
170 {
171  int ok = 0;
172 
173  /* Acquire access to the global PRNG object */
174  if (!global_prng_initialized) {
175  global_prng_initialized = 1;
176  ascon_init(&global_prng);
177  } else {
178  ascon_acquire(&global_prng);
179  }
180 
181  /* See if the application is willing to give us TRNG data */
183  ascon_add_bytes(&global_prng, seed, 8, ASCON_SYSTEM_SEED_SIZE);
184  ok = 1;
185  }
186 
187  /* Add the current time to the global PRNG and re-key */
188  ascon_trng_add_time(&global_prng);
189  return ok;
190 }
191 
192 int ascon_trng_generate(unsigned char *out, size_t outlen)
193 {
194  unsigned char seed[ASCON_SYSTEM_SEED_SIZE];
195  int ok;
196 
197  /* Re-seed and squeeze some data out of the global PRNG */
198  ok = ascon_trng_global_init(seed);
199  ascon_trng_squeeze(&global_prng, out, outlen);
200 
201  /* Re-key the global PRNG after generating the bytes */
202  ascon_overwrite_with_zeroes(&global_prng, 0, 8);
203  ascon_permute6(&global_prng);
204  ascon_release(&global_prng);
205  ascon_clean(seed, sizeof(seed));
206  return ok;
207 }
208 
209 #endif /* ASCON_TRNG_NONE */
int ascon_trng_generate(unsigned char *out, size_t outlen)
Generates a buffer of bytes from the system TRNG source.
int ascon_trng_get_bytes(unsigned char *out, size_t outlen) __attribute__((weak))
Escape hatch that allows applications to provide their own interface to the system TRNG when the libr...
#define THREAD_LOCAL
Access to the system's random number source.
#define ASCON_SYSTEM_SEED_SIZE
Number of bytes to request from the system TRNG to seed a PRNG.
Definition: ascon-trng.h:58
void ascon_overwrite_with_zeroes(ascon_state_t *state, unsigned offset, unsigned size)
Overwrites a part of the ASCON state with zeroes.
void ascon_release(ascon_state_t *state)
Temporarily releases access to any shared hardware resources that a permutation state was using.
void ascon_extract_bytes(const ascon_state_t *state, uint8_t *data, unsigned offset, unsigned size)
Extracts bytes from the ASCON state.
void ascon_add_bytes(ascon_state_t *state, const uint8_t *data, unsigned offset, unsigned size)
Adds bytes to the ASCON state by XOR'ing them with existing bytes.
void ascon_acquire(ascon_state_t *state)
Re-acquires access to any shared hardware resources that a permutation state was using.
void ascon_init(ascon_state_t *state)
Initializes the words of the ASCON permutation state to zero.
#define ascon_permute6(state)
Permutes the ASCON state with 6 rounds of the permutation.
Definition: permutation.h:213
ascon_state_t state
[snippet_key]
Definition: snippets.c:2
Structure of the internal state of the ASCON permutation.
Definition: permutation.h:63
System utilities of use to applications that use ASCON.
void ascon_clean(void *buf, unsigned size)
Cleans a buffer that contains sensitive material.
Definition: ascon-clean.c:38