crypto: use OCF to encrypt/decrypt packets when supported

This requires the the recent changes in FreeBSD to support the
Chacha20-Poly1305 AEAD cipher with support for an 8 byte nonce (vs the
12 byte nonce used by TLS and IPsec).

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
This commit is contained in:
John Baldwin 2021-10-11 11:27:16 -07:00 committed by Jason A. Donenfeld
parent b7441e3154
commit a6354a1436
3 changed files with 109 additions and 2 deletions

View File

@ -5,10 +5,16 @@
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <opencrypto/cryptodev.h>
#include "crypto.h"
#ifdef OCF_CHACHA20_POLY1305
static crypto_session_t chacha20_poly1305_sid;
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
@ -587,6 +593,63 @@ chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, const size_t src_len,
return ret;
}
#ifdef OCF_CHACHA20_POLY1305
static int
crypto_callback(struct cryptop *crp)
{
return (0);
}
int
chacha20poly1305_encrypt_mbuf(struct mbuf *m, const uint64_t nonce,
const uint8_t key[CHACHA20POLY1305_KEY_SIZE])
{
static char blank_tag[POLY1305_HASH_LEN];
struct cryptop crp;
int error;
if (!m_append(m, POLY1305_HASH_LEN, blank_tag))
return (ENOMEM);
crypto_initreq(&crp, chacha20_poly1305_sid);
crp.crp_op = CRYPTO_OP_ENCRYPT | CRYPTO_OP_COMPUTE_DIGEST;
crp.crp_flags = CRYPTO_F_IV_SEPARATE | CRYPTO_F_CBIMM;
crypto_use_mbuf(&crp, m);
crp.crp_payload_length = m->m_pkthdr.len - POLY1305_HASH_LEN;
crp.crp_digest_start = crp.crp_payload_length;
le64enc(crp.crp_iv, nonce);
crp.crp_cipher_key = key;
crp.crp_callback = crypto_callback;
error = crypto_dispatch(&crp);
crypto_destroyreq(&crp);
return (error);
}
int
chacha20poly1305_decrypt_mbuf(struct mbuf *m, const uint64_t nonce,
const uint8_t key[CHACHA20POLY1305_KEY_SIZE])
{
struct cryptop crp;
int error;
if (m->m_pkthdr.len < POLY1305_HASH_LEN)
return (EMSGSIZE);
crypto_initreq(&crp, chacha20_poly1305_sid);
crp.crp_op = CRYPTO_OP_DECRYPT | CRYPTO_OP_VERIFY_DIGEST;
crp.crp_flags = CRYPTO_F_IV_SEPARATE | CRYPTO_F_CBIMM;
crypto_use_mbuf(&crp, m);
crp.crp_payload_length = m->m_pkthdr.len - POLY1305_HASH_LEN;
crp.crp_digest_start = crp.crp_payload_length;
le64enc(crp.crp_iv, nonce);
crp.crp_cipher_key = key;
crp.crp_callback = crypto_callback;
error = crypto_dispatch(&crp);
crypto_destroyreq(&crp);
if (error != 0)
return (error);
m_adj(m, -POLY1305_HASH_LEN);
return (0);
}
#else
static inline int
chacha20poly1305_crypt_mbuf(struct mbuf *m0, uint64_t nonce,
const uint8_t key[CHACHA20POLY1305_KEY_SIZE], bool encrypt)
@ -678,6 +741,7 @@ chacha20poly1305_decrypt_mbuf(struct mbuf *m, const uint64_t nonce,
{
return chacha20poly1305_crypt_mbuf(m, nonce, key, false);
}
#endif
void
xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src,
@ -1784,3 +1848,32 @@ bool curve25519(uint8_t out[CURVE25519_KEY_SIZE],
return timingsafe_bcmp(out, curve25519_null_point, CURVE25519_KEY_SIZE) != 0;
}
int
crypto_init(void)
{
#ifdef OCF_CHACHA20_POLY1305
struct crypto_session_params csp;
int error;
memset(&csp, 0, sizeof(csp));
csp.csp_mode = CSP_MODE_AEAD;
csp.csp_ivlen = sizeof(uint64_t);
csp.csp_cipher_alg = CRYPTO_CHACHA20_POLY1305;
csp.csp_cipher_klen = CHACHA20POLY1305_KEY_SIZE;
csp.csp_flags = CSP_F_SEPARATE_AAD | CSP_F_SEPARATE_OUTPUT;
error = crypto_newsession(&chacha20_poly1305_sid, &csp,
CRYPTOCAP_F_SOFTWARE);
if (error != 0)
return (error);
#endif
return (0);
}
void
crypto_deinit(void)
{
#ifdef OCF_CHACHA20_POLY1305
crypto_freesession(chacha20_poly1305_sid);
#endif
}

View File

@ -6,9 +6,14 @@
#ifndef _WG_CRYPTO
#define _WG_CRYPTO
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#if __FreeBSD_version >= 1400036 || \
(__FreeBSD_version < 1400000 && __FreeBSD_version >= 1300519)
#define OCF_CHACHA20_POLY1305
#endif
enum chacha20poly1305_lengths {
XCHACHA20POLY1305_NONCE_SIZE = 24,
CHACHA20POLY1305_KEY_SIZE = 32,
@ -109,4 +114,7 @@ static inline void curve25519_generate_secret(uint8_t secret[CURVE25519_KEY_SIZE
curve25519_clamp_secret(secret);
}
int crypto_init(void);
void crypto_deinit(void);
#endif

View File

@ -2980,8 +2980,11 @@ wg_module_init(void)
if ((wg_packet_zone = uma_zcreate("wg packet", sizeof(struct wg_packet),
NULL, NULL, NULL, NULL, 0, 0)) == NULL)
goto free_none;
if (cookie_init() != 0)
ret = crypto_init();
if (ret != 0)
goto free_zone;
if (cookie_init() != 0)
goto free_crypto;
wg_osd_jail_slot = osd_jail_register(NULL, methods);
@ -2994,6 +2997,8 @@ wg_module_init(void)
free_all:
osd_jail_deregister(wg_osd_jail_slot);
cookie_deinit();
free_crypto:
crypto_deinit();
free_zone:
uma_zdestroy(wg_packet_zone);
free_none:
@ -3017,6 +3022,7 @@ wg_module_deinit(void)
MPASS(LIST_EMPTY(&wg_list));
osd_jail_deregister(wg_osd_jail_slot);
cookie_deinit();
crypto_deinit();
uma_zdestroy(wg_packet_zone);
}