Add ssh auth flow (WIP)
This commit is contained in:
@@ -9,13 +9,22 @@ dependencies:
|
|||||||
path: .
|
path: .
|
||||||
type: git
|
type: git
|
||||||
version: d9792119ebaec0c54839e6605acd3f11dd937205
|
version: d9792119ebaec0c54839e6605acd3f11dd937205
|
||||||
|
esp-idf-ssh-client:
|
||||||
|
component_hash: d6f7b468c951d78e17e7a9b6911768c807729776338aad447f5c5dcd23642ee4
|
||||||
|
dependencies: []
|
||||||
|
source:
|
||||||
|
git: https://gitlab.com/ch405labs/ch405labs_esp_libssh2.git
|
||||||
|
path: .
|
||||||
|
type: git
|
||||||
|
version: 8b136ec9ee4ff26f19fad36e23062a0a79a32619
|
||||||
idf:
|
idf:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 5.5.2
|
version: 5.5.2
|
||||||
direct_dependencies:
|
direct_dependencies:
|
||||||
- esp-cryptoauthlib
|
- esp-cryptoauthlib
|
||||||
|
- esp-idf-ssh-client
|
||||||
- idf
|
- idf
|
||||||
manifest_hash: c756397bc94626ff7204b9330f85430937d2c27c736bf3075be0f87eb8eb0efc
|
manifest_hash: c0dd2805d23d2f57e818e665712d10a21c7d820835cc0b907c812de71ec4daa7
|
||||||
target: esp32c6
|
target: esp32c6
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ dependencies:
|
|||||||
version: ">=4.1.0"
|
version: ">=4.1.0"
|
||||||
esp-cryptoauthlib:
|
esp-cryptoauthlib:
|
||||||
git: https://github.com/espressif/esp-cryptoauthlib.git
|
git: https://github.com/espressif/esp-cryptoauthlib.git
|
||||||
|
esp-idf-ssh-client:
|
||||||
|
git: https://gitlab.com/ch405labs/ch405labs_esp_libssh2.git
|
||||||
|
|||||||
105
main/zk_auth.h
105
main/zk_auth.h
@@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#include "cryptoauthlib.h"
|
#include "cryptoauthlib.h"
|
||||||
#include "host/atca_host.h"
|
#include "host/atca_host.h"
|
||||||
|
#include "libssh2_config.h"
|
||||||
#include "mbedtls/sha256.h"
|
#include "mbedtls/sha256.h"
|
||||||
#include <cJSON.h>
|
#include <cJSON.h>
|
||||||
#include <esp_mac.h>
|
#include <esp_mac.h>
|
||||||
#include <esp_system.h>
|
#include <esp_system.h>
|
||||||
|
#include <libssh2.h>
|
||||||
#include <mbedtls/aes.h>
|
#include <mbedtls/aes.h>
|
||||||
#include <mbedtls/base64.h>
|
#include <mbedtls/base64.h>
|
||||||
#include <mbedtls/ctr_drbg.h>
|
#include <mbedtls/ctr_drbg.h>
|
||||||
@@ -19,15 +21,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// Zero-Knowledge Authentication Module
|
// Added network headers for ESP-IDF (lwIP) sockets
|
||||||
// Implements Client-Side KDF + ECIES Tunnel for ESP32-C6
|
#include <arpa/inet.h>
|
||||||
// Format: SHA-256 compatible with ATECC608B
|
#include <netinet/in.h>
|
||||||
//
|
#include <sys/socket.h>
|
||||||
// Encryption: AES-256-CBC + HMAC-SHA256 (Encrypt-then-MAC)
|
#include <unistd.h>
|
||||||
// - Provides confidentiality (CBC) + authenticity (HMAC)
|
|
||||||
// - Blob format: IV (16 bytes) + Ciphertext (32 bytes) + HMAC (32 bytes) = 80
|
|
||||||
// bytes
|
|
||||||
// - HMAC verified BEFORE decryption (prevents padding oracle attacks)
|
|
||||||
|
|
||||||
class ZKAuth {
|
class ZKAuth {
|
||||||
private:
|
private:
|
||||||
@@ -91,6 +89,25 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marked as static so it can be passed as a C callback to libssh2
|
||||||
|
static int sign_callback(LIBSSH2_SESSION *session, unsigned char **sig,
|
||||||
|
size_t *sig_len, const unsigned char *data,
|
||||||
|
size_t data_len, void **abstract) {
|
||||||
|
ATCA_STATUS status;
|
||||||
|
uint8_t signature[64];
|
||||||
|
|
||||||
|
// sign the data hash with ATECC608B
|
||||||
|
status = atcab_sign(0x0, data, signature);
|
||||||
|
if (status != ATCA_SUCCESS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement DER encoding and allocate output blob
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to write a 32-bit integer in big-endian format
|
// Helper function to write a 32-bit integer in big-endian format
|
||||||
void write_uint32_be(uint8_t *buf, uint32_t val) {
|
void write_uint32_be(uint8_t *buf, uint32_t val) {
|
||||||
buf[0] = (val >> 24) & 0xFF;
|
buf[0] = (val >> 24) & 0xFF;
|
||||||
@@ -100,7 +117,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to generate the authorized_keys string
|
// Function to generate the authorized_keys string
|
||||||
void generate_ssh_authorized_key(const uint8_t *atec_pubkey) {
|
void generate_ssh_authorized_key(const uint8_t *atecc_pubkey,
|
||||||
|
uint8_t *out_blob) {
|
||||||
uint8_t ssh_blob[104];
|
uint8_t ssh_blob[104];
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
@@ -122,7 +140,7 @@ public:
|
|||||||
write_uint32_be(&ssh_blob[offset], 65);
|
write_uint32_be(&ssh_blob[offset], 65);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
ssh_blob[offset++] = 0x04;
|
ssh_blob[offset++] = 0x04;
|
||||||
memcpy(&ssh_blob[offset], atec_pubkey, 64);
|
memcpy(&ssh_blob[offset], atecc_pubkey, 64);
|
||||||
offset += 64;
|
offset += 64;
|
||||||
|
|
||||||
// 4. Base64 Encode the blob
|
// 4. Base64 Encode the blob
|
||||||
@@ -136,23 +154,34 @@ public:
|
|||||||
|
|
||||||
// 5. Print out the final authorized_keys line
|
// 5. Print out the final authorized_keys line
|
||||||
printf("ecdsa-sha2-nistp256 %s esp32-atecc608b\n", b64_out);
|
printf("ecdsa-sha2-nistp256 %s esp32-atecc608b\n", b64_out);
|
||||||
|
|
||||||
|
memcpy(out_blob, ssh_blob, 104);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get device identity (for /api/identity endpoint)
|
// Get device identity (for /api/identity endpoint)
|
||||||
char *get_identity_json() {
|
char *get_identity_json() {
|
||||||
char pubkey_hex[131]; // 65 bytes * 2 + null
|
char pubkey_hex[131]; // 65 bytes * 2 + null
|
||||||
uint8_t atec_pubkey[64]; // 65 bytes * 2 + null
|
uint8_t atecc_pubkey[64]; // 65 bytes * 2 + null
|
||||||
uint8_t standard_pubkey[65];
|
uint8_t standard_pubkey[65];
|
||||||
standard_pubkey[0] = 0x04;
|
standard_pubkey[0] = 0x04;
|
||||||
// Get public key from ATECC608B and convert to hex
|
// Get public key from ATECC608B and convert to hex
|
||||||
ATCA_STATUS status = atcab_get_pubkey(0, atec_pubkey);
|
ATCA_STATUS status = atcab_get_pubkey(0, atecc_pubkey);
|
||||||
if (status != ATCA_SUCCESS) {
|
if (status != ATCA_SUCCESS) {
|
||||||
printf("Failed to read public key from ATECC608B: 0x%02X\n", status);
|
printf("Failed to read public key from ATECC608B: 0x%02X\n", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_ssh_authorized_key(atec_pubkey);
|
uint8_t pubkey_blob[256];
|
||||||
|
|
||||||
memcpy(&standard_pubkey[1], atec_pubkey, 64);
|
generate_ssh_authorized_key(atecc_pubkey, pubkey_blob);
|
||||||
|
|
||||||
|
// Print the authorized_keys line for debugging
|
||||||
|
printf("Generated authorized_keys line:\n");
|
||||||
|
for (int i = 0; i < 104; i++) {
|
||||||
|
printf("%02x", pubkey_blob[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
memcpy(&standard_pubkey[1], atecc_pubkey, 64);
|
||||||
bin_to_hex(standard_pubkey, 65, pubkey_hex);
|
bin_to_hex(standard_pubkey, 65, pubkey_hex);
|
||||||
|
|
||||||
// Get MAC address to use as salt
|
// Get MAC address to use as salt
|
||||||
@@ -167,8 +196,50 @@ public:
|
|||||||
|
|
||||||
char *json_str = cJSON_PrintUnformatted(root);
|
char *json_str = cJSON_PrintUnformatted(root);
|
||||||
cJSON_Delete(root);
|
cJSON_Delete(root);
|
||||||
|
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
const char *hostname = "192.168.4.1";
|
||||||
|
unsigned short port = 22;
|
||||||
|
const char *username = "key";
|
||||||
|
|
||||||
|
void *my_abstract = NULL;
|
||||||
|
LIBSSH2_SESSION *session;
|
||||||
|
|
||||||
|
// Initialize libssh2
|
||||||
|
libssh2_init(0);
|
||||||
|
|
||||||
|
// Set up and connect socket
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_port = htons(port);
|
||||||
|
inet_pton(AF_INET, hostname, &sin.sin_addr);
|
||||||
|
connect(sock, (struct sockaddr *)(&sin), sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
// Create SSH session
|
||||||
|
session = libssh2_session_init();
|
||||||
|
libssh2_session_handshake(session, sock);
|
||||||
|
|
||||||
|
// PUBLIC KEY AUTH: using custom callback
|
||||||
|
int rc = libssh2_userauth_publickey(session, username, pubkey_blob,
|
||||||
|
sizeof(pubkey_blob), sign_callback,
|
||||||
|
&my_abstract);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
printf("SSH authentication successful!\n");
|
||||||
|
// ... Continue SSH communication ...
|
||||||
|
} else {
|
||||||
|
printf("Authentication failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
libssh2_session_disconnect(session, "Bye");
|
||||||
|
libssh2_session_free(session);
|
||||||
|
close(sock);
|
||||||
|
libssh2_exit();
|
||||||
|
|
||||||
return json_str;
|
return json_str;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ZK_AUTH_H
|
#endif // ZK_AUTH_H
|
||||||
Reference in New Issue
Block a user