pkcs5_pbkdf2.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 23 Jun 2017 17:28:03 -0400
changeset 58 1390348facc7
parent 54 3d70f17a68b8
permissions -rw-r--r--
Command line tool that decrypts an OPVault keychain and dumps it to stdout.

To compile: gcc -o opvault opvault.c cJSON.c -lcrypto

Usage: ./opvault </path/to/mykeychain.opvault> <password>

This is just a proof of concept; I'll be recycling this into proper OPVault
support in 1pass later and deleting this tool.

This uses OpenSSL's libcrypto for the math instead of all the homegrown
crypto this project is otherwise using. I'll probably migrate the rest in
this direction, too, since this wasn't as bad as I expected to use and
gets you all the package-manager mojo of automatic bug fixes and security
patches and shared code, etc.

cJSON parses JSON in C. That is from https://github.com/DaveGamble/cJSON

An example OPVault keychain from AgileBits is available here:

https://cache.agilebits.com/security-kb/
icculus@0
     1
/*	$OpenBSD: pkcs5_pbkdf2.c,v 1.4 2013/06/03 21:07:02 tedu Exp $	*/
icculus@0
     2
icculus@0
     3
/*-
icculus@0
     4
 * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
icculus@0
     5
 *
icculus@0
     6
 * Permission to use, copy, modify, and distribute this software for any
icculus@0
     7
 * purpose with or without fee is hereby granted, provided that the above
icculus@0
     8
 * copyright notice and this permission notice appear in all copies.
icculus@0
     9
 *
icculus@0
    10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
icculus@0
    11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
icculus@0
    12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
icculus@0
    13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
icculus@0
    14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
icculus@0
    15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
icculus@0
    16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
icculus@0
    17
 */
icculus@0
    18
icculus@0
    19
#include <sys/types.h>
icculus@0
    20
#include <sys/param.h>
icculus@0
    21
icculus@0
    22
#include <string.h>
icculus@0
    23
#include <limits.h>
icculus@0
    24
#include <stdlib.h>
icculus@10
    25
//#include <util.h>
icculus@0
    26
icculus@0
    27
#include "sha1.h"
icculus@0
    28
icculus@0
    29
/*
icculus@0
    30
 * Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
icculus@0
    31
 * Code based on IEEE Std 802.11-2007, Annex H.4.2.
icculus@0
    32
 */
icculus@0
    33
int
icculus@0
    34
pkcs5_pbkdf2(const char *pass, size_t pass_len, const uint8_t *salt, size_t salt_len,
icculus@0
    35
    uint8_t *key, size_t key_len, unsigned int rounds)
icculus@0
    36
{
icculus@0
    37
	uint8_t *asalt, obuf[SHA1_DIGEST_LENGTH];
icculus@0
    38
	uint8_t d1[SHA1_DIGEST_LENGTH], d2[SHA1_DIGEST_LENGTH];
icculus@0
    39
	unsigned int i, j;
icculus@0
    40
	unsigned int count;
icculus@0
    41
	size_t r;
icculus@0
    42
icculus@0
    43
	if (rounds < 1 || key_len == 0)
icculus@0
    44
		return -1;
icculus@0
    45
	if (salt_len == 0 || salt_len > SIZE_MAX - 4)
icculus@0
    46
		return -1;
icculus@0
    47
	if ((asalt = malloc(salt_len + 4)) == NULL)
icculus@0
    48
		return -1;
icculus@0
    49
icculus@0
    50
	memcpy(asalt, salt, salt_len);
icculus@0
    51
icculus@0
    52
	for (count = 1; key_len > 0; count++) {
icculus@0
    53
		asalt[salt_len + 0] = (count >> 24) & 0xff;
icculus@0
    54
		asalt[salt_len + 1] = (count >> 16) & 0xff;
icculus@0
    55
		asalt[salt_len + 2] = (count >> 8) & 0xff;
icculus@0
    56
		asalt[salt_len + 3] = count & 0xff;
icculus@54
    57
		SHA1Hmac((const uint8_t *) pass, pass_len, asalt, salt_len + 4, d1);
icculus@0
    58
		memcpy(obuf, d1, sizeof(obuf));
icculus@0
    59
icculus@0
    60
		for (i = 1; i < rounds; i++) {
icculus@54
    61
			SHA1Hmac((const uint8_t *) pass, pass_len, d1, sizeof(d1), d2);
icculus@0
    62
			memcpy(d1, d2, sizeof(d1));
icculus@0
    63
			for (j = 0; j < sizeof(obuf); j++)
icculus@0
    64
				obuf[j] ^= d1[j];
icculus@0
    65
		}
icculus@0
    66
icculus@0
    67
		r = MIN(key_len, SHA1_DIGEST_LENGTH);
icculus@0
    68
		memcpy(key, obuf, r);
icculus@0
    69
		key += r;
icculus@0
    70
		key_len -= r;
icculus@0
    71
	};
icculus@0
    72
	bzero(asalt, salt_len + 4);
icculus@0
    73
	free(asalt);
icculus@0
    74
	bzero(d1, sizeof(d1));
icculus@0
    75
	bzero(d2, sizeof(d2));
icculus@0
    76
	bzero(obuf, sizeof(obuf));
icculus@0
    77
icculus@0
    78
	return 0;
icculus@0
    79
}
icculus@0
    80