Version 1.0
authorTj <hacker@iam.tj>
Wed, 7 Oct 2015 21:28:26 +0000 (22:28 +0100)
committerTj <hacker@iam.tj>
Wed, 7 Oct 2015 21:28:26 +0000 (22:28 +0100)
Makefile [new file with mode: 0644]
cfe_generate_password.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..049b15b
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+  Generate Broadcom CFE seeds and passwords for many popular modem/router devices
+
+  Copyright 2015 TJ <hacker@iam.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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+
+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", &timestamp);
+    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;
+}
+