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