Mercurial > dropbear
comparison libtomcrypt/src/stream/chacha/chacha_crypt.c @ 1471:6dba84798cd5
Update to libtomcrypt 1.18.1, merged with Dropbear changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 09 Feb 2018 21:44:05 +0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1470:8bba51a55704 | 1471:6dba84798cd5 |
---|---|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
2 * | |
3 * LibTomCrypt is a library that provides various cryptographic | |
4 * algorithms in a highly modular and flexible manner. | |
5 * | |
6 * The library is free for all purposes without any express | |
7 * guarantee it works. | |
8 */ | |
9 | |
10 /* The implementation is based on: | |
11 * chacha-ref.c version 20080118 | |
12 * Public domain from D. J. Bernstein | |
13 */ | |
14 | |
15 #include "tomcrypt.h" | |
16 | |
17 #ifdef LTC_CHACHA | |
18 | |
19 #define QUARTERROUND(a,b,c,d) \ | |
20 x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \ | |
21 x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \ | |
22 x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \ | |
23 x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7); | |
24 | |
25 static void _chacha_block(unsigned char *output, const ulong32 *input, int rounds) | |
26 { | |
27 ulong32 x[16]; | |
28 int i; | |
29 XMEMCPY(x, input, sizeof(x)); | |
30 for (i = rounds; i > 0; i -= 2) { | |
31 QUARTERROUND(0, 4, 8,12) | |
32 QUARTERROUND(1, 5, 9,13) | |
33 QUARTERROUND(2, 6,10,14) | |
34 QUARTERROUND(3, 7,11,15) | |
35 QUARTERROUND(0, 5,10,15) | |
36 QUARTERROUND(1, 6,11,12) | |
37 QUARTERROUND(2, 7, 8,13) | |
38 QUARTERROUND(3, 4, 9,14) | |
39 } | |
40 for (i = 0; i < 16; ++i) { | |
41 x[i] += input[i]; | |
42 STORE32L(x[i], output + 4 * i); | |
43 } | |
44 } | |
45 | |
46 /** | |
47 Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha | |
48 @param st The ChaCha state | |
49 @param in The plaintext (or ciphertext) | |
50 @param inlen The length of the input (octets) | |
51 @param out [out] The ciphertext (or plaintext), length inlen | |
52 @return CRYPT_OK if successful | |
53 */ | |
54 int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
55 { | |
56 unsigned char buf[64]; | |
57 unsigned long i, j; | |
58 | |
59 if (inlen == 0) return CRYPT_OK; /* nothing to do */ | |
60 | |
61 LTC_ARGCHK(st != NULL); | |
62 LTC_ARGCHK(in != NULL); | |
63 LTC_ARGCHK(out != NULL); | |
64 LTC_ARGCHK(st->ivlen != 0); | |
65 | |
66 if (st->ksleft > 0) { | |
67 j = MIN(st->ksleft, inlen); | |
68 for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; | |
69 inlen -= j; | |
70 if (inlen == 0) return CRYPT_OK; | |
71 out += j; | |
72 in += j; | |
73 } | |
74 for (;;) { | |
75 _chacha_block(buf, st->input, st->rounds); | |
76 if (st->ivlen == 8) { | |
77 /* IV-64bit, increment 64bit counter */ | |
78 if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; | |
79 } | |
80 else { | |
81 /* IV-96bit, increment 32bit counter */ | |
82 if (0 == ++st->input[12]) return CRYPT_OVERFLOW; | |
83 } | |
84 if (inlen <= 64) { | |
85 for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; | |
86 st->ksleft = 64 - inlen; | |
87 for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; | |
88 return CRYPT_OK; | |
89 } | |
90 for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; | |
91 inlen -= 64; | |
92 out += 64; | |
93 in += 64; | |
94 } | |
95 } | |
96 | |
97 #endif | |
98 | |
99 /* ref: $Format:%D$ */ | |
100 /* git commit: $Format:%H$ */ | |
101 /* commit time: $Format:%ai$ */ |