From 60b7984e0a8ce92e058e602da1235016a8fc0ede Mon Sep 17 00:00:00 2001 From: Tj Date: Wed, 7 Oct 2015 22:28:26 +0100 Subject: [PATCH] Version 1.0 --- Makefile | 10 ++ cfe_generate_password.c | 238 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 Makefile create mode 100644 cfe_generate_password.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3aaf3cc --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +PROG=cfe_gen_pass +SRC=cfe_generate_password + +$(PROG): $(SRC).c + $(CC) -o $@ $< $(CFLAGS) + +clean: + rm -f $(PROG) + +phony: clean diff --git a/cfe_generate_password.c b/cfe_generate_password.c new file mode 100644 index 0000000..049b15b --- /dev/null +++ b/cfe_generate_password.c @@ -0,0 +1,238 @@ +/* + Generate Broadcom CFE seeds and passwords for many popular modem/router devices + + Copyright 2015 TJ + Licenced on the terms of the GNU General Public Licence version 3 + + To build: + + gcc -o cfe_gen_pass cfe_generate_password.c + + Or: + + make + + To use: + + ./cfe_gen_pass [options] + + This tool can generate passwords for use with many devices that contain + Broadcom Common Firmware Environment (CFE) bootbase which has a debug mode + that is enabled using the "ATEN 1 XXXXXXXX" command, where XXXXXXXX is an + eight digit hexadecimal 'password'. + + It is NOT necessary to have the device generate a 'seed' using "ATSE [MODEL-ID]" + because this tool can generate the seed from the device's first (base) MAC address + *provided* the "ATSE" command has NOT been executed since the device last booted. + + Access to the device's console via a serial UART port is required to enter the password. + + So, for a device with base MAC address (reported by the CFE during boot) E.g: + + CFE version 1.0.38-112.118 for BCM963268 (32bit,SP,BE) + ... + Base MAC Address : ec:43:f6:46:c0:80 + ... + *** Press any key to stop auto run (1 seconds) *** + CFE> + + Using this tool do: + + ./cfe_gen_pass -s ec:43:f6:46:c0:80 -p + + MAC address: ec:43:f6:46:c0:80 Timestamp: 000000 Seed: 00000046c080 Password: 10f0a563 + + And on the device do: + + CFE> ATEN 1 10f0a563 + OK + *** command status = 0 + + The tool can accept a timestamp as 6 hexadecimal characters (useful for testing the algorithm): + + ./cfe_gen_pass -t 0FF020 -s ec:43:f6:46:c0:80 -p + + MAC address: ec:43:f6:46:c0:80 Timestamp: 0FF020 Seed: 0FF02046c080 Password: 110f65a3 + */ + +#include +#include +#include +#include +#include + +static const float VERSION = 1.0f; +static const unsigned int TIMESTAMP_SIZE = 6; +static const unsigned int SEED_SIZE = 12; +static const unsigned int PASSWORD_SIZE = 8; +static const unsigned int MESSAGE_SIZE = 128; + +void +pr_usage() +{ + fprintf(stderr, "%s\n", + "Usage:\n" + " -v show version\n" + " -s 00:01:02:03:04:05 create seed from MAC address\n" + " -t 000000 millisecond timestamp since boot\n" + " -p [SEED] generate password (with optional seed)\n\n" + " E.g. -s 01:02:03:04:05 \n" + " -s 01:02:03:04:05 -p\n" + " -p 000000030405\n" + ); +} + +void +pr_error_exit(unsigned int usage, const char *error, ...) +{ + va_list args; + char error_message[MESSAGE_SIZE]; + + if (!error) return; + + va_start(args, error); + vsnprintf(error_message, MESSAGE_SIZE, error, args); + va_end(args); + fprintf(stderr, "Error: %s\n", error_message); + + if (usage) pr_usage(); + + exit(1); +} + +static const unsigned int passwords[8] = { + 0x10F0A563, + 0x887852B1, + 0xC43C2958, + 0x621E14AC, + 0x310F0A56, + 0x1887852B, + 0x8C43C295, + 0xC621E14A +}; + +unsigned int +generate_seed(char *mac, char *timestamp, char *seed) +{ + unsigned int result = 0; + if (mac && strlen(mac) == 17) { + unsigned int i; + char *mac_ptr = mac + 9; + size_t ts_len = strlen(timestamp); + for (i = 0; i <= SEED_SIZE; ++i) { + /* if no timestamp assume CFE get_time() returned 0 and CFE g_pw_timestamp == 0x00000000 */ + if (i < 6) + seed[i] = ts_len ? timestamp[i] : '0'; + else { + if (*mac_ptr == ':' || *mac_ptr == '-') + ++mac_ptr; + seed[i] = *mac_ptr++; + } + } + result = 1; + } else + pr_error_exit(0, "MAC-ADDR should be 17 characters, e.g: 00:01:02:03:04:05"); + + return result; +} + +unsigned int +generate_pass(char *seed, char *password) +{ + unsigned int result = 0; + + if (seed && strlen(seed) == 12) { + unsigned int timestamp = 0; + unsigned byte = 0; + sscanf(seed, "%06x", ×tamp); + sscanf(&seed[10], "%02x", &byte); + unsigned int key = byte & 0x07; + unsigned int pass = (passwords[key] + timestamp) ^ timestamp; + snprintf(password, PASSWORD_SIZE + 1, "%08x", pass); + result = 1; + } else + pr_error_exit(0, "Seed should be %d hex characters", SEED_SIZE); + + return result; +} + +int +main(int argc, char **argv, char **env) +{ + int result = 0; + + if (argc == 1) { + pr_usage(); + } + else { + unsigned int arg; + char *MAC_ADDR = NULL; + char *MODEL = NULL; + char timestamp[TIMESTAMP_SIZE + 1]; + char seed[SEED_SIZE + 1]; + char password[PASSWORD_SIZE + 1]; + unsigned int opt_seed, opt_pass, opt_ts; + seed[0] = password[0] = 0; + seed[SEED_SIZE] = password[PASSWORD_SIZE] = timestamp[TIMESTAMP_SIZE] = 0; + opt_seed = opt_pass = opt_ts = 0; + strncpy(timestamp, "000000", TIMESTAMP_SIZE); + + for (arg = 1; arg < argc; ++arg) { + size_t arg_len = strlen(argv[arg]); + + if (argv[arg][0] == '-') { + switch (argv[arg][1]) { + case 's': + opt_seed = 1; + break; + case 'p': + opt_pass = 1; + break; + case 't': + opt_ts = 1; + break; + case 'v': + fprintf(stderr, "Version: %0.2f\n", VERSION); + } + } else if (opt_seed == 1) { + MAC_ADDR = argv[arg]; + ++opt_seed; + } else if (opt_pass == 1 && opt_seed == 0) { + if (arg_len != SEED_SIZE) + pr_error_exit(1, "seed length must be %d characters", SEED_SIZE); + + strncpy(seed, argv[arg], SEED_SIZE); + ++opt_pass; + } else if (opt_ts == 1) { + if (arg_len != TIMESTAMP_SIZE) + pr_error_exit(1, "timestamp length must be %d characters", TIMESTAMP_SIZE); + + strncpy(timestamp, argv[arg], TIMESTAMP_SIZE); + ++opt_ts; + } + } + if (! opt_seed && ! opt_pass) + pr_usage(); + else if (opt_seed && opt_seed != 2) + pr_error_exit(1, "seed requires MAC-ADDRESS"); + else if (! opt_seed && opt_pass && opt_pass != 2) + pr_error_exit(1, "password on its own requires a pre-generated seed"); + else if (opt_seed && opt_pass && opt_pass != 1) + pr_error_exit(1, "generating seed and password; cannot also accept pre-generated seed"); + else if (opt_ts == 1) + pr_error_exit(0, "missing timestamp; assuming 000000"); + + + if (opt_seed) + if (! generate_seed(MAC_ADDR, timestamp, seed)) + pr_error_exit(1, "unable to generate seed; aborting"); + if (opt_pass) + if (! generate_pass(seed, password)) + pr_error_exit(0, "unable to generate password"); + + printf("MAC address: %s Timestamp: %s Seed: %s Password: %s\n", MAC_ADDR, timestamp, seed, password); + } + + return result; +} + -- 2.17.1