LTC sync pr/stream_rc4_sober128
Karel Miko
7 years ago
9 | 9 | - maybe: switch yarrow > fortuna for Crypt::PK::* |
10 | 10 | - maybe: add encode_b32/decode_b32 |
11 | 11 | - maybe: x509_rsa_pubkey + x509_rsa_pubkey_alg |
12 | ||
13 | 0.048 2017/04/XX | |
14 | - NEW: Crypt::Digest::SHA3_224 | |
15 | - NEW: Crypt::Digest::SHA3_256 | |
16 | - NEW: Crypt::Digest::SHA3_384 | |
17 | - NEW: Crypt::Digest::SHA3_512 | |
18 | - NEW: Crypt::AuthEnc::ChaCha20Poly1305 | |
19 | - NEW: Crypt::Mac::Poly1305 | |
20 | - NEW: Crypt::Stream::ChaCha | |
21 | - NEW: Crypt::Stream::RC4 | |
22 | - NEW: Crypt::Stream::Sober128 | |
12 | 23 | |
13 | 24 | 0.047 2017/04/05 |
14 | 25 | - fix #32 Compile "ar" step fails when Perl built with -flto (better version) |
342 | 342 | if(chc_register(find_cipher("aes"))==-1) { croak("FATAL: chc_register failed"); } |
343 | 343 | /* --- */ |
344 | 344 | if(register_prng(&fortuna_desc)==-1) { croak("FATAL: cannot register_prng fortuna"); } |
345 | if(register_prng(&rc4_desc)==-1) { croak("FATAL: cannot register_prng rc4"); } | |
346 | if(register_prng(&sober128_desc)==-1) { croak("FATAL: cannot register_prng sober128"); } | |
347 | 345 | if(register_prng(&yarrow_desc)==-1) { croak("FATAL: cannot register_prng yarrow"); } |
346 | if(register_prng(&rc4_prng_desc)==-1) { croak("FATAL: cannot register_prng rc4"); } | |
347 | if(register_prng(&sober128_prng_desc)==-1) { croak("FATAL: cannot register_prng sober128"); } | |
348 | if(register_prng(&chacha20_prng_desc)==-1) { croak("FATAL: cannot register_prng chacha20"); } | |
348 | 349 | /* --- */ |
349 | 350 | #ifdef TFM_DESC |
350 | 351 | ltc_mp = tfm_desc; |
3 | 3 | ltc/ciphers/safer/saferp.o ltc/ciphers/skipjack.o ltc/ciphers/twofish/twofish.o ltc/ciphers/xtea.o \ |
4 | 4 | ltc/stream/chacha/chacha_crypt.o ltc/stream/chacha/chacha_done.o ltc/stream/chacha/chacha_ivctr32.o \ |
5 | 5 | ltc/stream/chacha/chacha_ivctr64.o ltc/stream/chacha/chacha_keystream.o ltc/stream/chacha/chacha_setup.o \ |
6 | ltc/stream/rc4/rc4.o ltc/stream/sober128/sober128.o \ | |
6 | 7 | ltc/encauth/chachapoly/chacha20poly1305_add_aad.o ltc/encauth/chachapoly/chacha20poly1305_decrypt.o \ |
7 | 8 | ltc/encauth/chachapoly/chacha20poly1305_done.o ltc/encauth/chachapoly/chacha20poly1305_encrypt.o \ |
8 | 9 | ltc/encauth/chachapoly/chacha20poly1305_init.o ltc/encauth/chachapoly/chacha20poly1305_memory.o \ |
3 | 3 | ltc/ciphers/safer/saferp.obj ltc/ciphers/skipjack.obj ltc/ciphers/twofish/twofish.obj ltc/ciphers/xtea.obj \ |
4 | 4 | ltc/stream/chacha/chacha_crypt.obj ltc/stream/chacha/chacha_done.obj ltc/stream/chacha/chacha_ivctr32.obj \ |
5 | 5 | ltc/stream/chacha/chacha_ivctr64.obj ltc/stream/chacha/chacha_keystream.obj ltc/stream/chacha/chacha_setup.obj \ |
6 | ltc/stream/rc4/rc4.o ltc/stream/sober128/sober128.o \ | |
6 | 7 | ltc/encauth/chachapoly/chacha20poly1305_add_aad.obj ltc/encauth/chachapoly/chacha20poly1305_decrypt.obj \ |
7 | 8 | ltc/encauth/chachapoly/chacha20poly1305_done.obj ltc/encauth/chachapoly/chacha20poly1305_encrypt.obj \ |
8 | 9 | ltc/encauth/chachapoly/chacha20poly1305_init.obj ltc/encauth/chachapoly/chacha20poly1305_memory.obj \ |
191 | 191 | #define LTC_KASUMI |
192 | 192 | #define LTC_MULTI2 |
193 | 193 | #define LTC_CAMELLIA |
194 | /* ChaCha is special (a stream cipher) */ | |
194 | ||
195 | /* stream ciphers */ | |
195 | 196 | #define LTC_CHACHA |
197 | #define LTC_RC4 | |
198 | #define LTC_SOBER128 | |
196 | 199 | |
197 | 200 | #endif /* LTC_NO_CIPHERS */ |
198 | 201 | |
293 | 296 | /* a PRNG that simply reads from an available system source */ |
294 | 297 | #define LTC_SPRNG |
295 | 298 | |
296 | /* The LTC_RC4 stream cipher */ | |
297 | #define LTC_RC4 | |
299 | /* The LTC_RC4 stream cipher based PRNG */ | |
300 | #define LTC_RC4_PRNG | |
298 | 301 | |
299 | 302 | /* The ChaCha20 stream cipher based PRNG */ |
300 | 303 | #define LTC_CHACHA20_PRNG |
302 | 305 | /* Fortuna PRNG */ |
303 | 306 | #define LTC_FORTUNA |
304 | 307 | |
305 | /* Greg's LTC_SOBER128 PRNG ;-0 */ | |
306 | #define LTC_SOBER128 | |
308 | /* Greg's SOBER128 stream cipher based PRNG */ | |
309 | #define LTC_SOBER128_PRNG | |
307 | 310 | |
308 | 311 | /* the *nix style /dev/random device */ |
309 | 312 | #define LTC_DEVRANDOM |
549 | 552 | #error LTC_CHACHA20_PRNG requires LTC_CHACHA |
550 | 553 | #endif |
551 | 554 | |
555 | #if defined(LTC_RC4_PRNG) && !defined(LTC_RC4) | |
556 | #error LTC_RC4_PRNG requires LTC_RC4 | |
557 | #endif | |
558 | ||
559 | #if defined(LTC_SOBER128_PRNG) && !defined(LTC_SOBER128) | |
560 | #error LTC_SOBER128_PRNG requires LTC_SOBER128 | |
561 | #endif | |
562 | ||
552 | 563 | /* THREAD management */ |
553 | 564 | #ifdef LTC_PTHREAD |
554 | 565 |
9 | 9 | |
10 | 10 | #ifdef LTC_RC4 |
11 | 11 | struct rc4_prng { |
12 | int x, y; | |
13 | unsigned char buf[256]; | |
12 | rc4_state s; | |
13 | short ready; | |
14 | 14 | }; |
15 | 15 | #endif |
16 | 16 | |
43 | 43 | |
44 | 44 | #ifdef LTC_SOBER128 |
45 | 45 | struct sober128_prng { |
46 | ulong32 R[17], /* Working storage for the shift register */ | |
47 | initR[17], /* saved register contents */ | |
48 | konst, /* key dependent constant */ | |
49 | sbuf; /* partial word encryption buffer */ | |
50 | ||
51 | int nbuf, /* number of part-word stream bits buffered */ | |
52 | flag, /* first add_entropy call or not? */ | |
53 | set; /* did we call add_entropy to set key? */ | |
54 | ||
46 | sober128_state s; /* sober128 state */ | |
47 | unsigned char ent[40]; /* entropy buffer */ | |
48 | unsigned long idx; /* entropy counter */ | |
49 | short ready; /* ready flag 0-1 */ | |
55 | 50 | }; |
56 | 51 | #endif |
57 | 52 | |
154 | 149 | #endif |
155 | 150 | |
156 | 151 | #ifdef LTC_RC4 |
157 | int rc4_start(prng_state *prng); | |
158 | int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
159 | int rc4_ready(prng_state *prng); | |
160 | unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
152 | int rc4_prng_start(prng_state *prng); | |
153 | int rc4_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
154 | int rc4_prng_ready(prng_state *prng); | |
155 | unsigned long rc4_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
161 | 156 | int rc4_prng_done(prng_state *prng); |
162 | int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
163 | int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
157 | int rc4_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
158 | int rc4_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
164 | 159 | int rc4_prng_test(void); |
165 | extern const struct ltc_prng_descriptor rc4_desc; | |
160 | extern const struct ltc_prng_descriptor rc4_prng_desc; | |
166 | 161 | #endif |
167 | 162 | |
168 | 163 | #ifdef LTC_CHACHA20_PRNG |
190 | 185 | #endif |
191 | 186 | |
192 | 187 | #ifdef LTC_SOBER128 |
193 | int sober128_start(prng_state *prng); | |
194 | int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
195 | int sober128_ready(prng_state *prng); | |
196 | unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
188 | int sober128_prng_start(prng_state *prng); | |
189 | int sober128_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
190 | int sober128_prng_ready(prng_state *prng); | |
191 | unsigned long sober128_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
197 | 192 | int sober128_prng_done(prng_state *prng); |
198 | int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
199 | int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
193 | int sober128_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
194 | int sober128_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
200 | 195 | int sober128_prng_test(void); |
201 | extern const struct ltc_prng_descriptor sober128_desc; | |
196 | extern const struct ltc_prng_descriptor sober128_prng_desc; | |
202 | 197 | #endif |
203 | 198 | |
204 | 199 | int find_prng(const char *name); |
88 | 88 | int err; |
89 | 89 | |
90 | 90 | LTC_ARGCHK(prng != NULL); |
91 | if (prng->chacha.ready) return CRYPT_OK; | |
91 | 92 | |
92 | 93 | /* key 32 bytes, 20 rounds */ |
93 | 94 | if ((err = chacha_setup(&prng->chacha.s, prng->chacha.ent, 32, 20)) != CRYPT_OK) return err; |
109 | 110 | unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) |
110 | 111 | { |
111 | 112 | LTC_ARGCHK(prng != NULL); |
113 | if (!prng->chacha.ready) return 0; | |
112 | 114 | if (chacha_keystream(&prng->chacha.s, out, outlen) != CRYPT_OK) return 0; |
113 | 115 | return outlen; |
114 | 116 | } |
120 | 122 | */ |
121 | 123 | int chacha20_prng_done(prng_state *prng) |
122 | 124 | { |
123 | LTC_ARGCHK(prng != NULL); | |
124 | return chacha_done(&prng->chacha.s); | |
125 | int err; | |
126 | ||
127 | LTC_ARGCHK(prng != NULL); | |
128 | if ((err = chacha_done(&prng->chacha.s)) != CRYPT_OK) return err; | |
129 | prng->chacha.ready = 0; | |
130 | return CRYPT_OK; | |
125 | 131 | } |
126 | 132 | |
127 | 133 | /** |
194 | 200 | chacha20_prng_add_entropy(en, sizeof(en), &st); /* add entropy to uninitialized prng */ |
195 | 201 | chacha20_prng_ready(&st); |
196 | 202 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ |
197 | if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; | |
203 | if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1) != 0) return CRYPT_FAIL_TESTVECTOR; | |
198 | 204 | chacha20_prng_read(out, 500, &st); |
199 | 205 | chacha20_prng_add_entropy(en, sizeof(en), &st); /* add entropy to already initialized prng */ |
200 | 206 | chacha20_prng_read(out, 500, &st); |
201 | 207 | chacha20_prng_export(dmp, &dmplen, &st); |
202 | 208 | chacha20_prng_read(out, 500, &st); /* skip 500 bytes */ |
203 | 209 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ |
204 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; | |
210 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; | |
205 | 211 | chacha20_prng_done(&st); |
206 | 212 | |
207 | 213 | XMEMSET(&st, 0xFF, sizeof(st)); /* just to be sure */ |
208 | 214 | chacha20_prng_import(dmp, dmplen, &st); |
209 | 215 | chacha20_prng_read(out, 500, &st); /* skip 500 bytes */ |
210 | 216 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ |
211 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; | |
217 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 3) != 0) return CRYPT_FAIL_TESTVECTOR; | |
212 | 218 | chacha20_prng_done(&st); |
213 | 219 | |
214 | 220 | return CRYPT_OK; |
16 | 16 | |
17 | 17 | #ifdef LTC_RC4 |
18 | 18 | |
19 | const struct ltc_prng_descriptor rc4_desc = | |
20 | { | |
21 | "rc4", 32, | |
22 | &rc4_start, | |
23 | &rc4_add_entropy, | |
24 | &rc4_ready, | |
25 | &rc4_read, | |
26 | &rc4_prng_done, | |
27 | &rc4_export, | |
28 | &rc4_import, | |
29 | &rc4_prng_test | |
19 | const struct ltc_prng_descriptor rc4_prng_desc = | |
20 | { | |
21 | "rc4", | |
22 | sizeof(rc4_state), | |
23 | &rc4_prng_start, | |
24 | &rc4_prng_add_entropy, | |
25 | &rc4_prng_ready, | |
26 | &rc4_prng_read, | |
27 | &rc4_prng_done, | |
28 | &rc4_prng_export, | |
29 | &rc4_prng_import, | |
30 | &rc4_prng_test | |
30 | 31 | }; |
31 | 32 | |
32 | 33 | /** |
34 | 35 | @param prng [out] The PRNG state to initialize |
35 | 36 | @return CRYPT_OK if successful |
36 | 37 | */ |
37 | int rc4_start(prng_state *prng) | |
38 | { | |
39 | LTC_ARGCHK(prng != NULL); | |
40 | ||
41 | /* set keysize to zero */ | |
42 | prng->rc4.x = 0; | |
43 | ||
44 | return CRYPT_OK; | |
38 | int rc4_prng_start(prng_state *prng) | |
39 | { | |
40 | LTC_ARGCHK(prng != NULL); | |
41 | prng->rc4.ready = 0; | |
42 | ||
43 | /* set entropy (key) size to zero */ | |
44 | prng->rc4.s.x = 0; | |
45 | /* clear entropy (key) buffer */ | |
46 | XMEMSET(&prng->rc4.s.buf, 0, 256); | |
47 | ||
48 | return CRYPT_OK; | |
45 | 49 | } |
46 | 50 | |
47 | 51 | /** |
51 | 55 | @param prng PRNG state to update |
52 | 56 | @return CRYPT_OK if successful |
53 | 57 | */ |
54 | int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
55 | { | |
56 | LTC_ARGCHK(in != NULL); | |
57 | LTC_ARGCHK(prng != NULL); | |
58 | ||
59 | /* trim as required */ | |
60 | if (prng->rc4.x + inlen > 256) { | |
61 | if (prng->rc4.x == 256) { | |
62 | /* I can't possibly accept another byte, ok maybe a mint wafer... */ | |
63 | return CRYPT_OK; | |
64 | } else { | |
65 | /* only accept part of it */ | |
66 | inlen = 256 - prng->rc4.x; | |
67 | } | |
68 | } | |
69 | ||
70 | while (inlen--) { | |
71 | prng->rc4.buf[prng->rc4.x++] = *in++; | |
72 | } | |
73 | ||
74 | return CRYPT_OK; | |
75 | ||
58 | int rc4_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
59 | { | |
60 | unsigned char buf[256]; | |
61 | unsigned long i; | |
62 | int err; | |
63 | ||
64 | LTC_ARGCHK(prng != NULL); | |
65 | LTC_ARGCHK(in != NULL); | |
66 | LTC_ARGCHK(inlen > 0); | |
67 | ||
68 | if (prng->rc4.ready) { | |
69 | /* rc4_prng_ready() was already called, do "rekey" operation */ | |
70 | if ((err = rc4_keystream(&prng->rc4.s, buf, 256)) != CRYPT_OK) return err; | |
71 | for(i = 0; i < inlen; i++) buf[i % 256] ^= in[i]; | |
72 | /* initialize RC4 */ | |
73 | if ((err = rc4_setup(&prng->rc4.s, buf, 256)) != CRYPT_OK) return err; | |
74 | /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ | |
75 | for (i = 0; i < 12; i++) rc4_keystream(&prng->rc4.s, buf, 256); | |
76 | } | |
77 | else { | |
78 | /* rc4_prng_ready() was not called yet, add entropy to the buffer */ | |
79 | while (inlen--) prng->rc4.s.buf[prng->rc4.s.x++ % 256] ^= *in++; | |
80 | } | |
81 | ||
82 | return CRYPT_OK; | |
76 | 83 | } |
77 | 84 | |
78 | 85 | /** |
80 | 87 | @param prng The PRNG to make active |
81 | 88 | @return CRYPT_OK if successful |
82 | 89 | */ |
83 | int rc4_ready(prng_state *prng) | |
84 | { | |
85 | unsigned char key[256], tmp, *s; | |
86 | int keylen, x, y, j; | |
87 | ||
88 | LTC_ARGCHK(prng != NULL); | |
89 | ||
90 | /* extract the key */ | |
91 | s = prng->rc4.buf; | |
92 | XMEMCPY(key, s, 256); | |
93 | keylen = prng->rc4.x; | |
94 | ||
95 | /* make LTC_RC4 perm and shuffle */ | |
96 | for (x = 0; x < 256; x++) { | |
97 | s[x] = x; | |
98 | } | |
99 | ||
100 | for (j = x = y = 0; x < 256; x++) { | |
101 | y = (y + prng->rc4.buf[x] + key[j++]) & 255; | |
102 | if (j == keylen) { | |
103 | j = 0; | |
104 | } | |
105 | tmp = s[x]; s[x] = s[y]; s[y] = tmp; | |
106 | } | |
107 | prng->rc4.x = 0; | |
108 | prng->rc4.y = 0; | |
109 | ||
110 | #ifdef LTC_CLEAN_STACK | |
111 | zeromem(key, sizeof(key)); | |
112 | #endif | |
113 | ||
114 | return CRYPT_OK; | |
90 | int rc4_prng_ready(prng_state *prng) | |
91 | { | |
92 | unsigned char buf[256]; | |
93 | unsigned long len; | |
94 | int err, i; | |
95 | ||
96 | LTC_ARGCHK(prng != NULL); | |
97 | if (prng->rc4.ready) return CRYPT_OK; | |
98 | ||
99 | len = MIN(prng->rc4.s.x, 256); | |
100 | if (len < 5) return CRYPT_ERROR; | |
101 | ||
102 | XMEMCPY(buf, prng->rc4.s.buf, len); | |
103 | /* initialize RC4 */ | |
104 | if ((err = rc4_setup(&prng->rc4.s, buf, len)) != CRYPT_OK) return err; | |
105 | /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ | |
106 | for (i = 0; i < 12; i++) rc4_keystream(&prng->rc4.s, buf, 256); | |
107 | prng->rc4.ready = 1; | |
108 | return CRYPT_OK; | |
115 | 109 | } |
116 | 110 | |
117 | 111 | /** |
121 | 115 | @param prng The active PRNG to read from |
122 | 116 | @return Number of octets read |
123 | 117 | */ |
124 | unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
125 | { | |
126 | unsigned char x, y, *s, tmp; | |
127 | unsigned long n; | |
128 | ||
129 | LTC_ARGCHK(out != NULL); | |
130 | LTC_ARGCHK(prng != NULL); | |
131 | ||
132 | #ifdef LTC_VALGRIND | |
133 | zeromem(out, outlen); | |
134 | #endif | |
135 | ||
136 | n = outlen; | |
137 | x = prng->rc4.x; | |
138 | y = prng->rc4.y; | |
139 | s = prng->rc4.buf; | |
140 | while (outlen--) { | |
141 | x = (x + 1) & 255; | |
142 | y = (y + s[x]) & 255; | |
143 | tmp = s[x]; s[x] = s[y]; s[y] = tmp; | |
144 | tmp = (s[x] + s[y]) & 255; | |
145 | *out++ ^= s[tmp]; | |
146 | } | |
147 | prng->rc4.x = x; | |
148 | prng->rc4.y = y; | |
149 | return n; | |
118 | unsigned long rc4_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
119 | { | |
120 | LTC_ARGCHK(prng != NULL); | |
121 | if (!prng->rc4.ready) return 0; | |
122 | if (rc4_keystream(&prng->rc4.s, out, outlen) != CRYPT_OK) return 0; | |
123 | return outlen; | |
150 | 124 | } |
151 | 125 | |
152 | 126 | /** |
156 | 130 | */ |
157 | 131 | int rc4_prng_done(prng_state *prng) |
158 | 132 | { |
159 | LTC_ARGCHK(prng != NULL); | |
133 | int err; | |
134 | ||
135 | LTC_ARGCHK(prng != NULL); | |
136 | if ((err = rc4_done(&prng->rc4.s)) != CRYPT_OK) return err; | |
137 | prng->rc4.ready = 0; | |
160 | 138 | return CRYPT_OK; |
161 | 139 | } |
162 | 140 | |
167 | 145 | @param prng The PRNG to export |
168 | 146 | @return CRYPT_OK if successful |
169 | 147 | */ |
170 | int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
171 | { | |
148 | int rc4_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
149 | { | |
150 | unsigned long len = sizeof(rc4_state); | |
151 | ||
172 | 152 | LTC_ARGCHK(outlen != NULL); |
173 | 153 | LTC_ARGCHK(out != NULL); |
174 | 154 | LTC_ARGCHK(prng != NULL); |
175 | 155 | |
176 | if (*outlen < 32) { | |
177 | *outlen = 32; | |
156 | if (!prng->rc4.ready) return CRYPT_ERROR; | |
157 | ||
158 | if (*outlen < len) { | |
159 | *outlen = len; | |
178 | 160 | return CRYPT_BUFFER_OVERFLOW; |
179 | 161 | } |
180 | ||
181 | if (rc4_read(out, 32, prng) != 32) { | |
182 | return CRYPT_ERROR_READPRNG; | |
183 | } | |
184 | *outlen = 32; | |
185 | ||
162 | XMEMCPY(out, &prng->rc4.s, len); | |
163 | *outlen = len; | |
186 | 164 | return CRYPT_OK; |
187 | 165 | } |
188 | 166 | |
193 | 171 | @param prng The PRNG to import |
194 | 172 | @return CRYPT_OK if successful |
195 | 173 | */ |
196 | int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
197 | { | |
198 | int err; | |
174 | int rc4_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
175 | { | |
199 | 176 | LTC_ARGCHK(in != NULL); |
200 | 177 | LTC_ARGCHK(prng != NULL); |
201 | 178 | |
202 | if (inlen != 32) { | |
203 | return CRYPT_INVALID_ARG; | |
204 | } | |
205 | ||
206 | if ((err = rc4_start(prng)) != CRYPT_OK) { | |
207 | return err; | |
208 | } | |
209 | return rc4_add_entropy(in, 32, prng); | |
179 | if (inlen != sizeof(rc4_state)) return CRYPT_INVALID_ARG; | |
180 | ||
181 | XMEMCPY(&prng->rc4.s, in, inlen); | |
182 | prng->rc4.ready = 1; | |
183 | return CRYPT_OK; | |
210 | 184 | } |
211 | 185 | |
212 | 186 | /** |
215 | 189 | */ |
216 | 190 | int rc4_prng_test(void) |
217 | 191 | { |
218 | #if !defined(LTC_TEST) || defined(LTC_VALGRIND) | |
192 | #ifndef LTC_TEST | |
219 | 193 | return CRYPT_NOP; |
220 | 194 | #else |
221 | static const struct { | |
222 | unsigned char key[8], pt[8], ct[8]; | |
223 | } tests[] = { | |
224 | { | |
225 | { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, | |
226 | { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, | |
227 | { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 } | |
228 | } | |
229 | }; | |
230 | prng_state prng; | |
231 | unsigned char dst[8]; | |
232 | int err, x; | |
233 | ||
234 | for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { | |
235 | if ((err = rc4_start(&prng)) != CRYPT_OK) { | |
236 | return err; | |
237 | } | |
238 | if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) { | |
239 | return err; | |
240 | } | |
241 | if ((err = rc4_ready(&prng)) != CRYPT_OK) { | |
242 | return err; | |
243 | } | |
244 | XMEMCPY(dst, tests[x].pt, 8); | |
245 | if (rc4_read(dst, 8, &prng) != 8) { | |
246 | return CRYPT_ERROR_READPRNG; | |
247 | } | |
248 | rc4_prng_done(&prng); | |
249 | if (XMEMCMP(dst, tests[x].ct, 8)) { | |
250 | #if 0 | |
251 | int y; | |
252 | printf("\n\nLTC_RC4 failed, I got:\n"); | |
253 | for (y = 0; y < 8; y++) printf("%02x ", dst[y]); | |
254 | printf("\n"); | |
195 | prng_state st; | |
196 | unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, | |
197 | 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, | |
198 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, | |
199 | 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, | |
200 | 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; | |
201 | unsigned char dmp[500]; | |
202 | unsigned long dmplen = sizeof(dmp); | |
203 | unsigned char out[1000]; | |
204 | unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 }; | |
205 | unsigned char t2[] = { 0xEC, 0x66, 0x32, 0xAF, 0xD8, 0xBD, 0x4C, 0x42, 0x1F, 0xCB }; | |
206 | ||
207 | rc4_prng_start(&st); | |
208 | rc4_prng_add_entropy(en, sizeof(en), &st); | |
209 | rc4_prng_ready(&st); | |
210 | rc4_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
211 | if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1) != 0) return CRYPT_FAIL_TESTVECTOR; | |
212 | rc4_prng_read(out, 500, &st); | |
213 | rc4_prng_export(dmp, &dmplen, &st); | |
214 | rc4_prng_read(out, 500, &st); /* skip 500 bytes */ | |
215 | rc4_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
216 | if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; | |
217 | rc4_prng_done(&st); | |
218 | ||
219 | XMEMSET(&st, 0xFF, sizeof(st)); /* just to be sure */ | |
220 | rc4_prng_import(dmp, dmplen, &st); | |
221 | rc4_prng_read(out, 500, &st); /* skip 500 bytes */ | |
222 | rc4_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
223 | if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 3) != 0) return CRYPT_FAIL_TESTVECTOR; | |
224 | rc4_prng_done(&st); | |
225 | ||
226 | return CRYPT_OK; | |
255 | 227 | #endif |
256 | return CRYPT_FAIL_TESTVECTOR; | |
257 | } | |
258 | } | |
259 | return CRYPT_OK; | |
228 | } | |
229 | ||
260 | 230 | #endif |
261 | } | |
262 | ||
263 | #endif | |
264 | ||
265 | ||
266 | /* $Source$ */ | |
267 | /* $Revision$ */ | |
268 | /* $Date$ */ |
4 | 4 | * |
5 | 5 | * The library is free for all purposes without any express |
6 | 6 | * guarantee it works. |
7 | * | |
8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org | |
9 | 7 | */ |
8 | ||
10 | 9 | #include "tomcrypt.h" |
11 | 10 | |
12 | 11 | /** |
17 | 16 | |
18 | 17 | #ifdef LTC_SOBER128 |
19 | 18 | |
20 | #define __LTC_SOBER128TAB_C__ | |
21 | #include "sober128tab.c" | |
22 | ||
23 | const struct ltc_prng_descriptor sober128_desc = | |
24 | { | |
25 | "sober128", 64, | |
26 | &sober128_start, | |
27 | &sober128_add_entropy, | |
28 | &sober128_ready, | |
29 | &sober128_read, | |
30 | &sober128_prng_done, | |
31 | &sober128_export, | |
32 | &sober128_import, | |
33 | &sober128_prng_test | |
19 | const struct ltc_prng_descriptor sober128_prng_desc = | |
20 | { | |
21 | "sober128", | |
22 | sizeof(sober128_state), | |
23 | &sober128_prng_start, | |
24 | &sober128_prng_add_entropy, | |
25 | &sober128_prng_ready, | |
26 | &sober128_prng_read, | |
27 | &sober128_prng_done, | |
28 | &sober128_prng_export, | |
29 | &sober128_prng_import, | |
30 | &sober128_prng_test | |
34 | 31 | }; |
35 | ||
36 | /* don't change these... */ | |
37 | #define N 17 | |
38 | #define FOLD N /* how many iterations of folding to do */ | |
39 | #define INITKONST 0x6996c53a /* value of KONST to use during key loading */ | |
40 | #define KEYP 15 /* where to insert key words */ | |
41 | #define FOLDP 4 /* where to insert non-linear feedback */ | |
42 | ||
43 | #define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF)) | |
44 | ||
45 | static ulong32 BYTE2WORD(unsigned char *b) | |
46 | { | |
47 | ulong32 t; | |
48 | LOAD32L(t, b); | |
49 | return t; | |
50 | } | |
51 | ||
52 | #define WORD2BYTE(w, b) STORE32L(b, w) | |
53 | ||
54 | static void XORWORD(ulong32 w, unsigned char *b) | |
55 | { | |
56 | ulong32 t; | |
57 | LOAD32L(t, b); | |
58 | t ^= w; | |
59 | STORE32L(t, b); | |
60 | } | |
61 | ||
62 | /* give correct offset for the current position of the register, | |
63 | * where logically R[0] is at position "zero". | |
64 | */ | |
65 | #define OFF(zero, i) (((zero)+(i)) % N) | |
66 | ||
67 | /* step the LFSR */ | |
68 | /* After stepping, "zero" moves right one place */ | |
69 | #define STEP(R,z) \ | |
70 | R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; | |
71 | ||
72 | static void cycle(ulong32 *R) | |
73 | { | |
74 | ulong32 t; | |
75 | int i; | |
76 | ||
77 | STEP(R,0); | |
78 | t = R[0]; | |
79 | for (i = 1; i < N; ++i) { | |
80 | R[i-1] = R[i]; | |
81 | } | |
82 | R[N-1] = t; | |
83 | } | |
84 | ||
85 | /* Return a non-linear function of some parts of the register. | |
86 | */ | |
87 | #define NLFUNC(c,z) \ | |
88 | { \ | |
89 | t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \ | |
90 | t ^= Sbox[(t >> 24) & 0xFF]; \ | |
91 | t = RORc(t, 8); \ | |
92 | t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \ | |
93 | t ^= Sbox[(t >> 24) & 0xFF]; \ | |
94 | t = t + c->R[OFF(z,13)]; \ | |
95 | } | |
96 | ||
97 | static ulong32 nltap(struct sober128_prng *c) | |
98 | { | |
99 | ulong32 t; | |
100 | NLFUNC(c, 0); | |
101 | return t; | |
102 | } | |
103 | 32 | |
104 | 33 | /** |
105 | 34 | Start the PRNG |
106 | 35 | @param prng [out] The PRNG state to initialize |
107 | 36 | @return CRYPT_OK if successful |
108 | 37 | */ |
109 | int sober128_start(prng_state *prng) | |
110 | { | |
111 | int i; | |
112 | struct sober128_prng *c; | |
113 | ||
114 | LTC_ARGCHK(prng != NULL); | |
115 | ||
116 | c = &(prng->sober128); | |
117 | ||
118 | /* Register initialised to Fibonacci numbers */ | |
119 | c->R[0] = 1; | |
120 | c->R[1] = 1; | |
121 | for (i = 2; i < N; ++i) { | |
122 | c->R[i] = c->R[i-1] + c->R[i-2]; | |
123 | } | |
124 | c->konst = INITKONST; | |
125 | ||
126 | /* next add_entropy will be the key */ | |
127 | c->flag = 1; | |
128 | c->set = 0; | |
129 | ||
130 | return CRYPT_OK; | |
131 | } | |
132 | ||
133 | /* Save the current register state | |
134 | */ | |
135 | static void s128_savestate(struct sober128_prng *c) | |
136 | { | |
137 | int i; | |
138 | for (i = 0; i < N; ++i) { | |
139 | c->initR[i] = c->R[i]; | |
140 | } | |
141 | } | |
142 | ||
143 | /* initialise to previously saved register state | |
144 | */ | |
145 | static void s128_reloadstate(struct sober128_prng *c) | |
146 | { | |
147 | int i; | |
148 | ||
149 | for (i = 0; i < N; ++i) { | |
150 | c->R[i] = c->initR[i]; | |
151 | } | |
152 | } | |
153 | ||
154 | /* Initialise "konst" | |
155 | */ | |
156 | static void s128_genkonst(struct sober128_prng *c) | |
157 | { | |
158 | ulong32 newkonst; | |
159 | ||
160 | do { | |
161 | cycle(c->R); | |
162 | newkonst = nltap(c); | |
163 | } while ((newkonst & 0xFF000000) == 0); | |
164 | c->konst = newkonst; | |
165 | } | |
166 | ||
167 | /* Load key material into the register | |
168 | */ | |
169 | #define ADDKEY(k) \ | |
170 | c->R[KEYP] += (k); | |
171 | ||
172 | #define XORNL(nl) \ | |
173 | c->R[FOLDP] ^= (nl); | |
174 | ||
175 | /* nonlinear diffusion of register for key */ | |
176 | #define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t; | |
177 | static void s128_diffuse(struct sober128_prng *c) | |
178 | { | |
179 | ulong32 t; | |
180 | /* relies on FOLD == N == 17! */ | |
181 | DROUND(0); | |
182 | DROUND(1); | |
183 | DROUND(2); | |
184 | DROUND(3); | |
185 | DROUND(4); | |
186 | DROUND(5); | |
187 | DROUND(6); | |
188 | DROUND(7); | |
189 | DROUND(8); | |
190 | DROUND(9); | |
191 | DROUND(10); | |
192 | DROUND(11); | |
193 | DROUND(12); | |
194 | DROUND(13); | |
195 | DROUND(14); | |
196 | DROUND(15); | |
197 | DROUND(16); | |
38 | int sober128_prng_start(prng_state *prng) | |
39 | { | |
40 | LTC_ARGCHK(prng != NULL); | |
41 | prng->sober128.ready = 0; | |
42 | XMEMSET(&prng->sober128.ent, 0, 40); | |
43 | prng->sober128.idx = 0; | |
44 | return CRYPT_OK; | |
198 | 45 | } |
199 | 46 | |
200 | 47 | /** |
204 | 51 | @param prng PRNG state to update |
205 | 52 | @return CRYPT_OK if successful |
206 | 53 | */ |
207 | int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
208 | { | |
209 | struct sober128_prng *c; | |
210 | ulong32 i, k; | |
211 | ||
212 | LTC_ARGCHK(in != NULL); | |
213 | LTC_ARGCHK(prng != NULL); | |
214 | c = &(prng->sober128); | |
215 | ||
216 | if (c->flag == 1) { | |
217 | /* this is the first call to the add_entropy so this input is the key */ | |
218 | /* inlen must be multiple of 4 bytes */ | |
219 | if ((inlen & 3) != 0) { | |
220 | return CRYPT_INVALID_KEYSIZE; | |
221 | } | |
222 | ||
223 | for (i = 0; i < inlen; i += 4) { | |
224 | k = BYTE2WORD((unsigned char *)&in[i]); | |
225 | ADDKEY(k); | |
226 | cycle(c->R); | |
227 | XORNL(nltap(c)); | |
228 | } | |
229 | ||
230 | /* also fold in the length of the key */ | |
231 | ADDKEY(inlen); | |
232 | ||
233 | /* now diffuse */ | |
234 | s128_diffuse(c); | |
235 | ||
236 | s128_genkonst(c); | |
237 | s128_savestate(c); | |
238 | c->nbuf = 0; | |
239 | c->flag = 0; | |
240 | c->set = 1; | |
241 | } else { | |
242 | /* ok we are adding an IV then... */ | |
243 | s128_reloadstate(c); | |
244 | ||
245 | /* inlen must be multiple of 4 bytes */ | |
246 | if ((inlen & 3) != 0) { | |
247 | return CRYPT_INVALID_KEYSIZE; | |
248 | } | |
249 | ||
250 | for (i = 0; i < inlen; i += 4) { | |
251 | k = BYTE2WORD((unsigned char *)&in[i]); | |
252 | ADDKEY(k); | |
253 | cycle(c->R); | |
254 | XORNL(nltap(c)); | |
255 | } | |
256 | ||
257 | /* also fold in the length of the key */ | |
258 | ADDKEY(inlen); | |
259 | ||
260 | /* now diffuse */ | |
261 | s128_diffuse(c); | |
262 | c->nbuf = 0; | |
263 | } | |
264 | ||
265 | return CRYPT_OK; | |
54 | int sober128_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
55 | { | |
56 | unsigned char buf[40]; | |
57 | unsigned long i; | |
58 | int err; | |
59 | ||
60 | LTC_ARGCHK(prng != NULL); | |
61 | LTC_ARGCHK(in != NULL); | |
62 | LTC_ARGCHK(inlen > 0); | |
63 | ||
64 | if (prng->sober128.ready) { | |
65 | /* sober128_prng_ready() was already called, do "rekey" operation */ | |
66 | if ((err = sober128_keystream(&prng->sober128.s, buf, 40)) != CRYPT_OK) return err; | |
67 | for(i = 0; i < inlen; i++) buf[i % 40] ^= in[i]; | |
68 | /* key 32 bytes, 20 rounds */ | |
69 | if ((err = sober128_setup(&prng->sober128.s, buf, 32)) != CRYPT_OK) return err; | |
70 | /* iv 8 bytes */ | |
71 | if ((err = sober128_setiv(&prng->sober128.s, buf + 32, 8)) != CRYPT_OK) return err; | |
72 | /* clear KEY + IV */ | |
73 | XMEMSET(buf, 0, 40); | |
74 | } | |
75 | else { | |
76 | /* sober128_prng_ready() was not called yet, add entropy to ent buffer */ | |
77 | while (inlen--) prng->sober128.ent[prng->sober128.idx++ % 40] ^= *in++; | |
78 | } | |
79 | ||
80 | return CRYPT_OK; | |
266 | 81 | } |
267 | 82 | |
268 | 83 | /** |
270 | 85 | @param prng The PRNG to make active |
271 | 86 | @return CRYPT_OK if successful |
272 | 87 | */ |
273 | int sober128_ready(prng_state *prng) | |
274 | { | |
275 | return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR; | |
276 | } | |
277 | ||
278 | /* XOR pseudo-random bytes into buffer | |
279 | */ | |
280 | #define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, out+(z*4)); | |
88 | int sober128_prng_ready(prng_state *prng) | |
89 | { | |
90 | int err; | |
91 | ||
92 | LTC_ARGCHK(prng != NULL); | |
93 | if (prng->sober128.ready) return CRYPT_OK; | |
94 | ||
95 | /* key 32 bytes, 20 rounds */ | |
96 | if ((err = sober128_setup(&prng->sober128.s, prng->sober128.ent, 32)) != CRYPT_OK) return err; | |
97 | /* iv 8 bytes */ | |
98 | if ((err = sober128_setiv(&prng->sober128.s, prng->sober128.ent + 32, 8)) != CRYPT_OK) return err; | |
99 | XMEMSET(&prng->sober128.ent, 0, 40); | |
100 | prng->sober128.ready = 1; | |
101 | prng->sober128.idx = 0; | |
102 | return CRYPT_OK; | |
103 | } | |
281 | 104 | |
282 | 105 | /** |
283 | 106 | Read from the PRNG |
286 | 109 | @param prng The active PRNG to read from |
287 | 110 | @return Number of octets read |
288 | 111 | */ |
289 | unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
290 | { | |
291 | struct sober128_prng *c; | |
292 | ulong32 t, tlen; | |
293 | ||
294 | LTC_ARGCHK(out != NULL); | |
295 | LTC_ARGCHK(prng != NULL); | |
296 | ||
297 | #ifdef LTC_VALGRIND | |
298 | zeromem(out, outlen); | |
299 | #endif | |
300 | ||
301 | c = &(prng->sober128); | |
302 | tlen = outlen; | |
303 | ||
304 | /* handle any previously buffered bytes */ | |
305 | while (c->nbuf != 0 && outlen != 0) { | |
306 | *out++ ^= c->sbuf & 0xFF; | |
307 | c->sbuf >>= 8; | |
308 | c->nbuf -= 8; | |
309 | --outlen; | |
310 | } | |
311 | ||
312 | #ifndef LTC_SMALL_CODE | |
313 | /* do lots at a time, if there's enough to do */ | |
314 | while (outlen >= N*4) { | |
315 | SROUND(0); | |
316 | SROUND(1); | |
317 | SROUND(2); | |
318 | SROUND(3); | |
319 | SROUND(4); | |
320 | SROUND(5); | |
321 | SROUND(6); | |
322 | SROUND(7); | |
323 | SROUND(8); | |
324 | SROUND(9); | |
325 | SROUND(10); | |
326 | SROUND(11); | |
327 | SROUND(12); | |
328 | SROUND(13); | |
329 | SROUND(14); | |
330 | SROUND(15); | |
331 | SROUND(16); | |
332 | out += 4*N; | |
333 | outlen -= 4*N; | |
334 | } | |
335 | #endif | |
336 | ||
337 | /* do small or odd size buffers the slow way */ | |
338 | while (4 <= outlen) { | |
339 | cycle(c->R); | |
340 | t = nltap(c); | |
341 | XORWORD(t, out); | |
342 | out += 4; | |
343 | outlen -= 4; | |
344 | } | |
345 | ||
346 | /* handle any trailing bytes */ | |
347 | if (outlen != 0) { | |
348 | cycle(c->R); | |
349 | c->sbuf = nltap(c); | |
350 | c->nbuf = 32; | |
351 | while (c->nbuf != 0 && outlen != 0) { | |
352 | *out++ ^= c->sbuf & 0xFF; | |
353 | c->sbuf >>= 8; | |
354 | c->nbuf -= 8; | |
355 | --outlen; | |
356 | } | |
357 | } | |
358 | ||
359 | return tlen; | |
112 | unsigned long sober128_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
113 | { | |
114 | LTC_ARGCHK(prng != NULL); | |
115 | if (!prng->sober128.ready) return 0; | |
116 | if (sober128_keystream(&prng->sober128.s, out, outlen) != CRYPT_OK) return 0; | |
117 | return outlen; | |
360 | 118 | } |
361 | 119 | |
362 | 120 | /** |
366 | 124 | */ |
367 | 125 | int sober128_prng_done(prng_state *prng) |
368 | 126 | { |
369 | LTC_ARGCHK(prng != NULL); | |
127 | int err; | |
128 | ||
129 | LTC_ARGCHK(prng != NULL); | |
130 | if ((err = sober128_done(&prng->sober128.s)) != CRYPT_OK) return err; | |
131 | prng->sober128.ready = 0; | |
370 | 132 | return CRYPT_OK; |
371 | 133 | } |
372 | 134 | |
377 | 139 | @param prng The PRNG to export |
378 | 140 | @return CRYPT_OK if successful |
379 | 141 | */ |
380 | int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
381 | { | |
142 | int sober128_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
143 | { | |
144 | unsigned long len = sizeof(sober128_state); | |
382 | 145 | LTC_ARGCHK(outlen != NULL); |
383 | 146 | LTC_ARGCHK(out != NULL); |
384 | 147 | LTC_ARGCHK(prng != NULL); |
385 | 148 | |
386 | if (*outlen < 64) { | |
387 | *outlen = 64; | |
149 | if (!prng->sober128.ready) { | |
150 | return CRYPT_ERROR; | |
151 | } | |
152 | if (*outlen < len) { | |
153 | *outlen = len; | |
388 | 154 | return CRYPT_BUFFER_OVERFLOW; |
389 | 155 | } |
390 | ||
391 | if (sober128_read(out, 64, prng) != 64) { | |
392 | return CRYPT_ERROR_READPRNG; | |
393 | } | |
394 | *outlen = 64; | |
395 | ||
156 | XMEMCPY(out, &prng->sober128.s, len); | |
157 | *outlen = len; | |
396 | 158 | return CRYPT_OK; |
397 | 159 | } |
398 | 160 | |
403 | 165 | @param prng The PRNG to import |
404 | 166 | @return CRYPT_OK if successful |
405 | 167 | */ |
406 | int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
407 | { | |
408 | int err; | |
168 | int sober128_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
169 | { | |
170 | unsigned long len = sizeof(sober128_state); | |
409 | 171 | LTC_ARGCHK(in != NULL); |
410 | 172 | LTC_ARGCHK(prng != NULL); |
411 | 173 | |
412 | if (inlen != 64) { | |
413 | return CRYPT_INVALID_ARG; | |
414 | } | |
415 | ||
416 | if ((err = sober128_start(prng)) != CRYPT_OK) { | |
417 | return err; | |
418 | } | |
419 | if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) { | |
420 | return err; | |
421 | } | |
422 | return sober128_ready(prng); | |
174 | if (inlen != len) return CRYPT_INVALID_ARG; | |
175 | XMEMCPY(&prng->sober128.s, in, inlen); | |
176 | prng->sober128.ready = 1; | |
177 | return CRYPT_OK; | |
423 | 178 | } |
424 | 179 | |
425 | 180 | /** |
431 | 186 | #ifndef LTC_TEST |
432 | 187 | return CRYPT_NOP; |
433 | 188 | #else |
434 | static const struct { | |
435 | int keylen, ivlen, len; | |
436 | unsigned char key[16], iv[4], out[20]; | |
437 | } tests[] = { | |
438 | ||
439 | { | |
440 | 16, 4, 20, | |
441 | ||
442 | /* key */ | |
443 | { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, | |
444 | 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }, | |
445 | ||
446 | /* IV */ | |
447 | { 0x00, 0x00, 0x00, 0x00 }, | |
448 | ||
449 | /* expected output */ | |
450 | { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, | |
451 | 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, | |
452 | 0x40, 0x37, 0x8b, 0xbb } | |
453 | } | |
454 | ||
455 | }; | |
456 | prng_state prng; | |
457 | unsigned char dst[20]; | |
458 | int err, x; | |
459 | ||
460 | for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { | |
461 | if ((err = sober128_start(&prng)) != CRYPT_OK) { | |
462 | return err; | |
463 | } | |
464 | if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) { | |
465 | return err; | |
466 | } | |
467 | /* add IV */ | |
468 | if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) { | |
469 | return err; | |
470 | } | |
471 | ||
472 | /* ready up */ | |
473 | if ((err = sober128_ready(&prng)) != CRYPT_OK) { | |
474 | return err; | |
475 | } | |
476 | XMEMSET(dst, 0, tests[x].len); | |
477 | if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) { | |
478 | return CRYPT_ERROR_READPRNG; | |
479 | } | |
480 | sober128_prng_done(&prng); | |
481 | if (XMEMCMP(dst, tests[x].out, tests[x].len)) { | |
482 | #if 0 | |
483 | printf("\n\nLTC_SOBER128 failed, I got:\n"); | |
484 | for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]); | |
485 | printf("\n"); | |
189 | prng_state st; | |
190 | unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, | |
191 | 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, | |
192 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, | |
193 | 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, | |
194 | 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; | |
195 | unsigned char dmp[300]; | |
196 | unsigned long dmplen = sizeof(dmp); | |
197 | unsigned char out[500]; | |
198 | unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A }; | |
199 | unsigned char t2[] = { 0x5C, 0xD6, 0x92, 0x4E, 0xE9, 0x2F, 0xD4, 0x82, 0x16, 0xD4 }; | |
200 | ||
201 | sober128_prng_start(&st); | |
202 | sober128_prng_add_entropy(en, sizeof(en), &st); /* add entropy to uninitialized prng */ | |
203 | sober128_prng_ready(&st); | |
204 | sober128_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
205 | if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1) != 0) return CRYPT_FAIL_TESTVECTOR; | |
206 | sober128_prng_read(out, 500, &st); | |
207 | sober128_prng_add_entropy(en, sizeof(en), &st); /* add entropy to already initialized prng */ | |
208 | sober128_prng_read(out, 500, &st); | |
209 | sober128_prng_export(dmp, &dmplen, &st); | |
210 | sober128_prng_read(out, 500, &st); /* skip 500 bytes */ | |
211 | sober128_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
212 | if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; | |
213 | sober128_prng_done(&st); | |
214 | ||
215 | XMEMSET(&st, 0xFF, sizeof(st)); /* just to be sure */ | |
216 | sober128_prng_import(dmp, dmplen, &st); | |
217 | sober128_prng_read(out, 500, &st); /* skip 500 bytes */ | |
218 | sober128_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
219 | if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 3) != 0) return CRYPT_FAIL_TESTVECTOR; | |
220 | sober128_prng_done(&st); | |
221 | ||
222 | return CRYPT_OK; | |
486 | 223 | #endif |
487 | return CRYPT_FAIL_TESTVECTOR; | |
488 | } | |
489 | } | |
490 | return CRYPT_OK; | |
224 | } | |
225 | ||
491 | 226 | #endif |
492 | } | |
493 | ||
494 | #endif | |
495 | ||
496 | ||
497 | /* $Source$ */ | |
498 | /* $Revision$ */ | |
499 | /* $Date$ */ |
0 | /** | |
1 | @file sober128tab.c | |
2 | SOBER-128 Tables | |
3 | */ | |
4 | ||
5 | #ifdef __LTC_SOBER128TAB_C__ | |
6 | ||
7 | /* $ID$ */ | |
8 | /* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ | |
9 | /* Multiplication table for Turing using 0xD02B4367 */ | |
10 | static const ulong32 Multab[256] = { | |
11 | 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, | |
12 | 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, | |
13 | 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, | |
14 | 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, | |
15 | 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, | |
16 | 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, | |
17 | 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, | |
18 | 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, | |
19 | 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, | |
20 | 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, | |
21 | 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, | |
22 | 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, | |
23 | 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, | |
24 | 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, | |
25 | 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, | |
26 | 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, | |
27 | 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, | |
28 | 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, | |
29 | 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, | |
30 | 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, | |
31 | 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, | |
32 | 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, | |
33 | 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, | |
34 | 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, | |
35 | 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, | |
36 | 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, | |
37 | 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, | |
38 | 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, | |
39 | 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, | |
40 | 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, | |
41 | 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, | |
42 | 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, | |
43 | 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, | |
44 | 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, | |
45 | 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, | |
46 | 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, | |
47 | 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, | |
48 | 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, | |
49 | 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, | |
50 | 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, | |
51 | 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, | |
52 | 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, | |
53 | 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, | |
54 | 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, | |
55 | 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, | |
56 | 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, | |
57 | 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, | |
58 | 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, | |
59 | 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, | |
60 | 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, | |
61 | 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, | |
62 | 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, | |
63 | 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, | |
64 | 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, | |
65 | 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, | |
66 | 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, | |
67 | 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, | |
68 | 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, | |
69 | 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, | |
70 | 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, | |
71 | 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, | |
72 | 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, | |
73 | 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, | |
74 | 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, | |
75 | }; | |
76 | ||
77 | /* $ID$ */ | |
78 | /* Sbox for SOBER-128 */ | |
79 | /* | |
80 | * This is really the combination of two SBoxes; the least significant | |
81 | * 24 bits comes from: | |
82 | * 8->32 Sbox generated by Millan et. al. at Queensland University of | |
83 | * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, | |
84 | * "On the Design of 8*32 S-boxes". Unpublished report, by the | |
85 | * Information Systems Research Centre, | |
86 | * Queensland University of Technology, 1999. | |
87 | * | |
88 | * The most significant 8 bits are the Skipjack "F table", which can be | |
89 | * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . | |
90 | * In this optimised table, though, the intent is to XOR the word from | |
91 | * the table selected by the high byte with the input word. Thus, the | |
92 | * high byte is actually the Skipjack F-table entry XORED with its | |
93 | * table index. | |
94 | */ | |
95 | static const ulong32 Sbox[256] = { | |
96 | 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, | |
97 | 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, | |
98 | 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, | |
99 | 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, | |
100 | 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, | |
101 | 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, | |
102 | 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, | |
103 | 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, | |
104 | 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, | |
105 | 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, | |
106 | 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, | |
107 | 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, | |
108 | 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, | |
109 | 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, | |
110 | 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, | |
111 | 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, | |
112 | 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, | |
113 | 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, | |
114 | 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, | |
115 | 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, | |
116 | 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, | |
117 | 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, | |
118 | 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, | |
119 | 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, | |
120 | 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, | |
121 | 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, | |
122 | 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, | |
123 | 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, | |
124 | 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, | |
125 | 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, | |
126 | 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, | |
127 | 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, | |
128 | 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, | |
129 | 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, | |
130 | 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, | |
131 | 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, | |
132 | 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, | |
133 | 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, | |
134 | 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, | |
135 | 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, | |
136 | 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, | |
137 | 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, | |
138 | 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, | |
139 | 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, | |
140 | 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, | |
141 | 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, | |
142 | 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, | |
143 | 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, | |
144 | 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, | |
145 | 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, | |
146 | 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, | |
147 | 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, | |
148 | 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, | |
149 | 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, | |
150 | 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, | |
151 | 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, | |
152 | 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, | |
153 | 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, | |
154 | 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, | |
155 | 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, | |
156 | 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, | |
157 | 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, | |
158 | 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, | |
159 | 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, | |
160 | }; | |
161 | ||
162 | #endif /* __LTC_SOBER128TAB_C__ */ | |
163 | ||
164 | /* $Source$ */ | |
165 | /* $Revision$ */ | |
166 | /* $Date$ */ |