1 /*
2 * (C) 2019 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6 
7 #include <botan/sodium.h>
8 #include <botan/stream_cipher.h>
9 
10 namespace Botan {
11 
crypto_stream_chacha20(uint8_t out[],size_t out_len,const uint8_t nonce[],const uint8_t key[])12 int Sodium::crypto_stream_chacha20(uint8_t out[], size_t out_len,
13                                    const uint8_t nonce[], const uint8_t key[])
14    {
15    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
16    chacha->set_key(key, crypto_stream_chacha20_KEYBYTES);
17    chacha->set_iv(nonce, crypto_stream_chacha20_NONCEBYTES);
18    chacha->write_keystream(out, out_len);
19    return 0;
20    }
21 
crypto_stream_chacha20_xor(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],const uint8_t key[])22 int Sodium::crypto_stream_chacha20_xor(uint8_t out[], const uint8_t in[],
23                                        size_t in_len, const uint8_t nonce[],
24                                        const uint8_t key[])
25    {
26    return crypto_stream_chacha20_xor_ic(out, in, in_len, nonce, 0, key);
27    }
28 
crypto_stream_chacha20_xor_ic(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],uint64_t ic,const uint8_t key[])29 int Sodium::crypto_stream_chacha20_xor_ic(uint8_t out[], const uint8_t in[],
30                                           size_t in_len,
31                                           const uint8_t nonce[], uint64_t ic,
32                                           const uint8_t key[])
33    {
34    if((ic >> 6) != 0) // otherwise multiply overflows
35       return -1;
36 
37    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
38    chacha->set_key(key, crypto_stream_chacha20_KEYBYTES);
39    chacha->set_iv(nonce, crypto_stream_chacha20_NONCEBYTES);
40    chacha->seek(ic * 64);
41    chacha->cipher(in, out, in_len);
42    return 0;
43    }
44 
crypto_stream_chacha20_ietf(uint8_t out[],size_t out_len,const uint8_t nonce[],const uint8_t key[])45 int Sodium::crypto_stream_chacha20_ietf(uint8_t out[], size_t out_len,
46                                         const uint8_t nonce[], const uint8_t key[])
47    {
48    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
49    chacha->set_key(key, crypto_stream_chacha20_ietf_KEYBYTES);
50    chacha->set_iv(nonce, crypto_stream_chacha20_ietf_NONCEBYTES);
51    chacha->write_keystream(out, out_len);
52    return 0;
53    }
54 
crypto_stream_chacha20_ietf_xor(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],const uint8_t key[])55 int Sodium::crypto_stream_chacha20_ietf_xor(uint8_t out[],
56                                             const uint8_t in[], size_t in_len,
57                                             const uint8_t nonce[],
58                                             const uint8_t key[])
59    {
60    return crypto_stream_chacha20_ietf_xor_ic(out, in, in_len, nonce, 0, key);
61    }
62 
crypto_stream_chacha20_ietf_xor_ic(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],uint32_t ic,const uint8_t key[])63 int Sodium::crypto_stream_chacha20_ietf_xor_ic(uint8_t out[],
64                                                const uint8_t in[], size_t in_len,
65                                                const uint8_t nonce[], uint32_t ic,
66                                                const uint8_t key[])
67    {
68    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
69    chacha->set_key(key, crypto_stream_chacha20_ietf_KEYBYTES);
70    chacha->set_iv(nonce, crypto_stream_chacha20_ietf_NONCEBYTES);
71    chacha->seek(static_cast<uint64_t>(ic) * 64);
72    chacha->cipher(in, out, in_len);
73    return 0;
74    }
75 
crypto_stream_xchacha20(uint8_t out[],size_t out_len,const uint8_t nonce[],const uint8_t key[])76 int Sodium::crypto_stream_xchacha20(uint8_t out[], size_t out_len,
77                                     const uint8_t nonce[], const uint8_t key[])
78    {
79    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
80    chacha->set_key(key, crypto_stream_xchacha20_KEYBYTES);
81    chacha->set_iv(nonce, crypto_stream_xchacha20_NONCEBYTES);
82    chacha->write_keystream(out, out_len);
83    return 0;
84    }
85 
crypto_stream_xchacha20_xor(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],const uint8_t key[])86 int Sodium::crypto_stream_xchacha20_xor(uint8_t out[], const uint8_t in[],
87                                        size_t in_len, const uint8_t nonce[],
88                                        const uint8_t key[])
89    {
90    return crypto_stream_xchacha20_xor_ic(out, in, in_len, nonce, 0, key);
91    }
92 
crypto_stream_xchacha20_xor_ic(uint8_t out[],const uint8_t in[],size_t in_len,const uint8_t nonce[],uint64_t ic,const uint8_t key[])93 int Sodium::crypto_stream_xchacha20_xor_ic(uint8_t out[], const uint8_t in[],
94                                            size_t in_len,
95                                            const uint8_t nonce[], uint64_t ic,
96                                            const uint8_t key[])
97    {
98    if((ic >> 6) != 0) // otherwise multiply overflows
99       return -1;
100 
101    auto chacha = StreamCipher::create_or_throw("ChaCha(20)");
102    chacha->set_key(key, crypto_stream_xchacha20_KEYBYTES);
103    chacha->set_iv(nonce, crypto_stream_xchacha20_NONCEBYTES);
104    chacha->seek(ic * 64);
105    chacha->cipher(in, out, in_len);
106    return 0;
107    }
108 
109 }
110