SEXP R_stream_chacha20(SEXP n, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_stream_chacha20_KEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_stream_chacha20_KEYBYTES); if(LENGTH(nonce) != crypto_stream_chacha20_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_stream_chacha20_NONCEBYTES); unsigned long long clen = (unsigned long long) asReal(n); SEXP res = allocVector(RAWSXP, clen); crypto_stream_chacha20(RAW(res), clen, RAW(nonce), RAW(key)); return res; }
int crypto_stream_xchacha20(unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) { unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES]; crypto_core_hchacha20(k2, n, k, NULL); assert(crypto_stream_chacha20_KEYBYTES <= sizeof k2); assert(crypto_stream_chacha20_NONCEBYTES == (sizeof n) - crypto_core_hchacha20_INPUTBYTES); return crypto_stream_chacha20(c, clen, n + crypto_core_hchacha20_INPUTBYTES, k2); }
int crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *mac, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) { crypto_onetimeauth_poly1305_state state; unsigned char block0[64U]; unsigned char slen[8U]; unsigned char computed_mac[crypto_aead_chacha20poly1305_ABYTES]; unsigned long long mlen; int ret; (void) nsec; crypto_stream_chacha20(block0, sizeof block0, npub, k); crypto_onetimeauth_poly1305_init(&state, block0); sodium_memzero(block0, sizeof block0); crypto_onetimeauth_poly1305_update(&state, ad, adlen); STORE64_LE(slen, (uint64_t) adlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); mlen = clen; crypto_onetimeauth_poly1305_update(&state, c, mlen); STORE64_LE(slen, (uint64_t) mlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_onetimeauth_poly1305_final(&state, computed_mac); sodium_memzero(&state, sizeof state); COMPILER_ASSERT(sizeof computed_mac == 16U); ret = crypto_verify_16(computed_mac, mac); sodium_memzero(computed_mac, sizeof computed_mac); if (m == NULL) { return ret; } if (ret != 0) { memset(m, 0, mlen); return -1; } crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k); return 0; }
int crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c, unsigned char *mac, unsigned long long *maclen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) { crypto_onetimeauth_poly1305_state state; unsigned char block0[64U]; unsigned char slen[8U]; (void) nsec; crypto_stream_chacha20(block0, sizeof block0, npub, k); crypto_onetimeauth_poly1305_init(&state, block0); sodium_memzero(block0, sizeof block0); crypto_onetimeauth_poly1305_update(&state, ad, adlen); STORE64_LE(slen, (uint64_t) adlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k); crypto_onetimeauth_poly1305_update(&state, c, mlen); STORE64_LE(slen, (uint64_t) mlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_onetimeauth_poly1305_final(&state, mac); sodium_memzero(&state, sizeof state); if (maclen_p != NULL) { *maclen_p = crypto_aead_chacha20poly1305_ABYTES; } return 0; }
static void tv(void) { static struct { const char *key_hex; const char *nonce_hex; } tests[] = { { "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000" }, { "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000" }, { "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000001" }, { "0000000000000000000000000000000000000000000000000000000000000000", "0100000000000000" }, { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "0001020304050607" } }; unsigned char key[crypto_stream_chacha20_KEYBYTES]; unsigned char nonce[crypto_stream_chacha20_NONCEBYTES]; unsigned char *part; unsigned char out[160]; unsigned char zero[160]; char out_hex[160 * 2 + 1]; size_t i = 0U; size_t plen; memset(zero, 0, sizeof zero); do { sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex, strlen(tests[i].key_hex), NULL, NULL, NULL); sodium_hex2bin(nonce, sizeof nonce, tests[i].nonce_hex, strlen(tests[i].nonce_hex), NULL, NULL, NULL); crypto_stream_chacha20(out, sizeof out, nonce, key); sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); printf("[%s]\n", out_hex); for (plen = 1U; plen < sizeof out; plen++) { part = (unsigned char *) sodium_malloc(plen); crypto_stream_chacha20_xor(part, out, plen, nonce, key); if (memcmp(part, zero, plen) != 0) { printf("Failed with length %lu\n", (unsigned long) plen); } sodium_free(part); } } while (++i < (sizeof tests) / (sizeof tests[0])); randombytes_buf(out, sizeof out); crypto_stream_chacha20(out, sizeof out, nonce, key); sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); printf("[%s]\n", out_hex); assert(crypto_stream_chacha20(out, 0U, nonce, key) == 0); assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0); assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0); assert(crypto_stream_chacha20_xor_ic(out, out, 0U, nonce, 1U, key) == 0); memset(out, 0x42, sizeof out); crypto_stream_chacha20_xor(out, out, sizeof out, nonce, key); sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); printf("[%s]\n", out_hex); crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 0U, key); sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); printf("[%s]\n", out_hex); crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 1U, key); sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); printf("[%s]\n", out_hex); };