LTC sync
Karel Miko
6 years ago
381 | 381 | /* --- */ |
382 | 382 | if(register_prng(&fortuna_desc)==-1) { croak("FATAL: cannot register_prng fortuna"); } |
383 | 383 | if(register_prng(&yarrow_desc)==-1) { croak("FATAL: cannot register_prng yarrow"); } |
384 | if(register_prng(&rc4_prng_desc)==-1) { croak("FATAL: cannot register_prng rc4"); } | |
385 | if(register_prng(&sober128_prng_desc)==-1) { croak("FATAL: cannot register_prng sober128"); } | |
384 | if(register_prng(&rc4_desc)==-1) { croak("FATAL: cannot register_prng rc4"); } | |
385 | if(register_prng(&sober128_desc)==-1) { croak("FATAL: cannot register_prng sober128"); } | |
386 | 386 | if(register_prng(&chacha20_prng_desc)==-1) { croak("FATAL: cannot register_prng chacha20"); } |
387 | 387 | /* --- */ |
388 | 388 | #ifdef TFM_DESC |
13 | 13 | Newz(0, RETVAL, 1, struct rc4_struct); |
14 | 14 | if (!RETVAL) croak("FATAL: Newz failed"); |
15 | 15 | |
16 | rv = rc4_setup(&RETVAL->state, k, (unsigned long)k_len); | |
17 | if (rv != CRYPT_OK) croak("FATAL: rc4_setup failed: %s", error_to_string(rv)); | |
16 | rv = rc4_stream_setup(&RETVAL->state, k, (unsigned long)k_len); | |
17 | if (rv != CRYPT_OK) croak("FATAL: rc4_stream_setup failed: %s", error_to_string(rv)); | |
18 | 18 | } |
19 | 19 | OUTPUT: |
20 | 20 | RETVAL |
22 | 22 | void |
23 | 23 | DESTROY(Crypt::Stream::RC4 self) |
24 | 24 | CODE: |
25 | rc4_done(&self->state); | |
25 | rc4_stream_done(&self->state); | |
26 | 26 | Safefree(self); |
27 | 27 | |
28 | 28 | Crypt::Stream::RC4 |
45 | 45 | SvPOK_only(RETVAL); |
46 | 46 | SvCUR_set(RETVAL, out_len); |
47 | 47 | out_data = (unsigned char *)SvPV_nolen(RETVAL); |
48 | rv = rc4_keystream(&self->state, out_data, out_len); | |
49 | if (rv != CRYPT_OK) croak("FATAL: rc4_keystream failed: %s", error_to_string(rv)); | |
48 | rv = rc4_stream_keystream(&self->state, out_data, out_len); | |
49 | if (rv != CRYPT_OK) croak("FATAL: rc4_stream_keystream failed: %s", error_to_string(rv)); | |
50 | 50 | } |
51 | 51 | OUTPUT: |
52 | 52 | RETVAL |
68 | 68 | SvPOK_only(RETVAL); |
69 | 69 | SvCUR_set(RETVAL, in_data_len); |
70 | 70 | out_data = (unsigned char *)SvPV_nolen(RETVAL); |
71 | rv = rc4_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data); | |
72 | if (rv != CRYPT_OK) croak("FATAL: rc4_crypt failed: %s", error_to_string(rv)); | |
71 | rv = rc4_stream_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data); | |
72 | if (rv != CRYPT_OK) croak("FATAL: rc4_stream_crypt failed: %s", error_to_string(rv)); | |
73 | 73 | } |
74 | 74 | } |
75 | 75 | OUTPUT: |
15 | 15 | Newz(0, RETVAL, 1, struct sober128_struct); |
16 | 16 | if (!RETVAL) croak("FATAL: Newz failed"); |
17 | 17 | |
18 | rv = sober128_setup(&RETVAL->state, k, (unsigned long)k_len); | |
19 | if (rv != CRYPT_OK) croak("FATAL: sober128_setup failed: %s", error_to_string(rv)); | |
18 | rv = sober128_stream_setup(&RETVAL->state, k, (unsigned long)k_len); | |
19 | if (rv != CRYPT_OK) croak("FATAL: sober128_stream_setup failed: %s", error_to_string(rv)); | |
20 | 20 | |
21 | rv = sober128_setiv(&RETVAL->state, iv, (unsigned long)iv_len); | |
22 | if (rv != CRYPT_OK) croak("FATAL: sober128_setiv failed: %s", error_to_string(rv)); | |
21 | rv = sober128_stream_setiv(&RETVAL->state, iv, (unsigned long)iv_len); | |
22 | if (rv != CRYPT_OK) croak("FATAL: sober128_stream_setiv failed: %s", error_to_string(rv)); | |
23 | 23 | } |
24 | 24 | OUTPUT: |
25 | 25 | RETVAL |
27 | 27 | void |
28 | 28 | DESTROY(Crypt::Stream::Sober128 self) |
29 | 29 | CODE: |
30 | sober128_done(&self->state); | |
30 | sober128_stream_done(&self->state); | |
31 | 31 | Safefree(self); |
32 | 32 | |
33 | 33 | Crypt::Stream::Sober128 |
50 | 50 | SvPOK_only(RETVAL); |
51 | 51 | SvCUR_set(RETVAL, out_len); |
52 | 52 | out_data = (unsigned char *)SvPV_nolen(RETVAL); |
53 | rv = sober128_keystream(&self->state, out_data, out_len); | |
54 | if (rv != CRYPT_OK) croak("FATAL: sober128_keystream failed: %s", error_to_string(rv)); | |
53 | rv = sober128_stream_keystream(&self->state, out_data, out_len); | |
54 | if (rv != CRYPT_OK) croak("FATAL: sober128_stream_keystream failed: %s", error_to_string(rv)); | |
55 | 55 | } |
56 | 56 | OUTPUT: |
57 | 57 | RETVAL |
73 | 73 | SvPOK_only(RETVAL); |
74 | 74 | SvCUR_set(RETVAL, in_data_len); |
75 | 75 | out_data = (unsigned char *)SvPV_nolen(RETVAL); |
76 | rv = sober128_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data); | |
77 | if (rv != CRYPT_OK) croak("FATAL: sober128_crypt failed: %s", error_to_string(rv)); | |
76 | rv = sober128_stream_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data); | |
77 | if (rv != CRYPT_OK) croak("FATAL: sober128_stream_crypt failed: %s", error_to_string(rv)); | |
78 | 78 | } |
79 | 79 | } |
80 | 80 | OUTPUT: |
26 | 26 | int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) |
27 | 27 | { |
28 | 28 | hash_state md; |
29 | unsigned char buf[512]; | |
29 | unsigned char *buf; | |
30 | 30 | size_t x; |
31 | 31 | int err; |
32 | 32 | |
34 | 34 | LTC_ARGCHK(outlen != NULL); |
35 | 35 | LTC_ARGCHK(in != NULL); |
36 | 36 | |
37 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
38 | return CRYPT_MEM; | |
39 | } | |
40 | ||
37 | 41 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { |
38 | return err; | |
42 | goto LBL_ERR; | |
39 | 43 | } |
40 | 44 | |
41 | 45 | if (*outlen < hash_descriptor[hash].hashsize) { |
42 | 46 | *outlen = hash_descriptor[hash].hashsize; |
43 | return CRYPT_BUFFER_OVERFLOW; | |
47 | err = CRYPT_BUFFER_OVERFLOW; | |
48 | goto LBL_ERR; | |
44 | 49 | } |
45 | 50 | if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) { |
46 | return err; | |
51 | goto LBL_ERR; | |
47 | 52 | } |
48 | 53 | |
49 | 54 | *outlen = hash_descriptor[hash].hashsize; |
50 | 55 | do { |
51 | x = fread(buf, 1, sizeof(buf), in); | |
56 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
52 | 57 | if ((err = hash_descriptor[hash].process(&md, buf, (unsigned long)x)) != CRYPT_OK) { |
53 | return err; | |
58 | goto LBL_CLEANBUF; | |
54 | 59 | } |
55 | } while (x == sizeof(buf)); | |
60 | } while (x == LTC_FILE_READ_BUFSIZE); | |
56 | 61 | err = hash_descriptor[hash].done(&md, out); |
57 | 62 | |
58 | #ifdef LTC_CLEAN_STACK | |
59 | zeromem(buf, sizeof(buf)); | |
60 | #endif | |
63 | LBL_CLEANBUF: | |
64 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
65 | LBL_ERR: | |
66 | XFREE(buf); | |
61 | 67 | return err; |
62 | 68 | } |
63 | 69 | #endif /* #ifndef LTC_NO_FILE */ |
958 | 958 | |
959 | 959 | #endif /* LTC_CHACHA */ |
960 | 960 | |
961 | #ifdef LTC_RC4 | |
962 | ||
963 | typedef struct { | |
964 | int x, y; | |
961 | #ifdef LTC_RC4_STREAM | |
962 | ||
963 | typedef struct { | |
964 | unsigned int x, y; | |
965 | 965 | unsigned char buf[256]; |
966 | 966 | } rc4_state; |
967 | 967 | |
968 | int rc4_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); | |
969 | int rc4_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); | |
970 | int rc4_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); | |
971 | int rc4_done(rc4_state *st); | |
972 | int rc4_test(void); | |
973 | ||
974 | #endif /* LTC_RC4 */ | |
975 | ||
976 | #ifdef LTC_SOBER128 | |
968 | int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); | |
969 | int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); | |
970 | int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); | |
971 | int rc4_stream_done(rc4_state *st); | |
972 | int rc4_stream_test(void); | |
973 | ||
974 | #endif /* LTC_RC4_STREAM */ | |
975 | ||
976 | #ifdef LTC_SOBER128_STREAM | |
977 | 977 | |
978 | 978 | typedef struct { |
979 | 979 | ulong32 R[17], /* Working storage for the shift register */ |
983 | 983 | int nbuf; /* number of part-word stream bits buffered */ |
984 | 984 | } sober128_state; |
985 | 985 | |
986 | int sober128_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); | |
987 | int sober128_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); | |
988 | int sober128_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); | |
989 | int sober128_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); | |
990 | int sober128_done(sober128_state *st); | |
991 | int sober128_test(void); | |
992 | ||
993 | #endif /* LTC_SOBER128 */ | |
986 | int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); | |
987 | int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); | |
988 | int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); | |
989 | int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); | |
990 | int sober128_stream_done(sober128_state *st); | |
991 | int sober128_stream_test(void); | |
992 | ||
993 | #endif /* LTC_SOBER128_STREAM */ | |
994 | 994 | |
995 | 995 | /* $Source$ */ |
996 | 996 | /* $Revision$ */ |
194 | 194 | |
195 | 195 | /* stream ciphers */ |
196 | 196 | #define LTC_CHACHA |
197 | #define LTC_RC4 | |
198 | #define LTC_SOBER128 | |
197 | #define LTC_RC4_STREAM | |
198 | #define LTC_SOBER128_STREAM | |
199 | 199 | |
200 | 200 | #endif /* LTC_NO_CIPHERS */ |
201 | 201 | |
301 | 301 | #define LTC_SPRNG |
302 | 302 | |
303 | 303 | /* The RC4 stream cipher based PRNG */ |
304 | #define LTC_RC4_PRNG | |
304 | #define LTC_RC4 | |
305 | 305 | |
306 | 306 | /* The ChaCha20 stream cipher based PRNG */ |
307 | 307 | #define LTC_CHACHA20_PRNG |
310 | 310 | #define LTC_FORTUNA |
311 | 311 | |
312 | 312 | /* Greg's SOBER128 stream cipher based PRNG */ |
313 | #define LTC_SOBER128_PRNG | |
313 | #define LTC_SOBER128 | |
314 | 314 | |
315 | 315 | /* the *nix style /dev/random device */ |
316 | 316 | #define LTC_DEVRANDOM |
556 | 556 | #error LTC_CHACHA20_PRNG requires LTC_CHACHA |
557 | 557 | #endif |
558 | 558 | |
559 | #if defined(LTC_RC4_PRNG) && !defined(LTC_RC4) | |
560 | #error LTC_RC4_PRNG requires LTC_RC4 | |
561 | #endif | |
562 | ||
563 | #if defined(LTC_SOBER128_PRNG) && !defined(LTC_SOBER128) | |
564 | #error LTC_SOBER128_PRNG requires LTC_SOBER128 | |
559 | #if defined(LTC_RC4) && !defined(LTC_RC4_STREAM) | |
560 | #error LTC_RC4 requires LTC_RC4_STREAM | |
561 | #endif | |
562 | ||
563 | #if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM) | |
564 | #error LTC_SOBER128 requires LTC_SOBER128_STREAM | |
565 | 565 | #endif |
566 | 566 | |
567 | 567 | #if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S) |
3 | 3 | int cipher, hash; |
4 | 4 | unsigned char pool[MAXBLOCKSIZE]; |
5 | 5 | symmetric_CTR ctr; |
6 | LTC_MUTEX_TYPE(prng_lock) | |
7 | 6 | }; |
8 | 7 | #endif |
9 | 8 | |
10 | 9 | #ifdef LTC_RC4 |
11 | 10 | struct rc4_prng { |
12 | 11 | rc4_state s; |
13 | short ready; | |
14 | 12 | }; |
15 | 13 | #endif |
16 | 14 | |
19 | 17 | chacha_state s; /* chacha state */ |
20 | 18 | unsigned char ent[40]; /* entropy buffer */ |
21 | 19 | unsigned long idx; /* entropy counter */ |
22 | short ready; /* ready flag 0-1 */ | |
23 | 20 | }; |
24 | 21 | #endif |
25 | 22 | |
37 | 34 | wd; |
38 | 35 | |
39 | 36 | ulong64 reset_cnt; /* number of times we have reset */ |
40 | LTC_MUTEX_TYPE(prng_lock) | |
41 | 37 | }; |
42 | 38 | #endif |
43 | 39 | |
46 | 42 | sober128_state s; /* sober128 state */ |
47 | 43 | unsigned char ent[40]; /* entropy buffer */ |
48 | 44 | unsigned long idx; /* entropy counter */ |
49 | short ready; /* ready flag 0-1 */ | |
50 | }; | |
51 | #endif | |
52 | ||
53 | typedef union Prng_state { | |
54 | char dummy[1]; | |
45 | }; | |
46 | #endif | |
47 | ||
48 | typedef struct { | |
49 | union { | |
50 | char dummy[1]; | |
55 | 51 | #ifdef LTC_YARROW |
56 | struct yarrow_prng yarrow; | |
52 | struct yarrow_prng yarrow; | |
57 | 53 | #endif |
58 | 54 | #ifdef LTC_RC4 |
59 | struct rc4_prng rc4; | |
55 | struct rc4_prng rc4; | |
60 | 56 | #endif |
61 | 57 | #ifdef LTC_CHACHA20_PRNG |
62 | struct chacha20_prng chacha; | |
58 | struct chacha20_prng chacha; | |
63 | 59 | #endif |
64 | 60 | #ifdef LTC_FORTUNA |
65 | struct fortuna_prng fortuna; | |
61 | struct fortuna_prng fortuna; | |
66 | 62 | #endif |
67 | 63 | #ifdef LTC_SOBER128 |
68 | struct sober128_prng sober128; | |
69 | #endif | |
64 | struct sober128_prng sober128; | |
65 | #endif | |
66 | }; | |
67 | short ready; /* ready flag 0-1 */ | |
68 | LTC_MUTEX_TYPE(lock); /* lock */ | |
70 | 69 | } prng_state; |
71 | 70 | |
72 | 71 | /** PRNG descriptor */ |
149 | 148 | #endif |
150 | 149 | |
151 | 150 | #ifdef LTC_RC4 |
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); | |
156 | int rc4_prng_done(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); | |
159 | int rc4_prng_test(void); | |
160 | extern const struct ltc_prng_descriptor rc4_prng_desc; | |
151 | int rc4_start(prng_state *prng); | |
152 | int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
153 | int rc4_ready(prng_state *prng); | |
154 | unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
155 | int rc4_done(prng_state *prng); | |
156 | int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
157 | int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
158 | int rc4_test(void); | |
159 | extern const struct ltc_prng_descriptor rc4_desc; | |
161 | 160 | #endif |
162 | 161 | |
163 | 162 | #ifdef LTC_CHACHA20_PRNG |
185 | 184 | #endif |
186 | 185 | |
187 | 186 | #ifdef LTC_SOBER128 |
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); | |
192 | int sober128_prng_done(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); | |
195 | int sober128_prng_test(void); | |
196 | extern const struct ltc_prng_descriptor sober128_prng_desc; | |
187 | int sober128_start(prng_state *prng); | |
188 | int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
189 | int sober128_ready(prng_state *prng); | |
190 | unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); | |
191 | int sober128_done(prng_state *prng); | |
192 | int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); | |
193 | int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); | |
194 | int sober128_test(void); | |
195 | extern const struct ltc_prng_descriptor sober128_desc; | |
197 | 196 | #endif |
198 | 197 | |
199 | 198 | int find_prng(const char *name); |
21 | 21 | @param cipher The index of the cipher desired |
22 | 22 | @param key The secret key |
23 | 23 | @param keylen The length of the secret key (octets) |
24 | @param filename The name of the file you wish to f9 | |
24 | @param fname The name of the file you wish to f9 | |
25 | 25 | @param out [out] Where the authentication tag is to be stored |
26 | 26 | @param outlen [in/out] The max size and resulting size of the authentication tag |
27 | 27 | @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled |
28 | 28 | */ |
29 | 29 | int f9_file(int cipher, |
30 | 30 | const unsigned char *key, unsigned long keylen, |
31 | const char *filename, | |
31 | const char *fname, | |
32 | 32 | unsigned char *out, unsigned long *outlen) |
33 | 33 | { |
34 | 34 | #ifdef LTC_NO_FILE |
38 | 38 | int err; |
39 | 39 | f9_state f9; |
40 | 40 | FILE *in; |
41 | unsigned char buf[512]; | |
41 | unsigned char *buf; | |
42 | 42 | |
43 | LTC_ARGCHK(key != NULL); | |
44 | LTC_ARGCHK(filename != NULL); | |
45 | LTC_ARGCHK(out != NULL); | |
46 | LTC_ARGCHK(outlen != NULL); | |
43 | LTC_ARGCHK(key != NULL); | |
44 | LTC_ARGCHK(fname != NULL); | |
45 | LTC_ARGCHK(out != NULL); | |
46 | LTC_ARGCHK(outlen != NULL); | |
47 | 47 | |
48 | in = fopen(filename, "rb"); | |
49 | if (in == NULL) { | |
50 | return CRYPT_FILE_NOTFOUND; | |
48 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
49 | return CRYPT_MEM; | |
51 | 50 | } |
52 | 51 | |
53 | 52 | if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { |
54 | fclose(in); | |
55 | return err; | |
53 | goto LBL_ERR; | |
54 | } | |
55 | ||
56 | in = fopen(fname, "rb"); | |
57 | if (in == NULL) { | |
58 | err = CRYPT_FILE_NOTFOUND; | |
59 | goto LBL_ERR; | |
56 | 60 | } |
57 | 61 | |
58 | 62 | do { |
59 | x = fread(buf, 1, sizeof(buf), in); | |
63 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
60 | 64 | if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { |
61 | 65 | fclose(in); |
62 | return err; | |
66 | goto LBL_CLEANBUF; | |
63 | 67 | } |
64 | } while (x == sizeof(buf)); | |
65 | fclose(in); | |
68 | } while (x == LTC_FILE_READ_BUFSIZE); | |
66 | 69 | |
67 | if ((err = f9_done(&f9, out, outlen)) != CRYPT_OK) { | |
68 | return err; | |
70 | if (fclose(in) != 0) { | |
71 | err = CRYPT_ERROR; | |
72 | goto LBL_CLEANBUF; | |
69 | 73 | } |
70 | 74 | |
75 | err = f9_done(&f9, out, outlen); | |
76 | ||
77 | LBL_CLEANBUF: | |
78 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
79 | LBL_ERR: | |
71 | 80 | #ifdef LTC_CLEAN_STACK |
72 | zeromem(buf, sizeof(buf)); | |
81 | zeromem(&f9, sizeof(f9_state)); | |
73 | 82 | #endif |
74 | ||
75 | return CRYPT_OK; | |
83 | XFREE(buf); | |
84 | return err; | |
76 | 85 | #endif |
77 | 86 | } |
78 | 87 |
35 | 35 | #else |
36 | 36 | hmac_state hmac; |
37 | 37 | FILE *in; |
38 | unsigned char buf[512]; | |
38 | unsigned char *buf; | |
39 | 39 | size_t x; |
40 | 40 | int err; |
41 | 41 | |
44 | 44 | LTC_ARGCHK(out != NULL); |
45 | 45 | LTC_ARGCHK(outlen != NULL); |
46 | 46 | |
47 | if((err = hash_is_valid(hash)) != CRYPT_OK) { | |
48 | return err; | |
47 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
48 | return CRYPT_MEM; | |
49 | } | |
50 | ||
51 | if ((err = hash_is_valid(hash)) != CRYPT_OK) { | |
52 | goto LBL_ERR; | |
49 | 53 | } |
50 | 54 | |
51 | 55 | if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { |
52 | return err; | |
56 | goto LBL_ERR; | |
53 | 57 | } |
54 | 58 | |
55 | 59 | in = fopen(fname, "rb"); |
56 | 60 | if (in == NULL) { |
57 | return CRYPT_FILE_NOTFOUND; | |
61 | err = CRYPT_FILE_NOTFOUND; | |
62 | goto LBL_ERR; | |
58 | 63 | } |
59 | 64 | |
60 | /* process the file contents */ | |
61 | 65 | do { |
62 | x = fread(buf, 1, sizeof(buf), in); | |
66 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
63 | 67 | if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { |
64 | /* we don't trap this error since we're already returning an error! */ | |
65 | fclose(in); | |
66 | return err; | |
68 | fclose(in); /* we don't trap this error since we're already returning an error! */ | |
69 | goto LBL_CLEANBUF; | |
67 | 70 | } |
68 | } while (x == sizeof(buf)); | |
71 | } while (x == LTC_FILE_READ_BUFSIZE); | |
69 | 72 | |
70 | 73 | if (fclose(in) != 0) { |
71 | return CRYPT_ERROR; | |
74 | err = CRYPT_ERROR; | |
75 | goto LBL_CLEANBUF; | |
72 | 76 | } |
73 | 77 | |
74 | /* get final hmac */ | |
75 | if ((err = hmac_done(&hmac, out, outlen)) != CRYPT_OK) { | |
76 | return err; | |
77 | } | |
78 | err = hmac_done(&hmac, out, outlen); | |
78 | 79 | |
80 | LBL_CLEANBUF: | |
81 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
82 | LBL_ERR: | |
79 | 83 | #ifdef LTC_CLEAN_STACK |
80 | /* clear memory */ | |
81 | zeromem(buf, sizeof(buf)); | |
84 | zeromem(&hmac, sizeof(hmac_state)); | |
82 | 85 | #endif |
83 | return CRYPT_OK; | |
86 | XFREE(buf); | |
87 | return err; | |
84 | 88 | #endif |
85 | 89 | } |
86 | 90 | |
87 | 91 | #endif |
88 | 92 | |
89 | ||
90 | 93 | /* $Source$ */ |
91 | 94 | /* $Revision$ */ |
92 | 95 | /* $Date$ */ |
38 | 38 | int err; |
39 | 39 | omac_state omac; |
40 | 40 | FILE *in; |
41 | unsigned char buf[512]; | |
41 | unsigned char *buf; | |
42 | 42 | |
43 | 43 | LTC_ARGCHK(key != NULL); |
44 | 44 | LTC_ARGCHK(filename != NULL); |
45 | 45 | LTC_ARGCHK(out != NULL); |
46 | 46 | LTC_ARGCHK(outlen != NULL); |
47 | 47 | |
48 | in = fopen(filename, "rb"); | |
49 | if (in == NULL) { | |
50 | return CRYPT_FILE_NOTFOUND; | |
48 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
49 | return CRYPT_MEM; | |
51 | 50 | } |
52 | 51 | |
53 | 52 | if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { |
54 | fclose(in); | |
55 | return err; | |
53 | goto LBL_ERR; | |
54 | } | |
55 | ||
56 | in = fopen(filename, "rb"); | |
57 | if (in == NULL) { | |
58 | err = CRYPT_FILE_NOTFOUND; | |
59 | goto LBL_ERR; | |
56 | 60 | } |
57 | 61 | |
58 | 62 | do { |
59 | x = fread(buf, 1, sizeof(buf), in); | |
63 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
60 | 64 | if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) { |
61 | 65 | fclose(in); |
62 | return err; | |
66 | goto LBL_CLEANBUF; | |
63 | 67 | } |
64 | } while (x == sizeof(buf)); | |
65 | fclose(in); | |
68 | } while (x == LTC_FILE_READ_BUFSIZE); | |
66 | 69 | |
67 | if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { | |
68 | return err; | |
70 | if (fclose(in) != 0) { | |
71 | err = CRYPT_ERROR; | |
72 | goto LBL_CLEANBUF; | |
69 | 73 | } |
70 | 74 | |
75 | err = omac_done(&omac, out, outlen); | |
76 | ||
77 | LBL_CLEANBUF: | |
78 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
79 | LBL_ERR: | |
71 | 80 | #ifdef LTC_CLEAN_STACK |
72 | zeromem(buf, sizeof(buf)); | |
81 | zeromem(&omac, sizeof(omac_state)); | |
73 | 82 | #endif |
74 | ||
75 | return CRYPT_OK; | |
83 | XFREE(buf); | |
84 | return err; | |
76 | 85 | #endif |
77 | 86 | } |
78 | 87 |
38 | 38 | int err; |
39 | 39 | pmac_state pmac; |
40 | 40 | FILE *in; |
41 | unsigned char buf[512]; | |
41 | unsigned char *buf; | |
42 | 42 | |
43 | 43 | |
44 | 44 | LTC_ARGCHK(key != NULL); |
46 | 46 | LTC_ARGCHK(out != NULL); |
47 | 47 | LTC_ARGCHK(outlen != NULL); |
48 | 48 | |
49 | in = fopen(filename, "rb"); | |
50 | if (in == NULL) { | |
51 | return CRYPT_FILE_NOTFOUND; | |
49 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
50 | return CRYPT_MEM; | |
52 | 51 | } |
53 | 52 | |
54 | 53 | if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { |
55 | fclose(in); | |
56 | return err; | |
54 | goto LBL_ERR; | |
55 | } | |
56 | ||
57 | in = fopen(filename, "rb"); | |
58 | if (in == NULL) { | |
59 | err = CRYPT_FILE_NOTFOUND; | |
60 | goto LBL_ERR; | |
57 | 61 | } |
58 | 62 | |
59 | 63 | do { |
60 | x = fread(buf, 1, sizeof(buf), in); | |
64 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
61 | 65 | if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) { |
62 | 66 | fclose(in); |
63 | return err; | |
67 | goto LBL_CLEANBUF; | |
64 | 68 | } |
65 | } while (x == sizeof(buf)); | |
66 | fclose(in); | |
69 | } while (x == LTC_FILE_READ_BUFSIZE); | |
67 | 70 | |
68 | if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { | |
69 | return err; | |
71 | if (fclose(in) != 0) { | |
72 | err = CRYPT_ERROR; | |
73 | goto LBL_CLEANBUF; | |
70 | 74 | } |
71 | 75 | |
76 | err = pmac_done(&pmac, out, outlen); | |
77 | ||
78 | LBL_CLEANBUF: | |
79 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
80 | LBL_ERR: | |
72 | 81 | #ifdef LTC_CLEAN_STACK |
73 | zeromem(buf, sizeof(buf)); | |
82 | zeromem(&pmac, sizeof(pmac_state)); | |
74 | 83 | #endif |
75 | ||
76 | return CRYPT_OK; | |
84 | XFREE(buf); | |
85 | return err; | |
77 | 86 | #endif |
78 | 87 | } |
79 | 88 |
20 | 20 | @param fname The name of the file you wish to POLY1305 |
21 | 21 | @param key The secret key |
22 | 22 | @param keylen The length of the secret key |
23 | @param out [out] The POLY1305 authentication tag | |
24 | @param outlen [in/out] The max size and resulting size of the authentication tag | |
23 | @param mac [out] The POLY1305 authentication tag | |
24 | @param maclen [in/out] The max size and resulting size of the authentication tag | |
25 | 25 | @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled |
26 | 26 | */ |
27 | 27 | int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) |
40 | 40 | LTC_ARGCHK(mac != NULL); |
41 | 41 | LTC_ARGCHK(maclen != NULL); |
42 | 42 | |
43 | if ((in = fopen(fname, "rb")) == NULL) { return CRYPT_FILE_NOTFOUND; } | |
44 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } | |
45 | if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } | |
43 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
44 | return CRYPT_MEM; | |
45 | } | |
46 | ||
47 | if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { | |
48 | goto LBL_ERR; | |
49 | } | |
50 | ||
51 | in = fopen(fname, "rb"); | |
52 | if (in == NULL) { | |
53 | err = CRYPT_FILE_NOTFOUND; | |
54 | goto LBL_ERR; | |
55 | } | |
46 | 56 | |
47 | 57 | do { |
48 | 58 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); |
49 | 59 | if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { |
50 | 60 | fclose(in); |
51 | goto LBL_ERR; | |
61 | goto LBL_CLEANBUF; | |
52 | 62 | } |
53 | 63 | } while (x == LTC_FILE_READ_BUFSIZE); |
54 | if (fclose(in) != 0) { | |
64 | ||
65 | if (fclose(in) != 0) { | |
55 | 66 | err = CRYPT_ERROR; |
56 | goto LBL_ERR; | |
67 | goto LBL_CLEANBUF; | |
57 | 68 | } |
69 | ||
58 | 70 | err = poly1305_done(&st, mac, maclen); |
59 | 71 | |
72 | LBL_CLEANBUF: | |
73 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
60 | 74 | LBL_ERR: |
61 | 75 | #ifdef LTC_CLEAN_STACK |
62 | 76 | zeromem(&st, sizeof(poly1305_state)); |
64 | 78 | XFREE(buf); |
65 | 79 | return err; |
66 | 80 | #endif |
67 | }; | |
81 | } | |
68 | 82 | |
69 | 83 | #endif |
38 | 38 | int err; |
39 | 39 | xcbc_state xcbc; |
40 | 40 | FILE *in; |
41 | unsigned char buf[512]; | |
41 | unsigned char *buf; | |
42 | 42 | |
43 | 43 | LTC_ARGCHK(key != NULL); |
44 | 44 | LTC_ARGCHK(filename != NULL); |
45 | 45 | LTC_ARGCHK(out != NULL); |
46 | 46 | LTC_ARGCHK(outlen != NULL); |
47 | 47 | |
48 | in = fopen(filename, "rb"); | |
49 | if (in == NULL) { | |
50 | return CRYPT_FILE_NOTFOUND; | |
48 | if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { | |
49 | return CRYPT_MEM; | |
51 | 50 | } |
52 | 51 | |
53 | 52 | if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { |
54 | fclose(in); | |
55 | return err; | |
53 | goto LBL_ERR; | |
54 | } | |
55 | ||
56 | in = fopen(filename, "rb"); | |
57 | if (in == NULL) { | |
58 | err = CRYPT_FILE_NOTFOUND; | |
59 | goto LBL_ERR; | |
56 | 60 | } |
57 | 61 | |
58 | 62 | do { |
59 | x = fread(buf, 1, sizeof(buf), in); | |
63 | x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); | |
60 | 64 | if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) { |
61 | 65 | fclose(in); |
62 | return err; | |
66 | goto LBL_CLEANBUF; | |
63 | 67 | } |
64 | } while (x == sizeof(buf)); | |
65 | fclose(in); | |
68 | } while (x == LTC_FILE_READ_BUFSIZE); | |
66 | 69 | |
67 | if ((err = xcbc_done(&xcbc, out, outlen)) != CRYPT_OK) { | |
68 | return err; | |
70 | if (fclose(in) != 0) { | |
71 | err = CRYPT_ERROR; | |
72 | goto LBL_CLEANBUF; | |
69 | 73 | } |
70 | 74 | |
75 | err = xcbc_done(&xcbc, out, outlen); | |
76 | ||
77 | LBL_CLEANBUF: | |
78 | zeromem(buf, LTC_FILE_READ_BUFSIZE); | |
79 | LBL_ERR: | |
71 | 80 | #ifdef LTC_CLEAN_STACK |
72 | zeromem(buf, sizeof(buf)); | |
81 | zeromem(&xcbc, sizeof(xcbc_state)); | |
73 | 82 | #endif |
74 | ||
75 | return CRYPT_OK; | |
83 | XFREE(buf); | |
84 | return err; | |
76 | 85 | #endif |
77 | 86 | } |
78 | 87 |
123 | 123 | #if defined(LTC_CAMELLIA) |
124 | 124 | " Camellia\n" |
125 | 125 | #endif |
126 | "Stream ciphers built-in:\n" | |
126 | 127 | #if defined(LTC_CHACHA) |
127 | 128 | " ChaCha\n" |
129 | #endif | |
130 | #if defined(LTC_RC4_STREAM) | |
131 | " RC4\n" | |
132 | #endif | |
133 | #if defined(LTC_SOBER128_STREAM) | |
134 | " SOBER128\n" | |
128 | 135 | #endif |
129 | 136 | |
130 | 137 | "\nHashes built-in:\n" |
178 | 185 | #endif |
179 | 186 | #if defined(LTC_WHIRLPOOL) |
180 | 187 | " WHIRLPOOL\n" |
188 | #endif | |
189 | #if defined(LTC_BLAKE2S) | |
190 | " BLAKE2S\n" | |
191 | #endif | |
192 | #if defined(LTC_BLAKE2B) | |
193 | " BLAKE2B\n" | |
181 | 194 | #endif |
182 | 195 | #if defined(LTC_CHC_HASH) |
183 | 196 | " CHC_HASH\n" |
234 | 247 | #endif |
235 | 248 | #if defined(LTC_POLY1305) |
236 | 249 | " POLY1305\n" |
250 | #endif | |
251 | #if defined(LTC_BLAKE2SMAC) | |
252 | " BLAKE2S MAC\n" | |
253 | #endif | |
254 | #if defined(LTC_BLAKE2BMAC) | |
255 | " BLAKE2B MAC\n" | |
237 | 256 | #endif |
238 | 257 | |
239 | 258 | "\nENC + AUTH modes:\n" |
17 | 17 | const struct ltc_prng_descriptor chacha20_prng_desc = |
18 | 18 | { |
19 | 19 | "chacha20", |
20 | sizeof(chacha_state), | |
20 | 40, | |
21 | 21 | &chacha20_prng_start, |
22 | 22 | &chacha20_prng_add_entropy, |
23 | 23 | &chacha20_prng_ready, |
36 | 36 | int chacha20_prng_start(prng_state *prng) |
37 | 37 | { |
38 | 38 | LTC_ARGCHK(prng != NULL); |
39 | prng->chacha.ready = 0; | |
40 | XMEMSET(&prng->chacha.ent, 0, 40); | |
39 | prng->ready = 0; | |
40 | XMEMSET(&prng->chacha.ent, 0, sizeof(prng->chacha.ent)); | |
41 | 41 | prng->chacha.idx = 0; |
42 | LTC_MUTEX_INIT(&prng->lock) | |
42 | 43 | return CRYPT_OK; |
43 | 44 | } |
44 | 45 | |
59 | 60 | LTC_ARGCHK(in != NULL); |
60 | 61 | LTC_ARGCHK(inlen > 0); |
61 | 62 | |
62 | if (prng->chacha.ready) { | |
63 | LTC_MUTEX_LOCK(&prng->lock); | |
64 | if (prng->ready) { | |
63 | 65 | /* chacha20_prng_ready() was already called, do "rekey" operation */ |
64 | if ((err = chacha_keystream(&prng->chacha.s, buf, 40)) != CRYPT_OK) return err; | |
65 | for(i = 0; i < inlen; i++) buf[i % 40] ^= in[i]; | |
66 | if ((err = chacha_keystream(&prng->chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; | |
67 | for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; | |
66 | 68 | /* key 32 bytes, 20 rounds */ |
67 | if ((err = chacha_setup(&prng->chacha.s, buf, 32, 20)) != CRYPT_OK) return err; | |
69 | if ((err = chacha_setup(&prng->chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; | |
68 | 70 | /* iv 8 bytes */ |
69 | if ((err = chacha_ivctr64(&prng->chacha.s, buf + 32, 8, 0)) != CRYPT_OK) return err; | |
71 | if ((err = chacha_ivctr64(&prng->chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; | |
70 | 72 | /* clear KEY + IV */ |
71 | XMEMSET(buf, 0, 40); | |
73 | XMEMSET(buf, 0, sizeof(buf)); | |
72 | 74 | } |
73 | 75 | else { |
74 | 76 | /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */ |
75 | while (inlen--) prng->chacha.ent[prng->chacha.idx++ % 40] ^= *in++; | |
76 | } | |
77 | ||
78 | return CRYPT_OK; | |
77 | while (inlen--) prng->chacha.ent[prng->chacha.idx++ % sizeof(prng->chacha.ent)] ^= *in++; | |
78 | } | |
79 | err = CRYPT_OK; | |
80 | LBL_UNLOCK: | |
81 | LTC_MUTEX_UNLOCK(&prng->lock); | |
82 | return err; | |
79 | 83 | } |
80 | 84 | |
81 | 85 | /** |
88 | 92 | int err; |
89 | 93 | |
90 | 94 | LTC_ARGCHK(prng != NULL); |
91 | if (prng->chacha.ready) return CRYPT_OK; | |
92 | ||
95 | ||
96 | LTC_MUTEX_LOCK(&prng->lock); | |
97 | if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } | |
93 | 98 | /* key 32 bytes, 20 rounds */ |
94 | if ((err = chacha_setup(&prng->chacha.s, prng->chacha.ent, 32, 20)) != CRYPT_OK) return err; | |
99 | if ((err = chacha_setup(&prng->chacha.s, prng->chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; | |
95 | 100 | /* iv 8 bytes */ |
96 | if ((err = chacha_ivctr64(&prng->chacha.s, prng->chacha.ent + 32, 8, 0)) != CRYPT_OK) return err; | |
97 | XMEMSET(&prng->chacha.ent, 0, 40); | |
98 | prng->chacha.ready = 1; | |
101 | if ((err = chacha_ivctr64(&prng->chacha.s, prng->chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; | |
102 | XMEMSET(&prng->chacha.ent, 0, sizeof(prng->chacha.ent)); | |
99 | 103 | prng->chacha.idx = 0; |
100 | return CRYPT_OK; | |
104 | prng->ready = 1; | |
105 | LBL_UNLOCK: | |
106 | LTC_MUTEX_UNLOCK(&prng->lock); | |
107 | return err; | |
101 | 108 | } |
102 | 109 | |
103 | 110 | /** |
109 | 116 | */ |
110 | 117 | unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) |
111 | 118 | { |
112 | LTC_ARGCHK(prng != NULL); | |
113 | if (!prng->chacha.ready) return 0; | |
114 | if (chacha_keystream(&prng->chacha.s, out, outlen) != CRYPT_OK) return 0; | |
119 | if (outlen == 0 || prng == NULL || out == NULL) return 0; | |
120 | LTC_MUTEX_LOCK(&prng->lock); | |
121 | if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } | |
122 | if (chacha_keystream(&prng->chacha.s, out, outlen) != CRYPT_OK) outlen = 0; | |
123 | LBL_UNLOCK: | |
124 | LTC_MUTEX_UNLOCK(&prng->lock); | |
115 | 125 | return outlen; |
116 | 126 | } |
117 | 127 | |
123 | 133 | int chacha20_prng_done(prng_state *prng) |
124 | 134 | { |
125 | 135 | 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; | |
136 | LTC_ARGCHK(prng != NULL); | |
137 | LTC_MUTEX_LOCK(&prng->lock); | |
138 | prng->ready = 0; | |
139 | err = chacha_done(&prng->chacha.s); | |
140 | LTC_MUTEX_UNLOCK(&prng->lock); | |
141 | return err; | |
131 | 142 | } |
132 | 143 | |
133 | 144 | /** |
139 | 150 | */ |
140 | 151 | int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) |
141 | 152 | { |
142 | unsigned long len = sizeof(chacha_state); | |
153 | unsigned long len = chacha20_prng_desc.export_size; | |
154 | ||
155 | LTC_ARGCHK(prng != NULL); | |
156 | LTC_ARGCHK(out != NULL); | |
143 | 157 | LTC_ARGCHK(outlen != NULL); |
144 | LTC_ARGCHK(out != NULL); | |
145 | LTC_ARGCHK(prng != NULL); | |
146 | ||
147 | if (!prng->chacha.ready) { | |
148 | return CRYPT_ERROR; | |
149 | } | |
158 | ||
150 | 159 | if (*outlen < len) { |
151 | 160 | *outlen = len; |
152 | 161 | return CRYPT_BUFFER_OVERFLOW; |
153 | 162 | } |
154 | XMEMCPY(out, &prng->chacha.s, len); | |
163 | ||
164 | if (chacha20_prng_read(out, len, prng) != len) { | |
165 | return CRYPT_ERROR_READPRNG; | |
166 | } | |
167 | ||
155 | 168 | *outlen = len; |
156 | 169 | return CRYPT_OK; |
157 | 170 | } |
165 | 178 | */ |
166 | 179 | int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) |
167 | 180 | { |
168 | unsigned long len = sizeof(chacha_state); | |
181 | int err; | |
182 | ||
183 | LTC_ARGCHK(prng != NULL); | |
169 | 184 | LTC_ARGCHK(in != NULL); |
170 | LTC_ARGCHK(prng != NULL); | |
171 | ||
172 | if (inlen != len) return CRYPT_INVALID_ARG; | |
173 | XMEMCPY(&prng->chacha.s, in, inlen); | |
174 | prng->chacha.ready = 1; | |
185 | if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG; | |
186 | ||
187 | if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err; | |
188 | if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; | |
175 | 189 | return CRYPT_OK; |
176 | 190 | } |
177 | 191 | |
193 | 207 | unsigned char dmp[300]; |
194 | 208 | unsigned long dmplen = sizeof(dmp); |
195 | 209 | unsigned char out[500]; |
196 | unsigned char t1[] = { 0x59, 0xb2, 0x26, 0x95, 0x2b, 0x01, 0x8f, 0x05, 0xbe, 0xd8 }; | |
197 | unsigned char t2[] = { 0x30, 0x34, 0x5c, 0x6e, 0x56, 0x18, 0x8c, 0x46, 0xbe, 0x8a }; | |
198 | ||
199 | chacha20_prng_start(&st); | |
200 | chacha20_prng_add_entropy(en, sizeof(en), &st); /* add entropy to uninitialized prng */ | |
201 | chacha20_prng_ready(&st); | |
202 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
203 | if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1) != 0) return CRYPT_FAIL_TESTVECTOR; | |
204 | chacha20_prng_read(out, 500, &st); | |
205 | chacha20_prng_add_entropy(en, sizeof(en), &st); /* add entropy to already initialized prng */ | |
206 | chacha20_prng_read(out, 500, &st); | |
207 | chacha20_prng_export(dmp, &dmplen, &st); | |
208 | chacha20_prng_read(out, 500, &st); /* skip 500 bytes */ | |
209 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
210 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; | |
211 | chacha20_prng_done(&st); | |
212 | ||
213 | XMEMSET(&st, 0xFF, sizeof(st)); /* just to be sure */ | |
214 | chacha20_prng_import(dmp, dmplen, &st); | |
215 | chacha20_prng_read(out, 500, &st); /* skip 500 bytes */ | |
216 | chacha20_prng_read(out, 10, &st); /* 10 bytes for testing */ | |
217 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 3) != 0) return CRYPT_FAIL_TESTVECTOR; | |
218 | chacha20_prng_done(&st); | |
210 | unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 }; | |
211 | unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE }; | |
212 | unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 }; | |
213 | int err; | |
214 | ||
215 | if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err; | |
216 | /* add entropy to uninitialized prng */ | |
217 | if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
218 | if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; | |
219 | if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
220 | if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; | |
221 | if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
222 | /* add entropy to already initialized prng */ | |
223 | if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
224 | if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
225 | if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; | |
226 | if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
227 | if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
228 | if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; | |
229 | if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; | |
230 | if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err; | |
231 | if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; | |
232 | if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
233 | if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
234 | if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; | |
235 | if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; | |
219 | 236 | |
220 | 237 | return CRYPT_OK; |
221 | 238 | #endif |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 | |
37 | 35 | #endif |
38 | 36 | |
39 | 37 | const struct ltc_prng_descriptor fortuna_desc = { |
40 | "fortuna", 1024, | |
38 | "fortuna", | |
39 | (32 * LTC_FORTUNA_POOLS), /* default: 1024 */ | |
41 | 40 | &fortuna_start, |
42 | 41 | &fortuna_add_entropy, |
43 | 42 | &fortuna_ready, |
132 | 131 | unsigned char tmp[MAXBLOCKSIZE]; |
133 | 132 | |
134 | 133 | LTC_ARGCHK(prng != NULL); |
134 | prng->ready = 0; | |
135 | 135 | |
136 | 136 | /* initialize the pools */ |
137 | 137 | for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
155 | 155 | } |
156 | 156 | zeromem(prng->fortuna.IV, 16); |
157 | 157 | |
158 | LTC_MUTEX_INIT(&prng->fortuna.prng_lock) | |
158 | LTC_MUTEX_INIT(&prng->lock) | |
159 | 159 | |
160 | 160 | return CRYPT_OK; |
161 | 161 | } |
172 | 172 | unsigned char tmp[2]; |
173 | 173 | int err; |
174 | 174 | |
175 | LTC_ARGCHK(in != NULL); | |
176 | 175 | LTC_ARGCHK(prng != NULL); |
177 | ||
178 | LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
176 | LTC_ARGCHK(in != NULL); | |
177 | LTC_ARGCHK(inlen > 0); | |
179 | 178 | |
180 | 179 | /* ensure inlen <= 32 */ |
181 | 180 | if (inlen > 32) { |
182 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
183 | return CRYPT_INVALID_ARG; | |
181 | inlen = 32; | |
184 | 182 | } |
185 | 183 | |
186 | 184 | /* add s || length(in) || in to pool[pool_idx] */ |
187 | 185 | tmp[0] = 0; |
188 | 186 | tmp[1] = (unsigned char)inlen; |
187 | ||
188 | LTC_MUTEX_LOCK(&prng->lock); | |
189 | 189 | if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) { |
190 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
191 | return err; | |
190 | goto LBL_UNLOCK; | |
192 | 191 | } |
193 | 192 | if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { |
194 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
195 | return err; | |
193 | goto LBL_UNLOCK; | |
196 | 194 | } |
197 | 195 | if (prng->fortuna.pool_idx == 0) { |
198 | 196 | prng->fortuna.pool0_len += inlen; |
200 | 198 | if (++(prng->fortuna.pool_idx) == LTC_FORTUNA_POOLS) { |
201 | 199 | prng->fortuna.pool_idx = 0; |
202 | 200 | } |
203 | ||
204 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
205 | return CRYPT_OK; | |
201 | err = CRYPT_OK; /* success */ | |
202 | ||
203 | LBL_UNLOCK: | |
204 | LTC_MUTEX_UNLOCK(&prng->lock); | |
205 | return err; | |
206 | 206 | } |
207 | 207 | |
208 | 208 | /** |
212 | 212 | */ |
213 | 213 | int fortuna_ready(prng_state *prng) |
214 | 214 | { |
215 | return fortuna_reseed(prng); | |
215 | int err; | |
216 | LTC_ARGCHK(prng != NULL); | |
217 | ||
218 | LTC_MUTEX_LOCK(&prng->lock); | |
219 | err = fortuna_reseed(prng); | |
220 | prng->ready = (err == CRYPT_OK) ? 1 : 0; | |
221 | ||
222 | LTC_MUTEX_UNLOCK(&prng->lock); | |
223 | return err; | |
216 | 224 | } |
217 | 225 | |
218 | 226 | /** |
225 | 233 | unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) |
226 | 234 | { |
227 | 235 | unsigned char tmp[16]; |
228 | unsigned long tlen; | |
229 | ||
230 | LTC_ARGCHK(out != NULL); | |
231 | LTC_ARGCHK(prng != NULL); | |
232 | ||
233 | LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
236 | unsigned long tlen = 0; | |
237 | ||
238 | if (outlen == 0 || prng == NULL || out == NULL) return 0; | |
239 | ||
240 | LTC_MUTEX_LOCK(&prng->lock); | |
241 | ||
242 | if (!prng->ready) { | |
243 | goto LBL_UNLOCK; | |
244 | } | |
234 | 245 | |
235 | 246 | /* do we have to reseed? */ |
236 | 247 | if (++prng->fortuna.wd == LTC_FORTUNA_WD || prng->fortuna.pool0_len >= 64) { |
237 | 248 | if (fortuna_reseed(prng) != CRYPT_OK) { |
238 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
239 | return 0; | |
249 | goto LBL_UNLOCK; | |
240 | 250 | } |
241 | 251 | } |
242 | 252 | |
267 | 277 | fortuna_update_iv(prng); |
268 | 278 | |
269 | 279 | if (rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey) != CRYPT_OK) { |
270 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
271 | return 0; | |
272 | } | |
273 | ||
280 | tlen = 0; | |
281 | } | |
282 | ||
283 | LBL_UNLOCK: | |
274 | 284 | #ifdef LTC_CLEAN_STACK |
275 | 285 | zeromem(tmp, sizeof(tmp)); |
276 | 286 | #endif |
277 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
287 | LTC_MUTEX_UNLOCK(&prng->lock); | |
278 | 288 | return tlen; |
279 | 289 | } |
280 | 290 | |
289 | 299 | unsigned char tmp[32]; |
290 | 300 | |
291 | 301 | LTC_ARGCHK(prng != NULL); |
292 | LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
302 | ||
303 | LTC_MUTEX_LOCK(&prng->lock); | |
304 | prng->ready = 0; | |
293 | 305 | |
294 | 306 | /* terminate all the hashes */ |
295 | 307 | for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
296 | 308 | if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { |
297 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
298 | return err; | |
309 | goto LBL_UNLOCK; | |
299 | 310 | } |
300 | 311 | } |
301 | 312 | /* call cipher done when we invent one ;-) */ |
302 | ||
313 | err = CRYPT_OK; /* success */ | |
314 | ||
315 | LBL_UNLOCK: | |
303 | 316 | #ifdef LTC_CLEAN_STACK |
304 | 317 | zeromem(tmp, sizeof(tmp)); |
305 | 318 | #endif |
306 | ||
307 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
308 | return CRYPT_OK; | |
319 | LTC_MUTEX_UNLOCK(&prng->lock); | |
320 | return err; | |
309 | 321 | } |
310 | 322 | |
311 | 323 | /** |
319 | 331 | { |
320 | 332 | int x, err; |
321 | 333 | hash_state *md; |
334 | unsigned long len = fortuna_desc.export_size; | |
322 | 335 | |
323 | 336 | LTC_ARGCHK(out != NULL); |
324 | 337 | LTC_ARGCHK(outlen != NULL); |
325 | 338 | LTC_ARGCHK(prng != NULL); |
326 | 339 | |
327 | LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
340 | LTC_MUTEX_LOCK(&prng->lock); | |
341 | ||
342 | if (!prng->ready) { | |
343 | err = CRYPT_ERROR; | |
344 | goto LBL_UNLOCK; | |
345 | } | |
328 | 346 | |
329 | 347 | /* we'll write bytes for s&g's */ |
330 | if (*outlen < 32*LTC_FORTUNA_POOLS) { | |
331 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
332 | *outlen = 32*LTC_FORTUNA_POOLS; | |
333 | return CRYPT_BUFFER_OVERFLOW; | |
348 | if (*outlen < len) { | |
349 | *outlen = len; | |
350 | err = CRYPT_BUFFER_OVERFLOW; | |
351 | goto LBL_UNLOCK; | |
334 | 352 | } |
335 | 353 | |
336 | 354 | md = XMALLOC(sizeof(hash_state)); |
337 | 355 | if (md == NULL) { |
338 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
339 | return CRYPT_MEM; | |
356 | err = CRYPT_MEM; | |
357 | goto LBL_UNLOCK; | |
340 | 358 | } |
341 | 359 | |
342 | 360 | /* to emit the state we copy each pool, terminate it then hash it again so |
362 | 380 | goto LBL_ERR; |
363 | 381 | } |
364 | 382 | } |
365 | *outlen = 32*LTC_FORTUNA_POOLS; | |
383 | *outlen = len; | |
366 | 384 | err = CRYPT_OK; |
367 | 385 | |
368 | 386 | LBL_ERR: |
370 | 388 | zeromem(md, sizeof(*md)); |
371 | 389 | #endif |
372 | 390 | XFREE(md); |
373 | LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
391 | LBL_UNLOCK: | |
392 | LTC_MUTEX_UNLOCK(&prng->lock); | |
374 | 393 | return err; |
375 | 394 | } |
376 | 395 | |
388 | 407 | LTC_ARGCHK(in != NULL); |
389 | 408 | LTC_ARGCHK(prng != NULL); |
390 | 409 | |
391 | if (inlen != 32*LTC_FORTUNA_POOLS) { | |
410 | if (inlen < (unsigned long)fortuna_desc.export_size) { | |
392 | 411 | return CRYPT_INVALID_ARG; |
393 | 412 | } |
394 | 413 | |
400 | 419 | return err; |
401 | 420 | } |
402 | 421 | } |
403 | return err; | |
422 | return CRYPT_OK; | |
404 | 423 | } |
405 | 424 | |
406 | 425 | /** |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 | |
12 | 10 | /** |
13 | 11 | @file rc4.c |
14 | LTC_RC4 PRNG, Tom St Denis | |
12 | RC4 PRNG, Tom St Denis | |
15 | 13 | */ |
16 | 14 | |
17 | 15 | #ifdef LTC_RC4 |
18 | 16 | |
19 | const struct ltc_prng_descriptor rc4_prng_desc = | |
17 | const struct ltc_prng_descriptor rc4_desc = | |
20 | 18 | { |
21 | 19 | "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 | |
20 | 32, | |
21 | &rc4_start, | |
22 | &rc4_add_entropy, | |
23 | &rc4_ready, | |
24 | &rc4_read, | |
25 | &rc4_done, | |
26 | &rc4_export, | |
27 | &rc4_import, | |
28 | &rc4_test | |
31 | 29 | }; |
32 | 30 | |
33 | 31 | /** |
35 | 33 | @param prng [out] The PRNG state to initialize |
36 | 34 | @return CRYPT_OK if successful |
37 | 35 | */ |
38 | int rc4_prng_start(prng_state *prng) | |
39 | { | |
40 | LTC_ARGCHK(prng != NULL); | |
41 | prng->rc4.ready = 0; | |
42 | ||
36 | int rc4_start(prng_state *prng) | |
37 | { | |
38 | LTC_ARGCHK(prng != NULL); | |
39 | prng->ready = 0; | |
43 | 40 | /* set entropy (key) size to zero */ |
44 | 41 | prng->rc4.s.x = 0; |
45 | 42 | /* clear entropy (key) buffer */ |
46 | XMEMSET(&prng->rc4.s.buf, 0, 256); | |
47 | ||
43 | XMEMSET(&prng->rc4.s.buf, 0, sizeof(prng->rc4.s.buf)); | |
44 | LTC_MUTEX_INIT(&prng->lock) | |
48 | 45 | return CRYPT_OK; |
49 | 46 | } |
50 | 47 | |
55 | 52 | @param prng PRNG state to update |
56 | 53 | @return CRYPT_OK if successful |
57 | 54 | */ |
58 | int rc4_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
55 | int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
59 | 56 | { |
60 | 57 | unsigned char buf[256]; |
61 | 58 | unsigned long i; |
65 | 62 | LTC_ARGCHK(in != NULL); |
66 | 63 | LTC_ARGCHK(inlen > 0); |
67 | 64 | |
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]; | |
65 | LTC_MUTEX_LOCK(&prng->lock); | |
66 | if (prng->ready) { | |
67 | /* rc4_ready() was already called, do "rekey" operation */ | |
68 | if ((err = rc4_stream_keystream(&prng->rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; | |
69 | for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; | |
72 | 70 | /* initialize RC4 */ |
73 | if ((err = rc4_setup(&prng->rc4.s, buf, 256)) != CRYPT_OK) return err; | |
71 | if ((err = rc4_stream_setup(&prng->rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; | |
74 | 72 | /* 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); | |
73 | for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->rc4.s, buf, sizeof(buf)); | |
76 | 74 | } |
77 | 75 | 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 | /* rc4_ready() was not called yet, add entropy to the buffer */ | |
77 | while (inlen--) prng->rc4.s.buf[prng->rc4.s.x++ % sizeof(prng->rc4.s.buf)] ^= *in++; | |
78 | } | |
79 | err = CRYPT_OK; | |
80 | LBL_UNLOCK: | |
81 | LTC_MUTEX_UNLOCK(&prng->lock); | |
82 | return err; | |
83 | 83 | } |
84 | 84 | |
85 | 85 | /** |
87 | 87 | @param prng The PRNG to make active |
88 | 88 | @return CRYPT_OK if successful |
89 | 89 | */ |
90 | int rc4_prng_ready(prng_state *prng) | |
91 | { | |
92 | unsigned char buf[256]; | |
90 | int rc4_ready(prng_state *prng) | |
91 | { | |
92 | unsigned char buf[256] = { 0 }; | |
93 | 93 | unsigned long len; |
94 | 94 | int err, i; |
95 | 95 | |
96 | 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); | |
97 | ||
98 | LTC_MUTEX_LOCK(&prng->lock); | |
99 | if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } | |
100 | XMEMCPY(buf, prng->rc4.s.buf, sizeof(buf)); | |
103 | 101 | /* initialize RC4 */ |
104 | if ((err = rc4_setup(&prng->rc4.s, buf, len)) != CRYPT_OK) return err; | |
102 | len = MIN(prng->rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */ | |
103 | if ((err = rc4_stream_setup(&prng->rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK; | |
105 | 104 | /* 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; | |
105 | for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->rc4.s, buf, sizeof(buf)); | |
106 | prng->ready = 1; | |
107 | LBL_UNLOCK: | |
108 | LTC_MUTEX_UNLOCK(&prng->lock); | |
109 | return err; | |
109 | 110 | } |
110 | 111 | |
111 | 112 | /** |
115 | 116 | @param prng The active PRNG to read from |
116 | 117 | @return Number of octets read |
117 | 118 | */ |
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; | |
119 | unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
120 | { | |
121 | if (outlen == 0 || prng == NULL || out == NULL) return 0; | |
122 | LTC_MUTEX_LOCK(&prng->lock); | |
123 | if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } | |
124 | if (rc4_stream_keystream(&prng->rc4.s, out, outlen) != CRYPT_OK) outlen = 0; | |
125 | LBL_UNLOCK: | |
126 | LTC_MUTEX_UNLOCK(&prng->lock); | |
123 | 127 | return outlen; |
124 | 128 | } |
125 | 129 | |
128 | 132 | @param prng The PRNG to terminate |
129 | 133 | @return CRYPT_OK if successful |
130 | 134 | */ |
131 | int rc4_prng_done(prng_state *prng) | |
132 | { | |
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; | |
138 | return CRYPT_OK; | |
135 | int rc4_done(prng_state *prng) | |
136 | { | |
137 | int err; | |
138 | LTC_ARGCHK(prng != NULL); | |
139 | LTC_MUTEX_LOCK(&prng->lock); | |
140 | prng->ready = 0; | |
141 | err = rc4_stream_done(&prng->rc4.s); | |
142 | LTC_MUTEX_UNLOCK(&prng->lock); | |
143 | return err; | |
139 | 144 | } |
140 | 145 | |
141 | 146 | /** |
145 | 150 | @param prng The PRNG to export |
146 | 151 | @return CRYPT_OK if successful |
147 | 152 | */ |
148 | int rc4_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
149 | { | |
150 | unsigned long len = sizeof(rc4_state); | |
151 | ||
153 | int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
154 | { | |
155 | unsigned long len = rc4_desc.export_size; | |
156 | ||
157 | LTC_ARGCHK(prng != NULL); | |
158 | LTC_ARGCHK(out != NULL); | |
152 | 159 | LTC_ARGCHK(outlen != NULL); |
153 | LTC_ARGCHK(out != NULL); | |
154 | LTC_ARGCHK(prng != NULL); | |
155 | ||
156 | if (!prng->rc4.ready) return CRYPT_ERROR; | |
157 | 160 | |
158 | 161 | if (*outlen < len) { |
159 | 162 | *outlen = len; |
160 | 163 | return CRYPT_BUFFER_OVERFLOW; |
161 | 164 | } |
162 | XMEMCPY(out, &prng->rc4.s, len); | |
165 | ||
166 | if (rc4_read(out, len, prng) != len) { | |
167 | return CRYPT_ERROR_READPRNG; | |
168 | } | |
169 | ||
163 | 170 | *outlen = len; |
164 | 171 | return CRYPT_OK; |
165 | 172 | } |
171 | 178 | @param prng The PRNG to import |
172 | 179 | @return CRYPT_OK if successful |
173 | 180 | */ |
174 | int rc4_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
175 | { | |
181 | int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
182 | { | |
183 | int err; | |
184 | ||
185 | LTC_ARGCHK(prng != NULL); | |
176 | 186 | LTC_ARGCHK(in != NULL); |
177 | LTC_ARGCHK(prng != NULL); | |
178 | ||
179 | if (inlen != sizeof(rc4_state)) return CRYPT_INVALID_ARG; | |
180 | ||
181 | XMEMCPY(&prng->rc4.s, in, inlen); | |
182 | prng->rc4.ready = 1; | |
187 | if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG; | |
188 | ||
189 | if ((err = rc4_start(prng)) != CRYPT_OK) return err; | |
190 | if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; | |
183 | 191 | return CRYPT_OK; |
184 | 192 | } |
185 | 193 | |
187 | 195 | PRNG self-test |
188 | 196 | @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled |
189 | 197 | */ |
190 | int rc4_prng_test(void) | |
198 | int rc4_test(void) | |
191 | 199 | { |
192 | 200 | #ifndef LTC_TEST |
193 | 201 | return CRYPT_NOP; |
202 | 210 | unsigned long dmplen = sizeof(dmp); |
203 | 211 | unsigned char out[1000]; |
204 | 212 | 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); | |
213 | unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A }; | |
214 | unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 }; | |
215 | int err; | |
216 | ||
217 | if ((err = rc4_start(&st)) != CRYPT_OK) return err; | |
218 | /* add entropy to uninitialized prng */ | |
219 | if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
220 | if ((err = rc4_ready(&st)) != CRYPT_OK) return err; | |
221 | if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
222 | if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; | |
223 | if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
224 | /* add entropy to already initialized prng */ | |
225 | if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
226 | if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
227 | if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; | |
228 | if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
229 | if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
230 | if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; | |
231 | if ((err = rc4_done(&st)) != CRYPT_OK) return err; | |
232 | if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err; | |
233 | if ((err = rc4_ready(&st)) != CRYPT_OK) return err; | |
234 | if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
235 | if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
236 | if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; | |
237 | if ((err = rc4_done(&st)) != CRYPT_OK) return err; | |
225 | 238 | |
226 | 239 | return CRYPT_OK; |
227 | 240 | #endif |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 |
16 | 16 | |
17 | 17 | #ifdef LTC_SOBER128 |
18 | 18 | |
19 | const struct ltc_prng_descriptor sober128_prng_desc = | |
19 | const struct ltc_prng_descriptor sober128_desc = | |
20 | 20 | { |
21 | 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 | |
22 | 40, | |
23 | &sober128_start, | |
24 | &sober128_add_entropy, | |
25 | &sober128_ready, | |
26 | &sober128_read, | |
27 | &sober128_done, | |
28 | &sober128_export, | |
29 | &sober128_import, | |
30 | &sober128_test | |
31 | 31 | }; |
32 | 32 | |
33 | 33 | /** |
35 | 35 | @param prng [out] The PRNG state to initialize |
36 | 36 | @return CRYPT_OK if successful |
37 | 37 | */ |
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); | |
38 | int sober128_start(prng_state *prng) | |
39 | { | |
40 | LTC_ARGCHK(prng != NULL); | |
41 | prng->ready = 0; | |
42 | XMEMSET(&prng->sober128.ent, 0, sizeof(prng->sober128.ent)); | |
43 | 43 | prng->sober128.idx = 0; |
44 | LTC_MUTEX_INIT(&prng->lock) | |
44 | 45 | return CRYPT_OK; |
45 | 46 | } |
46 | 47 | |
51 | 52 | @param prng PRNG state to update |
52 | 53 | @return CRYPT_OK if successful |
53 | 54 | */ |
54 | int sober128_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
55 | int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
55 | 56 | { |
56 | 57 | unsigned char buf[40]; |
57 | 58 | unsigned long i; |
61 | 62 | LTC_ARGCHK(in != NULL); |
62 | 63 | LTC_ARGCHK(inlen > 0); |
63 | 64 | |
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]; | |
65 | LTC_MUTEX_LOCK(&prng->lock); | |
66 | if (prng->ready) { | |
67 | /* sober128_ready() was already called, do "rekey" operation */ | |
68 | if ((err = sober128_stream_keystream(&prng->sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; | |
69 | for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; | |
68 | 70 | /* key 32 bytes, 20 rounds */ |
69 | if ((err = sober128_setup(&prng->sober128.s, buf, 32)) != CRYPT_OK) return err; | |
71 | if ((err = sober128_stream_setup(&prng->sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK; | |
70 | 72 | /* iv 8 bytes */ |
71 | if ((err = sober128_setiv(&prng->sober128.s, buf + 32, 8)) != CRYPT_OK) return err; | |
73 | if ((err = sober128_stream_setiv(&prng->sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; | |
72 | 74 | /* clear KEY + IV */ |
73 | XMEMSET(buf, 0, 40); | |
75 | XMEMSET(buf, 0, sizeof(buf)); | |
74 | 76 | } |
75 | 77 | 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; | |
78 | /* sober128_ready() was not called yet, add entropy to ent buffer */ | |
79 | while (inlen--) prng->sober128.ent[prng->sober128.idx++ % sizeof(prng->sober128.ent)] ^= *in++; | |
80 | } | |
81 | err = CRYPT_OK; | |
82 | LBL_UNLOCK: | |
83 | LTC_MUTEX_UNLOCK(&prng->lock); | |
84 | return err; | |
81 | 85 | } |
82 | 86 | |
83 | 87 | /** |
85 | 89 | @param prng The PRNG to make active |
86 | 90 | @return CRYPT_OK if successful |
87 | 91 | */ |
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 | ||
92 | int sober128_ready(prng_state *prng) | |
93 | { | |
94 | int err; | |
95 | ||
96 | LTC_ARGCHK(prng != NULL); | |
97 | ||
98 | LTC_MUTEX_LOCK(&prng->lock); | |
99 | if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } | |
95 | 100 | /* key 32 bytes, 20 rounds */ |
96 | if ((err = sober128_setup(&prng->sober128.s, prng->sober128.ent, 32)) != CRYPT_OK) return err; | |
101 | if ((err = sober128_stream_setup(&prng->sober128.s, prng->sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK; | |
97 | 102 | /* 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; | |
103 | if ((err = sober128_stream_setiv(&prng->sober128.s, prng->sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; | |
104 | XMEMSET(&prng->sober128.ent, 0, sizeof(prng->sober128.ent)); | |
101 | 105 | prng->sober128.idx = 0; |
102 | return CRYPT_OK; | |
106 | prng->ready = 1; | |
107 | LBL_UNLOCK: | |
108 | LTC_MUTEX_UNLOCK(&prng->lock); | |
109 | return err; | |
103 | 110 | } |
104 | 111 | |
105 | 112 | /** |
109 | 116 | @param prng The active PRNG to read from |
110 | 117 | @return Number of octets read |
111 | 118 | */ |
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; | |
119 | unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
120 | { | |
121 | if (outlen == 0 || prng == NULL || out == NULL) return 0; | |
122 | LTC_MUTEX_LOCK(&prng->lock); | |
123 | if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } | |
124 | if (sober128_stream_keystream(&prng->sober128.s, out, outlen) != CRYPT_OK) outlen = 0; | |
125 | LBL_UNLOCK: | |
126 | LTC_MUTEX_UNLOCK(&prng->lock); | |
117 | 127 | return outlen; |
118 | 128 | } |
119 | 129 | |
122 | 132 | @param prng The PRNG to terminate |
123 | 133 | @return CRYPT_OK if successful |
124 | 134 | */ |
125 | int sober128_prng_done(prng_state *prng) | |
126 | { | |
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; | |
132 | return CRYPT_OK; | |
135 | int sober128_done(prng_state *prng) | |
136 | { | |
137 | int err; | |
138 | LTC_ARGCHK(prng != NULL); | |
139 | LTC_MUTEX_LOCK(&prng->lock); | |
140 | prng->ready = 0; | |
141 | err = sober128_stream_done(&prng->sober128.s); | |
142 | LTC_MUTEX_UNLOCK(&prng->lock); | |
143 | return err; | |
133 | 144 | } |
134 | 145 | |
135 | 146 | /** |
139 | 150 | @param prng The PRNG to export |
140 | 151 | @return CRYPT_OK if successful |
141 | 152 | */ |
142 | int sober128_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
143 | { | |
144 | unsigned long len = sizeof(sober128_state); | |
153 | int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
154 | { | |
155 | unsigned long len = sober128_desc.export_size; | |
156 | ||
157 | LTC_ARGCHK(prng != NULL); | |
158 | LTC_ARGCHK(out != NULL); | |
145 | 159 | LTC_ARGCHK(outlen != NULL); |
146 | LTC_ARGCHK(out != NULL); | |
147 | LTC_ARGCHK(prng != NULL); | |
148 | ||
149 | if (!prng->sober128.ready) { | |
150 | return CRYPT_ERROR; | |
151 | } | |
160 | ||
152 | 161 | if (*outlen < len) { |
153 | 162 | *outlen = len; |
154 | 163 | return CRYPT_BUFFER_OVERFLOW; |
155 | 164 | } |
156 | XMEMCPY(out, &prng->sober128.s, len); | |
165 | ||
166 | if (sober128_read(out, len, prng) != len) { | |
167 | return CRYPT_ERROR_READPRNG; | |
168 | } | |
169 | ||
157 | 170 | *outlen = len; |
158 | 171 | return CRYPT_OK; |
159 | 172 | } |
165 | 178 | @param prng The PRNG to import |
166 | 179 | @return CRYPT_OK if successful |
167 | 180 | */ |
168 | int sober128_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
169 | { | |
170 | unsigned long len = sizeof(sober128_state); | |
181 | int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
182 | { | |
183 | int err; | |
184 | ||
185 | LTC_ARGCHK(prng != NULL); | |
171 | 186 | LTC_ARGCHK(in != NULL); |
172 | LTC_ARGCHK(prng != NULL); | |
173 | ||
174 | if (inlen != len) return CRYPT_INVALID_ARG; | |
175 | XMEMCPY(&prng->sober128.s, in, inlen); | |
176 | prng->sober128.ready = 1; | |
187 | if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG; | |
188 | ||
189 | if ((err = sober128_start(prng)) != CRYPT_OK) return err; | |
190 | if ((err = sober128_add_entropy(in, sober128_desc.export_size, prng)) != CRYPT_OK) return err; | |
177 | 191 | return CRYPT_OK; |
178 | 192 | } |
179 | 193 | |
181 | 195 | PRNG self-test |
182 | 196 | @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled |
183 | 197 | */ |
184 | int sober128_prng_test(void) | |
198 | int sober128_test(void) | |
185 | 199 | { |
186 | 200 | #ifndef LTC_TEST |
187 | 201 | return CRYPT_NOP; |
196 | 210 | unsigned long dmplen = sizeof(dmp); |
197 | 211 | unsigned char out[500]; |
198 | 212 | 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); | |
213 | unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 }; | |
214 | unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 }; | |
215 | int err; | |
216 | ||
217 | if ((err = sober128_start(&st)) != CRYPT_OK) return err; | |
218 | /* add entropy to uninitialized prng */ | |
219 | if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
220 | if ((err = sober128_ready(&st)) != CRYPT_OK) return err; | |
221 | if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
222 | if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; | |
223 | if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
224 | /* add entropy to already initialized prng */ | |
225 | if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
226 | if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
227 | if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; | |
228 | if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
229 | if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
230 | if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; | |
231 | if ((err = sober128_done(&st)) != CRYPT_OK) return err; | |
232 | if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err; | |
233 | if ((err = sober128_ready(&st)) != CRYPT_OK) return err; | |
234 | if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
235 | if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ | |
236 | if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; | |
237 | if ((err = sober128_done(&st)) != CRYPT_OK) return err; | |
221 | 238 | |
222 | 239 | return CRYPT_OK; |
223 | 240 | #endif |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 | |
134 | 132 | */ |
135 | 133 | int sprng_test(void) |
136 | 134 | { |
135 | #ifndef LTC_TEST | |
136 | return CRYPT_NOP; | |
137 | #else | |
138 | prng_state st; | |
139 | unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 }; | |
140 | unsigned char out[1000]; | |
141 | int err; | |
142 | ||
143 | if ((err = sprng_start(&st)) != CRYPT_OK) return err; | |
144 | if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; | |
145 | if ((err = sprng_ready(&st)) != CRYPT_OK) return err; | |
146 | if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ | |
147 | if ((err = sprng_done(&st)) != CRYPT_OK) return err; | |
148 | ||
137 | 149 | return CRYPT_OK; |
150 | #endif | |
138 | 151 | } |
139 | 152 | |
140 | 153 | #endif |
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 | */ |
10 | 8 | #include "tomcrypt.h" |
11 | 9 | |
39 | 37 | int err; |
40 | 38 | |
41 | 39 | LTC_ARGCHK(prng != NULL); |
40 | prng->ready = 0; | |
42 | 41 | |
43 | 42 | /* these are the default hash/cipher combo used */ |
44 | 43 | #ifdef LTC_RIJNDAEL |
119 | 118 | |
120 | 119 | /* zero the memory used */ |
121 | 120 | zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool)); |
122 | LTC_MUTEX_INIT(&prng->yarrow.prng_lock) | |
121 | LTC_MUTEX_INIT(&prng->lock) | |
123 | 122 | |
124 | 123 | return CRYPT_OK; |
125 | 124 | } |
136 | 135 | hash_state md; |
137 | 136 | int err; |
138 | 137 | |
139 | LTC_ARGCHK(in != NULL); | |
140 | LTC_ARGCHK(prng != NULL); | |
141 | ||
142 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
138 | LTC_ARGCHK(prng != NULL); | |
139 | LTC_ARGCHK(in != NULL); | |
140 | LTC_ARGCHK(inlen > 0); | |
141 | ||
142 | LTC_MUTEX_LOCK(&prng->lock); | |
143 | 143 | |
144 | 144 | if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { |
145 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
146 | return err; | |
145 | goto LBL_UNLOCK; | |
147 | 146 | } |
148 | 147 | |
149 | 148 | /* start the hash */ |
150 | 149 | if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { |
151 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
152 | return err; | |
150 | goto LBL_UNLOCK; | |
153 | 151 | } |
154 | 152 | |
155 | 153 | /* hash the current pool */ |
156 | 154 | if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, |
157 | 155 | hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { |
158 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
159 | return err; | |
156 | goto LBL_UNLOCK; | |
160 | 157 | } |
161 | 158 | |
162 | 159 | /* add the new entropy */ |
163 | 160 | if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { |
164 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
165 | return err; | |
161 | goto LBL_UNLOCK; | |
166 | 162 | } |
167 | 163 | |
168 | 164 | /* store result */ |
169 | if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { | |
170 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
171 | return err; | |
172 | } | |
173 | ||
174 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
175 | return CRYPT_OK; | |
165 | err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool); | |
166 | ||
167 | LBL_UNLOCK: | |
168 | LTC_MUTEX_UNLOCK(&prng->lock); | |
169 | return err; | |
176 | 170 | } |
177 | 171 | |
178 | 172 | /** |
185 | 179 | int ks, err; |
186 | 180 | |
187 | 181 | LTC_ARGCHK(prng != NULL); |
188 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
182 | ||
183 | LTC_MUTEX_LOCK(&prng->lock); | |
189 | 184 | |
190 | 185 | if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { |
191 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
192 | return err; | |
186 | goto LBL_UNLOCK; | |
193 | 187 | } |
194 | 188 | |
195 | 189 | if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { |
196 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
197 | return err; | |
190 | goto LBL_UNLOCK; | |
198 | 191 | } |
199 | 192 | |
200 | 193 | /* setup CTR mode using the "pool" as the key */ |
201 | 194 | ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; |
202 | 195 | if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { |
203 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
204 | return err; | |
196 | goto LBL_UNLOCK; | |
205 | 197 | } |
206 | 198 | |
207 | 199 | if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ |
210 | 202 | 0, /* number of rounds */ |
211 | 203 | CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ |
212 | 204 | &prng->yarrow.ctr)) != CRYPT_OK) { |
213 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
214 | return err; | |
215 | } | |
216 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
217 | return CRYPT_OK; | |
205 | goto LBL_UNLOCK; | |
206 | } | |
207 | prng->ready = 1; | |
208 | ||
209 | LBL_UNLOCK: | |
210 | LTC_MUTEX_UNLOCK(&prng->lock); | |
211 | return err; | |
218 | 212 | } |
219 | 213 | |
220 | 214 | /** |
226 | 220 | */ |
227 | 221 | unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) |
228 | 222 | { |
229 | LTC_ARGCHK(out != NULL); | |
230 | LTC_ARGCHK(prng != NULL); | |
231 | ||
232 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
223 | if (outlen == 0 || prng == NULL || out == NULL) return 0; | |
224 | ||
225 | LTC_MUTEX_LOCK(&prng->lock); | |
226 | ||
227 | if (!prng->ready) { | |
228 | outlen = 0; | |
229 | goto LBL_UNLOCK; | |
230 | } | |
233 | 231 | |
234 | 232 | /* put out in predictable state first */ |
235 | 233 | zeromem(out, outlen); |
236 | 234 | |
237 | 235 | /* now randomize it */ |
238 | 236 | if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { |
239 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
240 | return 0; | |
241 | } | |
242 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
237 | outlen = 0; | |
238 | } | |
239 | ||
240 | LBL_UNLOCK: | |
241 | LTC_MUTEX_UNLOCK(&prng->lock); | |
243 | 242 | return outlen; |
244 | 243 | } |
245 | 244 | |
253 | 252 | int err; |
254 | 253 | LTC_ARGCHK(prng != NULL); |
255 | 254 | |
256 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
255 | LTC_MUTEX_LOCK(&prng->lock); | |
256 | prng->ready = 0; | |
257 | 257 | |
258 | 258 | /* call cipher done when we invent one ;-) */ |
259 | 259 | |
260 | 260 | /* we invented one */ |
261 | 261 | err = ctr_done(&prng->yarrow.ctr); |
262 | 262 | |
263 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
263 | LTC_MUTEX_UNLOCK(&prng->lock); | |
264 | 264 | return err; |
265 | 265 | } |
266 | 266 | |
273 | 273 | */ |
274 | 274 | int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) |
275 | 275 | { |
276 | unsigned long len = yarrow_desc.export_size; | |
277 | ||
276 | 278 | LTC_ARGCHK(out != NULL); |
277 | 279 | LTC_ARGCHK(outlen != NULL); |
278 | 280 | LTC_ARGCHK(prng != NULL); |
279 | 281 | |
280 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
281 | ||
282 | /* we'll write 64 bytes for s&g's */ | |
283 | if (*outlen < 64) { | |
284 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
285 | *outlen = 64; | |
282 | if (*outlen < len) { | |
283 | *outlen = len; | |
286 | 284 | return CRYPT_BUFFER_OVERFLOW; |
287 | 285 | } |
288 | 286 | |
289 | if (yarrow_read(out, 64, prng) != 64) { | |
290 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
287 | if (yarrow_read(out, len, prng) != len) { | |
291 | 288 | return CRYPT_ERROR_READPRNG; |
292 | 289 | } |
293 | *outlen = 64; | |
294 | ||
290 | ||
291 | *outlen = len; | |
295 | 292 | return CRYPT_OK; |
296 | 293 | } |
297 | 294 | |
308 | 305 | |
309 | 306 | LTC_ARGCHK(in != NULL); |
310 | 307 | LTC_ARGCHK(prng != NULL); |
311 | ||
312 | LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
313 | ||
314 | if (inlen != 64) { | |
315 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
316 | return CRYPT_INVALID_ARG; | |
317 | } | |
318 | ||
319 | if ((err = yarrow_start(prng)) != CRYPT_OK) { | |
320 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
321 | return err; | |
322 | } | |
323 | err = yarrow_add_entropy(in, 64, prng); | |
324 | LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
325 | return err; | |
308 | if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; | |
309 | ||
310 | if ((err = yarrow_start(prng)) != CRYPT_OK) return err; | |
311 | if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; | |
312 | return CRYPT_OK; | |
326 | 313 | } |
327 | 314 | |
328 | 315 | /** |
70 | 70 | } |
71 | 71 | for (;;) { |
72 | 72 | _chacha_block(buf, st->input, st->rounds); |
73 | /* increment the counter */ | |
74 | if (!++st->input[12] && !++st->input[13] && !++st->input[14]) { ++st->input[15]; } | |
73 | if (st->ivlen == 8) { | |
74 | /* IV-64bit, increment 64bit counter */ | |
75 | if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; | |
76 | } | |
77 | else { | |
78 | /* IV-96bit, increment 32bit counter */ | |
79 | if (0 == ++st->input[12]) return CRYPT_OVERFLOW; | |
80 | } | |
75 | 81 | if (inlen <= 64) { |
76 | 82 | for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; |
77 | 83 | st->ksleft = 64 - inlen; |
83 | 89 | out += 64; |
84 | 90 | in += 64; |
85 | 91 | } |
86 | return CRYPT_OK; | |
87 | }; | |
92 | } | |
88 | 93 | |
89 | 94 | #endif |
20 | 20 | LTC_ARGCHK(st != NULL); |
21 | 21 | XMEMSET(st, 0, sizeof(chacha_state)); |
22 | 22 | return CRYPT_OK; |
23 | }; | |
23 | } | |
24 | 24 | |
25 | 25 | #endif |
15 | 15 | |
16 | 16 | #ifdef LTC_CHACHA |
17 | 17 | |
18 | static const char sigma[16] = "expand 32-byte k"; | |
19 | static const char tau[16] = "expand 16-byte k"; | |
18 | static const char * const sigma = "expand 32-byte k"; | |
19 | static const char * const tau = "expand 16-byte k"; | |
20 | 20 | |
21 | 21 | /** |
22 | 22 | Initialize an ChaCha context (only the key) |
52 | 52 | LOAD32L(st->input[1], constants + 4); |
53 | 53 | LOAD32L(st->input[2], constants + 8); |
54 | 54 | LOAD32L(st->input[3], constants + 12); |
55 | st->rounds = rounds; /* e.g. 20 for chacha20 */ | |
55 | st->rounds = rounds; /* e.g. 20 for chacha20 */ | |
56 | st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */ | |
56 | 57 | return CRYPT_OK; |
57 | }; | |
58 | } | |
58 | 59 | |
59 | 60 | #endif |
8 | 8 | |
9 | 9 | #include "tomcrypt.h" |
10 | 10 | |
11 | #ifdef LTC_RC4 | |
11 | #ifdef LTC_RC4_STREAM | |
12 | 12 | |
13 | 13 | /** |
14 | 14 | Initialize an RC4 context (only the key) |
17 | 17 | @param keylen The length of the secret key (8 - 256 bytes) |
18 | 18 | @return CRYPT_OK if successful |
19 | 19 | */ |
20 | int rc4_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) | |
20 | int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) | |
21 | 21 | { |
22 | 22 | unsigned char tmp, *s; |
23 | 23 | int x, y; |
53 | 53 | @param out [out] The ciphertext (or plaintext), length inlen |
54 | 54 | @return CRYPT_OK if successful |
55 | 55 | */ |
56 | int rc4_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
56 | int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
57 | 57 | { |
58 | 58 | unsigned char x, y, *s, tmp; |
59 | 59 | |
83 | 83 | @param outlen The output length |
84 | 84 | @return CRYPT_OK on success |
85 | 85 | */ |
86 | int rc4_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) | |
86 | int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) | |
87 | 87 | { |
88 | 88 | if (outlen == 0) return CRYPT_OK; /* nothing to do */ |
89 | 89 | LTC_ARGCHK(out != NULL); |
90 | 90 | XMEMSET(out, 0, outlen); |
91 | return rc4_crypt(st, out, outlen, out); | |
91 | return rc4_stream_crypt(st, out, outlen, out); | |
92 | 92 | } |
93 | 93 | |
94 | 94 | /** |
96 | 96 | @param st The RC4 state |
97 | 97 | @return CRYPT_OK on success |
98 | 98 | */ |
99 | int rc4_done(rc4_state *st) | |
99 | int rc4_stream_done(rc4_state *st) | |
100 | 100 | { |
101 | 101 | LTC_ARGCHK(st != NULL); |
102 | 102 | XMEMSET(st, 0, sizeof(rc4_state)); |
160 | 160 | @param keylen The length of the secret key (octets) |
161 | 161 | @return CRYPT_OK if successful |
162 | 162 | */ |
163 | int sober128_setup(sober128_state *c, const unsigned char *key, unsigned long keylen) | |
163 | int sober128_stream_setup(sober128_state *c, const unsigned char *key, unsigned long keylen) | |
164 | 164 | { |
165 | 165 | ulong32 i, k; |
166 | 166 | |
207 | 207 | @param inlen The length of the IV (must be 12) |
208 | 208 | @return CRYPT_OK on success |
209 | 209 | */ |
210 | int sober128_setiv(sober128_state *c, const unsigned char *iv, unsigned long ivlen) | |
210 | int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned long ivlen) | |
211 | 211 | { |
212 | 212 | ulong32 i, k; |
213 | 213 | |
252 | 252 | @param out [out] The ciphertext (or plaintext), length inlen |
253 | 253 | @return CRYPT_OK if successful |
254 | 254 | */ |
255 | int sober128_crypt(sober128_state *c, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
255 | int sober128_stream_crypt(sober128_state *c, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
256 | 256 | { |
257 | 257 | ulong32 t; |
258 | 258 | |
320 | 320 | return CRYPT_OK; |
321 | 321 | } |
322 | 322 | |
323 | int sober128_keystream(sober128_state *c, unsigned char *out, unsigned long outlen) | |
323 | int sober128_stream_keystream(sober128_state *c, unsigned char *out, unsigned long outlen) | |
324 | 324 | { |
325 | 325 | if (outlen == 0) return CRYPT_OK; /* nothing to do */ |
326 | 326 | LTC_ARGCHK(out != NULL); |
327 | 327 | XMEMSET(out, 0, outlen); |
328 | return sober128_crypt(c, out, outlen, out); | |
328 | return sober128_stream_crypt(c, out, outlen, out); | |
329 | 329 | } |
330 | 330 | |
331 | 331 | /** |
333 | 333 | @param c The Sober128 state |
334 | 334 | @return CRYPT_OK on success |
335 | 335 | */ |
336 | int sober128_done(sober128_state *c) | |
336 | int sober128_stream_done(sober128_state *c) | |
337 | 337 | { |
338 | 338 | LTC_ARGCHK(c != NULL); |
339 | 339 | XMEMSET(c, 0, sizeof(sober128_state)); |