upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/main/identity.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/identity.c')
-rw-r--r--main/identity.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/main/identity.c b/main/identity.c
new file mode 100644
index 0000000..1dab415
--- /dev/null
+++ b/main/identity.c
@@ -0,0 +1,124 @@
1#include "identity.h"
2#include "config.h"
3#include "esp_log.h"
4#include "lwip/ip4_addr.h"
5#include "mbedtls/md.h"
6#include "secp256k1.h"
7#include "secp256k1_extrakeys.h"
8#include <string.h>
9#include <stdio.h>
10#include <stdlib.h>
11
12static const char *TAG = "identity";
13static tollgate_identity_t s_identity;
14
15static int hex_to_bytes(const char *hex, uint8_t *out, size_t out_len)
16{
17 if (strlen(hex) != out_len * 2) return 0;
18 for (size_t i = 0; i < out_len; i++) {
19 unsigned int byte;
20 if (sscanf(hex + i * 2, "%02x", &byte) != 1) return 0;
21 out[i] = (uint8_t)byte;
22 }
23 return 1;
24}
25
26static void bytes_to_hex(const uint8_t *bytes, size_t len, char *hex)
27{
28 for (size_t i = 0; i < len; i++)
29 sprintf(hex + i * 2, "%02x", bytes[i]);
30 hex[len * 2] = '\0';
31}
32
33static void tollgate_derive(const uint8_t nsec[32], const char *label,
34 uint32_t index, uint8_t *out, size_t out_len)
35{
36 size_t label_len = strlen(label);
37 size_t msg_len = label_len + 4;
38 uint8_t *msg = (uint8_t *)malloc(msg_len);
39 memcpy(msg, label, label_len);
40 msg[label_len] = (uint8_t)(index & 0xff);
41 msg[label_len + 1] = (uint8_t)((index >> 8) & 0xff);
42 msg[label_len + 2] = (uint8_t)((index >> 16) & 0xff);
43 msg[label_len + 3] = (uint8_t)((index >> 24) & 0xff);
44
45 uint8_t hmac[64];
46 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
47 nsec, 32, msg, msg_len, hmac);
48 free(msg);
49
50 memcpy(out, hmac, out_len);
51}
52
53esp_err_t identity_init(const char *nsec_hex)
54{
55 memset(&s_identity, 0, sizeof(s_identity));
56
57 if (!nsec_hex || strlen(nsec_hex) != 64) {
58 ESP_LOGE(TAG, "Invalid nsec: must be 64 hex chars");
59 return ESP_ERR_INVALID_ARG;
60 }
61
62 strncpy(s_identity.nsec_hex, nsec_hex, sizeof(s_identity.nsec_hex) - 1);
63
64 if (!hex_to_bytes(nsec_hex, s_identity.nsec, 32)) {
65 ESP_LOGE(TAG, "Failed to parse nsec hex");
66 return ESP_ERR_INVALID_ARG;
67 }
68
69 secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
70 if (!ctx) {
71 ESP_LOGE(TAG, "Failed to create secp256k1 context");
72 return ESP_ERR_NO_MEM;
73 }
74
75 secp256k1_pubkey pubkey;
76 if (!secp256k1_ec_pubkey_create(ctx, &pubkey, s_identity.nsec)) {
77 ESP_LOGE(TAG, "Invalid nsec: secp256k1 key creation failed");
78 secp256k1_context_destroy(ctx);
79 return ESP_ERR_INVALID_ARG;
80 }
81
82 secp256k1_xonly_pubkey xonly;
83 secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly, NULL, &pubkey);
84 uint8_t npub_bytes[32];
85 secp256k1_xonly_pubkey_serialize(ctx, npub_bytes, &xonly);
86 bytes_to_hex(npub_bytes, 32, s_identity.npub_hex);
87
88 tollgate_derive(s_identity.nsec, "sta-mac", 0, s_identity.sta_mac, 6);
89 s_identity.sta_mac[0] = (s_identity.sta_mac[0] | 0x02) & 0xFE;
90
91 tollgate_derive(s_identity.nsec, "ap-mac", 0, s_identity.ap_mac, 6);
92 s_identity.ap_mac[0] = (s_identity.ap_mac[0] | 0x02) & 0xFE;
93
94 snprintf(s_identity.ap_ssid, sizeof(s_identity.ap_ssid),
95 "TollGate-%02X%02X%02X",
96 s_identity.ap_mac[3], s_identity.ap_mac[4], s_identity.ap_mac[5]);
97
98 uint8_t b3 = s_identity.ap_mac[3];
99 uint8_t b4 = s_identity.ap_mac[4];
100 uint8_t b5 = s_identity.ap_mac[5];
101 uint8_t subnet = (b4 ^ b5) % 200 + 10;
102 IP4_ADDR(&s_identity.ap_ip, 10, b3, subnet, 1);
103 snprintf(s_identity.ap_ip_str, sizeof(s_identity.ap_ip_str),
104 IPSTR, IP2STR(&s_identity.ap_ip));
105
106 secp256k1_context_destroy(ctx);
107 s_identity.initialized = true;
108
109 ESP_LOGI(TAG, "Identity: npub=%s", s_identity.npub_hex);
110 ESP_LOGI(TAG, " STA MAC: %02X:%02X:%02X:%02X:%02X:%02X",
111 s_identity.sta_mac[0], s_identity.sta_mac[1], s_identity.sta_mac[2],
112 s_identity.sta_mac[3], s_identity.sta_mac[4], s_identity.sta_mac[5]);
113 ESP_LOGI(TAG, " AP MAC: %02X:%02X:%02X:%02X:%02X:%02X",
114 s_identity.ap_mac[0], s_identity.ap_mac[1], s_identity.ap_mac[2],
115 s_identity.ap_mac[3], s_identity.ap_mac[4], s_identity.ap_mac[5]);
116 ESP_LOGI(TAG, " SSID: %s, AP IP: %s", s_identity.ap_ssid, s_identity.ap_ip_str);
117
118 return ESP_OK;
119}
120
121const tollgate_identity_t *identity_get(void)
122{
123 return &s_identity;
124}