| 251 | #define CHACHA20_BLOCK_BYTES 64 |
| 252 | |
| 253 | static void xor_cipher_stream_off(const struct secret *k, |
| 254 | size_t off, |
| 255 | void *dst, size_t dstlen) |
| 256 | { |
| 257 | const u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
| 258 | u8 block[CHACHA20_BLOCK_BYTES]; |
| 259 | size_t block_off; |
| 260 | size_t ic = off / CHACHA20_BLOCK_BYTES; |
| 261 | |
| 262 | /* From https://libsodium.gitbook.io/doc/advanced/stream_ciphers/chacha20: |
| 263 | * |
| 264 | * The crypto_stream_chacha20_xor_ic() function is similar to |
| 265 | * crypto_stream_chacha20_xor() but adds the ability to set |
| 266 | * the initial value of the block counter to a non-zero value, |
| 267 | * ic. |
| 268 | * |
| 269 | * This permits direct access to any block without having to |
| 270 | * compute the previous ones. |
| 271 | */ |
| 272 | block_off = (off % CHACHA20_BLOCK_BYTES); |
| 273 | if (block_off != 0) { |
| 274 | size_t rem = CHACHA20_BLOCK_BYTES - block_off; |
| 275 | if (rem > dstlen) |
| 276 | rem = dstlen; |
| 277 | memcpy(block + block_off, dst, rem); |
| 278 | crypto_stream_chacha20_xor_ic(block, block, block_off + rem, |
| 279 | nonce, |
| 280 | ic, |
| 281 | k->data); |
| 282 | ic++; |
| 283 | memcpy(dst, block + block_off, rem); |
| 284 | dst = (char *)dst + rem; |
| 285 | dstlen -= rem; |
| 286 | } |
| 287 | crypto_stream_chacha20_xor_ic(dst, dst, dstlen, nonce, ic, k->data); |
| 288 | } |
| 289 | |
| 290 | /* Convenience function: s2/s2len can be NULL/0 if unwanted */ |
| 291 | static void compute_hmac(const struct secret *key, |
no outgoing calls