1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file sober128.c
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Implementation of SOBER-128 by Tom St Denis.
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef SOBER128
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "sober128tab.c"
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_prng_descriptor sober128_desc =
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   "sober128", 64,
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_start,
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_add_entropy,
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_ready,
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_read,
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_done,
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_export,
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_import,
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &sober128_test
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* don't change these... */
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define N                        17
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define FOLD                      N /* how many iterations of folding to do */
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define INITKONST        0x6996c53a /* value of KONST to use during key loading */
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define KEYP                     15 /* where to insert key words */
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define FOLDP                     4 /* where to insert non-linear feedback */
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic ulong32 BYTE2WORD(unsigned char *b)
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ulong32 t;
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(t, b);
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return t;
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define WORD2BYTE(w, b) STORE32L(b, w)
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void XORWORD(ulong32 w, unsigned char *b)
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ulong32 t;
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(t, b);
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   t ^= w;
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   STORE32L(t, b);
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* give correct offset for the current position of the register,
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * where logically R[0] is at position "zero".
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define OFF(zero, i) (((zero)+(i)) % N)
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* step the LFSR */
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* After stepping, "zero" moves right one place */
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define STEP(R,z) \
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void cycle(ulong32 *R)
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 t;
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int     i;
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STEP(R,0);
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = R[0];
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 1; i < N; ++i) {
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        R[i-1] = R[i];
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    R[N-1] = t;
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Return a non-linear function of some parts of the register.
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define NLFUNC(c,z) \
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ \
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t ^= Sbox[(t >> 24) & 0xFF]; \
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = RORc(t, 8); \
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t ^= Sbox[(t >> 24) & 0xFF]; \
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = t + c->R[OFF(z,13)]; \
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic ulong32 nltap(struct sober128_prng *c)
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 t;
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    NLFUNC(c, 0);
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return t;
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Start the PRNG
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng     [out] The PRNG state to initialize
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_start(prng_state *prng)
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int                   i;
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    struct sober128_prng *c;
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(prng != NULL);
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c = &(prng->sober128);
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Register initialised to Fibonacci numbers */
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->R[0] = 1;
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->R[1] = 1;
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 2; i < N; ++i) {
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->R[i] = c->R[i-1] + c->R[i-2];
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->konst = INITKONST;
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* next add_entropy will be the key */
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->flag  = 1;
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->set   = 0;
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Save the current register state
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void s128_savestate(struct sober128_prng *c)
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < N; ++i) {
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        c->initR[i] = c->R[i];
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* initialise to previously saved register state
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void s128_reloadstate(struct sober128_prng *c)
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < N; ++i) {
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        c->R[i] = c->initR[i];
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Initialise "konst"
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void s128_genkonst(struct sober128_prng *c)
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 newkonst;
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    do {
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       cycle(c->R);
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       newkonst = nltap(c);
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    } while ((newkonst & 0xFF000000) == 0);
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c->konst = newkonst;
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Load key material into the register
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ADDKEY(k) \
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   c->R[KEYP] += (k);
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define XORNL(nl) \
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   c->R[FOLDP] ^= (nl);
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* nonlinear diffusion of register for key */
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void s128_diffuse(struct sober128_prng *c)
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 t;
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* relies on FOLD == N == 17! */
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(0);
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(1);
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(2);
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(3);
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(4);
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(5);
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(6);
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(7);
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(8);
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(9);
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(10);
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(11);
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(12);
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(13);
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(14);
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(15);
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    DROUND(16);
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Add entropy to the PRNG state
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param in       The data to add
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param inlen    Length of the data to add
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng     PRNG state to update
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    struct sober128_prng *c;
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32               i, k;
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(in != NULL);
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(prng != NULL);
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c = &(prng->sober128);
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (c->flag == 1) {
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* this is the first call to the add_entropy so this input is the key */
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* inlen must be multiple of 4 bytes */
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((inlen & 3) != 0) {
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return CRYPT_INVALID_KEYSIZE;
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       for (i = 0; i < inlen; i += 4) {
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           k = BYTE2WORD((unsigned char *)&in[i]);
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          ADDKEY(k);
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          cycle(c->R);
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          XORNL(nltap(c));
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* also fold in the length of the key */
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       ADDKEY(inlen);
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* now diffuse */
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       s128_diffuse(c);
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       s128_genkonst(c);
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       s128_savestate(c);
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->nbuf = 0;
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->flag = 0;
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->set  = 1;
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    } else {
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* ok we are adding an IV then... */
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       s128_reloadstate(c);
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* inlen must be multiple of 4 bytes */
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((inlen & 3) != 0) {
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return CRYPT_INVALID_KEYSIZE;
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       for (i = 0; i < inlen; i += 4) {
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           k = BYTE2WORD((unsigned char *)&in[i]);
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          ADDKEY(k);
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          cycle(c->R);
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          XORNL(nltap(c));
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* also fold in the length of the key */
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       ADDKEY(inlen);
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* now diffuse */
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       s128_diffuse(c);
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->nbuf = 0;
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Make the PRNG ready to read from
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng   The PRNG to make active
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_ready(prng_state *prng)
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* XOR pseudo-random bytes into buffer
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, out+(z*4));
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Read from the PRNG
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param out      Destination
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param outlen   Length of output
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng     The active PRNG to read from
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return Number of octets read
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectunsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng)
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   struct sober128_prng *c;
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ulong32               t, tlen;
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(out  != NULL);
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(prng != NULL);
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_VALGRIND
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   zeromem(out, outlen);
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   c = &(prng->sober128);
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   t = 0;
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   tlen = outlen;
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* handle any previously buffered bytes */
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   while (c->nbuf != 0 && outlen != 0) {
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      *out++ ^= c->sbuf & 0xFF;
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->sbuf >>= 8;
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       c->nbuf -= 8;
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       --outlen;
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifndef LTC_SMALL_CODE
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* do lots at a time, if there's enough to do */
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    while (outlen >= N*4) {
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(0);
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(1);
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(2);
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(3);
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(4);
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(5);
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(6);
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(7);
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(8);
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(9);
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(10);
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(11);
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(12);
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(13);
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(14);
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(15);
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SROUND(16);
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      out    += 4*N;
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      outlen -= 4*N;
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* do small or odd size buffers the slow way */
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    while (4 <= outlen) {
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      cycle(c->R);
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      t = nltap(c);
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      XORWORD(t, out);
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      out    += 4;
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      outlen -= 4;
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* handle any trailing bytes */
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (outlen != 0) {
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      cycle(c->R);
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      c->sbuf = nltap(c);
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      c->nbuf = 32;
352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      while (c->nbuf != 0 && outlen != 0) {
353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          *out++ ^= c->sbuf & 0xFF;
354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          c->sbuf >>= 8;
355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          c->nbuf -= 8;
356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          --outlen;
357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return tlen;
361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Terminate the PRNG
365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng   The PRNG to terminate
366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_done(prng_state *prng)
369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(prng != NULL);
371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Export the PRNG state
376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param out       [out] Destination
377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param outlen    [in/out] Max size and resulting size of the state
378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng      The PRNG to export
379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(outlen != NULL);
384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(out    != NULL);
385f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(prng   != NULL);
386f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
387f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*outlen < 64) {
388f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      *outlen = 64;
389f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_BUFFER_OVERFLOW;
390f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
391f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
392f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (sober128_read(out, 64, prng) != 64) {
393f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_ERROR_READPRNG;
394f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
395f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   *outlen = 64;
396f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
397f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
398f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
399f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
400f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
401f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Import a PRNG state
402f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param in       The PRNG state
403f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param inlen    Size of the state
404f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param prng     The PRNG to import
405f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
406f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
407f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
408f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
409f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int err;
410f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(in   != NULL);
411f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(prng != NULL);
412f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
413f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (inlen != 64) {
414f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_ARG;
415f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
416f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
417f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((err = sober128_start(prng)) != CRYPT_OK) {
418f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return err;
419f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
420f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) {
421f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return err;
422f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
423f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return sober128_ready(prng);
424f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
425f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
426f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
427f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  PRNG self-test
428f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
429f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
430f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sober128_test(void)
431f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
432f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifndef LTC_TEST
433f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_NOP;
434f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
435f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   static const struct {
436f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     int keylen, ivlen, len;
437f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     unsigned char key[16], iv[4], out[20];
438f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } tests[] = {
439f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
440f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
441f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   16, 4, 20,
442f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
443f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* key */
444f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79,
445f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 },
446f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
447f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* IV */
448f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00 },
449f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
450f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* expected output */
451f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d,
452f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2,
453f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     0x40, 0x37, 0x8b, 0xbb }
454f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
455f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
456f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
457f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   prng_state    prng;
458f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned char dst[20];
459f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int           err, x;
460f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
461f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
462f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = sober128_start(&prng)) != CRYPT_OK) {
463f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
464f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
465f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) {
466f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
467f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
468f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* add IV */
469f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) {
470f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
471f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
472f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
473f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       /* ready up */
474f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = sober128_ready(&prng)) != CRYPT_OK) {
475f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
476f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
477f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       XMEMSET(dst, 0, tests[x].len);
478f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) {
479f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return CRYPT_ERROR_READPRNG;
480f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
481f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       sober128_done(&prng);
482f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if (XMEMCMP(dst, tests[x].out, tests[x].len)) {
483f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if 0
484f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          printf("\n\nSOBER128 failed, I got:\n");
485f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]);
486f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          printf("\n");
487f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
488f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return CRYPT_FAIL_TESTVECTOR;
489f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
490f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
491f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
492f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
493f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
494f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
495f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
496f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
497f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
498f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sober128.c,v $ */
499f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.8 $ */
500f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/05 00:11:36 $ */
501