Last active
October 4, 2017 20:23
-
-
Save n-eq/a565089785a1f94f3422928a3e6e5b98 to your computer and use it in GitHub Desktop.
A C program to calculate LoRaWAN's Network Session Key (NwSKey) using mbed TLS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This C program calculates LoRaWAN's network session key (NwkSKey) using | |
* mbed TLS. | |
* To use it, you should provide the following parameters in this order when | |
* executing the program: | |
* AppKey: An AES-128 key | |
* AppNonce: A random 3 byte value | |
* NetID: A network identifier | |
* DevNonce: A 2 byte nonce | |
* Example: | |
* ./nwkskey 0x4F34BF40BFFF839D07FC62DEFA24D185 0x15AE9F 0x8A34DD 0x5519 | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <inttypes.h> | |
#include "mbedtls/aes.h" | |
#define ARGC 5 | |
#define KEY_LEN 16 | |
#define KEY_SIZE 128 | |
#define USAGE \ | |
"\nUsage: ./nwkskey <AppKey> <AppNonce> <NetID> <DevNonce>\n\n" | |
static mbedtls_aes_context aes_ctx; | |
int main(int argc, char* argv[]){ | |
if (argc != ARGC){ | |
fprintf(stderr, USAGE); | |
exit(EXIT_FAILURE); | |
} | |
assert(argc == ARGC); | |
// Define this loop internal variable to avoid c99/gnu99 compatibility errors | |
int i; | |
unsigned char app_key[KEY_LEN]; | |
unsigned char input[KEY_LEN]; | |
unsigned char nwkskey[KEY_LEN]; | |
// Cast the parameters to void* in order to avoid memset argument | |
// type warnings | |
memset(input, 0, sizeof(input)); | |
memset(nwkskey, 0, sizeof(nwkskey)); | |
memset(app_key, 0, sizeof(app_key)); | |
// Parse AppKey from the first command line argument | |
unsigned char* p; | |
p = &argv[1][0]; | |
// shift the pointer if the hex number starts with a "0[X|x]" pattern | |
if ((strncmp(argv[1], "0x", 2) == 0) || (strncmp(argv[1], "0X", 2))) | |
p += 2; | |
i = 0; | |
unsigned char tmp; | |
while ((sscanf(p, "%X", &tmp) > 0) && (i < KEY_LEN)){ | |
app_key[KEY_LEN - i++] = tmp; // data stored in little endian mode | |
p++; | |
} | |
// Parse input parameters from the command line arguments | |
uint32_t app_nonce = 0, net_id = 0; | |
uint16_t dev_nonce = 0; | |
sscanf(argv[2], "%X", &app_nonce); | |
sscanf(argv[3], "%X", &net_id); | |
sscanf(argv[4], "%X", &dev_nonce); | |
// An alternative may be using an array of pointers (void* p[]) | |
// and sscanf'ing in a loop | |
// Build up the input (data are stored in little endian (network byte order) | |
input[0] = 0x1; | |
input[1] = (unsigned char) (app_nonce & 0xFF); | |
input[2] = (unsigned char) ((app_nonce >> 8) & 0xFF); | |
input[3] = (unsigned char) ((app_nonce >> 16) & 0xFF); | |
input[4] = (unsigned char) (net_id & 0xFF); | |
input[5] = (unsigned char) ((net_id >> 8) & 0xFF); | |
input[6] = (unsigned char) ((net_id >> 16) & 0xFF); | |
input[7] = (unsigned char) (dev_nonce & 0xFF); | |
input[8] = (unsigned char) ((dev_nonce >> 8) & 0xFF); | |
mbedtls_aes_init(&aes_ctx); | |
mbedtls_aes_setkey_enc(&aes_ctx, app_key, KEY_SIZE); | |
mbedtls_aes_encrypt(&aes_ctx, input, nwkskey); | |
printf("Network Session Key: "); | |
for (i = 0; i < KEY_LEN; ++i) | |
printf("%c", nwkskey[i]); | |
printf("\n"); | |
return(EXIT_SUCCESS); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment