Skip to content

Commit

Permalink
Merge pull request #5 from firezone/keys-byte-array
Browse files Browse the repository at this point in the history
Use byte arrays instead of base64 strings
  • Loading branch information
Andrew Rousset authored Jun 9, 2022
2 parents 3182828 + 4b5f704 commit 4c167b0
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 51 deletions.
9 changes: 6 additions & 3 deletions lib/wireguardex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,20 @@ defmodule Wireguardex do
def add_peer(_name, _peer), do: error()

@doc """
Generates a random private key. It is returned as a base64 string.
Generates a random private key. It is returned as a byte array.
"""
def generate_private_key(), do: error()

@doc """
Generates a random preshared key. It is returned as a base64 string.
Generates a random preshared key. It is returned as a byte array.
"""
def generate_preshared_key(), do: error()

@doc """
Return a private key's public key as a base64 string.
Return a private key's public key as a byte array.
Returns `{:ok, [...]}` if successful. `{:error, error_info}` will be returned if
if getting the public key fails.
"""
def get_public_key(_private_key), do: error()

Expand Down
5 changes: 3 additions & 2 deletions lib/wireguardex/peer_config_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ defmodule Wireguardex.PeerConfigBuilder do
## Examples
iex> res =
iex> { :ok, public_key } = Wireguardex.get_public_key(Wireguardex.generate_private_key())
...> res =
...> device_config()
...> |> peers([
...> peer_config()
...> |> Wireguardex.PeerConfigBuilder.public_key(Wireguardex.get_public_key(Wireguardex.generate_private_key()))
...> |> Wireguardex.PeerConfigBuilder.public_key(public_key)
...> |> endpoint("127.0.0.1:1234")
...> |> preshared_key(Wireguardex.generate_preshared_key())
...> |> persistent_keepalive_interval(60)
Expand Down
23 changes: 11 additions & 12 deletions native/wireguard_nif/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::convert::{TryFrom, TryInto};
use rustler::{types::atom, Atom, Error, NifResult, NifStruct};
use wireguard_control::{Backend, Device, DeviceUpdate, InterfaceName, PeerConfigBuilder};

use crate::key;
use crate::key::{vec_to_key, NifKey};
use crate::peer::{NifPeerConfig, NifPeerInfo};

#[cfg(target_os = "linux")]
Expand All @@ -17,8 +17,8 @@ const BACKEND: Backend = Backend::Userspace;
#[module = "Wireguardex.Device"]
struct NifDevice {
name: String,
public_key: Option<String>,
private_key: Option<String>,
public_key: Option<NifKey>,
private_key: Option<NifKey>,
fwmark: Option<u32>,
listen_port: Option<u16>,
peers: Vec<NifPeerInfo>,
Expand All @@ -29,8 +29,8 @@ impl From<Device> for NifDevice {
fn from(d: Device) -> Self {
Self {
name: d.name.as_str_lossy().to_string(),
public_key: d.public_key.map(|k| k.to_base64()),
private_key: d.private_key.map(|k| k.to_base64()),
public_key: d.public_key.map(|k| k.0.to_vec()),
private_key: d.private_key.map(|k| k.0.to_vec()),
fwmark: d.fwmark,
listen_port: d.listen_port,
peers: d.peers.into_iter().map(|p| p.into()).collect(),
Expand All @@ -55,10 +55,10 @@ impl TryFrom<NifDeviceConfig> for DeviceUpdate {
.collect::<NifResult<Vec<PeerConfigBuilder>>>()?;

if let Some(public_key) = public_key {
device = device.set_public_key(key::from_base64(&public_key)?);
device = device.set_public_key(vec_to_key(public_key)?);
}
if let Some(private_key) = private_key {
device = device.set_private_key(key::from_base64(&private_key)?);
device = device.set_private_key(vec_to_key(private_key)?);
}
if let Some(fwmark) = fwmark {
device = device.set_fwmark(fwmark);
Expand All @@ -77,8 +77,8 @@ impl TryFrom<NifDeviceConfig> for DeviceUpdate {
#[derive(NifStruct)]
#[module = "Wireguardex.DeviceConfig"]
struct NifDeviceConfig {
public_key: Option<String>,
private_key: Option<String>,
public_key: Option<NifKey>,
private_key: Option<NifKey>,
fwmark: Option<u32>,
listen_port: Option<u16>,
peers: Vec<NifPeerConfig>,
Expand Down Expand Up @@ -122,10 +122,9 @@ fn delete_device(name: &str) -> NifResult<Atom> {
}

#[rustler::nif]
fn remove_peer(name: &str, public_key: &str) -> NifResult<Atom> {
fn remove_peer(name: &str, public_key: NifKey) -> NifResult<Atom> {
let iname = parse_iname(name)?;
let key = key::from_base64(public_key)?;
let device = DeviceUpdate::new().remove_peer_by_key(&key);
let device = DeviceUpdate::new().remove_peer_by_key(&vec_to_key(public_key)?);

to_term_error(device.apply(&iname, BACKEND))?;

Expand Down
32 changes: 15 additions & 17 deletions native/wireguard_nif/src/key.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
//! nif bindings for generating wireguard keys
use rustler::NifResult;
use wireguard_control::Key;
use std::convert::TryInto;

use crate::device::to_term_error;
use rustler::{types::atom, Atom, NifResult};
use wireguard_control::Key;

#[rustler::nif]
fn generate_private_key() -> String {
let key = Key::generate_private();
pub type NifKey = Vec<u8>;

key.to_base64()
pub(crate) fn vec_to_key(k: NifKey) -> NifResult<Key> {
Ok(Key(k.try_into().map_err(|_| {
rustler::Error::Term(Box::new("Key is either too long or too short"))
})?))
}

#[rustler::nif]
fn generate_preshared_key() -> String {
let key = Key::generate_preshared();

key.to_base64()
fn generate_private_key() -> NifKey {
Key::generate_private().0.to_vec()
}

#[rustler::nif]
fn get_public_key(key: &str) -> NifResult<String> {
let key = from_base64(key)?;

Ok(key.get_public().to_base64())
fn generate_preshared_key() -> NifKey {
Key::generate_preshared().0.to_vec()
}

pub(crate) fn from_base64(key: &str) -> NifResult<Key> {
to_term_error(Key::from_base64(key))
#[rustler::nif]
fn get_public_key(key: NifKey) -> NifResult<(Atom, NifKey)> {
Ok((atom::ok(), vec_to_key(key)?.get_public().0.to_vec()))
}
2 changes: 1 addition & 1 deletion native/wireguard_nif/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod device;
mod key;
mod peer;

use device::{delete_device, get_device, list_devices, remove_peer, set_device, add_peer};
use device::{add_peer, delete_device, get_device, list_devices, remove_peer, set_device};
use key::{generate_preshared_key, generate_private_key, get_public_key};

rustler::init!(
Expand Down
17 changes: 9 additions & 8 deletions native/wireguard_nif/src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use std::time::SystemTime;
use rustler::{Error, NifResult, NifStruct};
use wireguard_control::{AllowedIp, PeerConfig, PeerConfigBuilder, PeerInfo, PeerStats};

use crate::{device::to_term_error, key};
use crate::key::vec_to_key;
use crate::{device::to_term_error, key::NifKey};

#[derive(NifStruct)]
#[module = "Wireguardex.PeerConfig"]
pub(crate) struct NifPeerConfig {
public_key: String,
preshared_key: Option<String>,
public_key: NifKey,
preshared_key: Option<NifKey>,
endpoint: Option<String>,
persistent_keepalive_interval: Option<u16>,
allowed_ips: Vec<String>,
Expand All @@ -21,8 +22,8 @@ pub(crate) struct NifPeerConfig {
impl From<PeerConfig> for NifPeerConfig {
fn from(config: PeerConfig) -> Self {
Self {
public_key: config.public_key.to_base64(),
preshared_key: config.preshared_key.map(|k| k.to_base64()),
public_key: config.public_key.0.to_vec(),
preshared_key: config.preshared_key.map(|k| k.0.to_vec()),
endpoint: config.endpoint.map(|e| e.to_string()),
persistent_keepalive_interval: config.persistent_keepalive_interval,
allowed_ips: config
Expand All @@ -38,7 +39,7 @@ impl TryFrom<NifPeerConfig> for PeerConfigBuilder {
type Error = Error;

fn try_from(nif_config: NifPeerConfig) -> NifResult<Self> {
let public_key = key::from_base64(&nif_config.public_key)?;
let public_key = nif_config.public_key;
let preshared_key = nif_config.preshared_key;
let endpoint = nif_config.endpoint;
let persistent_keepalive_interval = nif_config.persistent_keepalive_interval;
Expand All @@ -52,10 +53,10 @@ impl TryFrom<NifPeerConfig> for PeerConfigBuilder {
})
.collect::<NifResult<Vec<AllowedIp>>>()?;

let mut config = PeerConfigBuilder::new(&public_key);
let mut config = PeerConfigBuilder::new(&vec_to_key(public_key)?);

if let Some(preshared_key) = preshared_key {
config = config.set_preshared_key(key::from_base64(&preshared_key)?);
config = config.set_preshared_key(vec_to_key(preshared_key)?);
}
if let Some(endpoint) = endpoint {
config = config.set_endpoint(to_term_error(endpoint.parse())?);
Expand Down
17 changes: 9 additions & 8 deletions test/wireguardex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defmodule WireguardexTest do
test "set device" do
interface_name = "wg0"
private_key = Wireguardex.generate_private_key()
public_key = Wireguardex.get_public_key(private_key)
{:ok, public_key} = Wireguardex.get_public_key(private_key)
listen_port = 58210
fwmark = 1234

Expand Down Expand Up @@ -44,19 +44,18 @@ defmodule WireguardexTest do
test "add peers to device" do
interface_name = "wg2"

{:ok, public_key_0} = Wireguardex.get_public_key(Wireguardex.generate_private_key())
{:ok, public_key_1} = Wireguardex.get_public_key(Wireguardex.generate_private_key())

peers = [
peer_config()
|> Wireguardex.PeerConfigBuilder.public_key(
Wireguardex.get_public_key(Wireguardex.generate_private_key())
)
|> Wireguardex.PeerConfigBuilder.public_key(public_key_0)
|> preshared_key(Wireguardex.generate_preshared_key())
|> endpoint("127.0.0.1:1234")
|> persistent_keepalive_interval(60)
|> allowed_ips(["192.168.0.0/24", "163.23.42.242/32"]),
peer_config()
|> Wireguardex.PeerConfigBuilder.public_key(
Wireguardex.get_public_key(Wireguardex.generate_private_key())
)
|> Wireguardex.PeerConfigBuilder.public_key(public_key_1)
|> preshared_key(Wireguardex.generate_preshared_key())
|> endpoint("127.0.0.1:1234")
|> persistent_keepalive_interval(30)
Expand All @@ -78,8 +77,10 @@ defmodule WireguardexTest do
test "add peer to device after creation" do
interface_name = "wg3"

{:ok, public_key} = Wireguardex.get_public_key(Wireguardex.generate_private_key())

peer = %Wireguardex.PeerConfig{
public_key: Wireguardex.get_public_key(Wireguardex.generate_private_key()),
public_key: public_key,
preshared_key: Wireguardex.generate_preshared_key(),
endpoint: "127.0.0.1:1234",
persistent_keepalive_interval: 60,
Expand Down

0 comments on commit 4c167b0

Please sign in to comment.