aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crypto/curve25519.c4
-rw-r--r--src/crypto/pubkey.c50
-rw-r--r--src/crypto/pubkey.hpp7
-rw-r--r--src/wg2nd.cpp21
4 files changed, 73 insertions, 9 deletions
diff --git a/src/crypto/curve25519.c b/src/crypto/curve25519.c
index 7121d1e..2f6f5d6 100644
--- a/src/crypto/curve25519.c
+++ b/src/crypto/curve25519.c
@@ -79,7 +79,9 @@ static noinline void memzero_explicit(void *s, size_t count)
asm volatile("": :"r"(s) : "memory");
}
-#ifdef __SIZEOF_INT128__
+#ifdef __EMSCRIPTEN__
+#include "curve25519-fiat32.h"
+#elif __SIZEOF_INT128__
#include "curve25519-hacl64.h"
#else
#include "curve25519-fiat32.h"
diff --git a/src/crypto/pubkey.c b/src/crypto/pubkey.c
index 1224b07..f43dbfc 100644
--- a/src/crypto/pubkey.c
+++ b/src/crypto/pubkey.c
@@ -1,9 +1,43 @@
#include "curve25519.h"
#include "encoding.h"
-int wg_pubkey_base64(char const * privkey, char * base64) {
+#define WG_KEY_LEN_BASE32 (((WG_KEY_LEN + 4) / 5) * 8 + 1)
+#define WG_KEY_LEN_BASE64 ((((WG_KEY_LEN) + 2) / 3) * 4 + 1)
+
+static inline void encode_base32(char dest[static 8], const uint8_t src[static 5]) {
+ const uint8_t input[] = {
+ src[0] >> 3,
+ ((src[0] & 0x07) << 2) | (src[1] >> 6),
+ (src[1] & 0x3F) >> 1,
+ ((src[1] & 0x01) << 4) | (src[2] >> 4),
+ ((src[2] & 0x0F) << 1) | (src[3] >> 7),
+ (src[3] & 0x7F) >> 2,
+ ((src[3] & 0x03) << 3) | (src[4] >> 5),
+ src[4] & 0x1F
+ };
+
+ for(unsigned int i = 0; i < 8; i++)
+ dest[i] = 'A' + input[i] - (((25 - input[i]) >> 8) & 41);
+}
+
+void key_to_base32(char base32[static WG_KEY_LEN_BASE32], const uint8_t key[static WG_KEY_LEN])
+{
+ unsigned int i;
+
+ for (i = 0; i < WG_KEY_LEN / 5; ++i)
+ encode_base32(&base32[i * 8], &key[i * 5]);
+ encode_base32(&base32[i * 8], (const uint8_t[]){ key[i * 5 + 0], key[i * 5 + 1], 0, 0, 0 });
+ base32[WG_KEY_LEN_BASE32 - 5] = '=';
+ base32[WG_KEY_LEN_BASE32 - 4] = '=';
+ base32[WG_KEY_LEN_BASE32 - 3] = '=';
+ base32[WG_KEY_LEN_BASE32 - 2] = '=';
+ base32[WG_KEY_LEN_BASE32 - 1] = '\0';
+}
+
+int wg_pubkey_base32(char const * privkey, char * base32) {
uint8_t key[WG_KEY_LEN] __attribute((aligned(sizeof(uintptr_t))));
+ char base64[WG_KEY_LEN_BASE64];
int i;
for(i = 0; privkey[i] && i < WG_KEY_LEN_BASE64 - 1; i++)
@@ -21,7 +55,19 @@ int wg_pubkey_base64(char const * privkey, char * base64) {
curve25519_generate_public(key, key);
- key_to_base64(base64, key);
+ key_to_base32(base32, key);
+
+ return 0;
+}
+
+int wg_key_convert_base32(char const * base64, char * base32) {
+ uint8_t key[WG_KEY_LEN] __attribute((aligned(sizeof(uintptr_t))));
+
+ if(!key_from_base64(key, base64)) {
+ return 1;
+ }
+
+ key_to_base32(base32, key);
return 0;
}
diff --git a/src/crypto/pubkey.hpp b/src/crypto/pubkey.hpp
index 8596431..cb1f794 100644
--- a/src/crypto/pubkey.hpp
+++ b/src/crypto/pubkey.hpp
@@ -5,18 +5,21 @@ extern "C" {
#endif
#define WG_KEY_LEN_BASE64 ((((WG_KEY_LEN) + 2) / 3) * 4 + 1)
+#define WG_KEY_LEN_BASE32 (((WG_KEY_LEN + 4) / 5) * 8 + 1)
/*
* wg_pubkey_base64 is a C++-compatible wrapper for the curve25519 public-key
* derivation routines used natively in `wg(8)`
*
* PRIVKEY: a c-style string containing the base64-encoded private key
- * BASE64: a c-style string of capacity WG_KEY_LEN_BASE64 containing the
+ * BASE32: a c-style string of capacity WG_KEY_LEN_BASE64 containing the
* encoded public key
*
* returns: 0 on success
* > 0 when an error occurs (due to improper key formatting)
*/
-int wg_pubkey_base64(char const * privkey, char * base64);
+int wg_pubkey_base32(char const * privkey, char * base32);
+
+int wg_key_convert_base32(char const * base64, char * base32);
}
diff --git a/src/wg2nd.cpp b/src/wg2nd.cpp
index cbe3c29..9397a0b 100644
--- a/src/wg2nd.cpp
+++ b/src/wg2nd.cpp
@@ -25,11 +25,11 @@ constexpr char const * SYMMETRIC_KEY_SUFFIX = ".symkey";
namespace wg2nd {
std::string private_keyfile_name(std::string const & priv_key) {
- char pub_key[WG_KEY_LEN_BASE64];
+ char pub_key[WG_KEY_LEN_BASE32];
// Derive public key
- if(wg_pubkey_base64(priv_key.c_str(), pub_key)) {
- throw ParsingException("Private key is formatted improperly");
+ if(wg_pubkey_base32(priv_key.c_str(), pub_key)) {
+ throw ParsingException("Private key is formatted improperly");
}
std::string keyfile_name { pub_key };
@@ -38,6 +38,19 @@ namespace wg2nd {
return keyfile_name;
}
+ std::string public_keyfile_name(std::string const & pub_key) {
+ char pub_key32[WG_KEY_LEN_BASE32];
+
+ if(wg_key_convert_base32(pub_key.c_str(), pub_key32)) {
+ throw ParsingException("Public key for [Peer] " + pub_key + " is formatted improperly");
+ }
+
+ std::string keyfile_name { pub_key32 };
+ keyfile_name.append(SYMMETRIC_KEY_SUFFIX);
+
+ return keyfile_name;
+ }
+
uint32_t deterministic_fwmark(std::string const & interface_name) {
constexpr uint8_t const SIP_KEY[8] = {
0x90, 0x08, 0x82, 0xd7,
@@ -409,7 +422,7 @@ namespace wg2nd {
}
if(!peer.preshared_key.empty()) {
- std::string filename = peer.public_key + SYMMETRIC_KEY_SUFFIX;
+ std::string filename = public_keyfile_name(peer.public_key);
symmetric_keyfiles.push_back(SystemdFilespec {
.name = filename,