sec/prinet: Module for encryption/decryption of prime network traffic

This commit is contained in:
icex2
2021-01-17 01:34:18 +01:00
parent c84ff4463f
commit abb383995a
11 changed files with 291 additions and 1 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
add_subdirectory(hasp)
add_subdirectory(lockchip)
add_subdirectory(microdog34)
add_subdirectory(microdog40)
add_subdirectory(microdog40)
add_subdirectory(prinet)
+13
View File
@@ -0,0 +1,13 @@
project(sec-prinet)
message(STATUS "Project " ${PROJECT_NAME})
set(SRC ${PT_ROOT_MAIN}/sec/prinet)
set(SOURCE_FILES
${SRC}/prinet.c)
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fPIC")
target_link_libraries(${PROJECT_NAME} util -lsodium)
+1
View File
@@ -5,5 +5,6 @@ include_directories(${PT_ROOT_TEST})
add_subdirectory(capnhook)
add_subdirectory(hook)
add_subdirectory(sec)
add_subdirectory(test-util)
add_subdirectory(util)
+1
View File
@@ -0,0 +1 @@
add_subdirectory(prinet)
+1
View File
@@ -0,0 +1 @@
add_subdirectory(prinet)
@@ -0,0 +1,14 @@
project(test-sec-prinet-prinet)
message(STATUS "Project " ${PROJECT_NAME})
set(SRC ${PT_ROOT_TEST}/sec/prinet/prinet)
add_resources(PRI_PRIVATE_KEY ${SRC} prime.private.key)
add_resources(PRI_PUBLIC_KEY ${SRC} prime.public.key)
set(SOURCE_FILES
${SRC}/main.c)
add_executable(${PROJECT_NAME} ${SOURCE_FILES} ${PRI_PRIVATE_KEY} ${PRI_PUBLIC_KEY})
target_link_libraries(${PROJECT_NAME} cmocka sec-prinet test-util util)
+118
View File
@@ -0,0 +1,118 @@
#define LOG_MODULE "sec-prinet"
#include <errno.h>
#include <sodium.h>
#include <string.h>
#include <unistd.h>
#include "sec/prinet/prinet.h"
#include "util/log.h"
#include "util/mem.h"
_Static_assert (crypto_box_NONCEBYTES == SEC_PRINET_NOUNCE_LEN, "Nounce length not as expected for prinet");
_Static_assert (crypto_box_MACBYTES == SEC_PRINET_MACBYTES_LEN, "Nounce length not as expected for prinet");
static void* _key_pub;
static size_t _key_pub_len;
static void* _key_priv;
static size_t _key_priv_len;
static void* _sec_prinet_safe_malloc(size_t size)
{
size_t pagesize = getpagesize();
size_t num_pages = size / pagesize;
size_t num_pages_round_up = num_pages;
if (size % pagesize != 0) {
num_pages_round_up++;
}
size_t size_aligned = num_pages_round_up * pagesize;
void* ptr = sodium_malloc(size_aligned);
if (ptr == NULL) {
log_error("Sodium malloc failed, %s", strerror(errno));
return NULL;
}
return ptr;
}
void sec_prinet_init(
const uint8_t* key_pub, size_t key_pub_len,
const uint8_t* key_priv, size_t key_priv_len)
{
_key_pub = util_xmalloc(key_pub_len);
memcpy(_key_pub, key_pub, key_pub_len);
_key_pub_len = key_pub_len;
_key_priv = util_xmalloc(key_priv_len);
memcpy(_key_priv, key_priv, key_priv_len);
_key_priv_len = key_priv_len;
// 0 on success, 1 if already initialized
if (sodium_init() == -1) {
log_error("Initializing sodium failed");
}
}
void sec_prinet_finit()
{
util_xfree(&_key_pub);
util_xfree(&_key_priv);
}
size_t sec_prinet_get_enc_data_buffer_size(size_t enc_data_len)
{
return enc_data_len + crypto_box_MACBYTES;
}
size_t sec_prinet_decrypt(
const uint8_t* nounce, size_t nounce_len, const uint8_t* enc_data,
size_t enc_data_len, uint8_t* dec_data)
{
if (nounce_len != SEC_PRINET_NOUNCE_LEN) {
log_error("Nounce len %d does not match expected len %d", nounce_len, SEC_PRINET_NOUNCE_LEN);
return -1;
}
if (crypto_box_open_easy(dec_data, enc_data, enc_data_len, nounce, _key_pub, _key_priv) != 0) {
log_error("Decrypting message, len %d, failed", enc_data_len);
return -1;
}
return enc_data_len;
}
size_t sec_prinet_encrypt(
const uint8_t* nounce, size_t nounce_len, const uint8_t* dec_data,
size_t dec_data_len, uint8_t* enc_data)
{
if (nounce_len != SEC_PRINET_NOUNCE_LEN) {
log_error("Nounce len %d does not match expected len %d", nounce_len, SEC_PRINET_NOUNCE_LEN);
return -1;
}
void* tmp_enc = _sec_prinet_safe_malloc(dec_data_len);
if (tmp_enc == NULL) {
return -1;
}
if (crypto_box_easy(tmp_enc, dec_data, dec_data_len, nounce, _key_pub, _key_priv) != 0) {
log_error("Encrypting message, len %d, failed", dec_data_len);
sodium_free(tmp_enc);
return -1;
}
// Encrypted data/response expects additional data after game specific payload
size_t enc_data_len = sec_prinet_get_enc_data_buffer_size(dec_data_len);
memcpy(enc_data, tmp_enc, enc_data_len);
sodium_free(tmp_enc);
return enc_data_len;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#define SEC_PRINET_NOUNCE_LEN 24
#define SEC_PRINET_MACBYTES_LEN 16
void sec_prinet_init(
const uint8_t* key_pub, size_t key_pub_len,
const uint8_t* key_priv, size_t key_priv_len);
void sec_prinet_finit();
size_t sec_prinet_get_enc_data_buffer_size(size_t enc_data_len);
size_t sec_prinet_decrypt(
const uint8_t* nounce, size_t nounce_len, const uint8_t* enc_data,
size_t enc_data_len, uint8_t* dec_data);
size_t sec_prinet_encrypt(
const uint8_t* nounce, size_t nounce_len, const uint8_t* dec_data,
size_t dec_data_len, uint8_t* enc_data);
+115
View File
@@ -0,0 +1,115 @@
#include <cmocka/cmocka.h>
#include "sec/prinet/prinet.h"
#include "test-util/mem.h"
#include "util/mem.h"
#include "util/rand.h"
/* Compiled binary data from data folder. Symbols are defined by compiler */
extern const uint8_t _binary_prime_private_key_start[];
extern const uint8_t _binary_prime_private_key_end[];
extern const uint8_t _binary_prime_public_key_start[];
extern const uint8_t _binary_prime_public_key_end[];
static void _test_encrypt_decrypt(uint32_t seed)
{
util_rand_init(seed);
uint8_t* data;
size_t data_len;
uint8_t* nounce;
uint8_t* enc_data;
size_t enc_data_len;
uint8_t* dec_data;
size_t dec_data_len;
size_t enc_data_len_res;
size_t dec_data_len_res;
for (uint32_t i = 0; i < 20; i++) {
data_len = util_rand_gen_range_32(1024 * 1024);
data = util_xmalloc(data_len);
util_rand_gen_bytes(data, data_len);
nounce = util_xmalloc(SEC_PRINET_NOUNCE_LEN);
util_rand_gen_bytes(nounce, SEC_PRINET_NOUNCE_LEN);
enc_data_len = sec_prinet_get_enc_data_buffer_size(data_len);
enc_data = util_xmalloc(enc_data_len);
enc_data_len_res =
sec_prinet_encrypt(nounce, SEC_PRINET_NOUNCE_LEN, data, data_len, enc_data);
assert_int_equal(enc_data_len_res, enc_data_len);
dec_data_len = enc_data_len_res;
dec_data = util_xmalloc(dec_data_len);
dec_data_len_res =
sec_prinet_decrypt(nounce, SEC_PRINET_NOUNCE_LEN, enc_data, dec_data_len, dec_data);
assert_int_equal(dec_data_len_res, sec_prinet_get_enc_data_buffer_size(data_len));
assert_memory_equal(data, dec_data, data_len);
util_xfree((void**) &dec_data);
util_xfree((void**) &enc_data);
util_xfree((void**) &nounce);
util_xfree((void**) &data);
}
}
static int setup(void** state)
{
test_util_mem_install_mem_interface();
sec_prinet_init(
(const uint8_t*) _binary_prime_public_key_start,
((uintptr_t) &_binary_prime_public_key_end -
(uintptr_t) &_binary_prime_public_key_start),
(const uint8_t*) _binary_prime_private_key_start,
((uintptr_t) &_binary_prime_private_key_end -
(uintptr_t) &_binary_prime_private_key_start));
return 0;
}
static int teardown(void** state)
{
sec_prinet_finit();
return 0;
}
static void test_encrypt_decrypt_1(void** state)
{
_test_encrypt_decrypt(1);
}
static void test_encrypt_decrypt_2(void** state)
{
_test_encrypt_decrypt(2);
}
static void test_encrypt_decrypt_3(void** state)
{
_test_encrypt_decrypt(3);
}
static void test_encrypt_decrypt_4(void** state)
{
_test_encrypt_decrypt(4);
}
int main(int argc, char* argv[])
{
const struct CMUnitTest tests[] ={
cmocka_unit_test_setup_teardown(test_encrypt_decrypt_1, setup, teardown),
cmocka_unit_test_setup_teardown(test_encrypt_decrypt_2, setup, teardown),
cmocka_unit_test_setup_teardown(test_encrypt_decrypt_3, setup, teardown),
cmocka_unit_test_setup_teardown(test_encrypt_decrypt_4, setup, teardown)
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
+1
View File
@@ -0,0 +1 @@
“²ø à•I߯þ6Væ­œšS›öcÓ|ð¤æ)<¿údV
+2
View File
@@ -0,0 +1,2 @@
°כ�GQ
. 2ם/ְשװכˆ°ֺ-½חײNג׀ƒL;¶�1U