Finished the C implementation & CLI tool. Providing an OS X binary.
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -29,6 +29,7 @@ Press/MasterPassword_PressKit/MasterPassword_pressrelease_*.pdf
 | 
			
		||||
MasterPassword/Java/**/target
 | 
			
		||||
 | 
			
		||||
# C
 | 
			
		||||
MasterPassword/C/*.o
 | 
			
		||||
MasterPassword/C/mpw
 | 
			
		||||
MasterPassword/C/lib/*/*
 | 
			
		||||
!MasterPassword/C/lib/*/.source
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								External/LoveLyndir
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								External/LoveLyndir
									
									
									
									
										vendored
									
									
								
							 Submodule External/LoveLyndir updated: ceed9e2000...77e8fa376e
									
								
							
							
								
								
									
										1920
									
								
								MasterPassword/C/bashlib
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1920
									
								
								MasterPassword/C/bashlib
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,5 +1,9 @@
 | 
			
		||||
#!/usr/bin/env bash -e
 | 
			
		||||
# Run with -DDEBUG to enable trace-level output.
 | 
			
		||||
 | 
			
		||||
gcc -c types.c -o types.o "$@"
 | 
			
		||||
gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"types.o" -l"crypto" -L"." -L"lib/scrypt" mpw.c -o mpw "$@"
 | 
			
		||||
[[ -e lib/scrypt/scryptenc.o ]] || { echo >&2 "Missing scrypt.  First get and build the scrypt source in lib/scrypt from <$(<lib/scrypt/.source)>.\n"; exit 1; }
 | 
			
		||||
 | 
			
		||||
deps=( -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"crypto" -L"." -L"lib/scrypt" )
 | 
			
		||||
 | 
			
		||||
gcc "${deps[@]}" -Qunused-arguments -c types.c -o types.o "$@"
 | 
			
		||||
gcc "${deps[@]}" -Qunused-arguments -l"types.o" mpw.c -o mpw "$@"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,78 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
			
		||||
<plist version="1.0">
 | 
			
		||||
<dict>
 | 
			
		||||
	<key>MPElementGeneratedEntity</key>
 | 
			
		||||
	<dict>
 | 
			
		||||
		<key>Maximum Security Password</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>anoxxxxxxxxxxxxxxxxx</string>
 | 
			
		||||
			<string>axxxxxxxxxxxxxxxxxno</string>
 | 
			
		||||
		</array>
 | 
			
		||||
		<key>Long Password</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>CvcvnoCvcvCvcv</string>
 | 
			
		||||
			<string>CvcvCvcvnoCvcv</string>
 | 
			
		||||
			<string>CvcvCvcvCvcvno</string>
 | 
			
		||||
			<string>CvccnoCvcvCvcv</string>
 | 
			
		||||
			<string>CvccCvcvnoCvcv</string>
 | 
			
		||||
			<string>CvccCvcvCvcvno</string>
 | 
			
		||||
			<string>CvcvnoCvccCvcv</string>
 | 
			
		||||
			<string>CvcvCvccnoCvcv</string>
 | 
			
		||||
			<string>CvcvCvccCvcvno</string>
 | 
			
		||||
			<string>CvcvnoCvcvCvcc</string>
 | 
			
		||||
			<string>CvcvCvcvnoCvcc</string>
 | 
			
		||||
			<string>CvcvCvcvCvccno</string>
 | 
			
		||||
			<string>CvccnoCvccCvcv</string>
 | 
			
		||||
			<string>CvccCvccnoCvcv</string>
 | 
			
		||||
			<string>CvccCvccCvcvno</string>
 | 
			
		||||
			<string>CvcvnoCvccCvcc</string>
 | 
			
		||||
			<string>CvcvCvccnoCvcc</string>
 | 
			
		||||
			<string>CvcvCvccCvccno</string>
 | 
			
		||||
			<string>CvccnoCvcvCvcc</string>
 | 
			
		||||
			<string>CvccCvcvnoCvcc</string>
 | 
			
		||||
			<string>CvccCvcvCvccno</string>
 | 
			
		||||
		</array>
 | 
			
		||||
		<key>Medium Password</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>CvcnoCvc</string>
 | 
			
		||||
			<string>CvcCvcno</string>
 | 
			
		||||
		</array>
 | 
			
		||||
		<key>Basic Password</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>aaanaaan</string>
 | 
			
		||||
			<string>aannaaan</string>
 | 
			
		||||
			<string>aaannaaa</string>
 | 
			
		||||
		</array>
 | 
			
		||||
		<key>Short Password</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>Cvcn</string>
 | 
			
		||||
		</array>
 | 
			
		||||
		<key>PIN</key>
 | 
			
		||||
		<array>
 | 
			
		||||
			<string>nnnn</string>
 | 
			
		||||
		</array>
 | 
			
		||||
	</dict>
 | 
			
		||||
	<key>MPCharacterClasses</key>
 | 
			
		||||
	<dict>
 | 
			
		||||
		<key>V</key>
 | 
			
		||||
		<string>AEIOU</string>
 | 
			
		||||
		<key>C</key>
 | 
			
		||||
		<string>BCDFGHJKLMNPQRSTVWXYZ</string>
 | 
			
		||||
		<key>v</key>
 | 
			
		||||
		<string>aeiou</string>
 | 
			
		||||
		<key>c</key>
 | 
			
		||||
		<string>bcdfghjklmnpqrstvwxyz</string>
 | 
			
		||||
		<key>A</key>
 | 
			
		||||
		<string>AEIOUBCDFGHJKLMNPQRSTVWXYZ</string>
 | 
			
		||||
		<key>a</key>
 | 
			
		||||
		<string>AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz</string>
 | 
			
		||||
		<key>n</key>
 | 
			
		||||
		<string>0123456789</string>
 | 
			
		||||
		<key>o</key>
 | 
			
		||||
		<string>@&%?,=[]_:-+*$#!'^~;()/.</string>
 | 
			
		||||
		<key>x</key>
 | 
			
		||||
		<string>AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()</string>
 | 
			
		||||
	</dict>
 | 
			
		||||
</dict>
 | 
			
		||||
</plist>
 | 
			
		||||
@@ -1,15 +1,53 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
BINDIR=${BINDIR:+${PREFIX:+$PREFIX/bin}}
 | 
			
		||||
[[ $BINDIR ]] && mkdir -p "$BINDIR"
 | 
			
		||||
if [[ ! -w $BINDIR ]]; then
 | 
			
		||||
    for dir in /usr/local/bin ~/.bin ~/bin /usr/bin; do
 | 
			
		||||
        [[ -w $dir ]] && BINDIR=$dir && break
 | 
			
		||||
    done
 | 
			
		||||
    if [[ ! -w $BINDIR ]]; then
 | 
			
		||||
        echo >&2 "Could not find directory to install to."
 | 
			
		||||
        echo >&2 "You can specify a prefix to install to, eg. PREFIX=/usr/local ./install"
 | 
			
		||||
        echo >&2 "You can specify a bin directory to install to, eg. BINDIR=~/bin ./install"
 | 
			
		||||
        echo >&2 "Make sure you have write permission to the bin directory."
 | 
			
		||||
    fi
 | 
			
		||||
#
 | 
			
		||||
# Install the Master Password CLI tool.
 | 
			
		||||
set -e
 | 
			
		||||
cd "${BASH_SOURCE%/*}"
 | 
			
		||||
source bashlib
 | 
			
		||||
 | 
			
		||||
inf "This will install the mpw tool."
 | 
			
		||||
 | 
			
		||||
# Try to guess then ask for the bin dir to install to.
 | 
			
		||||
IFS=: read -a paths <<< "$PATH"
 | 
			
		||||
if inArray ~/bin "${paths[@]}"; then
 | 
			
		||||
    bindir=~/bin
 | 
			
		||||
elif inArray ~/.bin "${paths[@]}"; then
 | 
			
		||||
    bindir=~/.bin
 | 
			
		||||
elif inArray /usr/local/bin "${paths[@]}"; then
 | 
			
		||||
    bindir=/usr/local/bin
 | 
			
		||||
else
 | 
			
		||||
    bindir=~/bin
 | 
			
		||||
fi
 | 
			
		||||
install -v -s mpw "$BINDIR"
 | 
			
		||||
bindir=$(ask -d "$bindir" "What bin directory should I install to?")
 | 
			
		||||
[[ -d "$bindir" ]] || mkdir "$bindir" || ftl 'Cannot create missing bin directory: %s' "$bindir" || exit
 | 
			
		||||
[[ -w "$bindir" ]] || ftl 'Cannot write to bin directory: %s' "$bindir" || exit
 | 
			
		||||
 | 
			
		||||
# Install Master Password.
 | 
			
		||||
install mpw "$bindir"
 | 
			
		||||
[[ ! -e "$bindir/bashlib" ]] && install bashlib "$bindir" ||:
 | 
			
		||||
 | 
			
		||||
# Convenience bash function.
 | 
			
		||||
inf "Installation successful!"
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
inf "To improve usability, you can install an mpw function in your bash shell."
 | 
			
		||||
inf "This function adds the following features:"
 | 
			
		||||
inf "  - Automatically remember your user name in the shell if not set."
 | 
			
		||||
inf "  - Automatically put the password in the clipboard (some platforms)."
 | 
			
		||||
echo
 | 
			
		||||
inf "To do this you need the following function in ~/.bashrc:\n%s" "$(<mpw.bashrc)"
 | 
			
		||||
echo
 | 
			
		||||
inf "We can do this for you automatically now."
 | 
			
		||||
if ask -c Y!n "Append the mpw function to your .bashrc?"; then
 | 
			
		||||
    cat mpw.bashrc >> ~/.bashrc
 | 
			
		||||
    inf "Done!  Don't forget to run '%s' to apply the changes!" "source ~/.bashrc"
 | 
			
		||||
fi
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
inf "You can also save your user name in ~/.bashrc.  Leave blank to skip this step."
 | 
			
		||||
if MP_USERNAME=$(ask "Your full name:") && [[ $MP_USERNAME ]] ; then
 | 
			
		||||
    printf 'export MP_USERNAME=%q\n' "$MP_USERNAME" >> ~/.bashrc
 | 
			
		||||
fi
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
inf "To begin using Master Password, type: mpw [site name]"
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
https://code.google.com/p/portableproplib/
 | 
			
		||||
							
								
								
									
										24
									
								
								MasterPassword/C/mpw.bashrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								MasterPassword/C/mpw.bashrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
## Added by Master Password
 | 
			
		||||
source bashlib
 | 
			
		||||
mpw() {
 | 
			
		||||
    _copy() {
 | 
			
		||||
        if hash pbcopy 2>/dev/null; then
 | 
			
		||||
            pbcopy
 | 
			
		||||
        elif hash xclip 2>/dev/null; then
 | 
			
		||||
            xclip
 | 
			
		||||
        else
 | 
			
		||||
            cat
 | 
			
		||||
            return
 | 
			
		||||
        fi
 | 
			
		||||
        echo >&2 "Copied!"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Empty the clipboard
 | 
			
		||||
    :| _copy 2>/dev/null
 | 
			
		||||
 | 
			
		||||
    # Ask for the user's name and password if not yet known.
 | 
			
		||||
    MP_USERNAME=${MP_USERNAME:-$(ask -s 'Your Full Name:')}
 | 
			
		||||
 | 
			
		||||
    # Start Master Password and copy the output.
 | 
			
		||||
    printf %s "$(MP_USERNAME=$MP_USERNAME command mpw "$@")" | _copy
 | 
			
		||||
}
 | 
			
		||||
@@ -32,6 +32,23 @@
 | 
			
		||||
#define MP_env_sitetype     "MP_SITETYPE"
 | 
			
		||||
#define MP_env_sitecounter  "MP_SITECOUNTER"
 | 
			
		||||
 | 
			
		||||
void usage() {
 | 
			
		||||
      fprintf(stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n");
 | 
			
		||||
      fprintf(stderr, "    -u name      Specify the full name of the user.\n"
 | 
			
		||||
                      "                 Defaults to %s in env.\n\n", MP_env_username);
 | 
			
		||||
      fprintf(stderr, "    -t type      Specify the password's template.\n"
 | 
			
		||||
                      "                 Defaults to %s in env or 'long'.\n"
 | 
			
		||||
                      "                     x, max, maximum | 20 characters, contains symbols.\n"
 | 
			
		||||
                      "                     l, long         | Copy-friendly, 14 characters, contains symbols.\n"
 | 
			
		||||
                      "                     m, med, medium  | Copy-friendly, 8 characters, contains symbols.\n"
 | 
			
		||||
                      "                     b, basic        | 8 characters, no symbols.\n"
 | 
			
		||||
                      "                     s, short        | Copy-friendly, 4 characters, no symbols.\n"
 | 
			
		||||
                      "                     p, pin          | 4 numbers.\n\n", MP_env_sitetype);
 | 
			
		||||
      fprintf(stderr, "    -c counter   The value of the counter.\n"
 | 
			
		||||
                      "                 Defaults to %s in env or '1'.\n\n", MP_env_sitecounter);
 | 
			
		||||
      exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *homedir(const char *filename) {
 | 
			
		||||
    char *homedir = NULL;
 | 
			
		||||
#if defined(__CYGWIN__)
 | 
			
		||||
@@ -59,6 +76,9 @@ char *homedir(const char *filename) {
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *const argv[]) {
 | 
			
		||||
 | 
			
		||||
    if (argc < 2)
 | 
			
		||||
        usage();
 | 
			
		||||
 | 
			
		||||
    // Read the environment.
 | 
			
		||||
    const char *userName = getenv( MP_env_username );
 | 
			
		||||
    const char *masterPassword = NULL;
 | 
			
		||||
@@ -70,34 +90,37 @@ int main(int argc, char *const argv[]) {
 | 
			
		||||
 | 
			
		||||
    // Read the options.
 | 
			
		||||
    char opt;
 | 
			
		||||
    while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
 | 
			
		||||
    while ((opt = getopt(argc, argv, "u:t:c:h")) != -1)
 | 
			
		||||
      switch (opt) {
 | 
			
		||||
        case 'u':
 | 
			
		||||
          userName = optarg;
 | 
			
		||||
          break;
 | 
			
		||||
        case 't':
 | 
			
		||||
          siteTypeString = optarg;
 | 
			
		||||
          break;
 | 
			
		||||
        case 'c':
 | 
			
		||||
          siteCounterString = optarg;
 | 
			
		||||
          break;
 | 
			
		||||
        case '?':
 | 
			
		||||
          switch (optopt) {
 | 
			
		||||
            case 'u':
 | 
			
		||||
              fprintf(stderr, "Missing user name to option: -%c\n", optopt);
 | 
			
		||||
          case 'h':
 | 
			
		||||
              usage();
 | 
			
		||||
              break;
 | 
			
		||||
            case 't':
 | 
			
		||||
              fprintf(stderr, "Missing type name to option: -%c\n", optopt);
 | 
			
		||||
          case 'u':
 | 
			
		||||
              userName = optarg;
 | 
			
		||||
              break;
 | 
			
		||||
            case 'c':
 | 
			
		||||
              fprintf(stderr, "Missing counter value to option: -%c\n", optopt);
 | 
			
		||||
          case 't':
 | 
			
		||||
              siteTypeString = optarg;
 | 
			
		||||
              break;
 | 
			
		||||
            default:
 | 
			
		||||
              fprintf(stderr, "Unknown option: -%c\n", optopt);
 | 
			
		||||
          }
 | 
			
		||||
          return 1;
 | 
			
		||||
        default:
 | 
			
		||||
          abort();
 | 
			
		||||
          case 'c':
 | 
			
		||||
              siteCounterString = optarg;
 | 
			
		||||
              break;
 | 
			
		||||
          case '?':
 | 
			
		||||
              switch (optopt) {
 | 
			
		||||
                case 'u':
 | 
			
		||||
                  fprintf(stderr, "Missing user name to option: -%c\n", optopt);
 | 
			
		||||
                  break;
 | 
			
		||||
                case 't':
 | 
			
		||||
                  fprintf(stderr, "Missing type name to option: -%c\n", optopt);
 | 
			
		||||
                  break;
 | 
			
		||||
                case 'c':
 | 
			
		||||
                  fprintf(stderr, "Missing counter value to option: -%c\n", optopt);
 | 
			
		||||
                  break;
 | 
			
		||||
                default:
 | 
			
		||||
                  fprintf(stderr, "Unknown option: -%c\n", optopt);
 | 
			
		||||
              }
 | 
			
		||||
              return 1;
 | 
			
		||||
          default:
 | 
			
		||||
              abort();
 | 
			
		||||
      }
 | 
			
		||||
    if (optind < argc)
 | 
			
		||||
        siteName = argv[optind];
 | 
			
		||||
@@ -142,7 +165,7 @@ int main(int argc, char *const argv[]) {
 | 
			
		||||
    ssize_t linelen;
 | 
			
		||||
    while ((linelen = getline(&line, &linecap, mpwConfig)) > 0)
 | 
			
		||||
        if (strcmp(strsep(&line, ":"), userName) == 0) {
 | 
			
		||||
            masterPassword = line;
 | 
			
		||||
            masterPassword = strsep(&line, "\n");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    if (!masterPassword) {
 | 
			
		||||
@@ -151,47 +174,75 @@ int main(int argc, char *const argv[]) {
 | 
			
		||||
    }
 | 
			
		||||
    trc("masterPassword: %s\n", masterPassword);
 | 
			
		||||
 | 
			
		||||
    // Calculate the master key salt.
 | 
			
		||||
    char *mpNameSpace = "com.lyndir.masterpassword";
 | 
			
		||||
    const uint32_t n_userNameLength = htonl(strlen(userName));
 | 
			
		||||
    size_t masterKeySaltLength = strlen(mpNameSpace) + sizeof(n_userNameLength) + strlen(userName);
 | 
			
		||||
    char *masterKeySalt = malloc( masterKeySaltLength );
 | 
			
		||||
    if (!masterKeySalt) {
 | 
			
		||||
        fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *mKS = masterKeySalt;
 | 
			
		||||
    memcpy(mKS, mpNameSpace, strlen(mpNameSpace)); mKS += strlen(mpNameSpace);
 | 
			
		||||
    memcpy(mKS, &n_userNameLength, sizeof(n_userNameLength)); mKS += sizeof(n_userNameLength);
 | 
			
		||||
    memcpy(mKS, userName, strlen(userName)); mKS += strlen(userName);
 | 
			
		||||
    if (mKS - masterKeySalt != masterKeySaltLength)
 | 
			
		||||
        abort();
 | 
			
		||||
    trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
 | 
			
		||||
 | 
			
		||||
    // Calculate the master key.
 | 
			
		||||
    uint8_t *masterKey = malloc( MP_dkLen );
 | 
			
		||||
    if (!masterKey) {
 | 
			
		||||
        fprintf(stderr, "Could not allocate master key: %d\n", errno);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    const uint32_t n_userNameLength = htonl(strlen(userName));
 | 
			
		||||
    char *masterKeySalt = NULL;
 | 
			
		||||
    size_t masterKeySaltLength = asprintf(&masterKeySalt, "com.lyndir.masterpassword%s%s", (const char *) &n_userNameLength, userName);
 | 
			
		||||
    if (!masterKeySalt) {
 | 
			
		||||
        fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
 | 
			
		||||
        fprintf(stderr, "Could not generate master key: %d\n", errno);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    memset(masterKeySalt, 0, masterKeySaltLength);
 | 
			
		||||
    free(masterKeySalt);
 | 
			
		||||
    trc("masterPassword Hex: %s\n", Hex(masterPassword, strlen(masterPassword)));
 | 
			
		||||
    trc("masterPassword ID: %s\n", IDForBuf(masterPassword, strlen(masterPassword)));
 | 
			
		||||
    trc("masterKey ID: %s\n", IDForBuf(masterKey, MP_dkLen));
 | 
			
		||||
 | 
			
		||||
    // Calculate the site seed.
 | 
			
		||||
    const uint32_t n_siteCounter = htonl(siteCounter), n_siteNameLength = htonl(strlen(siteName));
 | 
			
		||||
    char *sitePasswordInfo = NULL;
 | 
			
		||||
    size_t sitePasswordInfoLength = asprintf(&sitePasswordInfo, "com.lyndir.masterpassword%s%s%s", (const char *) &n_siteNameLength, siteName, (const char *) &n_siteCounter);
 | 
			
		||||
    const uint32_t n_siteNameLength = htonl(strlen(siteName));
 | 
			
		||||
    const uint32_t n_siteCounter = htonl(siteCounter);
 | 
			
		||||
    size_t sitePasswordInfoLength = strlen(mpNameSpace) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
 | 
			
		||||
    char *sitePasswordInfo = malloc( sitePasswordInfoLength );
 | 
			
		||||
    if (!sitePasswordInfo) {
 | 
			
		||||
        fprintf(stderr, "Could not allocate site seed: %d\n", errno);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *sPI = sitePasswordInfo;
 | 
			
		||||
    memcpy(sPI, mpNameSpace, strlen(mpNameSpace)); sPI += strlen(mpNameSpace);
 | 
			
		||||
    memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
 | 
			
		||||
    memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
 | 
			
		||||
    memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
 | 
			
		||||
    if (sPI - sitePasswordInfo != sitePasswordInfoLength)
 | 
			
		||||
        abort();
 | 
			
		||||
    trc("seed from: hmac-sha256(masterKey, 'com.lyndir.masterpassword' | %s | %s | %s)\n", Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)));
 | 
			
		||||
    trc("sitePasswordInfo ID: %s\n", IDForBuf(sitePasswordInfo, sitePasswordInfoLength));
 | 
			
		||||
 | 
			
		||||
    uint8_t sitePasswordSeed[32];
 | 
			
		||||
    HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
 | 
			
		||||
    memset(masterKey, 0, MP_dkLen);
 | 
			
		||||
    memset(sitePasswordInfo, 0, sitePasswordInfoLength);
 | 
			
		||||
    free(masterKey);
 | 
			
		||||
    free(sitePasswordInfo);
 | 
			
		||||
    trc("sitePasswordSeed ID: %s\n", IDForBuf(sitePasswordSeed, 32));
 | 
			
		||||
 | 
			
		||||
    // Determine the cipher.
 | 
			
		||||
    const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
 | 
			
		||||
    trc("type %s, cipher: %s\n", siteTypeString, cipher);
 | 
			
		||||
    if (strlen(cipher) > 32)
 | 
			
		||||
        abort();
 | 
			
		||||
 | 
			
		||||
    // Encode the password from the seed using the cipher.
 | 
			
		||||
    //NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
 | 
			
		||||
    char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
 | 
			
		||||
    for (int c = 0; c < strlen(cipher); ++c) {
 | 
			
		||||
        sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
#include <alg/sha256.h>
 | 
			
		||||
 | 
			
		||||
#include "types.h"
 | 
			
		||||
 | 
			
		||||
const MPElementType TypeWithName(const char *typeName) {
 | 
			
		||||
@@ -118,4 +121,20 @@ const char CharacterFromClass(char characterClass, uint8_t seedByte) {
 | 
			
		||||
 | 
			
		||||
    return classCharacters[seedByte % strlen(classCharacters)];
 | 
			
		||||
}
 | 
			
		||||
const char *IDForBuf(const void *buf, size_t length) {
 | 
			
		||||
    uint8_t hash[32];
 | 
			
		||||
    SHA256_Buf(buf, length, hash);
 | 
			
		||||
 | 
			
		||||
    char *id = calloc(65, sizeof(char));
 | 
			
		||||
    for (int kH = 0; kH < 32; kH++)
 | 
			
		||||
        sprintf(&(id[kH * 2]), "%02X", hash[kH]);
 | 
			
		||||
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *Hex(const void *buf, size_t length) {
 | 
			
		||||
    char *id = calloc(length*2+1, sizeof(char));
 | 
			
		||||
    for (int kH = 0; kH < length; kH++)
 | 
			
		||||
        sprintf(&(id[kH * 2]), "%02X", ((const uint8_t*)buf)[kH]);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,3 +47,6 @@ typedef enum {
 | 
			
		||||
const MPElementType TypeWithName(const char *typeName);
 | 
			
		||||
const char *CipherForType(MPElementType type, uint8_t seedByte);
 | 
			
		||||
const char CharacterFromClass(char characterClass, uint8_t seedByte);
 | 
			
		||||
const char *IDForBuf(const void *buf, size_t length);
 | 
			
		||||
const char *Hex(const void *buf, size_t length);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user