summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hashpwd.cpp278
-rw-r--r--src/Makefile.am27
-rwxr-xr-xubpasswd.sh108
3 files changed, 409 insertions, 4 deletions
diff --git a/hashpwd.cpp b/hashpwd.cpp
new file mode 100644
index 0000000..79f0667
--- /dev/null
+++ b/hashpwd.cpp
@@ -0,0 +1,278 @@
+//============================================================================
+// Name : hashpwd.cpp
+// Author :
+// Version :
+// Copyright : Your copyright notice
+// Description : Hello World in C++, Ansi-style
+//============================================================================
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <iomanip>
+#include <string.h>
+#include <openssl/sha.h>
+
+using namespace std;
+int v = 0;
+
+string magic_comp = "fc1c";
+
+static const string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+void escapeOutput(string &input, string &outstr)
+{
+ outstr.clear();
+ int idx = 0; int lastnl = 0;
+ for (string::iterator it=input.begin(); it!=input.end(); ++it) {
+ stringstream conv;
+ lastnl = 0;
+ if (isprint(*it)) {
+ if (idx > 0) {
+ outstr += ' ';
+ idx++;
+ }
+ outstr += *it;
+ idx++;
+ if(idx > 74) {
+ outstr += '\n';
+ lastnl = 1;
+ }
+ } else {
+ conv.str(string());
+ conv << "\\x" << hex << setw(2) << ((unsigned int)*it & 0xff);
+ if (idx > 0) {
+ outstr += ' ';
+ idx++;
+ }
+ idx+=5;
+ outstr += conv.str();
+ if(idx > 74) {
+ outstr += '\n';
+ lastnl = 1;
+ }
+ }
+ }
+ if(lastnl)
+ if (outstr.size () > 0) outstr.resize (outstr.size () - 1);
+}
+
+void binTo64(const unsigned char *data, unsigned int datalen, string &str, unsigned int strLen)
+{
+ unsigned int idx = 0;
+ int sex;
+ unsigned char incoming[3];
+ int last;
+
+ str.clear();
+ (v == 1) && cout << "binTo64 datalen: " << datalen << endl;
+ (v == 1) && cout << "binTo64 strLen: " << strLen << endl;
+ for(unsigned int i=0; i<strLen; i+=4) {
+ if(idx >= datalen)
+ break;
+ if (idx + 3 > datalen) {
+ memset(incoming,0,3);
+ memcpy(incoming,data+idx,datalen-idx);
+ last = datalen - idx - 1;
+ } else {
+ memcpy(incoming,data+idx,sizeof incoming);
+ last = 4;
+ }
+ idx += 3;
+
+ (v == 1) && cout << hex << "in[0]: " << (int)incoming[0] << " in[1]: " << (int)incoming[1]<< " in[2] " << (int)incoming[2] << endl;
+
+ sex = (incoming[0] >> 2);
+ str += base64_chars[sex];
+ (v == 1) && cout << "1st, 4th inp char: " << hex << sex << " to: " << str << endl;
+
+ sex = (incoming[1] >> 4);
+ (v == 1) && cout << "2nd, 5th inp char: " << hex << sex << endl;
+ sex += (incoming[0] << 4) & 0x30;
+ str += base64_chars[sex];
+ (v == 1) && cout << "3rd, 6th inp char: " << hex << sex << " to: " << str << endl;
+ (v == 1) && cout << "last: " << last << endl;
+ if (last == 0)
+ continue;
+ sex = (incoming[2] >> 6);
+ sex += ((incoming[1] << 2) & 0x3c);
+ str += base64_chars[sex];
+
+ if(last == 1)
+ continue;
+
+ sex = (incoming[2] & 0x3f);
+ str += base64_chars[sex];
+
+ (v == 1) && cout << "Converted " << idx << "chars: " << str << endl;
+ }
+ while (str.length() < strLen)
+ str += '=';
+ return;
+}
+
+int badPassword(string &passwd)
+{
+ unsigned char a[3];
+ int i = 0;
+ int lower=0, upper=0, numeric=0, special=0;
+ a[0] = a[1] = a[2] = 0;
+ for (string::iterator it=passwd.begin(); it!=passwd.end(); ++it) {
+ a[0] = *it;
+ if (i > 1) {
+ if ((a[0] == a[1]) && (a[1] == a[2]))
+ return 1;
+ if ((a[0] == a[1]+1) && (a[1] == a[2]+1))
+ return 1;
+ if ((a[0] == a[1]-1) && (a[1] == a[2]-1))
+ return 1;
+ }
+ a[2] = a[1];
+ a[1] = a[0];
+ if(islower(*it))
+ lower=1;
+ if(isupper(*it))
+ upper=1;
+ if(isdigit(*it))
+ numeric=1;
+ if((*it == '/') || (*it == '+'))
+ special=1;
+ i++;
+ }
+ if (lower + upper + numeric + special < 3)
+ return 1;
+ return 0;
+}
+
+void usage(void)
+{
+ cout << "usage:" << endl <<
+ " mts-hashpwd [-v] [[-d did] [-m mac] | [-p password]] salt" << endl <<
+ " -v verbose" << endl <<
+ " -d did Device ID (serial #)" << endl <<
+ " -m mac Ethernet mac address" << endl <<
+ " -p password" << endl <<
+ "Either password must be supplied, or Device-ID and Ethernet Mac address" << endl <<
+ "salt is required." <<endl;
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ int opt = 0, p = 0, d = 0, m = 0;
+ unsigned long long fudge = 0;
+ short unsigned int prefix;
+ string did, mac, pwd, salt;
+
+ while ((opt = getopt(argc,argv,"d:m:p:v")) != EOF)
+ switch(opt)
+ {
+ case 'v': v = 1; cout << " verbose" <<endl; break;
+ case 'd': d = 1; did = optarg ; (v==1) && cout << "device-id is " << did << endl; break;
+ case 'm': m = 1; mac = optarg ; (v==1) && cout << "Ethernet mac is " << mac << endl; break;
+ case 'p': p = 1; pwd = optarg ; (v==1) && cout << "User defined password is \"" << pwd << "\"" << endl; break;
+ case '?': usage(); break;
+ default: cout<<endl; abort();
+ }
+ (v == 1) && cout << "optind is " << optind << " and argc is " << argc << endl;
+ if (v == 1) {
+ cout << "arguments:" << endl;
+ for (int i = 0; i < argc; i++)
+ cout << " argv[" << i << "]=\"" << argv[i] << "\"" << endl;
+ }
+
+ if ((p && d) || (p && m)) {
+ cout << "Must use either a supplied password or Device ID and Ethernet MAC address, but not all three." << endl;
+ usage();
+ }
+ if ((d && !m) || (m && !d)) {
+ cout << "Must have both a Device-ID and an Ethernet MAC address." << endl;
+ usage();
+ }
+ if (optind != argc-1) {
+ cout << "Must have exactly one salt argument." << endl;
+ usage();
+ }
+ salt = argv[optind];
+ (v == 1) && cout << "Salt is \"" << salt << "\"" << endl;
+
+ prefix = strtol(magic_comp.c_str(),NULL,16);
+
+ prefix = ~prefix;
+
+ stringstream prefixStream;
+
+ prefixStream << setw(4) << setfill('0') << hex << prefix;
+
+ (v == 1) && cout << "prefix is " << prefixStream.str() << endl;
+
+
+ string passwd_str;
+ string passwd0, passwdnew;
+ SHA256_CTX sha256;
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+
+ if(!p) {
+ passwd0 = did + "|" + mac;
+ passwdnew = passwd0;
+
+ while (1) {
+ unsigned char append[9];
+ (v == 1) && cout << "pwdinput: " << passwdnew << endl;
+
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256,passwdnew.c_str(),passwdnew.length());
+ SHA256_Final(hash, &sha256);
+ if (v == 1) {
+ for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
+ cout << hex << setw(2) << setfill('0') << (int)hash[i];
+ cout << endl;
+ }
+ pwd = "";
+ binTo64(hash,SHA256_DIGEST_LENGTH,pwd,8);
+ (v == 1) && cout << "passwd_str: " << pwd << endl;
+ if(!badPassword(pwd))
+ break;
+ fudge++;
+ memcpy(append,&fudge,sizeof fudge);
+ append[8]=0;
+ string b64Appendstr;
+ binTo64(append,8,b64Appendstr,12);
+ unsigned int found = b64Appendstr.find_first_of('=');
+ if(found != string::npos)
+ b64Appendstr = b64Appendstr.substr(0,found);
+ passwdnew = passwd0 + b64Appendstr;
+ }
+#ifdef Runtest
+ // Test
+ string testencode = "aX2t^%~Q\377\377\xef", outencode, escaped ;
+ escapeOutput(testencode,escaped);
+ binTo64((unsigned char *)testencode.c_str(),testencode.length(),outencode,testencode.length()*2);
+ cout << "TEST encode input: " << escaped << " Output: " <<
+ outencode << endl;
+#endif
+ }
+
+ cout << "pass=" << pwd << endl;
+
+ passwd_str = prefixStream.str() + pwd + salt;
+
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256,passwd_str.c_str(),passwd_str.length());
+ SHA256_Final(hash, &sha256);
+
+ cout << "password_hash=";
+ cout << hex;
+ for (int i=0; i < SHA256_DIGEST_LENGTH; i++)
+ cout << setw(2) << setfill('0') << (int)hash[i];
+ cout << endl;
+ cout << "salt=" << salt << endl;
+ return 0;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index bfeafff..12f084c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,12 +1,31 @@
+## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = gnu
AM_CFLAGS = -Wall
-bin_PROGRAMS = mts-id-eeprom hashpwd
+bin_PROGRAMS = mts-id-eeprom
+sbin_PROGRAMS = mts-hashpwd
+mts_hashpwd_SOURCES = hashpwd.cpp
mts_id_eeprom_SOURCES = eeprom_main.c
-hashpwd_SOURCES = hashpwd.cpp
noinst_HEADERS = eeprom.h
-hashpwd_LDADD = -lcrypto
-
+mts_hashpwd_LDADD = -lcrypto
+sbin_SCRIPTS = ubpasswd.sh
EXTRA_DIST =
+SUFFIXES = .sh
+
+.sh:
+ $(shbin_verbose) cp $< $@.tmp
+ $(AM_V_at) chmod 0744 $@.tmp
+ $(AM_V_at) mv -f $@.tmp $@
+
+# Since this is Yocto we just make it work by moving
+# the sbin stuff to /sbin, and set permissions
+# on the script for root.
+install-exec-hook:
+ cd $(DESTDIR)$(sbindir) && mkdir ../../sbin && \
+ mv ubpasswd.sh ../../sbin/mts-ubpasswd && \
+ chmod 0744 ../../sbin/mts-ubpasswd
+ cd $(DESTDIR)$(sbindir) && \
+ mv mts-hashpwd ../../sbin/mts-hashpwd
+ rmdir $(DESTDIR)$(sbindir)
diff --git a/ubpasswd.sh b/ubpasswd.sh
new file mode 100755
index 0000000..000c831
--- /dev/null
+++ b/ubpasswd.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+# Password setting/generation script.
+# Sets both root and u-boot password,
+# or optionally just U-boot.
+# What is actually written is the password
+# and salt. But the password is printed
+# for reference.
+# ubpasswd -h will print usage.
+if ! [[ -x /sbin/hashpwd ]] ; then
+ echo Need /sbin/hashpwd to proceed.
+fi
+usage() {
+ echo "ubpasswd [-u] [-d] [-s salt] [password]"
+ echo " -u means u-boot only (not UNIX password)"
+ echo " -s salt is user supplied salt"
+ echo " -d debug"
+ echo " password is a user supplied password"
+ echo "A salt not supplied is generated."
+ echo "If a password is not supplied, it is generated"
+ exit 1
+}
+((ubonly=0))
+((hassalt=0))
+((debug=0))
+((upwd=0))
+while getopts ":dus:" opt; do
+ case $opt in
+ u)
+ ((ubonly=1))
+ ;;
+ s)
+ salt="$OPTARG"
+ ((hassalt=1))
+ ;;
+ d)
+ ((debug=1))
+ ;;
+ *)
+ usage
+ esac
+done
+((debug)) && echo OPTIND is $OPTIND
+((sc=OPTIND-1))
+shift $sc
+if (($# == 1)) ; then
+ ((debug)) && echo "User set password is \"$1\""
+ ((upwd = 1))
+ pass="$1"
+fi
+
+((debug)) && echo hassalt is $hassalt, salt is \"$salt\"
+((debug)) && echo ubonly is $ubonly
+((debug)) && echo debug is $debug
+
+len=8
+saltlen=128
+mts=/sys/devices/platform/mts-io
+did="${mts}/device-id"
+mac="${mts}/mac-eth"
+
+if ! /bin/fgrep "mts password protected" /dev/mtdblock2 >/dev/null 2>&1; then
+ echo "U-Boot does not support password protection."
+fi
+
+if ((hassalt == 0)) ; then
+ salt="$(/bin/dd if=/dev/urandom count=1 bs=128 2>/dev/null | /bin/base64 | tr -d '\n' | cut -c1-${saltlen})"
+fi
+
+echo "salt: $salt"
+
+((v == 1)) && echo upwd is $upwd
+((v == 1)) && echo did length is ${#did}
+if ((upwd == 0)) ; then
+ if ((${#did} == 0)) ; then
+ echo "${mts}/device-id must have a non-zero length value"
+ usage
+ fi
+ if ((${#mac} == 0)) ; then
+ echo "${mts}/mac-eth must have a non-zero length value"
+ usage
+ fi
+ if ((v == 1)) ; then
+ echo Try this:
+ echo "/sbin/hashpwd -d ${did} -m ${mac} ${salt}"
+ fi
+ result=$(/sbin/hashpwd -d ${did} -m ${mac} ${salt})
+else
+ result=$(/sbin/hashpwd -p "${pass}" ${salt})
+fi
+if ! [[ $result =~ ^pass=([^[:space:]]+)[[:space:]]+password_hash=([^[:space:]]+) ]] ; then
+ echo "/sbin/hashpwd failed: ${result}"
+ exit 1
+fi
+if ((v == 1)) ; then
+ echo result is:
+ echo "$result"
+fi
+pass="${BASH_REMATCH[1]}"
+password_hash="${BASH_REMATCH[2]}"
+echo "uboot password hash: \"$password_hash\""
+if ((ubonly == 0)) ; then
+ echo "setting root password to ${pass}"
+ echo -e "${pass}\n${pass}" | /usr/bin/passwd >/dev/null 2>&1
+fi
+set -e
+echo "u-boot password is ${pass}"
+/usr/bin/u-boot setenv mtss "$salt"
+/usr/bin/u-boot setenv mtsp "$password_hash"