-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaes_ctr_128_prng.h
More file actions
134 lines (104 loc) · 3.99 KB
/
aes_ctr_128_prng.h
File metadata and controls
134 lines (104 loc) · 3.99 KB
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
// SPDX-FileCopyrightText: Steven Ward
// SPDX-License-Identifier: MPL-2.0
/// AES-CTR-128 PRNG
/**
* \file
* \author Steven Ward
*/
#pragma once
#include "aes128-utils.h"
#include "aes_ctr_128_prng-defaults.h"
#include <err.h>
#include <immintrin.h>
#include <stdlib.h>
#include <unistd.h>
#if defined(__cplusplus)
extern "C" {
#endif
#if !defined(AESCTR128_PRNG_NUM_KEYS)
#define AESCTR128_PRNG_NUM_KEYS DEFAULT_AESCTR128_PRNG_NUM_KEYS
#endif
#if !defined(AESCTR128_PRNG_NUM_ROUNDS_PER_KEY)
#define AESCTR128_PRNG_NUM_ROUNDS_PER_KEY DEFAULT_AESCTR128_PRNG_NUM_ROUNDS_PER_KEY
#endif
/// A PRNG that uses AES instructions
struct aes_ctr_128_prng
{
static_assert(AESCTR128_PRNG_NUM_KEYS >= 1);
static_assert(AESCTR128_PRNG_NUM_ROUNDS_PER_KEY >= 1);
static_assert(AESCTR128_PRNG_NUM_KEYS * AESCTR128_PRNG_NUM_ROUNDS_PER_KEY >= 3,
"must do at least 3 rounds of AES enc/dec");
__m128i keys[AESCTR128_PRNG_NUM_KEYS];
__m128i ctr; ///< The state/counter
};
typedef struct aes_ctr_128_prng aes_ctr_128_prng;
static_assert(sizeof(aes_ctr_128_prng) <= 256,
"getentropy will fail if more than 256 bytes are requested");
/// Assign random bytes to the data members via \c getentropy.
/**
* \note This function terminates the calling process upon catastrophic error.
*/
static void
aes_ctr_128_prng_reseed(aes_ctr_128_prng* this_)
{
if (getentropy(this_, sizeof(*this_)) < 0)
err(EXIT_FAILURE, "getentropy");
}
/*
* The counter increment \c inc used in all \c _next functions forms a Weyl sequence.
* Criteria for its 32-bit lane values:
* 1) Must be odd
* 2) Must be unique across lanes
* 3) Should have half the bits set
*
* Its values were generated by the script `patterned_primes.py`.
*
* \sa https://en.wikipedia.org/wiki/Weyl_sequence#In_computing
*/
/// Get the next PRNG output via AES encryption.
static inline __m128i
aes_ctr_128_prng_enc_next(aes_ctr_128_prng* this_)
{
// most significant elem first
const __m128i inc = _mm_set_epi32(0x4a535aab, 0x55952d55, 0x6accb295, 0xad659529); // NOLINT(cppcoreguidelines-narrowing-conversions)
const __m128i dst = aes128_enc(this_->ctr, this_->keys, AESCTR128_PRNG_NUM_KEYS,
AESCTR128_PRNG_NUM_ROUNDS_PER_KEY);
this_->ctr = _mm_add_epi32(this_->ctr, inc);
return dst;
}
/// Get the next PRNG output via AES decryption.
static inline __m128i
aes_ctr_128_prng_dec_next(aes_ctr_128_prng* this_)
{
// most significant elem first
const __m128i inc = _mm_set_epi32(0x4a535aab, 0x55952d55, 0x6accb295, 0xad659529); // NOLINT(cppcoreguidelines-narrowing-conversions)
const __m128i dst = aes128_dec(this_->ctr, this_->keys, AESCTR128_PRNG_NUM_KEYS,
AESCTR128_PRNG_NUM_ROUNDS_PER_KEY);
this_->ctr = _mm_add_epi32(this_->ctr, inc);
return dst;
}
/// Get the next PRNG output via AES encryption and Davies-Meyer single-block-length compression function.
static inline __m128i
aes_ctr_128_prng_enc_davies_meyer_next(aes_ctr_128_prng* this_)
{
// most significant elem first
const __m128i inc = _mm_set_epi32(0x4a535aab, 0x55952d55, 0x6accb295, 0xad659529); // NOLINT(cppcoreguidelines-narrowing-conversions)
const __m128i dst = aes128_enc_davies_meyer(this_->ctr, this_->keys,
AESCTR128_PRNG_NUM_KEYS, AESCTR128_PRNG_NUM_ROUNDS_PER_KEY);
this_->ctr = _mm_add_epi32(this_->ctr, inc);
return dst;
}
/// Get the next PRNG output via AES decryption and Davies-Meyer single-block-length compression function.
static inline __m128i
aes_ctr_128_prng_dec_davies_meyer_next(aes_ctr_128_prng* this_)
{
// most significant elem first
const __m128i inc = _mm_set_epi32(0x4a535aab, 0x55952d55, 0x6accb295, 0xad659529); // NOLINT(cppcoreguidelines-narrowing-conversions)
const __m128i dst = aes128_dec_davies_meyer(this_->ctr, this_->keys,
AESCTR128_PRNG_NUM_KEYS, AESCTR128_PRNG_NUM_ROUNDS_PER_KEY);
this_->ctr = _mm_add_epi32(this_->ctr, inc);
return dst;
}
#if defined(__cplusplus)
}
#endif